From cd78f1e4e6d48656f1de26b1faefbd91e8179b7d Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sat, 25 Sep 2021 21:22:35 +0300 Subject: [PATCH 01/39] Working prototype :tada: of querying my balance with a signed permit instead of a viewing key --- Cargo.lock | 37 +++++++++++++++++++ Cargo.toml | 7 ++-- src/contract.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ src/msg.rs | 58 ++++++++++++++++++++++++++++++ src/state.rs | 3 ++ 5 files changed, 195 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index df6910c..3e3f255 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +[[package]] +name = "cc" +version = "1.0.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" + [[package]] name = "cfg-if" version = "1.0.0" @@ -364,6 +370,17 @@ dependencies = [ "rand_core", ] +[[package]] +name = "ripemd160" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eca4ecc81b7f313189bf73ce724400a07da2a6dac19588b03c8bd76a2dcc251" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "opaque-debug 0.3.0", +] + [[package]] name = "rustc-demangle" version = "0.1.18" @@ -399,6 +416,24 @@ dependencies = [ "syn", ] +[[package]] +name = "secp256k1" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6179428c22c73ac0fbb7b5579a56353ce78ba29759b3b8575183336ea74cdfb" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11553d210db090930f4432bea123b31f70bbf693ace14504ea2a35e796c28dd2" +dependencies = [ + "cc", +] + [[package]] name = "secret-toolkit" version = "0.1.0" @@ -587,7 +622,9 @@ dependencies = [ "hex", "rand_chacha", "rand_core", + "ripemd160", "schemars", + "secp256k1", "secret-toolkit", "serde", "sha2 0.9.2", diff --git a/Cargo.toml b/Cargo.toml index 80dbac0..674da5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ name = "snip20-reference-impl" version = "0.1.0" authors = ["Itzik "] edition = "2018" - exclude = [ # Those files are rust-optimizer artifacts. You might want to commit them for convenience but they should not be part of the source code publication. "contract.wasm", @@ -11,7 +10,6 @@ exclude = [ ] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [lib] crate-type = ["cdylib", "rlib"] @@ -44,10 +42,11 @@ bincode2 = "2.0.1" subtle = { version = "2.2.3", default-features = false } base64 = "0.12.3" hex = "0.4.2" - rand_chacha = { version = "0.2.2", default-features = false } -rand_core = { version = "0.5.1", default-features = false } +rand_core = { version = "0.5.1", default-features = false } sha2 = { version = "0.9.1", default-features = false } +ripemd160 = "0.9.1" +secp256k1 = "0.19.0" [dev-dependencies] cosmwasm-schema = { version = "0.9.2" } diff --git a/src/contract.rs b/src/contract.rs index 9bfefbe..84f2e69 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -5,17 +5,22 @@ use cosmwasm_std::{ HandleResponse, HumanAddr, InitResponse, Querier, QueryResult, ReadonlyStorage, StdError, StdResult, Storage, Uint128, }; +use ripemd160::{Digest, Ripemd160}; +use secp256k1::Secp256k1; +use sha2::Sha256; use crate::batch; use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; +use crate::msg::{Signature, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ get_receiver_hash, read_allowance, read_viewing_key, set_receiver_hash, write_allowance, write_viewing_key, Balances, Config, Constants, ReadonlyBalances, ReadonlyConfig, + QUERY_BALANCE_PERMIT_MSG, }; use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, @@ -90,6 +95,7 @@ pub fn init( redeem_is_enabled: init_config.redeem_enabled(), mint_is_enabled: init_config.mint_enabled(), burn_is_enabled: init_config.burn_enabled(), + query_balance_permit_msg: QUERY_BALANCE_PERMIT_MSG.to_string(), })?; config.set_total_supply(total_supply); config.set_contract_status(ContractStatusLevel::NormalRun); @@ -242,10 +248,92 @@ pub fn query(deps: &Extern, msg: QueryM QueryMsg::ContractStatus {} => query_contract_status(&deps.storage), QueryMsg::ExchangeRate {} => query_exchange_rate(&deps.storage), QueryMsg::Minters { .. } => query_minters(deps), + QueryMsg::BalanceWithPermit { signed, signature } => { + query_balance_with_permit(deps, signed, signature) + } _ => authenticated_queries(deps, msg), } } +fn query_balance_with_permit( + deps: &Extern, + signed: SignedPermit, + signature: Signature, +) -> Result { + if signed.msgs.len() != 1 { + return Err(StdError::generic_err(format!( + "Must sign exactly 1 permit message, got: {:?}.", + signed.msgs.len() + ))); + } + + if signed.msgs[0].r#type != "query_balance_permit" { + return Err(StdError::generic_err(format!( + "Permit message type must be 'query_balance_permit', got: {:?}.", + signed.msgs[0].r#type + ))); + } + + let permit = &signed.msgs[0].value; + + // Validate permit_id + let _permit_id = permit.permit_id; + // TODO fail if permit_id is revoked + + // Validate that account is derived from pubkey + let pubkey = signature.pub_key.value; + let account_from_pubkey = deps.api.human_address(&pubkey_to_account(&pubkey))?; + + if account_from_pubkey != permit.account { + return Err(StdError::generic_err(format!( + "Input account {:?} not the same as account {:?} that was derived from pubkey {:?}.", + permit.account, + account_from_pubkey, + pubkey.clone() + ))); + } + + // Validate signature, source: https://github.com/enigmampc/SecretNetwork/blob/master/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 + let signed_bytes = &to_binary(&signed)?.0; + + let signed_bytes_hash = Sha256::digest(signed_bytes); + let msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { + StdError::generic_err(format!( + "Failed to create a secp256k1 message from signed_bytes: {:?}", + err + )) + })?; + + let verifier = Secp256k1::verification_only(); + + // Create `secp256k1`'s types + let secp256k1_signature = secp256k1::Signature::from_compact(&signature.signature.0) + .map_err(|err| StdError::generic_err(format!("Malformed signature: {:?}", err)))?; + let secp256k1_pubkey = secp256k1::PublicKey::from_slice(pubkey.0.as_slice()) + .map_err(|err| StdError::generic_err(format!("Malformed pubkey: {:?}", err)))?; + + verifier + .verify(&msg, &secp256k1_signature, &secp256k1_pubkey) + .map_err(|err| { + StdError::generic_err(format!( + "Failed to verify signatures for the given permit: {:?}", + err + )) + })?; + + let amount = Uint128( + ReadonlyBalances::from_storage(&deps.storage) + .account_amount(&deps.api.canonical_address(&permit.account)?), + ); + to_binary(&QueryAnswer::Balance { amount }) +} + +fn pubkey_to_account(pubkey: &Binary) -> CanonicalAddr { + let mut hasher = Ripemd160::new(); + hasher.update(Sha256::digest(&pubkey.0)); + CanonicalAddr(Binary(hasher.finalize().to_vec())) +} + pub fn authenticated_queries( deps: &Extern, msg: QueryMsg, @@ -327,6 +415,7 @@ fn query_token_info(storage: &S) -> QueryResult { symbol: constants.symbol, decimals: constants.decimals, total_supply, + query_balance_permit_msg: constants.query_balance_permit_msg, }) } @@ -3609,11 +3698,16 @@ mod tests { symbol, decimals, total_supply, + query_balance_permit_msg, } => { assert_eq!(name, init_name); assert_eq!(symbol, init_symbol); assert_eq!(decimals, init_decimals); assert_eq!(total_supply, Some(Uint128(5000))); + assert_eq!( + query_balance_permit_msg, + QUERY_BALANCE_PERMIT_MSG.to_string() + ); } _ => panic!("unexpected"), } diff --git a/src/msg.rs b/src/msg.rs index 650aad0..fbb7afe 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -323,6 +323,10 @@ pub enum QueryMsg { address: HumanAddr, key: String, }, + BalanceWithPermit { + signed: SignedPermit, + signature: Signature, + }, TransferHistory { address: HumanAddr, key: String, @@ -365,6 +369,7 @@ pub enum QueryAnswer { symbol: String, decimals: u8, total_supply: Option, + query_balance_permit_msg: String, }, TokenConfig { public_total_supply: bool, @@ -456,6 +461,59 @@ pub fn space_pad(block_size: usize, message: &mut Vec) -> &mut Vec { message } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct Signature { + pub pub_key: PubKey, + pub signature: Binary, +} +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PubKey { + pub r#type: String, // must be "tendermint/PubKeySecp256k1", + pub value: Binary, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct SignedPermit { + pub chain_id: String, // ignored, no Env in query + pub account_number: Uint128, // ignored + pub sequence: Uint128, // ignored + pub fee: Fee, // ignored + pub msgs: Vec, // the signed message + pub memo: String, // ignored +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct Fee { + pub gas: Uint128, + pub amount: Vec, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct Coin { + pub denom: String, + pub amount: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PermitMsg { + pub r#type: String, + pub value: PermitContent, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PermitContent { + pub permit_id: Uint128, + pub account: HumanAddr, + pub message: String, +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/state.rs b/src/state.rs index a9d9a6a..7136db2 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,6 +28,8 @@ pub const PREFIX_ALLOWANCES: &[u8] = b"allowances"; pub const PREFIX_VIEW_KEY: &[u8] = b"viewingkey"; pub const PREFIX_RECEIVERS: &[u8] = b"receivers"; +pub const QUERY_BALANCE_PERMIT_MSG: &str = "This signature is a permit to query my balance."; + // Config #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, JsonSchema)] @@ -47,6 +49,7 @@ pub struct Constants { pub mint_is_enabled: bool, // is burn enabled pub burn_is_enabled: bool, + pub query_balance_permit_msg: String, } pub struct ReadonlyConfig<'a, S: ReadonlyStorage> { From e299b4dff093128e552921167f7c84e2ae08b1c5 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sat, 25 Sep 2021 21:53:38 +0300 Subject: [PATCH 02/39] Validate permit message And rename permit_id to permit_user_id --- src/contract.rs | 19 +++++++++++++++---- src/msg.rs | 2 +- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index 84f2e69..a910e96 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -269,16 +269,27 @@ fn query_balance_with_permit( if signed.msgs[0].r#type != "query_balance_permit" { return Err(StdError::generic_err(format!( - "Permit message type must be 'query_balance_permit', got: {:?}.", + "Type must be 'query_balance_permit', got: {:?}.", signed.msgs[0].r#type ))); } let permit = &signed.msgs[0].value; - // Validate permit_id - let _permit_id = permit.permit_id; - // TODO fail if permit_id is revoked + // Validate permit_user_id + let _permit_user_id = &permit.permit_user_id; + // TODO fail if permit_user_id is revoked + + // Validate permit message + let query_balance_permit_msg = ReadonlyConfig::from_storage(&deps.storage) + .constants()? + .query_balance_permit_msg; + if permit.message != query_balance_permit_msg { + return Err(StdError::generic_err(format!( + "Message must be '{:?}', got: '{:?}'.", + query_balance_permit_msg, permit.message + ))); + } // Validate that account is derived from pubkey let pubkey = signature.pub_key.value; diff --git a/src/msg.rs b/src/msg.rs index fbb7afe..29d2881 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -509,7 +509,7 @@ pub struct PermitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PermitContent { - pub permit_id: Uint128, + pub permit_user_id: String, pub account: HumanAddr, pub message: String, } From 7065602936a9ae3c085b75b508d45dbd695c64aa Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sat, 25 Sep 2021 21:57:53 +0300 Subject: [PATCH 03/39] Rename account to query_balance_of --- src/contract.rs | 6 +++--- src/msg.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index a910e96..bff94df 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -295,10 +295,10 @@ fn query_balance_with_permit( let pubkey = signature.pub_key.value; let account_from_pubkey = deps.api.human_address(&pubkey_to_account(&pubkey))?; - if account_from_pubkey != permit.account { + if account_from_pubkey != permit.query_balance_of { return Err(StdError::generic_err(format!( "Input account {:?} not the same as account {:?} that was derived from pubkey {:?}.", - permit.account, + permit.query_balance_of, account_from_pubkey, pubkey.clone() ))); @@ -334,7 +334,7 @@ fn query_balance_with_permit( let amount = Uint128( ReadonlyBalances::from_storage(&deps.storage) - .account_amount(&deps.api.canonical_address(&permit.account)?), + .account_amount(&deps.api.canonical_address(&permit.query_balance_of)?), ); to_binary(&QueryAnswer::Balance { amount }) } diff --git a/src/msg.rs b/src/msg.rs index 29d2881..e5902e1 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -510,7 +510,7 @@ pub struct PermitMsg { #[serde(rename_all = "snake_case")] pub struct PermitContent { pub permit_user_id: String, - pub account: HumanAddr, + pub query_balance_of: HumanAddr, pub message: String, } From 4dd50883aaf3176a1b514b57e4583864b66df450 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 14:58:03 +0300 Subject: [PATCH 04/39] Fix permit's content serialization to bytes In order to verify the signature, we need to serialize the permit's content into JSON as UTF8 bytes. Amino encoding requires JSON serialization to sort object fields alphabetically, so to do so inside the contract a reorder of the permit data structs had to be done. Apparently serde_json_wasm keeps this order while serializing to bytes. For reference, this is how it's done by Keplr/cosmjs: https://github.com/enigmampc/cosmjs/blob/b2279928c6d46a568e619cafddc6c1bbd17ec1b0/packages/amino/src/signdoc.ts?plain=1#L31-L51 --- src/msg.rs | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/msg.rs b/src/msg.rs index e5902e1..4f6df84 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -470,37 +470,49 @@ pub struct Signature { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PubKey { - pub r#type: String, // must be "tendermint/PubKeySecp256k1", + /// ignored, but must be "tendermint/PubKeySecp256k1" + pub r#type: String, + /// Secp256k1 PubKey pub value: Binary, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! pub struct SignedPermit { - pub chain_id: String, // ignored, no Env in query - pub account_number: Uint128, // ignored - pub sequence: Uint128, // ignored - pub fee: Fee, // ignored - pub msgs: Vec, // the signed message - pub memo: String, // ignored + /// ignored + pub account_number: Uint128, + /// ignored, no Env in query + pub chain_id: String, + /// ignored + pub fee: Fee, + /// ignored + pub memo: String, + /// the signed message + pub msgs: Vec, + /// ignored + pub sequence: Uint128, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! pub struct Fee { - pub gas: Uint128, pub amount: Vec, + pub gas: Uint128, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! pub struct Coin { - pub denom: String, pub amount: Uint128, + pub denom: String, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! pub struct PermitMsg { pub r#type: String, pub value: PermitContent, @@ -508,10 +520,11 @@ pub struct PermitMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! pub struct PermitContent { + pub message: String, pub permit_user_id: String, pub query_balance_of: HumanAddr, - pub message: String, } #[cfg(test)] From 468eda94169f947702d72662a32b67c294553486 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 14:58:27 +0300 Subject: [PATCH 05/39] Update make start-server --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index e6f520f..2919649 100644 --- a/Makefile +++ b/Makefile @@ -71,9 +71,9 @@ contract.wasm.gz: contract.wasm .PHONY: start-server start-server: # CTRL+C to stop docker run -it --rm \ - -p 26657:26657 -p 26656:26656 -p 1317:1317 \ + -p 26657:26657 -p 26656:26656 -p 1337:1337 \ -v $$(pwd):/root/code \ - --name secretdev enigmampc/secret-network-sw-dev:v1.0.4-3 + --name secretdev enigmampc/secret-network-sw-dev:latest .PHONY: schema schema: From 0582c62fffd8a90658419cc426ff7a2e03a9bedd Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 23:09:29 +0300 Subject: [PATCH 06/39] Refactor, make permit API UX better --- Makefile | 6 ++++- src/contract.rs | 51 +++++++++++++---------------------- src/lib.rs | 1 + src/msg.rs | 72 +++---------------------------------------------- src/permit.rs | 72 +++++++++++++++++++++++++++++++++++++++++++++++++ src/state.rs | 5 ++-- 6 files changed, 101 insertions(+), 106 deletions(-) create mode 100644 src/permit.rs diff --git a/Makefile b/Makefile index 2919649..f325bcb 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,7 @@ start-server: # CTRL+C to stop docker run -it --rm \ -p 26657:26657 -p 26656:26656 -p 1337:1337 \ -v $$(pwd):/root/code \ - --name secretdev enigmampc/secret-network-sw-dev:latest + --name secretdev enigmampc/secret-network-sw-dev:v1.0.4-4 .PHONY: schema schema: @@ -84,3 +84,7 @@ clean: cargo clean rm -f ./contract.wasm ./contract.wasm.gz $(MAKE) -C tests/example-receiver clean + +.PHONY: integration-test +permit-setup: compile-optimized + if tests/integration.sh; then echo -n '\a'; else echo -n '\a'; sleep 0.125; echo -n '\a'; fi \ No newline at end of file diff --git a/src/contract.rs b/src/contract.rs index bff94df..f824841 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -14,13 +14,12 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::msg::{Signature, SignedPermit}; +use crate::permit::{PermitSignature, Permit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ get_receiver_hash, read_allowance, read_viewing_key, set_receiver_hash, write_allowance, write_viewing_key, Balances, Config, Constants, ReadonlyBalances, ReadonlyConfig, - QUERY_BALANCE_PERMIT_MSG, }; use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, @@ -95,7 +94,7 @@ pub fn init( redeem_is_enabled: init_config.redeem_enabled(), mint_is_enabled: init_config.mint_enabled(), burn_is_enabled: init_config.burn_enabled(), - query_balance_permit_msg: QUERY_BALANCE_PERMIT_MSG.to_string(), + contract_address: env.contract.address, })?; config.set_total_supply(total_supply); config.set_contract_status(ContractStatusLevel::NormalRun); @@ -257,8 +256,8 @@ pub fn query(deps: &Extern, msg: QueryM fn query_balance_with_permit( deps: &Extern, - signed: SignedPermit, - signature: Signature, + signed: Permit, + signature: PermitSignature, ) -> Result { if signed.msgs.len() != 1 { return Err(StdError::generic_err(format!( @@ -267,44 +266,36 @@ fn query_balance_with_permit( ))); } - if signed.msgs[0].r#type != "query_balance_permit" { + if signed.msgs[0].r#type != "query_permit" { return Err(StdError::generic_err(format!( - "Type must be 'query_balance_permit', got: {:?}.", + "Type must be 'query_permit', got: {:?}.", signed.msgs[0].r#type ))); } let permit = &signed.msgs[0].value; - // Validate permit_user_id - let _permit_user_id = &permit.permit_user_id; - // TODO fail if permit_user_id is revoked + // Validate permit_name + let _permit_name = &permit.permit_name; + // TODO fail if permit_name is revoked // Validate permit message - let query_balance_permit_msg = ReadonlyConfig::from_storage(&deps.storage) + let token_address = ReadonlyConfig::from_storage(&deps.storage) .constants()? - .query_balance_permit_msg; - if permit.message != query_balance_permit_msg { + .contract_address; + + if !permit.allowed_tokens.contains(&token_address) { return Err(StdError::generic_err(format!( - "Message must be '{:?}', got: '{:?}'.", - query_balance_permit_msg, permit.message + "Permit doesn't apply to token {:?}, allowed tokens: {:?}", + token_address, permit.allowed_tokens ))); } - // Validate that account is derived from pubkey + // Derive account from pubkey let pubkey = signature.pub_key.value; let account_from_pubkey = deps.api.human_address(&pubkey_to_account(&pubkey))?; - if account_from_pubkey != permit.query_balance_of { - return Err(StdError::generic_err(format!( - "Input account {:?} not the same as account {:?} that was derived from pubkey {:?}.", - permit.query_balance_of, - account_from_pubkey, - pubkey.clone() - ))); - } - - // Validate signature, source: https://github.com/enigmampc/SecretNetwork/blob/master/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 + // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 let signed_bytes = &to_binary(&signed)?.0; let signed_bytes_hash = Sha256::digest(signed_bytes); @@ -334,7 +325,7 @@ fn query_balance_with_permit( let amount = Uint128( ReadonlyBalances::from_storage(&deps.storage) - .account_amount(&deps.api.canonical_address(&permit.query_balance_of)?), + .account_amount(&deps.api.canonical_address(&account_from_pubkey)?), ); to_binary(&QueryAnswer::Balance { amount }) } @@ -426,7 +417,6 @@ fn query_token_info(storage: &S) -> QueryResult { symbol: constants.symbol, decimals: constants.decimals, total_supply, - query_balance_permit_msg: constants.query_balance_permit_msg, }) } @@ -3709,16 +3699,11 @@ mod tests { symbol, decimals, total_supply, - query_balance_permit_msg, } => { assert_eq!(name, init_name); assert_eq!(symbol, init_symbol); assert_eq!(decimals, init_decimals); assert_eq!(total_supply, Some(Uint128(5000))); - assert_eq!( - query_balance_permit_msg, - QUERY_BALANCE_PERMIT_MSG.to_string() - ); } _ => panic!("unexpected"), } diff --git a/src/lib.rs b/src/lib.rs index 307d2d0..1b2a7f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ mod batch; pub mod contract; pub mod msg; +mod permit; mod rand; pub mod receiver; pub mod state; diff --git a/src/msg.rs b/src/msg.rs index 4f6df84..58d96d9 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; use crate::batch; +use crate::permit::{PermitSignature, Permit}; use crate::transaction_history::{RichTx, Tx}; use crate::viewing_key::ViewingKey; @@ -324,8 +325,8 @@ pub enum QueryMsg { key: String, }, BalanceWithPermit { - signed: SignedPermit, - signature: Signature, + signed: Permit, + signature: PermitSignature, }, TransferHistory { address: HumanAddr, @@ -369,7 +370,6 @@ pub enum QueryAnswer { symbol: String, decimals: u8, total_supply: Option, - query_balance_permit_msg: String, }, TokenConfig { public_total_supply: bool, @@ -461,72 +461,6 @@ pub fn space_pad(block_size: usize, message: &mut Vec) -> &mut Vec { message } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct Signature { - pub pub_key: PubKey, - pub signature: Binary, -} -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct PubKey { - /// ignored, but must be "tendermint/PubKeySecp256k1" - pub r#type: String, - /// Secp256k1 PubKey - pub value: Binary, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! -pub struct SignedPermit { - /// ignored - pub account_number: Uint128, - /// ignored, no Env in query - pub chain_id: String, - /// ignored - pub fee: Fee, - /// ignored - pub memo: String, - /// the signed message - pub msgs: Vec, - /// ignored - pub sequence: Uint128, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! -pub struct Fee { - pub amount: Vec, - pub gas: Uint128, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! -pub struct Coin { - pub amount: Uint128, - pub denom: String, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! -pub struct PermitMsg { - pub r#type: String, - pub value: PermitContent, -} - -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! -pub struct PermitContent { - pub message: String, - pub permit_user_id: String, - pub query_balance_of: HumanAddr, -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/permit.rs b/src/permit.rs new file mode 100644 index 0000000..0daf2eb --- /dev/null +++ b/src/permit.rs @@ -0,0 +1,72 @@ +#![allow(clippy::field_reassign_with_default)] // This is triggered in `#[derive(JsonSchema)]` + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::{Binary, HumanAddr, Uint128}; + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PermitSignature { + pub pub_key: PubKey, + pub signature: Binary, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PubKey { + /// ignored, but must be "tendermint/PubKeySecp256k1" + pub r#type: String, + /// Secp256k1 PubKey + pub value: Binary, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! +pub struct Permit { + /// ignored + pub account_number: Uint128, + /// ignored, no Env in query + pub chain_id: String, + /// ignored + pub fee: Fee, + /// ignored + pub memo: String, + /// the signed message + pub msgs: Vec, + /// ignored + pub sequence: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! +pub struct Fee { + pub amount: Vec, + pub gas: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! +pub struct Coin { + pub amount: Uint128, + pub denom: String, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! +pub struct PermitMsg { + pub r#type: String, + pub value: PermitContent, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +// Note: The order of fields in this struct is important for the permit signature verification! +pub struct PermitContent { + pub allowed_tokens: Vec, + pub permit_name: String, +} diff --git a/src/state.rs b/src/state.rs index 7136db2..b42c950 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,8 +28,6 @@ pub const PREFIX_ALLOWANCES: &[u8] = b"allowances"; pub const PREFIX_VIEW_KEY: &[u8] = b"viewingkey"; pub const PREFIX_RECEIVERS: &[u8] = b"receivers"; -pub const QUERY_BALANCE_PERMIT_MSG: &str = "This signature is a permit to query my balance."; - // Config #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, JsonSchema)] @@ -49,7 +47,8 @@ pub struct Constants { pub mint_is_enabled: bool, // is burn enabled pub burn_is_enabled: bool, - pub query_balance_permit_msg: String, + // the address of this contract, used to validate query permits + pub contract_address: HumanAddr, } pub struct ReadonlyConfig<'a, S: ReadonlyStorage> { From 476c0439e1bd6e9c23514d43bd0bf56f60a569c4 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 23:28:06 +0300 Subject: [PATCH 07/39] remain::sorted on SignedPermit To make sure it's aligned with Amino encoding --- Cargo.lock | 12 ++++++++++++ Cargo.toml | 1 + src/contract.rs | 4 ++-- src/msg.rs | 4 ++-- src/permit.rs | 7 ++++++- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e3f255..f56db2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -370,6 +370,17 @@ dependencies = [ "rand_core", ] +[[package]] +name = "remain" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ba1e78fa68412cb93ef642fd4d20b9a941be49ee9333875ebaf13112673ea7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -622,6 +633,7 @@ dependencies = [ "hex", "rand_chacha", "rand_core", + "remain", "ripemd160", "schemars", "secp256k1", diff --git a/Cargo.toml b/Cargo.toml index 674da5d..b0ae2f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ rand_core = { version = "0.5.1", default-features = false } sha2 = { version = "0.9.1", default-features = false } ripemd160 = "0.9.1" secp256k1 = "0.19.0" +remain = "0.2.2" [dev-dependencies] cosmwasm-schema = { version = "0.9.2" } diff --git a/src/contract.rs b/src/contract.rs index f824841..f813a15 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -14,7 +14,7 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::{PermitSignature, Permit}; +use crate::permit::{PermitSignature, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ @@ -256,7 +256,7 @@ pub fn query(deps: &Extern, msg: QueryM fn query_balance_with_permit( deps: &Extern, - signed: Permit, + signed: SignedPermit, signature: PermitSignature, ) -> Result { if signed.msgs.len() != 1 { diff --git a/src/msg.rs b/src/msg.rs index 58d96d9..3d85149 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; use crate::batch; -use crate::permit::{PermitSignature, Permit}; +use crate::permit::{SignedPermit, PermitSignature}; use crate::transaction_history::{RichTx, Tx}; use crate::viewing_key::ViewingKey; @@ -325,7 +325,7 @@ pub enum QueryMsg { key: String, }, BalanceWithPermit { - signed: Permit, + signed: SignedPermit, signature: PermitSignature, }, TransferHistory { diff --git a/src/permit.rs b/src/permit.rs index 0daf2eb..7e40d63 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -21,10 +21,11 @@ pub struct PubKey { pub value: Binary, } +#[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] // Note: The order of fields in this struct is important for the permit signature verification! -pub struct Permit { +pub struct SignedPermit { /// ignored pub account_number: Uint128, /// ignored, no Env in query @@ -39,6 +40,7 @@ pub struct Permit { pub sequence: Uint128, } +#[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] // Note: The order of fields in this struct is important for the permit signature verification! @@ -47,6 +49,7 @@ pub struct Fee { pub gas: Uint128, } +#[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] // Note: The order of fields in this struct is important for the permit signature verification! @@ -55,6 +58,7 @@ pub struct Coin { pub denom: String, } +#[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] // Note: The order of fields in this struct is important for the permit signature verification! @@ -63,6 +67,7 @@ pub struct PermitMsg { pub value: PermitContent, } +#[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] // Note: The order of fields in this struct is important for the permit signature verification! From 2365946039ac227bbe41284cc20edfd5cb6db06c Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 23:55:02 +0300 Subject: [PATCH 08/39] Query with permit for all authenticated queries - Balance - TransferHistory - TransactionHistory - Allowance --- src/contract.rs | 52 +++++++++++++++++++++++++++---------------------- src/msg.rs | 19 +++++++++++++----- src/permit.rs | 19 ++++++++++++------ 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index f813a15..12e4aec 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -10,11 +10,12 @@ use secp256k1::Secp256k1; use sha2::Sha256; use crate::batch; +use crate::msg::QueryWithPermit; use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::{PermitSignature, SignedPermit}; +use crate::permit::{Permit, PermitSignature, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ @@ -247,36 +248,34 @@ pub fn query(deps: &Extern, msg: QueryM QueryMsg::ContractStatus {} => query_contract_status(&deps.storage), QueryMsg::ExchangeRate {} => query_exchange_rate(&deps.storage), QueryMsg::Minters { .. } => query_minters(deps), - QueryMsg::BalanceWithPermit { signed, signature } => { - query_balance_with_permit(deps, signed, signature) - } + QueryMsg::WithPermit { permit, query } => query_with_permit(deps, permit, query), _ => authenticated_queries(deps, msg), } } -fn query_balance_with_permit( +fn query_with_permit( deps: &Extern, - signed: SignedPermit, - signature: PermitSignature, + permit: Permit, + query: QueryWithPermit, ) -> Result { - if signed.msgs.len() != 1 { + if permit.signed.msgs.len() != 1 { return Err(StdError::generic_err(format!( "Must sign exactly 1 permit message, got: {:?}.", - signed.msgs.len() + permit.signed.msgs.len() ))); } - if signed.msgs[0].r#type != "query_permit" { + if permit.signed.msgs[0].r#type != "query_permit" { return Err(StdError::generic_err(format!( "Type must be 'query_permit', got: {:?}.", - signed.msgs[0].r#type + permit.signed.msgs[0].r#type ))); } - let permit = &signed.msgs[0].value; + let permit_content = &permit.signed.msgs[0].value; // Validate permit_name - let _permit_name = &permit.permit_name; + let _permit_name = &permit_content.permit_name; // TODO fail if permit_name is revoked // Validate permit message @@ -284,19 +283,19 @@ fn query_balance_with_permit( .constants()? .contract_address; - if !permit.allowed_tokens.contains(&token_address) { + if !permit_content.allowed_tokens.contains(&token_address) { return Err(StdError::generic_err(format!( "Permit doesn't apply to token {:?}, allowed tokens: {:?}", - token_address, permit.allowed_tokens + token_address, permit_content.allowed_tokens ))); } // Derive account from pubkey - let pubkey = signature.pub_key.value; + let pubkey = permit.signature.pub_key.value; let account_from_pubkey = deps.api.human_address(&pubkey_to_account(&pubkey))?; // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 - let signed_bytes = &to_binary(&signed)?.0; + let signed_bytes = &to_binary(&permit.signed)?.0; let signed_bytes_hash = Sha256::digest(signed_bytes); let msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { @@ -309,7 +308,7 @@ fn query_balance_with_permit( let verifier = Secp256k1::verification_only(); // Create `secp256k1`'s types - let secp256k1_signature = secp256k1::Signature::from_compact(&signature.signature.0) + let secp256k1_signature = secp256k1::Signature::from_compact(&permit.signature.signature.0) .map_err(|err| StdError::generic_err(format!("Malformed signature: {:?}", err)))?; let secp256k1_pubkey = secp256k1::PublicKey::from_slice(pubkey.0.as_slice()) .map_err(|err| StdError::generic_err(format!("Malformed pubkey: {:?}", err)))?; @@ -323,11 +322,18 @@ fn query_balance_with_permit( )) })?; - let amount = Uint128( - ReadonlyBalances::from_storage(&deps.storage) - .account_amount(&deps.api.canonical_address(&account_from_pubkey)?), - ); - to_binary(&QueryAnswer::Balance { amount }) + return match query { + QueryWithPermit::Balance {} => query_balance(&deps, &account_from_pubkey), + QueryWithPermit::TransferHistory { page, page_size } => { + query_transfers(&deps, &account_from_pubkey, page.unwrap_or(0), page_size) + } + QueryWithPermit::TransactionHistory { page, page_size } => { + query_transactions(&deps, &account_from_pubkey, page.unwrap_or(0), page_size) + } + QueryWithPermit::Allowance { spender } => { + query_allowance(deps, account_from_pubkey, spender) + } + }; } fn pubkey_to_account(pubkey: &Binary) -> CanonicalAddr { diff --git a/src/msg.rs b/src/msg.rs index 3d85149..70ce901 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; use crate::batch; -use crate::permit::{SignedPermit, PermitSignature}; +use crate::permit::{Permit, PermitSignature, SignedPermit}; use crate::transaction_history::{RichTx, Tx}; use crate::viewing_key::ViewingKey; @@ -324,10 +324,6 @@ pub enum QueryMsg { address: HumanAddr, key: String, }, - BalanceWithPermit { - signed: SignedPermit, - signature: PermitSignature, - }, TransferHistory { address: HumanAddr, key: String, @@ -341,6 +337,10 @@ pub enum QueryMsg { page_size: u32, }, Minters {}, + WithPermit { + permit: Permit, + query: QueryWithPermit, + }, } impl QueryMsg { @@ -362,6 +362,15 @@ impl QueryMsg { } } +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum QueryWithPermit { + Allowance { spender: HumanAddr }, + Balance {}, + TransferHistory { page: Option, page_size: u32 }, + TransactionHistory { page: Option, page_size: u32 }, +} + #[derive(Serialize, Deserialize, JsonSchema, Debug)] #[serde(rename_all = "snake_case")] pub enum QueryAnswer { diff --git a/src/permit.rs b/src/permit.rs index 7e40d63..a11a707 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -5,6 +5,13 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, Uint128}; +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct Permit { + pub signed: SignedPermit, + pub signature: PermitSignature, +} + #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PermitSignature { @@ -15,16 +22,16 @@ pub struct PermitSignature { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PubKey { - /// ignored, but must be "tendermint/PubKeySecp256k1" + /// ignored, but must be "tendermint/PubKeySecp256k1" otherwise the verification will fail pub r#type: String, /// Secp256k1 PubKey pub value: Binary, } +// Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! pub struct SignedPermit { /// ignored pub account_number: Uint128, @@ -40,37 +47,37 @@ pub struct SignedPermit { pub sequence: Uint128, } +// Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! pub struct Fee { pub amount: Vec, pub gas: Uint128, } +// Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! pub struct Coin { pub amount: Uint128, pub denom: String, } +// Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! pub struct PermitMsg { pub r#type: String, pub value: PermitContent, } +// Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -// Note: The order of fields in this struct is important for the permit signature verification! pub struct PermitContent { pub allowed_tokens: Vec, pub permit_name: String, From 7d8a3658ed39d7eeced2a71c4c85694bf8fc28fb Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 26 Sep 2021 23:58:41 +0300 Subject: [PATCH 09/39] Refactor some var/func names --- src/contract.rs | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index 12e4aec..b80a109 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -249,7 +249,7 @@ pub fn query(deps: &Extern, msg: QueryM QueryMsg::ExchangeRate {} => query_exchange_rate(&deps.storage), QueryMsg::Minters { .. } => query_minters(deps), QueryMsg::WithPermit { permit, query } => query_with_permit(deps, permit, query), - _ => authenticated_queries(deps, msg), + _ => viewing_keys_queries(deps, msg), } } @@ -292,29 +292,28 @@ fn query_with_permit( // Derive account from pubkey let pubkey = permit.signature.pub_key.value; - let account_from_pubkey = deps.api.human_address(&pubkey_to_account(&pubkey))?; + let account = deps.api.human_address(&pubkey_to_account(&pubkey))?; // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 let signed_bytes = &to_binary(&permit.signed)?.0; - let signed_bytes_hash = Sha256::digest(signed_bytes); - let msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { - StdError::generic_err(format!( - "Failed to create a secp256k1 message from signed_bytes: {:?}", - err - )) - })?; + let secp256k1_msg = + secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { + StdError::generic_err(format!( + "Failed to create a secp256k1 message from signed_bytes: {:?}", + err + )) + })?; - let verifier = Secp256k1::verification_only(); + let secp256k1_verifier = Secp256k1::verification_only(); - // Create `secp256k1`'s types let secp256k1_signature = secp256k1::Signature::from_compact(&permit.signature.signature.0) .map_err(|err| StdError::generic_err(format!("Malformed signature: {:?}", err)))?; let secp256k1_pubkey = secp256k1::PublicKey::from_slice(pubkey.0.as_slice()) .map_err(|err| StdError::generic_err(format!("Malformed pubkey: {:?}", err)))?; - verifier - .verify(&msg, &secp256k1_signature, &secp256k1_pubkey) + secp256k1_verifier + .verify(&secp256k1_msg, &secp256k1_signature, &secp256k1_pubkey) .map_err(|err| { StdError::generic_err(format!( "Failed to verify signatures for the given permit: {:?}", @@ -322,18 +321,16 @@ fn query_with_permit( )) })?; - return match query { - QueryWithPermit::Balance {} => query_balance(&deps, &account_from_pubkey), + match query { + QueryWithPermit::Balance {} => query_balance(&deps, &account), QueryWithPermit::TransferHistory { page, page_size } => { - query_transfers(&deps, &account_from_pubkey, page.unwrap_or(0), page_size) + query_transfers(&deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::TransactionHistory { page, page_size } => { - query_transactions(&deps, &account_from_pubkey, page.unwrap_or(0), page_size) - } - QueryWithPermit::Allowance { spender } => { - query_allowance(deps, account_from_pubkey, spender) + query_transactions(&deps, &account, page.unwrap_or(0), page_size) } - }; + QueryWithPermit::Allowance { spender } => query_allowance(deps, account, spender), + } } fn pubkey_to_account(pubkey: &Binary) -> CanonicalAddr { @@ -342,7 +339,7 @@ fn pubkey_to_account(pubkey: &Binary) -> CanonicalAddr { CanonicalAddr(Binary(hasher.finalize().to_vec())) } -pub fn authenticated_queries( +pub fn viewing_keys_queries( deps: &Extern, msg: QueryMsg, ) -> QueryResult { From e3ac874c93debc3eb540c434e4256c18a667bbc2 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 27 Sep 2021 00:38:34 +0300 Subject: [PATCH 10/39] Implement revoke permit --- src/contract.rs | 36 ++++++++++++++++++++++++----- src/msg.rs | 12 +++++++++- src/state.rs | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index b80a109..9166f06 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -15,12 +15,13 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::{Permit, PermitSignature, SignedPermit}; +use crate::permit::Permit; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ get_receiver_hash, read_allowance, read_viewing_key, set_receiver_hash, write_allowance, write_viewing_key, Balances, Config, Constants, ReadonlyBalances, ReadonlyConfig, + ReadonlyRevokedPermits, RevokedPemits, }; use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, @@ -236,6 +237,7 @@ pub fn handle( HandleMsg::AddMinters { minters, .. } => add_minters(deps, env, minters), HandleMsg::RemoveMinters { minters, .. } => remove_minters(deps, env, minters), HandleMsg::SetMinters { minters, .. } => set_minters(deps, env, minters), + HandleMsg::RevokePermit { permit_name, .. } => revoke_permit(deps, env, permit_name), }; pad_response(response) @@ -274,11 +276,7 @@ fn query_with_permit( let permit_content = &permit.signed.msgs[0].value; - // Validate permit_name - let _permit_name = &permit_content.permit_name; - // TODO fail if permit_name is revoked - - // Validate permit message + // Validate permit content let token_address = ReadonlyConfig::from_storage(&deps.storage) .constants()? .contract_address; @@ -294,6 +292,17 @@ fn query_with_permit( let pubkey = permit.signature.pub_key.value; let account = deps.api.human_address(&pubkey_to_account(&pubkey))?; + // Validate permit_name + let permit_name = &permit_content.permit_name; + let is_permit_revoked = ReadonlyRevokedPermits::from_storage(&deps.storage) + .is_permit_revoked(&account, &permit_name); + if is_permit_revoked { + return Err(StdError::generic_err(format!( + "Permit '{:?}' was revoked by account {:?}", + permit_name, account + ))); + } + // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 let signed_bytes = &to_binary(&permit.signed)?.0; let signed_bytes_hash = Sha256::digest(signed_bytes); @@ -321,6 +330,7 @@ fn query_with_permit( )) })?; + // We're verified! We can now execute the query match query { QueryWithPermit::Balance {} => query_balance(&deps, &account), QueryWithPermit::TransferHistory { page, page_size } => { @@ -1704,6 +1714,20 @@ fn perform_transfer( Ok(()) } +fn revoke_permit( + deps: &mut Extern, + env: Env, + permit_name: String, +) -> StdResult { + RevokedPemits::from_storage(&mut deps.storage).revoke_permit(&env.message.sender, &permit_name); + + Ok(HandleResponse { + messages: vec![], + log: vec![], + data: Some(to_binary(&HandleAnswer::RevokePemit { status: Success })?), + }) +} + fn is_admin(config: &Config, account: &HumanAddr) -> StdResult { let consts = config.constants()?; if &consts.admin != account { diff --git a/src/msg.rs b/src/msg.rs index 70ce901..0a06721 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; use crate::batch; -use crate::permit::{Permit, PermitSignature, SignedPermit}; +use crate::permit::Permit; use crate::transaction_history::{RichTx, Tx}; use crate::viewing_key::ViewingKey; @@ -213,6 +213,11 @@ pub enum HandleMsg { level: ContractStatusLevel, padding: Option, }, + + // Permit + RevokePermit { + permit_name: String, + }, } #[derive(Serialize, Deserialize, JsonSchema, Debug)] @@ -306,6 +311,11 @@ pub enum HandleAnswer { SetContractStatus { status: ResponseStatus, }, + + // Permit + RevokePemit { + status: ResponseStatus, + }, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] diff --git a/src/state.rs b/src/state.rs index b42c950..1d2909d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,6 +28,8 @@ pub const PREFIX_ALLOWANCES: &[u8] = b"allowances"; pub const PREFIX_VIEW_KEY: &[u8] = b"viewingkey"; pub const PREFIX_RECEIVERS: &[u8] = b"receivers"; +pub const PREFIX_REVOKED_PERMITS: &[u8] = b"revoked_permits"; + // Config #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, JsonSchema)] @@ -297,6 +299,65 @@ impl<'a, S: ReadonlyStorage> ReadonlyBalancesImpl<'a, S> { } } +pub struct ReadonlyRevokedPermits<'a, S: ReadonlyStorage> { + storage: ReadonlyPrefixedStorage<'a, S>, +} + +impl<'a, S: ReadonlyStorage> ReadonlyRevokedPermits<'a, S> { + pub fn from_storage(storage: &'a S) -> Self { + Self { + storage: ReadonlyPrefixedStorage::new(PREFIX_REVOKED_PERMITS, storage), + } + } + + fn as_readonly(&self) -> ReadonlyRevokedPermitsImpl> { + ReadonlyRevokedPermitsImpl(&self.storage) + } + + pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { + self.as_readonly().is_permit_revoked(account, permit_name) + } +} + +pub struct RevokedPemits<'a, S: Storage> { + storage: PrefixedStorage<'a, S>, +} + +impl<'a, S: Storage> RevokedPemits<'a, S> { + pub fn from_storage(storage: &'a mut S) -> Self { + Self { + storage: PrefixedStorage::new(PREFIX_REVOKED_PERMITS, storage), + } + } + + fn as_readonly(&self) -> ReadonlyRevokedPermitsImpl> { + ReadonlyRevokedPermitsImpl(&self.storage) + } + + pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { + self.as_readonly().is_permit_revoked(account, permit_name) + } + + pub fn revoke_permit(&mut self, account: &HumanAddr, permit_name: &String) { + let storage_key = account.to_string() + permit_name; + + self.storage.set(storage_key.as_bytes(), &[]) + } +} + +struct ReadonlyRevokedPermitsImpl<'a, S: ReadonlyStorage>(&'a S); + +impl<'a, S: ReadonlyStorage> ReadonlyRevokedPermitsImpl<'a, S> { + pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { + let storage_key = account.to_string() + permit_name; + + match self.0.get(storage_key.as_bytes()) { + Some(_) => true, + None => false, + } + } +} + // Allowances #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Default, JsonSchema)] From b1f3d4647971c46f44f1831c595ad48db11b9200 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 27 Sep 2021 00:43:40 +0300 Subject: [PATCH 11/39] Clean makefile --- Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile b/Makefile index f325bcb..9ef335b 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,3 @@ clean: cargo clean rm -f ./contract.wasm ./contract.wasm.gz $(MAKE) -C tests/example-receiver clean - -.PHONY: integration-test -permit-setup: compile-optimized - if tests/integration.sh; then echo -n '\a'; else echo -n '\a'; sleep 0.125; echo -n '\a'; fi \ No newline at end of file From ca14f163859df1af075abb7b664758fd5b21f312 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 27 Sep 2021 12:16:11 +0300 Subject: [PATCH 12/39] Refactor RevokedPermits storage --- src/contract.rs | 7 +++--- src/state.rs | 64 +++++++++++-------------------------------------- 2 files changed, 17 insertions(+), 54 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index 9166f06..b98a55f 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -21,7 +21,7 @@ use crate::receiver::Snip20ReceiveMsg; use crate::state::{ get_receiver_hash, read_allowance, read_viewing_key, set_receiver_hash, write_allowance, write_viewing_key, Balances, Config, Constants, ReadonlyBalances, ReadonlyConfig, - ReadonlyRevokedPermits, RevokedPemits, + RevokedPemits, }; use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, @@ -294,8 +294,7 @@ fn query_with_permit( // Validate permit_name let permit_name = &permit_content.permit_name; - let is_permit_revoked = ReadonlyRevokedPermits::from_storage(&deps.storage) - .is_permit_revoked(&account, &permit_name); + let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, &permit_name); if is_permit_revoked { return Err(StdError::generic_err(format!( "Permit '{:?}' was revoked by account {:?}", @@ -1719,7 +1718,7 @@ fn revoke_permit( env: Env, permit_name: String, ) -> StdResult { - RevokedPemits::from_storage(&mut deps.storage).revoke_permit(&env.message.sender, &permit_name); + RevokedPemits::revoke_permit(&mut deps.storage, &env.message.sender, &permit_name); Ok(HandleResponse { messages: vec![], diff --git a/src/state.rs b/src/state.rs index 1d2909d..47830c2 100644 --- a/src/state.rs +++ b/src/state.rs @@ -299,62 +299,26 @@ impl<'a, S: ReadonlyStorage> ReadonlyBalancesImpl<'a, S> { } } -pub struct ReadonlyRevokedPermits<'a, S: ReadonlyStorage> { - storage: ReadonlyPrefixedStorage<'a, S>, -} - -impl<'a, S: ReadonlyStorage> ReadonlyRevokedPermits<'a, S> { - pub fn from_storage(storage: &'a S) -> Self { - Self { - storage: ReadonlyPrefixedStorage::new(PREFIX_REVOKED_PERMITS, storage), - } - } - - fn as_readonly(&self) -> ReadonlyRevokedPermitsImpl> { - ReadonlyRevokedPermitsImpl(&self.storage) - } - - pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { - self.as_readonly().is_permit_revoked(account, permit_name) - } -} - -pub struct RevokedPemits<'a, S: Storage> { - storage: PrefixedStorage<'a, S>, -} - -impl<'a, S: Storage> RevokedPemits<'a, S> { - pub fn from_storage(storage: &'a mut S) -> Self { - Self { - storage: PrefixedStorage::new(PREFIX_REVOKED_PERMITS, storage), - } - } - - fn as_readonly(&self) -> ReadonlyRevokedPermitsImpl> { - ReadonlyRevokedPermitsImpl(&self.storage) - } - - pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { - self.as_readonly().is_permit_revoked(account, permit_name) - } - - pub fn revoke_permit(&mut self, account: &HumanAddr, permit_name: &String) { +pub struct RevokedPemits {} + +impl RevokedPemits { + pub fn is_permit_revoked( + storgae: &dyn Storage, + account: &HumanAddr, + permit_name: &String, + ) -> bool { let storage_key = account.to_string() + permit_name; - self.storage.set(storage_key.as_bytes(), &[]) + match storgae.get(storage_key.as_bytes()) { + Some(_) => true, + None => false, + } } -} -struct ReadonlyRevokedPermitsImpl<'a, S: ReadonlyStorage>(&'a S); - -impl<'a, S: ReadonlyStorage> ReadonlyRevokedPermitsImpl<'a, S> { - pub fn is_permit_revoked(&self, account: &HumanAddr, permit_name: &String) -> bool { + pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &String) { let storage_key = account.to_string() + permit_name; - match self.0.get(storage_key.as_bytes()) { - Some(_) => true, - None => false, - } + storage.set(storage_key.as_bytes(), &[]) } } From 7c0d408864cbece13a0dca3d06cfce99cbc1ce69 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 27 Sep 2021 12:16:48 +0300 Subject: [PATCH 13/39] :shrug: --- src/state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state.rs b/src/state.rs index 47830c2..75c63d9 100644 --- a/src/state.rs +++ b/src/state.rs @@ -299,7 +299,7 @@ impl<'a, S: ReadonlyStorage> ReadonlyBalancesImpl<'a, S> { } } -pub struct RevokedPemits {} +pub struct RevokedPemits; impl RevokedPemits { pub fn is_permit_revoked( From a8dace9b230d2df463a470e9efd9bae9716fe1c9 Mon Sep 17 00:00:00 2001 From: Reuven Podmazo Date: Mon, 27 Sep 2021 13:34:06 +0300 Subject: [PATCH 14/39] simplified permit query interface --- src/contract.rs | 46 ++++++++++-------------------- src/msg.rs | 2 +- src/permit.rs | 75 +++++++++++++++++++++++++++++++++++++++++++------ src/state.rs | 4 +-- 4 files changed, 84 insertions(+), 43 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index b98a55f..4ea82fd 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -15,7 +15,7 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::Permit; +use crate::permit::{Permit, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ @@ -260,31 +260,15 @@ fn query_with_permit( permit: Permit, query: QueryWithPermit, ) -> Result { - if permit.signed.msgs.len() != 1 { - return Err(StdError::generic_err(format!( - "Must sign exactly 1 permit message, got: {:?}.", - permit.signed.msgs.len() - ))); - } - - if permit.signed.msgs[0].r#type != "query_permit" { - return Err(StdError::generic_err(format!( - "Type must be 'query_permit', got: {:?}.", - permit.signed.msgs[0].r#type - ))); - } - - let permit_content = &permit.signed.msgs[0].value; - // Validate permit content let token_address = ReadonlyConfig::from_storage(&deps.storage) .constants()? .contract_address; - if !permit_content.allowed_tokens.contains(&token_address) { + if !permit.signed.allowed_tokens.contains(&token_address) { return Err(StdError::generic_err(format!( "Permit doesn't apply to token {:?}, allowed tokens: {:?}", - token_address, permit_content.allowed_tokens + token_address, permit.signed.allowed_tokens ))); } @@ -293,8 +277,8 @@ fn query_with_permit( let account = deps.api.human_address(&pubkey_to_account(&pubkey))?; // Validate permit_name - let permit_name = &permit_content.permit_name; - let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, &permit_name); + let permit_name = &permit.signed.permit_name; + let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, permit_name); if is_permit_revoked { return Err(StdError::generic_err(format!( "Permit '{:?}' was revoked by account {:?}", @@ -303,8 +287,8 @@ fn query_with_permit( } // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 - let signed_bytes = &to_binary(&permit.signed)?.0; - let signed_bytes_hash = Sha256::digest(signed_bytes); + let signed_bytes = to_binary(&SignedPermit::from_params(permit.signed))?; + let signed_bytes_hash = Sha256::digest(signed_bytes.as_slice()); let secp256k1_msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { StdError::generic_err(format!( @@ -331,12 +315,12 @@ fn query_with_permit( // We're verified! We can now execute the query match query { - QueryWithPermit::Balance {} => query_balance(&deps, &account), + QueryWithPermit::Balance {} => query_balance(deps, &account), QueryWithPermit::TransferHistory { page, page_size } => { - query_transfers(&deps, &account, page.unwrap_or(0), page_size) + query_transfers(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::TransactionHistory { page, page_size } => { - query_transactions(&deps, &account, page.unwrap_or(0), page_size) + query_transactions(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::Allowance { spender } => query_allowance(deps, account, spender), } @@ -366,28 +350,28 @@ pub fn viewing_keys_queries( } else if key.check_viewing_key(expected_key.unwrap().as_slice()) { return match msg { // Base - QueryMsg::Balance { address, .. } => query_balance(&deps, &address), + QueryMsg::Balance { address, .. } => query_balance(deps, &address), QueryMsg::TransferHistory { address, page, page_size, .. - } => query_transfers(&deps, &address, page.unwrap_or(0), page_size), + } => query_transfers(deps, &address, page.unwrap_or(0), page_size), QueryMsg::TransactionHistory { address, page, page_size, .. - } => query_transactions(&deps, &address, page.unwrap_or(0), page_size), + } => query_transactions(deps, &address, page.unwrap_or(0), page_size), QueryMsg::Allowance { owner, spender, .. } => query_allowance(deps, owner, spender), _ => panic!("This query type does not require authentication"), }; } } - Ok(to_binary(&QueryAnswer::ViewingKeyError { + to_binary(&QueryAnswer::ViewingKeyError { msg: "Wrong viewing key for this address or viewing key not set".to_string(), - })?) + }) } fn query_exchange_rate(storage: &S) -> QueryResult { diff --git a/src/msg.rs b/src/msg.rs index 0a06721..e530186 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -318,7 +318,7 @@ pub enum HandleAnswer { }, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryMsg { TokenInfo {}, diff --git a/src/permit.rs b/src/permit.rs index a11a707..5f10387 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -5,21 +5,29 @@ use serde::{Deserialize, Serialize}; use cosmwasm_std::{Binary, HumanAddr, Uint128}; -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Permit { - pub signed: SignedPermit, + pub signed: PermitParams, pub signature: PermitSignature, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub struct PermitParams { + pub allowed_tokens: Vec, + pub permit_name: String, + pub chain_id: String, +} + +#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PermitSignature { pub pub_key: PubKey, pub signature: Binary, } -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct PubKey { /// ignored, but must be "tendermint/PubKeySecp256k1" otherwise the verification will fail @@ -30,7 +38,7 @@ pub struct PubKey { // Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub struct SignedPermit { /// ignored @@ -47,38 +55,87 @@ pub struct SignedPermit { pub sequence: Uint128, } +impl SignedPermit { + pub fn from_params(params: PermitParams) -> Self { + Self { + account_number: Uint128::zero(), + chain_id: params.chain_id.clone(), + fee: Fee::new(), + memo: String::new(), + msgs: vec![PermitMsg::from_content(PermitContent::from_params(params))], + sequence: Uint128::zero(), + } + } +} + // Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub struct Fee { pub amount: Vec, pub gas: Uint128, } +impl Fee { + pub fn new() -> Self { + Self { + amount: vec![Coin::new()], + gas: Uint128(1), + } + } +} + // Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub struct Coin { pub amount: Uint128, pub denom: String, } +impl Coin { + pub fn new() -> Self { + Self { + amount: Uint128::zero(), + denom: "uscrt".to_string(), + } + } +} + // Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub struct PermitMsg { pub r#type: String, pub value: PermitContent, } +impl PermitMsg { + pub fn from_content(content: PermitContent) -> Self { + Self { + r#type: "query_permit".to_string(), + value: content, + } + } +} + // Note: The order of fields in this struct is important for the permit signature verification! #[remain::sorted] -#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] pub struct PermitContent { pub allowed_tokens: Vec, pub permit_name: String, } + +impl PermitContent { + pub fn from_params(params: PermitParams) -> Self { + Self { + allowed_tokens: params.allowed_tokens, + permit_name: params.permit_name, + } + } +} diff --git a/src/state.rs b/src/state.rs index 75c63d9..a5ae9ee 100644 --- a/src/state.rs +++ b/src/state.rs @@ -305,7 +305,7 @@ impl RevokedPemits { pub fn is_permit_revoked( storgae: &dyn Storage, account: &HumanAddr, - permit_name: &String, + permit_name: &str, ) -> bool { let storage_key = account.to_string() + permit_name; @@ -315,7 +315,7 @@ impl RevokedPemits { } } - pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &String) { + pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &str) { let storage_key = account.to_string() + permit_name; storage.set(storage_key.as_bytes(), &[]) From c3071e908616d8fb168a86daf67f925d2635e753 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 11:52:54 +0300 Subject: [PATCH 15/39] Fix permit for query_allowance The query should validate permit from owner or spender, was only owner until now. --- src/contract.rs | 11 ++++++++++- src/msg.rs | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index b98a55f..746f02d 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -338,7 +338,16 @@ fn query_with_permit( QueryWithPermit::TransactionHistory { page, page_size } => { query_transactions(&deps, &account, page.unwrap_or(0), page_size) } - QueryWithPermit::Allowance { spender } => query_allowance(deps, account, spender), + QueryWithPermit::Allowance { owner, spender } => { + if owner == account || spender == account { + query_allowance(deps, owner, spender) + } else { + return Err(StdError::generic_err(format!( + "Cannot query allowance. Requires permit for either owner {:?} or spender {:?}, got permit for {:?}", + owner, spender, account + ))); + } + } } } diff --git a/src/msg.rs b/src/msg.rs index 0a06721..fb4a3a8 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -375,10 +375,19 @@ impl QueryMsg { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum QueryWithPermit { - Allowance { spender: HumanAddr }, + Allowance { + owner: HumanAddr, + spender: HumanAddr, + }, Balance {}, - TransferHistory { page: Option, page_size: u32 }, - TransactionHistory { page: Option, page_size: u32 }, + TransferHistory { + page: Option, + page_size: u32, + }, + TransactionHistory { + page: Option, + page_size: u32, + }, } #[derive(Serialize, Deserialize, JsonSchema, Debug)] From d986d2ebaf7fc52f08135b8cb6d8d3b5681f14ad Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 12:08:06 +0300 Subject: [PATCH 16/39] Rename struct SignedPermit -> PermitParams --- src/permit.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/permit.rs b/src/permit.rs index a11a707..fa9e4c2 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -8,7 +8,7 @@ use cosmwasm_std::{Binary, HumanAddr, Uint128}; #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Permit { - pub signed: SignedPermit, + pub signed: PermitParams, pub signature: PermitSignature, } @@ -32,7 +32,7 @@ pub struct PubKey { #[remain::sorted] #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] -pub struct SignedPermit { +pub struct PermitParams { /// ignored pub account_number: Uint128, /// ignored, no Env in query From 8a8d419a260ee0db26d8c9c974d27d617702ca16 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 12:21:28 +0300 Subject: [PATCH 17/39] A small refactor --- src/state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/state.rs b/src/state.rs index 75c63d9..a5ae9ee 100644 --- a/src/state.rs +++ b/src/state.rs @@ -305,7 +305,7 @@ impl RevokedPemits { pub fn is_permit_revoked( storgae: &dyn Storage, account: &HumanAddr, - permit_name: &String, + permit_name: &str, ) -> bool { let storage_key = account.to_string() + permit_name; @@ -315,7 +315,7 @@ impl RevokedPemits { } } - pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &String) { + pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &str) { let storage_key = account.to_string() + permit_name; storage.set(storage_key.as_bytes(), &[]) From 2323bf4596fb643c84e6ed9723ac3de1ababb87d Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 12:34:23 +0300 Subject: [PATCH 18/39] Code comment rephrase --- src/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/contract.rs b/src/contract.rs index 746f02d..f87d27d 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -329,7 +329,7 @@ fn query_with_permit( )) })?; - // We're verified! We can now execute the query + // Permit validated! We can now execute the query. match query { QueryWithPermit::Balance {} => query_balance(&deps, &account), QueryWithPermit::TransferHistory { page, page_size } => { From e14e85752fb5acd4598b5d9ea972bfef2934257d Mon Sep 17 00:00:00 2001 From: Reuven Podmazo Date: Wed, 29 Sep 2021 13:01:21 +0300 Subject: [PATCH 19/39] cargo schema --- schema/handle_answer.json | 19 +++ schema/handle_msg.json | 43 ++++++ schema/query_msg.json | 295 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 357 insertions(+) diff --git a/schema/handle_answer.json b/schema/handle_answer.json index ffd8a10..675fdfa 100644 --- a/schema/handle_answer.json +++ b/schema/handle_answer.json @@ -492,6 +492,25 @@ } } } + }, + { + "type": "object", + "required": [ + "revoke_pemit" + ], + "properties": { + "revoke_pemit": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "status": { + "$ref": "#/definitions/ResponseStatus" + } + } + } + } } ], "definitions": { diff --git a/schema/handle_msg.json b/schema/handle_msg.json index 41d5b1b..10ba231 100644 --- a/schema/handle_msg.json +++ b/schema/handle_msg.json @@ -127,6 +127,12 @@ }, "recipient": { "$ref": "#/definitions/HumanAddr" + }, + "recipient_code_hash": { + "type": [ + "string", + "null" + ] } } } @@ -451,6 +457,12 @@ }, "recipient": { "$ref": "#/definitions/HumanAddr" + }, + "recipient_code_hash": { + "type": [ + "string", + "null" + ] } } } @@ -771,6 +783,25 @@ } } } + }, + { + "type": "object", + "required": [ + "revoke_permit" + ], + "properties": { + "revoke_permit": { + "type": "object", + "required": [ + "permit_name" + ], + "properties": { + "permit_name": { + "type": "string" + } + } + } + } } ], "definitions": { @@ -859,6 +890,12 @@ }, "recipient": { "$ref": "#/definitions/HumanAddr" + }, + "recipient_code_hash": { + "type": [ + "string", + "null" + ] } } }, @@ -894,6 +931,12 @@ }, "recipient": { "$ref": "#/definitions/HumanAddr" + }, + "recipient_code_hash": { + "type": [ + "string", + "null" + ] } } }, diff --git a/schema/query_msg.json b/schema/query_msg.json index b16caf7..fdb92df 100644 --- a/schema/query_msg.json +++ b/schema/query_msg.json @@ -180,11 +180,306 @@ "type": "object" } } + }, + { + "type": "object", + "required": [ + "with_permit" + ], + "properties": { + "with_permit": { + "type": "object", + "required": [ + "permit", + "query" + ], + "properties": { + "permit": { + "$ref": "#/definitions/Permit" + }, + "query": { + "$ref": "#/definitions/QueryWithPermit" + } + } + } + } } ], "definitions": { + "Binary": { + "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec", + "type": "string" + }, + "Coin": { + "type": "object", + "required": [ + "amount", + "denom" + ], + "properties": { + "amount": { + "$ref": "#/definitions/Uint128" + }, + "denom": { + "type": "string" + } + } + }, + "Fee": { + "type": "object", + "required": [ + "amount", + "gas" + ], + "properties": { + "amount": { + "type": "array", + "items": { + "$ref": "#/definitions/Coin" + } + }, + "gas": { + "$ref": "#/definitions/Uint128" + } + } + }, "HumanAddr": { "type": "string" + }, + "Permit": { + "type": "object", + "required": [ + "signature", + "signed" + ], + "properties": { + "signature": { + "$ref": "#/definitions/PermitSignature" + }, + "signed": { + "$ref": "#/definitions/PermitParams" + } + } + }, + "PermitContent": { + "type": "object", + "required": [ + "allowed_tokens", + "permit_name" + ], + "properties": { + "allowed_tokens": { + "type": "array", + "items": { + "$ref": "#/definitions/HumanAddr" + } + }, + "permit_name": { + "type": "string" + } + } + }, + "PermitMsg": { + "type": "object", + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "type": "string" + }, + "value": { + "$ref": "#/definitions/PermitContent" + } + } + }, + "PermitParams": { + "type": "object", + "required": [ + "account_number", + "chain_id", + "fee", + "memo", + "msgs", + "sequence" + ], + "properties": { + "account_number": { + "description": "ignored", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + }, + "chain_id": { + "description": "ignored, no Env in query", + "type": "string" + }, + "fee": { + "description": "ignored", + "allOf": [ + { + "$ref": "#/definitions/Fee" + } + ] + }, + "memo": { + "description": "ignored", + "type": "string" + }, + "msgs": { + "description": "the signed message", + "type": "array", + "items": { + "$ref": "#/definitions/PermitMsg" + } + }, + "sequence": { + "description": "ignored", + "allOf": [ + { + "$ref": "#/definitions/Uint128" + } + ] + } + } + }, + "PermitSignature": { + "type": "object", + "required": [ + "pub_key", + "signature" + ], + "properties": { + "pub_key": { + "$ref": "#/definitions/PubKey" + }, + "signature": { + "$ref": "#/definitions/Binary" + } + } + }, + "PubKey": { + "type": "object", + "required": [ + "type", + "value" + ], + "properties": { + "type": { + "description": "ignored, but must be \"tendermint/PubKeySecp256k1\" otherwise the verification will fail", + "type": "string" + }, + "value": { + "description": "Secp256k1 PubKey", + "allOf": [ + { + "$ref": "#/definitions/Binary" + } + ] + } + } + }, + "QueryWithPermit": { + "anyOf": [ + { + "type": "object", + "required": [ + "allowance" + ], + "properties": { + "allowance": { + "type": "object", + "required": [ + "owner", + "spender" + ], + "properties": { + "owner": { + "$ref": "#/definitions/HumanAddr" + }, + "spender": { + "$ref": "#/definitions/HumanAddr" + } + } + } + } + }, + { + "type": "object", + "required": [ + "balance" + ], + "properties": { + "balance": { + "type": "object" + } + } + }, + { + "type": "object", + "required": [ + "transfer_history" + ], + "properties": { + "transfer_history": { + "type": "object", + "required": [ + "page_size" + ], + "properties": { + "page": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "page_size": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + } + }, + { + "type": "object", + "required": [ + "transaction_history" + ], + "properties": { + "transaction_history": { + "type": "object", + "required": [ + "page_size" + ], + "properties": { + "page": { + "type": [ + "integer", + "null" + ], + "format": "uint32", + "minimum": 0.0 + }, + "page_size": { + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + } + } + } + ] + }, + "Uint128": { + "type": "string" } } } From 3844f6cfd6bf29200b8fbbb590dddb8e7a5e2056 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 13:07:51 +0300 Subject: [PATCH 20/39] Simplify return logic of is_permit_revoked() --- src/state.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/state.rs b/src/state.rs index a5ae9ee..b240d7a 100644 --- a/src/state.rs +++ b/src/state.rs @@ -309,10 +309,7 @@ impl RevokedPemits { ) -> bool { let storage_key = account.to_string() + permit_name; - match storgae.get(storage_key.as_bytes()) { - Some(_) => true, - None => false, - } + storgae.get(storage_key.as_bytes()).is_some() } pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &str) { From 37b191f01a09b71d3d257ff00f02a30e7dbf2672 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 13:51:15 +0300 Subject: [PATCH 21/39] Fix merge conflict --- src/permit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/permit.rs b/src/permit.rs index ff1809c..5f10387 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -40,7 +40,7 @@ pub struct PubKey { #[remain::sorted] #[derive(Serialize, Clone, Debug, PartialEq)] #[serde(rename_all = "snake_case")] -pub struct PermitParams { +pub struct SignedPermit { /// ignored pub account_number: Uint128, /// ignored, no Env in query From 1ce2de6946e5bbb0a3aef4be796f589b1ca38528 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 13:51:35 +0300 Subject: [PATCH 22/39] Rename query_with_permit() -> permit_queries() --- src/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index 2f19da3..be056ef 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -250,12 +250,12 @@ pub fn query(deps: &Extern, msg: QueryM QueryMsg::ContractStatus {} => query_contract_status(&deps.storage), QueryMsg::ExchangeRate {} => query_exchange_rate(&deps.storage), QueryMsg::Minters { .. } => query_minters(deps), - QueryMsg::WithPermit { permit, query } => query_with_permit(deps, permit, query), + QueryMsg::WithPermit { permit, query } => permit_queries(deps, permit, query), _ => viewing_keys_queries(deps, msg), } } -fn query_with_permit( +fn permit_queries( deps: &Extern, permit: Permit, query: QueryWithPermit, From 716ee8a51fec617f9b354aaee63049f2ff0df6ca Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 15:31:59 +0300 Subject: [PATCH 23/39] Rename permit.signed -> permit.params --- src/contract.rs | 8 ++++---- src/permit.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index be056ef..0c856d5 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -265,10 +265,10 @@ fn permit_queries( .constants()? .contract_address; - if !permit.signed.allowed_tokens.contains(&token_address) { + if !permit.params.allowed_tokens.contains(&token_address) { return Err(StdError::generic_err(format!( "Permit doesn't apply to token {:?}, allowed tokens: {:?}", - token_address, permit.signed.allowed_tokens + token_address, permit.params.allowed_tokens ))); } @@ -277,7 +277,7 @@ fn permit_queries( let account = deps.api.human_address(&pubkey_to_account(&pubkey))?; // Validate permit_name - let permit_name = &permit.signed.permit_name; + let permit_name = &permit.params.permit_name; let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, permit_name); if is_permit_revoked { return Err(StdError::generic_err(format!( @@ -287,7 +287,7 @@ fn permit_queries( } // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 - let signed_bytes = to_binary(&SignedPermit::from_params(permit.signed))?; + let signed_bytes = to_binary(&SignedPermit::from_params(permit.params))?; let signed_bytes_hash = Sha256::digest(signed_bytes.as_slice()); let secp256k1_msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { diff --git a/src/permit.rs b/src/permit.rs index 5f10387..51c2d78 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -8,7 +8,7 @@ use cosmwasm_std::{Binary, HumanAddr, Uint128}; #[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub struct Permit { - pub signed: PermitParams, + pub params: PermitParams, pub signature: PermitSignature, } From 7af1d057ac602d9bc5c1f9f86e3d4f0629613402 Mon Sep 17 00:00:00 2001 From: Reuven Podmazo Date: Wed, 29 Sep 2021 16:27:36 +0300 Subject: [PATCH 24/39] cargo schema --- schema/query_msg.json | 115 +++--------------------------------------- 1 file changed, 8 insertions(+), 107 deletions(-) diff --git a/schema/query_msg.json b/schema/query_msg.json index fdb92df..e8e4bc8 100644 --- a/schema/query_msg.json +++ b/schema/query_msg.json @@ -210,61 +210,29 @@ "description": "Binary is a wrapper around Vec to add base64 de/serialization with serde. It also adds some helper methods to help encode inline.\n\nThis is only needed as serde-json-{core,wasm} has a horrible encoding for Vec", "type": "string" }, - "Coin": { - "type": "object", - "required": [ - "amount", - "denom" - ], - "properties": { - "amount": { - "$ref": "#/definitions/Uint128" - }, - "denom": { - "type": "string" - } - } - }, - "Fee": { - "type": "object", - "required": [ - "amount", - "gas" - ], - "properties": { - "amount": { - "type": "array", - "items": { - "$ref": "#/definitions/Coin" - } - }, - "gas": { - "$ref": "#/definitions/Uint128" - } - } - }, "HumanAddr": { "type": "string" }, "Permit": { "type": "object", "required": [ - "signature", - "signed" + "params", + "signature" ], "properties": { + "params": { + "$ref": "#/definitions/PermitParams" + }, "signature": { "$ref": "#/definitions/PermitSignature" - }, - "signed": { - "$ref": "#/definitions/PermitParams" } } }, - "PermitContent": { + "PermitParams": { "type": "object", "required": [ "allowed_tokens", + "chain_id", "permit_name" ], "properties": { @@ -274,75 +242,11 @@ "$ref": "#/definitions/HumanAddr" } }, - "permit_name": { - "type": "string" - } - } - }, - "PermitMsg": { - "type": "object", - "required": [ - "type", - "value" - ], - "properties": { - "type": { - "type": "string" - }, - "value": { - "$ref": "#/definitions/PermitContent" - } - } - }, - "PermitParams": { - "type": "object", - "required": [ - "account_number", - "chain_id", - "fee", - "memo", - "msgs", - "sequence" - ], - "properties": { - "account_number": { - "description": "ignored", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] - }, "chain_id": { - "description": "ignored, no Env in query", "type": "string" }, - "fee": { - "description": "ignored", - "allOf": [ - { - "$ref": "#/definitions/Fee" - } - ] - }, - "memo": { - "description": "ignored", + "permit_name": { "type": "string" - }, - "msgs": { - "description": "the signed message", - "type": "array", - "items": { - "$ref": "#/definitions/PermitMsg" - } - }, - "sequence": { - "description": "ignored", - "allOf": [ - { - "$ref": "#/definitions/Uint128" - } - ] } } }, @@ -477,9 +381,6 @@ } } ] - }, - "Uint128": { - "type": "string" } } } From 736a0d9b8fa4059cee4d2754be03e623df6a505e Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 29 Sep 2021 22:53:53 +0300 Subject: [PATCH 25/39] Query permit permissions --- src/contract.rs | 42 ++++++++++++++++++++++++++++++++++++------ src/permit.rs | 19 +++++++++++++++---- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index 0c856d5..2e3b38b 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -15,7 +15,7 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::{Permit, SignedPermit}; +use crate::permit::{Permission, Permit, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ @@ -287,7 +287,7 @@ fn permit_queries( } // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 - let signed_bytes = to_binary(&SignedPermit::from_params(permit.params))?; + let signed_bytes = to_binary(&SignedPermit::from_params(&permit.params))?; let signed_bytes_hash = Sha256::digest(signed_bytes.as_slice()); let secp256k1_msg = secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { @@ -315,22 +315,52 @@ fn permit_queries( // Permit validated! We can now execute the query. match query { - QueryWithPermit::Balance {} => query_balance(deps, &account), + QueryWithPermit::Balance {} => { + if !permit.params.permissions.contains(&Permission::Balance) { + return Err(StdError::generic_err(format!( + "No permission to query balance, got permissions {:?}", + permit.params.permissions + ))); + } + + query_balance(deps, &account) + } QueryWithPermit::TransferHistory { page, page_size } => { + if !permit.params.permissions.contains(&Permission::History) { + return Err(StdError::generic_err(format!( + "No permission to query history, got permissions {:?}", + permit.params.permissions + ))); + } + query_transfers(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::TransactionHistory { page, page_size } => { + if !permit.params.permissions.contains(&Permission::History) { + return Err(StdError::generic_err(format!( + "No permission to query history, got permissions {:?}", + permit.params.permissions + ))); + } + query_transactions(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::Allowance { owner, spender } => { - if owner == account || spender == account { - query_allowance(deps, owner, spender) - } else { + if !permit.params.permissions.contains(&Permission::Allowance) { + return Err(StdError::generic_err(format!( + "No permission to query allowance, got permissions {:?}", + permit.params.permissions + ))); + } + + if account != owner && account != spender { return Err(StdError::generic_err(format!( "Cannot query allowance. Requires permit for either owner {:?} or spender {:?}, got permit for {:?}", owner, spender, account ))); } + + query_allowance(deps, owner, spender) } } } diff --git a/src/permit.rs b/src/permit.rs index 51c2d78..0c22257 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -18,6 +18,7 @@ pub struct PermitParams { pub allowed_tokens: Vec, pub permit_name: String, pub chain_id: String, + pub permissions: Vec, } #[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] @@ -56,7 +57,7 @@ pub struct SignedPermit { } impl SignedPermit { - pub fn from_params(params: PermitParams) -> Self { + pub fn from_params(params: &PermitParams) -> Self { Self { account_number: Uint128::zero(), chain_id: params.chain_id.clone(), @@ -128,14 +129,24 @@ impl PermitMsg { #[serde(rename_all = "snake_case")] pub struct PermitContent { pub allowed_tokens: Vec, + pub permissions: Vec, pub permit_name: String, } impl PermitContent { - pub fn from_params(params: PermitParams) -> Self { + pub fn from_params(params: &PermitParams) -> Self { Self { - allowed_tokens: params.allowed_tokens, - permit_name: params.permit_name, + allowed_tokens: params.allowed_tokens.clone(), + permit_name: params.permit_name.clone(), + permissions: params.permissions.clone(), } } } + +#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum Permission { + Balance, + History, + Allowance, +} From 128e3f7641709cea18f30f239f3412e7b204d7ae Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 4 Oct 2021 20:06:58 +0300 Subject: [PATCH 26/39] Add prefix for RevokedPemits storage keys --- src/state.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/state.rs b/src/state.rs index b240d7a..4cf4c84 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,7 +28,7 @@ pub const PREFIX_ALLOWANCES: &[u8] = b"allowances"; pub const PREFIX_VIEW_KEY: &[u8] = b"viewingkey"; pub const PREFIX_RECEIVERS: &[u8] = b"receivers"; -pub const PREFIX_REVOKED_PERMITS: &[u8] = b"revoked_permits"; +pub const PREFIX_REVOKED_PERMITS: &str = "revoked_permits"; // Config @@ -307,13 +307,13 @@ impl RevokedPemits { account: &HumanAddr, permit_name: &str, ) -> bool { - let storage_key = account.to_string() + permit_name; + let storage_key = PREFIX_REVOKED_PERMITS.to_string() + &account.to_string() + permit_name; storgae.get(storage_key.as_bytes()).is_some() } pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &str) { - let storage_key = account.to_string() + permit_name; + let storage_key = PREFIX_REVOKED_PERMITS.to_string() + &account.to_string() + permit_name; storage.set(storage_key.as_bytes(), &[]) } From c9b53b505f4725774ea96be4f2312e00cfa2a84c Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Fri, 8 Oct 2021 11:38:41 +0300 Subject: [PATCH 27/39] Test permits for wrong token --- Makefile | 2 +- src/contract.rs | 11 +++- src/permit.rs | 2 +- tests/integration.sh | 128 ++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 130 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 9ef335b..ac62518 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,7 @@ start-server: # CTRL+C to stop docker run -it --rm \ -p 26657:26657 -p 26656:26656 -p 1337:1337 \ -v $$(pwd):/root/code \ - --name secretdev enigmampc/secret-network-sw-dev:v1.0.4-4 + --name secretdev enigmampc/secret-network-sw-dev:v1.0.4-5 .PHONY: schema schema: diff --git a/src/contract.rs b/src/contract.rs index 2e3b38b..b19beed 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -268,7 +268,13 @@ fn permit_queries( if !permit.params.allowed_tokens.contains(&token_address) { return Err(StdError::generic_err(format!( "Permit doesn't apply to token {:?}, allowed tokens: {:?}", - token_address, permit.params.allowed_tokens + token_address.as_str(), + permit + .params + .allowed_tokens + .iter() + .map(|a| a.as_str()) + .collect::>() ))); } @@ -282,7 +288,8 @@ fn permit_queries( if is_permit_revoked { return Err(StdError::generic_err(format!( "Permit '{:?}' was revoked by account {:?}", - permit_name, account + permit_name, + account.as_str() ))); } diff --git a/src/permit.rs b/src/permit.rs index 0c22257..5238617 100644 --- a/src/permit.rs +++ b/src/permit.rs @@ -146,7 +146,7 @@ impl PermitContent { #[derive(Deserialize, Serialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum Permission { + Allowance, Balance, History, - Allowance, } diff --git a/tests/integration.sh b/tests/integration.sh index 5291e8e..44e939f 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -526,6 +526,115 @@ function test_viewing_key() { fi } +function test_permit() { + set -e + local contract_addr="$1" + + log_test_header + + # common variables + local result + local tx_hash + + # query balance. should fail because of wrong contract. + secretcli keys delete banana -f || true + secretcli keys add banana + local wrong_contract=$(secretcli keys show -a banana) + + local wrong_permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error="ERROR: query result: encrypted: Permit doesn't apply to token \"$contract_addr\", allowed tokens: [\"$wrong_contract\"]" + for key in "${KEY[@]}"; do + log "querying balance for \"$key\" with wrong permit for that contract" + wrong_permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]},"signature":'"$wrong_permit"'}}}' + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" + done + + # Create permits + local create_viewing_key_message='{"create_viewing_key":{"entropy":"MyPassword123"}}' + local viewing_key_response + for key in "${KEY[@]}"; do + log "creating viewing key for \"$key\"" + tx_hash="$(compute_execute "$contract_addr" "$create_viewing_key_message" ${FROM[$key]} --gas 1400000)" + viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" "waiting for viewing key for \"$key\" to be created")" + VK[$key]="$(jq -er '.create_viewing_key.key' <<<"$viewing_key_response")" + log "viewing key for \"$key\" set to ${VK[$key]}" + if [[ "${VK[$key]}" =~ ^api_key_ ]]; then + log "viewing key \"$key\" seems valid" + else + log 'viewing key is invalid' + return 1 + fi + done + + # Check that all viewing keys are different despite using the same entropy + assert_ne "${VK[a]}" "${VK[b]}" + assert_ne "${VK[b]}" "${VK[c]}" + assert_ne "${VK[c]}" "${VK[d]}" + + # query balance. Should succeed. + local permit_query + for key in "${KEY[@]}"; do + permit_query='{"balance":{"address":"'"${ADDRESS[$key]}"'","key":"'"${VK[$key]}"'"}}' + log "querying balance for \"$key\" with correct viewing key" + result="$(compute_query "$contract_addr" "$permit_query")" + if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then + log "Balance query returned unexpected response: ${result@Q}" + return 1 + fi + done + + # Change viewing keys + local vk2_a + + log 'creating new viewing key for "a"' + tx_hash="$(compute_execute "$contract_addr" "$create_viewing_key_message" ${FROM[a]} --gas 1400000)" + viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" 'waiting for viewing key for "a" to be created')" + vk2_a="$(jq -er '.create_viewing_key.key' <<<"$viewing_key_response")" + log "viewing key for \"a\" set to $vk2_a" + assert_ne "${VK[a]}" "$vk2_a" + + # query balance with old keys. Should fail. + log 'querying balance for "a" with old viewing key' + local permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"${VK[a]}"'"}}' + result="$(compute_query "$contract_addr" "$permit_query_a")" + assert_eq "$result" "$expected_error" + + # query balance with new keys. Should succeed. + log 'querying balance for "a" with new viewing key' + permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"$vk2_a"'"}}' + result="$(compute_query "$contract_addr" "$permit_query_a")" + if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then + log "Balance query returned unexpected response: ${result@Q}" + return 1 + fi + + # Set the vk for "a" to the original vk + log 'setting the viewing key for "a" back to the first one' + local set_viewing_key_message='{"set_viewing_key":{"key":"'"${VK[a]}"'"}}' + tx_hash="$(compute_execute "$contract_addr" "$set_viewing_key_message" ${FROM[a]} --gas 1400000)" + viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" 'waiting for viewing key for "a" to be set')" + assert_eq "$viewing_key_response" "$(pad_space '{"set_viewing_key":{"status":"success"}}')" + + # try to use the new key - should fail + log 'querying balance for "a" with new viewing key' + permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"$vk2_a"'"}}' + result="$(compute_query "$contract_addr" "$permit_query_a")" + assert_eq "$result" "$expected_error" + + # try to use the old key - should succeed + log 'querying balance for "a" with old viewing key' + permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"${VK[a]}"'"}}' + result="$(compute_query "$contract_addr" "$permit_query_a")" + if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then + log "Balance query returned unexpected response: ${result@Q}" + return 1 + fi +} + function test_deposit() { set -e local contract_addr="$1" @@ -1454,15 +1563,16 @@ function main() { log "contract address: $contract_addr" # This first test also sets the `VK[*]` global variables that are used in the other tests - test_viewing_key "$contract_addr" - test_deposit "$contract_addr" - test_transfer "$contract_addr" - test_send "$contract_addr" register - test_send "$contract_addr" skip-register - test_burn "$contract_addr" - test_transfer_from "$contract_addr" - test_send_from "$contract_addr" register - test_send_from "$contract_addr" skip-register + # test_viewing_key "$contract_addr" + test_permit "$contract_addr" + # test_deposit "$contract_addr" + # test_transfer "$contract_addr" + # test_send "$contract_addr" register + # test_send "$contract_addr" skip-register + # test_burn "$contract_addr" + # test_transfer_from "$contract_addr" + # test_send_from "$contract_addr" register + # test_send_from "$contract_addr" skip-register log 'Tests completed successfully' From 59d61c7160c6ac39d645cc4d3b43e4f98f537cde Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Oct 2021 23:07:40 +0300 Subject: [PATCH 28/39] Permit: make errors more readable for humans --- src/contract.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/contract.rs b/src/contract.rs index b19beed..9bf41f1 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -287,7 +287,7 @@ fn permit_queries( let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, permit_name); if is_permit_revoked { return Err(StdError::generic_err(format!( - "Permit '{:?}' was revoked by account {:?}", + "Permit {:?} was revoked by account {:?}", permit_name, account.as_str() ))); @@ -363,7 +363,7 @@ fn permit_queries( if account != owner && account != spender { return Err(StdError::generic_err(format!( "Cannot query allowance. Requires permit for either owner {:?} or spender {:?}, got permit for {:?}", - owner, spender, account + owner.as_str(), spender.as_str(), account.as_str() ))); } From 7a27a75839f2e21042602987d24d5e026c1c6015 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Oct 2021 23:20:34 +0300 Subject: [PATCH 29/39] Permits: test every failure scenario --- tests/integration.sh | 158 +++++++++++++++++++++++-------------------- 1 file changed, 84 insertions(+), 74 deletions(-) diff --git a/tests/integration.sh b/tests/integration.sh index 44e939f..7ba60a1 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -536,103 +536,113 @@ function test_permit() { local result local tx_hash - # query balance. should fail because of wrong contract. + # fail due to token not in permit secretcli keys delete banana -f || true secretcli keys add banana local wrong_contract=$(secretcli keys show -a banana) - local wrong_permit - wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit + permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' local permit_query local expected_error="ERROR: query result: encrypted: Permit doesn't apply to token \"$contract_addr\", allowed tokens: [\"$wrong_contract\"]" for key in "${KEY[@]}"; do - log "querying balance for \"$key\" with wrong permit for that contract" - wrong_permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") - permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]},"signature":'"$wrong_permit"'}}}' + log "permit querying balance for \"$key\" with wrong permit for that contract" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$wrong_contract"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" assert_eq "$result" "$expected_error" done - # Create permits - local create_viewing_key_message='{"create_viewing_key":{"entropy":"MyPassword123"}}' - local viewing_key_response + # fail due to revoked permit + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"to_be_revoked","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error for key in "${KEY[@]}"; do - log "creating viewing key for \"$key\"" - tx_hash="$(compute_execute "$contract_addr" "$create_viewing_key_message" ${FROM[$key]} --gas 1400000)" - viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" "waiting for viewing key for \"$key\" to be created")" - VK[$key]="$(jq -er '.create_viewing_key.key' <<<"$viewing_key_response")" - log "viewing key for \"$key\" set to ${VK[$key]}" - if [[ "${VK[$key]}" =~ ^api_key_ ]]; then - log "viewing key \"$key\" seems valid" - else - log 'viewing key is invalid' - return 1 - fi - done + log "permit querying balance for \"$key\" with a revoked permit" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + tx_hash="$(compute_execute "$contract_addr" '{"revoke_permit":{"permit_name":"to_be_revoked"}}' ${FROM[$key]} --gas 250000)" + wait_for_compute_tx "$tx_hash" "waiting for revoke_permit from \"$key\" to process" - # Check that all viewing keys are different despite using the same entropy - assert_ne "${VK[a]}" "${VK[b]}" - assert_ne "${VK[b]}" "${VK[c]}" - assert_ne "${VK[c]}" "${VK[d]}" + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"to_be_revoked","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: Permit \"to_be_revoked\" was revoked by account \"${ADDRESS[$key]}\"" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" + done - # query balance. Should succeed. + # fail due to params not matching params that were signed on + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' local permit_query + local expected_error for key in "${KEY[@]}"; do - permit_query='{"balance":{"address":"'"${ADDRESS[$key]}"'","key":"'"${VK[$key]}"'"}}' - log "querying balance for \"$key\" with correct viewing key" - result="$(compute_query "$contract_addr" "$permit_query")" - if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then - log "Balance query returned unexpected response: ${result@Q}" - return 1 - fi + log "permit querying balance for \"$key\" with params not matching permit" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"not_blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: Failed to verify signatures for the given permit: IncorrectSignature" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" done - # Change viewing keys - local vk2_a - - log 'creating new viewing key for "a"' - tx_hash="$(compute_execute "$contract_addr" "$create_viewing_key_message" ${FROM[a]} --gas 1400000)" - viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" 'waiting for viewing key for "a" to be created')" - vk2_a="$(jq -er '.create_viewing_key.key' <<<"$viewing_key_response")" - log "viewing key for \"a\" set to $vk2_a" - assert_ne "${VK[a]}" "$vk2_a" + # fail balance query due to no balance permission + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error + for key in "${KEY[@]}"; do + log "permit querying balance for \"$key\" without the right permission" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: No permission to query balance, got permissions [History]" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" + done - # query balance with old keys. Should fail. - log 'querying balance for "a" with old viewing key' - local permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"${VK[a]}"'"}}' - result="$(compute_query "$contract_addr" "$permit_query_a")" - assert_eq "$result" "$expected_error" + # fail history query due to no history permission + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error + for key in "${KEY[@]}"; do + log "permit querying history for \"$key\" without the right permission" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + + permit_query='{"with_permit":{"query":{"transfer_history":{"page_size":10}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: No permission to query history, got permissions [Balance]" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" - # query balance with new keys. Should succeed. - log 'querying balance for "a" with new viewing key' - permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"$vk2_a"'"}}' - result="$(compute_query "$contract_addr" "$permit_query_a")" - if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then - log "Balance query returned unexpected response: ${result@Q}" - return 1 - fi + permit_query='{"with_permit":{"query":{"transaction_history":{"page_size":10}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: No permission to query history, got permissions [Balance]" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" + done - # Set the vk for "a" to the original vk - log 'setting the viewing key for "a" back to the first one' - local set_viewing_key_message='{"set_viewing_key":{"key":"'"${VK[a]}"'"}}' - tx_hash="$(compute_execute "$contract_addr" "$set_viewing_key_message" ${FROM[a]} --gas 1400000)" - viewing_key_response="$(data_of wait_for_compute_tx "$tx_hash" 'waiting for viewing key for "a" to be set')" - assert_eq "$viewing_key_response" "$(pad_space '{"set_viewing_key":{"status":"success"}}')" + # fail allowance query due to no allowance permission + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error + for key in "${KEY[@]}"; do + log "permit querying allowance for \"$key\" without the right permission" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"allowance":{"owner":"'"${ADDRESS[$key]}"'","spender":"'"${ADDRESS[$key]}"'"}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: No permission to query allowance, got permissions [History]" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_error" + done - # try to use the new key - should fail - log 'querying balance for "a" with new viewing key' - permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"$vk2_a"'"}}' - result="$(compute_query "$contract_addr" "$permit_query_a")" + # fail allowance query due to no permit signer not owner or spender + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["allowance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_error + log "permit querying allowance without signer being the owner or spender" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from a") + permit_query='{"with_permit":{"query":{"allowance":{"owner":"'"$wrong_contract"'","spender":"'"$wrong_contract"'"}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["allowance"]},"signature":'"$permit"'}}}' + expected_error="ERROR: query result: encrypted: Cannot query allowance. Requires permit for either owner \"$wrong_contract\" or spender \"$wrong_contract\", got permit for \"${ADDRESS[a]}\"" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" assert_eq "$result" "$expected_error" - - # try to use the old key - should succeed - log 'querying balance for "a" with old viewing key' - permit_query_a='{"balance":{"address":"'"${ADDRESS[a]}"'","key":"'"${VK[a]}"'"}}' - result="$(compute_query "$contract_addr" "$permit_query_a")" - if ! silent jq -e '.balance.amount | tonumber' <<<"$result"; then - log "Balance query returned unexpected response: ${result@Q}" - return 1 - fi } function test_deposit() { From 0384401b311bc3eb0f6ff92101d3bf1289dce9c9 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Oct 2021 23:23:57 +0300 Subject: [PATCH 30/39] Permit: test query balance --- tests/integration.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/integration.sh b/tests/integration.sh index 7ba60a1..61177dc 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -643,6 +643,20 @@ function test_permit() { expected_error="ERROR: query result: encrypted: Cannot query allowance. Requires permit for either owner \"$wrong_contract\" or spender \"$wrong_contract\", got permit for \"${ADDRESS[a]}\"" result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" assert_eq "$result" "$expected_error" + + # succeed balance query + local permit + wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_output + for key in "${KEY[@]}"; do + log "permit querying balance for \"$key\"" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' + expected_output="{\"balance\":{\"amount\":\"0\"}}" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_output" + done } function test_deposit() { From 60b4c53a2282b23ae74467326b2b86c45ddb676b Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Oct 2021 23:43:20 +0300 Subject: [PATCH 31/39] Permit: test query history & allowance --- tests/integration.sh | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/tests/integration.sh b/tests/integration.sh index 61177dc..ace17ee 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -646,17 +646,55 @@ function test_permit() { # succeed balance query local permit - wrong_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local good_permit + good_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' local permit_query local expected_output for key in "${KEY[@]}"; do log "permit querying balance for \"$key\"" - permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$wrong_permit"') --from '$key'") + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$good_permit"') --from '$key'") permit_query='{"with_permit":{"query":{"balance":{}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["balance"]},"signature":'"$permit"'}}}' expected_output="{\"balance\":{\"amount\":\"0\"}}" result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" assert_eq "$result" "$expected_output" done + + # succeed history queries + local permit + local good_permit + good_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_output + for key in "${KEY[@]}"; do + log "permit querying history for \"$key\"" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$good_permit"') --from '$key'") + + permit_query='{"with_permit":{"query":{"transfer_history":{"page_size":10}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]},"signature":'"$permit"'}}}' + expected_output="{\"transfer_history\":{\"txs\":[],\"total\":0}}" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_output" + + permit_query='{"with_permit":{"query":{"transaction_history":{"page_size":10}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["history"]},"signature":'"$permit"'}}}' + expected_output="{\"transaction_history\":{\"txs\":[],\"total\":0}}" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_output" + done + + # succeed allowance query + local permit + local good_permit + good_permit='{"account_number":"0","sequence":"0","chain_id":"blabla","msgs":[{"type":"query_permit","value":{"permit_name":"test","allowed_tokens":["'"$contract_addr"'"],"permissions":["allowance"]}}],"fee":{"amount":[{"denom":"uscrt","amount":"0"}],"gas":"1"},"memo":""}' + local permit_query + local expected_output + for key in "${KEY[@]}"; do + log "permit querying history for \"$key\"" + permit=$(docker exec secretdev bash -c "/usr/bin/secretcli tx sign-doc <(echo '"$good_permit"') --from '$key'") + + permit_query='{"with_permit":{"query":{"allowance":{"owner":"'"${ADDRESS[$key]}"'","spender":"'"${ADDRESS[$key]}"'"}},"permit":{"params":{"permit_name":"test","chain_id":"blabla","allowed_tokens":["'"$contract_addr"'"],"permissions":["allowance"]},"signature":'"$permit"'}}}' + expected_output="{\"allowance\":{\"spender\":\"${ADDRESS[$key]}\",\"owner\":\"${ADDRESS[$key]}\",\"allowance\":\"0\",\"expiration\":null}}" + result="$(compute_query "$contract_addr" "$permit_query" 2>&1 || true)" + assert_eq "$result" "$expected_output" + done } function test_deposit() { From 8e16bb48c19890f38b47b60d3c6b351fcf7b1df6 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Wed, 13 Oct 2021 23:56:45 +0300 Subject: [PATCH 32/39] Restore all the other tests --- tests/integration.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/integration.sh b/tests/integration.sh index ace17ee..084f383 100755 --- a/tests/integration.sh +++ b/tests/integration.sh @@ -1625,16 +1625,16 @@ function main() { log "contract address: $contract_addr" # This first test also sets the `VK[*]` global variables that are used in the other tests - # test_viewing_key "$contract_addr" + test_viewing_key "$contract_addr" test_permit "$contract_addr" - # test_deposit "$contract_addr" - # test_transfer "$contract_addr" - # test_send "$contract_addr" register - # test_send "$contract_addr" skip-register - # test_burn "$contract_addr" - # test_transfer_from "$contract_addr" - # test_send_from "$contract_addr" register - # test_send_from "$contract_addr" skip-register + test_deposit "$contract_addr" + test_transfer "$contract_addr" + test_send "$contract_addr" register + test_send "$contract_addr" skip-register + test_burn "$contract_addr" + test_transfer_from "$contract_addr" + test_send_from "$contract_addr" register + test_send_from "$contract_addr" skip-register log 'Tests completed successfully' From 0400dcbf3023fc081f88345a06abbcf1ad4ae5bb Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Thu, 14 Oct 2021 18:21:00 +0300 Subject: [PATCH 33/39] Move permit operations to secret-toolkit --- Cargo.lock | 179 ++++++++++++++++++++++++++++++------------------ Cargo.toml | 3 +- src/contract.rs | 67 +----------------- src/lib.rs | 1 - src/msg.rs | 5 +- src/permit.rs | 152 ---------------------------------------- src/state.rs | 22 ------ 7 files changed, 118 insertions(+), 311 deletions(-) delete mode 100644 src/permit.rs diff --git a/Cargo.lock b/Cargo.lock index f56db2d..ffd981e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.14.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" +checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" dependencies = [ "gimli", ] [[package]] name = "adler" -version = "0.2.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "arrayref" @@ -31,11 +31,12 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.55" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" +checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" dependencies = [ "addr2line", + "cc", "cfg-if", "libc", "miniz_oxide", @@ -103,15 +104,15 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "cc" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" [[package]] name = "cfg-if" @@ -151,10 +152,13 @@ dependencies = [ ] [[package]] -name = "cpuid-bool" -version = "0.1.2" +name = "cpufeatures" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" +checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" +dependencies = [ + "libc", +] [[package]] name = "crunchy" @@ -223,15 +227,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.23.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" [[package]] name = "hex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "644f9158b2f133fd50f5fb3242878846d9eb792e445c893805ff0e3824006e35" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hmac" @@ -256,15 +260,15 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "libc" -version = "0.2.81" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "libsecp256k1" @@ -278,15 +282,21 @@ dependencies = [ "hmac-drbg", "rand", "sha2 0.8.2", - "subtle 2.4.0", + "subtle 2.4.1", "typenum", ] +[[package]] +name = "memchr" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" + [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", @@ -294,9 +304,12 @@ dependencies = [ [[package]] name = "object" -version = "0.22.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" +dependencies = [ + "memchr", +] [[package]] name = "opaque-debug" @@ -312,24 +325,24 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" [[package]] name = "proc-macro2" -version = "1.0.24" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" +checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" dependencies = [ "unicode-xid", ] [[package]] name = "quote" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ "proc-macro2", ] @@ -394,9 +407,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.18" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "ryu" @@ -448,9 +461,11 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "secret-toolkit-crypto", + "secret-toolkit-incubator", + "secret-toolkit-permit", "secret-toolkit-serialization", "secret-toolkit-snip20", "secret-toolkit-snip721", @@ -461,19 +476,46 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "cosmwasm-std", "libsecp256k1", "rand_chacha", "rand_core", - "sha2 0.9.2", + "sha2 0.9.8", +] + +[[package]] +name = "secret-toolkit-incubator" +version = "0.1.0" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +dependencies = [ + "cosmwasm-std", + "cosmwasm-storage", + "secret-toolkit-serialization", + "serde", + "siphasher", +] + +[[package]] +name = "secret-toolkit-permit" +version = "0.1.0" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +dependencies = [ + "cosmwasm-std", + "remain", + "ripemd160", + "schemars", + "secp256k1", + "secret-toolkit-utils", + "serde", + "sha2 0.9.8", ] [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "bincode2", "cosmwasm-std", @@ -483,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "cosmwasm-std", "schemars", @@ -494,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "cosmwasm-std", "schemars", @@ -505,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -516,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=v0.1.1-debug-print#41a2eb310b5d1b08ced124a5e3664546bd3b355e" +source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" dependencies = [ "cosmwasm-std", "schemars", @@ -525,27 +567,27 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] [[package]] name = "serde-json-wasm" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7294d94d390f1d2334697c065ea591d7074c676e2d20aa6f1df752fced29823f" +checksum = "120bad73306616e91acd7ceed522ba96032a51cffeef3cc813de7f367df71e37" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ "proc-macro2", "quote", @@ -565,9 +607,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.60" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" dependencies = [ "itoa", "ryu", @@ -588,17 +630,23 @@ dependencies = [ [[package]] name = "sha2" -version = "0.9.2" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7aab86fe2149bad8c507606bdb3f4ef5e7b2380eb92350f56122cca72a42a8" +checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpuid-bool", + "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", ] +[[package]] +name = "siphasher" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533494a8f9b724d33625ab53c6c4800f7cc445895924a8ef649222dcb76e938b" + [[package]] name = "snafu" version = "0.6.10" @@ -633,15 +681,14 @@ dependencies = [ "hex", "rand_chacha", "rand_core", - "remain", "ripemd160", "schemars", "secp256k1", "secret-toolkit", "serde", - "sha2 0.9.2", + "sha2 0.9.8", "snafu", - "subtle 2.4.0", + "subtle 2.4.1", ] [[package]] @@ -652,15 +699,15 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.56" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ "proc-macro2", "quote", @@ -669,18 +716,18 @@ dependencies = [ [[package]] name = "typenum" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "unicode-xid" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "version_check" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" diff --git a/Cargo.toml b/Cargo.toml index b0ae2f9..e114170 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ debug-print = ["cosmwasm-std/debug-print"] [dependencies] cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "v0.1.1-debug-print" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", branch = "token-permits" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } @@ -47,7 +47,6 @@ rand_core = { version = "0.5.1", default-features = false } sha2 = { version = "0.9.1", default-features = false } ripemd160 = "0.9.1" secp256k1 = "0.19.0" -remain = "0.2.2" [dev-dependencies] cosmwasm-schema = { version = "0.9.2" } diff --git a/src/contract.rs b/src/contract.rs index 9bf41f1..46ad61c 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -5,9 +5,6 @@ use cosmwasm_std::{ HandleResponse, HumanAddr, InitResponse, Querier, QueryResult, ReadonlyStorage, StdError, StdResult, Storage, Uint128, }; -use ripemd160::{Digest, Ripemd160}; -use secp256k1::Secp256k1; -use sha2::Sha256; use crate::batch; use crate::msg::QueryWithPermit; @@ -15,18 +12,17 @@ use crate::msg::{ space_pad, ContractStatusLevel, HandleAnswer, HandleMsg, InitMsg, QueryAnswer, QueryMsg, ResponseStatus::Success, }; -use crate::permit::{Permission, Permit, SignedPermit}; use crate::rand::sha_256; use crate::receiver::Snip20ReceiveMsg; use crate::state::{ get_receiver_hash, read_allowance, read_viewing_key, set_receiver_hash, write_allowance, write_viewing_key, Balances, Config, Constants, ReadonlyBalances, ReadonlyConfig, - RevokedPemits, }; use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, }; use crate::viewing_key::{ViewingKey, VIEWING_KEY_SIZE}; +use secret_toolkit::permit::{validate_permit, Permission, Permit, RevokedPemits}; /// We make sure that responses from `handle` are padded to a multiple of this size. pub const RESPONSE_BLOCK_SIZE: usize = 256; @@ -265,60 +261,7 @@ fn permit_queries( .constants()? .contract_address; - if !permit.params.allowed_tokens.contains(&token_address) { - return Err(StdError::generic_err(format!( - "Permit doesn't apply to token {:?}, allowed tokens: {:?}", - token_address.as_str(), - permit - .params - .allowed_tokens - .iter() - .map(|a| a.as_str()) - .collect::>() - ))); - } - - // Derive account from pubkey - let pubkey = permit.signature.pub_key.value; - let account = deps.api.human_address(&pubkey_to_account(&pubkey))?; - - // Validate permit_name - let permit_name = &permit.params.permit_name; - let is_permit_revoked = RevokedPemits::is_permit_revoked(&deps.storage, &account, permit_name); - if is_permit_revoked { - return Err(StdError::generic_err(format!( - "Permit {:?} was revoked by account {:?}", - permit_name, - account.as_str() - ))); - } - - // Validate signature, reference: https://github.com/enigmampc/SecretNetwork/blob/f591ed0cb3af28608df3bf19d6cfb733cca48100/cosmwasm/packages/wasmi-runtime/src/crypto/secp256k1.rs#L49-L82 - let signed_bytes = to_binary(&SignedPermit::from_params(&permit.params))?; - let signed_bytes_hash = Sha256::digest(signed_bytes.as_slice()); - let secp256k1_msg = - secp256k1::Message::from_slice(signed_bytes_hash.as_slice()).map_err(|err| { - StdError::generic_err(format!( - "Failed to create a secp256k1 message from signed_bytes: {:?}", - err - )) - })?; - - let secp256k1_verifier = Secp256k1::verification_only(); - - let secp256k1_signature = secp256k1::Signature::from_compact(&permit.signature.signature.0) - .map_err(|err| StdError::generic_err(format!("Malformed signature: {:?}", err)))?; - let secp256k1_pubkey = secp256k1::PublicKey::from_slice(pubkey.0.as_slice()) - .map_err(|err| StdError::generic_err(format!("Malformed pubkey: {:?}", err)))?; - - secp256k1_verifier - .verify(&secp256k1_msg, &secp256k1_signature, &secp256k1_pubkey) - .map_err(|err| { - StdError::generic_err(format!( - "Failed to verify signatures for the given permit: {:?}", - err - )) - })?; + let account = validate_permit(deps, &permit, token_address)?; // Permit validated! We can now execute the query. match query { @@ -372,12 +315,6 @@ fn permit_queries( } } -fn pubkey_to_account(pubkey: &Binary) -> CanonicalAddr { - let mut hasher = Ripemd160::new(); - hasher.update(Sha256::digest(&pubkey.0)); - CanonicalAddr(Binary(hasher.finalize().to_vec())) -} - pub fn viewing_keys_queries( deps: &Extern, msg: QueryMsg, diff --git a/src/lib.rs b/src/lib.rs index 1b2a7f5..307d2d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,6 @@ mod batch; pub mod contract; pub mod msg; -mod permit; mod rand; pub mod receiver; pub mod state; diff --git a/src/msg.rs b/src/msg.rs index f19fb5b..2f830c4 100644 --- a/src/msg.rs +++ b/src/msg.rs @@ -3,12 +3,11 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; - use crate::batch; -use crate::permit::Permit; use crate::transaction_history::{RichTx, Tx}; use crate::viewing_key::ViewingKey; +use cosmwasm_std::{Binary, HumanAddr, StdError, StdResult, Uint128}; +use secret_toolkit::permit::Permit; #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema)] pub struct InitialBalance { diff --git a/src/permit.rs b/src/permit.rs deleted file mode 100644 index 5238617..0000000 --- a/src/permit.rs +++ /dev/null @@ -1,152 +0,0 @@ -#![allow(clippy::field_reassign_with_default)] // This is triggered in `#[derive(JsonSchema)]` - -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -use cosmwasm_std::{Binary, HumanAddr, Uint128}; - -#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct Permit { - pub params: PermitParams, - pub signature: PermitSignature, -} - -#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct PermitParams { - pub allowed_tokens: Vec, - pub permit_name: String, - pub chain_id: String, - pub permissions: Vec, -} - -#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct PermitSignature { - pub pub_key: PubKey, - pub signature: Binary, -} - -#[derive(Deserialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub struct PubKey { - /// ignored, but must be "tendermint/PubKeySecp256k1" otherwise the verification will fail - pub r#type: String, - /// Secp256k1 PubKey - pub value: Binary, -} - -// Note: The order of fields in this struct is important for the permit signature verification! -#[remain::sorted] -#[derive(Serialize, Clone, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -pub struct SignedPermit { - /// ignored - pub account_number: Uint128, - /// ignored, no Env in query - pub chain_id: String, - /// ignored - pub fee: Fee, - /// ignored - pub memo: String, - /// the signed message - pub msgs: Vec, - /// ignored - pub sequence: Uint128, -} - -impl SignedPermit { - pub fn from_params(params: &PermitParams) -> Self { - Self { - account_number: Uint128::zero(), - chain_id: params.chain_id.clone(), - fee: Fee::new(), - memo: String::new(), - msgs: vec![PermitMsg::from_content(PermitContent::from_params(params))], - sequence: Uint128::zero(), - } - } -} - -// Note: The order of fields in this struct is important for the permit signature verification! -#[remain::sorted] -#[derive(Serialize, Clone, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -pub struct Fee { - pub amount: Vec, - pub gas: Uint128, -} - -impl Fee { - pub fn new() -> Self { - Self { - amount: vec![Coin::new()], - gas: Uint128(1), - } - } -} - -// Note: The order of fields in this struct is important for the permit signature verification! -#[remain::sorted] -#[derive(Serialize, Clone, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -pub struct Coin { - pub amount: Uint128, - pub denom: String, -} - -impl Coin { - pub fn new() -> Self { - Self { - amount: Uint128::zero(), - denom: "uscrt".to_string(), - } - } -} - -// Note: The order of fields in this struct is important for the permit signature verification! -#[remain::sorted] -#[derive(Serialize, Clone, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -pub struct PermitMsg { - pub r#type: String, - pub value: PermitContent, -} - -impl PermitMsg { - pub fn from_content(content: PermitContent) -> Self { - Self { - r#type: "query_permit".to_string(), - value: content, - } - } -} - -// Note: The order of fields in this struct is important for the permit signature verification! -#[remain::sorted] -#[derive(Serialize, Clone, Debug, PartialEq)] -#[serde(rename_all = "snake_case")] -pub struct PermitContent { - pub allowed_tokens: Vec, - pub permissions: Vec, - pub permit_name: String, -} - -impl PermitContent { - pub fn from_params(params: &PermitParams) -> Self { - Self { - allowed_tokens: params.allowed_tokens.clone(), - permit_name: params.permit_name.clone(), - permissions: params.permissions.clone(), - } - } -} - -#[derive(Deserialize, Serialize, Clone, Debug, PartialEq, JsonSchema)] -#[serde(rename_all = "snake_case")] -pub enum Permission { - Allowance, - Balance, - History, -} diff --git a/src/state.rs b/src/state.rs index 4cf4c84..b42c950 100644 --- a/src/state.rs +++ b/src/state.rs @@ -28,8 +28,6 @@ pub const PREFIX_ALLOWANCES: &[u8] = b"allowances"; pub const PREFIX_VIEW_KEY: &[u8] = b"viewingkey"; pub const PREFIX_RECEIVERS: &[u8] = b"receivers"; -pub const PREFIX_REVOKED_PERMITS: &str = "revoked_permits"; - // Config #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, JsonSchema)] @@ -299,26 +297,6 @@ impl<'a, S: ReadonlyStorage> ReadonlyBalancesImpl<'a, S> { } } -pub struct RevokedPemits; - -impl RevokedPemits { - pub fn is_permit_revoked( - storgae: &dyn Storage, - account: &HumanAddr, - permit_name: &str, - ) -> bool { - let storage_key = PREFIX_REVOKED_PERMITS.to_string() + &account.to_string() + permit_name; - - storgae.get(storage_key.as_bytes()).is_some() - } - - pub fn revoke_permit(storage: &mut dyn Storage, account: &HumanAddr, permit_name: &str) { - let storage_key = PREFIX_REVOKED_PERMITS.to_string() + &account.to_string() + permit_name; - - storage.set(storage_key.as_bytes(), &[]) - } -} - // Allowances #[derive(Serialize, Debug, Deserialize, Clone, PartialEq, Default, JsonSchema)] From 942debd11a7c803f1aac28fd3a272077a6c68077 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Sun, 17 Oct 2021 21:46:21 +0300 Subject: [PATCH 34/39] Fix secret-toolkit dependency --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 2 +- src/contract.rs | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ffd981e..3e3adfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "secret-toolkit-crypto", "secret-toolkit-incubator", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "libsecp256k1", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "secret-toolkit-incubator" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "secret-toolkit-permit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "remain", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "bincode2", "cosmwasm-std", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "schemars", @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "schemars", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?branch=token-permits#6613bf49e105de30ab8f861ca4e56c32641e3cc2" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" dependencies = [ "cosmwasm-std", "schemars", diff --git a/Cargo.toml b/Cargo.toml index e114170..a1ab29a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ debug-print = ["cosmwasm-std/debug-print"] [dependencies] cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", branch = "token-permits" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "b264a14be1e97a90bf625338ffb0ea27bd4fdc94" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } diff --git a/src/contract.rs b/src/contract.rs index 46ad61c..3c1f7f2 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -22,7 +22,7 @@ use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, }; use crate::viewing_key::{ViewingKey, VIEWING_KEY_SIZE}; -use secret_toolkit::permit::{validate_permit, Permission, Permit, RevokedPemits}; +use secret_toolkit::permit::{validate, Permission, Permit, RevokedPemits}; /// We make sure that responses from `handle` are padded to a multiple of this size. pub const RESPONSE_BLOCK_SIZE: usize = 256; @@ -261,12 +261,12 @@ fn permit_queries( .constants()? .contract_address; - let account = validate_permit(deps, &permit, token_address)?; + let account = validate(deps, &permit, token_address)?; // Permit validated! We can now execute the query. match query { QueryWithPermit::Balance {} => { - if !permit.params.permissions.contains(&Permission::Balance) { + if !permit.check_permission(&Permission::Balance) { return Err(StdError::generic_err(format!( "No permission to query balance, got permissions {:?}", permit.params.permissions @@ -276,7 +276,7 @@ fn permit_queries( query_balance(deps, &account) } QueryWithPermit::TransferHistory { page, page_size } => { - if !permit.params.permissions.contains(&Permission::History) { + if !permit.check_permission(&Permission::History) { return Err(StdError::generic_err(format!( "No permission to query history, got permissions {:?}", permit.params.permissions @@ -286,7 +286,7 @@ fn permit_queries( query_transfers(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::TransactionHistory { page, page_size } => { - if !permit.params.permissions.contains(&Permission::History) { + if !permit.check_permission(&Permission::History) { return Err(StdError::generic_err(format!( "No permission to query history, got permissions {:?}", permit.params.permissions @@ -296,7 +296,7 @@ fn permit_queries( query_transactions(deps, &account, page.unwrap_or(0), page_size) } QueryWithPermit::Allowance { owner, spender } => { - if !permit.params.permissions.contains(&Permission::Allowance) { + if !permit.check_permission(&Permission::Allowance) { return Err(StdError::generic_err(format!( "No permission to query allowance, got permissions {:?}", permit.params.permissions From ea276391e0aff3a4a8335d0286a79df2ff69274a Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 18 Oct 2021 21:37:22 +0300 Subject: [PATCH 35/39] Pass storage key prefix to RevokedPemits --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 2 +- src/contract.rs | 10 ++++++++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3e3adfb..50d1f15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "secret-toolkit-crypto", "secret-toolkit-incubator", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "libsecp256k1", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "secret-toolkit-incubator" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "secret-toolkit-permit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "remain", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "bincode2", "cosmwasm-std", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "schemars", @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "schemars", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=b264a14be1e97a90bf625338ffb0ea27bd4fdc94#b264a14be1e97a90bf625338ffb0ea27bd4fdc94" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" dependencies = [ "cosmwasm-std", "schemars", diff --git a/Cargo.toml b/Cargo.toml index a1ab29a..5a4b40c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ debug-print = ["cosmwasm-std/debug-print"] [dependencies] cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "b264a14be1e97a90bf625338ffb0ea27bd4fdc94" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } diff --git a/src/contract.rs b/src/contract.rs index 3c1f7f2..935dc09 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -26,6 +26,7 @@ use secret_toolkit::permit::{validate, Permission, Permit, RevokedPemits}; /// We make sure that responses from `handle` are padded to a multiple of this size. pub const RESPONSE_BLOCK_SIZE: usize = 256; +pub const PREFIX_REVOKED_PERMITS: &str = "revoked_permits"; pub fn init( deps: &mut Extern, @@ -261,7 +262,7 @@ fn permit_queries( .constants()? .contract_address; - let account = validate(deps, &permit, token_address)?; + let account = validate(deps, PREFIX_REVOKED_PERMITS, &permit, token_address)?; // Permit validated! We can now execute the query. match query { @@ -1685,7 +1686,12 @@ fn revoke_permit( env: Env, permit_name: String, ) -> StdResult { - RevokedPemits::revoke_permit(&mut deps.storage, &env.message.sender, &permit_name); + RevokedPemits::revoke_permit( + &mut deps.storage, + PREFIX_REVOKED_PERMITS, + &env.message.sender, + &permit_name, + ); Ok(HandleResponse { messages: vec![], From caa8ab714280104e3ed398a6a8c2ed1db33be287 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 18 Oct 2021 21:48:28 +0300 Subject: [PATCH 36/39] RevokedPemits -> RevokedPermits --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 2 +- src/contract.rs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 50d1f15..09e4ef2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "secret-toolkit-crypto", "secret-toolkit-incubator", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "libsecp256k1", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "secret-toolkit-incubator" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "secret-toolkit-permit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "remain", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "bincode2", "cosmwasm-std", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "schemars", @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "schemars", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=2ec91d7b7422ff4e3441bc374ee1f6faf09cae55#2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" dependencies = [ "cosmwasm-std", "schemars", diff --git a/Cargo.toml b/Cargo.toml index 5a4b40c..338bee6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ debug-print = ["cosmwasm-std/debug-print"] [dependencies] cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "2ec91d7b7422ff4e3441bc374ee1f6faf09cae55" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "a93d9e8dd117793de292cd11f7944d399296bd1d" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } diff --git a/src/contract.rs b/src/contract.rs index 935dc09..9ecbdc0 100644 --- a/src/contract.rs +++ b/src/contract.rs @@ -22,7 +22,7 @@ use crate::transaction_history::{ get_transfers, get_txs, store_burn, store_deposit, store_mint, store_redeem, store_transfer, }; use crate::viewing_key::{ViewingKey, VIEWING_KEY_SIZE}; -use secret_toolkit::permit::{validate, Permission, Permit, RevokedPemits}; +use secret_toolkit::permit::{validate, Permission, Permit, RevokedPermits}; /// We make sure that responses from `handle` are padded to a multiple of this size. pub const RESPONSE_BLOCK_SIZE: usize = 256; @@ -1686,7 +1686,7 @@ fn revoke_permit( env: Env, permit_name: String, ) -> StdResult { - RevokedPemits::revoke_permit( + RevokedPermits::revoke_permit( &mut deps.storage, PREFIX_REVOKED_PERMITS, &env.message.sender, From b2f764ed25c47547c1f2fc24fb59201956e0efc0 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Mon, 18 Oct 2021 22:02:59 +0300 Subject: [PATCH 37/39] Use cosmwasm-std v1.0.0 --- Cargo.lock | 22 +++++++++++----------- Cargo.toml | 8 ++++---- src/transaction_history.rs | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09e4ef2..bb6a95c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -133,7 +133,7 @@ dependencies = [ [[package]] name = "cosmwasm-std" version = "0.10.0" -source = "git+https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca6f2b7f31a6594abe4f44f2e41b1456b3" +source = "git+https://github.com/enigmampc/SecretNetwork?tag=v1.0.0#490fba9243e6cb291462e9d3c1bcbd1975c0df1e" dependencies = [ "base64 0.11.0", "schemars", @@ -145,7 +145,7 @@ dependencies = [ [[package]] name = "cosmwasm-storage" version = "0.10.0" -source = "git+https://github.com/enigmampc/SecretNetwork?tag=v1.0.4-debug-print#004c6bca6f2b7f31a6594abe4f44f2e41b1456b3" +source = "git+https://github.com/enigmampc/SecretNetwork?tag=v1.0.0#490fba9243e6cb291462e9d3c1bcbd1975c0df1e" dependencies = [ "cosmwasm-std", "serde", @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "secret-toolkit-crypto", "secret-toolkit-incubator", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "libsecp256k1", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "secret-toolkit-incubator" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "secret-toolkit-permit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "remain", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "bincode2", "cosmwasm-std", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "schemars", @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "schemars", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=a93d9e8dd117793de292cd11f7944d399296bd1d#a93d9e8dd117793de292cd11f7944d399296bd1d" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" dependencies = [ "cosmwasm-std", "schemars", diff --git a/Cargo.toml b/Cargo.toml index 338bee6..73baa40 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,12 +29,12 @@ overflow-checks = true # for more explicit tests, cargo test --features=backtraces #default = ["debug-print"] backtraces = ["cosmwasm-std/backtraces"] -debug-print = ["cosmwasm-std/debug-print"] +# debug-print = ["cosmwasm-std/debug-print"] [dependencies] -cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.4-debug-print" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "a93d9e8dd117793de292cd11f7944d399296bd1d" } +cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.0" } +cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.0" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } diff --git a/src/transaction_history.rs b/src/transaction_history.rs index 0815808..a7debe6 100644 --- a/src/transaction_history.rs +++ b/src/transaction_history.rs @@ -321,18 +321,18 @@ pub fn store_transfer( // Write to the owners history if it's different from the other two addresses if owner != sender && owner != receiver { - cosmwasm_std::debug_print("saving transaction history for owner"); + // cosmwasm_std::debug_print("saving transaction history for owner"); append_tx(store, &tx, owner)?; append_transfer(store, &transfer, owner)?; } // Write to the sender's history if it's different from the receiver if sender != receiver { - cosmwasm_std::debug_print("saving transaction history for sender"); + // cosmwasm_std::debug_print("saving transaction history for sender"); append_tx(store, &tx, sender)?; append_transfer(store, &transfer, sender)?; } // Always write to the recipient's history - cosmwasm_std::debug_print("saving transaction history for receiver"); + // cosmwasm_std::debug_print("saving transaction history for receiver"); append_tx(store, &tx, receiver)?; append_transfer(store, &transfer, receiver)?; From bae405b3986d8d4a3acaf8206f788f6fc268311a Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 19 Oct 2021 17:03:49 +0300 Subject: [PATCH 38/39] Update secret-toolkit --- Cargo.lock | 22 +++++++++++----------- Cargo.toml | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb6a95c..220d94f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,9 +266,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "7b2f96d100e1cf1929e7719b7edb3b90ab5298072638fccd77be9ce942ecdfce" [[package]] name = "libsecp256k1" @@ -461,7 +461,7 @@ dependencies = [ [[package]] name = "secret-toolkit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "secret-toolkit-crypto", "secret-toolkit-incubator", @@ -476,7 +476,7 @@ dependencies = [ [[package]] name = "secret-toolkit-crypto" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "libsecp256k1", @@ -488,7 +488,7 @@ dependencies = [ [[package]] name = "secret-toolkit-incubator" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -500,7 +500,7 @@ dependencies = [ [[package]] name = "secret-toolkit-permit" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "remain", @@ -515,7 +515,7 @@ dependencies = [ [[package]] name = "secret-toolkit-serialization" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "bincode2", "cosmwasm-std", @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip20" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "schemars", @@ -536,7 +536,7 @@ dependencies = [ [[package]] name = "secret-toolkit-snip721" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "schemars", @@ -547,7 +547,7 @@ dependencies = [ [[package]] name = "secret-toolkit-storage" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "cosmwasm-storage", @@ -558,7 +558,7 @@ dependencies = [ [[package]] name = "secret-toolkit-utils" version = "0.1.0" -source = "git+https://github.com/enigmampc/secret-toolkit?rev=fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea#fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" +source = "git+https://github.com/enigmampc/secret-toolkit?rev=52df67c2becf98510fa55bdad5edf0e2dd11f5a6#52df67c2becf98510fa55bdad5edf0e2dd11f5a6" dependencies = [ "cosmwasm-std", "schemars", diff --git a/Cargo.toml b/Cargo.toml index 73baa40..62ebd53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,12 +29,12 @@ overflow-checks = true # for more explicit tests, cargo test --features=backtraces #default = ["debug-print"] backtraces = ["cosmwasm-std/backtraces"] -# debug-print = ["cosmwasm-std/debug-print"] +# debug-print = ["cosmwasm-std/debug-print"] [dependencies] cosmwasm-std = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.0" } cosmwasm-storage = { git = "https://github.com/enigmampc/SecretNetwork", tag = "v1.0.0" } -secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "fe4f9b5b305c0ddbdae097c0131a8bb1b1f8a6ea" } +secret-toolkit = { git = "https://github.com/enigmampc/secret-toolkit", rev = "52df67c2becf98510fa55bdad5edf0e2dd11f5a6" } schemars = "0.7" serde = { version = "1.0.103", default-features = false, features = ["derive"] } snafu = { version = "0.6.3" } From 2d1d60624838d6d76cf72d14d4d12c225baf6e45 Mon Sep 17 00:00:00 2001 From: Assaf Morami Date: Tue, 19 Oct 2021 22:32:45 +0300 Subject: [PATCH 39/39] cargo schema --- schema/query_msg.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/schema/query_msg.json b/schema/query_msg.json index e8e4bc8..6979c18 100644 --- a/schema/query_msg.json +++ b/schema/query_msg.json @@ -213,6 +213,15 @@ "HumanAddr": { "type": "string" }, + "Permission": { + "type": "string", + "enum": [ + "allowance", + "balance", + "history", + "owner" + ] + }, "Permit": { "type": "object", "required": [ @@ -233,6 +242,7 @@ "required": [ "allowed_tokens", "chain_id", + "permissions", "permit_name" ], "properties": { @@ -245,6 +255,12 @@ "chain_id": { "type": "string" }, + "permissions": { + "type": "array", + "items": { + "$ref": "#/definitions/Permission" + } + }, "permit_name": { "type": "string" }