From 1463a20d5bd324bc3420ab747d51523a42e8e245 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Mon, 2 Jan 2023 17:45:39 +0100 Subject: [PATCH 1/5] genesis: added parameter to control wrapper tx fees amount --- apps/src/lib/config/genesis.rs | 8 ++++ apps/src/lib/node/ledger/shell/init_chain.rs | 3 ++ core/src/ledger/parameters/mod.rs | 47 ++++++++++++++++++++ core/src/ledger/parameters/storage.rs | 11 +++++ core/src/ledger/storage/mod.rs | 2 + 5 files changed, 71 insertions(+) diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index 3ab8e60b6f..4ea6c56a6b 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -267,6 +267,9 @@ pub mod genesis_config { pub pos_gain_p: Decimal, /// PoS gain d pub pos_gain_d: Decimal, + #[cfg(not(feature = "mainnet"))] + /// Fix wrapper tx fees + pub wrapper_tx_fees: Option, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -613,6 +616,7 @@ pub mod genesis_config { pos_gain_d: parameters.pos_gain_d, staked_ratio: Decimal::ZERO, pos_inflation_amount: 0, + wrapper_tx_fees: parameters.wrapper_tx_fees, }; let GovernanceParamsConfig { @@ -858,6 +862,9 @@ pub struct Parameters { pub staked_ratio: Decimal, /// PoS inflation amount from the last epoch (read + write for every epoch) pub pos_inflation_amount: u64, + /// Fixed Wrapper tx fees + #[cfg(not(feature = "mainnet"))] + pub wrapper_tx_fees: Option, } #[cfg(not(feature = "dev"))] @@ -918,6 +925,7 @@ pub fn genesis() -> Genesis { pos_gain_d: dec!(0.1), staked_ratio: dec!(0.0), pos_inflation_amount: 0, + wrapper_tx_fees: Some(token::Amount::whole(0)), }; let albert = EstablishedAccount { address: wallet::defaults::albert_address(), diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index 5e4415a0c9..c58a8bd4ac 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -78,6 +78,7 @@ where pos_gain_d, staked_ratio, pos_inflation_amount, + wrapper_tx_fees, } = genesis.parameters; // borrow necessary for release build, annoys clippy on dev build #[allow(clippy::needless_borrow)] @@ -131,6 +132,8 @@ where pos_inflation_amount, #[cfg(not(feature = "mainnet"))] faucet_account, + #[cfg(not(feature = "mainnet"))] + wrapper_tx_fees, }; parameters.init_storage(&mut self.storage); diff --git a/core/src/ledger/parameters/mod.rs b/core/src/ledger/parameters/mod.rs index 75c6d33d9f..2b17927fc7 100644 --- a/core/src/ledger/parameters/mod.rs +++ b/core/src/ledger/parameters/mod.rs @@ -12,6 +12,7 @@ use crate::types::address::{Address, InternalAddress}; use crate::types::chain::ProposalBytes; use crate::types::storage::Key; use crate::types::time::DurationSecs; +use crate::types::token; const ADDRESS: Address = Address::Internal(InternalAddress::Parameters); @@ -54,6 +55,9 @@ pub struct Parameters { #[cfg(not(feature = "mainnet"))] /// Faucet account for free token withdrawal pub faucet_account: Option
, + #[cfg(not(feature = "mainnet"))] + /// Fixed fees for a wrapper tx to be accepted + pub wrapper_tx_fees: Option, } /// Epoch duration. A new epoch begins as soon as both the `min_num_of_blocks` @@ -118,6 +122,8 @@ impl Parameters { pos_inflation_amount, #[cfg(not(feature = "mainnet"))] faucet_account, + #[cfg(not(feature = "mainnet"))] + wrapper_tx_fees, } = self; // write max proposal bytes parameter @@ -218,6 +224,18 @@ impl Parameters { genesis block, if any", ); } + + #[cfg(not(feature = "mainnet"))] + { + let wrapper_tx_fees_key = storage::get_wrapper_tx_fees_key(); + let wrapper_tx_fees_val = + encode(&wrapper_tx_fees.unwrap_or(token::Amount::whole(100))); + storage + .write(&wrapper_tx_fees_key, wrapper_tx_fees_val) + .expect( + "Wrapper tx fees must be initialized in the genesis block", + ); + } } } /// Update the max_expected_time_per_block parameter in storage. Returns the @@ -423,6 +441,25 @@ where Ok((address, gas_faucet_account)) } +#[cfg(not(feature = "mainnet"))] +/// Read the wrapper tx fees amount, if any +pub fn read_wrapper_tx_fees_parameter( + storage: &Storage, +) -> std::result::Result<(Option, u64), ReadError> +where + DB: ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, + H: ledger_storage::StorageHasher, +{ + let wrapper_tx_fees_key = storage::get_wrapper_tx_fees_key(); + let (value, gas_wrapper_tx_fees) = storage + .read(&wrapper_tx_fees_key) + .map_err(ReadError::StorageError)?; + let address: Option = value + .map(|value| decode(value).map_err(ReadError::StorageTypeError)) + .transpose()?; + Ok((address, gas_wrapper_tx_fees)) +} + // Read the all the parameters from storage. Returns the parameters and gas /// cost. pub fn read( @@ -532,6 +569,13 @@ where #[cfg(feature = "mainnet")] let gas_faucet_account = 0; + // read faucet account + #[cfg(not(feature = "mainnet"))] + let (wrapper_tx_fees, gas_wrapper_tx_fees) = + read_wrapper_tx_fees_parameter(storage)?; + #[cfg(feature = "mainnet")] + let gas_wrapper_tx_fees = 0; + let total_gas_cost = [ gas_epoch, gas_tx, @@ -545,6 +589,7 @@ where gas_reward, gas_proposal_bytes, gas_faucet_account, + gas_wrapper_tx_fees, ] .into_iter() .fold(0u64, |accum, gas| { @@ -568,6 +613,8 @@ where pos_inflation_amount, #[cfg(not(feature = "mainnet"))] faucet_account, + #[cfg(not(feature = "mainnet"))] + wrapper_tx_fees, }, total_gas_cost, )) diff --git a/core/src/ledger/parameters/storage.rs b/core/src/ledger/parameters/storage.rs index f2b5d1353d..178b0860eb 100644 --- a/core/src/ledger/parameters/storage.rs +++ b/core/src/ledger/parameters/storage.rs @@ -20,6 +20,7 @@ struct Keys { vp_whitelist: &'static str, max_proposal_bytes: &'static str, faucet_account: &'static str, + wrapper_tx_fees: &'static str, } /// Returns if the key is a parameter key. @@ -249,3 +250,13 @@ pub fn get_faucet_account_key() -> Key { ], } } + +/// Storage key used for staked ratio parameter. +pub fn get_wrapper_tx_fees_key() -> Key { + Key { + segments: vec![ + DbKeySeg::AddressSeg(ADDRESS), + DbKeySeg::StringSeg(Keys::VALUES.wrapper_tx_fees.to_string()), + ], + } +} diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index 8f0606bd70..45f145ec87 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -1242,6 +1242,8 @@ mod tests { pos_inflation_amount: 0, #[cfg(not(feature = "mainnet"))] faucet_account: None, + #[cfg(not(feature = "mainnet"))] + wrapper_tx_fees: None, }; parameters.init_storage(&mut storage); From a800b8a7834ddb188fea98ef978e785d737f953c Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Tue, 3 Jan 2023 11:09:28 +0100 Subject: [PATCH 2/5] ledger: use genesis fees --- apps/src/lib/client/signing.rs | 13 +++++++++++-- apps/src/lib/node/ledger/shell/finalize_block.rs | 9 +++++---- apps/src/lib/node/ledger/shell/mod.rs | 11 +++++++++++ core/src/types/token.rs | 7 +++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/apps/src/lib/client/signing.rs b/apps/src/lib/client/signing.rs index c35f9aef6d..ec1641c1c4 100644 --- a/apps/src/lib/client/signing.rs +++ b/apps/src/lib/client/signing.rs @@ -2,6 +2,7 @@ //! wallet. use borsh::BorshSerialize; +use namada::ledger::parameters::storage as parameter_storage; use namada::proto::Tx; use namada::types::address::{Address, ImplicitAddress}; use namada::types::key::*; @@ -185,11 +186,19 @@ pub async fn sign_wrapper( keypair: &common::SecretKey, #[cfg(not(feature = "mainnet"))] requires_pow: bool, ) -> TxBroadcastData { - let fee_amount = Amount::from(MIN_FEE); + let client = HttpClient::new(args.ledger_address.clone()).unwrap(); + + let fee_amount = if cfg!(feature = "mainnet") { + Amount::from(MIN_FEE) + } else { + let wrapper_tx_fees_key = parameter_storage::get_wrapper_tx_fees_key(); + rpc::query_storage_value::(&client, &wrapper_tx_fees_key) + .await + .unwrap_or_default() + }; let fee_token = ctx.get(&args.fee_token); let source = Address::from(&keypair.ref_to()); let balance_key = token::balance_key(&fee_token, &source); - let client = HttpClient::new(args.ledger_address.clone()).unwrap(); let balance = rpc::query_storage_value::(&client, &balance_key) .await diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 577a4ac003..8fbcdb3592 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -55,6 +55,8 @@ where execute_governance_proposals(self, &mut response)?; } + let wrapper_fees = self.get_wrapper_tx_fees(); + // Tracks the accepted transactions self.storage.block.results = BlockResults::default(); for (tx_index, processed_tx) in req.txs.iter().enumerate() { @@ -179,13 +181,12 @@ where } }; - let balance: u64 = balance.into(); - match balance.checked_sub(MIN_FEE) { - Some(v) => { + match balance.checked_sub(wrapper_fees) { + Some(amount) => { self.write_log .write( &balance_key, - Amount::from(v).try_to_vec().unwrap(), + amount.try_to_vec().unwrap(), ) .unwrap(); } diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 3b5940f99c..3d11035c5c 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -719,6 +719,17 @@ where false } + #[cfg(not(feature = "mainnet"))] + /// Get fixed amount of fees for wrapper tx + fn get_wrapper_tx_fees(&self) -> token::Amount { + let (fees, _gas) = + namada::ledger::parameters::read_wrapper_tx_fees_parameter( + &self.storage, + ) + .expect("Must be able to read wrapper tx fees parameter"); + fees.unwrap_or_default() + } + #[cfg(not(feature = "mainnet"))] /// Check if the tx has a valid PoW solution and if so invalidate it to /// prevent replay. diff --git a/core/src/types/token.rs b/core/src/types/token.rs index 2bf95735ed..becbe323a3 100644 --- a/core/src/types/token.rs +++ b/core/src/types/token.rs @@ -71,6 +71,13 @@ impl Amount { Self { micro: u64::MAX } } + /// Checked subtraction + pub fn checked_sub(&self, amount: Amount) -> Option { + self.micro + .checked_sub(amount.micro) + .map(|result| Self { micro: result }) + } + /// Create amount from Change /// /// # Panics From 26f8443edab985ff37a71e099093603c92041415 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 4 Jan 2023 13:17:20 +0100 Subject: [PATCH 3/5] ledger: remove/changed some logs --- apps/src/lib/client/signing.rs | 2 +- shared/src/ledger/queries/router.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/src/lib/client/signing.rs b/apps/src/lib/client/signing.rs index ec1641c1c4..9f897df0ed 100644 --- a/apps/src/lib/client/signing.rs +++ b/apps/src/lib/client/signing.rs @@ -219,7 +219,7 @@ pub async fn sign_wrapper( // If the address derived from the keypair doesn't have enough balance // to pay for the fee, allow to find a PoW solution instead. if requires_pow || balance < fee_amount { - println!("The transaction requires to a PoW challenge."); + println!("The transaction requires the completion of a PoW challenge."); // Obtain a PoW challenge for faucet withdrawal let challenge = rpc::get_testnet_pow_challenge( source, diff --git a/shared/src/ledger/queries/router.rs b/shared/src/ledger/queries/router.rs index f614396d27..9bf1116a5c 100644 --- a/shared/src/ledger/queries/router.rs +++ b/shared/src/ledger/queries/router.rs @@ -250,7 +250,7 @@ macro_rules! try_match_segments { $end = $request.path.len(); match $request.path[$start..$end].parse::<$arg_ty>() { Ok(parsed) => { - println!("Parsed {}", parsed); + // println!("Parsed {}", parsed); $arg = parsed }, Err(_) => From 49a1d3f8fd00348fc74ba58be28b7af3bffb9c51 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 4 Jan 2023 14:09:51 +0100 Subject: [PATCH 4/5] chore: clippy/fmt --- apps/src/lib/client/signing.rs | 4 +++- apps/src/lib/node/ledger/shell/finalize_block.rs | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/src/lib/client/signing.rs b/apps/src/lib/client/signing.rs index 9f897df0ed..0f893a0190 100644 --- a/apps/src/lib/client/signing.rs +++ b/apps/src/lib/client/signing.rs @@ -219,7 +219,9 @@ pub async fn sign_wrapper( // If the address derived from the keypair doesn't have enough balance // to pay for the fee, allow to find a PoW solution instead. if requires_pow || balance < fee_amount { - println!("The transaction requires the completion of a PoW challenge."); + println!( + "The transaction requires the completion of a PoW challenge." + ); // Obtain a PoW challenge for faucet withdrawal let challenge = rpc::get_testnet_pow_challenge( source, diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 8fbcdb3592..b214c2b78a 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -265,7 +265,7 @@ where { Ok(result) => { if result.is_accepted() { - tracing::info!( + tracing::trace!( "all VPs accepted transaction {} storage \ modification {:#?}", tx_event["hash"], @@ -297,7 +297,7 @@ where } } } else { - tracing::info!( + tracing::trace!( "some VPs rejected transaction {} storage \ modification {:#?}", tx_event["hash"], @@ -326,6 +326,11 @@ where } response.events.push(tx_event); } + tracing::info!( + "Applied {} txs at height {}", + response.events.len(), + self.storage.last_height + ); if new_epoch { self.update_epoch(&mut response); From 2785ad0c14d26ebc4bab564469aa0ff95083eb4e Mon Sep 17 00:00:00 2001 From: "Raymond E. Pasco" Date: Tue, 10 Jan 2023 03:49:41 -0500 Subject: [PATCH 5/5] changelog: add #972 --- .changelog/unreleased/improvements/972-genesis-wrapper-fees.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/972-genesis-wrapper-fees.md diff --git a/.changelog/unreleased/improvements/972-genesis-wrapper-fees.md b/.changelog/unreleased/improvements/972-genesis-wrapper-fees.md new file mode 100644 index 0000000000..63579d9141 --- /dev/null +++ b/.changelog/unreleased/improvements/972-genesis-wrapper-fees.md @@ -0,0 +1,2 @@ +- Add genesis parameter to control wrapper transaction fees. + ([#972](https://github.com/anoma/namada/pull/972)) \ No newline at end of file