Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the shielded reward precision for tokens to be explicitly set. #4423

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Allow the shielded reward precision for tokens to be explicitly set via
governance proposals ([\#4423](https://github.com/anoma/namada/pull/4423))
15 changes: 6 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ libfuzzer-sys = "0.4"
libloading = "0.8"
linkme = "0.3"
madato = "0.7"
masp_primitives = { version = "1.2" }
masp_proofs = { version = "1.2", default-features = false, features = ["local-prover"] }
masp_primitives = { git = "https://github.com/anoma/masp", rev = "d38ab0e9bbf5b7161f8e951e5302b87da867aa4d" }
masp_proofs = { git = "https://github.com/anoma/masp", rev = "d38ab0e9bbf5b7161f8e951e5302b87da867aa4d", default-features = false, features = ["local-prover"] }
num256 = "0.6"
num_cpus = "1.13"
num_enum = "0.7"
Expand Down
39 changes: 31 additions & 8 deletions crates/shielded_token/src/conversion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use crate::storage_key::{masp_assets_hash_key, masp_token_map_key};
use crate::storage_key::{
masp_kd_gain_key, masp_kp_gain_key, masp_last_inflation_key,
masp_last_locked_amount_key, masp_locked_amount_target_key,
masp_max_reward_rate_key,
masp_max_reward_rate_key, masp_reward_precision_key,
};
#[cfg(any(feature = "multicore", test))]
use crate::{ConversionLeaf, Error, OptionExt, ResultExt};
Expand Down Expand Up @@ -87,21 +87,44 @@ pub fn calculate_masp_rewards_precision<S, TransToken>(
) -> Result<(u128, Denomination)>
where
S: StorageWrite + StorageRead,
TransToken: trans_token::Read<S>,
TransToken: trans_token::Keys + trans_token::Read<S>,
{
let denomination = TransToken::read_denom(storage, addr)?
.expect("failed to read token denomination");

// Inflation is implicitly denominated by this value. The lower this
// figure, the less precise inflation computations are. This is especially
// problematic when inflation is coming from a token with much higher
// denomination than the native token. The higher this figure, the higher
// the threshold of holdings required in order to receive non-zero rewards.
// This value should be fixed constant for each asset type. Here we choose
// a thousandth of the given asset.
let precision_denom = std::cmp::max(u32::from(denomination.0), 3)
.checked_sub(3)
.expect("Cannot underflow");
Ok((checked!(10u128 ^ precision_denom)?, denomination))
// This value should be fixed constant for each asset type. Here we read a
// value from storage and failing that we choose a thousandth of the given
// asset.
// Key to read/write reward precision from
let reward_precision_key = masp_reward_precision_key::<TransToken>(addr);
// Now read the desired reward precision for this token address
let reward_precision: u128 =
storage.read(&reward_precision_key)?.map_or_else(
|| -> Result<u128> {
// Since reading reward precision has failed, choose a
// thousandth of the given token. But clamp the precision above
// by 10^38, the maximum power of 10 that can be contained by a
// u128.
let precision_denom =
u32::from(denomination.0).saturating_sub(3).clamp(0, 38);
let reward_precision = checked!(10u128 ^ precision_denom)?;
// Record the precision that is now being used so that it does
// not have to be recomputed each time, and to
// ensure that this value is not accidentally
// changed even by a change to this initialization
// algorithm.
storage.write(&reward_precision_key, reward_precision)?;
Ok(reward_precision)
},
Ok,
)?;

Ok((reward_precision, denomination))
}

/// Compute the MASP rewards by applying the PD-controller to the genesis
Expand Down
25 changes: 19 additions & 6 deletions crates/shielded_token/src/masp/shielded_wallet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use masp_primitives::transaction::fees::fixed::FeeRule;
use masp_primitives::transaction::{builder, Transaction};
use masp_primitives::zip32::{ExtendedKey, PseudoExtendedKey};
use namada_core::address::Address;
use namada_core::arith::checked;
use namada_core::arith::{checked, CheckedAdd, CheckedSub};
use namada_core::borsh::{BorshDeserialize, BorshSerialize};
use namada_core::chain::BlockHeight;
use namada_core::collections::{HashMap, HashSet};
Expand Down Expand Up @@ -348,11 +348,24 @@ impl<U: ShieldedUtils + MaybeSend + MaybeSync> ShieldedWallet<U> {
// Forget about the trace amount left over because we cannot
// realize its value
let trace = I128Sum::from_pair(asset_type, value % threshold);
// Record how much more of the given conversion has been used
*usage += required;
// Apply the conversions to input and move the trace amount to output
*input += conv * required - trace.clone();
*output += trace;
match checked!(input + &(conv * required) - &trace) {
// If applying the conversion does not overflow or result in
// negative input
Ok(new_input) if new_input >= I128Sum::zero() => {
// Record how much more of the given conversion has been used
*usage += required;
// Apply conversions to input and move trace amount to output
*input = new_input;
*output += trace;
}
_ => {
// Otherwise don't apply the conversion and simply move value
// over to output
let comp = I128Sum::from_pair(asset_type, value);
*output += comp.clone();
*input -= comp;
}
}
Ok(())
}

Expand Down
10 changes: 10 additions & 0 deletions crates/shielded_token/src/storage_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub const MASP_LOCKED_AMOUNT_TARGET_KEY: &str = "locked_amount_target";
pub const MASP_MAX_REWARD_RATE_KEY: &str = "max_reward_rate";
/// The key for the total inflation rewards minted by MASP
pub const MASP_TOTAL_REWARDS: &str = "max_total_rewards";
/// The key for the reward precision for a given asset
pub const MASP_REWARD_PRECISION_KEY: &str = "reward_precision";

/// Obtain the nominal proportional key for the given token
pub fn masp_kp_gain_key<TransToken: trans_token::Keys>(
Expand All @@ -61,6 +63,14 @@ pub fn masp_max_reward_rate_key<TransToken: trans_token::Keys>(
.with_segment(MASP_MAX_REWARD_RATE_KEY.to_owned())
}

/// The precision of rewards for the given token
pub fn masp_reward_precision_key<TransToken: trans_token::Keys>(
token_addr: &Address,
) -> storage::Key {
TransToken::parameter_prefix(token_addr)
.with_segment(MASP_REWARD_PRECISION_KEY.to_owned())
}

/// Obtain the locked target amount key for the given token
pub fn masp_locked_amount_target_key<TransToken: trans_token::Keys>(
token_addr: &Address,
Expand Down
Loading
Loading