From de796d30ec9ada16e62c788af506f01e7576f19b Mon Sep 17 00:00:00 2001 From: yito88 Date: Sat, 20 Aug 2022 17:33:47 +0200 Subject: [PATCH 1/7] multitoken transfer and query --- apps/src/lib/cli.rs | 15 +++ apps/src/lib/client/rpc.rs | 128 ++++++++++++++++++---- apps/src/lib/client/tx.rs | 15 ++- shared/src/types/intent.rs | 4 + shared/src/types/token.rs | 68 ++++++++++++ tests/src/e2e/ledger_tests.rs | 1 + vm_env/src/governance.rs | 1 + vm_env/src/ibc.rs | 2 +- vm_env/src/proof_of_stake.rs | 2 +- vm_env/src/token.rs | 108 ++++++++++++++---- wasm/wasm_source/src/tx_from_intent.rs | 3 +- wasm/wasm_source/src/tx_transfer.rs | 3 +- wasm/wasm_source/src/vp_testnet_faucet.rs | 8 +- wasm/wasm_source/src/vp_user.rs | 20 +++- wasm_for_tests/wasm_source/src/lib.rs | 1 + 15 files changed, 323 insertions(+), 56 deletions(-) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index f546860cfd..6eb6454bc4 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -1465,6 +1465,7 @@ pub mod args { const SOURCE: Arg = arg("source"); const SOURCE_OPT: ArgOpt = SOURCE.opt(); const STORAGE_KEY: Arg = arg("storage-key"); + const SUB_PREFIX: ArgOpt = arg_opt("sub-prefix"); const TARGET: Arg = arg("target"); const TO_STDOUT: ArgFlag = flag("stdout"); const TOKEN_OPT: ArgOpt = TOKEN.opt(); @@ -1610,6 +1611,8 @@ pub mod args { pub target: WalletAddress, /// Transferred token address pub token: WalletAddress, + /// Transferred token address + pub sub_prefix: Option, /// Transferred token amount pub amount: token::Amount, } @@ -1620,12 +1623,14 @@ pub mod args { let source = SOURCE.parse(matches); let target = TARGET.parse(matches); let token = TOKEN.parse(matches); + let sub_prefix = SUB_PREFIX.parse(matches); let amount = AMOUNT.parse(matches); Self { tx, source, target, token, + sub_prefix, amount, } } @@ -1638,6 +1643,7 @@ pub mod args { )) .arg(TARGET.def().about("The target account address.")) .arg(TOKEN.def().about("The transfer token.")) + .arg(SUB_PREFIX.def().about("The token's sub prefix.")) .arg(AMOUNT.def().about("The amount to transfer in decimal.")) } } @@ -2185,6 +2191,8 @@ pub mod args { pub owner: Option, /// Address of a token pub token: Option, + /// Sub prefix of an account + pub sub_prefix: Option, } impl Args for QueryBalance { @@ -2192,10 +2200,12 @@ pub mod args { let query = Query::parse(matches); let owner = OWNER.parse(matches); let token = TOKEN_OPT.parse(matches); + let sub_prefix = SUB_PREFIX.parse(matches); Self { query, owner, token, + sub_prefix, } } @@ -2211,6 +2221,11 @@ pub mod args { .def() .about("The token's address whose balance to query."), ) + .arg( + SUB_PREFIX.def().about( + "The token's sub prefix whose balance to query.", + ), + ) } } diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index 4209772be2..756f704344 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -27,7 +27,7 @@ use namada::types::governance::{ OfflineProposal, OfflineVote, ProposalVote, TallyResult, }; use namada::types::key::*; -use namada::types::storage::{Epoch, PrefixValue}; +use namada::types::storage::{Epoch, Key, KeySeg, PrefixValue}; use namada::types::token::{balance_key, Amount}; use namada::types::{address, storage, token}; use tendermint::abci::Code; @@ -101,15 +101,29 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { (Some(token), Some(owner)) => { let token = ctx.get(&token); let owner = ctx.get(&owner); - let key = token::balance_key(&token, &owner); + let key = match &args.sub_prefix { + Some(sub_prefix) => { + let sub_prefix = Key::parse(sub_prefix).unwrap(); + let prefix = + token::multitoken_balance_prefix(&token, &sub_prefix); + token::multitoken_balance_key(&prefix, &owner) + } + None => token::balance_key(&token, &owner), + }; let currency_code = tokens .get(&token) .map(|c| Cow::Borrowed(*c)) .unwrap_or_else(|| Cow::Owned(token.to_string())); match query_storage_value::(&client, &key).await { - Some(balance) => { - println!("{}: {}", currency_code, balance); - } + Some(balance) => match &args.sub_prefix { + Some(sub_prefix) => { + println!( + "{} with {}: {}", + currency_code, sub_prefix, balance + ); + } + None => println!("{}: {}", currency_code, balance), + }, None => { println!("No {} balance found for {}", currency_code, owner) } @@ -119,12 +133,44 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { let owner = ctx.get(&owner); let mut found_any = false; for (token, currency_code) in tokens { - let key = token::balance_key(&token, &owner); - if let Some(balance) = - query_storage_value::(&client, &key).await - { - println!("{}: {}", currency_code, balance); - found_any = true; + let prefix = token.to_db_key().into(); + let balances = query_storage_prefix::( + client.clone(), + prefix, + ) + .await; + if let Some(balances) = balances { + let stdout = io::stdout(); + let mut w = stdout.lock(); + for (key, balance) in balances { + match token::is_any_multitoken_balance_key(&key) { + Some((sub_prefix, o)) if *o == owner => { + writeln!( + w, + "{} with {}: {}", + currency_code, sub_prefix, balance + ) + .unwrap(); + found_any = true; + } + Some(_) => {} + None => { + if let Some(o) = + token::is_any_token_balance_key(&key) + { + if *o == owner { + writeln!( + w, + "{}: {}", + currency_code, balance + ) + .unwrap(); + found_any = true; + } + } + } + } + } } } if !found_any { @@ -133,9 +179,9 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { } (Some(token), None) => { let token = ctx.get(&token); - let key = token::balance_prefix(&token); + let prefix = token.to_db_key().into(); let balances = - query_storage_prefix::(client, key).await; + query_storage_prefix::(client, prefix).await; match balances { Some(balances) => { let currency_code = tokens @@ -144,12 +190,30 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { .unwrap_or_else(|| Cow::Owned(token.to_string())); let stdout = io::stdout(); let mut w = stdout.lock(); - writeln!(w, "Token {}:", currency_code).unwrap(); + writeln!(w, "Token {}", currency_code).unwrap(); for (key, balance) in balances { - let owner = - token::is_any_token_balance_key(&key).unwrap(); - writeln!(w, " {}, owned by {}", balance, owner) - .unwrap(); + match token::is_any_multitoken_balance_key(&key) { + Some((sub_prefix, owner)) => { + writeln!( + w, + " with {}: {}, owned by {}", + sub_prefix, balance, owner + ) + .unwrap(); + } + None => { + if let Some(owner) = + token::is_any_token_balance_key(&key) + { + writeln!( + w, + ": {}, owned by {}", + balance, owner + ) + .unwrap(); + } + } + } } } None => { @@ -167,12 +231,30 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { .await; match balances { Some(balances) => { - writeln!(w, "Token {}:", currency_code).unwrap(); + writeln!(w, "Token {}", currency_code).unwrap(); for (key, balance) in balances { - let owner = - token::is_any_token_balance_key(&key).unwrap(); - writeln!(w, " {}, owned by {}", balance, owner) - .unwrap(); + match token::is_any_multitoken_balance_key(&key) { + Some((sub_prefix, owner)) => { + writeln!( + w, + " with {}: {}, owned by {}", + sub_prefix, balance, owner + ) + .unwrap(); + } + None => { + if let Some(owner) = + token::is_any_token_balance_key(&key) + { + writeln!( + w, + ": {}, owned by {}", + balance, owner + ) + .unwrap() + } + } + } } } None => { diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 8daf318435..43eeb49c68 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -16,7 +16,7 @@ use namada::types::governance::{ }; use namada::types::key::*; use namada::types::nft::{self, Nft, NftToken}; -use namada::types::storage::Epoch; +use namada::types::storage::{Epoch, Key}; use namada::types::token::Amount; use namada::types::transaction::governance::{ InitProposalData, VoteProposalData, @@ -415,7 +415,17 @@ pub async fn submit_transfer(ctx: Context, args: args::TxTransfer) { } } // Check source balance - let balance_key = token::balance_key(&token, &source); + let (sub_prefix, balance_key) = match args.sub_prefix { + Some(sub_prefix) => { + let sub_prefix = Key::parse(sub_prefix).unwrap(); + let prefix = token::multitoken_balance_prefix(&token, &sub_prefix); + ( + Some(sub_prefix), + token::multitoken_balance_key(&prefix, &source), + ) + } + None => (None, token::balance_key(&token, &source)), + }; let client = HttpClient::new(args.tx.ledger_address.clone()).unwrap(); match rpc::query_storage_value::(&client, &balance_key).await { @@ -447,6 +457,7 @@ pub async fn submit_transfer(ctx: Context, args: args::TxTransfer) { source, target, token, + sub_prefix, amount: args.amount, }; tracing::debug!("Transfer data {:?}", transfer); diff --git a/shared/src/types/intent.rs b/shared/src/types/intent.rs index c3effbb4fc..3acb43f0c0 100644 --- a/shared/src/types/intent.rs +++ b/shared/src/types/intent.rs @@ -316,12 +316,14 @@ mod tests { source: bertha_addr.clone(), target: albert_addr.clone(), token: Address::from_str(BTC).unwrap(), + sub_prefix: None, amount: token::Amount::from(100), }, token::Transfer { source: albert_addr, target: bertha_addr, token: Address::from_str(XAN).unwrap(), + sub_prefix: None, amount: token::Amount::from(1), }, ] @@ -424,12 +426,14 @@ mod tests { source: bertha_addr.clone(), target: albert_addr.clone(), token: Address::from_str(BTC).unwrap(), + sub_prefix: None, amount: token::Amount::from(100), }, token::Transfer { source: albert_addr, target: bertha_addr, token: Address::from_str(XAN).unwrap(), + sub_prefix: None, amount: token::Amount::from(1), }, ] diff --git a/shared/src/types/token.rs b/shared/src/types/token.rs index f3e4cd4ed2..4d03138e60 100644 --- a/shared/src/types/token.rs +++ b/shared/src/types/token.rs @@ -250,6 +250,23 @@ pub fn balance_prefix(token_addr: &Address) -> Key { .expect("Cannot obtain a storage key") } +/// Obtain a storage key prefix for multitoken balances. +pub fn multitoken_balance_prefix( + token_addr: &Address, + sub_prefix: &Key, +) -> Key { + Key::from(token_addr.to_db_key()).join(sub_prefix) +} + +/// Obtain a storage key for user's multitoken balance. +pub fn multitoken_balance_key(prefix: &Key, owner: &Address) -> Key { + prefix + .push(&BALANCE_STORAGE_KEY.to_owned()) + .expect("Cannot obtain a storage key") + .push(&owner.to_db_key()) + .expect("Cannot obtain a storage key") +} + /// Check if the given storage key is balance key for the given token. If it is, /// returns the owner. pub fn is_balance_key<'a>( @@ -297,6 +314,54 @@ pub fn is_non_owner_balance_key(key: &Key) -> Option<&Address> { } } +/// Check if the given storage key is multitoken balance key for the given +/// token. If it is, returns the sub prefix and the owner. +pub fn is_multitoken_balance_key<'a>( + token_addr: &Address, + key: &'a Key, +) -> Option<(Key, &'a Address)> { + match key.segments.first() { + Some(DbKeySeg::AddressSeg(addr)) if addr == token_addr => { + multitoken_balance_owner(key) + } + _ => None, + } +} + +/// Check if the given storage key is multitoken balance key for unspecified +/// token. If it is, returns the sub prefix and the owner. +pub fn is_any_multitoken_balance_key(key: &Key) -> Option<(Key, &Address)> { + match key.segments.first() { + Some(DbKeySeg::AddressSeg(_)) => multitoken_balance_owner(key), + _ => None, + } +} + +fn multitoken_balance_owner(key: &Key) -> Option<(Key, &Address)> { + let len = key.segments.len(); + if len < 4 { + // the key of a multitoken should have 1 or more segments other than + // token, balance, owner + return None; + } + match key.get_at(len - 2) { + Some(DbKeySeg::StringSeg(balance)) + if balance == BALANCE_STORAGE_KEY => + { + match key.segments.last() { + Some(DbKeySeg::AddressSeg(owner)) => { + let sub_prefix = Key { + segments: key.segments[1..(len - 2)].to_vec(), + }; + Some((sub_prefix, owner)) + } + _ => None, + } + } + _ => None, + } +} + /// A simple bilateral token transfer #[derive( Debug, @@ -318,6 +383,8 @@ pub struct Transfer { pub target: Address, /// Token's address pub token: Address, + /// Source token's sub prefix + pub sub_prefix: Option, /// The amount of tokens pub amount: Amount, } @@ -354,6 +421,7 @@ impl TryFrom for Transfer { source, target, token, + sub_prefix: None, amount, }) } diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index 22eb4f4ac5..1f19433ca1 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -425,6 +425,7 @@ fn invalid_transactions() -> Result<()> { source: find_address(&test, DAEWON)?, target: find_address(&test, ALBERT)?, token: find_address(&test, XAN)?, + sub_prefix: None, amount: token::Amount::whole(1), }; let data = transfer diff --git a/vm_env/src/governance.rs b/vm_env/src/governance.rs index db4ea7916f..cfe16e2acb 100644 --- a/vm_env/src/governance.rs +++ b/vm_env/src/governance.rs @@ -63,6 +63,7 @@ pub mod tx { &data.author, &governance_address, &m1t(), + None, min_proposal_funds, ); } diff --git a/vm_env/src/ibc.rs b/vm_env/src/ibc.rs index febaa78560..c7abb82ec5 100644 --- a/vm_env/src/ibc.rs +++ b/vm_env/src/ibc.rs @@ -37,7 +37,7 @@ impl IbcActions for Ibc { token: &Address, amount: Amount, ) { - transfer(src, dest, token, amount) + transfer(src, dest, token, None, amount) } fn get_height(&self) -> BlockHeight { diff --git a/vm_env/src/proof_of_stake.rs b/vm_env/src/proof_of_stake.rs index 8e4bba4223..afabd85ed7 100644 --- a/vm_env/src/proof_of_stake.rs +++ b/vm_env/src/proof_of_stake.rs @@ -256,6 +256,6 @@ impl namada_proof_of_stake::PosActions for PoS { src: &Self::Address, dest: &Self::Address, ) { - crate::token::tx::transfer(src, dest, token, amount) + crate::token::tx::transfer(src, dest, token, None, amount) } } diff --git a/vm_env/src/token.rs b/vm_env/src/token.rs index 8a7367afb9..784b838707 100644 --- a/vm_env/src/token.rs +++ b/vm_env/src/token.rs @@ -20,7 +20,12 @@ pub mod vp { ) -> bool { let mut change: Change = 0; let all_checked = keys_changed.iter().all(|key| { - match token::is_balance_key(token, key) { + let owner: Option<&Address> = + match token::is_multitoken_balance_key(token, key) { + Some((_, o)) => Some(o), + None => token::is_balance_key(token, key), + }; + match owner { None => { // Unknown changes to this address space are disallowed, but // unknown changes anywhere else are permitted @@ -73,38 +78,101 @@ pub mod tx { src: &Address, dest: &Address, token: &Address, + sub_prefix: Option, amount: Amount, ) { - let src_key = token::balance_key(token, src); - let dest_key = token::balance_key(token, dest); + let src_key = match &sub_prefix { + Some(sub_prefix) => { + let prefix = + token::multitoken_balance_prefix(token, sub_prefix); + token::multitoken_balance_key(&prefix, src) + } + None => token::balance_key(token, src), + }; + let dest_key = match &sub_prefix { + Some(sub_prefix) => { + let prefix = + token::multitoken_balance_prefix(token, sub_prefix); + token::multitoken_balance_key(&prefix, dest) + } + None => token::balance_key(token, dest), + }; let src_bal: Option = tx::read(&src_key.to_string()); - let mut src_bal = src_bal.unwrap_or_else(|| match src { - Address::Internal(InternalAddress::IbcMint) => Amount::max(), - _ => { + match src_bal { + None => { tx::log_string(format!("src {} has no balance", src)); unreachable!() } - }); - src_bal.spend(&amount); - let mut dest_bal: Amount = - tx::read(&dest_key.to_string()).unwrap_or_default(); - dest_bal.receive(&amount); - match src { - Address::Internal(InternalAddress::IbcMint) => { - tx::write_temp(&src_key.to_string(), src_bal) + Some(mut src_bal) => { + src_bal.spend(&amount); + let mut dest_bal: Amount = + tx::read(&dest_key.to_string()).unwrap_or_default(); + dest_bal.receive(&amount); + tx::write(&src_key.to_string(), src_bal); + tx::write(&dest_key.to_string(), dest_bal); } - Address::Internal(InternalAddress::IbcBurn) => { + } + } + + /// A token transfer with storage keys that can be used in a transaction. + pub fn transfer_with_keys(src_key: &Key, dest_key: &Key, amount: Amount) { + let src_owner = is_any_multitoken_balance_key(src_key).map(|(_, o)| o); + let src_bal: Option = match src_owner { + Some(Address::Internal(InternalAddress::IbcMint)) => { + Some(Amount::max()) + } + Some(Address::Internal(InternalAddress::IbcBurn)) => { tx::log_string("invalid transfer from the burn address"); unreachable!() } - _ => tx::write(&src_key.to_string(), src_bal), - } - match dest { - Address::Internal(InternalAddress::IbcMint) => { + Some(_) => tx::read(&src_key.to_string()), + None => { + // the key is not a multitoken key + match is_any_token_balance_key(src_key) { + Some(_) => tx::read(src_key.to_string()), + None => { + tx::log_string(format!( + "invalid balance key: {}", + src_key + )); + unreachable!() + } + } + } + }; + let mut src_bal = src_bal.unwrap_or_else(|| { + tx::log_string(format!("src {} has no balance", src_key)); + unreachable!() + }); + src_bal.spend(&amount); + let dest_owner = + is_any_multitoken_balance_key(dest_key).map(|(_, o)| o); + let mut dest_bal: Amount = match dest_owner { + Some(Address::Internal(InternalAddress::IbcMint)) => { tx::log_string("invalid transfer to the mint address"); unreachable!() } - Address::Internal(InternalAddress::IbcBurn) => { + Some(_) => tx::read(dest_key.to_string()).unwrap_or_default(), + None => match is_any_token_balance_key(dest_key) { + Some(_) => tx::read(dest_key.to_string()).unwrap_or_default(), + None => { + tx::log_string(format!( + "invalid balance key: {}", + dest_key + )); + unreachable!() + } + }, + }; + dest_bal.receive(&amount); + match src_owner { + Some(Address::Internal(InternalAddress::IbcMint)) => { + tx::write_temp(&src_key.to_string(), src_bal) + } + _ => tx::write(&src_key.to_string(), src_bal), + } + match dest_owner { + Some(Address::Internal(InternalAddress::IbcBurn)) => { tx::write_temp(&dest_key.to_string(), dest_bal) } _ => tx::write(&dest_key.to_string(), dest_bal), diff --git a/wasm/wasm_source/src/tx_from_intent.rs b/wasm/wasm_source/src/tx_from_intent.rs index e39963fae7..f86c412353 100644 --- a/wasm/wasm_source/src/tx_from_intent.rs +++ b/wasm/wasm_source/src/tx_from_intent.rs @@ -20,10 +20,11 @@ fn apply_tx(tx_data: Vec) { source, target, token, + sub_prefix, amount, } in tx_data.matches.transfers { - token::transfer(&source, &target, &token, amount); + token::transfer(&source, &target, &token, sub_prefix, amount); } tx_data diff --git a/wasm/wasm_source/src/tx_transfer.rs b/wasm/wasm_source/src/tx_transfer.rs index f0ab0ad2d0..059a3296e1 100644 --- a/wasm/wasm_source/src/tx_transfer.rs +++ b/wasm/wasm_source/src/tx_transfer.rs @@ -14,7 +14,8 @@ fn apply_tx(tx_data: Vec) { source, target, token, + sub_prefix, amount, } = transfer; - token::transfer(&source, &target, &token, amount) + token::transfer(&source, &target, &token, sub_prefix, amount) } diff --git a/wasm/wasm_source/src/vp_testnet_faucet.rs b/wasm/wasm_source/src/vp_testnet_faucet.rs index 553288926e..a2f9a6267b 100644 --- a/wasm/wasm_source/src/vp_testnet_faucet.rs +++ b/wasm/wasm_source/src/vp_testnet_faucet.rs @@ -136,7 +136,9 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(&source, address, &token, amount); + tx_host_env::token::transfer( + &source, address, &token, None, amount, + ); }); let vp_env = vp_host_env::take(); @@ -251,7 +253,7 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(address, &target, &token, amount); + tx_host_env::token::transfer(address, &target, &token, None, amount); }); let vp_env = vp_host_env::take(); @@ -284,7 +286,7 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(address, &target, &token, amount); + tx_host_env::token::transfer(address, &target, &token, None, amount); }); let vp_env = vp_host_env::take(); diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index a222a344ef..e1815cc0b1 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -34,6 +34,10 @@ impl<'a> From<&'a storage::Key> for KeyType<'a> { fn from(key: &'a storage::Key) -> KeyType<'a> { if let Some(address) = token::is_any_token_balance_key(key) { Self::Token(address) + } else if let Some((_, address)) = + token::is_any_multitoken_balance_key(key) + { + Self::Token(address) } else if proof_of_stake::is_pos_key(key) { Self::PoS } else if let Some(address) = intent::is_invalid_intent_key(key) { @@ -412,7 +416,9 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(&source, address, &token, amount); + tx_host_env::token::transfer( + &source, address, &token, None, amount, + ); }); let vp_env = vp_host_env::take(); @@ -445,7 +451,9 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(address, &target, &token, amount); + tx_host_env::token::transfer( + address, &target, &token, None, amount, + ); }); let vp_env = vp_host_env::take(); @@ -482,7 +490,9 @@ mod tests { // Initialize VP environment from a transaction vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { // Apply transfer in a transaction - tx_host_env::token::transfer(address, &target, &token, amount); + tx_host_env::token::transfer( + address, &target, &token, None, amount, + ); }); let mut vp_env = vp_host_env::take(); @@ -520,7 +530,9 @@ mod tests { vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { tx_host_env::insert_verifier(address); // Apply transfer in a transaction - tx_host_env::token::transfer(&source, &target, &token, amount); + tx_host_env::token::transfer( + &source, &target, &token, None, amount, + ); }); let vp_env = vp_host_env::take(); diff --git a/wasm_for_tests/wasm_source/src/lib.rs b/wasm_for_tests/wasm_source/src/lib.rs index 674fb2a2d9..1062d1ce43 100644 --- a/wasm_for_tests/wasm_source/src/lib.rs +++ b/wasm_for_tests/wasm_source/src/lib.rs @@ -140,6 +140,7 @@ pub mod main { source: _, target, token, + sub_prefix: _, amount, } = transfer; let target_key = token::balance_key(&token, &target); From 86b373c747663d95e216a7f112c077fcb4f39ab7 Mon Sep 17 00:00:00 2001 From: yito88 Date: Sat, 20 Aug 2022 18:41:52 +0200 Subject: [PATCH 2/7] remove an error message --- apps/src/lib/client/rpc.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index 756f704344..bf673b0dd3 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -1414,14 +1414,7 @@ where Ok(values) => { let decode = |PrefixValue { key, value }: PrefixValue| { match T::try_from_slice(&value[..]) { - Err(err) => { - eprintln!( - "Skipping a value for key {}. Error in \ - decoding: {}", - key, err - ); - None - } + Err(_) => None, Ok(value) => Some((key, value)), } }; From 8789392fc41d5604df4ef19e669bfe6a36fa17a9 Mon Sep 17 00:00:00 2001 From: yito88 Date: Sun, 21 Aug 2022 09:39:48 +0200 Subject: [PATCH 3/7] update a test wasm --- wasm_for_tests/tx_mint_tokens.wasm | Bin 226185 -> 229247 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/wasm_for_tests/tx_mint_tokens.wasm b/wasm_for_tests/tx_mint_tokens.wasm index c9a102773e28ced047f374606582082da3d839d0..b6f8f074bf213c9a7bcd33fbf811e213ff4bab37 100755 GIT binary patch delta 78238 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 z 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 delta 75499 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
j?xxwrg2Y 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 Date: Tue, 23 Aug 2022 12:52:12 +0200 Subject: [PATCH 4/7] change the balance format --- apps/src/lib/client/rpc.rs | 168 ++++++++++++++----------------------- shared/src/types/token.rs | 23 +++-- 2 files changed, 71 insertions(+), 120 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index bf673b0dd3..ba02e82b5e 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -131,8 +131,7 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { } (None, Some(owner)) => { let owner = ctx.get(&owner); - let mut found_any = false; - for (token, currency_code) in tokens { + for (token, _) in tokens { let prefix = token.to_db_key().into(); let balances = query_storage_prefix::( client.clone(), @@ -140,132 +139,87 @@ pub async fn query_balance(ctx: Context, args: args::QueryBalance) { ) .await; if let Some(balances) = balances { - let stdout = io::stdout(); - let mut w = stdout.lock(); - for (key, balance) in balances { - match token::is_any_multitoken_balance_key(&key) { - Some((sub_prefix, o)) if *o == owner => { - writeln!( - w, - "{} with {}: {}", - currency_code, sub_prefix, balance - ) - .unwrap(); - found_any = true; - } - Some(_) => {} - None => { - if let Some(o) = - token::is_any_token_balance_key(&key) - { - if *o == owner { - writeln!( - w, - "{}: {}", - currency_code, balance - ) - .unwrap(); - found_any = true; - } - } - } - } - } + print_balances(balances, &token, Some(&owner)); } } - if !found_any { - println!("No balance found for {}", owner); - } } (Some(token), None) => { let token = ctx.get(&token); let prefix = token.to_db_key().into(); let balances = query_storage_prefix::(client, prefix).await; - match balances { - Some(balances) => { - let currency_code = tokens - .get(&token) - .map(|c| Cow::Borrowed(*c)) - .unwrap_or_else(|| Cow::Owned(token.to_string())); - let stdout = io::stdout(); - let mut w = stdout.lock(); - writeln!(w, "Token {}", currency_code).unwrap(); - for (key, balance) in balances { - match token::is_any_multitoken_balance_key(&key) { - Some((sub_prefix, owner)) => { - writeln!( - w, - " with {}: {}, owned by {}", - sub_prefix, balance, owner - ) - .unwrap(); - } - None => { - if let Some(owner) = - token::is_any_token_balance_key(&key) - { - writeln!( - w, - ": {}, owned by {}", - balance, owner - ) - .unwrap(); - } - } - } - } - } - None => { - println!("No balances for token {}", token.encode()) - } + if let Some(balances) = balances { + print_balances(balances, &token, None); } } (None, None) => { - let stdout = io::stdout(); - let mut w = stdout.lock(); - for (token, currency_code) in tokens { + for (token, _) in tokens { let key = token::balance_prefix(&token); let balances = query_storage_prefix::(client.clone(), key) .await; - match balances { - Some(balances) => { - writeln!(w, "Token {}", currency_code).unwrap(); - for (key, balance) in balances { - match token::is_any_multitoken_balance_key(&key) { - Some((sub_prefix, owner)) => { - writeln!( - w, - " with {}: {}, owned by {}", - sub_prefix, balance, owner - ) - .unwrap(); - } - None => { - if let Some(owner) = - token::is_any_token_balance_key(&key) - { - writeln!( - w, - ": {}, owned by {}", - balance, owner - ) - .unwrap() - } - } - } - } - } - None => { - println!("No balances for token {}", token.encode()) - } + if let Some(balances) = balances { + print_balances(balances, &token, None); } } } } } +fn print_balances( + balances: impl Iterator, + token: &Address, + target: Option<&Address>, +) { + let stdout = io::stdout(); + let mut w = stdout.lock(); + + // Token + let tokens = address::tokens(); + let currency_code = tokens + .get(token) + .map(|c| Cow::Borrowed(*c)) + .unwrap_or_else(|| Cow::Owned(token.to_string())); + writeln!(w, "Token {}", currency_code).unwrap(); + + let print_num = balances + .filter_map( + |(key, balance)| match token::is_any_multitoken_balance_key(&key) { + Some((sub_prefix, owner)) => Some(( + owner.clone(), + format!( + "with {}: {}, owned by {}", + sub_prefix, balance, owner + ), + )), + None => token::is_any_token_balance_key(&key).map(|owner| { + ( + owner.clone(), + format!(": {}, owned by {}", balance, owner), + ) + }), + }, + ) + .filter_map(|(o, s)| match target { + Some(t) if o == *t => Some(s), + Some(_) => None, + None => Some(s), + }) + .map(|s| { + writeln!(w, "{}", s).unwrap(); + }) + .count(); + + if print_num == 0 { + match target { + Some(t) => writeln!(w, "No balances owned by {}", t).unwrap(), + None => { + writeln!(w, "No balances for token {}", currency_code).unwrap() + } + } + } +} + /// Query Proposals pub async fn query_proposal(_ctx: Context, args: args::QueryProposal) { async fn print_proposal( diff --git a/shared/src/types/token.rs b/shared/src/types/token.rs index 4d03138e60..a4a123da12 100644 --- a/shared/src/types/token.rs +++ b/shared/src/types/token.rs @@ -344,19 +344,16 @@ fn multitoken_balance_owner(key: &Key) -> Option<(Key, &Address)> { // token, balance, owner return None; } - match key.get_at(len - 2) { - Some(DbKeySeg::StringSeg(balance)) - if balance == BALANCE_STORAGE_KEY => - { - match key.segments.last() { - Some(DbKeySeg::AddressSeg(owner)) => { - let sub_prefix = Key { - segments: key.segments[1..(len - 2)].to_vec(), - }; - Some((sub_prefix, owner)) - } - _ => None, - } + match &key.segments[..] { + [ + .., + DbKeySeg::StringSeg(balance), + DbKeySeg::AddressSeg(owner), + ] if balance == BALANCE_STORAGE_KEY => { + let sub_prefix = Key { + segments: key.segments[1..(len - 2)].to_vec(), + }; + Some((sub_prefix, owner)) } _ => None, } From fe95e805810226ab492337907e060cd2af6ea798 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 2 Sep 2022 12:40:32 +0000 Subject: [PATCH 5/7] wasm checksums update --- wasm/checksums.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index a337a7b1a8..5aff977ad1 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,19 +1,19 @@ { - "tx_bond.wasm": "tx_bond.e0cf6b4c7cae7606f597f66a2b467ed44ab817744471554650e59c1504e1cfd8.wasm", - "tx_from_intent.wasm": "tx_from_intent.2190adc094be799ff1c8383e4b57c7d2ab5da328e845f8f3095cce4ed8b0041b.wasm", - "tx_ibc.wasm": "tx_ibc.014a3a93980f04147826f1e568551b1127de763e6c07480990db1c240877141b.wasm", - "tx_init_account.wasm": "tx_init_account.f4eceee710c20f402a9984338294a87ca5b33b45ac3e4c2229550c2a00597230.wasm", - "tx_init_nft.wasm": "tx_init_nft.809d0b46379ea9ea4cd7cd026e52ac7ad25094b090976a748a349691026db95b.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.b6b1014750b667bca57d82979c2295e99d0d3ab3723301029dcaa4b125ed401a.wasm", - "tx_init_validator.wasm": "tx_init_validator.da09c65fad79490ededfbf9ebc75df6626031f36f62791dc4e092743c91914aa.wasm", - "tx_mint_nft.wasm": "tx_mint_nft.07d3118e626ca59c95571ccf00e24265570388b66f8e67228b109b7c095653a7.wasm", - "tx_transfer.wasm": "tx_transfer.e84e5b4d77c81d2d6fe248d2c3b5ae0bb6d5fb7ef13da5e62e4b7ac7764fd80a.wasm", - "tx_unbond.wasm": "tx_unbond.35bb3196fd77c138541507d139cb68ca0f752df6cad0fb22db4a00bc64471771.wasm", - "tx_update_vp.wasm": "tx_update_vp.f73a121138f8b9d2fa0a50ae0b1dfb0b69ca4fd6559f5600aec61cd2aeece960.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.66f3c60eb109f2c631c2ee5f5fb47d73a086fa2a786b2ff63907e4e95bd79fcf.wasm", - "tx_withdraw.wasm": "tx_withdraw.a630427bcb03ec5cbd96b85ef86f79f85a5d1cff12f6b10308a9cb006ac95533.wasm", - "vp_nft.wasm": "vp_nft.bd7840f82f1ad27546266c01884ef69e81bd9e365cee53c8b013339e395ce392.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.feb9eec34cc11bd2233281a199e78d1bc284ce9eb4465198f483c5eb8075d8ab.wasm", - "vp_token.wasm": "vp_token.07f6e0b8a161125c7c1ed3356694a28e340332be1674e1d561802ba213736417.wasm", - "vp_user.wasm": "vp_user.b856d1a609021e0a4728ecd961268840eddff938fd67d09b648f31fc6422bf5a.wasm" + "tx_bond.wasm": "tx_bond.d8eb4f60b307ff0c0e5ccd76b38dac64aa9c40b32fe222e6180367f8adf61566.wasm", + "tx_from_intent.wasm": "tx_from_intent.a9fec9c3e07acf21676a4559017722c75db0d4e2013d8a24a2413cc1dcf51fbf.wasm", + "tx_ibc.wasm": "tx_ibc.f17dddf05a835f7bcd898ed90f10f4cb64c4b3246b15f4a92fa098c30eacf45e.wasm", + "tx_init_account.wasm": "tx_init_account.36f85e33e85816c73d24fdae42cef7c80309de05460e78ac5a78024b54d9c90d.wasm", + "tx_init_nft.wasm": "tx_init_nft.6e156e65bc19858ade99f91705b475fb9ab9c2641d23cf22db85958cc626146d.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.4e2cc918ea175b29c8b2fcf48865eb6251b8db88799f80226e796d070cd3f2e9.wasm", + "tx_init_validator.wasm": "tx_init_validator.90c115e298fb7906c83eed0e965c84ce4657a163d828b1a676f231f04cebea2a.wasm", + "tx_mint_nft.wasm": "tx_mint_nft.86e54bbefb7b6bc4f189df15943f4b7a9247fa6faf30ebf31c8b450bacae6e08.wasm", + "tx_transfer.wasm": "tx_transfer.40d4409576a238aa447da2a5728cc2c67d0e6896e50f66c76f10f2ab28660d30.wasm", + "tx_unbond.wasm": "tx_unbond.b41aadf4b8f1f1b9188de26a54d0cfc1097a69d2e3632548144af46efe988547.wasm", + "tx_update_vp.wasm": "tx_update_vp.9a68c44fc97171a8d2218df2b1267dcf9faffb4b12393f72c4a7cc726192a351.wasm", + "tx_vote_proposal.wasm": "tx_vote_proposal.7053bdd44c9996c3b22d8ef65747e019328f334ed58016f7ff93d0f61d76331d.wasm", + "tx_withdraw.wasm": "tx_withdraw.dccadb23e21d1ac3f19e8c71702f5b896834757d6aa9e7d0acd369f27539dee4.wasm", + "vp_nft.wasm": "vp_nft.08c41172486de46d40e1fe4e38d742f740fc2c91929e183ec69b091907665068.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.1598a5c1a78fc1df8e04c16a247a86b44e003954edc8594f4c73d3d226c1bb6c.wasm", + "vp_token.wasm": "vp_token.956607c8a4199be635a2b27799be5f78ae34dab23654c6f8b0ad36501ae740d3.wasm", + "vp_user.wasm": "vp_user.251d6f05c0a51dad915ccc11606206fdf1edb897ddcb8ce0a632d7c442372b65.wasm" } \ No newline at end of file From bf9a0966722719232d9f1343dd81d8162464aef8 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 5 Sep 2022 09:06:48 +0100 Subject: [PATCH 6/7] Update vm_env/src/token.rs Co-authored-by: Jacob Turner --- vm_env/src/token.rs | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/vm_env/src/token.rs b/vm_env/src/token.rs index 784b838707..5ba2d7e33f 100644 --- a/vm_env/src/token.rs +++ b/vm_env/src/token.rs @@ -81,21 +81,19 @@ pub mod tx { sub_prefix: Option, amount: Amount, ) { - let src_key = match &sub_prefix { + let (src_key, dest_key) = match &sub_prefix { Some(sub_prefix) => { let prefix = token::multitoken_balance_prefix(token, sub_prefix); - token::multitoken_balance_key(&prefix, src) + ( + token::multitoken_balance_key(&prefix, src), + token::multitoken_balance_key(&prefix, dest), + ) } - None => token::balance_key(token, src), - }; - let dest_key = match &sub_prefix { - Some(sub_prefix) => { - let prefix = - token::multitoken_balance_prefix(token, sub_prefix); - token::multitoken_balance_key(&prefix, dest) - } - None => token::balance_key(token, dest), + None => ( + token::balance_key(token, src), + token::balance_key(token, dest), + ), }; let src_bal: Option = tx::read(&src_key.to_string()); match src_bal { From b0df28b989011b399079ace6043a25560bf19d1d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 5 Sep 2022 09:49:49 +0000 Subject: [PATCH 7/7] [ci skip] wasm checksums update --- wasm/checksums.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 5aff977ad1..4d5f3196e2 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,17 +1,17 @@ { - "tx_bond.wasm": "tx_bond.d8eb4f60b307ff0c0e5ccd76b38dac64aa9c40b32fe222e6180367f8adf61566.wasm", - "tx_from_intent.wasm": "tx_from_intent.a9fec9c3e07acf21676a4559017722c75db0d4e2013d8a24a2413cc1dcf51fbf.wasm", - "tx_ibc.wasm": "tx_ibc.f17dddf05a835f7bcd898ed90f10f4cb64c4b3246b15f4a92fa098c30eacf45e.wasm", + "tx_bond.wasm": "tx_bond.ca09fef16b5566de27ed431899e0efe9050623371f481369b68af32676c850b7.wasm", + "tx_from_intent.wasm": "tx_from_intent.6be622fab8082f4be8180c212a271d7e103d003526c7684b335cbbdbf0329ad1.wasm", + "tx_ibc.wasm": "tx_ibc.ef07534b7cf30af60ebc91f53bab5796647e1fd97cd2e096a60c3e064340abbf.wasm", "tx_init_account.wasm": "tx_init_account.36f85e33e85816c73d24fdae42cef7c80309de05460e78ac5a78024b54d9c90d.wasm", "tx_init_nft.wasm": "tx_init_nft.6e156e65bc19858ade99f91705b475fb9ab9c2641d23cf22db85958cc626146d.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.4e2cc918ea175b29c8b2fcf48865eb6251b8db88799f80226e796d070cd3f2e9.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.bba11610d204f103585016275d96c53c8d7f53d13853def667efa9c245b8b759.wasm", "tx_init_validator.wasm": "tx_init_validator.90c115e298fb7906c83eed0e965c84ce4657a163d828b1a676f231f04cebea2a.wasm", "tx_mint_nft.wasm": "tx_mint_nft.86e54bbefb7b6bc4f189df15943f4b7a9247fa6faf30ebf31c8b450bacae6e08.wasm", - "tx_transfer.wasm": "tx_transfer.40d4409576a238aa447da2a5728cc2c67d0e6896e50f66c76f10f2ab28660d30.wasm", + "tx_transfer.wasm": "tx_transfer.daef631bcc3ceda491dafdea95afa9d912e891c7a166fcd45b33febdac1224c7.wasm", "tx_unbond.wasm": "tx_unbond.b41aadf4b8f1f1b9188de26a54d0cfc1097a69d2e3632548144af46efe988547.wasm", "tx_update_vp.wasm": "tx_update_vp.9a68c44fc97171a8d2218df2b1267dcf9faffb4b12393f72c4a7cc726192a351.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.7053bdd44c9996c3b22d8ef65747e019328f334ed58016f7ff93d0f61d76331d.wasm", - "tx_withdraw.wasm": "tx_withdraw.dccadb23e21d1ac3f19e8c71702f5b896834757d6aa9e7d0acd369f27539dee4.wasm", + "tx_withdraw.wasm": "tx_withdraw.9b1db13df08924f6d94c6a5e982f52522e160b6c57078f9165f7aff8877abade.wasm", "vp_nft.wasm": "vp_nft.08c41172486de46d40e1fe4e38d742f740fc2c91929e183ec69b091907665068.wasm", "vp_testnet_faucet.wasm": "vp_testnet_faucet.1598a5c1a78fc1df8e04c16a247a86b44e003954edc8594f4c73d3d226c1bb6c.wasm", "vp_token.wasm": "vp_token.956607c8a4199be635a2b27799be5f78ae34dab23654c6f8b0ad36501ae740d3.wasm",