From 3afcc1a2dbf2f2a63778beb3adb14d69c369a6ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 11 Oct 2022 16:19:14 +0200 Subject: [PATCH 01/11] add native_token to genesis config --- apps/src/lib/client/utils.rs | 22 +++-- apps/src/lib/config/genesis.rs | 124 +++++++++++++++++++---------- apps/src/lib/wallet/defaults.rs | 18 ++--- genesis/dev.toml | 19 ++--- genesis/e2e-tests-single-node.toml | 1 + 5 files changed, 110 insertions(+), 74 deletions(-) diff --git a/apps/src/lib/client/utils.rs b/apps/src/lib/client/utils.rs index 8848726792..e1f865d5d7 100644 --- a/apps/src/lib/client/utils.rs +++ b/apps/src/lib/client/utils.rs @@ -612,18 +612,16 @@ pub fn init_network( }) } - if let Some(token) = &mut config.token { - token.iter_mut().for_each(|(name, config)| { - if config.address.is_none() { - let address = address::gen_established_address("token"); - config.address = Some(address.to_string()); - wallet.add_address(name.clone(), address); - } - if config.vp.is_none() { - config.vp = Some("vp_token".to_string()); - } - }) - } + config.token.iter_mut().for_each(|(name, config)| { + if config.address.is_none() { + let address = address::gen_established_address("token"); + config.address = Some(address.to_string()); + wallet.add_address(name.clone(), address); + } + if config.vp.is_none() { + config.vp = Some("vp_token".to_string()); + } + }); if let Some(implicit) = &mut config.implicit { implicit.iter_mut().for_each(|(name, config)| { diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index 9425e3b019..e8f5f61fa0 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -104,10 +104,13 @@ pub mod genesis_config { pub struct GenesisConfig { // Genesis timestamp pub genesis_time: Rfc3339String, + // Name of the native token - this must one of the tokens included in + // the `token` field + pub native_token: String, // Initial validator set pub validator: HashMap, // Token accounts present at genesis - pub token: Option>, + pub token: HashMap, // Established accounts present at genesis pub established: Option>, // Implicit accounts present at genesis @@ -479,32 +482,53 @@ pub mod genesis_config { } pub fn load_genesis_config(config: GenesisConfig) -> Genesis { - let wasms = config.wasm; - let validators: HashMap = config - .validator - .iter() - .map(|(name, cfg)| (name.clone(), load_validator(cfg, &wasms))) - .collect(); - let established_accounts: HashMap = config - .established - .unwrap_or_default() + let GenesisConfig { + genesis_time, + native_token, + validator, + token, + established, + implicit, + parameters, + pos_params, + gov_params, + wasm, + } = config; + + let native_token = Address::decode( + token + .get(&native_token) + .expect( + "Native token's alias must be present in the declared \ + tokens", + ) + .address + .as_ref() + .expect("Missing native token address"), + ) + .expect("Invalid address"); + + let validators: HashMap = validator .iter() - .map(|(name, cfg)| (name.clone(), load_established(cfg, &wasms))) + .map(|(name, cfg)| (name.clone(), load_validator(cfg, &wasm))) .collect(); - let implicit_accounts: HashMap = config - .implicit + let established_accounts: HashMap = + established + .unwrap_or_default() + .iter() + .map(|(name, cfg)| (name.clone(), load_established(cfg, &wasm))) + .collect(); + let implicit_accounts: HashMap = implicit .unwrap_or_default() .iter() .map(|(name, cfg)| (name.clone(), load_implicit(cfg))) .collect(); - let token_accounts = config - .token - .unwrap_or_default() + let token_accounts = token .iter() .map(|(_name, cfg)| { load_token( cfg, - &wasms, + &wasm, &validators, &established_accounts, &implicit_accounts, @@ -514,53 +538,66 @@ pub mod genesis_config { let parameters = Parameters { epoch_duration: EpochDuration { - min_num_of_blocks: config.parameters.min_num_of_blocks, + min_num_of_blocks: parameters.min_num_of_blocks, min_duration: namada::types::time::Duration::seconds( - config.parameters.min_duration, + parameters.min_duration, ) .into(), }, max_expected_time_per_block: namada::types::time::Duration::seconds( - config.parameters.max_expected_time_per_block, + parameters.max_expected_time_per_block, ) .into(), - vp_whitelist: config.parameters.vp_whitelist.unwrap_or_default(), - tx_whitelist: config.parameters.tx_whitelist.unwrap_or_default(), + vp_whitelist: parameters.vp_whitelist.unwrap_or_default(), + tx_whitelist: parameters.tx_whitelist.unwrap_or_default(), }; + let GovernanceParamsConfig { + min_proposal_fund, + max_proposal_code_size, + min_proposal_period, + max_proposal_content_size, + min_proposal_grace_epochs, + max_proposal_period, + } = gov_params; let gov_params = GovParams { - min_proposal_fund: config.gov_params.min_proposal_fund, - max_proposal_code_size: config.gov_params.max_proposal_code_size, - min_proposal_period: config.gov_params.min_proposal_period, - max_proposal_period: config.gov_params.max_proposal_period, - max_proposal_content_size: config - .gov_params - .max_proposal_content_size, - min_proposal_grace_epochs: config - .gov_params - .min_proposal_grace_epochs, + min_proposal_fund, + max_proposal_code_size, + min_proposal_period, + max_proposal_content_size, + min_proposal_grace_epochs, + max_proposal_period, }; + let PosParamsConfig { + max_validator_slots, + pipeline_len, + unbonding_len, + votes_per_token, + block_proposer_reward, + block_vote_reward, + duplicate_vote_slash_rate, + light_client_attack_slash_rate, + } = pos_params; let pos_params = PosParams { - max_validator_slots: config.pos_params.max_validator_slots, - pipeline_len: config.pos_params.pipeline_len, - unbonding_len: config.pos_params.unbonding_len, - votes_per_token: BasisPoints::new( - config.pos_params.votes_per_token, - ), - block_proposer_reward: config.pos_params.block_proposer_reward, - block_vote_reward: config.pos_params.block_vote_reward, + max_validator_slots, + pipeline_len, + unbonding_len, + votes_per_token: BasisPoints::new(votes_per_token), + block_proposer_reward, + block_vote_reward, duplicate_vote_slash_rate: BasisPoints::new( - config.pos_params.duplicate_vote_slash_rate, + duplicate_vote_slash_rate, ), light_client_attack_slash_rate: BasisPoints::new( - config.pos_params.light_client_attack_slash_rate, + light_client_attack_slash_rate, ), }; let mut genesis = Genesis { - genesis_time: config.genesis_time.try_into().unwrap(), + genesis_time: genesis_time.try_into().unwrap(), + native_token, validators: validators.into_values().collect(), token_accounts, established_accounts: established_accounts.into_values().collect(), @@ -608,6 +645,7 @@ pub mod genesis_config { #[borsh_init(init)] pub struct Genesis { pub genesis_time: DateTimeUtc, + pub native_token: Address, pub validators: Vec, pub token_accounts: Vec, pub established_accounts: Vec, diff --git a/apps/src/lib/wallet/defaults.rs b/apps/src/lib/wallet/defaults.rs index ad519d64de..03d6c06ca2 100644 --- a/apps/src/lib/wallet/defaults.rs +++ b/apps/src/lib/wallet/defaults.rs @@ -33,16 +33,14 @@ pub fn addresses_from_genesis(genesis: GenesisConfig) -> Vec<(Alias, Address)> { }); addresses.extend(validator_addresses); // Genesis tokens - if let Some(accounts) = genesis.token { - let token_addresses = accounts.into_iter().map(|(alias, token)| { - // The address must be set in the genesis config file - ( - alias.into(), - Address::decode(token.address.unwrap()).unwrap(), - ) - }); - addresses.extend(token_addresses); - } + let token_addresses = genesis.token.into_iter().map(|(alias, token)| { + // The address must be set in the genesis config file + ( + alias.into(), + Address::decode(token.address.unwrap()).unwrap(), + ) + }); + addresses.extend(token_addresses); // Genesis established accounts if let Some(accounts) = genesis.established { let est_addresses = accounts.into_iter().map(|(alias, established)| { diff --git a/genesis/dev.toml b/genesis/dev.toml index fc95244e14..c14390bdff 100644 --- a/genesis/dev.toml +++ b/genesis/dev.toml @@ -1,5 +1,6 @@ # Example genesis with dev settings. genesis_time = "2021-09-30:10:00.00Z" +native_token = "NAM" # A genesis validator with alias "validator". [validator.validator] @@ -26,10 +27,10 @@ net_address = "127.0.0.1:26656" # Some tokens present at genesis. -[token.nam] +[token.NAM] address = "atest1v4ehgw36x3prswzxggunzv6pxqmnvdj9xvcyzvpsggeyvs3cg9qnywf589qnwvfsg5erg3fkl09rg5" vp = "vp_token" -[token.nam.balances] +[token.NAM.balances] # In token balances, we can use: # 1. An address any account a1qyqzsqqqqqcyvvf5xcu5vd6rg4z5233hg9pn23pjgdryzdjy8pz52wzxxscnvvjxx3rryvzz8y5p6mtz = 1000000 @@ -42,28 +43,28 @@ bertha = 1000000 "bertha.public_key" = 100 "validator.public_key" = 100 -[token.btc] +[token.BTC] address = "atest1v4ehgw36xdzryve5gsc52veeg5cnsv2yx5eygvp38qcrvd29xy6rys6p8yc5xvp4xfpy2v694wgwcp" vp = "vp_token" -[token.btc.balances] +[token.BTC.balances] atest1v4ehgw368ycryv2z8qcnxv3cxgmrgvjpxs6yg333gym5vv2zxepnj334g4rryvj9xucrgve4x3xvr4 = 1000000 atest1v4ehgw36x3qng3jzggu5yvpsxgcngv2xgguy2dpkgvu5x33kx3pr2w2zgep5xwfkxscrxs2pj8075p = 1000000 atest1v4ehgw36xvcyyvejgvenxs34g3zygv3jxqunjd6rxyeyys3sxy6rwvfkx4qnj33hg9qnvse4lsfctw = 1000000 a1qyqzsqqqqqcyvvf5xcu5vd6rg4z5233hg9pn23pjgdryzdjy8pz52wzxxscnvvjxx3rryvzz8y5p6mtz = 1000000 -[token.eth] +[token.ETH] address = "atest1v4ehgw36xqmr2d3nx3ryvd2xxgmrq33j8qcns33sxezrgv6zxdzrydjrxveygd2yxumrsdpsf9jc2p" vp = "vp_token" -[token.eth.balances] +[token.ETH.balances] atest1v4ehgw368ycryv2z8qcnxv3cxgmrgvjpxs6yg333gym5vv2zxepnj334g4rryvj9xucrgve4x3xvr4 = 1000000 atest1v4ehgw36x3qng3jzggu5yvpsxgcngv2xgguy2dpkgvu5x33kx3pr2w2zgep5xwfkxscrxs2pj8075p = 1000000 atest1v4ehgw36xvcyyvejgvenxs34g3zygv3jxqunjd6rxyeyys3sxy6rwvfkx4qnj33hg9qnvse4lsfctw = 1000000 a1qyqzsqqqqqcyvvf5xcu5vd6rg4z5233hg9pn23pjgdryzdjy8pz52wzxxscnvvjxx3rryvzz8y5p6mtz = 1000000 -[token.dot] +[token.DOT] address = "atest1v4ehgw36gg6nvs2zgfpyxsfjgc65yv6pxy6nwwfsxgungdzrggeyzv35gveyxsjyxymyz335hur2jn" vp = "vp_token" -[token.dot.balances] +[token.DOT.balances] atest1v4ehgw368ycryv2z8qcnxv3cxgmrgvjpxs6yg333gym5vv2zxepnj334g4rryvj9xucrgve4x3xvr4 = 1000000 atest1v4ehgw36x3qng3jzggu5yvpsxgcngv2xgguy2dpkgvu5x33kx3pr2w2zgep5xwfkxscrxs2pj8075p = 1000000 atest1v4ehgw36xvcyyvejgvenxs34g3zygv3jxqunjd6rxyeyys3sxy6rwvfkx4qnj33hg9qnvse4lsfctw = 1000000 @@ -168,7 +169,7 @@ light_client_attack_slash_rate = 500 # Governance parameters. [gov_params] -# minimum amount of nam token to lock +# minimum amount of NAM token to lock min_proposal_fund = 500 # proposal code size in bytes max_proposal_code_size = 300000 diff --git a/genesis/e2e-tests-single-node.toml b/genesis/e2e-tests-single-node.toml index 95e51173c6..f327af7eaa 100644 --- a/genesis/e2e-tests-single-node.toml +++ b/genesis/e2e-tests-single-node.toml @@ -3,6 +3,7 @@ # - User accounts same as the ones in "dev" build (Albert, Bertha, Christel) genesis_time = "2021-09-30T10:00:00Z" +native_token = "XAN" [validator.validator-0] # Validator's staked NAM at genesis. From 858b5e98fbc12ea5e6c04da346fca72a3770e30e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 11 Oct 2022 18:23:56 +0200 Subject: [PATCH 02/11] add native_token to Shell and cli::Context and use it --- apps/src/lib/cli/context.rs | 13 +++++++++---- apps/src/lib/client/tx.rs | 4 ++-- apps/src/lib/node/ledger/mod.rs | 6 ++++++ apps/src/lib/node/ledger/shell/finalize_block.rs | 10 +++++----- apps/src/lib/node/ledger/shell/init_chain.rs | 2 +- apps/src/lib/node/ledger/shell/mod.rs | 9 ++++++++- .../lib/node/ledger/shell/prepare_proposal.rs | 4 ++-- .../lib/node/ledger/shell/process_proposal.rs | 16 ++++++++-------- apps/src/lib/node/ledger/shims/abcipp_shim.rs | 3 +++ shared/src/ledger/governance/vp.rs | 6 +++--- 10 files changed, 47 insertions(+), 26 deletions(-) diff --git a/apps/src/lib/cli/context.rs b/apps/src/lib/cli/context.rs index fc6db9633b..36a8d66753 100644 --- a/apps/src/lib/cli/context.rs +++ b/apps/src/lib/cli/context.rs @@ -47,6 +47,8 @@ pub struct Context { pub global_config: GlobalConfig, /// The ledger configuration for a specific chain ID pub config: Config, + /// Native token's address + pub native_token: Address, } impl Context { @@ -66,10 +68,12 @@ impl Context { let genesis_file_path = global_args .base_dir .join(format!("{}.toml", global_config.default_chain_id.as_str())); - let wallet = Wallet::load_or_new_from_genesis( - &chain_dir, - genesis_config::open_genesis_config(&genesis_file_path)?, - ); + let genesis = genesis_config::read_genesis_config(&genesis_file_path); + let native_token = genesis.native_token; + let default_genesis = + genesis_config::open_genesis_config(genesis_file_path)?; + let wallet = + Wallet::load_or_new_from_genesis(&chain_dir, default_genesis); // If the WASM dir specified, put it in the config match global_args.wasm_dir.as_ref() { @@ -88,6 +92,7 @@ impl Context { wallet, global_config, config, + native_token, }) } diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index ab302fef1b..6e5a390070 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -23,7 +23,7 @@ use namada::types::transaction::governance::{ }; use namada::types::transaction::nft::{CreateNft, MintNft}; use namada::types::transaction::{pos, InitAccount, InitValidator, UpdateVp}; -use namada::types::{address, storage, token}; +use namada::types::{storage, token}; use namada::{ledger, vm}; use super::rpc; @@ -911,7 +911,7 @@ pub async fn submit_bond(ctx: Context, args: args::Bond) { // Check bond's source (source for delegation or validator for self-bonds) // balance let bond_source = source.as_ref().unwrap_or(&validator); - let balance_key = token::balance_key(&address::nam(), bond_source); + let balance_key = token::balance_key(&ctx.native_token, bond_source); let client = HttpClient::new(args.tx.ledger_address.clone()).unwrap(); match rpc::query_storage_value::(&client, &balance_key).await { diff --git a/apps/src/lib/node/ledger/mod.rs b/apps/src/lib/node/ledger/mod.rs index dc0dfc184c..2f09d02db9 100644 --- a/apps/src/lib/node/ledger/mod.rs +++ b/apps/src/lib/node/ledger/mod.rs @@ -30,6 +30,7 @@ use crate::config::TendermintMode; use crate::facade::tendermint_proto::abci::CheckTxType; use crate::facade::tower_abci::{response, split, Server}; use crate::node::ledger::broadcaster::Broadcaster; +use crate::node::ledger::config::genesis; use crate::node::ledger::shell::{Error, MempoolTxType, Shell}; use crate::node::ledger::shims::abcipp_shim::AbcippShim; use crate::node::ledger::shims::abcipp_shim_types::shim::{Request, Response}; @@ -423,6 +424,10 @@ fn start_abci_broadcaster_shell( // Construct our ABCI application. let tendermint_mode = config.tendermint.tendermint_mode.clone(); let ledger_address = config.shell.ledger_address; + #[cfg(not(feature = "dev"))] + let genesis = genesis::genesis(&config.shell.base_dir, &config.chain_id); + #[cfg(feature = "dev")] + let genesis = genesis::genesis(); let (shell, abci_service) = AbcippShim::new( config, wasm_dir, @@ -430,6 +435,7 @@ fn start_abci_broadcaster_shell( &db_cache, vp_wasm_compilation_cache, tx_wasm_compilation_cache, + genesis.native_token, ); // Channel for signalling shut down to ABCI server diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 098719dc96..47fe6e9fdd 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -349,7 +349,7 @@ mod test_finalize_block { let wrapper = WrapperTx::new( Fee { amount: i.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -420,7 +420,7 @@ mod test_finalize_block { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -472,7 +472,7 @@ mod test_finalize_block { let wrapper = WrapperTx { fee: Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, pk: keypair.ref_to(), epoch: Epoch(0), @@ -538,7 +538,7 @@ mod test_finalize_block { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -569,7 +569,7 @@ mod test_finalize_block { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index d556fc1afd..63f1aa5aa6 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -222,7 +222,7 @@ where // Account balance (tokens no staked in PoS) self.storage .write( - &token::balance_key(&address::nam(), addr), + &token::balance_key(&self.native_token, addr), validator .non_staked_balance .try_to_vec() diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index f095d5edb7..9550c367e8 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -32,6 +32,7 @@ use namada::ledger::storage::{ }; use namada::ledger::{ibc, pos}; use namada::proto::{self, Tx}; +use namada::types::address::Address; use namada::types::chain::ChainId; use namada::types::key::*; use namada::types::storage::{BlockHeight, Key}; @@ -192,6 +193,8 @@ where /// The id of the current chain #[allow(dead_code)] chain_id: ChainId, + /// The address of the native token + native_token: Address, /// The persistent storage pub(super) storage: Storage, /// Gas meter for the current block @@ -231,6 +234,7 @@ where db_cache: Option<&D::Cache>, vp_wasm_compilation_cache: u64, tx_wasm_compilation_cache: u64, + native_token: Address, ) -> Self { let chain_id = config.chain_id; let db_path = config.shell.db_dir(&chain_id); @@ -304,6 +308,7 @@ where Self { chain_id, + native_token, storage, gas_meter: BlockGasMeter::default(), write_log: WriteLog::default(), @@ -840,6 +845,7 @@ mod test_utils { let (sender, _) = tokio::sync::mpsc::unbounded_channel(); let vp_wasm_compilation_cache = 50 * 1024 * 1024; // 50 kiB let tx_wasm_compilation_cache = 50 * 1024 * 1024; // 50 kiB + let native_token = address::nam(); let mut shell = Shell::::new( config::Ledger::new( base_dir.clone(), @@ -851,6 +857,7 @@ mod test_utils { None, vp_wasm_compilation_cache, tx_wasm_compilation_cache, + native_token.clone(), ); let keypair = gen_keypair(); // enqueue a wrapper tx @@ -861,7 +868,7 @@ mod test_utils { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: native_token.clone(), }, &keypair, Epoch(0), diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index 6251740181..71f27320c3 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -189,7 +189,7 @@ mod test_prepare_proposal { WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -244,7 +244,7 @@ mod test_prepare_proposal { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index c3938b327c..463f79ffac 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -217,7 +217,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -264,7 +264,7 @@ mod test_process_proposal { let mut wrapper = WrapperTx::new( Fee { amount: 100.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -346,7 +346,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 1.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -399,7 +399,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: Amount::whole(1_000_100), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -447,7 +447,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: i.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -511,7 +511,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -570,7 +570,7 @@ mod test_process_proposal { let mut wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, &keypair, Epoch(0), @@ -623,7 +623,7 @@ mod test_process_proposal { let wrapper = WrapperTx { fee: Fee { amount: 0.into(), - token: nam(), + token: shell.native_token.clone(), }, pk: keypair.ref_to(), epoch: Epoch(0), diff --git a/apps/src/lib/node/ledger/shims/abcipp_shim.rs b/apps/src/lib/node/ledger/shims/abcipp_shim.rs index e919610f8e..76fbd34d24 100644 --- a/apps/src/lib/node/ledger/shims/abcipp_shim.rs +++ b/apps/src/lib/node/ledger/shims/abcipp_shim.rs @@ -5,6 +5,7 @@ use std::pin::Pin; use std::task::{Context, Poll}; use futures::future::FutureExt; +use namada::types::address::Address; #[cfg(not(feature = "abcipp"))] use namada::types::hash::Hash; #[cfg(not(feature = "abcipp"))] @@ -50,6 +51,7 @@ impl AbcippShim { db_cache: &rocksdb::Cache, vp_wasm_compilation_cache: u64, tx_wasm_compilation_cache: u64, + native_token: Address, ) -> (Self, AbciService) { // We can use an unbounded channel here, because tower-abci limits the // the number of requests that can come in @@ -63,6 +65,7 @@ impl AbcippShim { Some(db_cache), vp_wasm_compilation_cache, tx_wasm_compilation_cache, + native_token, ), #[cfg(not(feature = "abcipp"))] begin_block_request: None, diff --git a/shared/src/ledger/governance/vp.rs b/shared/src/ledger/governance/vp.rs index c01e9d56bd..9114283959 100644 --- a/shared/src/ledger/governance/vp.rs +++ b/shared/src/ledger/governance/vp.rs @@ -8,7 +8,7 @@ use crate::ledger::native_vp::{self, Ctx}; use crate::ledger::pos::{self as pos_storage, BondId, Bonds}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; use crate::ledger::vp_env::VpEnv; -use crate::types::address::{nam, Address, InternalAddress}; +use crate::types::address::{self, Address, InternalAddress}; use crate::types::storage::{Epoch, Key}; use crate::types::token; use crate::vm::WasmCacheAccess; @@ -53,7 +53,7 @@ where H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - let balance_key = token::balance_key(&nam(), &ADDRESS); + let balance_key = token::balance_key(&address::nam(), &ADDRESS); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); @@ -164,7 +164,7 @@ where CA: 'static + WasmCacheAccess, { let funds_key = gov_storage::get_funds_key(proposal_id); - let balance_key = token::balance_key(&nam(), &ADDRESS); + let balance_key = token::balance_key(&address::nam(), &ADDRESS); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); From 78d9860bd011935454112896946e8d7638237b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 25 Oct 2022 12:29:10 +0200 Subject: [PATCH 03/11] add native_token to storage and `StorageRead::get_native_token` --- apps/src/lib/node/ledger/shell/init_chain.rs | 2 +- apps/src/lib/node/ledger/shell/mod.rs | 6 +-- shared/src/ledger/native_vp.rs | 8 ++++ shared/src/ledger/storage/mod.rs | 13 ++++++ shared/src/ledger/storage_api/mod.rs | 4 ++ shared/src/ledger/vp_env.rs | 14 ++++++ shared/src/vm/host_env.rs | 47 +++++++++++++++++++- shared/src/vm/wasm/host_env.rs | 2 + tx_prelude/src/lib.rs | 13 ++++++ vm_env/src/lib.rs | 6 +++ vp_prelude/src/lib.rs | 18 ++++++++ 11 files changed, 127 insertions(+), 6 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index 63f1aa5aa6..f29b824efd 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -222,7 +222,7 @@ where // Account balance (tokens no staked in PoS) self.storage .write( - &token::balance_key(&self.native_token, addr), + &token::balance_key(&self.storage.native_token, addr), validator .non_staked_balance .try_to_vec() diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 9550c367e8..d2423b70cd 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -193,8 +193,6 @@ where /// The id of the current chain #[allow(dead_code)] chain_id: ChainId, - /// The address of the native token - native_token: Address, /// The persistent storage pub(super) storage: Storage, /// Gas meter for the current block @@ -245,7 +243,8 @@ where .expect("Creating directory for Anoma should not fail"); } // load last state from storage - let mut storage = Storage::open(db_path, chain_id.clone(), db_cache); + let mut storage = + Storage::open(db_path, chain_id.clone(), native_token, db_cache); storage .load_last_state() .map_err(|e| { @@ -308,7 +307,6 @@ where Self { chain_id, - native_token, storage, gas_meter: BlockGasMeter::default(), write_log: WriteLog::default(), diff --git a/shared/src/ledger/native_vp.rs b/shared/src/ledger/native_vp.rs index 2b7d41e795..1f83f42c42 100644 --- a/shared/src/ledger/native_vp.rs +++ b/shared/src/ledger/native_vp.rs @@ -228,6 +228,10 @@ where fn get_block_epoch(&self) -> Result { self.ctx.get_block_epoch() } + + fn get_native_token(&self) -> Result { + Ok(self.ctx.storage.native_token.clone()) + } } impl<'view, 'a, DB, H, CA> StorageRead<'view> @@ -309,6 +313,10 @@ where fn get_block_epoch(&self) -> Result { self.ctx.get_block_epoch() } + + fn get_native_token(&self) -> Result { + Ok(self.ctx.storage.native_token.clone()) + } } impl<'view, 'a: 'view, DB, H, CA> VpEnv<'view> for Ctx<'a, DB, H, CA> diff --git a/shared/src/ledger/storage/mod.rs b/shared/src/ledger/storage/mod.rs index 16c3ecf180..44751fa5a6 100644 --- a/shared/src/ledger/storage/mod.rs +++ b/shared/src/ledger/storage/mod.rs @@ -52,6 +52,9 @@ where pub db: D, /// The ID of the chain pub chain_id: ChainId, + /// The address of the native token - this is not stored in DB, but read + /// from genesis + pub native_token: Address, /// The storage for the current (yet to be committed) block pub block: BlockStorage, /// The latest block header @@ -279,6 +282,7 @@ where pub fn open( db_path: impl AsRef, chain_id: ChainId, + native_token: Address, cache: Option<&D::Cache>, ) -> Self { let block = BlockStorage { @@ -302,6 +306,7 @@ where ), #[cfg(feature = "ferveo-tpke")] tx_queue: TxQueue::default(), + native_token, } } @@ -789,6 +794,12 @@ where ) -> std::result::Result { Ok(self.block.epoch) } + + fn get_native_token( + &self, + ) -> std::result::Result { + Ok(self.native_token.clone()) + } } impl StorageWrite for Storage @@ -879,6 +890,7 @@ pub mod testing { use super::mockdb::MockDB; use super::*; use crate::ledger::storage::traits::Sha256Hasher; + use crate::types::address; /// Storage with a mock DB for testing pub type TestStorage = Storage; @@ -907,6 +919,7 @@ pub mod testing { ), #[cfg(feature = "ferveo-tpke")] tx_queue: TxQueue::default(), + native_token: address::nam(), } } } diff --git a/shared/src/ledger/storage_api/mod.rs b/shared/src/ledger/storage_api/mod.rs index b806f35801..fbef8742ac 100644 --- a/shared/src/ledger/storage_api/mod.rs +++ b/shared/src/ledger/storage_api/mod.rs @@ -8,6 +8,7 @@ pub mod validation; use borsh::{BorshDeserialize, BorshSerialize}; pub use error::{CustomError, Error, OptionExt, Result, ResultExt}; +use crate::types::address::Address; use crate::types::storage::{self, BlockHash, BlockHeight, Epoch}; /// Common storage read interface @@ -96,6 +97,9 @@ pub trait StorageRead<'iter> { /// Getting the block epoch. The epoch is that of the block to which the /// current transaction is being applied. fn get_block_epoch(&self) -> Result; + + /// Get the native token address + fn get_native_token(&self) -> Result
; } /// Common storage write interface diff --git a/shared/src/ledger/vp_env.rs b/shared/src/ledger/vp_env.rs index 3f1b22ddc6..0172f986c5 100644 --- a/shared/src/ledger/vp_env.rs +++ b/shared/src/ledger/vp_env.rs @@ -13,6 +13,7 @@ use crate::ledger::gas::VpGasMeter; use crate::ledger::storage::write_log::WriteLog; use crate::ledger::storage::{self, write_log, Storage, StorageHasher}; use crate::proto::Tx; +use crate::types::address::Address; use crate::types::hash::Hash; use crate::types::key::common; use crate::types::storage::{BlockHash, BlockHeight, Epoch, Key}; @@ -434,6 +435,19 @@ where Ok(epoch) } +/// Getting the chain ID. +pub fn get_native_token( + gas_meter: &mut VpGasMeter, + storage: &Storage, +) -> EnvResult
+where + DB: storage::DB + for<'iter> storage::DBIter<'iter>, + H: StorageHasher, +{ + add_gas(gas_meter, MIN_STORAGE_GAS)?; + Ok(storage.native_token.clone()) +} + /// Storage prefix iterator, ordered by storage keys. It will try to get an /// iterator from the storage. pub fn iter_prefix<'a, DB, H>( diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs index 1ac0754e25..cf522b786c 100644 --- a/shared/src/vm/host_env.rs +++ b/shared/src/vm/host_env.rs @@ -12,7 +12,7 @@ use super::wasm::TxCache; #[cfg(feature = "wasm-runtime")] use super::wasm::VpCache; use super::WasmCacheAccess; -use crate::ledger::gas::{self, BlockGasMeter, VpGasMeter}; +use crate::ledger::gas::{self, BlockGasMeter, VpGasMeter, MIN_STORAGE_GAS}; use crate::ledger::storage::write_log::{self, WriteLog}; use crate::ledger::storage::{self, Storage, StorageHasher}; use crate::ledger::vp_env; @@ -1555,6 +1555,28 @@ where Ok(epoch.0) } +/// Get the native token's address +pub fn tx_get_native_token( + env: &TxVmEnv, + result_ptr: u64, +) -> TxResult<()> +where + MEM: VmMemory, + DB: storage::DB + for<'iter> storage::DBIter<'iter>, + H: StorageHasher, + CA: WasmCacheAccess, +{ + let storage = unsafe { env.ctx.storage.get() }; + tx_add_gas(env, MIN_STORAGE_GAS)?; + let native_token = storage.native_token.clone(); + let native_token_bytes = native_token.try_to_vec().unwrap(); + let gas = env + .memory + .write_bytes(result_ptr, native_token_bytes) + .map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?; + tx_add_gas(env, gas) +} + /// Getting the chain ID function exposed to the wasm VM VP environment. pub fn vp_get_chain_id( env: &VpVmEnv, @@ -1804,6 +1826,29 @@ where .to_i64()) } +/// Get the native token's address +pub fn vp_get_native_token( + env: &VpVmEnv, + result_ptr: u64, +) -> vp_env::EnvResult<()> +where + MEM: VmMemory, + DB: storage::DB + for<'iter> storage::DBIter<'iter>, + H: StorageHasher, + EVAL: VpEvaluator, + CA: WasmCacheAccess, +{ + let gas_meter = unsafe { env.ctx.gas_meter.get() }; + let storage = unsafe { env.ctx.storage.get() }; + let native_token = vp_env::get_native_token(gas_meter, storage)?; + let native_token_bytes = native_token.try_to_vec().unwrap(); + let gas = env + .memory + .write_bytes(result_ptr, native_token_bytes) + .map_err(|e| vp_env::RuntimeError::MemoryError(Box::new(e)))?; + vp_env::add_gas(gas_meter, gas) +} + /// Log a string from exposed to the wasm VM VP environment. The message will be /// printed at the [`tracing::Level::INFO`]. This function is for development /// only. diff --git a/shared/src/vm/wasm/host_env.rs b/shared/src/vm/wasm/host_env.rs index 06d45fa4f9..7c94b9390d 100644 --- a/shared/src/vm/wasm/host_env.rs +++ b/shared/src/vm/wasm/host_env.rs @@ -78,6 +78,7 @@ where "anoma_tx_get_block_time" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_time), "anoma_tx_get_block_hash" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_hash), "anoma_tx_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_block_epoch), + "anoma_tx_get_native_token" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_get_native_token), "anoma_tx_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_log_string), }, } @@ -118,6 +119,7 @@ where "anoma_vp_get_block_epoch" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_block_epoch), "anoma_vp_verify_tx_signature" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_verify_tx_signature), "anoma_vp_eval" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_eval), + "anoma_vp_get_native_token" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_native_token), "anoma_vp_log_string" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_log_string), }, } diff --git a/tx_prelude/src/lib.rs b/tx_prelude/src/lib.rs index 730adb3155..3909793f6f 100644 --- a/tx_prelude/src/lib.rs +++ b/tx_prelude/src/lib.rs @@ -168,6 +168,19 @@ impl StorageRead<'_> for Ctx { Ok(Epoch(unsafe { anoma_tx_get_block_epoch() })) } + /// Get the native token address + fn get_native_token(&self) -> Result { + let result = Vec::with_capacity(address::ADDRESS_LEN); + unsafe { + anoma_tx_get_native_token(result.as_ptr() as _); + } + let slice = unsafe { + slice::from_raw_parts(result.as_ptr(), address::ADDRESS_LEN) + }; + Ok(Address::try_from_slice(slice) + .expect("Cannot decode native address")) + } + fn iter_prefix( &self, prefix: &namada::types::storage::Key, diff --git a/vm_env/src/lib.rs b/vm_env/src/lib.rs index 1421dbde48..62212fd5e8 100644 --- a/vm_env/src/lib.rs +++ b/vm_env/src/lib.rs @@ -101,6 +101,9 @@ pub mod tx { // Get the current block epoch pub fn anoma_tx_get_block_epoch() -> u64; + // Get the native token address + pub fn anoma_tx_get_native_token(result_ptr: u64); + // Requires a node running with "Info" log level pub fn anoma_tx_log_string(str_ptr: u64, str_len: u64); } @@ -181,6 +184,9 @@ pub mod vp { // Get the current block epoch pub fn anoma_vp_get_block_epoch() -> u64; + // Get the native token address + pub fn anoma_vp_get_native_token(result_ptr: u64); + // Verify a transaction signature pub fn anoma_vp_verify_tx_signature( pk_ptr: u64, diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs index e6618bc5de..a302bb5ac3 100644 --- a/vp_prelude/src/lib.rs +++ b/vp_prelude/src/lib.rs @@ -361,6 +361,10 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { fn get_block_epoch(&self) -> Result { get_block_epoch() } + + fn get_native_token(&self) -> Result { + get_native_token() + } } impl StorageRead<'_> for CtxPostStorageRead<'_> { @@ -422,6 +426,10 @@ impl StorageRead<'_> for CtxPostStorageRead<'_> { fn get_block_epoch(&self) -> Result { get_block_epoch() } + + fn get_native_token(&self) -> Result { + get_native_token() + } } fn iter_prefix_impl( @@ -474,3 +482,13 @@ fn get_block_hash() -> Result { fn get_block_epoch() -> Result { Ok(Epoch(unsafe { anoma_vp_get_block_epoch() })) } + +fn get_native_token() -> Result { + let result = Vec::with_capacity(address::ADDRESS_LEN); + unsafe { + anoma_vp_get_native_token(result.as_ptr() as _); + } + let slice = + unsafe { slice::from_raw_parts(result.as_ptr(), address::ADDRESS_LEN) }; + Ok(Address::try_from_slice(slice).expect("Cannot decode native address")) +} From 4416df66cf9ddbdadf680bbd4f0c1e78587d63ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 25 Oct 2022 12:40:14 +0200 Subject: [PATCH 04/11] PoS: replace hard-coded staking token address --- proof_of_stake/src/lib.rs | 16 ++++++---------- shared/src/ledger/pos/mod.rs | 11 +++-------- shared/src/ledger/pos/storage.rs | 4 ++-- shared/src/ledger/pos/vp.rs | 15 ++++++++------- tests/src/native_vp/pos.rs | 11 +++++------ 5 files changed, 24 insertions(+), 33 deletions(-) diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 6e5f4e2196..66a026e6f3 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -101,9 +101,7 @@ pub trait PosReadOnly { const POS_ADDRESS: Self::Address; /// Address of the staking token - /// TODO: this should be `const`, but in the ledger `address::nam` is not a - /// `const fn` - fn staking_token_address() -> Self::Address; + fn staking_token_address(&self) -> Self::Address; /// Read PoS parameters. fn read_pos_params(&self) -> Result; @@ -375,7 +373,7 @@ pub trait PosActions: PosReadOnly { // Transfer the bonded tokens from the source to PoS self.transfer( - &Self::staking_token_address(), + &self.staking_token_address(), amount, source, &Self::POS_ADDRESS, @@ -505,7 +503,7 @@ pub trait PosActions: PosReadOnly { // Transfer the tokens from PoS back to the source self.transfer( - &Self::staking_token_address(), + &self.staking_token_address(), withdrawn, &Self::POS_ADDRESS, source, @@ -577,9 +575,7 @@ pub trait PosBase { /// Address of the PoS account const POS_ADDRESS: Self::Address; /// Address of the staking token - /// TODO: this should be `const`, but in the ledger `address::nam` is not a - /// `const fn` - fn staking_token_address() -> Self::Address; + fn staking_token_address(&self) -> Self::Address; /// Address of the slash pool, into which slashed tokens are transferred. const POS_SLASH_POOL_ADDRESS: Self::Address; @@ -759,7 +755,7 @@ pub trait PosBase { self.write_total_voting_power(&total_voting_power); // Credit the bonded tokens to the PoS account self.credit_tokens( - &Self::staking_token_address(), + &self.staking_token_address(), &Self::POS_ADDRESS, total_bonded_balance, ); @@ -934,7 +930,7 @@ pub trait PosBase { self.write_total_voting_power(&total_voting_power); // Transfer the slashed tokens to the PoS slash pool self.transfer( - &Self::staking_token_address(), + &self.staking_token_address(), slashed_amount, &Self::POS_ADDRESS, &Self::POS_SLASH_POOL_ADDRESS, diff --git a/shared/src/ledger/pos/mod.rs b/shared/src/ledger/pos/mod.rs index 0b1617c7c3..1c8742c4f6 100644 --- a/shared/src/ledger/pos/mod.rs +++ b/shared/src/ledger/pos/mod.rs @@ -15,7 +15,7 @@ pub use vp::PosVP; use super::storage_api; use crate::ledger::storage::{self as ledger_storage, Storage, StorageHasher}; -use crate::types::address::{self, Address, InternalAddress}; +use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Epoch; use crate::types::{key, token}; @@ -26,11 +26,6 @@ pub const ADDRESS: Address = Address::Internal(InternalAddress::PoS); pub const SLASH_POOL_ADDRESS: Address = Address::Internal(InternalAddress::PosSlashPool); -/// Address of the staking token (NAM) -pub fn staking_token_address() -> Address { - address::nam() -} - /// Initialize storage in the genesis block. pub fn init_genesis_storage<'a, DB, H>( storage: &mut Storage, @@ -157,8 +152,8 @@ mod macros { const POS_ADDRESS: Self::Address = $crate::ledger::pos::ADDRESS; - fn staking_token_address() -> Self::Address { - $crate::ledger::pos::staking_token_address() + fn staking_token_address(&self) -> Self::Address { + self.get_native_token().expect("Native token must be available") } fn read_pos_params(&self) -> std::result::Result { diff --git a/shared/src/ledger/pos/storage.rs b/shared/src/ledger/pos/storage.rs index 366ce489b5..8d65dba1fc 100644 --- a/shared/src/ledger/pos/storage.rs +++ b/shared/src/ledger/pos/storage.rs @@ -379,8 +379,8 @@ where const POS_ADDRESS: Self::Address = super::ADDRESS; const POS_SLASH_POOL_ADDRESS: Self::Address = super::SLASH_POOL_ADDRESS; - fn staking_token_address() -> Self::Address { - super::staking_token_address() + fn staking_token_address(&self) -> Self::Address { + self.native_token.clone() } fn read_pos_params(&self) -> PosParams { diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index 60264e4926..a293044db0 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -19,12 +19,12 @@ use super::{ bond_key, is_bond_key, is_params_key, is_total_voting_power_key, is_unbond_key, is_validator_set_key, is_validator_staking_reward_address_key, is_validator_total_deltas_key, - is_validator_voting_power_key, params_key, staking_token_address, - total_voting_power_key, unbond_key, validator_consensus_key_key, - validator_set_key, validator_slashes_key, - validator_staking_reward_address_key, validator_state_key, - validator_total_deltas_key, validator_voting_power_key, BondId, Bonds, - Unbonds, ValidatorConsensusKeys, ValidatorSets, ValidatorTotalDeltas, + is_validator_voting_power_key, params_key, total_voting_power_key, + unbond_key, validator_consensus_key_key, validator_set_key, + validator_slashes_key, validator_staking_reward_address_key, + validator_state_key, validator_total_deltas_key, + validator_voting_power_key, BondId, Bonds, Unbonds, ValidatorConsensusKeys, + ValidatorSets, ValidatorTotalDeltas, }; use crate::impl_pos_read_only; use crate::ledger::governance::vp::is_proposal_accepted; @@ -122,6 +122,7 @@ where let addr = Address::Internal(Self::ADDR); let mut changes: Vec> = vec![]; let current_epoch = self.ctx.pre().get_block_epoch()?; + let staking_token_address = self.ctx.pre().get_native_token()?; for key in keys_changed { if is_params_key(key) { @@ -214,7 +215,7 @@ where data: Data { pre, post }, }); } else if let Some(owner) = - token::is_balance_key(&staking_token_address(), key) + token::is_balance_key(&staking_token_address, key) { if owner != &addr { continue; diff --git a/tests/src/native_vp/pos.rs b/tests/src/native_vp/pos.rs index ec6f75a15f..00a57b4683 100644 --- a/tests/src/native_vp/pos.rs +++ b/tests/src/native_vp/pos.rs @@ -101,9 +101,7 @@ use namada::ledger::pos::namada_proof_of_stake::PosBase; use namada::types::storage::Epoch; -use namada_tx_prelude::proof_of_stake::{ - staking_token_address, GenesisValidator, PosParams, -}; +use namada_tx_prelude::proof_of_stake::{GenesisValidator, PosParams}; use crate::tx::tx_host_env; @@ -119,7 +117,8 @@ pub fn init_pos( tx_host_env::with(|tx_env| { // Ensure that all the used // addresses exist - tx_env.spawn_accounts([&staking_token_address()]); + let native_token = tx_env.storage.native_token.clone(); + tx_env.spawn_accounts([&native_token]); for validator in genesis_validators { tx_env.spawn_accounts([ &validator.address, @@ -587,7 +586,7 @@ pub mod testing { WeightedValidator, }; use namada_tx_prelude::proof_of_stake::{ - staking_token_address, BondId, Bonds, PosParams, Unbonds, + BondId, Bonds, PosParams, Unbonds, }; use namada_tx_prelude::{Address, StorageRead, StorageWrite}; use proptest::prelude::*; @@ -1478,7 +1477,7 @@ pub mod testing { } PosStorageChange::StakingTokenPosBalance { delta } => { let balance_key = token::balance_key( - &staking_token_address(), + &tx::ctx().get_native_token().unwrap(), &::POS_ADDRESS, ); let mut balance: token::Amount = From 4c9e7272547de6eb0cd705a850219bbf347e016b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 25 Oct 2022 12:54:10 +0200 Subject: [PATCH 05/11] gov: replace hard-coded nam with native token --- apps/src/lib/client/tx.rs | 12 ++-- apps/src/lib/node/ledger/shell/governance.rs | 12 ++-- shared/src/ledger/governance/mod.rs | 69 ++++++++++---------- shared/src/ledger/governance/vp.rs | 25 ++++--- tx_prelude/src/governance.rs | 3 +- 5 files changed, 68 insertions(+), 53 deletions(-) diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 6e5a390070..af884bd916 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -11,7 +11,7 @@ use itertools::Either::*; use namada::ledger::governance::storage as gov_storage; use namada::ledger::pos::{BondId, Bonds, Unbonds}; use namada::proto::Tx; -use namada::types::address::{nam, Address}; +use namada::types::address::Address; use namada::types::governance::{ OfflineProposal, OfflineVote, Proposal, ProposalVote, }; @@ -639,9 +639,13 @@ pub async fn submit_init_proposal(mut ctx: Context, args: args::InitProposal) { safe_exit(1) }; - let balance = rpc::get_token_balance(&client, &nam(), &proposal.author) - .await - .unwrap_or_default(); + let balance = rpc::get_token_balance( + &client, + &ctx.native_token, + &proposal.author, + ) + .await + .unwrap_or_default(); if balance < token::Amount::from(governance_parameters.min_proposal_fund) { diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 828ff05524..90fd22f04b 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -6,7 +6,7 @@ use namada::ledger::governance::vp::ADDRESS as gov_address; use namada::ledger::slash_fund::ADDRESS as slash_fund_address; use namada::ledger::storage::types::encode; use namada::ledger::storage::{DBIter, StorageHasher, DB}; -use namada::types::address::{nam, Address}; +use namada::types::address::Address; use namada::types::governance::TallyResult; use namada::types::storage::Epoch; use namada::types::token; @@ -176,10 +176,14 @@ where } }; + let native_token = shell.storage.native_token.clone(); // transfer proposal locked funds - shell - .storage - .transfer(&nam(), funds, &gov_address, &transfer_address); + shell.storage.transfer( + &native_token, + funds, + &gov_address, + &transfer_address, + ); } Ok(proposals_result) diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index a4e0c80211..38e9ed86fc 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -15,9 +15,10 @@ use std::collections::BTreeSet; pub use vp::Result; use self::storage as gov_storage; +use super::storage_api::StorageRead; use crate::ledger::native_vp::{Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::types::address::{nam, Address, InternalAddress}; +use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::token as token_storage; use crate::vm::WasmCacheAccess; @@ -55,10 +56,11 @@ where return Ok(false); }; + let native_token = self.ctx.pre().get_native_token()?; let result = keys_changed.iter().all(|key| { let proposal_id = gov_storage::get_proposal_id(key); - let key_type: KeyType = key.into(); + let key_type: KeyType = get_key_type(key, &native_token); match (key_type, proposal_id) { (KeyType::VOTE(validate), Some(proposal_id)) => { validate(&self.ctx, proposal_id, key, verifiers) @@ -206,41 +208,42 @@ where UNKNOWN(fn() -> bool), } -impl<'a, DB, H, CA> From<&Key> for KeyType<'a, DB, H, CA> +fn get_key_type<'a, DB, H, CA>( + value: &Key, + native_token: &Address, +) -> KeyType<'a, DB, H, CA> where DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - fn from(value: &Key) -> Self { - if gov_storage::is_vote_key(value) { - KeyType::VOTE(vp::validate_vote_key) - } else if gov_storage::is_content_key(value) { - KeyType::CONTENT(vp::validate_content_key) - } else if gov_storage::is_proposal_code_key(value) { - KeyType::PROPOSAL_CODE(vp::validate_proposal_code_key) - } else if gov_storage::is_grace_epoch_key(value) { - KeyType::GRACE_EPOCH(vp::validate_grace_epoch_key) - } else if gov_storage::is_start_epoch_key(value) { - KeyType::START_EPOCH(vp::validate_start_epoch_key) - } else if gov_storage::is_commit_proposal_key(value) { - KeyType::PROPOSAL_COMMIT(vp::validate_commit_key) - } else if gov_storage::is_end_epoch_key(value) { - KeyType::END_EPOCH(vp::validate_end_epoch_key) - } else if gov_storage::is_balance_key(value) { - KeyType::FUNDS(vp::validate_funds_key) - } else if gov_storage::is_author_key(value) { - KeyType::AUTHOR(vp::validate_author_key) - } else if gov_storage::is_counter_key(value) { - KeyType::COUNTER(vp::validate_counter_key) - } else if gov_storage::is_parameter_key(value) { - KeyType::PARAMETER(vp::validate_parameter_key) - } else if token_storage::is_balance_key(&nam(), value).is_some() { - KeyType::BALANCE(vp::validate_balance_key) - } else if gov_storage::is_governance_key(value) { - KeyType::UNKNOWN_GOVERNANCE(vp::validate_unknown_governance_key) - } else { - KeyType::UNKNOWN(vp::validate_unknown_key) - } + if gov_storage::is_vote_key(value) { + KeyType::VOTE(vp::validate_vote_key) + } else if gov_storage::is_content_key(value) { + KeyType::CONTENT(vp::validate_content_key) + } else if gov_storage::is_proposal_code_key(value) { + KeyType::PROPOSAL_CODE(vp::validate_proposal_code_key) + } else if gov_storage::is_grace_epoch_key(value) { + KeyType::GRACE_EPOCH(vp::validate_grace_epoch_key) + } else if gov_storage::is_start_epoch_key(value) { + KeyType::START_EPOCH(vp::validate_start_epoch_key) + } else if gov_storage::is_commit_proposal_key(value) { + KeyType::PROPOSAL_COMMIT(vp::validate_commit_key) + } else if gov_storage::is_end_epoch_key(value) { + KeyType::END_EPOCH(vp::validate_end_epoch_key) + } else if gov_storage::is_balance_key(value) { + KeyType::FUNDS(vp::validate_funds_key) + } else if gov_storage::is_author_key(value) { + KeyType::AUTHOR(vp::validate_author_key) + } else if gov_storage::is_counter_key(value) { + KeyType::COUNTER(vp::validate_counter_key) + } else if gov_storage::is_parameter_key(value) { + KeyType::PARAMETER(vp::validate_parameter_key) + } else if token_storage::is_balance_key(native_token, value).is_some() { + KeyType::BALANCE(vp::validate_balance_key) + } else if gov_storage::is_governance_key(value) { + KeyType::UNKNOWN_GOVERNANCE(vp::validate_unknown_governance_key) + } else { + KeyType::UNKNOWN(vp::validate_unknown_key) } } diff --git a/shared/src/ledger/governance/vp.rs b/shared/src/ledger/governance/vp.rs index 9114283959..0d78fa1bf5 100644 --- a/shared/src/ledger/governance/vp.rs +++ b/shared/src/ledger/governance/vp.rs @@ -7,8 +7,9 @@ use super::storage as gov_storage; use crate::ledger::native_vp::{self, Ctx}; use crate::ledger::pos::{self as pos_storage, BondId, Bonds}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; +use crate::ledger::storage_api::StorageRead; use crate::ledger::vp_env::VpEnv; -use crate::types::address::{self, Address, InternalAddress}; +use crate::types::address::{Address, InternalAddress}; use crate::types::storage::{Epoch, Key}; use crate::types::token; use crate::vm::WasmCacheAccess; @@ -53,7 +54,12 @@ where H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - let balance_key = token::balance_key(&address::nam(), &ADDRESS); + let balance_key = token::balance_key( + &ctx.pre() + .get_native_token() + .expect("Native token must be available"), + &ADDRESS, + ); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); @@ -164,7 +170,12 @@ where CA: 'static + WasmCacheAccess, { let funds_key = gov_storage::get_funds_key(proposal_id); - let balance_key = token::balance_key(&address::nam(), &ADDRESS); + let balance_key = token::balance_key( + &ctx.pre() + .get_native_token() + .expect("Native token must be available"), + &ADDRESS, + ); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); @@ -534,19 +545,13 @@ where #[derive(Error, Debug)] pub enum Error { #[error("Native VP error: {0}")] - NativeVpError(native_vp::Error), + NativeVpError(#[from] native_vp::Error), #[error("Native VP error deserialization: {0}")] NativeVpDeserializationError(std::io::Error), #[error("Native VP error non-existing key: {0}")] NativeVpNonExistingKeyError(String), } -impl From for Error { - fn from(err: native_vp::Error) -> Self { - Self::NativeVpError(err) - } -} - /// Check if a vote is from a delegator pub fn is_delegator( context: &Ctx, diff --git a/tx_prelude/src/governance.rs b/tx_prelude/src/governance.rs index bb0e6cb6f9..f33a30cab6 100644 --- a/tx_prelude/src/governance.rs +++ b/tx_prelude/src/governance.rs @@ -2,7 +2,6 @@ use namada::ledger::governance::storage; use namada::ledger::governance::vp::ADDRESS as governance_address; -use namada::types::address::nam; use namada::types::token::Amount; use namada::types::transaction::governance::{ InitProposalData, VoteProposalData, @@ -59,7 +58,7 @@ pub fn init_proposal(ctx: &mut Ctx, data: InitProposalData) -> TxResult { ctx, &data.author, &governance_address, - &nam(), + &ctx.get_native_token()?, None, min_proposal_funds, ) From 3880c61c76698a50fc11539f67acb79a7474e95d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 25 Oct 2022 13:13:48 +0200 Subject: [PATCH 06/11] slash_fund: replace hard-coded nam with native_token --- shared/src/ledger/slash_fund/mod.rs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/shared/src/ledger/slash_fund/mod.rs b/shared/src/ledger/slash_fund/mod.rs index b944dc0bf2..26044444fe 100644 --- a/shared/src/ledger/slash_fund/mod.rs +++ b/shared/src/ledger/slash_fund/mod.rs @@ -10,9 +10,10 @@ use thiserror::Error; use self::storage as slash_fund_storage; use super::governance::vp::is_proposal_accepted; +use super::storage_api::StorageRead; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::types::address::{nam, Address, InternalAddress}; +use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::token; use crate::vm::WasmCacheAccess; @@ -24,7 +25,7 @@ pub const ADDRESS: Address = Address::Internal(InternalAddress::SlashFund); #[derive(Error, Debug)] pub enum Error { #[error("Native VP error: {0}")] - NativeVpError(native_vp::Error), + NativeVpError(#[from] native_vp::Error), } /// SlashFund functions result @@ -57,8 +58,9 @@ where keys_changed: &BTreeSet, _verifiers: &BTreeSet
, ) -> Result { + let native_token = self.ctx.pre().get_native_token()?; let result = keys_changed.iter().all(|key| { - let key_type: KeyType = key.into(); + let key_type: KeyType = get_key_type(key, &native_token); match key_type { KeyType::BALANCE(addr) => { if addr.ne(&ADDRESS) { @@ -90,17 +92,15 @@ enum KeyType { UNKNOWN, } -impl From<&Key> for KeyType { - fn from(value: &Key) -> Self { - if slash_fund_storage::is_slash_fund_key(value) { - KeyType::UNKNOWN_SLASH_FUND - } else if token::is_any_token_balance_key(value).is_some() { - match token::is_balance_key(&nam(), value) { - Some(addr) => KeyType::BALANCE(addr.clone()), - None => KeyType::UNKNOWN, - } - } else { - KeyType::UNKNOWN +fn get_key_type(value: &Key, native_token: &Address) -> KeyType { + if slash_fund_storage::is_slash_fund_key(value) { + KeyType::UNKNOWN_SLASH_FUND + } else if token::is_any_token_balance_key(value).is_some() { + match token::is_balance_key(native_token, value) { + Some(addr) => KeyType::BALANCE(addr.clone()), + None => KeyType::UNKNOWN, } + } else { + KeyType::UNKNOWN } } From e0c02c33213404e1f0dd73f53624183021755a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 25 Oct 2022 13:24:06 +0200 Subject: [PATCH 07/11] tests: update for native_token --- apps/src/lib/config/genesis.rs | 1 + .../lib/node/ledger/shell/finalize_block.rs | 11 +++-- apps/src/lib/node/ledger/shell/mod.rs | 6 ++- .../lib/node/ledger/shell/prepare_proposal.rs | 5 +-- .../lib/node/ledger/shell/process_proposal.rs | 17 ++++---- apps/src/lib/node/ledger/storage/mod.rs | 41 ++++++++++++++----- tests/src/vm_host_env/tx.rs | 1 + tests/src/vm_host_env/vp.rs | 1 + wasm/wasm_source/src/tx_bond.rs | 12 +++--- wasm/wasm_source/src/tx_unbond.rs | 16 +++----- wasm/wasm_source/src/tx_withdraw.rs | 16 +++----- 11 files changed, 71 insertions(+), 56 deletions(-) diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index e8f5f61fa0..ac7ed4032b 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -877,6 +877,7 @@ pub fn genesis() -> Genesis { parameters, pos_params: PosParams::default(), gov_params: GovParams::default(), + native_token: address::nam(), } } diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 47fe6e9fdd..a3e429477f 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -321,7 +321,6 @@ where /// are covered by the e2e tests. #[cfg(test)] mod test_finalize_block { - use namada::types::address::nam; use namada::types::storage::Epoch; use namada::types::transaction::{EncryptionKey, Fee}; @@ -349,7 +348,7 @@ mod test_finalize_block { let wrapper = WrapperTx::new( Fee { amount: i.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -420,7 +419,7 @@ mod test_finalize_block { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -472,7 +471,7 @@ mod test_finalize_block { let wrapper = WrapperTx { fee: Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, pk: keypair.ref_to(), epoch: Epoch(0), @@ -538,7 +537,7 @@ mod test_finalize_block { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -569,7 +568,7 @@ mod test_finalize_block { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index d2423b70cd..186eb87726 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -644,7 +644,7 @@ mod test_utils { use namada::ledger::storage::mockdb::MockDB; use namada::ledger::storage::{BlockStateWrite, MerkleTree, Sha256Hasher}; - use namada::types::address::{nam, EstablishedAddressGen}; + use namada::types::address::EstablishedAddressGen; use namada::types::chain::ChainId; use namada::types::hash::Hash; use namada::types::key::*; @@ -742,6 +742,7 @@ mod test_utils { None, vp_wasm_compilation_cache, tx_wasm_compilation_cache, + address::nam(), ), }, receiver, @@ -866,7 +867,7 @@ mod test_utils { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: native_token.clone(), + token: native_token, }, &keypair, Epoch(0), @@ -914,6 +915,7 @@ mod test_utils { None, vp_wasm_compilation_cache, tx_wasm_compilation_cache, + address::nam(), ); assert!(!shell.storage.tx_queue.is_empty()); } diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index 71f27320c3..9338ecc482 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -140,7 +140,6 @@ pub(super) mod record { #[cfg(test)] mod test_prepare_proposal { use borsh::BorshSerialize; - use namada::types::address::nam; use namada::types::storage::Epoch; use namada::types::transaction::{Fee, WrapperTx}; @@ -189,7 +188,7 @@ mod test_prepare_proposal { WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -244,7 +243,7 @@ mod test_prepare_proposal { let wrapper_tx = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index 463f79ffac..83cef2cb6a 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -189,7 +189,6 @@ where mod test_process_proposal { use borsh::BorshDeserialize; use namada::proto::SignedTxData; - use namada::types::address::nam; use namada::types::hash::Hash; use namada::types::key::*; use namada::types::storage::Epoch; @@ -217,7 +216,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -264,7 +263,7 @@ mod test_process_proposal { let mut wrapper = WrapperTx::new( Fee { amount: 100.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -346,7 +345,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 1.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -399,7 +398,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: Amount::whole(1_000_100), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -447,7 +446,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: i.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -511,7 +510,7 @@ mod test_process_proposal { let wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -570,7 +569,7 @@ mod test_process_proposal { let mut wrapper = WrapperTx::new( Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, &keypair, Epoch(0), @@ -623,7 +622,7 @@ mod test_process_proposal { let wrapper = WrapperTx { fee: Fee { amount: 0.into(), - token: shell.native_token.clone(), + token: shell.storage.native_token.clone(), }, pk: keypair.ref_to(), epoch: Epoch(0), diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index 2876236bca..2209b8500d 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -51,6 +51,7 @@ fn new_blake2b() -> Blake2b { #[cfg(test)] mod tests { use namada::ledger::storage::types; + use namada::types::address; use namada::types::chain::ChainId; use namada::types::storage::{BlockHash, BlockHeight, Key}; use tempfile::TempDir; @@ -61,8 +62,12 @@ mod tests { fn test_crud_value() { let db_path = TempDir::new().expect("Unable to create a temporary DB directory"); - let mut storage = - PersistentStorage::open(db_path.path(), ChainId::default(), None); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); let key = Key::parse("key").expect("cannot parse the key string"); let value: u64 = 1; let value_bytes = types::encode(&value); @@ -104,8 +109,12 @@ mod tests { fn test_commit_block() { let db_path = TempDir::new().expect("Unable to create a temporary DB directory"); - let mut storage = - PersistentStorage::open(db_path.path(), ChainId::default(), None); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); storage .begin_block(BlockHash::default(), BlockHeight(100)) .expect("begin_block failed"); @@ -126,8 +135,12 @@ mod tests { drop(storage); // load the last state - let mut storage = - PersistentStorage::open(db_path.path(), ChainId::default(), None); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); storage .load_last_state() .expect("loading the last state failed"); @@ -145,8 +158,12 @@ mod tests { fn test_iter() { let db_path = TempDir::new().expect("Unable to create a temporary DB directory"); - let mut storage = - PersistentStorage::open(db_path.path(), ChainId::default(), None); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); storage .begin_block(BlockHash::default(), BlockHeight(100)) .expect("begin_block failed"); @@ -185,8 +202,12 @@ mod tests { fn test_validity_predicate() { let db_path = TempDir::new().expect("Unable to create a temporary DB directory"); - let mut storage = - PersistentStorage::open(db_path.path(), ChainId::default(), None); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); storage .begin_block(BlockHash::default(), BlockHeight(100)) .expect("begin_block failed"); diff --git a/tests/src/vm_host_env/tx.rs b/tests/src/vm_host_env/tx.rs index 6a3ef96084..ec16f89a27 100644 --- a/tests/src/vm_host_env/tx.rs +++ b/tests/src/vm_host_env/tx.rs @@ -380,5 +380,6 @@ mod native_tx_host_env { native_host_fn!(tx_get_block_time() -> i64); native_host_fn!(tx_get_block_hash(result_ptr: u64)); native_host_fn!(tx_get_block_epoch() -> u64); + native_host_fn!(tx_get_native_token(result_ptr: u64)); native_host_fn!(tx_log_string(str_ptr: u64, str_len: u64)); } diff --git a/tests/src/vm_host_env/vp.rs b/tests/src/vm_host_env/vp.rs index 88aa63d530..99a6facc03 100644 --- a/tests/src/vm_host_env/vp.rs +++ b/tests/src/vm_host_env/vp.rs @@ -334,6 +334,7 @@ mod native_vp_host_env { native_host_fn!(vp_get_block_hash(result_ptr: u64)); native_host_fn!(vp_get_tx_code_hash(result_ptr: u64)); native_host_fn!(vp_get_block_epoch() -> u64); + native_host_fn!(vp_get_native_token(result_ptr: u64)); native_host_fn!(vp_verify_tx_signature( pk_ptr: u64, pk_len: u64, diff --git a/wasm/wasm_source/src/tx_bond.rs b/wasm/wasm_source/src/tx_bond.rs index 6718988657..650d6eb3a1 100644 --- a/wasm/wasm_source/src/tx_bond.rs +++ b/wasm/wasm_source/src/tx_bond.rs @@ -35,9 +35,7 @@ mod tests { use namada_vp_prelude::proof_of_stake::types::{ Bond, VotingPower, VotingPowerDelta, }; - use namada_vp_prelude::proof_of_stake::{ - staking_token_address, BondId, GenesisValidator, PosVP, - }; + use namada_vp_prelude::proof_of_stake::{BondId, GenesisValidator, PosVP}; use proptest::prelude::*; use super::*; @@ -82,14 +80,16 @@ mod tests { init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - tx_host_env::with(|tx_env| { + let native_token = tx_host_env::with(|tx_env| { if let Some(source) = &bond.source { tx_env.spawn_accounts([source]); } // Ensure that the bond's source has enough tokens for the bond let target = bond.source.as_ref().unwrap_or(&bond.validator); - tx_env.credit_tokens(target, &staking_token_address(), bond.amount); + let native_token = tx_env.storage.native_token.clone(); + tx_env.credit_tokens(target, &native_token, bond.amount); + native_token }); let tx_code = vec![]; @@ -100,7 +100,7 @@ mod tests { // Read the data before the tx is executed let pos_balance_key = token::balance_key( - &staking_token_address(), + &native_token, &Address::Internal(InternalAddress::PoS), ); let pos_balance_pre: token::Amount = ctx() diff --git a/wasm/wasm_source/src/tx_unbond.rs b/wasm/wasm_source/src/tx_unbond.rs index 6199393fb1..7bbef99372 100644 --- a/wasm/wasm_source/src/tx_unbond.rs +++ b/wasm/wasm_source/src/tx_unbond.rs @@ -33,9 +33,7 @@ mod tests { use namada_vp_prelude::proof_of_stake::types::{ Bond, Unbond, VotingPower, VotingPowerDelta, }; - use namada_vp_prelude::proof_of_stake::{ - staking_token_address, BondId, GenesisValidator, PosVP, - }; + use namada_vp_prelude::proof_of_stake::{BondId, GenesisValidator, PosVP}; use proptest::prelude::*; use super::*; @@ -87,7 +85,8 @@ mod tests { init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - tx_host_env::with(|tx_env| { + let native_token = tx_host_env::with(|tx_env| { + let native_token = tx_env.storage.native_token.clone(); if is_delegation { let source = unbond.source.as_ref().unwrap(); tx_env.spawn_accounts([source]); @@ -96,12 +95,9 @@ mod tests { // bond first. // First, credit the bond's source with the initial stake, // before we initialize the bond below - tx_env.credit_tokens( - source, - &staking_token_address(), - initial_stake, - ); + tx_env.credit_tokens(source, &native_token, initial_stake); } + native_token }); if is_delegation { @@ -131,7 +127,7 @@ mod tests { }; let pos_balance_key = token::balance_key( - &staking_token_address(), + &native_token, &Address::Internal(InternalAddress::PoS), ); let pos_balance_pre: token::Amount = ctx() diff --git a/wasm/wasm_source/src/tx_withdraw.rs b/wasm/wasm_source/src/tx_withdraw.rs index 8add20a78d..cfabee5d99 100644 --- a/wasm/wasm_source/src/tx_withdraw.rs +++ b/wasm/wasm_source/src/tx_withdraw.rs @@ -35,9 +35,7 @@ mod tests { use namada_tx_prelude::key::testing::arb_common_keypair; use namada_tx_prelude::key::RefTo; use namada_tx_prelude::proof_of_stake::parameters::testing::arb_pos_params; - use namada_vp_prelude::proof_of_stake::{ - staking_token_address, BondId, GenesisValidator, PosVP, - }; + use namada_vp_prelude::proof_of_stake::{BondId, GenesisValidator, PosVP}; use proptest::prelude::*; use super::*; @@ -94,7 +92,8 @@ mod tests { init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - tx_host_env::with(|tx_env| { + let native_token = tx_host_env::with(|tx_env| { + let native_token = tx_env.storage.native_token.clone(); if is_delegation { let source = withdraw.source.as_ref().unwrap(); tx_env.spawn_accounts([source]); @@ -103,12 +102,9 @@ mod tests { // bond first. // First, credit the bond's source with the initial stake, // before we initialize the bond below - tx_env.credit_tokens( - source, - &staking_token_address(), - initial_stake, - ); + tx_env.credit_tokens(source, &native_token, initial_stake); } + native_token }); if is_delegation { @@ -150,7 +146,7 @@ mod tests { // Read data before we apply tx: let pos_balance_key = token::balance_key( - &staking_token_address(), + &native_token, &Address::Internal(InternalAddress::PoS), ); let pos_balance_pre: token::Amount = ctx() From f1a679994d9ef45e3b5f5c9eb2b6d879fd972be4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 25 Oct 2022 12:28:31 +0000 Subject: [PATCH 08/11] [ci] wasm checksums update --- wasm/checksums.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 01140354ba..4aad2ec376 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,18 +1,18 @@ { - "tx_bond.wasm": "tx_bond.38c037a51f9215c2be9c1b01f647251ffdc96a02a0c958c5d3db4ee36ccde43b.wasm", - "tx_ibc.wasm": "tx_ibc.5f86477029d987073ebfec66019dc991b0bb8b80717d4885b860f910916cbcdd.wasm", - "tx_init_account.wasm": "tx_init_account.8d901bce15d1ab63a591def00421183a651d4d5e09ace4291bf0a9044692741d.wasm", - "tx_init_nft.wasm": "tx_init_nft.1991808f44c1c24d4376a3d46b602bed27575f6c0359095c53f37b9225050ffc.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.716cd08d59b26bd75815511f03e141e6ac27bc0b7d7be10a71b04559244722c2.wasm", - "tx_init_validator.wasm": "tx_init_validator.611edff2746f71cdaa7547a84a96676b555821f00af8375a28f8dab7ae9fc9fa.wasm", + "tx_bond.wasm": "tx_bond.18c82eeae00649e8399bcff497449807448ab933dde172c661069f551e3cafa9.wasm", + "tx_ibc.wasm": "tx_ibc.df63b5bb9378e086da9395098bfecf4d9917c2e3a081799ed56371217a926eed.wasm", + "tx_init_account.wasm": "tx_init_account.f1f395c9e87e86f8773bf060c0da56b560434f35ac59b088e28f38501bfa3710.wasm", + "tx_init_nft.wasm": "tx_init_nft.3c5dd0e82aa99441f8401b327f28c7651742823eaacfc5d3da767518ca1d9f6a.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.0566d8208ed8608a484dee260380766921bef0e326a01b5d1a6d4cac36a10d7f.wasm", + "tx_init_validator.wasm": "tx_init_validator.7e09a954c080a7aae74b3463761feb1e161a1d288f2e0c7f7c354b1a6a87f5aa.wasm", "tx_mint_nft.wasm": "tx_mint_nft.3f20f1a86da43cc475ccc127428944bd177d40fbe2d2d1588c6fadd069cbe4b2.wasm", - "tx_transfer.wasm": "tx_transfer.5653340103a32e6685f9668ec24855f65ae17bcc43035c2559a13f5c47bb67af.wasm", - "tx_unbond.wasm": "tx_unbond.71e66ac6f792123a2aaafd60b3892d74a7d0e7a03c3ea34f15fea9089010b810.wasm", + "tx_transfer.wasm": "tx_transfer.1d70145df64271486f56dbf53591b0134f1e2464c1f2e16dafcca12ea05b309f.wasm", + "tx_unbond.wasm": "tx_unbond.155d5a01f28979ebeab420e2e831358610a44499fd600e269f9044686e879f6f.wasm", "tx_update_vp.wasm": "tx_update_vp.6d291dadb43545a809ba33fe26582b7984c67c65f05e363a93dbc62e06a33484.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.ff3def7b4bb0c46635bd6d544ac1745362757ce063feb8142d2ed9ab207f2a12.wasm", - "tx_withdraw.wasm": "tx_withdraw.ba1a743cf8914a353d7706777e0b1a37e20cd271b16e022fd3b50ad28971291f.wasm", - "vp_nft.wasm": "vp_nft.4471284b5c5f3e28c973f0a2ad2dde52ebe4a1dcd5dc15e93b380706fd0e35ea.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.7d7eb09cddc7ae348417da623e21ec4a4f8c78f15ae12de5abe7087eeab1e0db.wasm", - "vp_token.wasm": "vp_token.4a5436f7519de15c80103557add57e8d06e766e1ec1f7a642ffca252be01c5d0.wasm", - "vp_user.wasm": "vp_user.729b18aab60e8ae09b75b5f067658f30459a5ccfcd34f909b88da96523681019.wasm" + "tx_vote_proposal.wasm": "tx_vote_proposal.206bdcfbf1e640c6f5f665122f96ea55fdd6ee00807aa45d19bfe6e79974c160.wasm", + "tx_withdraw.wasm": "tx_withdraw.510e870df424e158cab0d79effd11e2c8bebaf106ffa86e18f73e0a75585a9c8.wasm", + "vp_nft.wasm": "vp_nft.ce4de0794341532b7556605415273bc05768469ba2f49c346616ba61801b6457.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.a50e428f14e16841837ec3b40c03a7b0b7ec994d15362309882a9cbe97329ff4.wasm", + "vp_token.wasm": "vp_token.0d10511e4d46e83b5bbc17544e17e86e2f707dfe955fdeae41ff796a7c2feb3b.wasm", + "vp_user.wasm": "vp_user.bc174b6514393330c5756d92cd6ca6450b65f5ceb08374c7407735f68f540871.wasm" } \ No newline at end of file From 922f3b9a6aeef7d26e2c0f139eb9749a7f4d6c74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 26 Oct 2022 10:33:33 +0200 Subject: [PATCH 09/11] use address string encoding for WASM FFI and add native_token to VpEnv --- shared/src/ledger/native_vp.rs | 10 +++++++++- shared/src/ledger/vp_env.rs | 3 +++ shared/src/vm/host_env.rs | 8 ++++---- tests/src/vm_host_env/mod.rs | 8 ++++++++ tx_prelude/src/lib.rs | 5 +++-- vp_prelude/src/lib.rs | 9 ++++++++- 6 files changed, 35 insertions(+), 8 deletions(-) diff --git a/shared/src/ledger/native_vp.rs b/shared/src/ledger/native_vp.rs index 1f83f42c42..e4ef2ce651 100644 --- a/shared/src/ledger/native_vp.rs +++ b/shared/src/ledger/native_vp.rs @@ -230,7 +230,7 @@ where } fn get_native_token(&self) -> Result { - Ok(self.ctx.storage.native_token.clone()) + self.ctx.get_native_token() } } @@ -387,6 +387,14 @@ where .into_storage_result() } + fn get_native_token(&'view self) -> Result { + vp_env::get_native_token( + &mut *self.gas_meter.borrow_mut(), + self.storage, + ) + .into_storage_result() + } + fn iter_prefix( &'view self, prefix: &Key, diff --git a/shared/src/ledger/vp_env.rs b/shared/src/ledger/vp_env.rs index 0172f986c5..fab888b9a3 100644 --- a/shared/src/ledger/vp_env.rs +++ b/shared/src/ledger/vp_env.rs @@ -66,6 +66,9 @@ pub trait VpEnv<'view> { /// current transaction is being applied. fn get_block_epoch(&'view self) -> Result; + /// Get the address of the native token. + fn get_native_token(&'view self) -> Result; + /// Storage prefix iterator, ordered by storage keys. It will try to get an /// iterator from the storage. fn iter_prefix( diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs index cf522b786c..47eba121e8 100644 --- a/shared/src/vm/host_env.rs +++ b/shared/src/vm/host_env.rs @@ -1569,10 +1569,10 @@ where let storage = unsafe { env.ctx.storage.get() }; tx_add_gas(env, MIN_STORAGE_GAS)?; let native_token = storage.native_token.clone(); - let native_token_bytes = native_token.try_to_vec().unwrap(); + let native_token_string = native_token.encode(); let gas = env .memory - .write_bytes(result_ptr, native_token_bytes) + .write_string(result_ptr, native_token_string) .map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?; tx_add_gas(env, gas) } @@ -1841,10 +1841,10 @@ where let gas_meter = unsafe { env.ctx.gas_meter.get() }; let storage = unsafe { env.ctx.storage.get() }; let native_token = vp_env::get_native_token(gas_meter, storage)?; - let native_token_bytes = native_token.try_to_vec().unwrap(); + let native_token_string = native_token.encode(); let gas = env .memory - .write_bytes(result_ptr, native_token_bytes) + .write_string(result_ptr, native_token_string) .map_err(|e| vp_env::RuntimeError::MemoryError(Box::new(e)))?; vp_env::add_gas(gas_meter, gas) } diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index 3325c6eb6a..75c27f649f 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -260,6 +260,10 @@ mod tests { tx::ctx().get_block_epoch().unwrap(), tx_host_env::with(|env| env.storage.get_current_epoch().0) ); + assert_eq!( + tx::ctx().get_native_token().unwrap(), + tx_host_env::with(|env| env.storage.native_token.clone()) + ); } /// An example how to write a VP host environment integration test @@ -510,6 +514,10 @@ mod tests { vp::CTX.get_block_epoch().unwrap(), vp_host_env::with(|env| env.storage.get_current_epoch().0) ); + assert_eq!( + vp::CTX.get_native_token().unwrap(), + vp_host_env::with(|env| env.storage.native_token.clone()) + ); } #[test] diff --git a/tx_prelude/src/lib.rs b/tx_prelude/src/lib.rs index 3909793f6f..209c8e132f 100644 --- a/tx_prelude/src/lib.rs +++ b/tx_prelude/src/lib.rs @@ -177,8 +177,9 @@ impl StorageRead<'_> for Ctx { let slice = unsafe { slice::from_raw_parts(result.as_ptr(), address::ADDRESS_LEN) }; - Ok(Address::try_from_slice(slice) - .expect("Cannot decode native address")) + let address_str = + std::str::from_utf8(slice).expect("Cannot decode native address"); + Ok(Address::decode(address_str).expect("Cannot decode native address")) } fn iter_prefix( diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs index a302bb5ac3..14fef3133c 100644 --- a/vp_prelude/src/lib.rs +++ b/vp_prelude/src/lib.rs @@ -241,6 +241,11 @@ impl<'view> VpEnv<'view> for Ctx { get_block_epoch() } + fn get_native_token(&'view self) -> Result { + // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl + get_native_token() + } + fn iter_prefix( &self, prefix: &storage::Key, @@ -490,5 +495,7 @@ fn get_native_token() -> Result { } let slice = unsafe { slice::from_raw_parts(result.as_ptr(), address::ADDRESS_LEN) }; - Ok(Address::try_from_slice(slice).expect("Cannot decode native address")) + let address_str = + std::str::from_utf8(slice).expect("Cannot decode native address"); + Ok(Address::decode(address_str).expect("Cannot decode native address")) } From 34af207080e36e1f8236872880ac690aa5e4f570 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 2 Nov 2022 11:00:46 +0100 Subject: [PATCH 10/11] fix: rename native token in e2e genesis file --- genesis/e2e-tests-single-node.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/genesis/e2e-tests-single-node.toml b/genesis/e2e-tests-single-node.toml index f327af7eaa..fa7e614163 100644 --- a/genesis/e2e-tests-single-node.toml +++ b/genesis/e2e-tests-single-node.toml @@ -3,7 +3,7 @@ # - User accounts same as the ones in "dev" build (Albert, Bertha, Christel) genesis_time = "2021-09-30T10:00:00Z" -native_token = "XAN" +native_token = "NAM" [validator.validator-0] # Validator's staked NAM at genesis. From feead24cc4013b6cdc432ae371fa16b66bf9707a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 9 Nov 2022 12:16:18 +0100 Subject: [PATCH 11/11] changelog: add #582 --- .changelog/unreleased/features/582-native-token-param.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/features/582-native-token-param.md diff --git a/.changelog/unreleased/features/582-native-token-param.md b/.changelog/unreleased/features/582-native-token-param.md new file mode 100644 index 0000000000..10dbb27503 --- /dev/null +++ b/.changelog/unreleased/features/582-native-token-param.md @@ -0,0 +1,2 @@ +- Allow to set the native token via genesis configuration. + ([#582](https://github.com/anoma/namada/pull/582)) \ No newline at end of file