Skip to content

Commit

Permalink
Adapt ed25519_verify to VerificationError
Browse files Browse the repository at this point in the history
  • Loading branch information
maurolacy committed Feb 17, 2021
1 parent 36ec177 commit f1d389c
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 70 deletions.
31 changes: 22 additions & 9 deletions packages/crypto/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ pub enum CryptoError {
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
#[error("Hash error: {msg}")]
HashErr {
#[error("Message error: {msg}")]
MessageError {
msg: String,
error_code: u32,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
#[error("Message error: {msg}")]
MsgErr {
#[error("Hash error: {msg}")]
HashErr {
msg: String,
error_code: u32,
#[cfg(feature = "backtraces")]
backtrace: Backtrace,
},
Expand Down Expand Up @@ -53,18 +54,19 @@ impl CryptoError {
}
}

pub fn hash_err<S: Into<String>>(msg: S) -> Self {
CryptoError::HashErr {
pub fn msg_err<S: Into<String>>(msg: S) -> Self {
CryptoError::MessageError {
msg: msg.into(),
error_code: 3,
error_code: 2,
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
}

pub fn msg_err<S: Into<String>>(msg: S) -> Self {
CryptoError::MsgErr {
pub fn hash_err<S: Into<String>>(msg: S) -> Self {
CryptoError::HashErr {
msg: msg.into(),
error_code: 3,
#[cfg(feature = "backtraces")]
backtrace: Backtrace::capture(),
}
Expand Down Expand Up @@ -105,6 +107,17 @@ mod tests {
}
}

#[test]
fn msg_err_works() {
let error = CryptoError::msg_err("something went wrong with the msg");
match error {
CryptoError::MessageError { msg, .. } => {
assert_eq!(msg, "something went wrong with the msg")
}
_ => panic!("wrong error type!"),
}
}

#[test]
fn hash_err_works() {
let error = CryptoError::hash_err("something went wrong with the hash");
Expand Down
4 changes: 4 additions & 0 deletions packages/std/src/errors/verification_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use cosmwasm_crypto::CryptoError;
pub enum VerificationError {
#[error("Generic error")]
GenericErr,
#[error("Message error")]
MessageErr,
#[error("Hash error")]
HashErr,
#[error("Signature error")]
Expand Down Expand Up @@ -38,6 +40,7 @@ impl PartialEq<VerificationError> for VerificationError {
fn eq(&self, rhs: &VerificationError) -> bool {
match self {
VerificationError::GenericErr => matches!(rhs, VerificationError::GenericErr),
VerificationError::MessageErr => matches!(rhs, VerificationError::MessageErr),
VerificationError::HashErr => matches!(rhs, VerificationError::HashErr),
VerificationError::SignatureErr => matches!(rhs, VerificationError::SignatureErr),
VerificationError::PublicKeyErr => matches!(rhs, VerificationError::PublicKeyErr),
Expand All @@ -60,6 +63,7 @@ impl PartialEq<VerificationError> for VerificationError {
impl From<CryptoError> for VerificationError {
fn from(original: CryptoError) -> Self {
match original {
CryptoError::MessageError { .. } => VerificationError::MessageErr,
CryptoError::HashErr { .. } => VerificationError::HashErr,
CryptoError::SignatureErr { .. } => VerificationError::SignatureErr,
CryptoError::PublicKeyErr { .. } => VerificationError::PublicKeyErr,
Expand Down
19 changes: 15 additions & 4 deletions packages/std/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ impl Api for ExternalApi {
match result {
0 => Ok(true),
1 => Ok(false),
2 => Err(VerificationError::MessageErr), // shouldn't happen
3 => Err(VerificationError::HashErr),
4 => Err(VerificationError::SignatureErr),
5 => Err(VerificationError::PublicKeyErr),
Expand All @@ -208,7 +209,12 @@ impl Api for ExternalApi {
}
}

fn ed25519_verify(&self, message: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
fn ed25519_verify(
&self,
message: &[u8],
signature: &[u8],
public_key: &[u8],
) -> Result<bool, VerificationError> {
let msg_send = build_region(message);
let msg_send_ptr = &*msg_send as *const Region as u32;
let sig_send = build_region(signature);
Expand All @@ -218,9 +224,14 @@ impl Api for ExternalApi {

let result = unsafe { ed25519_verify(msg_send_ptr, sig_send_ptr, pubkey_send_ptr) };
match result {
0 => false,
1 => true,
_ => unreachable!(),
0 => Ok(true),
1 => Ok(false),
2 => Err(VerificationError::MessageErr),
3 => Err(VerificationError::HashErr), // shouldn't happen
4 => Err(VerificationError::SignatureErr),
5 => Err(VerificationError::PublicKeyErr),
10 => Err(VerificationError::GenericErr),
error_code => Err(VerificationError::unknown_err(error_code)),
}
}

Expand Down
28 changes: 15 additions & 13 deletions packages/std/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,15 @@ impl Api for MockApi {
)?)
}

fn ed25519_verify(&self, message: &[u8], signature: &[u8], public_key: &[u8]) -> bool {
let result = cosmwasm_crypto::ed25519_verify(message, signature, public_key);
match result {
Ok(v) => v,
Err(err) => panic!("ed25519_verify error: {:?}", err),
}
fn ed25519_verify(
&self,
message: &[u8],
signature: &[u8],
public_key: &[u8],
) -> Result<bool, VerificationError> {
Ok(cosmwasm_crypto::ed25519_verify(
message, signature, public_key,
)?)
}

fn debug(&self, message: &str) {
Expand Down Expand Up @@ -583,7 +586,6 @@ mod tests {
let public_key = vec![];

let res = api.secp256k1_verify(&hash, &signature, &public_key);

assert_eq!(res.unwrap_err(), VerificationError::PublicKeyErr);
}

Expand All @@ -596,7 +598,7 @@ mod tests {
let signature = hex::decode(ED25519_SIG_HEX).unwrap();
let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();

assert!(api.ed25519_verify(&hash, &signature, &public_key));
assert!(api.ed25519_verify(&hash, &signature, &public_key).unwrap());
}

// Basic "fails" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
Expand All @@ -610,20 +612,20 @@ mod tests {
let signature = hex::decode(ED25519_SIG_HEX).unwrap();
let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();

assert!(!api.ed25519_verify(&msg, &signature, &public_key));
assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
}

// Basic "panics" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
// Basic "errors" test. Exhaustive tests on VM's side (packages/vm/src/imports.rs)
#[test]
#[should_panic(expected = "empty")]
fn ed25519_verify_panics() {
fn ed25519_verify_errs() {
let api = MockApi::default();

let msg = hex::decode(ED25519_MSG_HEX).unwrap();
let signature = hex::decode(ED25519_SIG_HEX).unwrap();
let public_key = vec![];

assert!(!api.ed25519_verify(&msg, &signature, &public_key));
let res = api.ed25519_verify(&msg, &signature, &public_key);
assert_eq!(res.unwrap_err(), VerificationError::PublicKeyErr);
}

#[test]
Expand Down
7 changes: 6 additions & 1 deletion packages/std/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ pub trait Api {
public_key: &[u8],
) -> Result<bool, VerificationError>;

fn ed25519_verify(&self, message: &[u8], signature: &[u8], public_key: &[u8]) -> bool;
fn ed25519_verify(
&self,
message: &[u8],
signature: &[u8],
public_key: &[u8],
) -> Result<bool, VerificationError>;

/// Emits a debugging message that is handled depending on the environment (typically printed to console or ignored).
/// Those messages are not persisted to chain.
Expand Down
75 changes: 32 additions & 43 deletions packages/vm/src/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ fn do_secp256k1_verify<A: BackendApi, S: Storage, Q: Querier>(
match result {
Ok(true) => Ok(0),
Ok(false) => Ok(1),
Err(CryptoError::MessageError { error_code, .. }) => Ok(error_code),
Err(CryptoError::HashErr { error_code, .. }) => Ok(error_code),
Err(CryptoError::SignatureErr { error_code, .. }) => Ok(error_code),
Err(CryptoError::PublicKeyErr { error_code, .. }) => Ok(error_code),
Expand All @@ -303,7 +304,16 @@ fn do_ed25519_verify<A: BackendApi, S: Storage, Q: Querier>(
let result = ed25519_verify(&message, &signature, &pubkey);
let gas_info = GasInfo::with_cost(GAS_COST_VERIFY_ED25519_SIGNATURE);
process_gas_info::<A, S, Q>(env, gas_info)?;
Ok(result?.into())
// Ok((!(result?)).into())
match result {
Ok(true) => Ok(0),
Ok(false) => Ok(1),
Err(CryptoError::MessageError { error_code, .. }) => Ok(error_code),
Err(CryptoError::HashErr { error_code, .. }) => Ok(error_code),
Err(CryptoError::SignatureErr { error_code, .. }) => Ok(error_code),
Err(CryptoError::PublicKeyErr { error_code, .. }) => Ok(error_code),
Err(CryptoError::GenericErr { error_code, .. }) => Ok(error_code),
}
}

/// Creates a Region in the contract, writes the given data to it and returns the memory location
Expand Down Expand Up @@ -1226,6 +1236,7 @@ mod tests {
// reduce / break pubkey
pubkey.pop();
let pubkey_ptr = write_data(&env, &pubkey);

assert_eq!(
do_secp256k1_verify::<MA, MS, MQ>(&env, hash_ptr, sig_ptr, pubkey_ptr).unwrap(),
5 // mapped PublicKeyErr
Expand Down Expand Up @@ -1282,7 +1293,7 @@ mod tests {

assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
1
0
);
}

Expand All @@ -1302,7 +1313,7 @@ mod tests {

assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
0
1
);
}

Expand Down Expand Up @@ -1346,7 +1357,7 @@ mod tests {

assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
0
1
);
}

Expand Down Expand Up @@ -1388,17 +1399,10 @@ mod tests {
let pubkey = hex::decode(EDDSA_PUBKEY_HEX).unwrap();
let pubkey_ptr = write_data(&env, &pubkey);

let result = do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr);
match result.unwrap_err() {
VmError::CryptoErr {
source: CryptoError::SignatureErr { msg, .. },
..
} => assert_eq!(
msg,
format!("wrong / unsupported length: {}", EDDSA_SIGNATURE_LEN - 1)
),
e => panic!("Unexpected error: {:?}", e),
}
assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
4 // mapped SignatureErr
)
}

#[test]
Expand All @@ -1417,7 +1421,7 @@ mod tests {

assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
0
1
);
}

Expand Down Expand Up @@ -1459,17 +1463,10 @@ mod tests {
pubkey.pop();
let pubkey_ptr = write_data(&env, &pubkey);

let result = do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr);
match result.unwrap_err() {
VmError::CryptoErr {
source: CryptoError::PublicKeyErr { msg, .. },
..
} => assert_eq!(
msg,
format!("wrong / unsupported length: {}", EDDSA_PUBKEY_LEN - 1)
),
err => panic!("Incorrect error returned: {:?}", err),
}
assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
5 // mapped PublicKeyErr
)
}

#[test]
Expand All @@ -1484,14 +1481,10 @@ mod tests {
let pubkey = vec![];
let pubkey_ptr = write_data(&env, &pubkey);

let result = do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr);
match result.unwrap_err() {
VmError::CryptoErr {
source: CryptoError::PublicKeyErr { msg, .. },
..
} => assert_eq!(msg, "empty"),
err => panic!("Incorrect error returned: {:?}", err),
}
assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
5 // mapped PublicKeyError
)
}

#[test]
Expand All @@ -1506,14 +1499,10 @@ mod tests {
let pubkey = vec![0x04; EDDSA_PUBKEY_LEN];
let pubkey_ptr = write_data(&env, &pubkey);

let result = do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr);
match result.unwrap_err() {
VmError::CryptoErr {
source: CryptoError::GenericErr { msg, .. },
..
} => assert_eq!(msg, "Malformed public key encoding."),
err => panic!("Incorrect error returned: {:?}", err),
}
assert_eq!(
do_ed25519_verify::<MA, MS, MQ>(&env, msg_ptr, sig_ptr, pubkey_ptr).unwrap(),
10 // mapped GenericErr
)
}

#[test]
Expand Down

0 comments on commit f1d389c

Please sign in to comment.