From 4f89775604d326d9ba3372f3e3bd11b59a5ec6ab Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 26 Sep 2023 16:34:24 -0600 Subject: [PATCH 01/26] refactor `Epoched` for past epochs --- proof_of_stake/src/epoched.rs | 180 +++++++++++++++++++++++++--------- proof_of_stake/src/types.rs | 36 +++++-- 2 files changed, 157 insertions(+), 59 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index d5a567fc94..3a69c83c39 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -16,6 +16,7 @@ use namada_core::ledger::storage_api::{StorageRead, StorageWrite}; use namada_core::types::storage::{self, Epoch}; use crate::parameters::PosParams; +use crate::read_pos_params; /// Sub-key holding a lazy map in storage pub const LAZY_MAP_SUB_KEY: &str = "lazy_map"; @@ -28,57 +29,48 @@ pub const OLDEST_EPOCH_SUB_KEY: &str = "oldest_epoch"; const DEFAULT_NUM_PAST_EPOCHS: u64 = 2; /// Discrete epoched data handle -pub struct Epoched< - Data, - FutureEpochs, - const NUM_PAST_EPOCHS: u64 = DEFAULT_NUM_PAST_EPOCHS, - SON = collections::Simple, -> { +pub struct Epoched { storage_prefix: storage::Key, future_epochs: PhantomData, + past_epochs: PhantomData, data: PhantomData, phantom_son: PhantomData, } /// Discrete epoched data handle with nested lazy structure -pub type NestedEpoched< - Data, - FutureEpochs, - const NUM_PAST_EPOCHS: u64 = DEFAULT_NUM_PAST_EPOCHS, -> = Epoched; +pub type NestedEpoched = + Epoched; /// Delta epoched data handle -pub struct EpochedDelta { +pub struct EpochedDelta { storage_prefix: storage::Key, future_epochs: PhantomData, + past_epochs: PhantomData, data: PhantomData, } -impl - Epoched +impl + Epoched where FutureEpochs: EpochOffset, + PastEpochs: EpochOffset, { /// Open the handle pub fn open(key: storage::Key) -> Self { Self { storage_prefix: key, future_epochs: PhantomData, + past_epochs: PhantomData, data: PhantomData, phantom_son: PhantomData, } } - - /// Return the number of past epochs to keep data for - pub fn get_num_past_epochs() -> u64 { - NUM_PAST_EPOCHS - } } -impl - Epoched +impl Epoched where FutureEpochs: EpochOffset, + PastEpochs: EpochOffset, Data: BorshSerialize + BorshDeserialize + 'static + Debug, { /// Initialize new epoched data. Sets the head to the given value. @@ -125,7 +117,8 @@ where Some(_) => return Ok(res), None => { if epoch.0 > 0 - && epoch > Self::sub_past_epochs(last_update) + && epoch + > Self::sub_past_epochs(params, last_update) { epoch = Epoch(epoch.0 - 1); } else { @@ -149,7 +142,8 @@ where where S: StorageWrite + StorageRead, { - self.update_data(storage, current_epoch)?; + let params = read_pos_params(storage)?; + self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -177,6 +171,7 @@ where fn update_data( &self, storage: &mut S, + params: &PosParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -189,7 +184,7 @@ where { let oldest_to_keep = current_epoch .0 - .checked_sub(NUM_PAST_EPOCHS) + .checked_sub(PastEpochs::value(params)) .unwrap_or_default(); if oldest_epoch.0 < oldest_to_keep { let diff = oldest_to_keep - oldest_epoch.0; @@ -211,7 +206,8 @@ where } } if let Some(latest_value) = latest_value { - let new_oldest_epoch = Self::sub_past_epochs(current_epoch); + let new_oldest_epoch = + Self::sub_past_epochs(params, current_epoch); // TODO we can add `contains_key` to LazyMap if data_handler.get(storage, &new_oldest_epoch)?.is_none() { tracing::debug!( @@ -269,8 +265,13 @@ where LazyMap::open(key) } - fn sub_past_epochs(epoch: Epoch) -> Epoch { - Epoch(epoch.0.checked_sub(NUM_PAST_EPOCHS).unwrap_or_default()) + fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { + Epoch( + epoch + .0 + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default(), + ) } fn get_oldest_epoch_storage_key(&self) -> storage::Key { @@ -303,10 +304,11 @@ where } } -impl - Epoched +impl + Epoched where FutureEpochs: EpochOffset, + PastEpochs: EpochOffset, Data: LazyCollection + Debug, { /// Get the inner LazyCollection value by the outer key @@ -393,10 +395,11 @@ where // } // } -impl - EpochedDelta +impl + EpochedDelta where FutureEpochs: EpochOffset, + PastEpochs: EpochOffset, Data: BorshSerialize + BorshDeserialize + ops::Add @@ -409,6 +412,7 @@ where Self { storage_prefix: key, future_epochs: PhantomData, + past_epochs: PhantomData, data: PhantomData, } } @@ -457,7 +461,7 @@ where None => Ok(None), Some(last_update) => { let data_handler = self.get_data_handler(); - let start_epoch = Self::sub_past_epochs(last_update); + let start_epoch = Self::sub_past_epochs(params, last_update); let future_most_epoch = last_update + FutureEpochs::value(params); @@ -493,7 +497,8 @@ where where S: StorageWrite + StorageRead, { - self.update_data(storage, current_epoch)?; + let params = read_pos_params(storage)?; + self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -519,6 +524,7 @@ where fn update_data( &self, storage: &mut S, + params: &PosParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -531,7 +537,7 @@ where { let oldest_to_keep = current_epoch .0 - .checked_sub(NUM_PAST_EPOCHS) + .checked_sub(PastEpochs::value(params)) .unwrap_or_default(); if oldest_epoch.0 < oldest_to_keep { let diff = oldest_to_keep - oldest_epoch.0; @@ -557,7 +563,8 @@ where } } if let Some(sum) = sum { - let new_oldest_epoch = Self::sub_past_epochs(current_epoch); + let new_oldest_epoch = + Self::sub_past_epochs(params, current_epoch); let new_oldest_epoch_data = match data_handler.get(storage, &new_oldest_epoch)? { Some(oldest_epoch_data) => oldest_epoch_data + sum, @@ -631,8 +638,13 @@ where handle.iter(storage)?.collect() } - fn sub_past_epochs(epoch: Epoch) -> Epoch { - Epoch(epoch.0.checked_sub(NUM_PAST_EPOCHS).unwrap_or_default()) + fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { + Epoch( + epoch + .0 + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default(), + ) } fn get_oldest_epoch_storage_key(&self) -> storage::Key { @@ -688,6 +700,29 @@ impl EpochOffset for OffsetZero { } } +/// Default offset +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetDefaultNumPastEpochs; +impl EpochOffset for OffsetDefaultNumPastEpochs { + fn value(_params: &PosParams) -> u64 { + DEFAULT_NUM_PAST_EPOCHS + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::DefaultNumPastEpoch + } +} + /// Offset at pipeline length. #[derive( Debug, @@ -757,11 +792,59 @@ impl EpochOffset for OffsetPipelinePlusUnbondingLen { } } +/// Offset at the slash processing delay. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetSlashProcessingLen; +impl EpochOffset for OffsetSlashProcessingLen { + fn value(params: &PosParams) -> u64 { + params.slash_processing_epoch_offset() + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::SlashProcessingLen + } +} + +/// Maximum offset. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetMaxU64; +impl EpochOffset for OffsetMaxU64 { + fn value(_params: &PosParams) -> u64 { + u64::MAX + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::MaxU64 + } +} + /// Offset length dynamic choice. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum DynEpochOffset { /// Zero offset Zero, + /// Offset at the const default num past epochs (above) + DefaultNumPastEpoch, /// Offset at pipeline length - 1 PipelineLenMinusOne, /// Offset at pipeline length. @@ -770,6 +853,11 @@ pub enum DynEpochOffset { UnbondingLen, /// Offset at pipeline + unbonding length. PipelinePlusUnbondingLen, + /// Offset at slash processing delay (unbonding + + /// cubic_slashing_window + 1). + SlashProcessingLen, + /// Offset of the max u64 value + MaxU64, } /// Which offset should be used to set data. The value is read from @@ -794,11 +882,9 @@ mod test { fn test_epoched_data_trimming() -> storage_api::Result<()> { let mut s = TestWlStorage::default(); - const NUM_PAST_EPOCHS: u64 = 2; let key_prefix = storage::Key::parse("test").unwrap(); - let epoched = Epoched::::open( - key_prefix, - ); + let epoched = + Epoched::::open(key_prefix); let data_handler = epoched.get_data_handler(); assert!(epoched.get_last_update(&s)?.is_none()); assert!(epoched.get_oldest_epoch(&s)?.is_none()); @@ -865,11 +951,9 @@ mod test { fn test_epoched_without_data_trimming() -> storage_api::Result<()> { let mut s = TestWlStorage::default(); - const NUM_PAST_EPOCHS: u64 = u64::MAX; let key_prefix = storage::Key::parse("test").unwrap(); - let epoched = Epoched::::open( - key_prefix, - ); + let epoched = + Epoched::::open(key_prefix); let data_handler = epoched.get_data_handler(); assert!(epoched.get_last_update(&s)?.is_none()); assert!(epoched.get_oldest_epoch(&s)?.is_none()); @@ -935,10 +1019,9 @@ mod test { fn test_epoched_delta_data_trimming() -> storage_api::Result<()> { let mut s = TestWlStorage::default(); - const NUM_PAST_EPOCHS: u64 = 2; let key_prefix = storage::Key::parse("test").unwrap(); let epoched = - EpochedDelta::::open( + EpochedDelta::::open( key_prefix, ); let data_handler = epoched.get_data_handler(); @@ -1010,10 +1093,9 @@ mod test { let mut s = TestWlStorage::default(); // Nothing should ever get trimmed - const NUM_PAST_EPOCHS: u64 = u64::MAX; let key_prefix = storage::Key::parse("test").unwrap(); let epoched = - EpochedDelta::::open( + EpochedDelta::::open( key_prefix, ); let data_handler = epoched.get_data_handler(); diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 736ffe7a46..4c2eb8bbed 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -38,6 +38,7 @@ const VALIDATOR_DELTAS_SLASHES_LEN: u64 = 23; pub type ValidatorSetPositions = crate::epoched::NestedEpoched< LazyMap, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; impl ValidatorSetPositions { @@ -84,23 +85,29 @@ impl ValidatorSetPositions { pub type ValidatorConsensusKeys = crate::epoched::Epoched< common::PublicKey, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Epoched validator's eth hot key. pub type ValidatorEthHotKeys = crate::epoched::Epoched< common::PublicKey, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Epoched validator's eth cold key. pub type ValidatorEthColdKeys = crate::epoched::Epoched< common::PublicKey, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Epoched validator's state. -pub type ValidatorStates = - crate::epoched::Epoched; +pub type ValidatorStates = crate::epoched::Epoched< + ValidatorState, + crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, +>; /// A map from a position to an address in a Validator Set pub type ValidatorPositionAddresses = LazyMap; @@ -117,41 +124,49 @@ pub type BelowCapacityValidatorSet = pub type ConsensusValidatorSets = crate::epoched::NestedEpoched< ConsensusValidatorSet, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Epoched below-capacity validator sets. pub type BelowCapacityValidatorSets = crate::epoched::NestedEpoched< BelowCapacityValidatorSet, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Epoched total consensus validator stake -pub type TotalConsensusStakes = - crate::epoched::Epoched; +pub type TotalConsensusStakes = crate::epoched::Epoched< + Amount, + crate::epoched::OffsetZero, + crate::epoched::OffsetMaxU64, +>; /// Epoched validator's deltas. pub type ValidatorDeltas = crate::epoched::EpochedDelta< token::Change, crate::epoched::OffsetUnbondingLen, - VALIDATOR_DELTAS_SLASHES_LEN, + crate::epoched::OffsetSlashProcessingLen, >; /// Epoched total deltas. pub type TotalDeltas = crate::epoched::EpochedDelta< token::Change, crate::epoched::OffsetUnbondingLen, - VALIDATOR_DELTAS_SLASHES_LEN, + crate::epoched::OffsetSlashProcessingLen, >; /// Epoched validator commission rate -pub type CommissionRates = - crate::epoched::Epoched; +pub type CommissionRates = crate::epoched::Epoched< + Dec, + crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, +>; /// Epoched validator's bonds pub type Bonds = crate::epoched::EpochedDelta< token::Change, crate::epoched::OffsetPipelineLen, - U64_MAX, + crate::epoched::OffsetMaxU64, >; /// An epoched lazy set of all known active validator addresses (consensus, @@ -159,6 +174,7 @@ pub type Bonds = crate::epoched::EpochedDelta< pub type ValidatorAddresses = crate::epoched::NestedEpoched< LazySet
, crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetDefaultNumPastEpochs, >; /// Slashes indexed by validator address and then block height (for easier @@ -172,7 +188,7 @@ pub type ValidatorSlashes = NestedMap; pub type EpochedSlashes = crate::epoched::NestedEpoched< ValidatorSlashes, crate::epoched::OffsetUnbondingLen, - VALIDATOR_DELTAS_SLASHES_LEN, + crate::epoched::OffsetSlashProcessingLen, >; /// Epoched validator's unbonds From d8a29effe87bef203ffc4146a8c062bb423bcc34 Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 26 Sep 2023 16:38:15 -0600 Subject: [PATCH 02/26] cleaning: remove unused code + improve docstrings --- proof_of_stake/src/epoched.rs | 116 +--------------------------------- proof_of_stake/src/types.rs | 47 -------------- 2 files changed, 3 insertions(+), 160 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 3a69c83c39..8483a61c62 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -344,7 +344,7 @@ where .unwrap() } - /// TODO + /// Get the epoch of the most recent update pub fn get_last_update( &self, storage: &S, @@ -356,7 +356,7 @@ where storage.read(&key) } - /// TODO + /// Set the epoch of the most recent update pub fn set_last_update( &self, storage: &mut S, @@ -368,33 +368,8 @@ where let key = self.get_last_update_storage_key(); storage.write(&key, current_epoch) } - - /// TODO - pub fn sub_past_epochs(epoch: Epoch) -> Epoch { - Epoch(epoch.0.checked_sub(NUM_PAST_EPOCHS).unwrap_or_default()) - } - - // pub fn get_inner_by_epoch(&self) -> storage_api::Result {} - - // TODO: we may need an update_data() method, figure out when it should be - // called (in at()?) } -// impl -// Epoched< -// LazyMap, -// FutureEpochs, -// NUM_PAST_EPOCHS, -// collections::Nested, -// > -// where -// FutureEpochs: EpochOffset, -// { -// pub fn get_inner_by_epoch(&self, epoch: &Epoch) -> LazyMap { -// self.at() -// } -// } - impl EpochedDelta where @@ -691,7 +666,7 @@ where )] pub struct OffsetZero; impl EpochOffset for OffsetZero { - fn value(_paras: &PosParams) -> u64 { + fn value(_params: &PosParams) -> u64 { 0 } @@ -1158,89 +1133,4 @@ mod test { Ok(()) } - - // use namada_core::ledger::storage::testing::TestStorage; - // use namada_core::types::address::{self, Address}; - // use namada_core::types::storage::Key; - // - // use super::{ - // storage, storage_api, Epoch, LazyMap, NestedEpoched, NestedMap, - // OffsetPipelineLen, - // }; - // - // #[test] - // fn testing_epoched_new() -> storage_api::Result<()> { - // let mut storage = TestStorage::default(); - // - // let key1 = storage::Key::parse("test_nested1").unwrap(); - // let nested1 = - // NestedEpoched::, OffsetPipelineLen>::open( - // key1, - // ); - // nested1.init(&mut storage, Epoch(0))?; - // - // let key2 = storage::Key::parse("test_nested2").unwrap(); - // let nested2 = NestedEpoched::< - // NestedMap>, - // OffsetPipelineLen, - // >::open(key2); - // nested2.init(&mut storage, Epoch(0))?; - // - // dbg!(&nested1.get_last_update_storage_key()); - // dbg!(&nested1.get_last_update(&storage)); - // - // nested1.at(&Epoch(0)).insert( - // &mut storage, - // address::testing::established_address_1(), - // 1432, - // )?; - // dbg!(&nested1.at(&Epoch(0)).iter(&mut storage)?.next()); - // dbg!(&nested1.at(&Epoch(1)).iter(&mut storage)?.next()); - // - // nested2.at(&Epoch(0)).at(&100).insert( - // &mut storage, - // 1, - // address::testing::established_address_2(), - // )?; - // dbg!(&nested2.at(&Epoch(0)).iter(&mut storage)?.next()); - // dbg!(&nested2.at(&Epoch(1)).iter(&mut storage)?.next()); - // - // dbg!(&nested_epoched.get_epoch_key(&Epoch::from(0))); - // - // let epoch = Epoch::from(0); - // let addr = address::testing::established_address_1(); - // let amount: u64 = 234235; - // - // nested_epoched - // .at(&epoch) - // .insert(&mut storage, addr.clone(), amount)?; - // - // let epoch = epoch + 3_u64; - // nested_epoched.at(&epoch).insert( - // &mut storage, - // addr.clone(), - // 999_u64, - // )?; - // - // dbg!(nested_epoched.contains_epoch(&storage, &Epoch::from(0))?); - // dbg!( - // nested_epoched - // .get_data_handler() - // .get_data_key(&Epoch::from(3)) - // ); - // dbg!(nested_epoched.contains_epoch(&storage, &Epoch::from(3))?); - // dbg!( - // nested_epoched - // .at(&Epoch::from(0)) - // .get(&storage, &addr.clone())? - // ); - // dbg!( - // nested_epoched - // .at(&Epoch::from(3)) - // .get(&storage, &addr.clone())? - // ); - // dbg!(nested_epoched.at(&Epoch::from(3)).get_data_key(&addr)); - // - // Ok(()) - // } } diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 4c2eb8bbed..2ec8e4fd86 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -14,7 +14,6 @@ use namada_core::ledger::storage_api::collections::lazy_map::NestedMap; use namada_core::ledger::storage_api::collections::{ LazyMap, LazySet, LazyVec, }; -use namada_core::ledger::storage_api::{self, StorageRead}; use namada_core::types::address::Address; use namada_core::types::dec::Dec; use namada_core::types::key::common; @@ -25,14 +24,6 @@ pub use rev_order::ReverseOrdTokenAmount; use crate::parameters::PosParams; -// TODO: replace `POS_MAX_DECIMAL_PLACES` with -// core::types::token::NATIVE_MAX_DECIMAL_PLACES?? -const U64_MAX: u64 = u64::MAX; - -/// Number of epochs below the current epoch for which validator deltas and -/// slashes are stored -const VALIDATOR_DELTAS_SLASHES_LEN: u64 = 23; - // TODO: add this to the spec /// Stored positions of validators in validator sets pub type ValidatorSetPositions = crate::epoched::NestedEpoched< @@ -41,44 +32,6 @@ pub type ValidatorSetPositions = crate::epoched::NestedEpoched< crate::epoched::OffsetDefaultNumPastEpochs, >; -impl ValidatorSetPositions { - /// TODO - pub fn get_position( - &self, - storage: &S, - epoch: &Epoch, - address: &Address, - params: &PosParams, - ) -> storage_api::Result> - where - S: StorageRead, - { - let last_update = self.get_last_update(storage)?; - // dbg!(&last_update); - if last_update.is_none() { - return Ok(None); - } - let last_update = last_update.unwrap(); - let future_most_epoch: Epoch = last_update + params.pipeline_len; - // dbg!(future_most_epoch); - let mut epoch = std::cmp::min(*epoch, future_most_epoch); - loop { - // dbg!(epoch); - match self.at(&epoch).get(storage, address)? { - Some(val) => return Ok(Some(val)), - None => { - if epoch.0 > 0 && epoch > Self::sub_past_epochs(last_update) - { - epoch = Epoch(epoch.0 - 1); - } else { - return Ok(None); - } - } - } - } - } -} - // TODO: check the offsets for each epoched type!! /// Epoched validator's consensus key. From 8416f0bc37b5a9e5778596e300b2f31a36a7463c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 14:19:34 +0100 Subject: [PATCH 03/26] test/eth: init storage with PoS params where needed --- ethereum_bridge/src/protocol/transactions/votes/update.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ethereum_bridge/src/protocol/transactions/votes/update.rs b/ethereum_bridge/src/protocol/transactions/votes/update.rs index c1173bdf12..928bb4d7f8 100644 --- a/ethereum_bridge/src/protocol/transactions/votes/update.rs +++ b/ethereum_bridge/src/protocol/transactions/votes/update.rs @@ -376,6 +376,7 @@ mod tests { #[test] fn test_apply_duplicate_votes() -> Result<()> { let mut wl_storage = TestWlStorage::default(); + test_utils::init_default_storage(&mut wl_storage); let validator = address::testing::established_address_1(); let already_voted_height = BlockHeight(100); @@ -411,6 +412,7 @@ mod tests { #[test] fn test_calculate_already_seen() -> Result<()> { let mut wl_storage = TestWlStorage::default(); + test_utils::init_default_storage(&mut wl_storage); let event = default_event(); let keys = vote_tallies::Keys::from(&event); let tally_pre = TallyParams { From f5d4544639caad90f3e5e7aebc35ba11c97abd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 14:26:29 +0100 Subject: [PATCH 04/26] test/PoS/epoched: init PoS params and fix `PastEpochs` type param --- proof_of_stake/src/epoched.rs | 39 +++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 8483a61c62..92b336d960 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -849,17 +849,23 @@ pub trait EpochOffset: #[cfg(test)] mod test { use namada_core::ledger::storage::testing::TestWlStorage; + use namada_core::types::address::testing::established_address_1; + use namada_core::types::dec::Dec; + use namada_core::types::{key, token}; use test_log::test; use super::*; + use crate::types::GenesisValidator; #[test] fn test_epoched_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; let key_prefix = storage::Key::parse("test").unwrap(); let epoched = - Epoched::::open(key_prefix); + Epoched::::open( + key_prefix, + ); let data_handler = epoched.get_data_handler(); assert!(epoched.get_last_update(&s)?.is_none()); assert!(epoched.get_oldest_epoch(&s)?.is_none()); @@ -924,7 +930,7 @@ mod test { #[test] fn test_epoched_without_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; let key_prefix = storage::Key::parse("test").unwrap(); let epoched = @@ -992,11 +998,11 @@ mod test { #[test] fn test_epoched_delta_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; let key_prefix = storage::Key::parse("test").unwrap(); let epoched = - EpochedDelta::::open( + EpochedDelta::::open( key_prefix, ); let data_handler = epoched.get_data_handler(); @@ -1065,7 +1071,7 @@ mod test { #[test] fn test_epoched_delta_without_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; // Nothing should ever get trimmed let key_prefix = storage::Key::parse("test").unwrap(); @@ -1133,4 +1139,25 @@ mod test { Ok(()) } + + fn init_storage() -> storage_api::Result { + let mut s = TestWlStorage::default(); + crate::init_genesis( + &mut s, + &PosParams::default(), + [GenesisValidator { + address: established_address_1(), + tokens: token::Amount::native_whole(1_000), + consensus_key: key::testing::keypair_1().to_public(), + eth_hot_key: key::testing::keypair_3().to_public(), + eth_cold_key: key::testing::keypair_3().to_public(), + commission_rate: Dec::new(1, 1).expect("Dec creation failed"), + max_commission_rate_change: Dec::new(1, 1) + .expect("Dec creation failed"), + }] + .into_iter(), + Epoch::default(), + )?; + Ok(s) + } } From d3f1eb3dfe3be49087bd4fb5b765402e5c7748c1 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 28 Sep 2023 09:24:19 -0600 Subject: [PATCH 05/26] changelog: add #1943 --- .../improvements/1943-refactor-past-epoch-offsets.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/improvements/1943-refactor-past-epoch-offsets.md diff --git a/.changelog/unreleased/improvements/1943-refactor-past-epoch-offsets.md b/.changelog/unreleased/improvements/1943-refactor-past-epoch-offsets.md new file mode 100644 index 0000000000..958b40760d --- /dev/null +++ b/.changelog/unreleased/improvements/1943-refactor-past-epoch-offsets.md @@ -0,0 +1,3 @@ +- Improve the Epoched data structure's bookkeeping of past + epochs, now parameterizable by PoS and governance params. + ([\#1943](https://github.com/anoma/namada/pull/1943)) \ No newline at end of file From 812b2c2bd782fe015e91873b8548219f233ee01f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 28 Sep 2023 16:22:37 +0000 Subject: [PATCH 06/26] [ci] wasm checksums update --- wasm/checksums.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 614ab78e6b..8ebfc20f2b 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,20 +1,20 @@ { - "tx_bond.wasm": "tx_bond.b322054eef9d45e299384b2a363049ce0b0160a0c4781ca357aa59970904726c.wasm", + "tx_bond.wasm": "tx_bond.126ab38555f9dfbfb689f9774a7a028f7ffc226bd43fef118a3f32261c164fea.wasm", "tx_bridge_pool.wasm": "tx_bridge_pool.6f6ad3b95e21072af9e854e374fa0d7f691f0743da8cf52a643ed1bdb0e16611.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.9310e0a0b7c14fc7c2427040da8c91eb4067babfaaea9e3b646edbfdd09c8069.wasm", + "tx_change_validator_commission.wasm": "tx_change_validator_commission.a75d583d6ccbd956ef9c9e85010bba75b4bf63a15a67b55dfb159be35cb5c142.wasm", "tx_ibc.wasm": "tx_ibc.54313469bcc9bcaabf661177f88cb90ac9008f542edbf686f286a02f8cdbfd41.wasm", "tx_init_account.wasm": "tx_init_account.10ee01dac5325685360119ba8e4b597d776a018ea4c9ac3534dd876ec377789e.wasm", "tx_init_proposal.wasm": "tx_init_proposal.04cad5a3a71f833a5867bca3ced54b06d34ad07f3f21877599d38581d362ba10.wasm", - "tx_init_validator.wasm": "tx_init_validator.16d53a09e5df06400849aaa161c35e4e377284692f73a71dcbd4573656da7f64.wasm", + "tx_init_validator.wasm": "tx_init_validator.964c9449ffe0fc41649decd283c905c7cd3665127274444fafc6f1347364a61e.wasm", "tx_resign_steward.wasm": "tx_resign_steward.b5d92c1bd196be0d196ef16e2ceed9a9ced7ac61d7b177fdbad208c0e784e172.wasm", "tx_reveal_pk.wasm": "tx_reveal_pk.32011ddc5316705ae005059d5916b071288a04fb4dee80854af16d61548b5c27.wasm", "tx_transfer.wasm": "tx_transfer.963ec4c2705377423ddc46b4ff3de63f9b625351467d89290fa771a485710c41.wasm", - "tx_unbond.wasm": "tx_unbond.7f26336db8e8cfebc04d301dc4790138fdd9bc22878fe7542c3da525a09576be.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.15a7a399d8fb79f8df959d0ddf4c193020886d1caab1e094cca10ea3aff44a72.wasm", + "tx_unbond.wasm": "tx_unbond.63baa912938704817d2b23b4f889ffa0f40ea38ca1ce1990ed08999a717998d2.wasm", + "tx_unjail_validator.wasm": "tx_unjail_validator.03bcdf9d8f4ff06b87e9eb6207b709b8b99fac4035737dbfc70881fc5810e0c0.wasm", "tx_update_account.wasm": "tx_update_account.7b4e225a823449d3d8bffde197c439ad24f4f6c95cf754acf62b6373958c4486.wasm", "tx_update_steward_commission.wasm": "tx_update_steward_commission.0001b21ef3ef4f9b33afb5a5ef75a6a5427fbe221a8350cfbd81781ac18ded6e.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.727e36112fcd0753f758370dff981cc93430fe7d6f95ceb570a02a37529a7531.wasm", - "tx_withdraw.wasm": "tx_withdraw.e70485a8b79c5bff17d3b6ea96a7546cb709137c8a64606bdd1e77637157de33.wasm", + "tx_withdraw.wasm": "tx_withdraw.311993b9362f1a66acf002f15fbd9599115e41d9c5b4e1b0fa565335fae147cd.wasm", "vp_implicit.wasm": "vp_implicit.e0958c2ec06863f7bd48cd9abb67cc7557f956ce9fa6c714deba885db721fa50.wasm", "vp_masp.wasm": "vp_masp.037671b60b3e9f312c1c5fdc53d040ebfad21a646b9b1e2dac6b3e20fc0d01ec.wasm", "vp_user.wasm": "vp_user.0203fddde57bc31ef411370b628963486928a7c4d34614980d1a52616e0f617b.wasm", From bfd91f932e98a1c506cad208081a856cf9f17016 Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 26 Sep 2023 17:30:14 -0600 Subject: [PATCH 07/26] WIP want to pass `max_proposal_period` from gov params into PoS --- proof_of_stake/src/epoched.rs | 50 +++++++++++++++++--------------- proof_of_stake/src/lib.rs | 19 ++++++++++-- proof_of_stake/src/parameters.rs | 10 +++++++ 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 92b336d960..2b649a53a1 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -15,8 +15,8 @@ use namada_core::ledger::storage_api::collections::{self, LazyCollection}; use namada_core::ledger::storage_api::{StorageRead, StorageWrite}; use namada_core::types::storage::{self, Epoch}; -use crate::parameters::PosParams; -use crate::read_pos_params; +use crate::parameters::{PosAndGovParams, PosParams}; +use crate::read_pos_and_gov_params; /// Sub-key holding a lazy map in storage pub const LAZY_MAP_SUB_KEY: &str = "lazy_map"; @@ -95,7 +95,7 @@ where &self, storage: &S, epoch: Epoch, - params: &PosParams, + params: &PosAndGovParams, ) -> storage_api::Result> where S: StorageRead, @@ -142,7 +142,7 @@ where where S: StorageWrite + StorageRead, { - let params = read_pos_params(storage)?; + let params = read_pos_and_gov_params(storage)?; self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -171,7 +171,7 @@ where fn update_data( &self, storage: &mut S, - params: &PosParams, + params: &PosAndGovParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -265,7 +265,7 @@ where LazyMap::open(key) } - fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { + fn sub_past_epochs(params: &PosAndGovParams, epoch: Epoch) -> Epoch { Epoch( epoch .0 @@ -426,7 +426,7 @@ where &self, storage: &S, epoch: Epoch, - params: &PosParams, + params: &PosAndGovParams, ) -> storage_api::Result> where S: StorageRead, @@ -472,7 +472,7 @@ where where S: StorageWrite + StorageRead, { - let params = read_pos_params(storage)?; + let params = read_pos_and_gov_params(storage)?; self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -499,7 +499,7 @@ where fn update_data( &self, storage: &mut S, - params: &PosParams, + params: &PosAndGovParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -613,7 +613,7 @@ where handle.iter(storage)?.collect() } - fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { + fn sub_past_epochs(params: &PosAndGovParams, epoch: Epoch) -> Epoch { Epoch( epoch .0 @@ -666,7 +666,7 @@ where )] pub struct OffsetZero; impl EpochOffset for OffsetZero { - fn value(_params: &PosParams) -> u64 { + fn value(_params: &PosAndGovParams) -> u64 { 0 } @@ -689,7 +689,7 @@ impl EpochOffset for OffsetZero { )] pub struct OffsetDefaultNumPastEpochs; impl EpochOffset for OffsetDefaultNumPastEpochs { - fn value(_params: &PosParams) -> u64 { + fn value(_params: &PosAndGovParams) -> u64 { DEFAULT_NUM_PAST_EPOCHS } @@ -712,8 +712,8 @@ impl EpochOffset for OffsetDefaultNumPastEpochs { )] pub struct OffsetPipelineLen; impl EpochOffset for OffsetPipelineLen { - fn value(params: &PosParams) -> u64 { - params.pipeline_len + fn value(params: &PosAndGovParams) -> u64 { + params.pos_params.pipeline_len } fn dyn_offset() -> DynEpochOffset { @@ -735,8 +735,8 @@ impl EpochOffset for OffsetPipelineLen { )] pub struct OffsetUnbondingLen; impl EpochOffset for OffsetUnbondingLen { - fn value(params: &PosParams) -> u64 { - params.unbonding_len + fn value(params: &PosAndGovParams) -> u64 { + params.pos_params.unbonding_len } fn dyn_offset() -> DynEpochOffset { @@ -758,8 +758,8 @@ impl EpochOffset for OffsetUnbondingLen { )] pub struct OffsetPipelinePlusUnbondingLen; impl EpochOffset for OffsetPipelinePlusUnbondingLen { - fn value(params: &PosParams) -> u64 { - params.pipeline_len + params.unbonding_len + fn value(params: &PosAndGovParams) -> u64 { + params.pos_params.pipeline_len + params.pos_params.unbonding_len } fn dyn_offset() -> DynEpochOffset { @@ -781,8 +781,8 @@ impl EpochOffset for OffsetPipelinePlusUnbondingLen { )] pub struct OffsetSlashProcessingLen; impl EpochOffset for OffsetSlashProcessingLen { - fn value(params: &PosParams) -> u64 { - params.slash_processing_epoch_offset() + fn value(params: &PosAndGovParams) -> u64 { + params.pos_params.slash_processing_epoch_offset() } fn dyn_offset() -> DynEpochOffset { @@ -804,7 +804,7 @@ impl EpochOffset for OffsetSlashProcessingLen { )] pub struct OffsetMaxU64; impl EpochOffset for OffsetMaxU64 { - fn value(_params: &PosParams) -> u64 { + fn value(_params: &PosAndGovParams) -> u64 { u64::MAX } @@ -831,6 +831,10 @@ pub enum DynEpochOffset { /// Offset at slash processing delay (unbonding + /// cubic_slashing_window + 1). SlashProcessingLen, + /// Offset at the max proposal period + MaxProposalPeriod, + /// Offset at the larger of max proposal period or slash processing delay + MaxProposalPeriodOrSlashProcessingLen, /// Offset of the max u64 value MaxU64, } @@ -840,8 +844,8 @@ pub enum DynEpochOffset { pub trait EpochOffset: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema { - /// Find the value of a given offset from PoS parameters. - fn value(params: &PosParams) -> u64; + /// Find the value of a given offset from PoS and Gov parameters. + fn value(params: &PosAndGovParams) -> u64; /// Convert to [`DynEpochOffset`] fn dyn_offset() -> DynEpochOffset; } diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 0fbbf2231b..54d49c65e3 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -36,7 +36,7 @@ use namada_core::ledger::storage_api::collections::lazy_map::{ use namada_core::ledger::storage_api::collections::{LazyCollection, LazySet}; use namada_core::ledger::storage_api::token::credit_tokens; use namada_core::ledger::storage_api::{ - self, ResultExt, StorageRead, StorageWrite, + self, governance, ResultExt, StorageRead, StorageWrite, }; use namada_core::types::address::{Address, InternalAddress}; use namada_core::types::dec::Dec; @@ -46,7 +46,7 @@ use namada_core::types::key::{ pub use namada_core::types::storage::{Epoch, Key, KeySeg}; use namada_core::types::token; use once_cell::unsync::Lazy; -use parameters::PosParams; +use parameters::{PosAndGovParams, PosParams}; use rewards::PosRewardsCalculator; use storage::{ bonds_for_source_prefix, bonds_prefix, consensus_keys_key, @@ -512,6 +512,21 @@ where Ok(()) } +/// Read PoS and Governance parameters +pub fn read_pos_and_gov_params( + storage: &S, +) -> storage_api::Result +where + S: StorageRead, +{ + let gov_params = governance::get_parameters(storage)?; + let pos_params = read_pos_params(storage)?; + Ok(PosAndGovParams { + pos_params, + gov_params, + }) +} + /// Read PoS parameters pub fn read_pos_params(storage: &S) -> storage_api::Result where diff --git a/proof_of_stake/src/parameters.rs b/proof_of_stake/src/parameters.rs index 8501aff379..87ec199f28 100644 --- a/proof_of_stake/src/parameters.rs +++ b/proof_of_stake/src/parameters.rs @@ -1,6 +1,7 @@ //! Proof-of-Stake system parameters use borsh::{BorshDeserialize, BorshSerialize}; +use namada_core::ledger::governance::parameters::GovernanceParameters; use namada_core::types::dec::Dec; use namada_core::types::storage::Epoch; use namada_core::types::token; @@ -74,6 +75,15 @@ impl Default for PosParams { } } +/// A struct to hold both PoS and governance parameters +#[derive(Debug, Clone)] +pub struct PosAndGovParams { + /// Pos parameters + pub pos_params: PosParams, + /// Governance parameters + pub gov_params: GovernanceParameters, +} + #[allow(missing_docs)] #[derive(Error, Debug)] pub enum ValidationError { From 053fffbd08fabb5f25398fcb445c611aaebba2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 27 Sep 2023 17:30:59 +0100 Subject: [PATCH 08/26] add PosParams type with added gov param --- apps/src/lib/config/genesis.rs | 10 +- .../lib/node/ledger/shell/finalize_block.rs | 10 +- apps/src/lib/node/ledger/shell/init_chain.rs | 4 +- .../shell/vote_extensions/bridge_pool_vext.rs | 2 +- core/src/ledger/storage_api/governance.rs | 15 +- .../transactions/bridge_pool_roots.rs | 6 +- .../src/protocol/transactions/votes.rs | 6 +- .../src/protocol/transactions/votes/update.rs | 1 + ethereum_bridge/src/test_utils.rs | 7 +- proof_of_stake/src/epoched.rs | 44 ++-- proof_of_stake/src/lib.rs | 65 ++++-- proof_of_stake/src/parameters.rs | 59 +++-- proof_of_stake/src/tests.rs | 214 +++++++++--------- proof_of_stake/src/tests/state_machine.rs | 5 +- shared/src/ledger/native_vp/ibc/mod.rs | 3 + shared/src/ledger/pos/mod.rs | 4 +- tests/src/native_vp/pos.rs | 16 +- tests/src/vm_host_env/ibc.rs | 3 + wasm/wasm_source/src/tx_bond.rs | 9 +- .../src/tx_change_validator_commission.rs | 7 +- wasm/wasm_source/src/tx_unbond.rs | 9 +- wasm/wasm_source/src/tx_withdraw.rs | 9 +- wasm/wasm_source/src/vp_validator.rs | 6 +- 23 files changed, 298 insertions(+), 216 deletions(-) diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index b7281fd4ce..502082af48 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -8,7 +8,7 @@ use namada::core::ledger::governance::parameters::GovernanceParameters; use namada::core::ledger::pgf::parameters::PgfParameters; use namada::ledger::eth_bridge::EthereumBridgeConfig; use namada::ledger::parameters::EpochDuration; -use namada::ledger::pos::{Dec, GenesisValidator, PosParams}; +use namada::ledger::pos::{Dec, GenesisValidator, OwnedPosParams}; use namada::types::address::Address; use namada::types::chain::ProposalBytes; use namada::types::key::dkg_session_keys::DkgPublicKey; @@ -31,7 +31,7 @@ pub mod genesis_config { use namada::core::ledger::governance::parameters::GovernanceParameters; use namada::core::ledger::pgf::parameters::PgfParameters; use namada::ledger::parameters::EpochDuration; - use namada::ledger::pos::{Dec, GenesisValidator, PosParams}; + use namada::ledger::pos::{Dec, GenesisValidator, OwnedPosParams}; use namada::types::address::Address; use namada::types::chain::ProposalBytes; use namada::types::key::dkg_session_keys::DkgPublicKey; @@ -665,7 +665,7 @@ pub mod genesis_config { validator_stake_threshold, } = pos_params; - let pos_params = PosParams { + let pos_params = OwnedPosParams { max_validator_slots, pipeline_len, unbonding_len, @@ -738,7 +738,7 @@ pub struct Genesis { pub established_accounts: Vec, pub implicit_accounts: Vec, pub parameters: Parameters, - pub pos_params: PosParams, + pub pos_params: OwnedPosParams, pub gov_params: GovernanceParameters, pub pgf_params: PgfParameters, // Ethereum bridge config @@ -1109,7 +1109,7 @@ pub fn genesis(num_validators: u64) -> Genesis { implicit_accounts, token_accounts, parameters, - pos_params: PosParams::default(), + pos_params: OwnedPosParams::default(), gov_params: GovernanceParameters::default(), pgf_params: PgfParameters::default(), ethereum_bridge_params: Some(EthereumBridgeConfig { diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 53252065f1..2f8f970210 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -2653,8 +2653,8 @@ mod test_finalize_block { num_validators, }); let mut params = read_pos_params(&shell.wl_storage).unwrap(); - params.unbonding_len = 4; - write_pos_params(&mut shell.wl_storage, params.clone())?; + params.owned.unbonding_len = 4; + write_pos_params(&mut shell.wl_storage, ¶ms.owned)?; let validator_set: Vec = read_consensus_validator_set_addresses_with_stake( @@ -3031,9 +3031,9 @@ mod test_finalize_block { num_validators, }); let mut params = read_pos_params(&shell.wl_storage).unwrap(); - params.unbonding_len = 4; - params.max_validator_slots = 4; - write_pos_params(&mut shell.wl_storage, params.clone())?; + params.owned.unbonding_len = 4; + params.owned.max_validator_slots = 4; + write_pos_params(&mut shell.wl_storage, ¶ms.owned)?; // Slash pool balance let nam_address = shell.wl_storage.storage.native_token.clone(); diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index d6b2efe4dd..4d7522aaba 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -4,7 +4,7 @@ use std::hash::Hash; use namada::ledger::eth_bridge::EthBridgeStatus; use namada::ledger::parameters::{self, Parameters}; -use namada::ledger::pos::{staking_token_address, PosParams}; +use namada::ledger::pos::{staking_token_address, OwnedPosParams}; use namada::ledger::storage::traits::StorageHasher; use namada::ledger::storage::{DBIter, DB}; use namada::ledger::storage_api::token::{ @@ -412,7 +412,7 @@ where &mut self, staking_token: &Address, validators: Vec, - pos_params: &PosParams, + pos_params: &OwnedPosParams, ) -> Result { let mut response = response::InitChain::default(); // PoS system depends on epoch being initialized. Write the total diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs index 002bd18904..880409bef8 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs @@ -336,7 +336,7 @@ mod test_bp_vote_extensions { // change pipeline length to 1 let mut params = shell.wl_storage.pos_queries().get_pos_params(); - params.pipeline_len = 1; + params.owned.pipeline_len = 1; let consensus_key = gen_keypair(); let hot_key = gen_secp256k1_keypair(); diff --git a/core/src/ledger/storage_api/governance.rs b/core/src/ledger/storage_api/governance.rs index e03be937b5..e5b27a5d02 100644 --- a/core/src/ledger/storage_api/governance.rs +++ b/core/src/ledger/storage_api/governance.rs @@ -245,9 +245,7 @@ where let min_proposal_voting_period: u64 = storage.read(&key)?.expect("Parameter should be definied."); - let key = governance_keys::get_max_proposal_period_key(); - let max_proposal_period: u64 = - storage.read(&key)?.expect("Parameter should be definied."); + let max_proposal_period: u64 = get_max_proposal_period(storage)?; Ok(GovernanceParameters { min_proposal_fund, @@ -258,3 +256,14 @@ where min_proposal_grace_epochs, }) } + +/// Get governance "max_proposal_period" parameter +pub fn get_max_proposal_period(storage: &S) -> storage_api::Result +where + S: storage_api::StorageRead, +{ + let key = governance_keys::get_max_proposal_period_key(); + let max_proposal_period: u64 = + storage.read(&key)?.expect("Parameter should be definied."); + Ok(max_proposal_period) +} diff --git a/ethereum_bridge/src/protocol/transactions/bridge_pool_roots.rs b/ethereum_bridge/src/protocol/transactions/bridge_pool_roots.rs index 3271efeed5..b8a9d22303 100644 --- a/ethereum_bridge/src/protocol/transactions/bridge_pool_roots.rs +++ b/ethereum_bridge/src/protocol/transactions/bridge_pool_roots.rs @@ -235,7 +235,7 @@ mod test_apply_bp_roots_to_storage { use namada_core::types::storage::Key; use namada_core::types::vote_extensions::bridge_pool_roots; use namada_core::types::voting_power::FractionalVotingPower; - use namada_proof_of_stake::parameters::PosParams; + use namada_proof_of_stake::parameters::OwnedPosParams; use namada_proof_of_stake::write_pos_params; use super::*; @@ -757,11 +757,11 @@ mod test_apply_bp_roots_to_storage { ); // update the pos params - let params = PosParams { + let params = OwnedPosParams { pipeline_len: 1, ..Default::default() }; - write_pos_params(&mut wl_storage, params).expect("Test failed"); + write_pos_params(&mut wl_storage, ¶ms).expect("Test failed"); // insert validators 2 and 3 at epoch 1 test_utils::append_validators_to_storage( diff --git a/ethereum_bridge/src/protocol/transactions/votes.rs b/ethereum_bridge/src/protocol/transactions/votes.rs index c3a82bd370..cc029e28f5 100644 --- a/ethereum_bridge/src/protocol/transactions/votes.rs +++ b/ethereum_bridge/src/protocol/transactions/votes.rs @@ -189,7 +189,7 @@ mod tests { use namada_core::types::storage::BlockHeight; use namada_core::types::{address, token}; - use namada_proof_of_stake::parameters::PosParams; + use namada_proof_of_stake::parameters::OwnedPosParams; use namada_proof_of_stake::write_pos_params; use super::*; @@ -321,11 +321,11 @@ mod tests { ); // update the pos params - let params = PosParams { + let params = OwnedPosParams { pipeline_len: 1, ..Default::default() }; - write_pos_params(&mut wl_storage, params).expect("Test failed"); + write_pos_params(&mut wl_storage, ¶ms).expect("Test failed"); // insert validators 2 and 3 at epoch 1 test_utils::append_validators_to_storage( diff --git a/ethereum_bridge/src/protocol/transactions/votes/update.rs b/ethereum_bridge/src/protocol/transactions/votes/update.rs index 928bb4d7f8..a98be1859d 100644 --- a/ethereum_bridge/src/protocol/transactions/votes/update.rs +++ b/ethereum_bridge/src/protocol/transactions/votes/update.rs @@ -263,6 +263,7 @@ mod tests { votes, total_stake, } = self; + let keys = vote_tallies::Keys::from(event); let seen_voting_power: token::Amount = votes .iter() diff --git a/ethereum_bridge/src/test_utils.rs b/ethereum_bridge/src/test_utils.rs index 9c24e9edfa..8091566f10 100644 --- a/ethereum_bridge/src/test_utils.rs +++ b/ethereum_bridge/src/test_utils.rs @@ -6,6 +6,7 @@ use std::num::NonZeroU64; use borsh::BorshSerialize; use namada_core::ledger::eth_bridge::storage::bridge_pool::get_key_from_hash; use namada_core::ledger::eth_bridge::storage::whitelist; +use namada_core::ledger::governance::parameters::GovernanceParameters; use namada_core::ledger::storage::mockdb::MockDBWriteBatch; use namada_core::ledger::storage::testing::{TestStorage, TestWlStorage}; use namada_core::ledger::storage_api::{StorageRead, StorageWrite}; @@ -16,7 +17,7 @@ use namada_core::types::keccak::KeccakHash; use namada_core::types::key::{self, protocol_pk_key, RefTo}; use namada_core::types::storage::{BlockHeight, Key}; use namada_core::types::token; -use namada_proof_of_stake::parameters::PosParams; +use namada_proof_of_stake::parameters::OwnedPosParams; use namada_proof_of_stake::pos_queries::PosQueries; use namada_proof_of_stake::types::GenesisValidator; use namada_proof_of_stake::{ @@ -212,9 +213,11 @@ pub fn init_storage_with_validators( }) .collect(); + let gov_params = GovernanceParameters::default(); + gov_params.init_storage(wl_storage).unwrap(); namada_proof_of_stake::init_genesis( wl_storage, - &PosParams::default(), + &OwnedPosParams::default(), validators.into_iter(), 0.into(), ) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 2b649a53a1..5c119fee3c 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -15,8 +15,8 @@ use namada_core::ledger::storage_api::collections::{self, LazyCollection}; use namada_core::ledger::storage_api::{StorageRead, StorageWrite}; use namada_core::types::storage::{self, Epoch}; -use crate::parameters::{PosAndGovParams, PosParams}; -use crate::read_pos_and_gov_params; +use crate::parameters::PosParams; +use crate::read_pos_params; /// Sub-key holding a lazy map in storage pub const LAZY_MAP_SUB_KEY: &str = "lazy_map"; @@ -95,7 +95,7 @@ where &self, storage: &S, epoch: Epoch, - params: &PosAndGovParams, + params: &PosParams, ) -> storage_api::Result> where S: StorageRead, @@ -142,7 +142,7 @@ where where S: StorageWrite + StorageRead, { - let params = read_pos_and_gov_params(storage)?; + let params = read_pos_params(storage)?; self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -171,7 +171,7 @@ where fn update_data( &self, storage: &mut S, - params: &PosAndGovParams, + params: &PosParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -265,7 +265,7 @@ where LazyMap::open(key) } - fn sub_past_epochs(params: &PosAndGovParams, epoch: Epoch) -> Epoch { + fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { Epoch( epoch .0 @@ -426,7 +426,7 @@ where &self, storage: &S, epoch: Epoch, - params: &PosAndGovParams, + params: &PosParams, ) -> storage_api::Result> where S: StorageRead, @@ -472,7 +472,7 @@ where where S: StorageWrite + StorageRead, { - let params = read_pos_and_gov_params(storage)?; + let params = read_pos_params(storage)?; self.update_data(storage, ¶ms, current_epoch)?; self.set_at_epoch(storage, value, current_epoch, offset) } @@ -499,7 +499,7 @@ where fn update_data( &self, storage: &mut S, - params: &PosAndGovParams, + params: &PosParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -613,7 +613,7 @@ where handle.iter(storage)?.collect() } - fn sub_past_epochs(params: &PosAndGovParams, epoch: Epoch) -> Epoch { + fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { Epoch( epoch .0 @@ -666,7 +666,7 @@ where )] pub struct OffsetZero; impl EpochOffset for OffsetZero { - fn value(_params: &PosAndGovParams) -> u64 { + fn value(_params: &PosParams) -> u64 { 0 } @@ -689,7 +689,7 @@ impl EpochOffset for OffsetZero { )] pub struct OffsetDefaultNumPastEpochs; impl EpochOffset for OffsetDefaultNumPastEpochs { - fn value(_params: &PosAndGovParams) -> u64 { + fn value(_params: &PosParams) -> u64 { DEFAULT_NUM_PAST_EPOCHS } @@ -712,8 +712,8 @@ impl EpochOffset for OffsetDefaultNumPastEpochs { )] pub struct OffsetPipelineLen; impl EpochOffset for OffsetPipelineLen { - fn value(params: &PosAndGovParams) -> u64 { - params.pos_params.pipeline_len + fn value(params: &PosParams) -> u64 { + params.pipeline_len } fn dyn_offset() -> DynEpochOffset { @@ -735,8 +735,8 @@ impl EpochOffset for OffsetPipelineLen { )] pub struct OffsetUnbondingLen; impl EpochOffset for OffsetUnbondingLen { - fn value(params: &PosAndGovParams) -> u64 { - params.pos_params.unbonding_len + fn value(params: &PosParams) -> u64 { + params.unbonding_len } fn dyn_offset() -> DynEpochOffset { @@ -758,8 +758,8 @@ impl EpochOffset for OffsetUnbondingLen { )] pub struct OffsetPipelinePlusUnbondingLen; impl EpochOffset for OffsetPipelinePlusUnbondingLen { - fn value(params: &PosAndGovParams) -> u64 { - params.pos_params.pipeline_len + params.pos_params.unbonding_len + fn value(params: &PosParams) -> u64 { + params.pipeline_len + params.unbonding_len } fn dyn_offset() -> DynEpochOffset { @@ -781,8 +781,8 @@ impl EpochOffset for OffsetPipelinePlusUnbondingLen { )] pub struct OffsetSlashProcessingLen; impl EpochOffset for OffsetSlashProcessingLen { - fn value(params: &PosAndGovParams) -> u64 { - params.pos_params.slash_processing_epoch_offset() + fn value(params: &PosParams) -> u64 { + params.slash_processing_epoch_offset() } fn dyn_offset() -> DynEpochOffset { @@ -804,7 +804,7 @@ impl EpochOffset for OffsetSlashProcessingLen { )] pub struct OffsetMaxU64; impl EpochOffset for OffsetMaxU64 { - fn value(_params: &PosAndGovParams) -> u64 { + fn value(_params: &PosParams) -> u64 { u64::MAX } @@ -845,7 +845,7 @@ pub trait EpochOffset: Debug + Clone + BorshDeserialize + BorshSerialize + BorshSchema { /// Find the value of a given offset from PoS and Gov parameters. - fn value(params: &PosAndGovParams) -> u64; + fn value(params: &PosParams) -> u64; /// Convert to [`DynEpochOffset`] fn dyn_offset() -> DynEpochOffset; } diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 54d49c65e3..3645a84d05 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -46,7 +46,7 @@ use namada_core::types::key::{ pub use namada_core::types::storage::{Epoch, Key, KeySeg}; use namada_core::types::token; use once_cell::unsync::Lazy; -use parameters::{PosAndGovParams, PosParams}; +use parameters::{OwnedPosParams, PosParams}; use rewards::PosRewardsCalculator; use storage::{ bonds_for_source_prefix, bonds_prefix, consensus_keys_key, @@ -394,10 +394,10 @@ pub fn delegator_rewards_products_handle( RewardsProducts::open(key) } -/// Init genesis +/// Init genesis. Requires that the governance parameters are initialized. pub fn init_genesis( storage: &mut S, - params: &PosParams, + params: &OwnedPosParams, validators: impl Iterator + Clone, current_epoch: namada_core::types::storage::Epoch, ) -> storage_api::Result<()> @@ -405,7 +405,8 @@ where S: StorageRead + StorageWrite, { tracing::debug!("Initializing PoS genesis"); - write_pos_params(storage, params.clone())?; + write_pos_params(storage, params)?; + let params = read_non_pos_owned_params(storage, params.clone())?; let mut total_bonded = token::Amount::default(); consensus_validator_set_handle().init(storage, current_epoch)?; @@ -433,7 +434,7 @@ where // validator data insert_validator_into_validator_set( storage, - params, + ¶ms, &address, tokens, current_epoch, @@ -512,36 +513,38 @@ where Ok(()) } -/// Read PoS and Governance parameters -pub fn read_pos_and_gov_params( - storage: &S, -) -> storage_api::Result +/// Read PoS parameters +pub fn read_pos_params(storage: &S) -> storage_api::Result where S: StorageRead, { - let gov_params = governance::get_parameters(storage)?; - let pos_params = read_pos_params(storage)?; - Ok(PosAndGovParams { - pos_params, - gov_params, - }) + let params = storage + .read(¶ms_key()) + .transpose() + .expect("PosParams should always exist in storage after genesis")?; + read_non_pos_owned_params(storage, params) } -/// Read PoS parameters -pub fn read_pos_params(storage: &S) -> storage_api::Result +/// Read non-PoS-owned parameters to add them to `OwnedPosParams` to construct +/// `PosParams`. +pub fn read_non_pos_owned_params( + storage: &S, + owned: OwnedPosParams, +) -> storage_api::Result where S: StorageRead, { - storage - .read(¶ms_key()) - .transpose() - .expect("PosParams should always exist in storage after genesis") + let max_proposal_period = governance::get_max_proposal_period(storage)?; + Ok(PosParams { + owned, + max_proposal_period, + }) } /// Write PoS parameters pub fn write_pos_params( storage: &mut S, - params: PosParams, + params: &OwnedPosParams, ) -> storage_api::Result<()> where S: StorageRead + StorageWrite, @@ -4057,3 +4060,21 @@ where } Ok(slashes) } + +/// Init PoS genesis wrapper helper that also initializes gov params that are +/// used in PoS with default values. +#[cfg(feature = "testing")] +pub fn test_init_genesis( + storage: &mut S, + owned: OwnedPosParams, + validators: impl Iterator + Clone, + current_epoch: namada_core::types::storage::Epoch, +) -> storage_api::Result +where + S: StorageRead + StorageWrite, +{ + let gov_params = namada_core::ledger::governance::parameters::GovernanceParameters::default(); + gov_params.init_storage(storage)?; + crate::init_genesis(storage, &owned, validators, current_epoch)?; + crate::read_non_pos_owned_params(storage, owned) +} diff --git a/proof_of_stake/src/parameters.rs b/proof_of_stake/src/parameters.rs index 87ec199f28..0776b2791b 100644 --- a/proof_of_stake/src/parameters.rs +++ b/proof_of_stake/src/parameters.rs @@ -8,10 +8,21 @@ use namada_core::types::token; use namada_core::types::uint::Uint; use thiserror::Error; -/// Proof-of-Stake system parameters, set at genesis and can only be changed via -/// governance +/// Proof-of-Stake system parameters. This includes parameters that are used in +/// PoS but are read from other accounts storage (governance). #[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] pub struct PosParams { + /// PoS-owned params + pub owned: OwnedPosParams, + /// Governance param - Maximum proposal voting period in epochs. + /// This param is stored in governance. + pub max_proposal_period: u64, +} + +/// Proof-of-Stake system parameters owned by the PoS address, set at genesis +/// and can only be changed via governance +#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +pub struct OwnedPosParams { /// A maximum number of consensus validators pub max_validator_slots: u64, /// Any change applied during an epoch `n` will become active at the @@ -50,6 +61,17 @@ pub struct PosParams { } impl Default for PosParams { + fn default() -> Self { + let owned = OwnedPosParams::default(); + let gov = GovernanceParameters::default(); + Self { + owned, + max_proposal_period: gov.max_proposal_period, + } + } +} + +impl Default for OwnedPosParams { fn default() -> Self { Self { max_validator_slots: 100, @@ -75,15 +97,6 @@ impl Default for PosParams { } } -/// A struct to hold both PoS and governance parameters -#[derive(Debug, Clone)] -pub struct PosAndGovParams { - /// Pos parameters - pub pos_params: PosParams, - /// Governance parameters - pub gov_params: GovernanceParameters, -} - #[allow(missing_docs)] #[derive(Error, Debug)] pub enum ValidationError { @@ -112,7 +125,7 @@ const MAX_TOTAL_VOTING_POWER: i64 = i64::MAX / 8; /// Assuming token amount is `u64` in micro units. const TOKEN_MAX_AMOUNT: u64 = u64::MAX / TOKENS_PER_NAM; -impl PosParams { +impl OwnedPosParams { /// Validate PoS parameters values. Returns an empty list if the values are /// valid. #[must_use] @@ -183,6 +196,24 @@ impl PosParams { let end = infraction_epoch + self.cubic_slashing_window_length; (start, end) } + + /// A test helper to add the default gov params to PoS params. + #[cfg(any(test, feature = "testing"))] + pub fn with_default_gov_params(self) -> PosParams { + let gov = GovernanceParameters::default(); + PosParams { + owned: self, + max_proposal_period: gov.max_proposal_period, + } + } +} + +impl std::ops::Deref for PosParams { + type Target = OwnedPosParams; + + fn deref(&self) -> &Self::Target { + &self.owned + } } #[cfg(test)] @@ -224,8 +255,8 @@ pub mod testing { unbonding_len in pipeline_len + 1..pipeline_len + 8, pipeline_len in Just(pipeline_len), tm_votes_per_token in 1..10_001_i128) - -> PosParams { - PosParams { + -> OwnedPosParams { + OwnedPosParams { max_validator_slots, pipeline_len, unbonding_len, diff --git a/proof_of_stake/src/tests.rs b/proof_of_stake/src/tests.rs index b7463c8ea5..4465bdc687 100644 --- a/proof_of_stake/src/tests.rs +++ b/proof_of_stake/src/tests.rs @@ -30,7 +30,7 @@ use proptest::test_runner::Config; use test_log::test; use crate::parameters::testing::arb_pos_params; -use crate::parameters::PosParams; +use crate::parameters::{OwnedPosParams, PosParams}; use crate::types::{ into_tm_voting_power, BondDetails, BondId, BondsAndUnbondsDetails, ConsensusValidator, GenesisValidator, Position, ReverseOrdTokenAmount, @@ -41,36 +41,35 @@ use crate::{ become_validator, below_capacity_validator_set_handle, bond_handle, bond_tokens, bonds_and_unbonds, consensus_validator_set_handle, copy_validator_sets_and_positions, find_validator_by_raw_hash, - get_num_consensus_validators, init_genesis, - insert_validator_into_validator_set, is_validator, process_slashes, - purge_validator_sets_for_old_epoch, + get_num_consensus_validators, insert_validator_into_validator_set, + is_validator, process_slashes, purge_validator_sets_for_old_epoch, read_below_capacity_validator_set_addresses_with_stake, read_below_threshold_validator_set_addresses, read_consensus_validator_set_addresses_with_stake, read_total_stake, read_validator_delta_value, read_validator_stake, slash, - staking_token_address, store_total_consensus_stake, total_deltas_handle, - unbond_handle, unbond_tokens, unjail_validator, update_validator_deltas, - update_validator_set, validator_consensus_key_handle, - validator_set_positions_handle, validator_set_update_tendermint, - validator_slashes_handle, validator_state_handle, withdraw_tokens, - write_validator_address_raw_hash, BecomeValidator, - STORE_VALIDATOR_SETS_LEN, + staking_token_address, store_total_consensus_stake, test_init_genesis, + total_deltas_handle, unbond_handle, unbond_tokens, unjail_validator, + update_validator_deltas, update_validator_set, + validator_consensus_key_handle, validator_set_positions_handle, + validator_set_update_tendermint, validator_slashes_handle, + validator_state_handle, withdraw_tokens, write_validator_address_raw_hash, + BecomeValidator, STORE_VALIDATOR_SETS_LEN, }; proptest! { - // Generate arb valid input for `test_init_genesis_aux` + // Generate arb valid input for `test_test_init_genesis_aux` #![proptest_config(Config { cases: 1, .. Config::default() })] #[test] - fn test_init_genesis( + fn test_test_init_genesis( (pos_params, genesis_validators) in arb_params_and_genesis_validators(Some(5), 1..10), start_epoch in (0_u64..1000).prop_map(Epoch), ) { - test_init_genesis_aux(pos_params, start_epoch, genesis_validators) + test_test_init_genesis_aux(pos_params, start_epoch, genesis_validators) } } @@ -144,7 +143,7 @@ proptest! { fn arb_params_and_genesis_validators( num_max_validator_slots: Option, val_size: Range, -) -> impl Strategy)> { +) -> impl Strategy)> { let params = arb_pos_params(num_max_validator_slots); params.prop_flat_map(move |params| { let validators = arb_genesis_validators( @@ -156,7 +155,7 @@ fn arb_params_and_genesis_validators( } fn test_slashes_with_unbonding_params() --> impl Strategy, u64)> { +-> impl Strategy, u64)> { let params = arb_pos_params(Some(5)); params.prop_flat_map(|params| { let unbond_delay = 0..(params.slash_processing_epoch_offset() * 2); @@ -168,8 +167,8 @@ fn test_slashes_with_unbonding_params() } /// Test genesis initialization -fn test_init_genesis_aux( - params: PosParams, +fn test_test_init_genesis_aux( + params: OwnedPosParams, start_epoch: Epoch, mut validators: Vec, ) { @@ -181,8 +180,13 @@ fn test_init_genesis_aux( s.storage.block.epoch = start_epoch; validators.sort_by(|a, b| b.tokens.cmp(&a.tokens)); - init_genesis(&mut s, ¶ms, validators.clone().into_iter(), start_epoch) - .unwrap(); + let params = test_init_genesis( + &mut s, + params, + validators.clone().into_iter(), + start_epoch, + ) + .unwrap(); let mut bond_details = bonds_and_unbonds(&s, None, None).unwrap(); assert!(bond_details.iter().all(|(_id, details)| { @@ -250,7 +254,7 @@ fn test_init_genesis_aux( /// Test bonding /// NOTE: copy validator sets each time we advance the epoch -fn test_bonds_aux(params: PosParams, validators: Vec) { +fn test_bonds_aux(params: OwnedPosParams, validators: Vec) { // This can be useful for debugging: // params.pipeline_len = 2; // params.unbonding_len = 4; @@ -260,9 +264,9 @@ fn test_bonds_aux(params: PosParams, validators: Vec) { // Genesis let start_epoch = s.storage.block.epoch; let mut current_epoch = s.storage.block.epoch; - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, validators.clone().into_iter(), current_epoch, ) @@ -801,7 +805,7 @@ fn test_bonds_aux(params: PosParams, validators: Vec) { /// Test validator initialization. fn test_become_validator_aux( - params: PosParams, + params: OwnedPosParams, new_validator: Address, new_validator_consensus_key: SecretKey, validators: Vec, @@ -815,9 +819,9 @@ fn test_become_validator_aux( // Genesis let mut current_epoch = dbg!(s.storage.block.epoch); - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, validators.clone().into_iter(), current_epoch, ) @@ -949,7 +953,7 @@ fn test_become_validator_aux( } fn test_slashes_with_unbonding_aux( - mut params: PosParams, + mut params: OwnedPosParams, validators: Vec, unbond_delay: u64, ) { @@ -975,9 +979,9 @@ fn test_slashes_with_unbonding_aux( // Genesis // let start_epoch = s.storage.block.epoch; let mut current_epoch = s.storage.block.epoch; - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, validators.clone().into_iter(), current_epoch, ) @@ -1128,7 +1132,7 @@ fn test_validator_raw_hash() { fn test_validator_sets() { let mut s = TestWlStorage::default(); // Only 3 consensus validator slots - let params = PosParams { + let params = OwnedPosParams { max_validator_slots: 3, ..Default::default() }; @@ -1145,39 +1149,6 @@ fn test_validator_sets() { res }; - // A helper to insert a non-genesis validator - let insert_validator = |s: &mut TestWlStorage, - addr, - pk: &PublicKey, - stake: token::Amount, - epoch: Epoch| { - insert_validator_into_validator_set( - s, - ¶ms, - addr, - stake, - epoch, - params.pipeline_len, - ) - .unwrap(); - - update_validator_deltas( - s, - ¶ms, - addr, - stake.change(), - epoch, - params.pipeline_len, - ) - .unwrap(); - - // Set their consensus key (needed for - // `validator_set_update_tendermint` fn) - validator_consensus_key_handle(addr) - .set(s, pk.clone(), epoch, params.pipeline_len) - .unwrap(); - }; - // Create genesis validators let ((val1, pk1), stake1) = (gen_validator(), token::Amount::native_whole(1)); @@ -1204,9 +1175,9 @@ fn test_validator_sets() { let start_epoch = Epoch::default(); let epoch = start_epoch; - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, [ GenesisValidator { address: val1.clone(), @@ -1246,6 +1217,39 @@ fn test_validator_sets() { ) .unwrap(); + // A helper to insert a non-genesis validator + let insert_validator = |s: &mut TestWlStorage, + addr, + pk: &PublicKey, + stake: token::Amount, + epoch: Epoch| { + insert_validator_into_validator_set( + s, + ¶ms, + addr, + stake, + epoch, + params.pipeline_len, + ) + .unwrap(); + + update_validator_deltas( + s, + ¶ms, + addr, + stake.change(), + epoch, + params.pipeline_len, + ) + .unwrap(); + + // Set their consensus key (needed for + // `validator_set_update_tendermint` fn) + validator_consensus_key_handle(addr) + .set(s, pk.clone(), epoch, params.pipeline_len) + .unwrap(); + }; + // Advance to EPOCH 1 // // We cannot call `get_tendermint_set_updates` for the genesis state as @@ -1804,7 +1808,7 @@ fn test_validator_sets() { fn test_validator_sets_swap() { let mut s = TestWlStorage::default(); // Only 2 consensus validator slots - let params = PosParams { + let params = OwnedPosParams { max_validator_slots: 2, // Set the stake threshold to 0 so no validators are in the // below-threshold set @@ -1826,39 +1830,6 @@ fn test_validator_sets_swap() { res }; - // A helper to insert a non-genesis validator - let insert_validator = |s: &mut TestWlStorage, - addr, - pk: &PublicKey, - stake: token::Amount, - epoch: Epoch| { - insert_validator_into_validator_set( - s, - ¶ms, - addr, - stake, - epoch, - params.pipeline_len, - ) - .unwrap(); - - update_validator_deltas( - s, - ¶ms, - addr, - stake.change(), - epoch, - params.pipeline_len, - ) - .unwrap(); - - // Set their consensus key (needed for - // `validator_set_update_tendermint` fn) - validator_consensus_key_handle(addr) - .set(s, pk.clone(), epoch, params.pipeline_len) - .unwrap(); - }; - // Start with two genesis validators, one with 1 voting power and other 0 let epoch = Epoch::default(); // 1M voting power @@ -1874,9 +1845,9 @@ fn test_validator_sets_swap() { println!("val2: {val2}, {pk2}, {}", stake2.to_string_native()); println!("val3: {val3}, {pk3}, {}", stake3.to_string_native()); - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, [ GenesisValidator { address: val1, @@ -1916,6 +1887,39 @@ fn test_validator_sets_swap() { ) .unwrap(); + // A helper to insert a non-genesis validator + let insert_validator = |s: &mut TestWlStorage, + addr, + pk: &PublicKey, + stake: token::Amount, + epoch: Epoch| { + insert_validator_into_validator_set( + s, + ¶ms, + addr, + stake, + epoch, + params.pipeline_len, + ) + .unwrap(); + + update_validator_deltas( + s, + ¶ms, + addr, + stake.change(), + epoch, + params.pipeline_len, + ) + .unwrap(); + + // Set their consensus key (needed for + // `validator_set_update_tendermint` fn) + validator_consensus_key_handle(addr) + .set(s, pk.clone(), epoch, params.pipeline_len) + .unwrap(); + }; + // Advance to EPOCH 1 let epoch = advance_epoch(&mut s, ¶ms); let pipeline_epoch = epoch + params.pipeline_len; @@ -2043,7 +2047,7 @@ fn get_tendermint_set_updates( } /// Advance to the next epoch. Returns the new epoch. -fn advance_epoch(s: &mut TestWlStorage, params: &PosParams) -> Epoch { +fn advance_epoch(s: &mut TestWlStorage, params: &OwnedPosParams) -> Epoch { s.storage.block.epoch = s.storage.block.epoch.next(); let current_epoch = s.storage.block.epoch; store_total_consensus_stake(s, current_epoch).unwrap(); @@ -2131,7 +2135,7 @@ fn arb_genesis_validators( } fn test_unjail_validator_aux( - params: PosParams, + params: OwnedPosParams, mut validators: Vec, ) { println!("\nTest inputs: {params:?}, genesis validators: {validators:#?}"); @@ -2153,9 +2157,9 @@ fn test_unjail_validator_aux( // Genesis let mut current_epoch = s.storage.block.epoch; - init_genesis( + let params = test_init_genesis( &mut s, - ¶ms, + params, validators.clone().into_iter(), current_epoch, ) diff --git a/proof_of_stake/src/tests/state_machine.rs b/proof_of_stake/src/tests/state_machine.rs index 6c9968c519..05b9b26345 100644 --- a/proof_of_stake/src/tests/state_machine.rs +++ b/proof_of_stake/src/tests/state_machine.rs @@ -151,9 +151,9 @@ impl StateMachineTest for ConcretePosState { .collect::>() ); let mut s = TestWlStorage::default(); - crate::init_genesis( + crate::test_init_genesis( &mut s, - &initial_state.params, + initial_state.params.owned.clone(), initial_state.genesis_validators.clone().into_iter(), initial_state.epoch, ) @@ -1197,6 +1197,7 @@ impl ReferenceStateMachine for AbstractPosState { println!("\nInitializing abstract state machine"); arb_params_and_genesis_validators(Some(8), 8..10) .prop_map(|(params, genesis_validators)| { + let params = params.with_default_gov_params(); let epoch = Epoch::default(); let mut state = Self { epoch, diff --git a/shared/src/ledger/native_vp/ibc/mod.rs b/shared/src/ledger/native_vp/ibc/mod.rs index 3b6521905b..818aa4df79 100644 --- a/shared/src/ledger/native_vp/ibc/mod.rs +++ b/shared/src/ledger/native_vp/ibc/mod.rs @@ -293,6 +293,7 @@ mod tests { use borsh::BorshSerialize; use namada_core::ledger::gas::TxGasMeter; + use namada_core::ledger::governance::parameters::GovernanceParameters; use prost::Message; use sha2::Digest; @@ -409,6 +410,8 @@ mod tests { // initialize the storage ibc::init_genesis_storage(&mut wl_storage); + let gov_params = GovernanceParameters::default(); + gov_params.init_storage(&mut wl_storage).unwrap(); pos::init_genesis_storage( &mut wl_storage, &PosParams::default(), diff --git a/shared/src/ledger/pos/mod.rs b/shared/src/ledger/pos/mod.rs index a61a721e4f..d47e5cc884 100644 --- a/shared/src/ledger/pos/mod.rs +++ b/shared/src/ledger/pos/mod.rs @@ -11,7 +11,7 @@ pub use namada_core::types::dec::Dec; pub use namada_core::types::key::common; pub use namada_core::types::token; pub use namada_proof_of_stake; -pub use namada_proof_of_stake::parameters::PosParams; +pub use namada_proof_of_stake::parameters::{OwnedPosParams, PosParams}; pub use namada_proof_of_stake::pos_queries::*; pub use namada_proof_of_stake::storage::*; pub use namada_proof_of_stake::{staking_token_address, types}; @@ -42,7 +42,7 @@ pub fn into_tm_voting_power( /// Initialize storage in the genesis block. pub fn init_genesis_storage( storage: &mut S, - params: &PosParams, + params: &OwnedPosParams, validators: impl Iterator + Clone, current_epoch: Epoch, ) where diff --git a/tests/src/native_vp/pos.rs b/tests/src/native_vp/pos.rs index 344a75d4e3..4140c08b7f 100644 --- a/tests/src/native_vp/pos.rs +++ b/tests/src/native_vp/pos.rs @@ -95,9 +95,9 @@ //! - add slashes //! - add rewards -use namada::ledger::pos::namada_proof_of_stake::init_genesis; -use namada::proof_of_stake::parameters::PosParams; +use namada::proof_of_stake::parameters::{OwnedPosParams, PosParams}; use namada::proof_of_stake::storage::GenesisValidator; +use namada::proof_of_stake::test_init_genesis as init_genesis; use namada::types::storage::Epoch; use crate::tx::tx_host_env; @@ -106,9 +106,9 @@ use crate::tx::tx_host_env; /// parameters. pub fn init_pos( genesis_validators: &[GenesisValidator], - params: &PosParams, + params: &OwnedPosParams, start_epoch: Epoch, -) { +) -> PosParams { tx_host_env::init(); tx_host_env::with(|tx_env| { @@ -130,9 +130,9 @@ pub fn init_pos( // .storage // .init_genesis(params, genesis_validators.iter(), start_epoch) // .unwrap(); - init_genesis( + let params = init_genesis( &mut tx_env.wl_storage, - params, + params.clone(), genesis_validators.iter().cloned(), start_epoch, ) @@ -140,7 +140,8 @@ pub fn init_pos( // Commit changes in WL to genesis state tx_env.commit_genesis(); - }); + params + }) } #[cfg(test)] @@ -334,6 +335,7 @@ mod tests { // We're starting from an empty state let state = vec![]; let epoch = Epoch(epoch); + let params = params.with_default_gov_params(); arb_valid_pos_action(&state).prop_map(move |valid_action| { Self { epoch, diff --git a/tests/src/vm_host_env/ibc.rs b/tests/src/vm_host_env/ibc.rs index b8d88961ea..9cd1caebdb 100644 --- a/tests/src/vm_host_env/ibc.rs +++ b/tests/src/vm_host_env/ibc.rs @@ -84,6 +84,7 @@ use namada::types::time::DurationSecs; use namada::types::token::{self, Amount, DenominatedAmount}; use namada::vm::{wasm, WasmCacheRwAccess}; use namada_core::ledger::gas::TxGasMeter; +use namada_core::ledger::governance::parameters::GovernanceParameters; use namada_test_utils::TestWasms; use namada_tx_prelude::BorshSerialize; @@ -211,6 +212,8 @@ pub fn init_storage() -> (Address, Address) { tx_host_env::with(|env| { ibc::init_genesis_storage(&mut env.wl_storage); + let gov_params = GovernanceParameters::default(); + gov_params.init_storage(&mut env.wl_storage).unwrap(); pos::init_genesis_storage( &mut env.wl_storage, &PosParams::default(), diff --git a/wasm/wasm_source/src/tx_bond.rs b/wasm/wasm_source/src/tx_bond.rs index 3453747161..509a50f822 100644 --- a/wasm/wasm_source/src/tx_bond.rs +++ b/wasm/wasm_source/src/tx_bond.rs @@ -17,7 +17,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { mod tests { use std::collections::BTreeSet; - use namada::ledger::pos::{GenesisValidator, PosParams, PosVP}; + use namada::ledger::pos::{GenesisValidator, OwnedPosParams, PosVP}; use namada::proof_of_stake::{ bond_handle, read_consensus_validator_set_addresses_with_stake, read_total_stake, read_validator_stake, @@ -64,10 +64,10 @@ mod tests { initial_stake: token::Amount, bond: transaction::pos::Bond, key: key::common::SecretKey, - pos_params: PosParams, + pos_params: OwnedPosParams, ) -> TxResult { // Remove the validator stake threshold for simplicity - let pos_params = PosParams { + let pos_params = OwnedPosParams { validator_stake_threshold: token::Amount::default(), ..pos_params }; @@ -91,7 +91,8 @@ mod tests { max_commission_rate_change, }]; - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + let pos_params = + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); let native_token = tx_host_env::with(|tx_env| { if let Some(source) = &bond.source { diff --git a/wasm/wasm_source/src/tx_change_validator_commission.rs b/wasm/wasm_source/src/tx_change_validator_commission.rs index c1e1b35226..b8db50ecb0 100644 --- a/wasm/wasm_source/src/tx_change_validator_commission.rs +++ b/wasm/wasm_source/src/tx_change_validator_commission.rs @@ -19,7 +19,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { mod tests { use std::cmp; - use namada::ledger::pos::{PosParams, PosVP}; + use namada::ledger::pos::{OwnedPosParams, PosVP}; use namada::proof_of_stake::validator_commission_rate_handle; use namada::types::dec::{Dec, POS_DECIMAL_PRECISION}; use namada::types::storage::Epoch; @@ -63,7 +63,7 @@ mod tests { max_change: Dec, commission_change: transaction::pos::CommissionChange, key: key::common::SecretKey, - pos_params: PosParams, + pos_params: OwnedPosParams, ) -> TxResult { let consensus_key = key::testing::keypair_1().ref_to(); let eth_hot_key = key::common::PublicKey::Secp256k1( @@ -82,7 +82,8 @@ mod tests { eth_cold_key, }]; - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + let pos_params = + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); let tx_code = vec![]; let tx_data = commission_change.try_to_vec().unwrap(); diff --git a/wasm/wasm_source/src/tx_unbond.rs b/wasm/wasm_source/src/tx_unbond.rs index 7e08c0dcda..5e1eaeb2a3 100644 --- a/wasm/wasm_source/src/tx_unbond.rs +++ b/wasm/wasm_source/src/tx_unbond.rs @@ -17,7 +17,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { mod tests { use std::collections::BTreeSet; - use namada::ledger::pos::{GenesisValidator, PosParams, PosVP}; + use namada::ledger::pos::{GenesisValidator, OwnedPosParams, PosVP}; use namada::proof_of_stake::types::WeightedValidator; use namada::proof_of_stake::{ bond_handle, read_consensus_validator_set_addresses_with_stake, @@ -62,10 +62,10 @@ mod tests { initial_stake: token::Amount, unbond: transaction::pos::Unbond, key: key::common::SecretKey, - pos_params: PosParams, + pos_params: OwnedPosParams, ) -> TxResult { // Remove the validator stake threshold for simplicity - let pos_params = PosParams { + let pos_params = OwnedPosParams { validator_stake_threshold: token::Amount::default(), ..pos_params }; @@ -96,7 +96,8 @@ mod tests { max_commission_rate_change, }]; - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + let pos_params = + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); let native_token = tx_host_env::with(|tx_env| { let native_token = tx_env.wl_storage.storage.native_token.clone(); diff --git a/wasm/wasm_source/src/tx_withdraw.rs b/wasm/wasm_source/src/tx_withdraw.rs index c8fa649c43..e288282c42 100644 --- a/wasm/wasm_source/src/tx_withdraw.rs +++ b/wasm/wasm_source/src/tx_withdraw.rs @@ -20,7 +20,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { #[cfg(test)] mod tests { - use namada::ledger::pos::{GenesisValidator, PosParams, PosVP}; + use namada::ledger::pos::{GenesisValidator, OwnedPosParams, PosVP}; use namada::proof_of_stake::unbond_handle; use namada::types::dec::Dec; use namada::types::storage::Epoch; @@ -67,10 +67,10 @@ mod tests { unbonded_amount: token::Amount, withdraw: transaction::pos::Withdraw, key: key::common::SecretKey, - pos_params: PosParams, + pos_params: OwnedPosParams, ) -> TxResult { // Remove the validator stake threshold for simplicity - let pos_params = PosParams { + let pos_params = OwnedPosParams { validator_stake_threshold: token::Amount::default(), ..pos_params }; @@ -100,7 +100,8 @@ mod tests { max_commission_rate_change, }]; - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + let pos_params = + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); let native_token = tx_host_env::with(|tx_env| { let native_token = tx_env.wl_storage.storage.native_token.clone(); diff --git a/wasm/wasm_source/src/vp_validator.rs b/wasm/wasm_source/src/vp_validator.rs index f929a8a0d1..77a8c76d66 100644 --- a/wasm/wasm_source/src/vp_validator.rs +++ b/wasm/wasm_source/src/vp_validator.rs @@ -191,7 +191,7 @@ fn validate_tx( #[cfg(test)] mod tests { use address::testing::arb_non_internal_address; - use namada::ledger::pos::{GenesisValidator, PosParams}; + use namada::ledger::pos::{GenesisValidator, OwnedPosParams}; use namada::proto::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; @@ -421,7 +421,7 @@ mod tests { #[test] fn test_unsigned_pos_action_rejected() { // Init PoS genesis - let pos_params = PosParams::default(); + let pos_params = OwnedPosParams::default(); let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); @@ -504,7 +504,7 @@ mod tests { #[test] fn test_signed_pos_action_accepted() { // Init PoS genesis - let pos_params = PosParams::default(); + let pos_params = OwnedPosParams::default(); let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); From bfe4c97c0bebd489e343ec6755722dde9846b42b Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 27 Sep 2023 18:15:19 -0600 Subject: [PATCH 09/26] pos/types: configure number of past epochs kept for PoS data --- proof_of_stake/src/epoched.rs | 107 +++++++++++++++++++++++++++++++++- proof_of_stake/src/types.rs | 6 +- 2 files changed, 109 insertions(+), 4 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 5c119fee3c..25dcbcb7f3 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use std::fmt::Debug; use std::marker::PhantomData; -use std::ops; +use std::{cmp, ops}; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use namada_core::ledger::storage_api; @@ -813,6 +813,106 @@ impl EpochOffset for OffsetMaxU64 { } } +/// Offset at max proposal period. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetMaxProposalPeriod; +impl EpochOffset for OffsetMaxProposalPeriod { + fn value(params: &PosParams) -> u64 { + params.max_proposal_period + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::MaxProposalPeriod + } +} + +/// Offset at the max proposal period, plus the default num past epochs. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetMaxProposalPeriodPlus; +impl EpochOffset for OffsetMaxProposalPeriodPlus { + fn value(params: &PosParams) -> u64 { + params.max_proposal_period + DEFAULT_NUM_PAST_EPOCHS + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::MaxProposalPeriodPlus + } +} + +/// Offset at the larger of the slash processing length and the max proposal +/// period. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetMaxProposalPeriodOrSlashProcessingLen; +impl EpochOffset for OffsetMaxProposalPeriodOrSlashProcessingLen { + fn value(params: &PosParams) -> u64 { + cmp::max( + params.slash_processing_epoch_offset(), + params.max_proposal_period, + ) + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::MaxProposalPeriodOrSlashProcessingLen + } +} + +/// Offset at the larger of the slash processing length and the max proposal +/// period, plus the default num past epochs. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetMaxProposalPeriodOrSlashProcessingLenPlus; +impl EpochOffset for OffsetMaxProposalPeriodOrSlashProcessingLenPlus { + fn value(params: &PosParams) -> u64 { + cmp::max( + params.slash_processing_epoch_offset(), + params.max_proposal_period, + ) + DEFAULT_NUM_PAST_EPOCHS + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::MaxProposalPeriodOrSlashProcessingLenPlus + } +} + /// Offset length dynamic choice. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum DynEpochOffset { @@ -833,8 +933,13 @@ pub enum DynEpochOffset { SlashProcessingLen, /// Offset at the max proposal period MaxProposalPeriod, + /// Offset at the max proposal period plus the default num past epochs + MaxProposalPeriodPlus, /// Offset at the larger of max proposal period or slash processing delay MaxProposalPeriodOrSlashProcessingLen, + /// Offset at the larger of max proposal period or slash processing delay, + /// plus the default num past epochs + MaxProposalPeriodOrSlashProcessingLenPlus, /// Offset of the max u64 value MaxU64, } diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 2ec8e4fd86..88881aae84 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -77,7 +77,7 @@ pub type BelowCapacityValidatorSet = pub type ConsensusValidatorSets = crate::epoched::NestedEpoched< ConsensusValidatorSet, crate::epoched::OffsetPipelineLen, - crate::epoched::OffsetDefaultNumPastEpochs, + crate::epoched::OffsetMaxProposalPeriodPlus, >; /// Epoched below-capacity validator sets. @@ -98,7 +98,7 @@ pub type TotalConsensusStakes = crate::epoched::Epoched< pub type ValidatorDeltas = crate::epoched::EpochedDelta< token::Change, crate::epoched::OffsetUnbondingLen, - crate::epoched::OffsetSlashProcessingLen, + crate::epoched::OffsetMaxProposalPeriodOrSlashProcessingLenPlus, >; /// Epoched total deltas. @@ -141,7 +141,7 @@ pub type ValidatorSlashes = NestedMap; pub type EpochedSlashes = crate::epoched::NestedEpoched< ValidatorSlashes, crate::epoched::OffsetUnbondingLen, - crate::epoched::OffsetSlashProcessingLen, + crate::epoched::OffsetSlashProcessingLen, /* TODO: should this be slash procesing + cubic window? */ >; /// Epoched validator's unbonds From eaed1895931d7fde66164d11d11bf1fbddaaa9dc Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 27 Sep 2023 18:21:10 -0600 Subject: [PATCH 10/26] new impl for purging old validator sets --- .../lib/node/ledger/shell/finalize_block.rs | 178 +++++++++++++++++- benches/lib.rs | 9 +- proof_of_stake/src/epoched.rs | 110 ++++++++++- proof_of_stake/src/lib.rs | 46 ++--- proof_of_stake/src/tests.rs | 12 +- 5 files changed, 312 insertions(+), 43 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 2f8f970210..739d803bc2 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -100,6 +100,7 @@ where namada_proof_of_stake::read_pos_params(&self.wl_storage)?; namada_proof_of_stake::copy_validator_sets_and_positions( &mut self.wl_storage, + &pos_params, current_epoch, current_epoch + pos_params.pipeline_len, )?; @@ -107,10 +108,6 @@ where &mut self.wl_storage, current_epoch, )?; - namada_proof_of_stake::purge_validator_sets_for_old_epoch( - &mut self.wl_storage, - current_epoch, - )?; } // Invariant: Has to be applied before `record_slashes_from_evidence` @@ -3823,6 +3820,179 @@ mod test_finalize_block { Ok(()) } + #[test] + fn test_purge_validator_information() -> storage_api::Result<()> { + // Setup the network with pipeline_len = 2, unbonding_len = 4 + let num_validators = 4_u64; + let (mut shell, _recv, _, _) = setup_with_cfg(SetupCfg { + last_height: 0, + num_validators, + }); + let mut params = read_pos_params(&shell.wl_storage).unwrap(); + params.owned.unbonding_len = 4; + // params.owned.max_validator_slots = 3; + // params.owned.validator_stake_threshold = token::Amount::zero(); + write_pos_params(&mut shell.wl_storage, ¶ms.owned)?; + + let max_proposal_period = params.max_proposal_period; + let default_past_epochs = 2; + let consensus_val_set_len = max_proposal_period + default_past_epochs; + + let consensus_val_set = + namada_proof_of_stake::consensus_validator_set_handle(); + // let below_cap_val_set = + // namada_proof_of_stake::below_capacity_validator_set_handle(); + let validator_positions = + namada_proof_of_stake::validator_set_positions_handle(); + let all_validator_addresses = + namada_proof_of_stake::validator_addresses_handle(); + + let consensus_set: Vec = + read_consensus_validator_set_addresses_with_stake( + &shell.wl_storage, + Epoch::default(), + ) + .unwrap() + .into_iter() + .collect(); + let val1 = consensus_set[0].clone(); + let pkh1 = get_pkh_from_address( + &shell.wl_storage, + ¶ms, + val1.address, + Epoch::default(), + ); + + // Finalize block 1 + next_block_for_inflation(&mut shell, pkh1.clone(), vec![], None); + + let votes = get_default_true_votes(&shell.wl_storage, Epoch::default()); + assert!(!votes.is_empty()); + + let check_is_data = |storage: &WlStorage<_, _>, + start: Epoch, + end: Epoch| { + for ep in Epoch::iter_bounds_inclusive(start, end) { + assert!(!consensus_val_set.at(&ep).is_empty(storage).unwrap()); + // assert!(!below_cap_val_set.at(&ep).is_empty(storage). + // unwrap()); + assert!( + !validator_positions.at(&ep).is_empty(storage).unwrap() + ); + assert!( + !all_validator_addresses.at(&ep).is_empty(storage).unwrap() + ); + } + }; + + // Check that there is validator data for epochs 0 - pipeline_len + check_is_data(&shell.wl_storage, Epoch(0), Epoch(params.pipeline_len)); + + // Advance to epoch `default_past_epochs` + let mut current_epoch = Epoch(0); + for _ in 0..default_past_epochs { + let votes = get_default_true_votes( + &shell.wl_storage, + shell.wl_storage.storage.block.epoch, + ); + current_epoch = advance_epoch(&mut shell, &pkh1, &votes, None); + } + assert_eq!(shell.wl_storage.storage.block.epoch.0, default_past_epochs); + assert_eq!(current_epoch.0, default_past_epochs); + + check_is_data( + &shell.wl_storage, + Epoch(0), + Epoch(params.pipeline_len + default_past_epochs), + ); + + // Advance one more epoch, which should purge the data for epoch 0 in + // everything except the consensus validator set + let votes = get_default_true_votes( + &shell.wl_storage, + shell.wl_storage.storage.block.epoch, + ); + current_epoch = advance_epoch(&mut shell, &pkh1, &votes, None); + assert_eq!(current_epoch.0, default_past_epochs + 1); + + check_is_data( + &shell.wl_storage, + Epoch(1), + Epoch(params.pipeline_len + default_past_epochs + 1), + ); + assert!( + !consensus_val_set + .at(&Epoch(0)) + .is_empty(&shell.wl_storage) + .unwrap() + ); + assert!( + validator_positions + .at(&Epoch(0)) + .is_empty(&shell.wl_storage) + .unwrap() + ); + assert!( + all_validator_addresses + .at(&Epoch(0)) + .is_empty(&shell.wl_storage) + .unwrap() + ); + + // Advance to the epoch `consensus_val_set_len` + 1 + loop { + assert!( + !consensus_val_set + .at(&Epoch(0)) + .is_empty(&shell.wl_storage) + .unwrap() + ); + let votes = get_default_true_votes( + &shell.wl_storage, + shell.wl_storage.storage.block.epoch, + ); + current_epoch = advance_epoch(&mut shell, &pkh1, &votes, None); + if current_epoch.0 == consensus_val_set_len + 1 { + break; + } + } + + assert!( + consensus_val_set + .at(&Epoch(0)) + .is_empty(&shell.wl_storage) + .unwrap() + ); + + // Advance one more epoch + let votes = get_default_true_votes( + &shell.wl_storage, + shell.wl_storage.storage.block.epoch, + ); + current_epoch = advance_epoch(&mut shell, &pkh1, &votes, None); + for ep in Epoch::default().iter_range(2) { + assert!( + consensus_val_set + .at(&ep) + .is_empty(&shell.wl_storage) + .unwrap() + ); + } + for ep in Epoch::iter_bounds_inclusive( + Epoch(2), + current_epoch + params.pipeline_len, + ) { + assert!( + !consensus_val_set + .at(&ep) + .is_empty(&shell.wl_storage) + .unwrap() + ); + } + + Ok(()) + } + fn get_default_true_votes(storage: &S, epoch: Epoch) -> Vec where S: StorageRead, diff --git a/benches/lib.rs b/benches/lib.rs index 47645abdf4..d247d3872d 100644 --- a/benches/lib.rs +++ b/benches/lib.rs @@ -267,10 +267,8 @@ impl BenchShell { } pub fn advance_epoch(&mut self) { - let pipeline_len = - proof_of_stake::read_pos_params(&self.inner.wl_storage) - .unwrap() - .pipeline_len; + let params = + proof_of_stake::read_pos_params(&self.inner.wl_storage).unwrap(); self.wl_storage.storage.block.epoch = self.wl_storage.storage.block.epoch.next(); @@ -278,8 +276,9 @@ impl BenchShell { proof_of_stake::copy_validator_sets_and_positions( &mut self.wl_storage, + ¶ms, current_epoch, - current_epoch + pipeline_len, + current_epoch + params.pipeline_len, ) .unwrap(); } diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 25dcbcb7f3..553eda01ef 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -26,7 +26,7 @@ pub const LAST_UPDATE_SUB_KEY: &str = "last_update"; pub const OLDEST_EPOCH_SUB_KEY: &str = "oldest_epoch"; /// Default number of past epochs to keep. -const DEFAULT_NUM_PAST_EPOCHS: u64 = 2; +pub const DEFAULT_NUM_PAST_EPOCHS: u64 = 2; /// Discrete epoched data handle pub struct Epoched { @@ -168,7 +168,7 @@ where /// kept is dropped. If the oldest stored epoch is not already /// associated with some value, the latest value from the dropped /// values, if any, is associated with it. - fn update_data( + pub fn update_data( &self, storage: &mut S, params: &PosParams, @@ -335,7 +335,8 @@ where S: StorageWrite + StorageRead, { let key = self.get_last_update_storage_key(); - storage.write(&key, epoch) + storage.write(&key, epoch)?; + self.set_oldest_epoch(storage, epoch) } fn get_last_update_storage_key(&self) -> storage::Key { @@ -368,6 +369,109 @@ where let key = self.get_last_update_storage_key(); storage.write(&key, current_epoch) } + + fn get_oldest_epoch_storage_key(&self) -> storage::Key { + self.storage_prefix + .push(&OLDEST_EPOCH_SUB_KEY.to_owned()) + .unwrap() + } + + fn get_oldest_epoch( + &self, + storage: &S, + ) -> storage_api::Result> + where + S: StorageRead, + { + let key = self.get_oldest_epoch_storage_key(); + storage.read(&key) + } + + fn set_oldest_epoch( + &self, + storage: &mut S, + new_oldest_epoch: Epoch, + ) -> storage_api::Result<()> + where + S: StorageRead + StorageWrite, + { + let key = self.get_oldest_epoch_storage_key(); + storage.write(&key, new_oldest_epoch) + } + + fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { + Epoch( + epoch + .0 + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default(), + ) + } + + /// Update data by removing old epochs + /// TODO: should we consider more complex handling of empty epochs in the + /// data below? + pub fn update_data( + &self, + storage: &mut S, + params: &PosParams, + current_epoch: Epoch, + ) -> storage_api::Result<()> + where + S: StorageRead + StorageWrite, + { + let last_update = self.get_last_update(storage)?; + let oldest_epoch = self.get_oldest_epoch(storage)?; + println!( + "\nLast update = {:?}\nOldest epoch = {:?}\n", + last_update, oldest_epoch + ); + if let (Some(last_update), Some(oldest_epoch)) = + (last_update, oldest_epoch) + { + let oldest_to_keep = current_epoch + .0 + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default(); + if oldest_epoch.0 < oldest_to_keep { + let diff = oldest_to_keep - oldest_epoch.0; + // Go through the epochs before the expected oldest epoch and + // keep the latest one + tracing::debug!( + "Trimming nested epoched data in epoch {current_epoch}, \ + last updated at {last_update}." + ); + let data_handler = self.get_data_handler(); + // Remove data before the new oldest epoch, keep the latest + // value + dbg!(&diff); + for epoch in oldest_epoch.iter_range(diff) { + let was_data = data_handler.remove_all(storage, &epoch)?; + if was_data { + tracing::debug!( + "Removed inner map data at epoch {epoch}" + ); + } else { + tracing::debug!("WARNING: was no data in {epoch}"); + } + } + let new_oldest_epoch = + Self::sub_past_epochs(params, current_epoch); + + // if !data_handler.contains(storage, &new_oldest_epoch)? { + // panic!("WARNING: no data existing in + // {new_oldest_epoch}"); } + self.set_oldest_epoch(storage, new_oldest_epoch)?; + + // Update the epoch of the last update to the current epoch + let key = self.get_last_update_storage_key(); + storage.write(&key, current_epoch)?; + return Ok(()); + } + } + + Ok(()) + } } impl diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 3645a84d05..d8af48a1ff 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -85,10 +85,6 @@ pub fn staking_token_address(storage: &impl StorageRead) -> Address { .expect("Must be able to read native token address") } -/// Number of epochs below the current epoch for which full validator sets are -/// stored -const STORE_VALIDATOR_SETS_LEN: u64 = 2; - #[allow(missing_docs)] #[derive(Error, Debug)] pub enum GenesisError { @@ -505,7 +501,12 @@ where credit_tokens(storage, &staking_token, &ADDRESS, total_bonded)?; // Copy the genesis validator set into the pipeline epoch as well for epoch in (current_epoch.next()).iter_range(params.pipeline_len) { - copy_validator_sets_and_positions(storage, current_epoch, epoch)?; + copy_validator_sets_and_positions( + storage, + ¶ms, + current_epoch, + epoch, + )?; } tracing::debug!("Genesis initialized"); @@ -1554,6 +1555,7 @@ where /// Validator sets and positions copying into a future epoch pub fn copy_validator_sets_and_positions( storage: &mut S, + params: &PosParams, current_epoch: Epoch, target_epoch: Epoch, ) -> storage_api::Result<()> @@ -1623,6 +1625,9 @@ where .at(&val_stake) .insert(storage, val_position, val_address)?; } + // Purge consensus and below-capacity validator sets + consensus_validator_set.update_data(storage, params, current_epoch)?; + below_capacity_validator_set.update_data(storage, params, current_epoch)?; // Copy validator positions let mut positions = HashMap::::default(); @@ -1641,6 +1646,13 @@ where } validator_set_positions_handle.set_last_update(storage, current_epoch)?; + // Purge old epochs of validator positions + validator_set_positions_handle.update_data( + storage, + params, + current_epoch, + )?; + // Copy set of all validator addresses let mut all_validators = HashSet::
::default(); let validator_addresses_handle = validator_addresses_handle(); @@ -1656,6 +1668,9 @@ where debug_assert!(!was_in); } + // Purge old epochs of all validator addresses + validator_addresses_handle.update_data(storage, params, current_epoch)?; + Ok(()) } @@ -1700,27 +1715,6 @@ where total_consensus_stake_key_handle().set(storage, total, epoch, 0) } -/// Purge the validator sets from the epochs older than the current epoch minus -/// `STORE_VALIDATOR_SETS_LEN` -pub fn purge_validator_sets_for_old_epoch( - storage: &mut S, - epoch: Epoch, -) -> storage_api::Result<()> -where - S: StorageRead + StorageWrite, -{ - if Epoch(STORE_VALIDATOR_SETS_LEN) < epoch { - let old_epoch = epoch - STORE_VALIDATOR_SETS_LEN - 1; - consensus_validator_set_handle() - .get_data_handler() - .remove_all(storage, &old_epoch)?; - below_capacity_validator_set_handle() - .get_data_handler() - .remove_all(storage, &old_epoch)?; - } - Ok(()) -} - /// Read the position of the validator in the subset of validators that have the /// same bonded stake. This information is held in its own epoched structure in /// addition to being inside the validator sets. diff --git a/proof_of_stake/src/tests.rs b/proof_of_stake/src/tests.rs index 4465bdc687..2319319d54 100644 --- a/proof_of_stake/src/tests.rs +++ b/proof_of_stake/src/tests.rs @@ -29,6 +29,7 @@ use proptest::test_runner::Config; // `tracing` logs from tests use test_log::test; +use crate::epoched::DEFAULT_NUM_PAST_EPOCHS; use crate::parameters::testing::arb_pos_params; use crate::parameters::{OwnedPosParams, PosParams}; use crate::types::{ @@ -42,7 +43,7 @@ use crate::{ bond_tokens, bonds_and_unbonds, consensus_validator_set_handle, copy_validator_sets_and_positions, find_validator_by_raw_hash, get_num_consensus_validators, insert_validator_into_validator_set, - is_validator, process_slashes, purge_validator_sets_for_old_epoch, + is_validator, process_slashes, read_below_capacity_validator_set_addresses_with_stake, read_below_threshold_validator_set_addresses, read_consensus_validator_set_addresses_with_stake, read_total_stake, @@ -53,7 +54,7 @@ use crate::{ validator_consensus_key_handle, validator_set_positions_handle, validator_set_update_tendermint, validator_slashes_handle, validator_state_handle, withdraw_tokens, write_validator_address_raw_hash, - BecomeValidator, STORE_VALIDATOR_SETS_LEN, + BecomeValidator, }; proptest! { @@ -1780,7 +1781,7 @@ fn test_validator_sets() { for e in Epoch::iter_bounds_inclusive( start_epoch, last_epoch - .sub_or_default(Epoch(STORE_VALIDATOR_SETS_LEN)) + .sub_or_default(Epoch(DEFAULT_NUM_PAST_EPOCHS)) .sub_or_default(Epoch(1)), ) { assert!( @@ -2047,17 +2048,18 @@ fn get_tendermint_set_updates( } /// Advance to the next epoch. Returns the new epoch. -fn advance_epoch(s: &mut TestWlStorage, params: &OwnedPosParams) -> Epoch { +fn advance_epoch(s: &mut TestWlStorage, params: &PosParams) -> Epoch { s.storage.block.epoch = s.storage.block.epoch.next(); let current_epoch = s.storage.block.epoch; store_total_consensus_stake(s, current_epoch).unwrap(); copy_validator_sets_and_positions( s, + params, current_epoch, current_epoch + params.pipeline_len, ) .unwrap(); - purge_validator_sets_for_old_epoch(s, current_epoch).unwrap(); + // purge_validator_sets_for_old_epoch(s, current_epoch).unwrap(); // process_slashes(s, current_epoch).unwrap(); // dbg!(current_epoch); current_epoch From 85bf4aa5f1271b18ba00b06cd740d364399228cf Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 27 Sep 2023 18:21:59 -0600 Subject: [PATCH 11/26] docstring cleanup --- proof_of_stake/src/epoched.rs | 2 +- proof_of_stake/src/types.rs | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 553eda01ef..d608f6a98c 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -325,7 +325,7 @@ where NestedMap::open(key) } - /// Initialize new nested data at the given epoch offset. + /// Initialize new nested data at the given epoch. pub fn init( &self, storage: &mut S, diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 88881aae84..8807b8072e 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -24,7 +24,8 @@ pub use rev_order::ReverseOrdTokenAmount; use crate::parameters::PosParams; -// TODO: add this to the spec +// TODO: review the offsets for each epoched type!! + /// Stored positions of validators in validator sets pub type ValidatorSetPositions = crate::epoched::NestedEpoched< LazyMap, @@ -32,8 +33,6 @@ pub type ValidatorSetPositions = crate::epoched::NestedEpoched< crate::epoched::OffsetDefaultNumPastEpochs, >; -// TODO: check the offsets for each epoched type!! - /// Epoched validator's consensus key. pub type ValidatorConsensusKeys = crate::epoched::Epoched< common::PublicKey, @@ -87,7 +86,7 @@ pub type BelowCapacityValidatorSets = crate::epoched::NestedEpoched< crate::epoched::OffsetDefaultNumPastEpochs, >; -/// Epoched total consensus validator stake +/// Epoched total consensus validator set stake pub type TotalConsensusStakes = crate::epoched::Epoched< Amount, crate::epoched::OffsetZero, @@ -123,7 +122,7 @@ pub type Bonds = crate::epoched::EpochedDelta< >; /// An epoched lazy set of all known active validator addresses (consensus, -/// below-capacity, jailed) +/// below-capacity, below-threshold, jailed) pub type ValidatorAddresses = crate::epoched::NestedEpoched< LazySet
, crate::epoched::OffsetPipelineLen, From 6364cc09af7fed0ba563e7bb263120a4f7098e72 Mon Sep 17 00:00:00 2001 From: Tomas Zemanovic Date: Thu, 28 Sep 2023 14:16:13 +0200 Subject: [PATCH 12/26] Apply suggestions from code review Co-authored-by: Tiago Carvalho --- core/src/ledger/storage_api/governance.rs | 2 +- proof_of_stake/src/epoched.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/core/src/ledger/storage_api/governance.rs b/core/src/ledger/storage_api/governance.rs index e5b27a5d02..ab4ad27b0b 100644 --- a/core/src/ledger/storage_api/governance.rs +++ b/core/src/ledger/storage_api/governance.rs @@ -264,6 +264,6 @@ where { let key = governance_keys::get_max_proposal_period_key(); let max_proposal_period: u64 = - storage.read(&key)?.expect("Parameter should be definied."); + storage.read(&key)?.expect("Parameter should be defined."); Ok(max_proposal_period) } diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index d608f6a98c..8b8f4f6fdd 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -409,8 +409,8 @@ where } /// Update data by removing old epochs - /// TODO: should we consider more complex handling of empty epochs in the - /// data below? + // TODO: should we consider more complex handling of empty epochs in the + // data below? pub fn update_data( &self, storage: &mut S, @@ -422,10 +422,6 @@ where { let last_update = self.get_last_update(storage)?; let oldest_epoch = self.get_oldest_epoch(storage)?; - println!( - "\nLast update = {:?}\nOldest epoch = {:?}\n", - last_update, oldest_epoch - ); if let (Some(last_update), Some(oldest_epoch)) = (last_update, oldest_epoch) { From 1ddd82b87da365e9b1b4a6a19282e1e70b2541ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:24:44 +0100 Subject: [PATCH 13/26] fixup! Apply suggestions from code review --- proof_of_stake/src/epoched.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 8b8f4f6fdd..5622ee6aa4 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -440,7 +440,6 @@ where let data_handler = self.get_data_handler(); // Remove data before the new oldest epoch, keep the latest // value - dbg!(&diff); for epoch in oldest_epoch.iter_range(diff) { let was_data = data_handler.remove_all(storage, &epoch)?; if was_data { From f1bc264dbaf75f6b1ee7def83f97c7579772cc49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:31:14 +0100 Subject: [PATCH 14/26] fix PoS crate standalone build --- proof_of_stake/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index d8af48a1ff..96160bd486 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -4057,7 +4057,7 @@ where /// Init PoS genesis wrapper helper that also initializes gov params that are /// used in PoS with default values. -#[cfg(feature = "testing")] +#[cfg(any(test, feature = "testing"))] pub fn test_init_genesis( storage: &mut S, owned: OwnedPosParams, From f40bd267207e3c0166a6e3549fe7916f6cff6955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:47:26 +0100 Subject: [PATCH 15/26] replace direct storage read of PosParams with an RPC fn --- apps/src/lib/client/tx.rs | 8 +------- tests/src/e2e/ibc_tests.rs | 8 +++----- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index c8c42b190b..b7c2bd8fc6 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -12,8 +12,6 @@ use namada::core::ledger::governance::cli::offline::{ use namada::core::ledger::governance::cli::onchain::{ DefaultProposal, PgfFundingProposal, PgfStewardProposal, ProposalVote, }; -use namada::ledger::pos; -use namada::proof_of_stake::parameters::PosParams; use namada::proto::Tx; use namada::sdk::rpc::{TxBroadcastData, TxResponse}; use namada::sdk::wallet::{Wallet, WalletUtils}; @@ -550,11 +548,7 @@ where ) .unwrap(); - let key = pos::params_key(); - let pos_params = - rpc::query_storage_value::(client, &key) - .await - .expect("Pos parameter should be defined."); + let pos_params = rpc::query_pos_parameters(client).await; display_line!(IO, ""); display_line!( diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index c294367f1c..6097482245 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -64,7 +64,7 @@ use namada::types::key::PublicKey; use namada::types::storage::{BlockHeight, Key}; use namada::types::token::Amount; use namada_apps::client::rpc::{ - query_storage_value, query_storage_value_bytes, + query_pos_parameters, query_storage_value, query_storage_value_bytes, }; use namada_apps::client::utils::id_from_pk; use namada_apps::config::ethereum_bridge; @@ -250,10 +250,8 @@ fn make_client_state(test: &Test, height: Height) -> TmClientState { let client = HttpClient::new(ledger_address).unwrap(); let key = pos::params_key(); - let pos_params = test - .async_runtime() - .block_on(query_storage_value::(&client, &key)) - .unwrap(); + let pos_params = + test.async_runtime().block_on(query_pos_parameters(&client)); let pipeline_len = pos_params.pipeline_len; let key = param_storage::get_epoch_duration_storage_key(); From 41d3838079d9d8e7c1ef36dd4a16c94575d3a8e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:56:29 +0100 Subject: [PATCH 16/26] fixup! replace direct storage read of PosParams with an RPC fn --- tests/src/e2e/ibc_tests.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index 6097482245..f3ab55d83e 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -53,7 +53,6 @@ use namada::ibc_proto::google::protobuf::Any; use namada::ledger::events::EventType; use namada::ledger::ibc::storage::*; use namada::ledger::parameters::{storage as param_storage, EpochDuration}; -use namada::ledger::pos::{self, PosParams}; use namada::ledger::queries::RPC; use namada::ledger::storage::ics23_specs::ibc_proof_specs; use namada::ledger::storage::traits::Sha256Hasher; @@ -249,7 +248,6 @@ fn make_client_state(test: &Test, height: Height) -> TmClientState { let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); let client = HttpClient::new(ledger_address).unwrap(); - let key = pos::params_key(); let pos_params = test.async_runtime().block_on(query_pos_parameters(&client)); let pipeline_len = pos_params.pipeline_len; From 620e4e26141a3e5b67da4ed53a8986f08a77034b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:54:40 +0100 Subject: [PATCH 17/26] core/types/storage:m ore flexible fn checked_sub param --- core/src/types/storage.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index ad0c14f499..9437a1c8bd 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -1035,11 +1035,12 @@ impl Epoch { /// overflow occurred. #[must_use = "this returns the result of the operation, without modifying \ the original"] - pub fn checked_sub(self, rhs: Epoch) -> Option { - if rhs.0 > self.0 { + pub fn checked_sub(self, rhs: impl Into) -> Option { + let Epoch(rhs) = rhs.into(); + if rhs > self.0 { None } else { - Some(Self(self.0 - rhs.0)) + Some(Self(self.0 - rhs)) } } From 856130ef8d603f76d8fc76906ebdc4c47eebc687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 28 Sep 2023 13:56:35 +0100 Subject: [PATCH 18/26] PoS: refactor usages of `Epoch::checked_sub` --- proof_of_stake/src/epoched.rs | 42 +++++++++++++---------------------- proof_of_stake/src/lib.rs | 12 +++++----- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 5622ee6aa4..167d4eb862 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -183,11 +183,10 @@ where (last_update, oldest_epoch) { let oldest_to_keep = current_epoch - .0 .checked_sub(PastEpochs::value(params)) .unwrap_or_default(); - if oldest_epoch.0 < oldest_to_keep { - let diff = oldest_to_keep - oldest_epoch.0; + if oldest_epoch < oldest_to_keep { + let diff = u64::from(oldest_to_keep - oldest_epoch); // Go through the epochs before the expected oldest epoch and // keep the latest one tracing::debug!( @@ -266,12 +265,9 @@ where } fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { - Epoch( - epoch - .0 - .checked_sub(PastEpochs::value(params)) - .unwrap_or_default(), - ) + epoch + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default() } fn get_oldest_epoch_storage_key(&self) -> storage::Key { @@ -400,12 +396,9 @@ where } fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { - Epoch( - epoch - .0 - .checked_sub(PastEpochs::value(params)) - .unwrap_or_default(), - ) + epoch + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default() } /// Update data by removing old epochs @@ -426,11 +419,10 @@ where (last_update, oldest_epoch) { let oldest_to_keep = current_epoch - .0 .checked_sub(PastEpochs::value(params)) .unwrap_or_default(); - if oldest_epoch.0 < oldest_to_keep { - let diff = oldest_to_keep - oldest_epoch.0; + if oldest_epoch < oldest_to_keep { + let diff = u64::from(oldest_to_keep - oldest_epoch); // Go through the epochs before the expected oldest epoch and // keep the latest one tracing::debug!( @@ -610,11 +602,10 @@ where (last_update, oldest_epoch) { let oldest_to_keep = current_epoch - .0 .checked_sub(PastEpochs::value(params)) .unwrap_or_default(); - if oldest_epoch.0 < oldest_to_keep { - let diff = oldest_to_keep - oldest_epoch.0; + if oldest_epoch < oldest_to_keep { + let diff = u64::from(oldest_to_keep - oldest_epoch); // Go through the epochs before the expected oldest epoch and // sum them into it tracing::debug!( @@ -713,12 +704,9 @@ where } fn sub_past_epochs(params: &PosParams, epoch: Epoch) -> Epoch { - Epoch( - epoch - .0 - .checked_sub(PastEpochs::value(params)) - .unwrap_or_default(), - ) + epoch + .checked_sub(PastEpochs::value(params)) + .unwrap_or_default() } fn get_oldest_epoch_storage_key(&self) -> storage::Key { diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 96160bd486..6f39fc6527 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -3215,10 +3215,10 @@ fn make_unbond_details( if slash.epoch >= start && slash.epoch < withdraw - .checked_sub(Epoch( + .checked_sub( params.unbonding_len + params.cubic_slashing_window_length, - )) + ) .unwrap_or_default() { let cur_rate = slash_rates_by_epoch.entry(slash.epoch).or_default(); @@ -3751,10 +3751,10 @@ where start, Some( infraction_epoch - .checked_sub(Epoch( + .checked_sub( params.unbonding_len + params.cubic_slashing_window_length, - )) + ) .unwrap_or_default(), ), &validator, @@ -3813,10 +3813,10 @@ where start, Some( infraction_epoch - .checked_sub(Epoch( + .checked_sub( params.unbonding_len + params.cubic_slashing_window_length, - )) + ) .unwrap_or_default(), ), &validator, From 20180c4805dd670da9937c01c9bacf933d75a367 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 28 Sep 2023 09:27:08 -0600 Subject: [PATCH 19/26] changelog: add #1944 --- .../unreleased/improvements/1944-tune-storage-past-epochs.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/1944-tune-storage-past-epochs.md diff --git a/.changelog/unreleased/improvements/1944-tune-storage-past-epochs.md b/.changelog/unreleased/improvements/1944-tune-storage-past-epochs.md new file mode 100644 index 0000000000..9ddda02759 --- /dev/null +++ b/.changelog/unreleased/improvements/1944-tune-storage-past-epochs.md @@ -0,0 +1,2 @@ +- New implementation and parameters for purging old epochs for Epoched validator + data in storage. ([\#1944](https://github.com/anoma/namada/pull/1944)) \ No newline at end of file From 3fa8d388cf4f21bce4c5aaa796ac40024170e973 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 28 Sep 2023 16:07:44 +0000 Subject: [PATCH 20/26] [ci] wasm checksums update --- wasm/checksums.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 8ebfc20f2b..b628a75ae4 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,22 +1,22 @@ { - "tx_bond.wasm": "tx_bond.126ab38555f9dfbfb689f9774a7a028f7ffc226bd43fef118a3f32261c164fea.wasm", - "tx_bridge_pool.wasm": "tx_bridge_pool.6f6ad3b95e21072af9e854e374fa0d7f691f0743da8cf52a643ed1bdb0e16611.wasm", - "tx_change_validator_commission.wasm": "tx_change_validator_commission.a75d583d6ccbd956ef9c9e85010bba75b4bf63a15a67b55dfb159be35cb5c142.wasm", + "tx_bond.wasm": "tx_bond.e68381be69fdbd323507f88b8a1e67537e1c883edabbcb17a77f827748f99d11.wasm", + "tx_bridge_pool.wasm": "tx_bridge_pool.1b7d7a458a365b627f297a8598ab0405c5092f94d3aa6b43d157e91494a8db6d.wasm", + "tx_change_validator_commission.wasm": "tx_change_validator_commission.5d34345991a3c3461a55a7a7c801b56944b14a3f0055d2913852c6ab65e4d604.wasm", "tx_ibc.wasm": "tx_ibc.54313469bcc9bcaabf661177f88cb90ac9008f542edbf686f286a02f8cdbfd41.wasm", - "tx_init_account.wasm": "tx_init_account.10ee01dac5325685360119ba8e4b597d776a018ea4c9ac3534dd876ec377789e.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.04cad5a3a71f833a5867bca3ced54b06d34ad07f3f21877599d38581d362ba10.wasm", - "tx_init_validator.wasm": "tx_init_validator.964c9449ffe0fc41649decd283c905c7cd3665127274444fafc6f1347364a61e.wasm", - "tx_resign_steward.wasm": "tx_resign_steward.b5d92c1bd196be0d196ef16e2ceed9a9ced7ac61d7b177fdbad208c0e784e172.wasm", - "tx_reveal_pk.wasm": "tx_reveal_pk.32011ddc5316705ae005059d5916b071288a04fb4dee80854af16d61548b5c27.wasm", - "tx_transfer.wasm": "tx_transfer.963ec4c2705377423ddc46b4ff3de63f9b625351467d89290fa771a485710c41.wasm", - "tx_unbond.wasm": "tx_unbond.63baa912938704817d2b23b4f889ffa0f40ea38ca1ce1990ed08999a717998d2.wasm", - "tx_unjail_validator.wasm": "tx_unjail_validator.03bcdf9d8f4ff06b87e9eb6207b709b8b99fac4035737dbfc70881fc5810e0c0.wasm", - "tx_update_account.wasm": "tx_update_account.7b4e225a823449d3d8bffde197c439ad24f4f6c95cf754acf62b6373958c4486.wasm", - "tx_update_steward_commission.wasm": "tx_update_steward_commission.0001b21ef3ef4f9b33afb5a5ef75a6a5427fbe221a8350cfbd81781ac18ded6e.wasm", + "tx_init_account.wasm": "tx_init_account.ee302c3711231a402164cb49f8828242f5be7863315fae35e2575f6009dd94d2.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.26d8b4ba0089faa2fbce56e5d088292b801dbbc0d4dcb7e203b3fec7a19b28f6.wasm", + "tx_init_validator.wasm": "tx_init_validator.ad7a059eacc883ebafb612d628a1e33229d2a3e5cda21d48da4263ae4ee437b0.wasm", + "tx_resign_steward.wasm": "tx_resign_steward.f6a526f45dab93076be0d7bdeb90b58183c13925907974093eaaecee2127b5e4.wasm", + "tx_reveal_pk.wasm": "tx_reveal_pk.b5f6b17103aceb439eaf1a2d79b9bffc47e4175504363ade652e39ea850012be.wasm", + "tx_transfer.wasm": "tx_transfer.9995453c1f8144a7457e7af4c21bc5f358ead953dd6d0cf5fa7ea75365303ce2.wasm", + "tx_unbond.wasm": "tx_unbond.2330b177c14d95a6a92a6a6d0702c447a16d6789d8ce8c4b4889a0818b1e477a.wasm", + "tx_unjail_validator.wasm": "tx_unjail_validator.1e27f103e0ea615cea9f86710bc2c56304516b42d3337e516b97d7e03982aaa1.wasm", + "tx_update_account.wasm": "tx_update_account.602610e10d70faa7c9e65f98de161669eb7ce5fc366b96cc6fb4b17abef226c7.wasm", + "tx_update_steward_commission.wasm": "tx_update_steward_commission.c049d39194fda97c7cd579dfc818ad282a6cb41e65bd4f376a2e61440cebf580.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.727e36112fcd0753f758370dff981cc93430fe7d6f95ceb570a02a37529a7531.wasm", - "tx_withdraw.wasm": "tx_withdraw.311993b9362f1a66acf002f15fbd9599115e41d9c5b4e1b0fa565335fae147cd.wasm", + "tx_withdraw.wasm": "tx_withdraw.be5b04c3e76850c697a14b4d92c6eeb7f3e20f16b865fecf71572df053589509.wasm", "vp_implicit.wasm": "vp_implicit.e0958c2ec06863f7bd48cd9abb67cc7557f956ce9fa6c714deba885db721fa50.wasm", "vp_masp.wasm": "vp_masp.037671b60b3e9f312c1c5fdc53d040ebfad21a646b9b1e2dac6b3e20fc0d01ec.wasm", "vp_user.wasm": "vp_user.0203fddde57bc31ef411370b628963486928a7c4d34614980d1a52616e0f617b.wasm", "vp_validator.wasm": "vp_validator.39c685bc1407ef484f963aff9f7576273d56bbf283dcbded9f01944cf7ff9bf0.wasm" -} \ No newline at end of file +} From c65a6d0a51af791797c2e4833853af6f3462f899 Mon Sep 17 00:00:00 2001 From: brentstone Date: Thu, 28 Sep 2023 10:31:46 -0600 Subject: [PATCH 21/26] fixed `epoched` tests and `test_validator_sets` --- proof_of_stake/src/epoched.rs | 2 ++ proof_of_stake/src/tests.rs | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 167d4eb862..8b86f4dbd4 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -1338,6 +1338,8 @@ mod test { fn init_storage() -> storage_api::Result { let mut s = TestWlStorage::default(); + let gov_params = namada_core::ledger::governance::parameters::GovernanceParameters::default(); + gov_params.init_storage(&mut s)?; crate::init_genesis( &mut s, &PosParams::default(), diff --git a/proof_of_stake/src/tests.rs b/proof_of_stake/src/tests.rs index 2319319d54..045fc383da 100644 --- a/proof_of_stake/src/tests.rs +++ b/proof_of_stake/src/tests.rs @@ -1776,7 +1776,8 @@ fn test_validator_sets() { ); assert_eq!(tm_updates[1], ValidatorSetUpdate::Deactivated(pk4)); - // Check that the validator sets were purged for the old epochs + // Check that the below-capacity validator set was purged for the old epochs + // but that the consensus_validator_set was not let last_epoch = epoch; for e in Epoch::iter_bounds_inclusive( start_epoch, @@ -1785,7 +1786,7 @@ fn test_validator_sets() { .sub_or_default(Epoch(1)), ) { assert!( - consensus_validator_set_handle() + !consensus_validator_set_handle() .at(&e) .is_empty(&s) .unwrap() From 99714977f8ee6898ba9321ea97c847957235fb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Fri, 29 Sep 2023 10:09:02 +0100 Subject: [PATCH 22/26] fixup! pos/types: configure number of past epochs kept for PoS data --- proof_of_stake/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 8807b8072e..d3ac47ac29 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -140,7 +140,7 @@ pub type ValidatorSlashes = NestedMap; pub type EpochedSlashes = crate::epoched::NestedEpoched< ValidatorSlashes, crate::epoched::OffsetUnbondingLen, - crate::epoched::OffsetSlashProcessingLen, /* TODO: should this be slash procesing + cubic window? */ + crate::epoched::OffsetSlashProcessingLen, >; /// Epoched validator's unbonds From 7c7ee029a1e91cd21c41e3c8633a0d4224075b69 Mon Sep 17 00:00:00 2001 From: brentstone Date: Mon, 2 Oct 2023 14:04:50 -0600 Subject: [PATCH 23/26] keep validator eth keys for max proposal period --- proof_of_stake/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index d3ac47ac29..c7d666bdd3 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -44,14 +44,14 @@ pub type ValidatorConsensusKeys = crate::epoched::Epoched< pub type ValidatorEthHotKeys = crate::epoched::Epoched< common::PublicKey, crate::epoched::OffsetPipelineLen, - crate::epoched::OffsetDefaultNumPastEpochs, + crate::epoched::OffsetMaxProposalPeriodPlus, >; /// Epoched validator's eth cold key. pub type ValidatorEthColdKeys = crate::epoched::Epoched< common::PublicKey, crate::epoched::OffsetPipelineLen, - crate::epoched::OffsetDefaultNumPastEpochs, + crate::epoched::OffsetMaxProposalPeriodPlus, >; /// Epoched validator's state. From 85770beec8bd02d7fb0686611b926192e3c55c81 Mon Sep 17 00:00:00 2001 From: brentstone Date: Mon, 2 Oct 2023 14:05:29 -0600 Subject: [PATCH 24/26] clear old enqueued slashes when processing slashes --- proof_of_stake/src/epoched.rs | 25 +++++++++++++++++++++++++ proof_of_stake/src/lib.rs | 3 +++ proof_of_stake/src/types.rs | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 8b86f4dbd4..0f66a36d84 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -877,6 +877,29 @@ impl EpochOffset for OffsetSlashProcessingLen { } } +/// Offset at the slash processing delay plus the default num past epochs. +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + BorshSchema, + PartialEq, + Eq, + PartialOrd, + Ord, +)] +pub struct OffsetSlashProcessingLenPlus; +impl EpochOffset for OffsetSlashProcessingLenPlus { + fn value(params: &PosParams) -> u64 { + params.slash_processing_epoch_offset() + DEFAULT_NUM_PAST_EPOCHS + } + + fn dyn_offset() -> DynEpochOffset { + DynEpochOffset::SlashProcessingLenPlus + } +} + /// Maximum offset. #[derive( Debug, @@ -1018,6 +1041,8 @@ pub enum DynEpochOffset { /// Offset at slash processing delay (unbonding + /// cubic_slashing_window + 1). SlashProcessingLen, + /// Offset at slash processing delay plus the defaul num past epochs + SlashProcessingLenPlus, /// Offset at the max proposal period MaxProposalPeriod, /// Offset at the max proposal period plus the default num past epochs diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 6f39fc6527..223abdc1fe 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -3689,6 +3689,9 @@ where cur_slashes.push(updated_slash); } + // Update the epochs of enqueued slashes in storage + enqueued_slashes_handle().update_data(storage, ¶ms, current_epoch)?; + let mut deltas_for_update: HashMap> = HashMap::new(); diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index c7d666bdd3..68a89c86cb 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -140,7 +140,7 @@ pub type ValidatorSlashes = NestedMap; pub type EpochedSlashes = crate::epoched::NestedEpoched< ValidatorSlashes, crate::epoched::OffsetUnbondingLen, - crate::epoched::OffsetSlashProcessingLen, + crate::epoched::OffsetSlashProcessingLenPlus, >; /// Epoched validator's unbonds From 59d84653729264b86847304f3b6d4dd69af7356b Mon Sep 17 00:00:00 2001 From: brentstone Date: Mon, 2 Oct 2023 14:07:09 -0600 Subject: [PATCH 25/26] keep `total_deltas` for same period of time as `validator_deltas` --- proof_of_stake/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 68a89c86cb..3cc24ffbbb 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -104,7 +104,7 @@ pub type ValidatorDeltas = crate::epoched::EpochedDelta< pub type TotalDeltas = crate::epoched::EpochedDelta< token::Change, crate::epoched::OffsetUnbondingLen, - crate::epoched::OffsetSlashProcessingLen, + crate::epoched::OffsetMaxProposalPeriodOrSlashProcessingLenPlus, >; /// Epoched validator commission rate From 64e817b13ab2476004b43f62bc997a03dbe57159 Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 3 Oct 2023 16:10:14 -0600 Subject: [PATCH 26/26] move protocol keys into epoched PoS data fix tests --- apps/src/lib/config/genesis.rs | 19 ++++------ apps/src/lib/node/ledger/shell/init_chain.rs | 4 -- .../shell/vote_extensions/bridge_pool_vext.rs | 16 +------- ethereum_bridge/src/test_utils.rs | 4 ++ proof_of_stake/src/epoched.rs | 1 + proof_of_stake/src/lib.rs | 27 +++++++++++++- proof_of_stake/src/pos_queries.rs | 37 +++++++++---------- proof_of_stake/src/tests.rs | 17 +++++++++ proof_of_stake/src/tests/state_machine.rs | 9 +++++ proof_of_stake/src/types.rs | 9 +++++ shared/src/ledger/native_vp/ibc/mod.rs | 4 ++ tx_prelude/src/proof_of_stake.rs | 3 +- wasm/wasm_source/src/tx_bond.rs | 2 + .../src/tx_change_validator_commission.rs | 3 ++ wasm/wasm_source/src/tx_unbond.rs | 3 ++ wasm/wasm_source/src/tx_withdraw.rs | 3 ++ wasm/wasm_source/src/vp_implicit.rs | 4 ++ wasm/wasm_source/src/vp_user.rs | 4 ++ wasm/wasm_source/src/vp_validator.rs | 4 ++ 19 files changed, 120 insertions(+), 53 deletions(-) diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index 502082af48..921e42a844 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -338,6 +338,12 @@ pub mod genesis_config { .unwrap() .to_public_key() .unwrap(), + protocol_key: config + .protocol_public_key + .as_ref() + .unwrap() + .to_public_key() + .unwrap(), eth_cold_key: config .eth_cold_key .as_ref() @@ -372,12 +378,6 @@ pub mod genesis_config { .unwrap() .to_public_key() .unwrap(), - protocol_key: config - .protocol_public_key - .as_ref() - .unwrap() - .to_public_key() - .unwrap(), dkg_public_key: config .dkg_public_key .as_ref() @@ -774,9 +774,6 @@ pub struct Validator { /// this key on a transaction signature. /// Note that this is distinct from consensus key used in the PoS system. pub account_key: common::PublicKey, - /// Public key associated with validator account used for signing protocol - /// transactions - pub protocol_key: common::PublicKey, /// The public DKG session key used during the DKG protocol pub dkg_public_key: DkgPublicKey, /// These tokens are not staked and hence do not contribute to the @@ -938,6 +935,7 @@ pub fn genesis(num_validators: u64) -> Genesis { address, tokens: token::Amount::native_whole(200_000), consensus_key: consensus_keypair.ref_to(), + protocol_key: protocol_keypair.ref_to(), commission_rate: Dec::new(5, 2).expect("This can't fail"), max_commission_rate_change: Dec::new(1, 2) .expect("This can't fail"), @@ -945,7 +943,6 @@ pub fn genesis(num_validators: u64) -> Genesis { eth_hot_key: eth_bridge_keypair.ref_to(), }, account_key: account_keypair.ref_to(), - protocol_key: protocol_keypair.ref_to(), dkg_public_key: dkg_keypair.public(), non_staked_balance: token::Amount::native_whole(100_000), // TODO replace with https://github.com/anoma/namada/issues/25) @@ -971,6 +968,7 @@ pub fn genesis(num_validators: u64) -> Genesis { address, tokens: token::Amount::native_whole(200_000), consensus_key: consensus_keypair.ref_to(), + protocol_key: protocol_keypair.ref_to(), commission_rate: Dec::new(5, 2).expect("This can't fail"), max_commission_rate_change: Dec::new(1, 2) .expect("This can't fail"), @@ -978,7 +976,6 @@ pub fn genesis(num_validators: u64) -> Genesis { eth_hot_key: eth_bridge_keypair.ref_to(), }, account_key: account_keypair.ref_to(), - protocol_key: protocol_keypair.ref_to(), dkg_public_key: dkg_keypair.public(), non_staked_balance: token::Amount::native_whole(100_000), // TODO replace with https://github.com/anoma/namada/issues/25) diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index 4d7522aaba..a8d47df174 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -394,10 +394,6 @@ where ) .unwrap(); - self.wl_storage - .write(&protocol_pk_key(addr), &validator.protocol_key) - .expect("Unable to set genesis user protocol public key"); - self.wl_storage .write( &dkg_session_keys::dkg_pk_key(addr), diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs index 880409bef8..05f0263a10 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs @@ -276,7 +276,6 @@ mod test_bp_vote_extensions { #[cfg(not(feature = "abcipp"))] use namada::ledger::eth_bridge::EthBridgeQueries; use namada::ledger::pos::PosQueries; - use namada::ledger::storage_api::StorageWrite; use namada::proof_of_stake::types::{ Position as ValidatorPosition, WeightedValidator, }; @@ -321,24 +320,12 @@ mod test_bp_vote_extensions { ) .expect("Test failed"); - // register Bertha's protocol key - let pk_key = protocol_pk_key(&bertha_address()); - shell - .wl_storage - .write_bytes( - &pk_key, - bertha_keypair() - .ref_to() - .try_to_vec() - .expect("Test failed."), - ) - .expect("Test failed."); - // change pipeline length to 1 let mut params = shell.wl_storage.pos_queries().get_pos_params(); params.owned.pipeline_len = 1; let consensus_key = gen_keypair(); + let protocol_key = bertha_keypair(); let hot_key = gen_secp256k1_keypair(); let cold_key = gen_secp256k1_keypair(); @@ -347,6 +334,7 @@ mod test_bp_vote_extensions { params: ¶ms, address: &bertha_address(), consensus_key: &consensus_key.ref_to(), + protocol_key: &protocol_key.ref_to(), eth_hot_key: &hot_key.ref_to(), eth_cold_key: &cold_key.ref_to(), current_epoch: 0.into(), diff --git a/ethereum_bridge/src/test_utils.rs b/ethereum_bridge/src/test_utils.rs index 8091566f10..2764d5c4d7 100644 --- a/ethereum_bridge/src/test_utils.rs +++ b/ethereum_bridge/src/test_utils.rs @@ -198,6 +198,7 @@ pub fn init_storage_with_validators( .map(|(address, tokens)| { let keys = TestValidatorKeys::generate(); let consensus_key = keys.consensus.ref_to(); + let protocol_key = keys.protocol.ref_to(); let eth_cold_key = keys.eth_gov.ref_to(); let eth_hot_key = keys.eth_bridge.ref_to(); all_keys.insert(address.clone(), keys); @@ -205,6 +206,7 @@ pub fn init_storage_with_validators( address, tokens, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate: Dec::new(5, 2).unwrap(), @@ -270,6 +272,7 @@ pub fn append_validators_to_storage( let keys = TestValidatorKeys::generate(); let consensus_key = &keys.consensus.ref_to(); + let protocol_key = &&keys.protocol.ref_to(); let eth_cold_key = &keys.eth_gov.ref_to(); let eth_hot_key = &keys.eth_bridge.ref_to(); @@ -278,6 +281,7 @@ pub fn append_validators_to_storage( params: ¶ms, address: &validator, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, current_epoch, diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index 0f66a36d84..e8e8498645 100644 --- a/proof_of_stake/src/epoched.rs +++ b/proof_of_stake/src/epoched.rs @@ -1372,6 +1372,7 @@ mod test { address: established_address_1(), tokens: token::Amount::native_whole(1_000), consensus_key: key::testing::keypair_1().to_public(), + protocol_key: key::testing::keypair_2().to_public(), eth_hot_key: key::testing::keypair_3().to_public(), eth_cold_key: key::testing::keypair_3().to_public(), commission_rate: Dec::new(1, 1).expect("Dec creation failed"), diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 223abdc1fe..bcb03319f9 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -41,7 +41,7 @@ use namada_core::ledger::storage_api::{ use namada_core::types::address::{Address, InternalAddress}; use namada_core::types::dec::Dec; use namada_core::types::key::{ - common, tm_consensus_key_raw_hash, PublicKeyTmRawHash, + common, protocol_pk_key, tm_consensus_key_raw_hash, PublicKeyTmRawHash, }; pub use namada_core::types::storage::{Epoch, Key, KeySeg}; use namada_core::types::token; @@ -58,7 +58,7 @@ use storage::{ BondsAndUnbondsDetail, BondsAndUnbondsDetails, EpochedSlashes, ReverseOrdTokenAmount, RewardsAccumulator, SlashedAmount, TotalConsensusStakes, UnbondDetails, ValidatorAddresses, - ValidatorUnbondRecords, + ValidatorProtocolKeys, ValidatorUnbondRecords, }; use thiserror::Error; use types::{ @@ -261,6 +261,14 @@ pub fn validator_consensus_key_handle( ValidatorConsensusKeys::open(key) } +/// Get the storage handle to a PoS validator's protocol key key. +pub fn validator_protocol_key_handle( + validator: &Address, +) -> ValidatorProtocolKeys { + let key = protocol_pk_key(validator); + ValidatorProtocolKeys::open(key) +} + /// Get the storage handle to a PoS validator's eth hot key. pub fn validator_eth_hot_key_handle( validator: &Address, @@ -414,6 +422,7 @@ where address, tokens, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, @@ -453,6 +462,11 @@ where consensus_key, current_epoch, )?; + validator_protocol_key_handle(&address).init_at_genesis( + storage, + protocol_key, + current_epoch, + )?; validator_eth_hot_key_handle(&address).init_at_genesis( storage, eth_hot_key, @@ -2159,6 +2173,8 @@ pub struct BecomeValidator<'a, S> { pub address: &'a Address, /// The validator's consensus key, used by Tendermint. pub consensus_key: &'a common::PublicKey, + /// The validator's protocol key. + pub protocol_key: &'a common::PublicKey, /// The validator's Ethereum bridge cold key. pub eth_cold_key: &'a common::PublicKey, /// The validator's Ethereum bridge hot key. @@ -2183,6 +2199,7 @@ where params, address, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, current_epoch, @@ -2213,6 +2230,12 @@ where current_epoch, params.pipeline_len, )?; + validator_protocol_key_handle(address).set( + storage, + protocol_key.clone(), + current_epoch, + params.pipeline_len, + )?; validator_eth_hot_key_handle(address).set( storage, eth_hot_key.clone(), diff --git a/proof_of_stake/src/pos_queries.rs b/proof_of_stake/src/pos_queries.rs index 190548570b..b694897aa8 100644 --- a/proof_of_stake/src/pos_queries.rs +++ b/proof_of_stake/src/pos_queries.rs @@ -1,7 +1,6 @@ //! Storage API for querying data about Proof-of-stake related //! data. This includes validator and epoch related data. -use borsh::{BorshDeserialize, BorshSerialize}; use namada_core::ledger::parameters::storage::get_max_proposal_bytes_key; use namada_core::ledger::parameters::EpochDuration; use namada_core::ledger::storage::WlStorage; @@ -172,17 +171,17 @@ where pk: &key::common::PublicKey, epoch: Option, ) -> Result { - let pk_bytes = pk - .try_to_vec() - .expect("Serializing public key should not fail"); + let params = crate::read_pos_params(self.wl_storage) + .expect("Failed to fetch Pos params"); let epoch = epoch .unwrap_or_else(|| self.wl_storage.storage.get_current_epoch().0); self.get_consensus_validators(Some(epoch)) .iter() .find(|validator| { - let pk_key = key::protocol_pk_key(&validator.address); - match self.wl_storage.storage.read(&pk_key) { - Ok((Some(bytes), _)) => bytes == pk_bytes, + let protocol_keys = + crate::validator_protocol_key_handle(&validator.address); + match protocol_keys.get(self.wl_storage, epoch, ¶ms) { + Ok(Some(key)) => key == *pk, _ => false, } }) @@ -195,26 +194,24 @@ where address: &Address, epoch: Option, ) -> Result<(token::Amount, key::common::PublicKey)> { + let params = crate::read_pos_params(self.wl_storage) + .expect("Failed to fetch Pos params"); let epoch = epoch .unwrap_or_else(|| self.wl_storage.storage.get_current_epoch().0); self.get_consensus_validators(Some(epoch)) .iter() .find(|validator| address == &validator.address) .map(|validator| { - let protocol_pk_key = key::protocol_pk_key(&validator.address); - // TODO: rewrite this, to use `StorageRead::read` - let bytes = self - .wl_storage - .storage - .read(&protocol_pk_key) - .expect("Validator should have public protocol key") - .0 - .expect("Validator should have public protocol key"); - let protocol_pk: key::common::PublicKey = - BorshDeserialize::deserialize(&mut bytes.as_ref()).expect( - "Protocol public key in storage should be \ - deserializable", + let protocol_keys = + crate::validator_protocol_key_handle(&validator.address); + let protocol_pk = protocol_keys + .get(self.wl_storage, epoch, ¶ms) + .unwrap() + .expect( + "Protocol public key should be set in storage after \ + genesis.", ); + (validator.bonded_stake, protocol_pk) }) .ok_or_else(|| Error::NotValidatorAddress(address.clone(), epoch)) diff --git a/proof_of_stake/src/tests.rs b/proof_of_stake/src/tests.rs index 045fc383da..497b53151c 100644 --- a/proof_of_stake/src/tests.rs +++ b/proof_of_stake/src/tests.rs @@ -853,6 +853,8 @@ fn test_become_validator_aux( // Initialize the validator account let consensus_key = new_validator_consensus_key.to_public(); + let protocol_sk = common_sk_from_simple_seed(0); + let protocol_key = protocol_sk.to_public(); let eth_hot_key = key::common::PublicKey::Secp256k1( key::testing::gen_keypair::().ref_to(), ); @@ -864,6 +866,7 @@ fn test_become_validator_aux( params: ¶ms, address: &new_validator, consensus_key: &consensus_key, + protocol_key: &protocol_key, eth_cold_key: ð_cold_key, eth_hot_key: ð_hot_key, current_epoch, @@ -1176,6 +1179,9 @@ fn test_validator_sets() { let start_epoch = Epoch::default(); let epoch = start_epoch; + let protocol_sk_1 = common_sk_from_simple_seed(0); + let protocol_sk_2 = common_sk_from_simple_seed(1); + let params = test_init_genesis( &mut s, params, @@ -1184,6 +1190,7 @@ fn test_validator_sets() { address: val1.clone(), tokens: stake1, consensus_key: pk1.clone(), + protocol_key: protocol_sk_1.to_public(), eth_hot_key: key::common::PublicKey::Secp256k1( key::testing::gen_keypair::() .ref_to(), @@ -1200,6 +1207,7 @@ fn test_validator_sets() { address: val2.clone(), tokens: stake2, consensus_key: pk2.clone(), + protocol_key: protocol_sk_2.to_public(), eth_hot_key: key::common::PublicKey::Secp256k1( key::testing::gen_keypair::() .ref_to(), @@ -1847,6 +1855,9 @@ fn test_validator_sets_swap() { println!("val2: {val2}, {pk2}, {}", stake2.to_string_native()); println!("val3: {val3}, {pk3}, {}", stake3.to_string_native()); + let protocol_sk_1 = common_sk_from_simple_seed(0); + let protocol_sk_2 = common_sk_from_simple_seed(1); + let params = test_init_genesis( &mut s, params, @@ -1855,6 +1866,7 @@ fn test_validator_sets_swap() { address: val1, tokens: stake1, consensus_key: pk1, + protocol_key: protocol_sk_1.to_public(), eth_hot_key: key::common::PublicKey::Secp256k1( key::testing::gen_keypair::() .ref_to(), @@ -1871,6 +1883,7 @@ fn test_validator_sets_swap() { address: val2.clone(), tokens: stake2, consensus_key: pk2, + protocol_key: protocol_sk_2.to_public(), eth_hot_key: key::common::PublicKey::Secp256k1( key::testing::gen_keypair::() .ref_to(), @@ -2098,6 +2111,9 @@ fn arb_genesis_validators( let consensus_sk = common_sk_from_simple_seed(seed); let consensus_key = consensus_sk.to_public(); + let protocol_sk = common_sk_from_simple_seed(seed); + let protocol_key = protocol_sk.to_public(); + let eth_hot_key = key::common::PublicKey::Secp256k1( key::testing::gen_keypair::( ) @@ -2116,6 +2132,7 @@ fn arb_genesis_validators( address, tokens, consensus_key, + protocol_key, eth_hot_key, eth_cold_key, commission_rate, diff --git a/proof_of_stake/src/tests/state_machine.rs b/proof_of_stake/src/tests/state_machine.rs index 05b9b26345..1313c467ff 100644 --- a/proof_of_stake/src/tests/state_machine.rs +++ b/proof_of_stake/src/tests/state_machine.rs @@ -106,6 +106,7 @@ enum Transition { InitValidator { address: Address, consensus_key: PublicKey, + protocol_key: PublicKey, eth_cold_key: PublicKey, eth_hot_key: PublicKey, commission_rate: Dec, @@ -189,6 +190,7 @@ impl StateMachineTest for ConcretePosState { Transition::InitValidator { address, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, @@ -202,6 +204,7 @@ impl StateMachineTest for ConcretePosState { params: ¶ms, address: &address, consensus_key: &consensus_key, + protocol_key: &protocol_key, eth_cold_key: ð_cold_key, eth_hot_key: ð_hot_key, current_epoch, @@ -1226,6 +1229,7 @@ impl ReferenceStateMachine for AbstractPosState { address, tokens, consensus_key: _, + protocol_key: _, eth_cold_key: _, eth_hot_key: _, commission_rate: _, @@ -1349,6 +1353,7 @@ impl ReferenceStateMachine for AbstractPosState { 1 => ( address::testing::arb_established_address(), key::testing::arb_common_keypair(), + key::testing::arb_common_keypair(), key::testing::arb_common_secp256k1_keypair(), key::testing::arb_common_secp256k1_keypair(), arb_rate(), @@ -1358,6 +1363,7 @@ impl ReferenceStateMachine for AbstractPosState { |( addr, consensus_key, + protocol_key, eth_hot_key, eth_cold_key, commission_rate, @@ -1366,6 +1372,7 @@ impl ReferenceStateMachine for AbstractPosState { Transition::InitValidator { address: Address::Established(addr), consensus_key: consensus_key.to_public(), + protocol_key: protocol_key.to_public(), eth_hot_key: eth_hot_key.to_public(), eth_cold_key: eth_cold_key.to_public(), commission_rate, @@ -1443,6 +1450,7 @@ impl ReferenceStateMachine for AbstractPosState { Transition::InitValidator { address, consensus_key: _, + protocol_key: _, eth_cold_key: _, eth_hot_key: _, commission_rate: _, @@ -1839,6 +1847,7 @@ impl ReferenceStateMachine for AbstractPosState { Transition::InitValidator { address, consensus_key: _, + protocol_key: _, eth_cold_key: _, eth_hot_key: _, commission_rate: _, diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 3cc24ffbbb..6a38785917 100644 --- a/proof_of_stake/src/types.rs +++ b/proof_of_stake/src/types.rs @@ -40,6 +40,13 @@ pub type ValidatorConsensusKeys = crate::epoched::Epoched< crate::epoched::OffsetDefaultNumPastEpochs, >; +/// Epoched validator's protocol key. +pub type ValidatorProtocolKeys = crate::epoched::Epoched< + common::PublicKey, + crate::epoched::OffsetPipelineLen, + crate::epoched::OffsetMaxProposalPeriodPlus, +>; + /// Epoched validator's eth hot key. pub type ValidatorEthHotKeys = crate::epoched::Epoched< common::PublicKey, @@ -205,6 +212,8 @@ pub struct GenesisValidator { pub tokens: token::Amount, /// A public key used for signing validator's consensus actions pub consensus_key: common::PublicKey, + /// A public key used for signing protocol transactions + pub protocol_key: common::PublicKey, /// An Eth bridge governance public key pub eth_cold_key: common::PublicKey, /// An Eth bridge hot signing public key used for validator set updates and diff --git a/shared/src/ledger/native_vp/ibc/mod.rs b/shared/src/ledger/native_vp/ibc/mod.rs index 818aa4df79..0f6c9ef6f7 100644 --- a/shared/src/ledger/native_vp/ibc/mod.rs +++ b/shared/src/ledger/native_vp/ibc/mod.rs @@ -257,6 +257,9 @@ pub fn get_dummy_genesis_validator() let consensus_sk = common_sk_from_simple_seed(0); let consensus_key = consensus_sk.to_public(); + let protocol_sk = common_sk_from_simple_seed(1); + let protocol_key = protocol_sk.to_public(); + let commission_rate = Dec::new(1, 1).expect("expected 0.1 to be a valid decimal"); let max_commission_rate_change = @@ -278,6 +281,7 @@ pub fn get_dummy_genesis_validator() address, tokens, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, diff --git a/tx_prelude/src/proof_of_stake.rs b/tx_prelude/src/proof_of_stake.rs index cc8bcb7b63..341c819347 100644 --- a/tx_prelude/src/proof_of_stake.rs +++ b/tx_prelude/src/proof_of_stake.rs @@ -96,8 +96,6 @@ impl Ctx { &account_keys, threshold, )?; - let protocol_pk_key = key::protocol_pk_key(&validator_address); - self.write(&protocol_pk_key, &protocol_key)?; let dkg_pk_key = key::dkg_session_keys::dkg_pk_key(&validator_address); self.write(&dkg_pk_key, &dkg_key)?; let eth_cold_key = key::common::PublicKey::Secp256k1(eth_cold_key); @@ -109,6 +107,7 @@ impl Ctx { params: ¶ms, address: &validator_address, consensus_key: &consensus_key, + protocol_key: &protocol_key, eth_cold_key: ð_cold_key, eth_hot_key: ð_hot_key, current_epoch, diff --git a/wasm/wasm_source/src/tx_bond.rs b/wasm/wasm_source/src/tx_bond.rs index 509a50f822..e51164b3a3 100644 --- a/wasm/wasm_source/src/tx_bond.rs +++ b/wasm/wasm_source/src/tx_bond.rs @@ -76,6 +76,7 @@ mod tests { let is_delegation = matches!(&bond.source, Some(source) if *source != bond.validator); let consensus_key = key::testing::keypair_1().ref_to(); + let protocol_key = key::testing::keypair_2().ref_to(); let commission_rate = Dec::new(5, 2).expect("Cannot fail"); let max_commission_rate_change = Dec::new(1, 2).expect("Cannot fail"); let eth_cold_key = key::testing::keypair_3().ref_to(); @@ -85,6 +86,7 @@ mod tests { address: bond.validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, diff --git a/wasm/wasm_source/src/tx_change_validator_commission.rs b/wasm/wasm_source/src/tx_change_validator_commission.rs index b8db50ecb0..82bdd5717f 100644 --- a/wasm/wasm_source/src/tx_change_validator_commission.rs +++ b/wasm/wasm_source/src/tx_change_validator_commission.rs @@ -66,6 +66,8 @@ mod tests { pos_params: OwnedPosParams, ) -> TxResult { let consensus_key = key::testing::keypair_1().ref_to(); + let protocol_key = key::testing::keypair_2().ref_to(); + let eth_hot_key = key::common::PublicKey::Secp256k1( key::testing::gen_keypair::().ref_to(), ); @@ -76,6 +78,7 @@ mod tests { address: commission_change.validator.clone(), tokens: token::Amount::from_uint(1_000_000, 0).unwrap(), consensus_key, + protocol_key, commission_rate: initial_rate, max_commission_rate_change: max_change, eth_hot_key, diff --git a/wasm/wasm_source/src/tx_unbond.rs b/wasm/wasm_source/src/tx_unbond.rs index 5e1eaeb2a3..cd085e3c2e 100644 --- a/wasm/wasm_source/src/tx_unbond.rs +++ b/wasm/wasm_source/src/tx_unbond.rs @@ -75,6 +75,8 @@ mod tests { &unbond.source, Some(source) if *source != unbond.validator); let consensus_key = key::testing::keypair_1().ref_to(); + let protocol_key = key::testing::keypair_2().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); let eth_hot_key = key::testing::keypair_4().ref_to(); let commission_rate = Dec::new(5, 2).expect("Cannot fail"); @@ -90,6 +92,7 @@ mod tests { initial_stake }, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, diff --git a/wasm/wasm_source/src/tx_withdraw.rs b/wasm/wasm_source/src/tx_withdraw.rs index e288282c42..54280fa7e2 100644 --- a/wasm/wasm_source/src/tx_withdraw.rs +++ b/wasm/wasm_source/src/tx_withdraw.rs @@ -78,6 +78,8 @@ mod tests { let is_delegation = matches!( &withdraw.source, Some(source) if *source != withdraw.validator); let consensus_key = key::testing::keypair_1().ref_to(); + let protocol_key = key::testing::keypair_2().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); let eth_hot_key = key::testing::keypair_4().ref_to(); let commission_rate = Dec::new(5, 2).expect("Cannot fail"); @@ -94,6 +96,7 @@ mod tests { initial_stake }, consensus_key, + protocol_key, eth_cold_key, eth_hot_key, commission_rate, diff --git a/wasm/wasm_source/src/vp_implicit.rs b/wasm/wasm_source/src/vp_implicit.rs index 215dccf421..c51650b752 100644 --- a/wasm/wasm_source/src/vp_implicit.rs +++ b/wasm/wasm_source/src/vp_implicit.rs @@ -391,6 +391,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let eth_cold_key = key::testing::keypair_3().ref_to(); let eth_hot_key = key::testing::keypair_4().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); @@ -400,6 +401,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key, @@ -470,6 +472,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); let max_commission_rate_change = Dec::new(1, 2).unwrap(); @@ -477,6 +480,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key: key::common::PublicKey::Secp256k1( diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index a334576b53..5283b5e8db 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -418,6 +418,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let eth_cold_key = key::testing::keypair_3().ref_to(); let eth_hot_key = key::testing::keypair_4().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); @@ -427,6 +428,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key, @@ -495,6 +497,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); let max_commission_rate_change = Dec::new(1, 2).unwrap(); @@ -502,6 +505,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key: key::common::PublicKey::Secp256k1( diff --git a/wasm/wasm_source/src/vp_validator.rs b/wasm/wasm_source/src/vp_validator.rs index 77a8c76d66..1c53daa4f1 100644 --- a/wasm/wasm_source/src/vp_validator.rs +++ b/wasm/wasm_source/src/vp_validator.rs @@ -425,6 +425,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let eth_cold_key = key::testing::keypair_3().ref_to(); let eth_hot_key = key::testing::keypair_4().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); @@ -434,6 +435,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key, @@ -508,6 +510,7 @@ mod tests { let validator = address::testing::established_address_3(); let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); let commission_rate = Dec::new(5, 2).unwrap(); let max_commission_rate_change = Dec::new(1, 2).unwrap(); @@ -515,6 +518,7 @@ mod tests { address: validator.clone(), tokens: initial_stake, consensus_key, + protocol_key, commission_rate, max_commission_rate_change, eth_hot_key: key::common::PublicKey::Secp256k1(