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 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 { diff --git a/proof_of_stake/src/epoched.rs b/proof_of_stake/src/epoched.rs index d5a567fc94..92b336d960 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 @@ -342,7 +344,7 @@ where .unwrap() } - /// TODO + /// Get the epoch of the most recent update pub fn get_last_update( &self, storage: &S, @@ -354,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, @@ -366,37 +368,13 @@ 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 +impl + EpochedDelta where FutureEpochs: EpochOffset, + PastEpochs: EpochOffset, Data: BorshSerialize + BorshDeserialize + ops::Add @@ -409,6 +387,7 @@ where Self { storage_prefix: key, future_epochs: PhantomData, + past_epochs: PhantomData, data: PhantomData, } } @@ -457,7 +436,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 +472,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 +499,7 @@ where fn update_data( &self, storage: &mut S, + params: &PosParams, current_epoch: Epoch, ) -> storage_api::Result<()> where @@ -531,7 +512,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 +538,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 +613,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 { @@ -679,7 +666,7 @@ where )] pub struct OffsetZero; impl EpochOffset for OffsetZero { - fn value(_paras: &PosParams) -> u64 { + fn value(_params: &PosParams) -> u64 { 0 } @@ -688,6 +675,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 +767,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 +828,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 @@ -786,19 +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()?; - 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()); @@ -863,13 +930,11 @@ mod test { #[test] fn test_epoched_without_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; - 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()); @@ -933,12 +998,11 @@ mod test { #[test] fn test_epoched_delta_data_trimming() -> storage_api::Result<()> { - let mut s = TestWlStorage::default(); + let mut s = init_storage()?; - 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(); @@ -1007,13 +1071,12 @@ 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 - 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(); @@ -1077,88 +1140,24 @@ 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(()) - // } + 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) + } } diff --git a/proof_of_stake/src/types.rs b/proof_of_stake/src/types.rs index 736ffe7a46..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,82 +24,43 @@ 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< LazyMap, crate::epoched::OffsetPipelineLen, + 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. 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 +77,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 +127,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 +141,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 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",