Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .changelog/unreleased/bug-fixes/1816-pgf-v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Introduce a new genesis section to control PGF storage at chain start.
([\#1816](https://github.com/anoma/namada/pull/1816))
32 changes: 31 additions & 1 deletion apps/src/lib/config/genesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::collections::HashMap;
use borsh::{BorshDeserialize, BorshSerialize};
use derivative::Derivative;
use namada::core::ledger::governance::parameters::GovernanceParameters;
use namada::core::ledger::pgf::parameters::PgfParameters;
#[cfg(not(feature = "mainnet"))]
use namada::core::ledger::testnet_pow;
use namada::ledger::eth_bridge::EthereumBridgeConfig;
Expand All @@ -22,14 +23,15 @@ use namada::types::{storage, token};
/// Genesis configuration file format
pub mod genesis_config {
use std::array::TryFromSliceError;
use std::collections::HashMap;
use std::collections::{BTreeSet, HashMap};
use std::convert::TryInto;
use std::path::Path;
use std::str::FromStr;

use data_encoding::HEXLOWER;
use eyre::Context;
use namada::core::ledger::governance::parameters::GovernanceParameters;
use namada::core::ledger::pgf::parameters::PgfParameters;
#[cfg(not(feature = "mainnet"))]
use namada::core::ledger::testnet_pow;
use namada::ledger::parameters::EpochDuration;
Expand Down Expand Up @@ -135,6 +137,8 @@ pub mod genesis_config {
pub pos_params: PosParamsConfig,
// Governance parameters
pub gov_params: GovernanceParamsConfig,
// Pgf parameters
pub pgf_params: PgfParametersConfig,
// Ethereum bridge config
pub ethereum_bridge_params: Option<EthereumBridgeConfig>,
// Wasm definitions
Expand All @@ -157,6 +161,16 @@ pub mod genesis_config {
pub min_proposal_grace_epochs: u64,
}

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct PgfParametersConfig {
/// The set of stewards
pub stewards: BTreeSet<Address>,
/// The pgf inflation rate
pub pgf_inflation_rate: Dec,
/// The stewards inflation rate
pub stewards_inflation_rate: Dec,
}

/// Validator pre-genesis configuration can be created with client utils
/// `init-genesis-validator` command and added to a genesis for
/// `init-network` cmd and that can be subsequently read by `join-network`
Expand Down Expand Up @@ -526,6 +540,7 @@ pub mod genesis_config {
parameters,
pos_params,
gov_params,
pgf_params,
wasm,
ethereum_bridge_params,
} = config;
Expand Down Expand Up @@ -630,6 +645,17 @@ pub mod genesis_config {
max_proposal_period,
};

let PgfParametersConfig {
stewards,
pgf_inflation_rate,
stewards_inflation_rate,
} = pgf_params;
let pgf_params = PgfParameters {
stewards,
pgf_inflation_rate,
stewards_inflation_rate,
};

let PosParamsConfig {
max_validator_slots,
pipeline_len,
Expand All @@ -644,6 +670,7 @@ pub mod genesis_config {
cubic_slashing_window_length,
validator_stake_threshold,
} = pos_params;

let pos_params = PosParams {
max_validator_slots,
pipeline_len,
Expand Down Expand Up @@ -673,6 +700,7 @@ pub mod genesis_config {
parameters,
pos_params,
gov_params,
pgf_params,
ethereum_bridge_params,
};
genesis.init();
Expand Down Expand Up @@ -726,6 +754,7 @@ pub struct Genesis {
pub parameters: Parameters,
pub pos_params: PosParams,
pub gov_params: GovernanceParameters,
pub pgf_params: PgfParameters,
// Ethereum bridge config
pub ethereum_bridge_params: Option<EthereumBridgeConfig>,
}
Expand Down Expand Up @@ -1084,6 +1113,7 @@ pub fn genesis(num_validators: u64) -> Genesis {
parameters,
pos_params: PosParams::default(),
gov_params: GovernanceParameters::default(),
pgf_params: PgfParameters::default(),
ethereum_bridge_params: Some(EthereumBridgeConfig {
eth_start_height: Default::default(),
min_confirmations: Default::default(),
Expand Down
7 changes: 7 additions & 0 deletions apps/src/lib/node/ledger/shell/init_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ where
.gov_params
.init_storage(&mut self.wl_storage)
.expect("Initializing chain parameters must not fail");

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

// configure the Ethereum bridge if the configuration is set.
if let Some(config) = genesis.ethereum_bridge_params {
tracing::debug!("Initializing Ethereum bridge storage.");
Expand Down
9 changes: 8 additions & 1 deletion core/src/ledger/governance/cli/onchain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ impl PgfStewardProposal {
&self.proposal.content,
governance_parameters.max_proposal_content_size,
)?;
is_valid_pgf_stewards_data(&self.data)?;
is_valid_pgf_stewards_data(&self.data, &self.proposal.author)?;

Ok(self)
}
Expand Down Expand Up @@ -245,6 +245,13 @@ pub enum PgfAction {
Remove,
}

impl PgfAction {
/// Check if a pgf action is adding a steward
pub fn is_add(&self) -> bool {
matches!(self, PgfAction::Add)
}
}

/// Pgf fundings
#[derive(
Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize,
Expand Down
20 changes: 19 additions & 1 deletion core/src/ledger/governance/cli/validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::BTreeMap;
use thiserror::Error;

use super::onchain::{PgfFunding, PgfSteward};
use crate::types::address::Address;
use crate::types::storage::Epoch;
use crate::types::token;

Expand Down Expand Up @@ -222,9 +223,26 @@ pub fn is_valid_default_proposal_data(

pub fn is_valid_pgf_stewards_data(
data: &Vec<PgfSteward>,
author: &Address,
) -> Result<(), ProposalValidation> {
if !data.is_empty() {
Ok(())
let total_added_stewards = data
.iter()
.filter(|steward| steward.action.is_add())
.cloned()
.collect::<Vec<PgfSteward>>();
if total_added_stewards.len() > 1 {
Err(ProposalValidation::InvalidPgfStewardsExtraData)
} else if total_added_stewards.is_empty() {
Ok(())
} else {
let steward_address = &total_added_stewards.get(0).unwrap().address;
if steward_address.eq(author) {
return Ok(());
} else {
return Err(ProposalValidation::InvalidPgfStewardsExtraData);
}
}
} else {
Err(ProposalValidation::InvalidPgfStewardsExtraData)
}
Expand Down
15 changes: 4 additions & 11 deletions core/src/ledger/pgf/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,47 +19,40 @@ use crate::types::dec::Dec;
BorshDeserialize,
)]
/// Pgf parameter structure
pub struct PgfParams {
pub struct PgfParameters {
/// The set of stewards
pub stewards: BTreeSet<Address>,
/// The set of continous payments
pub payments: BTreeSet<u64>,
/// The pgf funding inflation rate
pub pgf_inflation_rate: Dec,
/// The pgf stewards inflation rate
pub stewards_inflation_rate: Dec,
}

impl Default for PgfParams {
impl Default for PgfParameters {
fn default() -> Self {
Self {
stewards: BTreeSet::default(),
payments: BTreeSet::default(),
pgf_inflation_rate: Dec::new(5, 2).unwrap(),
pgf_inflation_rate: Dec::new(10, 2).unwrap(),
stewards_inflation_rate: Dec::new(1, 2).unwrap(),
}
}
}

impl PgfParams {
impl PgfParameters {
/// Initialize governance parameters into storage
pub fn init_storage<S>(&self, storage: &mut S) -> storage_api::Result<()>
where
S: StorageRead + StorageWrite,
{
let Self {
stewards,
payments,
pgf_inflation_rate,
stewards_inflation_rate,
} = self;

let stewards_key = pgf_storage::get_stewards_key();
storage.write(&stewards_key, stewards)?;

let payments_key = pgf_storage::get_payments_key();
storage.write(&payments_key, payments)?;

let pgf_inflation_rate_key = pgf_storage::get_pgf_inflation_rate_key();
storage.write(&pgf_inflation_rate_key, pgf_inflation_rate)?;

Expand Down
10 changes: 9 additions & 1 deletion genesis/dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,12 @@ max_proposal_period = 27
# maximum number of characters in the proposal content
max_proposal_content_size = 10000
# minimum epochs between end and grace epoch
min_proposal_grace_epochs = 6
min_proposal_grace_epochs = 6

[pgf_params]
# list of steward address at genezis
stewards = []
# inflation rate for pgf fundings
pgf_inflation_rate = "0.1"
# inflation rate for pgf stewards
stewards_inflation_rate = "0.01"
8 changes: 8 additions & 0 deletions genesis/e2e-tests-single-node.toml
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,11 @@ max_proposal_period = 27
max_proposal_content_size = 10000
# minimum epochs between end and grace epoch
min_proposal_grace_epochs = 6

[pgf_params]
# list of steward address at genezis
stewards = []
# inflation rate for pgf fundings
pgf_inflation_rate = "0.1"
# inflation rate for pgf stewards
stewards_inflation_rate = "0.01"
31 changes: 29 additions & 2 deletions shared/src/ledger/governance/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use std::collections::BTreeSet;

use borsh::BorshDeserialize;
use namada_core::ledger::governance::storage::keys as gov_storage;
use namada_core::ledger::governance::storage::proposal::ProposalType;
use namada_core::ledger::governance::storage::proposal::{
AddRemove, ProposalType,
};
use namada_core::ledger::governance::storage::vote::StorageProposalVote;
use namada_core::ledger::governance::utils::is_valid_validator_voting_period;
use namada_core::ledger::storage_api::governance::is_proposal_accepted;
Expand Down Expand Up @@ -282,7 +284,32 @@ where

match proposal_type {
ProposalType::PGFSteward(stewards) => {
Ok(stewards.len() < MAX_PGF_ACTIONS)
let steward_added = stewards
.iter()
.filter_map(|steward| match steward {
AddRemove::Add(address) => Some(address),
AddRemove::Remove(_) => None,
})
.cloned()
.collect::<Vec<Address>>();

if steward_added.len() > 1 {
Ok(false)
} else if steward_added.is_empty() {
return Ok(stewards.len() < MAX_PGF_ACTIONS);
} else {
match steward_added.get(0) {
Some(address) => {
let author_key =
gov_storage::get_author_key(proposal_id);
let author =
self.force_read(&author_key, ReadType::Post)?;
return Ok(stewards.len() < MAX_PGF_ACTIONS
&& address.eq(&author));
}
None => return Ok(false),
}
}
}
ProposalType::PGFPayment(payments) => {
if payments.len() < MAX_PGF_ACTIONS {
Expand Down