diff --git a/packages/vm/src/backend.rs b/packages/vm/src/backend.rs index cadf234c8a..694aec361d 100644 --- a/packages/vm/src/backend.rs +++ b/packages/vm/src/backend.rs @@ -127,6 +127,13 @@ pub trait Storage { pub trait Api: Copy + Clone + Send { fn canonical_address(&self, human: &HumanAddr) -> BackendResult; fn human_address(&self, canonical: &CanonicalAddr) -> BackendResult; + + fn secp256k1_verify( + &self, + message_hash: &[u8], + signature: &[u8], + public_key: &[u8], + ) -> BackendResult<()>; } pub trait Querier { @@ -168,6 +175,8 @@ pub enum BackendError { // This is the only error case of BackendError that is reported back to the contract. #[error("User error during call into backend: {msg}")] UserErr { msg: String }, + #[error("Crypto error: {msg}")] + CryptoErr { msg: String }, } impl BackendError { @@ -203,6 +212,12 @@ impl BackendError { msg: msg.to_string(), } } + + pub fn crypto_err(msg: S) -> Self { + BackendError::CryptoErr { + msg: msg.to_string(), + } + } } impl From for BackendError { diff --git a/packages/vm/src/testing/mock.rs b/packages/vm/src/testing/mock.rs index 6413b1b121..fb632c8c0b 100644 --- a/packages/vm/src/testing/mock.rs +++ b/packages/vm/src/testing/mock.rs @@ -3,11 +3,13 @@ use cosmwasm_std::{BlockInfo, CanonicalAddr, Coin, ContractInfo, Env, HumanAddr, use super::querier::MockQuerier; use super::storage::MockStorage; +use crate::crypto; use crate::{Api, Backend, BackendError, BackendResult, GasInfo}; pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract"; const GAS_COST_HUMANIZE: u64 = 44; const GAS_COST_CANONICALIZE: u64 = 55; +const GAS_COST_VERIFY_SIGNATURE: u64 = 100; /// All external requirements that can be injected for unit tests. /// It sets the given balance for the contract itself, nothing else @@ -134,6 +136,25 @@ impl Api for MockApi { }; (result, gas_info) } + + fn secp256k1_verify( + &self, + message_hash: &[u8], + signature: &[u8], + public_key: &[u8], + ) -> BackendResult<()> { + let gas_info = GasInfo::with_cost(GAS_COST_VERIFY_SIGNATURE); + + if let Some(backend_error) = self.backend_error { + return (Err(BackendError::unknown(backend_error)), gas_info); + } + + let result = match crypto::secp256k1_verify(message_hash, signature, public_key) { + Ok(_) => Ok(()), + Err(err) => Err(BackendError::crypto_err(err.to_string())), + }; + (result, gas_info) + } } /// Returns a default enviroment with height, time, chain_id, and contract address