Skip to content

Commit

Permalink
Merge branch 'murisi/compounding-rewards' (#1985)
Browse files Browse the repository at this point in the history
* origin/murisi/compounding-rewards:
  Added changelog entry.
  Implemented a mul_div operation for Uints and reduced overflow risks in inflation computations.
  make token amounts in `RewardsController` of `Uint` type
  Increased the precision of MASP rewards.
  Integrated PD controller support.
  Implemented compounding inflation for native tokens.
  • Loading branch information
Fraccaman committed Oct 23, 2023
2 parents 0f4beb8 + 2e3e640 commit 7bfafb0
Show file tree
Hide file tree
Showing 42 changed files with 1,120 additions and 489 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- MASP rewards are now distributed in the manner dictated by the PD-controller
([\#1985](https://github.com/anoma/namada/pull/1985))
6 changes: 3 additions & 3 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 @@ -92,8 +92,8 @@ lazy_static = "1.4.0"
libc = "0.2.97"
libloading = "0.7.2"
# branch = "murisi/namada-integration"
masp_primitives = { git = "https://github.com/anoma/masp", rev = "449a7295fe24d96456ece24c223ca9eb76b0e6ba" }
masp_proofs = { git = "https://github.com/anoma/masp", rev = "449a7295fe24d96456ece24c223ca9eb76b0e6ba", default-features = false, features = ["local-prover"] }
masp_primitives = { git = "https://github.com/anoma/masp", rev = "77e009626f3f52fe83c81ec6ee38fc2547d38da3" }
masp_proofs = { git = "https://github.com/anoma/masp", rev = "77e009626f3f52fe83c81ec6ee38fc2547d38da3", default-features = false, features = ["local-prover"] }
num256 = "0.3.5"
num_cpus = "1.13.0"
num-derive = "0.3.3"
Expand Down
4 changes: 2 additions & 2 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2235,7 +2235,7 @@ pub async fn query_conversions<'a>(
// Track whether any non-sentinel conversions are found
let mut conversions_found = false;
for ((addr, _), epoch, conv, _) in conv_state.assets.values() {
let amt: masp_primitives::transaction::components::I32Sum =
let amt: masp_primitives::transaction::components::I128Sum =
conv.clone().into();
// If the user has specified any targets, then meet them
// If we have a sentinel conversion, then skip printing
Expand Down Expand Up @@ -2290,7 +2290,7 @@ pub async fn query_conversion<C: namada::ledger::queries::Client + Sync>(
Address,
MaspDenom,
Epoch,
masp_primitives::transaction::components::I32Sum,
masp_primitives::transaction::components::I128Sum,
MerklePath<Node>,
)> {
namada_sdk::rpc::query_conversion(client, asset_type).await
Expand Down
18 changes: 16 additions & 2 deletions apps/src/lib/config/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ pub mod genesis_config {
pub vp: Option<String>,
// Initial balances held by accounts defined elsewhere.
pub balances: Option<HashMap<String, token::Amount>>,
// Token parameters
pub parameters: Option<token::Parameters>,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
Expand Down Expand Up @@ -403,6 +405,9 @@ pub mod genesis_config {
implicit_accounts: &HashMap<String, ImplicitAccount>,
) -> TokenAccount {
TokenAccount {
last_locked_ratio: Dec::zero(),
last_inflation: token::Amount::zero(),
parameters: config.parameters.as_ref().unwrap().to_owned(),
address: Address::decode(config.address.as_ref().unwrap()).unwrap(),
denom: config.denom,
balances: config
Expand Down Expand Up @@ -814,6 +819,12 @@ pub struct TokenAccount {
/// Accounts' balances of this token
#[derivative(PartialOrd = "ignore", Ord = "ignore")]
pub balances: HashMap<Address, token::Amount>,
/// Token parameters
pub parameters: token::Parameters,
/// Token inflation from the last epoch (read + write for every epoch)
pub last_inflation: token::Amount,
/// Token shielded ratio from the last epoch (read + write for every epoch)
pub last_locked_ratio: Dec,
}

#[derive(
Expand Down Expand Up @@ -998,8 +1009,8 @@ pub fn genesis(num_validators: u64) -> Genesis {
implicit_vp_code_path: vp_implicit_path.into(),
implicit_vp_sha256: Default::default(),
max_signatures_per_transaction: 15,
epochs_per_year: 525_600, /* seconds in yr (60*60*24*365) div seconds
* per epoch (60 = min_duration) */
epochs_per_year: 365, /* seconds in yr (60*60*24*365) div seconds
* per epoch (60 = min_duration) */
pos_gain_p: Dec::new(1, 1).expect("This can't fail"),
pos_gain_d: Dec::new(1, 1).expect("This can't fail"),
staked_ratio: Dec::zero(),
Expand Down Expand Up @@ -1097,6 +1108,9 @@ pub fn genesis(num_validators: u64) -> Genesis {
.into_iter()
.map(|(k, v)| (k, token::Amount::from_uint(v, denom).unwrap()))
.collect(),
parameters: token::Parameters::default(),
last_inflation: token::Amount::zero(),
last_locked_ratio: Dec::zero(),
})
.collect();
Genesis {
Expand Down
42 changes: 11 additions & 31 deletions apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use std::collections::HashMap;

use data_encoding::HEXUPPER;
use namada::core::ledger::inflation;
use namada::core::ledger::pgf::ADDRESS as pgf_address;
use namada::ledger::events::EventType;
use namada::ledger::gas::{GasMetering, TxGasMeter};
Expand All @@ -11,7 +12,7 @@ use namada::ledger::pos::{namada_proof_of_stake, staking_token_address};
use namada::ledger::storage::EPOCH_SWITCH_BLOCKS_DELAY;
use namada::ledger::storage_api::token::credit_tokens;
use namada::ledger::storage_api::{pgf, StorageRead, StorageWrite};
use namada::ledger::{inflation, protocol, replay_protection};
use namada::ledger::{protocol, replay_protection};
use namada::proof_of_stake::{
delegator_rewards_products_handle, find_validator_by_raw_hash,
read_last_block_proposer_address, read_pos_params, read_total_stake,
Expand Down Expand Up @@ -614,10 +615,8 @@ where
/// with respect to the previous epoch.
fn apply_inflation(&mut self, current_epoch: Epoch) -> Result<()> {
let last_epoch = current_epoch.prev();
// Get input values needed for the PD controller for PoS and MASP.
// Get input values needed for the PD controller for PoS.
// Run the PD controllers to calculate new rates.
//
// MASP is included below just for some completeness.

let params = read_pos_params(&self.wl_storage)?;

Expand All @@ -639,7 +638,7 @@ where
.read_storage_key(&params_storage::get_pos_inflation_amount_key())
.expect("PoS inflation amount should exist in storage");
// Read from PoS storage
let total_tokens = self
let total_tokens: token::Amount = self
.read_storage_key(&token::minted_balance_key(
&staking_token_address(&self.wl_storage),
))
Expand All @@ -649,47 +648,25 @@ where
let pos_locked_ratio_target = params.target_staked_ratio;
let pos_max_inflation_rate = params.max_inflation_rate;

// TODO: properly fetch these values (arbitrary for now)
let masp_locked_supply: Amount = Amount::default();
let masp_locked_ratio_target = Dec::new(5, 1).expect("Cannot fail");
let masp_locked_ratio_last = Dec::new(5, 1).expect("Cannot fail");
let masp_max_inflation_rate = Dec::new(2, 1).expect("Cannot fail");
let masp_last_inflation_rate = Dec::new(12, 2).expect("Cannot fail");
let masp_p_gain = Dec::new(1, 1).expect("Cannot fail");
let masp_d_gain = Dec::new(1, 1).expect("Cannot fail");

// Run rewards PD controller
let pos_controller = inflation::RewardsController {
locked_tokens: pos_locked_supply,
total_tokens,
locked_tokens: pos_locked_supply.raw_amount(),
total_tokens: total_tokens.raw_amount(),
total_native_tokens: total_tokens.raw_amount(),
locked_ratio_target: pos_locked_ratio_target,
locked_ratio_last: pos_last_staked_ratio,
max_reward_rate: pos_max_inflation_rate,
last_inflation_amount: pos_last_inflation_amount,
last_inflation_amount: pos_last_inflation_amount.raw_amount(),
p_gain_nom: pos_p_gain_nom,
d_gain_nom: pos_d_gain_nom,
epochs_per_year,
};
let _masp_controller = inflation::RewardsController {
locked_tokens: masp_locked_supply,
total_tokens,
locked_ratio_target: masp_locked_ratio_target,
locked_ratio_last: masp_locked_ratio_last,
max_reward_rate: masp_max_inflation_rate,
last_inflation_amount: token::Amount::from(
masp_last_inflation_rate,
),
p_gain_nom: masp_p_gain,
d_gain_nom: masp_d_gain,
epochs_per_year,
};

// Run the rewards controllers
let inflation::ValsToUpdate {
locked_ratio,
inflation,
} = pos_controller.run();
// let new_masp_vals = _masp_controller.run();

// Get the number of blocks in the last epoch
let first_block_of_last_epoch = self
Expand All @@ -709,6 +686,9 @@ where
// for the previous epoch
//
// TODO: think about changing the reward to Decimal
let inflation = token::Amount::from_uint(inflation, 0)
.expect("Should not fail Uint -> Amount conversion");

let mut reward_tokens_remaining = inflation;
let mut new_rewards_products: HashMap<Address, (Dec, Dec)> =
HashMap::new();
Expand Down
27 changes: 27 additions & 0 deletions apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,14 +330,41 @@ where
address,
denom,
balances,
parameters,
last_inflation,
last_locked_ratio,
} in accounts
{
// Init token parameters and last inflation and caching rates
parameters.init_storage(&address, &mut self.wl_storage);
self.wl_storage
.write(
&token::masp_last_inflation_key(&address),
last_inflation,
)
.unwrap();
self.wl_storage
.write(
&token::masp_last_locked_ratio_key(&address),
last_locked_ratio,
)
.unwrap();
// associate a token with its denomination.
write_denom(&mut self.wl_storage, &address, denom).unwrap();

let mut total_balance_for_token = token::Amount::default();
for (owner, amount) in balances {
total_balance_for_token += amount;
credit_tokens(&mut self.wl_storage, &address, &owner, amount)
.unwrap();
}
// Write the total amount of tokens for the ratio
self.wl_storage
.write(
&token::minted_balance_key(&address),
total_balance_for_token,
)
.unwrap();
}
}

Expand Down
2 changes: 2 additions & 0 deletions apps/src/lib/node/ledger/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1996,6 +1996,7 @@ mod test_utils {

/// We test that on shell shutdown, the tx queue gets persisted in a DB, and
/// on startup it is read successfully
#[cfg(feature = "testing")]
#[test]
fn test_tx_queue_persistence() {
let base_dir = tempdir().unwrap().as_ref().canonicalize().unwrap();
Expand Down Expand Up @@ -2033,6 +2034,7 @@ mod test_utils {
.storage
.begin_block(BlockHash::default(), BlockHeight(1))
.expect("begin_block failed");
token::testing::init_token_storage(&mut shell.wl_storage, 60);
let keypair = gen_keypair();
// enqueue a wrapper tx
let mut wrapper =
Expand Down
2 changes: 2 additions & 0 deletions apps/src/lib/node/ledger/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ mod tests {
assert_eq!(result, None);
}

#[cfg(feature = "testing")]
#[test]
fn test_commit_block() {
let db_path =
Expand All @@ -144,6 +145,7 @@ mod tests {
storage.block.pred_epochs.new_epoch(BlockHeight(100));
// make wl_storage to update conversion for a new epoch
let mut wl_storage = WlStorage::new(WriteLog::default(), storage);
namada::types::token::testing::init_token_storage(&mut wl_storage, 60);
update_allowed_conversions(&mut wl_storage)
.expect("update conversions failed");
wl_storage.commit_block().expect("commit failed");
Expand Down
Loading

0 comments on commit 7bfafb0

Please sign in to comment.