Skip to content

Commit

Permalink
feat: added pgf logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Gianmarco Fraccaroli committed May 8, 2023
1 parent 76cbd1b commit 1526dc8
Show file tree
Hide file tree
Showing 23 changed files with 307 additions and 360 deletions.
27 changes: 17 additions & 10 deletions apps/src/lib/client/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,6 @@ pub async fn compute_offline_proposal_votes(
Address,
HashMap<Address, VotePower>,
> = HashMap::default();

for vote in votes {
let is_validator = is_validator(client, &vote.address).await;
let is_delegator = is_delegator(client, &vote.address).await;
Expand All @@ -1136,15 +1135,16 @@ pub async fn compute_offline_proposal_votes(
validator_voting_power
.insert(vote.address.clone(), validator_stake.into());
} else if is_delegator {
let validators = get_delegations_at(
client,
&vote.address.clone(),
Some(proposal.proposal.tally_epoch),
)
.await;

for validator in vote.delegations.clone() {
let delegator_stake = get_bond_amount_at(
client,
&vote.address.clone(),
&validator,
proposal.proposal.tally_epoch,
)
.await
.unwrap_or_default();
let delegator_stake =
validators.get(&validator).cloned().unwrap_or_default();

delegators_vote
.insert(vote.address.clone(), vote.clone().into());
Expand All @@ -1153,6 +1153,11 @@ pub async fn compute_offline_proposal_votes(
.or_default()
.insert(validator, delegator_stake.into());
}
} else {
println!(
"Skipping vote, not a validator/delegator at epoch {}.",
proposal.proposal.tally_epoch
);
}
}

Expand Down Expand Up @@ -1307,7 +1312,8 @@ pub async fn query_proposal_result(
.collect::<Vec<OfflineVote>>();

let proposal_votes =
compute_offline_proposal_votes(&client, &proposal, votes).await;
compute_offline_proposal_votes(&client, &proposal, votes.clone())
.await;
let total_voting_power =
get_total_staked_tokens(&client, proposal.proposal.tally_epoch)
.await;
Expand All @@ -1319,6 +1325,7 @@ pub async fn query_proposal_result(
);

println!("Proposal offline: {}", proposal.proposal.hash());
println!("Parsed {} votes.", votes.len());
println!("{:4}{}", "", proposal_result);
} else {
eprintln!("Either --proposal-id or --offline argument is required.");
Expand Down
9 changes: 8 additions & 1 deletion apps/src/lib/client/tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1999,7 +1999,14 @@ pub async fn submit_init_proposal(
safe_exit(1)
}

let _is_valid_offline_proposal = proposal.validate(current_epoch);
let is_valid_offline_proposal = proposal.validate(current_epoch);
if !is_valid_offline_proposal.ok() {
eprintln!(
"Invalid offline proposal: {}",
is_valid_offline_proposal
);
safe_exit(1)
}
let signer = WalletAddress::new(proposal.author.to_string());

let default_signers = ctx.default_signing_keys(Some(signer));
Expand Down
4 changes: 2 additions & 2 deletions apps/src/lib/config/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,13 +661,13 @@ pub mod genesis_config {
stewards,
payments,
pgf_inflation_rate,
stewards_inflation_rate
stewards_inflation_rate,
} = pgf_params;
let pgf_params = PgfParams {
stewards,
payments,
pgf_inflation_rate,
stewards_inflation_rate
stewards_inflation_rate,
};

let PosParamsConfig {
Expand Down
94 changes: 80 additions & 14 deletions apps/src/lib/node/ledger/shell/finalize_block.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
//! Implementation of the `FinalizeBlock` ABCI++ method for the Shell
use std::collections::HashMap;
use std::collections::{BTreeSet, HashMap};

use data_encoding::HEXUPPER;
use namada::core::ledger::parameters::storage as params_storage;
use namada::core::ledger::pgf::storage::keys as pgf_storage;
use namada::core::ledger::pgf::ADDRESS as pgf_address;
use namada::ledger::pos::types::{decimal_mult_u64, into_tm_voting_power};
use namada::ledger::pos::{namada_proof_of_stake, staking_token_address};
use namada::ledger::storage::EPOCH_SWITCH_BLOCKS_DELAY;
Expand Down Expand Up @@ -87,7 +89,6 @@ where
)?;

execute_governance_proposals(self, &mut response)?;
execute_pgf_payments(self, &mut response)?;

// Copy the new_epoch + pipeline_len - 1 validator set into
// new_epoch + pipeline_len
Expand Down Expand Up @@ -485,6 +486,7 @@ where

if new_epoch {
self.apply_inflation(current_epoch)?;
execute_pgf_payments(self, &mut response)?;
}

if !req.proposer_address.is_empty() {
Expand Down Expand Up @@ -607,7 +609,9 @@ where
//
// MASP is included below just for some completeness.

let params = read_pos_params(&self.wl_storage)?;
let params: namada_proof_of_stake::parameters::PosParams =
read_pos_params(&self.wl_storage)?;
let staking_token = staking_token_address(&self.wl_storage);

// Read from Parameters storage
let epochs_per_year: u64 = self
Expand Down Expand Up @@ -681,6 +685,64 @@ where
} = pos_controller.run();
// let new_masp_vals = _masp_controller.run();

// Pgf inflation
let pgf_inflation_rate_key = pgf_storage::get_pgf_inflation_rate_key();
let pgf_inflation_rate: Decimal = self
.read_storage_key(&pgf_inflation_rate_key)
.unwrap_or_default();

let pgf_pd_rate = pgf_inflation_rate / Decimal::from(epochs_per_year);
let pgf_inflation = Decimal::from(total_tokens) * pgf_pd_rate;

credit_tokens(
&mut self.wl_storage,
&staking_token,
&pgf_address,
token::Amount::from(pgf_inflation),
)?;

tracing::info!(
"Minting tokens for PGF rewards distribution into the PGF \
account. Amount: {}",
token::Amount::from(pgf_inflation)
);

// Pgf steward inflation
let pgf_stewards_inflation_rate_key =
pgf_storage::get_steward_inflation_rate_key();
let pgf_stewards_inflation_rate: Decimal = self
.read_storage_key(&pgf_stewards_inflation_rate_key)
.unwrap_or_default();

let pgf_stewards_pd_rate =
pgf_stewards_inflation_rate / Decimal::from(epochs_per_year);
let pgf_steward_inflation =
Decimal::from(total_tokens) * pgf_stewards_pd_rate;

let pgf_stewards_key = pgf_storage::get_stewards_key();
let pgf_stewards: BTreeSet<Address> =
self.read_storage_key(&pgf_stewards_key).unwrap_or_default();

let pgf_steward_reward = match pgf_stewards.len() {
0 => Decimal::ZERO,
_ => pgf_steward_inflation / Decimal::from(pgf_stewards.len()),
};

for steward in pgf_stewards {
credit_tokens(
&mut self.wl_storage,
&staking_token,
&steward,
token::Amount::from(pgf_steward_reward),
)?;
tracing::info!(
"Minting tokens for PGF Steward rewards distribution into the \
steward address {}. Amount: {}",
pgf_steward_reward,
steward,
);
}

// Get the number of blocks in the last epoch
let first_block_of_last_epoch = self
.wl_storage
Expand Down Expand Up @@ -758,8 +820,6 @@ where
)?;
}

let staking_token = staking_token_address(&self.wl_storage);

// Mint tokens to the PoS account for the last epoch's inflation
let pos_reward_tokens =
Amount::from(inflation - reward_tokens_remaining);
Expand Down Expand Up @@ -1508,9 +1568,11 @@ mod test_finalize_block {
// won't receive votes from TM since we receive votes at a 1-block
// delay, so votes will be empty here
next_block_for_inflation(&mut shell, pkh1.clone(), vec![]);
assert!(rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap());
assert!(
rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap()
);

// FINALIZE BLOCK 2. Tell Namada that val1 is the block proposer.
// Include votes that correspond to block 1. Make val2 the next block's
Expand All @@ -1520,9 +1582,11 @@ mod test_finalize_block {
assert!(rewards_prod_2.is_empty(&shell.wl_storage).unwrap());
assert!(rewards_prod_3.is_empty(&shell.wl_storage).unwrap());
assert!(rewards_prod_4.is_empty(&shell.wl_storage).unwrap());
assert!(!rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap());
assert!(
!rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap()
);
// Val1 was the proposer, so its reward should be larger than all
// others, which should themselves all be equal
let acc_sum = get_rewards_sum(&shell.wl_storage);
Expand Down Expand Up @@ -1623,9 +1687,11 @@ mod test_finalize_block {
);
next_block_for_inflation(&mut shell, pkh1.clone(), votes.clone());
}
assert!(rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap());
assert!(
rewards_accumulator_handle()
.is_empty(&shell.wl_storage)
.unwrap()
);
let rp1 = rewards_prod_1
.get(&shell.wl_storage, &Epoch::default())
.unwrap()
Expand Down
60 changes: 49 additions & 11 deletions apps/src/lib/node/ledger/shell/governance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ use namada::proof_of_stake::{
use namada::types::address::Address;
use namada::types::storage::Epoch;

use super::*;
use super::utils::force_read;
use super::*;

#[derive(Default)]
pub struct ProposalsResult {
Expand Down Expand Up @@ -76,18 +76,26 @@ where
let transfer_address = match proposal_result.result {
TallyResult::Passed => {
let proposal_event = match proposal_type {
ProposalType::Default(code) => {
let result =
execute_default_proposal(shell, id, code.clone())?;
ProposalType::Default(_) => {
let proposal_code_key =
gov_storage::get_proposal_code_key(id);
let proposal_code =
shell.wl_storage.read_bytes(&proposal_code_key)?;
let result = execute_default_proposal(
shell,
id,
proposal_code.clone(),
)?;
tracing::info!(
"Governance proposal (default) {} has been \
executed and passed",
id
executed ({}) and passed.",
id,
result
);

ProposalEvent::default_proposal_event(
id,
code.is_some(),
proposal_code.is_some(),
result,
)
.into()
Expand All @@ -99,7 +107,7 @@ where
)?;
tracing::info!(
"Governance proposal (pgf stewards){} has been \
executed and passed",
executed and passed.",
id
);

Expand All @@ -116,7 +124,7 @@ where
)?;
tracing::info!(
"Governance proposal (pgs payments) {} has been \
executed and passed",
executed and passed.",
id
);

Expand All @@ -127,7 +135,7 @@ where
let result = execute_eth_proposal(id)?;
tracing::info!(
"Governance proposal (eth) {} has been executed \
and passed",
and passed.",
id
);

Expand All @@ -141,13 +149,39 @@ where
shell.wl_storage.read::<Address>(&proposal_author_key)?
}
TallyResult::Rejected => {
if let ProposalType::PGFPayment(_) = proposal_type {
let two_third_nay = proposal_result.two_third_nay();
if two_third_nay {
let pgf_stewards_key = pgf_storage::get_stewards_key();
let proposal_author = gov_storage::get_author_key(id);

let mut pgf_stewards = shell
.wl_storage
.read::<BTreeSet<Address>>(&pgf_stewards_key)?
.unwrap_or_default();
let proposal_author: Address =
force_read(&shell.wl_storage, &proposal_author)?;

pgf_stewards.remove(&proposal_author);
shell
.wl_storage
.write(&pgf_stewards_key, pgf_stewards)?;

tracing::info!(
"Governance proposal {} was rejected with 2/3 of \
nay votes. Removing {} from stewards set.",
id,
proposal_author
);
}
}
let proposal_event =
ProposalEvent::rejected_proposal_event(id).into();
response.events.push(proposal_event);
proposals_result.rejected.push(id);

tracing::info!(
"Governance proposal {} has been executed and rejected",
"Governance proposal {} has been executed and rejected.",
id
);

Expand Down Expand Up @@ -319,6 +353,10 @@ where
}
}
} else {
tracing::info!(
"Governance proposal {} doesn't have any associated proposal code.",
id
);
Ok(true)
}
}
Expand Down
3 changes: 2 additions & 1 deletion apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@ where

genesis
.pgf_params
.init_storage(&mut self.wl_storage).expect("Initializing pgf parameters must not fail");
.init_storage(&mut self.wl_storage)
.expect("Initializing pgf parameters must not fail");

// Depends on parameters being initialized
self.wl_storage
Expand Down
2 changes: 1 addition & 1 deletion apps/src/lib/node/ledger/shell/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
mod block_space_alloc;
mod finalize_block;
mod governance;
mod pgf;
mod init_chain;
mod pgf;
mod prepare_proposal;
mod process_proposal;
mod queries;
Expand Down
Loading

0 comments on commit 1526dc8

Please sign in to comment.