From 54a5baa48e393084baff63fd05b9badc8dc3a6f2 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Mon, 31 Oct 2022 18:57:48 +0100 Subject: [PATCH 01/10] governance: refactor with storage api --- apps/src/lib/client/tx.rs | 2 +- apps/src/lib/node/ledger/protocol/mod.rs | 2 +- apps/src/lib/node/ledger/shell/governance.rs | 2 +- apps/src/lib/wallet/defaults.rs | 4 +- shared/src/ledger/governance/mod.rs | 749 +++++++++++++++---- shared/src/ledger/governance/storage.rs | 2 +- shared/src/ledger/governance/utils.rs | 9 + shared/src/ledger/governance/vp.rs | 642 ---------------- shared/src/ledger/parameters/mod.rs | 11 +- shared/src/ledger/pos/vp.rs | 9 +- shared/src/ledger/slash_fund/mod.rs | 9 +- tx_prelude/src/governance.rs | 2 +- 12 files changed, 627 insertions(+), 816 deletions(-) delete mode 100644 shared/src/ledger/governance/vp.rs diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index af884bd916..3a41a01b24 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -840,7 +840,7 @@ async fn is_safe_voting_window( match proposal_end_epoch { Some(proposal_end_epoch) => { - !namada::ledger::governance::vp::is_valid_validator_voting_period( + !namada::ledger::governance::utils::is_valid_validator_voting_period( current_epoch, proposal_start_epoch, proposal_end_epoch, diff --git a/apps/src/lib/node/ledger/protocol/mod.rs b/apps/src/lib/node/ledger/protocol/mod.rs index ed776fe21a..a082fbdfec 100644 --- a/apps/src/lib/node/ledger/protocol/mod.rs +++ b/apps/src/lib/node/ledger/protocol/mod.rs @@ -48,7 +48,7 @@ pub enum Error { #[error("IBC Token native VP: {0}")] IbcTokenNativeVpError(namada::ledger::ibc::vp::IbcTokenError), #[error("Governance native VP error: {0}")] - GovernanceNativeVpError(namada::ledger::governance::vp::Error), + GovernanceNativeVpError(namada::ledger::governance::Error), #[error("SlashFund native VP error: {0}")] SlashFundNativeVpError(namada::ledger::slash_fund::Error), #[error("Ethereum bridge native VP error: {0}")] diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 90fd22f04b..80a9f8d55a 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -2,7 +2,7 @@ use namada::ledger::governance::storage as gov_storage; use namada::ledger::governance::utils::{ compute_tally, get_proposal_votes, ProposalEvent, }; -use namada::ledger::governance::vp::ADDRESS as gov_address; +use namada::ledger::governance::ADDRESS as gov_address; use namada::ledger::slash_fund::ADDRESS as slash_fund_address; use namada::ledger::storage::types::encode; use namada::ledger::storage::{DBIter, StorageHasher, DB}; diff --git a/apps/src/lib/wallet/defaults.rs b/apps/src/lib/wallet/defaults.rs index 03d6c06ca2..b0ae08ac83 100644 --- a/apps/src/lib/wallet/defaults.rs +++ b/apps/src/lib/wallet/defaults.rs @@ -19,7 +19,7 @@ pub fn addresses_from_genesis(genesis: GenesisConfig) -> Vec<(Alias, Address)> { let mut addresses: Vec<(Alias, Address)> = vec![ ("pos".into(), pos::ADDRESS), ("pos_slash_pool".into(), pos::SLASH_POOL_ADDRESS), - ("governance".into(), governance::vp::ADDRESS), + ("governance".into(), governance::ADDRESS), ("eth_bridge".into(), eth_bridge::vp::ADDRESS), ]; // Genesis validators @@ -113,7 +113,7 @@ mod dev { let mut addresses: Vec<(Alias, Address)> = vec![ ("pos".into(), pos::ADDRESS), ("pos_slash_pool".into(), pos::SLASH_POOL_ADDRESS), - ("governance".into(), governance::vp::ADDRESS), + ("governance".into(), governance::ADDRESS), ("validator".into(), validator_address()), ("albert".into(), albert_address()), ("bertha".into(), bertha_address()), diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index 38e9ed86fc..fa322c2876 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -6,22 +6,34 @@ pub mod parameters; pub mod storage; /// utility function pub mod utils; -/// vp functions -pub mod vp; use std::collections::BTreeSet; -/// Governance functions result -pub use vp::Result; - use self::storage as gov_storage; +use self::utils::is_valid_validator_voting_period; +use super::native_vp; use super::storage_api::StorageRead; +use super::vp_env::VpEnv; use crate::ledger::native_vp::{Ctx, NativeVp}; +use crate::ledger::pos::{self as pos_storage, BondId, Bonds}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; use crate::types::address::{Address, InternalAddress}; -use crate::types::storage::Key; +use crate::types::storage::{Epoch, Key}; use crate::types::token as token_storage; use crate::vm::WasmCacheAccess; +use borsh::BorshDeserialize; +use thiserror::Error; + +pub type Result = std::result::Result; + +pub const ADDRESS: Address = Address::Internal(InternalAddress::Governance); + +#[allow(missing_docs)] +#[derive(Error, Debug)] +pub enum Error { + #[error("Native VP error: {0}")] + NativeVpError(#[from] native_vp::Error), +} /// Governance VP pub struct GovernanceVp<'a, DB, H, CA> @@ -40,7 +52,7 @@ where H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - type Error = vp::Error; + type Error = Error; const ADDR: InternalAddress = InternalAddress::Governance; @@ -51,199 +63,614 @@ where verifiers: &BTreeSet
, ) -> Result { let (is_valid_keys_set, set_count) = - is_valid_key_set(&self.ctx, keys_changed); + self.is_valid_key_set(keys_changed)?; if !is_valid_keys_set { return Ok(false); }; - let native_token = self.ctx.pre().get_native_token()?; + let result = keys_changed.iter().all(|key| { let proposal_id = gov_storage::get_proposal_id(key); + let key_type = KeyType::from_key(&key, &native_token); - let key_type: KeyType = get_key_type(key, &native_token); - match (key_type, proposal_id) { - (KeyType::VOTE(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id, key, verifiers) - } - (KeyType::CONTENT(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + let result = match (key_type, proposal_id) { + (KeyType::VOTE, Some(proposal_id)) => { + self.is_valid_vote_key(proposal_id, key, verifiers) } - (KeyType::PROPOSAL_CODE(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + (KeyType::CONTENT, Some(proposal_id)) => { + self.is_valid_content_key(proposal_id) } - (KeyType::GRACE_EPOCH(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + (KeyType::PROPOSAL_CODE, Some(proposal_id)) => { + self.is_valid_proposal_code(proposal_id) } - (KeyType::START_EPOCH(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + (KeyType::GRACE_EPOCH, Some(proposal_id)) => { + self.is_valid_grace_epoch(proposal_id) } - (KeyType::END_EPOCH(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + (KeyType::START_EPOCH, Some(proposal_id)) => { + self.is_valid_start_epoch(proposal_id) } - (KeyType::FUNDS(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id) + (KeyType::END_EPOCH, Some(proposal_id)) => { + self.is_valid_end_epoch(proposal_id) } - (KeyType::AUTHOR(validate), Some(proposal_id)) => { - validate(&self.ctx, proposal_id, verifiers) + (KeyType::FUNDS, Some(proposal_id)) => { + self.is_valid_funds(proposal_id) } - (KeyType::COUNTER(validate), _) => { - validate(&self.ctx, set_count) + (KeyType::AUTHOR, Some(proposal_id)) => { + self.is_valid_author(proposal_id, verifiers) } - (KeyType::PROPOSAL_COMMIT(validate), _) => validate(&self.ctx), - (KeyType::BALANCE(validate), _) => validate(&self.ctx), - (KeyType::PARAMETER(validate), _) => { - validate(&self.ctx, tx_data) + (KeyType::COUNTER, _) => self.is_valid_counter(set_count), + (KeyType::PROPOSAL_COMMIT, _) => { + self.is_valid_proposal_commit() } - (KeyType::UNKNOWN_GOVERNANCE(validate), _) => validate(), - (KeyType::UNKNOWN(validate), _) => validate(), - _ => false, - } + (KeyType::PARAMETER, _) => self.is_valid_parameter(tx_data), + (KeyType::BALANCE, _) => self.is_valid_balance(), + (KeyType::UNKNOWN_GOVERNANCE, _) => Ok(false), + (KeyType::UNKNOWN, _) => Ok(true), + _ => Ok(false), + }; + + result.unwrap_or(false) }); Ok(result) } } -fn is_valid_key_set( - context: &Ctx, - keys: &BTreeSet, -) -> (bool, u64) +impl<'a, DB, H, CA> GovernanceVp<'a, DB, H, CA> where DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - is_valid_proposal_init_key_set(context, keys) -} + fn is_valid_key_set(&self, keys: &BTreeSet) -> Result<(bool, u64)> { + let counter_key = gov_storage::get_counter_key(); + let pre_counter: u64 = + self.ctx.pre().read(&counter_key)?.unwrap_or_default(); + let post_counter: u64 = + self.ctx.post().read(&counter_key)?.unwrap_or_default(); -fn is_valid_proposal_init_key_set( - context: &Ctx, - keys: &BTreeSet, -) -> (bool, u64) -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let counter_key = gov_storage::get_counter_key(); - let pre_counter = match vp::read(context, &counter_key, vp::ReadType::PRE) { - Ok(v) => v, - Err(_) => return (false, 0), - }; + if post_counter < pre_counter { + return Ok((false, 0)); + } - let post_counter = match vp::read(context, &counter_key, vp::ReadType::POST) - { - Ok(v) => v, - Err(_) => return (false, 0), - }; + for counter in pre_counter..post_counter { + // Construct the set of expected keys + // NOTE: we don't check the existance of committing_epoch because it's + // going to be checked later into the VP + let mandatory_keys = BTreeSet::from([ + counter_key.clone(), + gov_storage::get_content_key(counter), + gov_storage::get_author_key(counter), + gov_storage::get_funds_key(counter), + gov_storage::get_voting_start_epoch_key(counter), + gov_storage::get_voting_end_epoch_key(counter), + gov_storage::get_grace_epoch_key(counter), + ]); + + // Check that expected set is a subset the actual one + if !keys.is_superset(&mandatory_keys) { + return Ok((false, 0)); + } + } + + Ok((true, post_counter - pre_counter)) + } + + fn is_valid_vote_key( + &self, + proposal_id: u64, + key: &Key, + verifiers: &BTreeSet
, + ) -> Result { + let counter_key = gov_storage::get_counter_key(); + let voting_start_epoch_key = + gov_storage::get_voting_start_epoch_key(proposal_id); + let voting_end_epoch_key = + gov_storage::get_voting_end_epoch_key(proposal_id); + + let current_epoch = self.ctx.get_block_epoch().ok(); + let pre_counter: Option = + self.ctx.pre().read(&counter_key)?.unwrap_or_default(); + let pre_voting_start_epoch: Option = self + .ctx + .pre() + .read(&voting_start_epoch_key)? + .unwrap_or_default(); + let pre_voting_end_epoch: Option = self + .ctx + .pre() + .read(&voting_end_epoch_key)? + .unwrap_or_default(); + + let voter = gov_storage::get_voter_address(key); + let delegation_address = gov_storage::get_vote_delegation_address(key); + + match ( + pre_counter, + voter, + delegation_address, + current_epoch, + pre_voting_start_epoch, + pre_voting_end_epoch, + ) { + ( + Some(pre_counter), + Some(voter_address), + Some(delegation_address), + Some(current_epoch), + Some(pre_voting_start_epoch), + Some(pre_voting_end_epoch), + ) => { + let is_delegator = self + .is_delegator( + pre_voting_start_epoch, + verifiers, + voter_address, + delegation_address, + ) + .unwrap_or(false); + + let is_validator = self + .is_validator( + pre_voting_start_epoch, + verifiers, + voter_address, + delegation_address, + ) + .unwrap_or(false); + + let is_valid_validator_voting_period = + is_valid_validator_voting_period( + current_epoch, + pre_voting_start_epoch, + pre_voting_end_epoch, + ); + + let is_valid = pre_counter > proposal_id + && current_epoch >= pre_voting_start_epoch + && current_epoch <= pre_voting_end_epoch + && (is_delegator + || (is_validator && is_valid_validator_voting_period)); + + Ok(is_valid) + } + _ => Ok(false), + } + } + + /// Validate a content key + pub fn is_valid_content_key(&self, proposal_id: u64) -> Result { + let content_key: Key = gov_storage::get_content_key(proposal_id); + let max_content_length_parameter_key = + gov_storage::get_max_proposal_content_key(); + + let has_pre_content: bool = self.ctx.has_key_pre(&content_key)?; + if has_pre_content { + return Ok(false); + } + + let max_content_length: Option = + self.ctx.pre().read(&max_content_length_parameter_key)?; + let post_content: Option> = + self.ctx.read_bytes_post(&content_key)?; + match (post_content, max_content_length) { + (Some(post_content), Some(max_content_length)) => { + Ok(post_content.len() < max_content_length) + } + _ => Ok(false), + } + } + + /// Validate a proposal_code key + /// TODO: fix with correct parameters + pub fn is_valid_proposal_code(&self, proposal_id: u64) -> Result { + let content_key: Key = gov_storage::get_content_key(proposal_id); + let max_content_length_parameter_key = + gov_storage::get_max_proposal_content_key(); + + let has_pre_content: bool = self.ctx.has_key_pre(&content_key)?; + if has_pre_content { + return Ok(false); + } + + let max_content_length: Option = + self.ctx.pre().read(&max_content_length_parameter_key)?; + let post_content: Option> = + self.ctx.read_bytes_post(&content_key)?; + match (post_content, max_content_length) { + (Some(post_content), Some(max_content_length)) => { + Ok(post_content.len() < max_content_length) + } + _ => Ok(false), + } + } + + /// Validate a grace_epoch key + pub fn is_valid_grace_epoch(&self, proposal_id: u64) -> Result { + let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); + let grace_epoch_key = gov_storage::get_grace_epoch_key(proposal_id); + let min_grace_epoch_key = + gov_storage::get_min_proposal_grace_epoch_key(); + + let has_pre_grace_epoch = self.ctx.has_key_pre(&grace_epoch_key)?; + if has_pre_grace_epoch { + return Ok(false); + } + + let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; + let grace_epoch: Option = self.ctx.pre().read(&grace_epoch_key)?; + let min_grace_epoch: Option = + self.ctx.pre().read(&min_grace_epoch_key)?; + match (min_grace_epoch, grace_epoch, end_epoch) { + (Some(min_grace_epoch), Some(grace_epoch), Some(end_epoch)) => { + let committing_epoch_key = + gov_storage::get_committing_proposals_key( + proposal_id, + grace_epoch, + ); + let hash_post_committing_epoch = + self.ctx.has_key_post(&committing_epoch_key)?; + + return Ok(hash_post_committing_epoch + && end_epoch < grace_epoch + && grace_epoch - end_epoch >= min_grace_epoch); + } + _ => Ok(false), + } + } + + /// Validate a start_epoch key + pub fn is_valid_start_epoch(&self, proposal_id: u64) -> Result { + let start_epoch_key = + gov_storage::get_voting_start_epoch_key(proposal_id); + let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); + let min_period_parameter_key = + gov_storage::get_min_proposal_period_key(); + + let current_epoch = self.ctx.get_block_epoch().ok(); + + let has_pre_start_epoch = self.ctx.has_key_pre(&start_epoch_key)?; + let has_pre_end_epoch = self.ctx.has_key_pre(&end_epoch_key)?; + + if has_pre_start_epoch || has_pre_end_epoch { + return Ok(false); + } + + let start_epoch: Option = + self.ctx.pre().read(&start_epoch_key)?; + let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; + let min_period: Option = + self.ctx.pre().read(&min_period_parameter_key)?; + match (min_period, start_epoch, end_epoch, current_epoch) { + ( + Some(min_period), + Some(start_epoch), + Some(end_epoch), + Some(current_epoch), + ) => { + if end_epoch <= start_epoch || start_epoch <= current_epoch { + return Ok(false); + } + return Ok((end_epoch - start_epoch) % min_period == 0 + && (end_epoch - start_epoch).0 >= min_period); + } + _ => Ok(false), + } + } - if post_counter < pre_counter { - return (false, 0); + /// Validate a end_epoch key + fn is_valid_end_epoch(&self, proposal_id: u64) -> Result { + let start_epoch_key = + gov_storage::get_voting_start_epoch_key(proposal_id); + let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); + let min_period_parameter_key = + gov_storage::get_min_proposal_period_key(); + let max_period_parameter_key = + gov_storage::get_max_proposal_period_key(); + + let current_epoch = self.ctx.get_block_epoch().ok(); + + let has_pre_start_epoch = self.ctx.has_key_pre(&start_epoch_key)?; + let has_pre_end_epoch = self.ctx.has_key_pre(&end_epoch_key)?; + + if has_pre_start_epoch || has_pre_end_epoch { + return Ok(false); + } + + let start_epoch: Option = + self.ctx.pre().read(&start_epoch_key)?; + let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; + let min_period: Option = + self.ctx.pre().read(&min_period_parameter_key)?; + let max_period: Option = + self.ctx.pre().read(&max_period_parameter_key)?; + match ( + min_period, + max_period, + start_epoch, + end_epoch, + current_epoch, + ) { + ( + Some(min_period), + Some(max_period), + Some(start_epoch), + Some(end_epoch), + Some(current_epoch), + ) => { + if end_epoch <= start_epoch || start_epoch <= current_epoch { + return Ok(false); + } + return Ok((end_epoch - start_epoch) % min_period == 0 + && (end_epoch - start_epoch).0 >= min_period + && (end_epoch - start_epoch).0 <= max_period); + } + _ => Ok(false), + } } - for counter in pre_counter..post_counter { - // Construct the set of expected keys - // NOTE: we don't check the existance of committing_epoch because it's - // going to be checked later into the VP - let mandatory_keys = BTreeSet::from([ - counter_key.clone(), - gov_storage::get_content_key(counter), - gov_storage::get_author_key(counter), - gov_storage::get_funds_key(counter), - gov_storage::get_voting_start_epoch_key(counter), - gov_storage::get_voting_end_epoch_key(counter), - gov_storage::get_grace_epoch_key(counter), - ]); + /// Validate a funds key + pub fn is_valid_funds(&self, proposal_id: u64) -> Result { + let funds_key = gov_storage::get_funds_key(proposal_id); + let balance_key = token_storage::balance_key( + &self + .ctx + .pre() + .get_native_token() + .expect("Native token must be available"), + &self.ctx.address, + ); + let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); + let min_funds_parameter: Option = + self.ctx.pre().read(&min_funds_parameter_key)?; + let pre_balance: Option = + self.ctx.pre().read(&balance_key)?; + let post_balance: Option = + self.ctx.post().read(&balance_key)?; + let post_funds: Option = + self.ctx.post().read(&funds_key)?; - // Check that expected set is a subset the actual one - if !keys.is_superset(&mandatory_keys) { - return (false, 0); + match (min_funds_parameter, pre_balance, post_balance, post_funds) { + ( + Some(min_funds_parameter), + Some(pre_balance), + Some(post_balance), + Some(post_funds), + ) => Ok(post_funds >= min_funds_parameter + && post_balance - pre_balance == post_funds), + ( + Some(min_funds_parameter), + None, + Some(post_balance), + Some(post_funds), + ) => { + Ok(post_funds >= min_funds_parameter + && post_balance == post_funds) + } + _ => Ok(false), } } - (true, post_counter - pre_counter) + /// Validate a balance key + fn is_valid_balance(&self) -> Result { + let balance_key = token_storage::balance_key( + &self + .ctx + .pre() + .get_native_token() + .expect("Native token must be available"), + &self.ctx.address, + ); + let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); + + let min_funds_parameter: Option = + self.ctx.pre().read(&min_funds_parameter_key)?; + let pre_balance: Option = + self.ctx.pre().read(&balance_key)?; + let post_balance: Option = + self.ctx.pre().read(&balance_key)?; + + match (min_funds_parameter, pre_balance, post_balance) { + ( + Some(min_funds_parameter), + Some(pre_balance), + Some(post_balance), + ) => Ok(post_balance > pre_balance + && post_balance - pre_balance >= min_funds_parameter), + (Some(min_funds_parameter), None, Some(post_balance)) => { + Ok(post_balance >= min_funds_parameter) + } + _ => Ok(false), + } + } + + /// Validate a author key + pub fn is_valid_author( + &self, + proposal_id: u64, + verifiers: &BTreeSet
, + ) -> Result { + let author_key = gov_storage::get_author_key(proposal_id); + + let has_pre_author = self.ctx.has_key_pre(&author_key)?; + + if has_pre_author { + return Ok(false); + } + + let author = self.ctx.pre().read(&author_key)?; + + match author { + Some(author) => match author { + Address::Established(_) => { + let address_exist_key = Key::validity_predicate(&author); + let address_exist = + self.ctx.has_key_post(&address_exist_key)?; + + Ok(address_exist && verifiers.contains(&author)) + } + Address::Implicit(_) => Ok(verifiers.contains(&author)), + Address::Internal(_) => Ok(false), + }, + _ => Ok(false), + } + } + + /// Validate a counter key + pub fn is_valid_counter(&self, set_count: u64) -> Result { + let counter_key = gov_storage::get_counter_key(); + let pre_counter: Option = self.ctx.pre().read(&counter_key)?; + let post_counter: Option = self.ctx.post().read(&counter_key)?; + + match (pre_counter, post_counter) { + (Some(pre_counter), Some(post_counter)) => { + Ok(pre_counter + set_count == post_counter) + } + _ => Ok(false), + } + } + + /// Validate a commit key + pub fn is_valid_proposal_commit(&self) -> Result { + let counter_key = gov_storage::get_counter_key(); + let pre_counter: Option = self.ctx.pre().read(&counter_key)?; + let post_counter: Option = self.ctx.post().read(&counter_key)?; + + match (pre_counter, post_counter) { + (Some(pre_counter), Some(post_counter)) => { + // NOTE: can't do pre_counter + set_count == post_counter here + // because someone may update an empty proposal that just register a + // committing key causing a bug + Ok(pre_counter < post_counter) + } + _ => Ok(false), + } + } + + /// Validate a governance parameter + pub fn is_valid_parameter(&self, tx_data: &[u8]) -> Result { + let proposal_id = u64::try_from_slice(tx_data).ok(); + match proposal_id { + Some(id) => { + let proposal_execution_key = + gov_storage::get_proposal_execution_key(id); + return Ok(self + .ctx + .has_key_pre(&proposal_execution_key).unwrap_or(false)); + } + _ => Ok(false), + } + } + + /// Check if a vote is from a validator + pub fn is_validator( + &self, + epoch: Epoch, + verifiers: &BTreeSet
, + address: &Address, + delegation_address: &Address, + ) -> Result + where + DB: 'static + + ledger_storage::DB + + for<'iter> ledger_storage::DBIter<'iter>, + H: 'static + StorageHasher, + CA: 'static + WasmCacheAccess, + { + let validator_set_key = pos_storage::validator_set_key(); + let pre_validator_set: pos_storage::ValidatorSets = + self.ctx.pre().read(&validator_set_key)?.unwrap(); + + let validator_set = pre_validator_set.get(epoch); + + match validator_set { + Some(validator_set) => { + let all_validators = + validator_set.active.union(&validator_set.inactive); + + let is_voter_validator = all_validators + .into_iter() + .any(|validator| validator.address.eq(address)); + let is_signer_validator = verifiers.contains(address); + let is_delegation_address = delegation_address.eq(address); + + Ok(is_voter_validator + && is_signer_validator + && is_delegation_address) + } + None => Ok(false), + } + } + + /// Check if a vote is from a delegator + pub fn is_delegator( + &self, + epoch: Epoch, + verifiers: &BTreeSet
, + address: &Address, + delegation_address: &Address, + ) -> Result { + let bond_key = pos_storage::bond_key(&BondId { + source: address.clone(), + validator: delegation_address.clone(), + }); + let bonds: Option = self.ctx.pre().read(&bond_key)?; + + if let Some(bonds) = bonds { + Ok(bonds.get(epoch).is_some() && verifiers.contains(address)) + } else { + Ok(false) + } + } } #[allow(clippy::upper_case_acronyms)] -enum KeyType<'a, DB, H, CA> -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - #[allow(clippy::upper_case_acronyms)] - COUNTER(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::type_complexity)] - #[allow(clippy::upper_case_acronyms)] - VOTE(fn(&Ctx<'a, DB, H, CA>, u64, &Key, &BTreeSet
) -> bool), - #[allow(clippy::upper_case_acronyms)] - CONTENT(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - PROPOSAL_CODE(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - PROPOSAL_COMMIT(fn(&Ctx<'a, DB, H, CA>) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - GRACE_EPOCH(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - START_EPOCH(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - END_EPOCH(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - FUNDS(fn(&Ctx<'a, DB, H, CA>, u64) -> bool), - #[allow(clippy::upper_case_acronyms)] - BALANCE(fn(&Ctx<'a, DB, H, CA>) -> bool), - #[allow(clippy::type_complexity)] - #[allow(clippy::upper_case_acronyms)] - AUTHOR(fn(&Ctx<'a, DB, H, CA>, u64, &BTreeSet
) -> bool), - #[allow(clippy::upper_case_acronyms)] - PARAMETER(fn(&Ctx<'a, DB, H, CA>, &[u8]) -> bool), - #[allow(clippy::upper_case_acronyms)] - #[allow(non_camel_case_types)] - UNKNOWN_GOVERNANCE(fn() -> bool), - #[allow(clippy::upper_case_acronyms)] - UNKNOWN(fn() -> bool), +enum KeyType { + COUNTER, + VOTE, + CONTENT, + PROPOSAL_CODE, + PROPOSAL_COMMIT, + GRACE_EPOCH, + START_EPOCH, + END_EPOCH, + FUNDS, + BALANCE, + AUTHOR, + PARAMETER, + UNKNOWN_GOVERNANCE, + UNKNOWN, } -fn get_key_type<'a, DB, H, CA>( - value: &Key, - native_token: &Address, -) -> KeyType<'a, DB, H, CA> -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - if gov_storage::is_vote_key(value) { - KeyType::VOTE(vp::validate_vote_key) - } else if gov_storage::is_content_key(value) { - KeyType::CONTENT(vp::validate_content_key) - } else if gov_storage::is_proposal_code_key(value) { - KeyType::PROPOSAL_CODE(vp::validate_proposal_code_key) - } else if gov_storage::is_grace_epoch_key(value) { - KeyType::GRACE_EPOCH(vp::validate_grace_epoch_key) - } else if gov_storage::is_start_epoch_key(value) { - KeyType::START_EPOCH(vp::validate_start_epoch_key) - } else if gov_storage::is_commit_proposal_key(value) { - KeyType::PROPOSAL_COMMIT(vp::validate_commit_key) - } else if gov_storage::is_end_epoch_key(value) { - KeyType::END_EPOCH(vp::validate_end_epoch_key) - } else if gov_storage::is_balance_key(value) { - KeyType::FUNDS(vp::validate_funds_key) - } else if gov_storage::is_author_key(value) { - KeyType::AUTHOR(vp::validate_author_key) - } else if gov_storage::is_counter_key(value) { - KeyType::COUNTER(vp::validate_counter_key) - } else if gov_storage::is_parameter_key(value) { - KeyType::PARAMETER(vp::validate_parameter_key) - } else if token_storage::is_balance_key(native_token, value).is_some() { - KeyType::BALANCE(vp::validate_balance_key) - } else if gov_storage::is_governance_key(value) { - KeyType::UNKNOWN_GOVERNANCE(vp::validate_unknown_governance_key) - } else { - KeyType::UNKNOWN(vp::validate_unknown_key) +impl KeyType { + fn from_key(key: &Key, native_token: &Address) -> Self { + if gov_storage::is_vote_key(key) { + return Self::VOTE; + } else if gov_storage::is_content_key(key) { + KeyType::CONTENT + } else if gov_storage::is_proposal_code_key(key) { + KeyType::PROPOSAL_CODE + } else if gov_storage::is_grace_epoch_key(key) { + KeyType::GRACE_EPOCH + } else if gov_storage::is_start_epoch_key(key) { + KeyType::START_EPOCH + } else if gov_storage::is_commit_proposal_key(key) { + KeyType::PROPOSAL_COMMIT + } else if gov_storage::is_end_epoch_key(key) { + KeyType::END_EPOCH + } else if gov_storage::is_balance_key(key) { + KeyType::FUNDS + } else if gov_storage::is_author_key(key) { + KeyType::AUTHOR + } else if gov_storage::is_counter_key(key) { + KeyType::COUNTER + } else if gov_storage::is_parameter_key(key) { + KeyType::PARAMETER + } else if token_storage::is_balance_key(native_token, key).is_some() { + KeyType::BALANCE + } else if gov_storage::is_governance_key(key) { + KeyType::UNKNOWN_GOVERNANCE + } else { + KeyType::UNKNOWN + } } } diff --git a/shared/src/ledger/governance/storage.rs b/shared/src/ledger/governance/storage.rs index 9d2f0a4e4a..701881d476 100644 --- a/shared/src/ledger/governance/storage.rs +++ b/shared/src/ledger/governance/storage.rs @@ -1,4 +1,4 @@ -use super::vp::ADDRESS; +use crate::ledger::governance::ADDRESS; use crate::types::address::Address; use crate::types::storage::{DbKeySeg, Key, KeySeg}; diff --git a/shared/src/ledger/governance/utils.rs b/shared/src/ledger/governance/utils.rs index 152a629575..20cbc77fad 100644 --- a/shared/src/ledger/governance/utils.rs +++ b/shared/src/ledger/governance/utils.rs @@ -366,3 +366,12 @@ where } VotePower::from(0_u64) } + +pub fn is_valid_validator_voting_period( + current_epoch: Epoch, + voting_start_epoch: Epoch, + voting_end_epoch: Epoch, +) -> bool { + voting_start_epoch < voting_end_epoch + && current_epoch * 3 <= voting_start_epoch + voting_end_epoch * 2 +} \ No newline at end of file diff --git a/shared/src/ledger/governance/vp.rs b/shared/src/ledger/governance/vp.rs deleted file mode 100644 index 0d78fa1bf5..0000000000 --- a/shared/src/ledger/governance/vp.rs +++ /dev/null @@ -1,642 +0,0 @@ -use std::collections::BTreeSet; - -use borsh::BorshDeserialize; -use thiserror::Error; - -use super::storage as gov_storage; -use crate::ledger::native_vp::{self, Ctx}; -use crate::ledger::pos::{self as pos_storage, BondId, Bonds}; -use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::ledger::storage_api::StorageRead; -use crate::ledger::vp_env::VpEnv; -use crate::types::address::{Address, InternalAddress}; -use crate::types::storage::{Epoch, Key}; -use crate::types::token; -use crate::vm::WasmCacheAccess; - -/// Internal governance address -pub const ADDRESS: Address = Address::Internal(InternalAddress::Governance); - -/// Governance functions result -pub type Result = std::result::Result; - -/// Validate an unknown key -pub fn validate_unknown_key() -> bool { - true -} - -/// Validate an unknown governance key -pub fn validate_unknown_governance_key() -> bool { - false -} - -/// Validate a governance parameter -pub fn validate_parameter_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - tx_data: &[u8], -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let proposal_id = u64::try_from_slice(tx_data).ok(); - match proposal_id { - Some(id) => is_proposal_accepted(ctx, id), - _ => false, - } -} - -/// Validate a balance key -pub fn validate_balance_key<'a, DB, H, CA>(ctx: &Ctx<'a, DB, H, CA>) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let balance_key = token::balance_key( - &ctx.pre() - .get_native_token() - .expect("Native token must be available"), - &ADDRESS, - ); - let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); - let min_funds_parameter: Option = - read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); - let pre_balance: Option = - read(ctx, &balance_key, ReadType::PRE).ok(); - let post_balance: Option = - read(ctx, &balance_key, ReadType::POST).ok(); - match (min_funds_parameter, pre_balance, post_balance) { - (Some(min_funds_parameter), Some(pre_balance), Some(post_balance)) => { - post_balance > pre_balance - && post_balance - pre_balance >= min_funds_parameter - } - (Some(min_funds_parameter), None, Some(post_balance)) => { - post_balance >= min_funds_parameter - } - _ => false, - } -} - -/// Validate a author key -pub fn validate_author_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, - verifiers: &BTreeSet
, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let author_key = gov_storage::get_author_key(proposal_id); - let author = read(ctx, &author_key, ReadType::POST).ok(); - let has_pre_author = ctx.has_key_pre(&author_key).ok(); - match (has_pre_author, author) { - (Some(has_pre_author), Some(author)) => match author { - Address::Established(_) => { - let address_exist_key = Key::validity_predicate(&author); - let address_exist = ctx.has_key_post(&address_exist_key).ok(); - if let Some(address_exist) = address_exist { - !has_pre_author - && verifiers.contains(&author) - && address_exist - } else { - false - } - } - Address::Implicit(_) => { - !has_pre_author && verifiers.contains(&author) - } - Address::Internal(_) => false, - }, - _ => false, - } -} - -/// Validate a counter key -pub fn validate_counter_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - set_count: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let counter_key = gov_storage::get_counter_key(); - let pre_counter: Option = read(ctx, &counter_key, ReadType::PRE).ok(); - let post_counter: Option = - read(ctx, &counter_key, ReadType::POST).ok(); - match (pre_counter, post_counter) { - (Some(pre_counter), Some(post_counter)) => { - pre_counter + set_count == post_counter - } - _ => false, - } -} - -/// Validate a commit key -pub fn validate_commit_key<'a, DB, H, CA>(ctx: &Ctx<'a, DB, H, CA>) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let counter_key = gov_storage::get_counter_key(); - let pre_counter: Option = read(ctx, &counter_key, ReadType::PRE).ok(); - let post_counter: Option = - read(ctx, &counter_key, ReadType::POST).ok(); - match (pre_counter, post_counter) { - (Some(pre_counter), Some(post_counter)) => { - // NOTE: can't do pre_counter + set_count == post_counter here - // because someone may update an empty proposal that just register a - // committing key causing a bug - pre_counter < post_counter - } - _ => false, - } -} - -/// Validate a funds key -pub fn validate_funds_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let funds_key = gov_storage::get_funds_key(proposal_id); - let balance_key = token::balance_key( - &ctx.pre() - .get_native_token() - .expect("Native token must be available"), - &ADDRESS, - ); - let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); - let min_funds_parameter: Option = - read(ctx, &min_funds_parameter_key, ReadType::PRE).ok(); - let pre_balance: Option = - read(ctx, &balance_key, ReadType::PRE).ok(); - let post_balance: Option = - read(ctx, &balance_key, ReadType::POST).ok(); - let post_funds: Option = - read(ctx, &funds_key, ReadType::POST).ok(); - match (min_funds_parameter, pre_balance, post_balance, post_funds) { - ( - Some(min_funds_parameter), - Some(pre_balance), - Some(post_balance), - Some(post_funds), - ) => { - post_funds >= min_funds_parameter - && post_balance - pre_balance == post_funds - } - ( - Some(min_funds_parameter), - None, - Some(post_balance), - Some(post_funds), - ) => post_funds >= min_funds_parameter && post_balance == post_funds, - _ => false, - } -} - -/// Validate a start_epoch key -pub fn validate_start_epoch_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let start_epoch_key = gov_storage::get_voting_start_epoch_key(proposal_id); - let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); - let start_epoch: Option = - read(ctx, &start_epoch_key, ReadType::POST).ok(); - let end_epoch: Option = - read(ctx, &end_epoch_key, ReadType::POST).ok(); - let current_epoch = ctx.get_block_epoch().ok(); - let min_period_parameter_key = gov_storage::get_min_proposal_period_key(); - let min_period: Option = - read(ctx, &min_period_parameter_key, ReadType::PRE).ok(); - let has_pre_start_epoch = ctx.has_key_pre(&start_epoch_key).ok(); - let has_pre_end_epoch = ctx.has_key_pre(&end_epoch_key).ok(); - match ( - has_pre_start_epoch, - has_pre_end_epoch, - min_period, - start_epoch, - end_epoch, - current_epoch, - ) { - ( - Some(has_pre_start_epoch), - Some(has_pre_end_epoch), - Some(min_period), - Some(start_epoch), - Some(end_epoch), - Some(current_epoch), - ) => { - if end_epoch <= start_epoch || start_epoch <= current_epoch { - return false; - } - !has_pre_start_epoch - && !has_pre_end_epoch - && (end_epoch - start_epoch) % min_period == 0 - && (end_epoch - start_epoch).0 >= min_period - } - _ => false, - } -} - -/// Validate a end_epoch key -pub fn validate_end_epoch_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let start_epoch_key = gov_storage::get_voting_start_epoch_key(proposal_id); - let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); - let start_epoch: Option = - read(ctx, &start_epoch_key, ReadType::POST).ok(); - let end_epoch: Option = - read(ctx, &end_epoch_key, ReadType::POST).ok(); - let current_epoch = ctx.get_block_epoch().ok(); - let min_period_parameter_key = gov_storage::get_min_proposal_period_key(); - let min_period: Option = - read(ctx, &min_period_parameter_key, ReadType::PRE).ok(); - let max_period_parameter_key = gov_storage::get_max_proposal_period_key(); - let max_period: Option = - read(ctx, &max_period_parameter_key, ReadType::PRE).ok(); - let has_pre_start_epoch = ctx.has_key_pre(&start_epoch_key).ok(); - let has_pre_end_epoch = ctx.has_key_pre(&end_epoch_key).ok(); - match ( - has_pre_start_epoch, - has_pre_end_epoch, - min_period, - max_period, - start_epoch, - end_epoch, - current_epoch, - ) { - ( - Some(has_pre_start_epoch), - Some(has_pre_end_epoch), - Some(min_period), - Some(max_period), - Some(start_epoch), - Some(end_epoch), - Some(current_epoch), - ) => { - if end_epoch <= start_epoch || start_epoch <= current_epoch { - return false; - } - !has_pre_start_epoch - && !has_pre_end_epoch - && (end_epoch - start_epoch) % min_period == 0 - && (end_epoch - start_epoch).0 >= min_period - && (end_epoch - start_epoch).0 <= max_period - } - _ => false, - } -} - -/// Validate a grace_epoch key -pub fn validate_grace_epoch_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let end_epoch_key = gov_storage::get_voting_end_epoch_key(proposal_id); - let grace_epoch_key = gov_storage::get_grace_epoch_key(proposal_id); - let min_grace_epoch_key = gov_storage::get_min_proposal_grace_epoch_key(); - let end_epoch: Option = read(ctx, &end_epoch_key, ReadType::POST).ok(); - let grace_epoch: Option = - read(ctx, &grace_epoch_key, ReadType::POST).ok(); - let min_grace_epoch: Option = - read(ctx, &min_grace_epoch_key, ReadType::PRE).ok(); - let has_pre_grace_epoch = ctx.has_key_pre(&grace_epoch_key).ok(); - match (has_pre_grace_epoch, min_grace_epoch, grace_epoch, end_epoch) { - ( - Some(has_pre_grace_epoch), - Some(min_grace_epoch), - Some(grace_epoch), - Some(end_epoch), - ) => { - let committing_epoch_key = - gov_storage::get_committing_proposals_key( - proposal_id, - grace_epoch, - ); - let committing_epoch = ctx.has_key_post(&committing_epoch_key); - match committing_epoch { - Ok(committing_epoch_exists) => { - !has_pre_grace_epoch - && end_epoch < grace_epoch - && grace_epoch - end_epoch >= min_grace_epoch - && committing_epoch_exists - } - _ => false, - } - } - _ => false, - } -} - -/// Validate a proposal_code key -pub fn validate_proposal_code_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let content_key: Key = gov_storage::get_content_key(proposal_id); - let max_content_length_parameter_key = - gov_storage::get_max_proposal_content_key(); - let max_content_length = - read(ctx, &max_content_length_parameter_key, ReadType::PRE).ok(); - let has_pre_content = ctx.has_key_pre(&content_key).ok(); - let post_content = ctx.read_bytes_post(&content_key).unwrap(); - match (has_pre_content, post_content, max_content_length) { - ( - Some(has_pre_content), - Some(post_content), - Some(max_content_length), - ) => !has_pre_content && post_content.len() < max_content_length, - _ => false, - } -} - -/// Validate a content key -pub fn validate_content_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let content_key: Key = gov_storage::get_content_key(proposal_id); - let max_content_length_parameter_key = - gov_storage::get_max_proposal_content_key(); - let max_content_length = - read(ctx, &max_content_length_parameter_key, ReadType::PRE).ok(); - let has_pre_content = ctx.has_key_pre(&content_key).ok(); - let post_content = ctx.read_bytes_post(&content_key).unwrap(); - match (has_pre_content, post_content, max_content_length) { - ( - Some(has_pre_content), - Some(post_content), - Some(max_content_length), - ) => !has_pre_content && post_content.len() < max_content_length, - _ => false, - } -} - -/// Validate a vote key -pub fn validate_vote_key<'a, DB, H, CA>( - ctx: &Ctx<'a, DB, H, CA>, - proposal_id: u64, - key: &Key, - verifiers: &BTreeSet
, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let counter_key = gov_storage::get_counter_key(); - let voting_start_epoch_key = - gov_storage::get_voting_start_epoch_key(proposal_id); - let voting_end_epoch_key = - gov_storage::get_voting_end_epoch_key(proposal_id); - let current_epoch = ctx.get_block_epoch().ok(); - let pre_voting_start_epoch: Option = - read(ctx, &voting_start_epoch_key, ReadType::PRE).ok(); - let pre_voting_end_epoch: Option = - read(ctx, &voting_end_epoch_key, ReadType::PRE).ok(); - let pre_counter: Option = read(ctx, &counter_key, ReadType::PRE).ok(); - let voter = gov_storage::get_voter_address(key); - let delegation_address = gov_storage::get_vote_delegation_address(key); - - match ( - pre_counter, - voter, - delegation_address, - current_epoch, - pre_voting_start_epoch, - pre_voting_end_epoch, - ) { - ( - Some(pre_counter), - Some(voter_address), - Some(delegation_address), - Some(current_epoch), - Some(pre_voting_start_epoch), - Some(pre_voting_end_epoch), - ) => { - let is_delegator = is_delegator( - ctx, - pre_voting_start_epoch, - verifiers, - voter_address, - delegation_address, - ); - - let is_validator = is_validator( - ctx, - pre_voting_start_epoch, - verifiers, - voter_address, - delegation_address, - ); - - let is_valid_validator_voting_period = - is_valid_validator_voting_period( - current_epoch, - pre_voting_start_epoch, - pre_voting_end_epoch, - ); - - pre_counter > proposal_id - && current_epoch >= pre_voting_start_epoch - && current_epoch <= pre_voting_end_epoch - && (is_delegator - || (is_validator && is_valid_validator_voting_period)) - } - _ => false, - } -} - -/// Read options -#[allow(clippy::upper_case_acronyms)] -pub enum ReadType { - /// Read pre storage - #[allow(clippy::upper_case_acronyms)] - PRE, - /// Read post storage - #[allow(clippy::upper_case_acronyms)] - POST, -} - -/// Check if a proposal id is being executed -pub fn is_proposal_accepted( - context: &Ctx, - proposal_id: u64, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let proposal_execution_key = - gov_storage::get_proposal_execution_key(proposal_id); - context - .has_key_pre(&proposal_execution_key) - .unwrap_or(false) -} - -/// Read a value from the storage -pub fn read( - context: &Ctx, - key: &Key, - read_type: ReadType, -) -> Result -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, - T: Clone + BorshDeserialize, -{ - let storage_result = match read_type { - ReadType::PRE => context.read_bytes_pre(key), - ReadType::POST => context.read_bytes_post(key), - }; - - match storage_result { - Ok(value) => match value { - Some(bytes) => T::try_from_slice(&bytes) - .map_err(Error::NativeVpDeserializationError), - None => Err(Error::NativeVpNonExistingKeyError(key.to_string())), - }, - Err(err) => Err(Error::NativeVpError(err)), - } -} - -#[allow(missing_docs)] -#[derive(Error, Debug)] -pub enum Error { - #[error("Native VP error: {0}")] - NativeVpError(#[from] native_vp::Error), - #[error("Native VP error deserialization: {0}")] - NativeVpDeserializationError(std::io::Error), - #[error("Native VP error non-existing key: {0}")] - NativeVpNonExistingKeyError(String), -} - -/// Check if a vote is from a delegator -pub fn is_delegator( - context: &Ctx, - epoch: Epoch, - verifiers: &BTreeSet
, - address: &Address, - delegation_address: &Address, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let bond_key = pos_storage::bond_key(&BondId { - source: address.clone(), - validator: delegation_address.clone(), - }); - let bonds: Option = read(context, &bond_key, ReadType::PRE).ok(); - - if let Some(bonds) = bonds { - bonds.get(epoch).is_some() && verifiers.contains(address) - } else { - false - } -} - -/// Checks if it's a valid epoch window for a validator to vote -pub fn is_valid_validator_voting_period( - current_epoch: Epoch, - voting_start_epoch: Epoch, - voting_end_epoch: Epoch, -) -> bool { - voting_start_epoch < voting_end_epoch - && current_epoch * 3 <= voting_start_epoch + voting_end_epoch * 2 -} - -/// Check if a vote is from a validator -pub fn is_validator( - context: &Ctx, - epoch: Epoch, - verifiers: &BTreeSet
, - address: &Address, - delegation_address: &Address, -) -> bool -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let validator_set_key = pos_storage::validator_set_key(); - let pre_validator_set: pos_storage::ValidatorSets = - read(context, &validator_set_key, ReadType::PRE).unwrap(); - let validator_set = pre_validator_set.get(epoch); - - match validator_set { - Some(validator_set) => { - let all_validators = - validator_set.active.union(&validator_set.inactive); - all_validators.into_iter().any(|weighted_validator| { - weighted_validator.address.eq(address) - }) && verifiers.contains(address) - && delegation_address.eq(address) - } - None => false, - } -} - -/// Reads bytes from storage either before or after the execution of a tx -pub fn read_bytes( - context: &Ctx, - key: &Key, - read_type: ReadType, -) -> Option> -where - DB: 'static + ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter>, - H: 'static + StorageHasher, - CA: 'static + WasmCacheAccess, -{ - let storage_result = match read_type { - ReadType::PRE => context.read_pre(key), - ReadType::POST => context.read_post(key), - }; - - match storage_result { - Ok(value) => value, - Err(_err) => None, - } -} diff --git a/shared/src/ledger/parameters/mod.rs b/shared/src/ledger/parameters/mod.rs index fdc2a110d0..cc932611a6 100644 --- a/shared/src/ledger/parameters/mod.rs +++ b/shared/src/ledger/parameters/mod.rs @@ -7,11 +7,12 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use thiserror::Error; use self::storage as parameter_storage; -use super::governance::vp::is_proposal_accepted; +use super::governance::storage as gov_storage; use super::storage::types::{decode, encode}; use super::storage::{types, Storage}; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; +use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::time::DurationSecs; @@ -62,7 +63,13 @@ where KeyType::PARAMETER => { let proposal_id = u64::try_from_slice(tx_data).ok(); match proposal_id { - Some(id) => is_proposal_accepted(&self.ctx, id), + Some(id) => { + let proposal_execution_key = + gov_storage::get_proposal_execution_key(id); + self.ctx + .has_key_pre(&proposal_execution_key) + .unwrap_or(false) + } _ => false, } } diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index a293044db0..b3ee20616c 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -27,7 +27,7 @@ use super::{ ValidatorSets, ValidatorTotalDeltas, }; use crate::impl_pos_read_only; -use crate::ledger::governance::vp::is_proposal_accepted; +use crate::ledger::governance::storage as gov_storage; use crate::ledger::native_vp::{ self, Ctx, CtxPostStorageRead, CtxPreStorageRead, NativeVp, }; @@ -37,6 +37,7 @@ use crate::ledger::pos::{ }; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; use crate::ledger::storage_api::{self, StorageRead}; +use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::{Key, KeySeg}; use crate::types::token; @@ -128,7 +129,11 @@ where if is_params_key(key) { let proposal_id = u64::try_from_slice(tx_data).ok(); match proposal_id { - Some(id) => return Ok(is_proposal_accepted(&self.ctx, id)), + Some(id) => { + let proposal_execution_key = + gov_storage::get_proposal_execution_key(id); + return Ok(self.ctx.has_key_pre(&proposal_execution_key).unwrap_or(false)); + } _ => return Ok(false), } } else if is_validator_set_key(key) { diff --git a/shared/src/ledger/slash_fund/mod.rs b/shared/src/ledger/slash_fund/mod.rs index 26044444fe..ac4278bd56 100644 --- a/shared/src/ledger/slash_fund/mod.rs +++ b/shared/src/ledger/slash_fund/mod.rs @@ -9,7 +9,8 @@ use borsh::BorshDeserialize; use thiserror::Error; use self::storage as slash_fund_storage; -use super::governance::vp::is_proposal_accepted; +use crate::ledger::vp_env::VpEnv; +use super::governance::storage as gov_storage; use super::storage_api::StorageRead; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; @@ -69,7 +70,11 @@ where let proposal_id = u64::try_from_slice(tx_data).ok(); match proposal_id { - Some(id) => is_proposal_accepted(&self.ctx, id), + Some(id) => { + let proposal_execution_key = + gov_storage::get_proposal_execution_key(id); + self.ctx.has_key_pre(&proposal_execution_key).unwrap_or(false) + } None => false, } } diff --git a/tx_prelude/src/governance.rs b/tx_prelude/src/governance.rs index f33a30cab6..c314318eeb 100644 --- a/tx_prelude/src/governance.rs +++ b/tx_prelude/src/governance.rs @@ -1,7 +1,7 @@ //! Governance use namada::ledger::governance::storage; -use namada::ledger::governance::vp::ADDRESS as governance_address; +use namada::ledger::governance::ADDRESS as governance_address; use namada::types::token::Amount; use namada::types::transaction::governance::{ InitProposalData, VoteProposalData, From 7bfd9320e24046dbc13445db3980fbc6ca2da14d Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 2 Nov 2022 11:00:01 +0100 Subject: [PATCH 02/10] governance: more refactor --- apps/src/lib/client/rpc.rs | 11 +++ apps/src/lib/node/ledger/shell/governance.rs | 5 +- shared/src/ledger/governance/mod.rs | 74 ++++++++++++-------- shared/src/ledger/governance/utils.rs | 4 +- shared/src/ledger/pos/vp.rs | 5 +- shared/src/ledger/slash_fund/mod.rs | 6 +- tx_prelude/src/governance.rs | 3 +- 7 files changed, 71 insertions(+), 37 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index 6c1e3fb5f3..9c709ad8f9 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -275,6 +275,17 @@ pub async fn query_proposal(_ctx: Context, args: args::QueryProposal) { println!("{:4}Status: pending", ""); } else if start_epoch <= current_epoch && current_epoch <= end_epoch { + let votes = get_proposal_votes(client, start_epoch, id).await; + let partial_proposal_result = + compute_tally(client, start_epoch, votes).await; + println!( + "{:4}Yay votes: {}", + "", partial_proposal_result.total_yay_power + ); + println!( + "{:4}Nay votes: {}", + "", partial_proposal_result.total_nay_power + ); println!("{:4}Status: on-going", ""); } else { let votes = get_proposal_votes(client, start_epoch, id).await; diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 80a9f8d55a..7e8089065c 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -1,8 +1,9 @@ -use namada::ledger::governance::storage as gov_storage; use namada::ledger::governance::utils::{ compute_tally, get_proposal_votes, ProposalEvent, }; -use namada::ledger::governance::ADDRESS as gov_address; +use namada::ledger::governance::{ + storage as gov_storage, ADDRESS as gov_address, +}; use namada::ledger::slash_fund::ADDRESS as slash_fund_address; use namada::ledger::storage::types::encode; use namada::ledger::storage::{DBIter, StorageHasher, DB}; diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index fa322c2876..9db3d98c3c 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -9,6 +9,9 @@ pub mod utils; use std::collections::BTreeSet; +use borsh::BorshDeserialize; +use thiserror::Error; + use self::storage as gov_storage; use self::utils::is_valid_validator_voting_period; use super::native_vp; @@ -21,11 +24,11 @@ use crate::types::address::{Address, InternalAddress}; use crate::types::storage::{Epoch, Key}; use crate::types::token as token_storage; use crate::vm::WasmCacheAccess; -use borsh::BorshDeserialize; -use thiserror::Error; +/// for handling Governance NativeVP errors pub type Result = std::result::Result; +/// The governance internal address pub const ADDRESS: Address = Address::Internal(InternalAddress::Governance); #[allow(missing_docs)] @@ -71,7 +74,7 @@ where let result = keys_changed.iter().all(|key| { let proposal_id = gov_storage::get_proposal_id(key); - let key_type = KeyType::from_key(&key, &native_token); + let key_type = KeyType::from_key(key, &native_token); let result = match (key_type, proposal_id) { (KeyType::VOTE, Some(proposal_id)) => { @@ -134,8 +137,8 @@ where for counter in pre_counter..post_counter { // Construct the set of expected keys - // NOTE: we don't check the existance of committing_epoch because it's - // going to be checked later into the VP + // NOTE: we don't check the existance of committing_epoch because + // it's going to be checked later into the VP let mandatory_keys = BTreeSet::from([ counter_key.clone(), gov_storage::get_content_key(counter), @@ -261,22 +264,20 @@ where } /// Validate a proposal_code key - /// TODO: fix with correct parameters pub fn is_valid_proposal_code(&self, proposal_id: u64) -> Result { - let content_key: Key = gov_storage::get_content_key(proposal_id); - let max_content_length_parameter_key = - gov_storage::get_max_proposal_content_key(); + let code_key: Key = gov_storage::get_proposal_code_key(proposal_id); + let max_code_size_parameter_key = + gov_storage::get_max_proposal_code_size_key(); - let has_pre_content: bool = self.ctx.has_key_pre(&content_key)?; - if has_pre_content { + let has_pre_code: bool = self.ctx.has_key_pre(&code_key)?; + if has_pre_code { return Ok(false); } - let max_content_length: Option = - self.ctx.pre().read(&max_content_length_parameter_key)?; - let post_content: Option> = - self.ctx.read_bytes_post(&content_key)?; - match (post_content, max_content_length) { + let max_proposal_length: Option = + self.ctx.pre().read(&max_code_size_parameter_key)?; + let post_code: Option> = self.ctx.read_bytes_post(&code_key)?; + match (post_code, max_proposal_length) { (Some(post_content), Some(max_content_length)) => { Ok(post_content.len() < max_content_length) } @@ -310,9 +311,9 @@ where let hash_post_committing_epoch = self.ctx.has_key_post(&committing_epoch_key)?; - return Ok(hash_post_committing_epoch + Ok(hash_post_committing_epoch && end_epoch < grace_epoch - && grace_epoch - end_epoch >= min_grace_epoch); + && grace_epoch - end_epoch >= min_grace_epoch) } _ => Ok(false), } @@ -350,8 +351,8 @@ where if end_epoch <= start_epoch || start_epoch <= current_epoch { return Ok(false); } - return Ok((end_epoch - start_epoch) % min_period == 0 - && (end_epoch - start_epoch).0 >= min_period); + Ok((end_epoch - start_epoch) % min_period == 0 + && (end_epoch - start_epoch).0 >= min_period) } _ => Ok(false), } @@ -400,9 +401,9 @@ where if end_epoch <= start_epoch || start_epoch <= current_epoch { return Ok(false); } - return Ok((end_epoch - start_epoch) % min_period == 0 + Ok((end_epoch - start_epoch) % min_period == 0 && (end_epoch - start_epoch).0 >= min_period - && (end_epoch - start_epoch).0 <= max_period); + && (end_epoch - start_epoch).0 <= max_period) } _ => Ok(false), } @@ -417,7 +418,7 @@ where .pre() .get_native_token() .expect("Native token must be available"), - &self.ctx.address, + self.ctx.address, ); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = @@ -458,7 +459,7 @@ where .pre() .get_native_token() .expect("Native token must be available"), - &self.ctx.address, + self.ctx.address, ); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); @@ -538,8 +539,8 @@ where match (pre_counter, post_counter) { (Some(pre_counter), Some(post_counter)) => { // NOTE: can't do pre_counter + set_count == post_counter here - // because someone may update an empty proposal that just register a - // committing key causing a bug + // because someone may update an empty proposal that just + // register a committing key causing a bug Ok(pre_counter < post_counter) } _ => Ok(false), @@ -553,9 +554,10 @@ where Some(id) => { let proposal_execution_key = gov_storage::get_proposal_execution_key(id); - return Ok(self + Ok(self .ctx - .has_key_pre(&proposal_execution_key).unwrap_or(false)); + .has_key_pre(&proposal_execution_key) + .unwrap_or(false)) } _ => Ok(false), } @@ -625,26 +627,40 @@ where #[allow(clippy::upper_case_acronyms)] enum KeyType { + #[allow(non_camel_case_types)] COUNTER, + #[allow(non_camel_case_types)] VOTE, + #[allow(non_camel_case_types)] CONTENT, + #[allow(non_camel_case_types)] PROPOSAL_CODE, + #[allow(non_camel_case_types)] PROPOSAL_COMMIT, + #[allow(non_camel_case_types)] GRACE_EPOCH, + #[allow(non_camel_case_types)] START_EPOCH, + #[allow(non_camel_case_types)] END_EPOCH, + #[allow(non_camel_case_types)] FUNDS, + #[allow(non_camel_case_types)] BALANCE, + #[allow(non_camel_case_types)] AUTHOR, + #[allow(non_camel_case_types)] PARAMETER, + #[allow(non_camel_case_types)] UNKNOWN_GOVERNANCE, + #[allow(non_camel_case_types)] UNKNOWN, } impl KeyType { fn from_key(key: &Key, native_token: &Address) -> Self { if gov_storage::is_vote_key(key) { - return Self::VOTE; + Self::VOTE } else if gov_storage::is_content_key(key) { KeyType::CONTENT } else if gov_storage::is_proposal_code_key(key) { diff --git a/shared/src/ledger/governance/utils.rs b/shared/src/ledger/governance/utils.rs index 20cbc77fad..b63b981020 100644 --- a/shared/src/ledger/governance/utils.rs +++ b/shared/src/ledger/governance/utils.rs @@ -367,6 +367,8 @@ where VotePower::from(0_u64) } +/// Calculate the valid voting window for validator given a proposal epoch +/// details pub fn is_valid_validator_voting_period( current_epoch: Epoch, voting_start_epoch: Epoch, @@ -374,4 +376,4 @@ pub fn is_valid_validator_voting_period( ) -> bool { voting_start_epoch < voting_end_epoch && current_epoch * 3 <= voting_start_epoch + voting_end_epoch * 2 -} \ No newline at end of file +} diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index b3ee20616c..8d34d70e93 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -132,7 +132,10 @@ where Some(id) => { let proposal_execution_key = gov_storage::get_proposal_execution_key(id); - return Ok(self.ctx.has_key_pre(&proposal_execution_key).unwrap_or(false)); + return Ok(self + .ctx + .has_key_pre(&proposal_execution_key) + .unwrap_or(false)); } _ => return Ok(false), } diff --git a/shared/src/ledger/slash_fund/mod.rs b/shared/src/ledger/slash_fund/mod.rs index ac4278bd56..c9d4f7566e 100644 --- a/shared/src/ledger/slash_fund/mod.rs +++ b/shared/src/ledger/slash_fund/mod.rs @@ -9,11 +9,11 @@ use borsh::BorshDeserialize; use thiserror::Error; use self::storage as slash_fund_storage; -use crate::ledger::vp_env::VpEnv; use super::governance::storage as gov_storage; use super::storage_api::StorageRead; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; +use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::token; @@ -73,7 +73,9 @@ where Some(id) => { let proposal_execution_key = gov_storage::get_proposal_execution_key(id); - self.ctx.has_key_pre(&proposal_execution_key).unwrap_or(false) + self.ctx + .has_key_pre(&proposal_execution_key) + .unwrap_or(false) } None => false, } diff --git a/tx_prelude/src/governance.rs b/tx_prelude/src/governance.rs index c314318eeb..1c915002af 100644 --- a/tx_prelude/src/governance.rs +++ b/tx_prelude/src/governance.rs @@ -1,7 +1,6 @@ //! Governance -use namada::ledger::governance::storage; -use namada::ledger::governance::ADDRESS as governance_address; +use namada::ledger::governance::{storage, ADDRESS as governance_address}; use namada::types::token::Amount; use namada::types::transaction::governance::{ InitProposalData, VoteProposalData, From 079cffa6240d0d3e84d34b34e074b85cce33b8ce Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 2 Nov 2022 11:40:23 +0100 Subject: [PATCH 03/10] governance: more refactor --- shared/src/ledger/governance/mod.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index 9db3d98c3c..692159bf9c 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -278,8 +278,8 @@ where self.ctx.pre().read(&max_code_size_parameter_key)?; let post_code: Option> = self.ctx.read_bytes_post(&code_key)?; match (post_code, max_proposal_length) { - (Some(post_content), Some(max_content_length)) => { - Ok(post_content.len() < max_content_length) + (Some(post_code), Some(max_content_length)) => { + Ok(post_code.len() < max_content_length) } _ => Ok(false), } @@ -297,8 +297,8 @@ where return Ok(false); } - let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; - let grace_epoch: Option = self.ctx.pre().read(&grace_epoch_key)?; + let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; + let grace_epoch: Option = self.ctx.post().read(&grace_epoch_key)?; let min_grace_epoch: Option = self.ctx.pre().read(&min_grace_epoch_key)?; match (min_grace_epoch, grace_epoch, end_epoch) { @@ -337,8 +337,8 @@ where } let start_epoch: Option = - self.ctx.pre().read(&start_epoch_key)?; - let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; + self.ctx.post().read(&start_epoch_key)?; + let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; let min_period: Option = self.ctx.pre().read(&min_period_parameter_key)?; match (min_period, start_epoch, end_epoch, current_epoch) { @@ -379,9 +379,9 @@ where let start_epoch: Option = self.ctx.pre().read(&start_epoch_key)?; - let end_epoch: Option = self.ctx.pre().read(&end_epoch_key)?; + let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; let min_period: Option = - self.ctx.pre().read(&min_period_parameter_key)?; + self.ctx.post().read(&min_period_parameter_key)?; let max_period: Option = self.ctx.pre().read(&max_period_parameter_key)?; match ( @@ -468,7 +468,7 @@ where let pre_balance: Option = self.ctx.pre().read(&balance_key)?; let post_balance: Option = - self.ctx.pre().read(&balance_key)?; + self.ctx.post().read(&balance_key)?; match (min_funds_parameter, pre_balance, post_balance) { ( @@ -498,7 +498,7 @@ where return Ok(false); } - let author = self.ctx.pre().read(&author_key)?; + let author = self.ctx.post().read(&author_key)?; match author { Some(author) => match author { From fa7ef5c2c7f19ea1945578dbfb9a70c9c457c89c Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 2 Nov 2022 14:58:35 +0100 Subject: [PATCH 04/10] governance: more refactor --- shared/src/ledger/governance/mod.rs | 48 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index 692159bf9c..8e1232d4cb 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -96,7 +96,7 @@ where self.is_valid_end_epoch(proposal_id) } (KeyType::FUNDS, Some(proposal_id)) => { - self.is_valid_funds(proposal_id) + self.is_valid_funds(proposal_id, &native_token) } (KeyType::AUTHOR, Some(proposal_id)) => { self.is_valid_author(proposal_id, verifiers) @@ -106,7 +106,7 @@ where self.is_valid_proposal_commit() } (KeyType::PARAMETER, _) => self.is_valid_parameter(tx_data), - (KeyType::BALANCE, _) => self.is_valid_balance(), + (KeyType::BALANCE, _) => self.is_valid_balance(&native_token), (KeyType::UNKNOWN_GOVERNANCE, _) => Ok(false), (KeyType::UNKNOWN, _) => Ok(true), _ => Ok(false), @@ -171,6 +171,7 @@ where gov_storage::get_voting_end_epoch_key(proposal_id); let current_epoch = self.ctx.get_block_epoch().ok(); + let pre_counter: Option = self.ctx.pre().read(&counter_key)?.unwrap_or_default(); let pre_voting_start_epoch: Option = self @@ -255,6 +256,7 @@ where self.ctx.pre().read(&max_content_length_parameter_key)?; let post_content: Option> = self.ctx.read_bytes_post(&content_key)?; + match (post_content, max_content_length) { (Some(post_content), Some(max_content_length)) => { Ok(post_content.len() < max_content_length) @@ -277,6 +279,7 @@ where let max_proposal_length: Option = self.ctx.pre().read(&max_code_size_parameter_key)?; let post_code: Option> = self.ctx.read_bytes_post(&code_key)?; + match (post_code, max_proposal_length) { (Some(post_code), Some(max_content_length)) => { Ok(post_code.len() < max_content_length) @@ -298,7 +301,8 @@ where } let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; - let grace_epoch: Option = self.ctx.post().read(&grace_epoch_key)?; + let grace_epoch: Option = + self.ctx.post().read(&grace_epoch_key)?; let min_grace_epoch: Option = self.ctx.pre().read(&min_grace_epoch_key)?; match (min_grace_epoch, grace_epoch, end_epoch) { @@ -308,10 +312,10 @@ where proposal_id, grace_epoch, ); - let hash_post_committing_epoch = + let has_post_committing_epoch = self.ctx.has_key_post(&committing_epoch_key)?; - Ok(hash_post_committing_epoch + Ok(has_post_committing_epoch && end_epoch < grace_epoch && grace_epoch - end_epoch >= min_grace_epoch) } @@ -341,6 +345,7 @@ where let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; let min_period: Option = self.ctx.pre().read(&min_period_parameter_key)?; + match (min_period, start_epoch, end_epoch, current_epoch) { ( Some(min_period), @@ -378,10 +383,10 @@ where } let start_epoch: Option = - self.ctx.pre().read(&start_epoch_key)?; + self.ctx.post().read(&start_epoch_key)?; let end_epoch: Option = self.ctx.post().read(&end_epoch_key)?; let min_period: Option = - self.ctx.post().read(&min_period_parameter_key)?; + self.ctx.pre().read(&min_period_parameter_key)?; let max_period: Option = self.ctx.pre().read(&max_period_parameter_key)?; match ( @@ -410,17 +415,16 @@ where } /// Validate a funds key - pub fn is_valid_funds(&self, proposal_id: u64) -> Result { + pub fn is_valid_funds( + &self, + proposal_id: u64, + native_token_address: &Address, + ) -> Result { let funds_key = gov_storage::get_funds_key(proposal_id); - let balance_key = token_storage::balance_key( - &self - .ctx - .pre() - .get_native_token() - .expect("Native token must be available"), - self.ctx.address, - ); + let balance_key = + token_storage::balance_key(native_token_address, self.ctx.address); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); + let min_funds_parameter: Option = self.ctx.pre().read(&min_funds_parameter_key)?; let pre_balance: Option = @@ -452,15 +456,9 @@ where } /// Validate a balance key - fn is_valid_balance(&self) -> Result { - let balance_key = token_storage::balance_key( - &self - .ctx - .pre() - .get_native_token() - .expect("Native token must be available"), - self.ctx.address, - ); + fn is_valid_balance(&self, native_token_address: &Address) -> Result { + let balance_key = + token_storage::balance_key(native_token_address, self.ctx.address); let min_funds_parameter_key = gov_storage::get_min_proposal_fund_key(); let min_funds_parameter: Option = From 1eb7f1e4d449282e8862462bdea345039d503bcd Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 2 Nov 2022 15:34:00 +0100 Subject: [PATCH 05/10] chore: rebuild wasm for test --- wasm_for_tests/tx_memory_limit.wasm | Bin 135502 -> 135517 bytes wasm_for_tests/tx_mint_tokens.wasm | Bin 237764 -> 238002 bytes wasm_for_tests/tx_no_op.wasm | Bin 25027 -> 25030 bytes wasm_for_tests/tx_proposal_code.wasm | Bin 212270 -> 212469 bytes wasm_for_tests/tx_read_storage_key.wasm | Bin 154943 -> 155038 bytes wasm_for_tests/tx_write_storage_key.wasm | Bin 228606 -> 228689 bytes wasm_for_tests/vp_always_false.wasm | Bin 160341 -> 160371 bytes wasm_for_tests/vp_always_true.wasm | Bin 160683 -> 160742 bytes wasm_for_tests/vp_eval.wasm | Bin 161259 -> 161699 bytes wasm_for_tests/vp_memory_limit.wasm | Bin 162871 -> 163735 bytes wasm_for_tests/vp_read_storage_key.wasm | Bin 176352 -> 175916 bytes 11 files changed, 0 insertions(+), 0 deletions(-) diff --git a/wasm_for_tests/tx_memory_limit.wasm b/wasm_for_tests/tx_memory_limit.wasm index dd2372605d64f675a874dd0604fa352f0803151c..c31821bdf45cc9da95e876de939171236563b048 100755 GIT binary patch delta 681 zcmY*WO=wd=5Z>AMx9RJPj~Zf|2eN%)2_>a%B5BcD-ToNcCMiYmqL$QLRYdI~ z^&nV^VJUbJl-ipVg#~k|pa(CaLQg80ScRh zEdmxe_0RVR8yg=zIoS3|F2G;QUDM2~lw_?a_ZY;|I2yt`K>MVu~55P?Lf` zDn`hF-SWvA>BF!hpR}zS3i_k}4Cf41vv4fZ9m8>#0>%DhLM5sil`KXKxxXauSObi? zh{e+2%2Tl;y2j0TmudWoy5f5_CY~kY9zzr*u^$=?a)EfCn8$otqynx$ZU!}5<~z8}%~0dj214SF`^B delta 681 zcmY*WO=uHA6n<}Z_OCH@iLFf&k#WHiw54ql(jq}Kt)Xd5QY#{eQj?nmM3YuU(1cbG z9;8?Xp-`kD^eUo@#zO?XiJ&6(AXpEI9t5FB@gmM{d+9KIAMbtdXXd@HP2+vjxIc2F zR#fZm!Fmy00N8dwQK@-u&C^|tZU^d~XQ?texJ&nUDnJkwP!TEaHW0zR1a*@rDA_wi zMbl7m>GNIV=&{t;_;AM?=OX@5eeJbZ!0$=0xG3wFcG%zb@t!qLvcV6GFv5*8qYSMv zku-+1EzPMK0|eVnqhnE#G}!r1QBM;27ZDGPb~9weN{3{YEKp7m;Nbh|ECe2)=8_MT(^w`8DfU>BQ~qJZ#z3OqvC?|BKev! z*}Ay)S!4p}@p+ v{sMulc$$ApASY^t^Db=^o@3GxQ(sWh^nE*Zy`tkYw^&4KwKXG2!^^jrP(uu|!=%UG!naDORdr5v#3GCcUAD#*3bw@BIb6lKbni5#@& zmq}$7xw3X%L|JX!?6Q)^1tqiUs!HZGHdNPEF(;J-HYuvx6gU_2~TvN6eOp<-?ikr-MrZsDFFD&@>V`7-`2XyqV4phb=( z+3hwxLsZr4b33wRVCzC3l(q(OE4ML*4(oYkrB&uE%oZp6xv!~dH*@)!Z{;=5i0{?v zZM=tn5obQ`s&E7ad!l1{OzAVVZ+BnbMHgG@mvAK|wd3ga>D_vcDi}PZYC|Q8IX{Q^0bNBy|$8Ky{i z5_2g|pQk2`xqhz8RDEL;)S|IA^;Sy<^;L^Agk#=PnQx{{(RhH_qGY_vy29XQ9i3)U`2rvmBF|-D3}9TsE?%txg|liPH)^_ zp;!IgHnPy_4st10C1{wXfVl8~M0bHe7v%Gg2zDt!0$u2!;8^N_#t@3(2Z71)^o_Bh z=Rv_7e36MA&R%STT>-adrr0qaaK)lH)phnZ{DAtH{o)x%f8N9LBn#SFAPGJ>#p<@3 zco6khcyNw6i&7U^6M2-HZI87OY3eJEG=5V3-jQ#?j7F-z*xMyWqOZta%z>}gREY+S zPVYp!uix-ssfDExe-m{Pg1QKz&QG0f?XRrpFE8&d?~{dy`5w2{c%44h3o1(qM6mPbGxeUko9%`u4Dy&_l_$7UKts_VQ|rKKhl&2+=zi+*l1bOtBL&0^TSXCWay4 z&48`?Km@!EutgsV!GwC7t-Gu?xx@UyilrIPF;Hevtj+LIz*bW~hXLCaTXXp#z)mHs z89o5mrGywT_0wd9WYGK`GgvDqItobin+?!y>hcir)j;4o07&p$G};Hqr4|Ht?Ab!{ z3Ax79`WT>=)<*%gv_1^TrQQ+TWrEvnHK{GB(%)ffBcT}aQ(;dcF_l6$t-kj^)h&iq zSPWf1c4IPRLl*YY%oxA{nl>GPVh5PeGCwd@>V}Yn%s}Hnvp@q|a|0+?pebw_8pNu< zhb*rHT@fvG88*YJ$YM>C6st*(u~4*!I(u1vWhK@uTDV|32Pr{=8iFO*P_nC5n19Ub zy+SVo8m+55X31+;zYlGjPMT;^&ci4mgJn`qh=JFp_VHwMi(2bZe6r$%Wzg~b1Ysh< z`GyN+7Ul#3Y7#$)r_v(y5Kbjnea({qjr_{fJPxmu!oot2zyFH}^t; z$R_y6O4#vz*jm#pd}K^q>WyK^9fMJV$!RVjYve#4X0JJqjFt_{#o@51YMKIlm6m)v z#V}fgavNZKi!SPR!lbLhRG5Y(tVPS9iSA?2snz<@Ff}~>LNKklH`4qT0g!xT87wA7 zkZCdZPL{-F>U|~PV8x-n93JO~oeY@8Ca|_ekx1nX5rbZzrE zG9(r~t9@I;kDW zF?7P~BA_FH1DFGdv9-n%LMu!R_&|7>1VW*I5=oHgF*eX+KQHi$&g^*-tcawzxiV|QdH>7*VNJ1uY|3#+LT z2#PUUZMIP>D?HZdKr6W9fmW74tM+n13Kz0O6G?rwpz#NKKYu)KqT`T61|TIaz=>3Y z_sI0R@+9Hb#^p(Hv~*^qp$#}sZGwrpZHcK8gbi8Ct=M3iH(P(pUeiH)R!9Gvo0^(7 z!n9eihOCcID{+X8lJ59m_KBb@B0fWEvU+XUV&x%$3>$3-9Af_k2OT>wubV`#KTF}X zd!T=cBShj1n@*PE#wPn1n+X$@k`RMYT}HzrQSv%6B#T$px3A=DSY~=*$U%*Q66Ou@ zSLNd@@NHFhjX|;=`uK%kcp zuT%-~-OI(tumrCgF#-GyPw+}T`C%~}{@KZ7AU zJDe^I^J`Y)<1{#1f8JfX2stMa1Id$$kwQFX1n9TU>9M+It}N+ z<|~+~%N4Lf;(BzKi(ACds`!N*7B|abV4ZGJ2<*#DaUEUwd{Gqd0jJZv4&qS;*y+%h z93uz=8)7#m#(`y(CL;yo#q412K*)>~%u$BquSk)7jKna+aDP%5Laup|hl(vJXo|H< ziljE4lyL0OLk3$gYl_>0JhI~A%VAaAF4!g|vc~I%e}WlsBTNaWMWo#DKxkInq-(S= z^`$97`yvU1qY0U?2#h5{7%no=7AOcOPQpQQ(K4d=fCUv9^oF@SaR|VQ{vC=N4c+J* z*3hB)I}Y}faVH}WBS{t>eMJV?0~>}_8)dYF)2uRHdt~kV1HUAX-X;hc?^VL#)$KJ48KL2v6LY6B8hE=SX5-N2&}*~w&*jY><`uy@JM|jZD`~l zjoJVI!I)e5tt5yfYQk|^ZWS98;jNJt2fQ^n`TNNK4(wBfAC5h#0z0~rzTt{4r*9aP zCM+LtHp9_}SY5GR&_Tw3-c~m6F@0{o@Oy#=1&1g>{jVeM5*FT~K%84Kn9vIQDEnHr zqd`KIeEZ5^eQuL+l@I z8(`^Hh}O%gE;>#%8aIi?B+qey#x7xjsAHGjF(dziE6`)NLdxq9+G`D%I7>j`#8!oN z#>Q49plDW7G^?R#u-eUv1|ta;SrE6w1iP_=7ZhHDJ(x}B(n=(;L<{SIWR{*hNt;o8!>39*hs%ttAZRZNid@u?v? zEwqExcl)a?=gqxfm{b|_D`HVjbz#cu^y z)dihn1+Jnbp`jF7Ff_E4s;Q?trz75+o}Hw3onsHolauC&f)zL~)-8&8o&rt?39tHk zrv&xg>;!4~uj=vaNBtI`ePr|Q98r5j{n65V5^N;{YB~wFLU_z4!B*iK=s~)`5(I5P ze8aRmw+m$qlm>bcXBK|*p@q>|-V$99N4Dbff3Ttj{w&pm7A}e7K<4R#ZhrovFP8{!w_17>1-{vL;B;ov~L%pQS zs9r&kwUbui<%k8Jw1o0bAP+-7GmmsocN&A#+ODx`eAjq^;u-@5w9i0+sJf1#bzW-} zy;FsU!2?xc7C@rV-poc?k|+C_0f_9`Gc2ot5MI!+zyxTs5&{Xk#AEE93+U=fl(@Vi zBBUGb*!_e;9H8aCj=r@d3Gru2!WJrQ*$dI;<^Yy{H8DTlPWaj=9<^`&kQBOQ1GUPN zXmzq+x+QEod|Qy~+lvp+Kh(SOYpYB!PeE7u-JA?b>=K2hQV#7cC58EA-&norOJ~=kMaQj1jJa)cCeRkjgeA)-m=Wy|Pt@wOXe8vo> z{K?{T!{GZnnJ(|}GfXx=!(?;carN~!5$ZpNRN$t^4?||~qv}ONXa6-6-BsVPgumMK z;IMefKSDh=ER~N?BMUe4C)Hhr!|~}H?gLRHKZ#Y#htK~j*b_!f!r11Gs0NzDBgXMk zHE(1CKJOVhKO(SmrscQB_w{j-7PZT$?J*xnQs7RNM_j2=c!m_~`%OJHs=I&LPpC#F z6C!ee#BLC6rZMAfuuX9*+;`<4RmcuhxRxr=xx|?m_EKPpP+U(nXc0h-jYu1Ppfn1_ z+e|&|6vf-08oj_GfA5P4+zks-FB1j$PXj#+HBQ>67iaPiRV^Mq6}*s3_^>9ja-^prm_(Lz|%DHAhdLNH7WIY>cQa4Zo{ zz_t_YS~oF0I2dJg=?%Rh=fK3rLEqJrygXRFe^RU~crYorPXYtg*C)mL1F#G@i!oo$ zVB)h+o{3385DKvlyAr4Z{+O#+&QS%CUvm}fIjY!NS5aq74hCiOCg<^x?OP|elaj*} zM@q0%0RG9CIyMUQxGIcH55es#0cA1C*Y9Es+1A*AS(bhExPph7g|H)on#loIB)kz9 zHIK22>7+nzZqtBUUQJDV*xQexO4E6S8e7&TGq`z7Ar#DqG)jTS zk`g^QSRA&|Tv#v{YH8W+=R2;R-t!ocHtnwr2-0$n0mZ91<(-DX8bF*VVrZG^lZIjD zaM1SJ? zB8HznpwExjLz77zpo;oic{cZ`nH6a{VT#k^CCSETsPC9j8~Z8IF$y7CO2|wFv6Kkt zXtcVd!i%9|RBGj)d#$b)^SDDLus|}S4c~|x8 z${F|^H$9zqQ5R2t4JKn`RSp!>U)3%mhfd40afFJm9#|-VQ{7pW$8*&0s*3PgFe4We ztv1YP7uiMFE4opNO&wF@8q&A>W_$*GYpN%DqG&H0MVG0p?QudGrT$vov2&D&?&1P2 z@)1;aK!EISU;qsMl6{9zAz#5BR06uOHC^Jc8U(W4_znuF2bFHDnE;Yb)U*fj-kF0E zBD>29wr4oykGvc42lSifjiDYrBh&{!k5!LZEb981!Jf##M#@H=;3RST6Ek~q;P`2l z(l*S8r6fc0ctdfpNU1iUCJ3?llt`#a5FIlrk!r8mZ6iIhgjVo$LNwYFha=ggky z3>9(yNbvrx*(NS&L$3~ZaC?iObxvT;BXscxOqHZ4#C{7AtS zHWwCJGXi3(5~cn;XSO4XVlue#ynSY47UvVyC*O!yx6e)HcWr-j?muja<7kdOB>4Dt zAl!o(EzVUa%IBBVMTYG>iR{oYQ*Bjn4vX`r-{#KHR!TFB9*1i zy-X3QO!b+|2JmsJ%|DbEZy)V{nDc$AWy#*K2{5hbj&|)$94307`p%NBC<|HoP{b>A z5YQ2sI6m+lCYNNN`sUIuJYTghJB3f{^0x9iM=(5+72UQTxm0=t4Ix8HQ-m$H4VaONbn?%(O^1FOQgOWnOHl^@>z>8gL=T>`%v z_C}O?#kGmtwf&B3Q)Iqn`}5b$Bfn{T-|MGH)_!pHkE$DQY{!35U$}8xhHvvqD7xYF z(Ye0x*kJyBbQg*|Hl#g+)Ft09-o9JA*+S0wx&yqInt5w6J}O6JKi5x$Mikt4(V8Wk37z?Zy$DZ^}vPWtvMu@PNNE>y@a2hSiVlf3r ziF9NHY$V+9st9Hxkct=v4$C0+t}D4rj;?rp0IsgAZhNh}ns8MxC{pfRPCU5l&M}dYOgV+P!Uif4R=LPDlU32hxc-N=)f)oYVKF@9Dt^uw#;2cr-qjkn1we$Wkk;)LCiW6dl>5BD91GEPp0*_349|YSCMY8vIretWRu>dg)tUwbxsb$n0Qb6sWu2>IxvEM*a6&_59)O z<^OCa!$Mv4&V{gJAHFjbS?TX)Spx&NH4mKFK&Q4k8wi5_wm|BZV-C?K=?_?Tqv%3Kk!1HKGeW|{AL?6=7VIVn%1f?5C1Hvf9h!&mS7=q2U?v`js5i+0Pax2t}a zg=C~jf)FOC@!uC@_^w}OGQ;kG88+*{9ioCD_Qro5+ zuKUzCzV63=RKvf?_WyheV-;JG8sABzVdjbW47#Mme0z-2fOI}<*NGrZ@c)l>dhw;Y^Rq(4L$0HlhL+sDH%pd{*n6a$pl<3z^Cmg$_^Jb zwzkyRq)t7RAgx`hCZCSCt!zdjpIY+F4fQ;Z|Df(am0?&>@AMwE^i-Vu3cin>jI%vP zl_CVi_uo*<6QoyuzoCxD+cr_YK9Uj z4CccYiUrL_{?u~3G%7yGnShT$>z7pEJ9+gp44w%c5ugIfP=fooxNAoxK909bTqx3> zmUw*B31m?f{|Iv0hBq_>qf~pr%7?f_n3+C2|Ip%W{E}7~>ur1j|5U4z`Q#MI?}HaY z7f*=4nzhgQz2E?dyK7C=Rr_St-%+`b3e=i?8rqq1pbv&w4AE7?a2J&f{?<1Yw* z0@kt?@R+b}0L|SNYU390<)LSEq#aqnhXzKPvygY@#ah`y{&Y~>#b`Raa?YHxs!BnW12FMpqW1bCo)9(($;tS02eL2HPAx(&iCW5H-jPqyMlR+t zeCm$M#W=sJC_$xC{FUL421pOb-cK#{62}r97smV8~t@G17Q) zo^zfLPyex$x8-BChnMmkuM2FI#yUa`6k>AT(HI+XL=@QPYxZTlD(SskxF&YSx-6BV zZPfsbC-jCS_j>J`Wst`ov~A1yF#fUj>oQ);8?@@>Ji&kWP@^X9uUru3zPytOE{bwb zL>$t1@-B?@{Dk@&(NSJyr0Xsy=}x43Dcl*h5WoQd8R1Td&X>3^V?24)?QB1oc$r`3 za(o_uHTiN3wn1xu`Cp_Z8@g!FG8E}%T1o-@Nm}OJ&O@}fui#-xv6nEm0F#_^ChI4* zW9;J_R|x*qt@w*HA8XS>vm?<&vjX5x((JrK@UQa~f033ZbZPK!t(lf>f1VbDe^K72 z51oT|b9TXlJ}wIE`?Qdiyoz_#=B?y)?Hte&NI7p7bNe?kNzaDUag05zOS)sRhCoMK z{;ZaBB~J+b<#o}7NpX<5@B`Z9D|tI9Z=<&CO1{{CWnV+~(A#KhwC&S=Eg8deoVG(I zxKMH0=JjkTFTBEP`?7lrJnTZJeF&{mfoI@HZl~?ADPwSlFxv;F21EUeoUSjRgC1zY zz@E-T+gy`E4uC@LG-<dS9*vlDZyT(M((6Mc7Kba^VRut_{G!3!viexN4 zy_!*IzhA|((tb8!$obeBZvVuT(eVYz>FAQFjlPS1t>0WvmZne1ftXU$dWttql2 zK1ciUYMyf5Bq#T2w1&Be?3HG+H=4=b`Nw2yH(bNB{f>?;gyr03bvu4D4X496DTvuu z_Aynt&zfq#)RZw|h}_9u)U~C?h!8o(zQi=uX&*{XTbgOEN0o&+Vgj(A8n%5z3Kt0M zmgd>RJWyB1O%gS57IlHUpg&dY!f!lb96tN_V8^uonKOT^yXuTAQRH zQGc^Z3Rt8j&_foRC})Mf_0y26o%XH&(w!PpQBb<6YRfrY{^K!&ti3KGSx`$3e(2y zYfKY8>Pl;peYq(k&1nm_&ktk>8BLpP>ttVHmcJW$r2Qh3^OUg=ir3dLm3h_!+iD_sbf$~?-iCDAS8@jz^}CM%^y#8L4-1L(vZ<(EG(n|NP)O;Y=Zj-Q!zDyP6~HV>tH~r z@3%6~X*4LJ#^v#zn{uHl3jmO$J_kmurZh>a=wmZgt4L^#b9(eyI9m(kK+o9%`N#6; zXa9Z84=C6nkaK=Zz7W|HRNWBSjF1+QEk@c9*_D0(EsC~NR5L{O3{CsneHj|pBuvLq z^ct`nu!eBd48x&Ny4i5_0MtC782}6&T#K|ZpnXUO#-m+yJ#Tw{>;9eB^W>SrRq>cy zl~MrBu1XUD=j*Dls7LN#Yz`dFoUeI!&UnVgVb7gYXXEn0V#Fx4&NuLk*kSwNwxCXK ze~C-mkdR{^U@Z8!R(As*<-Z>b%i1uMwoP{BKqR*zJ>m+B)Aa_aAAk#P<#CbKP_n}S z#NuK`m~&Kk$YdvrCR^QVH=}Zm-GYqf2JXHusR__lQ-fG|)w4cOckE0F9Q}NeGPRf=77=2ML1l z=)y27(|{o>J9r!WY!eOXFIa=!lT8_8;$d20usipIK%pOhZs!z_1;7aaBYjR6c|M*9 zq|z7XU?WcDQF1(#3?%=d?E=ji*+8j;s%KR!^mcEiRTQ zJ-^QEH|rR6gd=&P-Rw7yEaPq9IEyt;>va=PBsr zUMT8XgdFm|k8&F>J`E=C`%a>48e_jK+DBv=g_P6D(W<(g>-A4ieVIo)c4{T-d3%0ByAof+hn+_D0B(8pR>tZA={l2~(h&3?^?-J2Jx}$$a2sQ{!hYsmf!JaW z*cdf^2kk1+EQ?2-UdGr%Hl#bCvI#=TUJ|3Nh)xUdAeksW*dd2Z-CBXe&1H{`@=b#Z7z+zfWs(+c`+P z?i_4VQd-#51Ls!x;;uIitsj7!AFeF^UZ#a_9IVRWGAYz_5+->w_6g!TwNGD1YmThFy?v)B`2ulL6pRx#1j@M>6Qi#0?2vX z5^o;|z<6?AvqU+Dm@_`Za@@Mg0ZW{zN*S<-Iy+5EN6y>8JK41Ok>_qJ&NjM1??-|i z!%eUeRYaGyJ@wAO zZ2BFo>oz%@E(#;;iwCBqju;O`It~Lsl*2<&juVv53=b1QHW(5_H_i-Th-gO!mGz7e z=>ke4^5H{!@%ZsMs1s%sK`Zm*~BjEmu6jy~p$ zp*)XjyN2|`l8JtEu5u)K9s^Jh0PCl1E7H`zct#!y^-zRjB^7S*7y$}Vc7Cg;Xugq} zZ$1C!fz^ZJ8@A^_kMWFrD6v)0YUGPz?Y(6)j&!bagbB&mNrSrD5$__&H~^qoGL8~p zNCwWN%#slcFy|Ualznn9qcddu!_mfZr-{E=7h(hHBF`h6>aTG`3)f>P0Kdui5Ez-;hKWue?_K+ju94Bbzfj8M;&K%3M!h3jn z!rC%VrEQPY#Q;%N> z)L>L4W9z{~TYFlY>X9$M^AclI4f34PZxQ<@U;rVI z(RT0A!SX+lWw}=izMsdW^SiLEfd|@s66OsNbyV(rGf-h4-TgEQ6 zmiu|KzZ+!f63l};+sWmxu}dt3V7dD^xIE%99q<8YqYtBH;m2Eo>{m4NWjoI*D}U&Z z%L*qqm&s!;W{i)~dOZM7U?kjC;F2d*wNSvMjW!JWX8Pz2A6MQ0#2qoIAsTe>3QYGD z0=7X3-pOX{7$jDdG;CyS4@MzMs-`pcBF5g9+N5SM_B{dA=GldM8!D-i_rgF^BT3#_!C>mY21S{}6fs#8F#twqJq9nJNu^7k!wUO>885}kUc9gKlm^b;W2N?SjRJHvL z61j5>MLF`f@mN1m8nX%X^u1f}G{%bxzs}R?=}#p?*60)v0K9248Cwjz@vESHDNt<7 zmVCxKeE@x~MMoXVPzS}m`(Rv7EOkksw|93)`;cvneFEdq8x7^j_hHL%fVp(Y3)kRF z?Za(6x-bMYS^O+II?H5KZGj{B6*}I{!P|<_4|ob73Zo2QatKI3vTg6d45*5>hMU?*B-4=ZO=0W@?V|@FV$mQdqL^DQz__2n3{ZLmOy3n?TiC(|7aX=UfpH2*30=W0L(>_1p1MR@h8|IR0Me&6LsrlYrQK7o)uV2Z zzHuy=1L>pmn)!^qdO+mM4^M#Udktv?qLZ=~wiDJ)0M~|LCSE4MkD`UJ2F_Oi<#BGQ zE@JErqHP5%gBzsD!F_RQh`2EYb;n~E1PlPcBq!GxSm`7luenQM{60Fe6 zp~(FOz-9nzVGxF(TH3XoORo?W8G{*n`~-5gqIg^vOv3R1aMvmbz^^*MG8QESB$G6cItU#KQ)B8UW~M zS((5V4J_KbM?{bUZ6U*3J1fZaQAH5Q#4_?LCzadmqseS-LESN9kGYM0`3>EJ-D#ToB0LxHAY(p&pFs4(=!i-J($F~tU4UU3VcfE=FJtXL(bJuuLlF1+05Da< z^*3$FBRp2h*{ab$1+pY;#))e*puE3r;Pj51J- zC4xxt7)xyNwTwOMKAhE*{U}dP6C@KKn6wN`vxM)1P5@i}B#gpoM~-8? zw(U_~Hud?_5Z*Dy*alt3*b|f!ho(&GhMH2C6(3L0`t&J2#7xu-Tyj(Sd9Kfn5nl37%Ill8AFvYo6PbWge~Ml9MrVuQaW-iPflm-$`6o{#Vr%V zu^svx?{Q^uW*L4LntuVHeGRdJ&VHnKY-q6w1u-Y_s>lai?%Wn(qGL!;hT>i7MwJC{ zI^=toL*c$h_B84qxks?>>B>$A5Ix?8^A;&6D-S}!3xqad1#awVvv=~u0i!=dSY-jX zl!76HzQLw<0r-0>uv;e2V5}b$B5EwR+=Mx_d`HI_MBmkzCh1G0EVkW@ZP#Ai$z%K@ zzJ%A?flJp?AyH=WUBlRe|3YqOZh5OSP6j>_X_Rce0j3q4L48#2L^CH;_(zBwH@12g_cg^Aml55iXR7?mIOwHXm9sI*TV+?kr&JY9IxG@_!P8M5WS8 zpv&5l$9QbyT3CpVv&a{_7mWEMqSd zfWV*p;9^|M!QirnVJ#EYwD8AyU;m6=khB=&Kft@VejJEBIsx-!r|S~{r0J>MaT(z2 zuB`b<9UN-^$OOZDI_)Q6K8+`>%IURt?`D9oEEM<%%5KS^z{e?Yws|uhhXD}7FPSd$9C(69`sZRIj3;Xw&vLwI>M!dC985Uw9Bfp;6g`CVt)hsu|H6?PoIWzJkh6x;Ug-d?1d&FA7SH(u2)fEWdvNCzED!SeX<$A z2nSctP6T)M5xg+!uf&F)=mX(AOzkg?c0C1oJwa*o>iH*z9UBSR3wJv9n#4cj9qx>r zhr%9I2mrgRvq+xT1tUiJfPCK8btf!+69Kb$QWzb7Y$l+#Jz`)Onx7pY&=}hZ0Q%S* zi!fB<8DZtg`iYYgg$j#9MA)YX(tjBBDWbyve&FOk_njVawlA*e1UjR*;!32?aUtRDLqS@{Vbnbod97^?a8GhSR^&LMW4OgR9gYsAk^k>GFbjeF?;7d&ThE^q4cVtO zJP^y%+VH(NPWnQdyO*coy8O+1c@n=!du%UH_e+ByaEa*lgwqz$%@`A47<`)v{=XRf z0M>xLcV%>iT%$`Y88Lpl-()w>&)7$jvG*ha!GAII)bD?>^ChTqZbM&Bh8~@ep}(38 zJ<|Wl&{I{z&?9YJ+U)Z@&+|J~xb>LQ2^QOCsG{*qz$^5>fEmU^*K;0(b{da zO6Idr<5sq-1dJ*2jJ*o#gx7SmGaA&*@N1aecb0hq#{sZ zVXSYH`$g@SeKHG?#I?RwjjnFh2>t&-E60N%)_Cy01a^#k9(@-R^{aV=W0$#f4VEa^LnE*y(g)|X z4;yVXMg4#Aj&=w6xq&BW84s~9%pxc-em7kO>TPP{`owC_G{HfB9&A5R8bE-rpiS`n zJ~L%Fi#hHznlcPxvBBxZ@y+Q{ahy!4}-|ZW<|f^z*iu)-R_a4l4bV)l$D0xw*=Xo5rZ_bu$VLbi-YU`gy@fS5aa z!RMeUBMdM2tkzrT42i<^a|&)@&&oV>{rumkJ%a$;xN|YqxWuR|N z-M7gN452bff8e8pO%=J2X-1Gvh@w90NX<@G1aoA;0hgb73S4=-l908kn zzUNEyj))dh{J6{d0Re$Wp?kA+Kpjh^bZ_=8^XT!iP{(dYU7XQ~mxZqF(2|oRUKYX? zFB5gt;~z0Gpw7Z>oevjX{V*o{uctJO6jvt*`%nTl^9WBgfKmXNy`7$!us{ot?mWcl zDnWWR(%veBU!OCL)%$6p&2KejB#sTYRhx#}W^AN=iixeE2=2Jea~nzlp4LsK#+*kJ zcbL&DjlWH)qcx85gg=FYP*l2GqnMF=J}7>n$e8i8sXjyaYR-UXg|rsV+925brQq&n z;_hcru7Q|=-IOlpk)8`MQHKCzW+%D&z+X9rH0CM8lL^3K!S3i?r|mnxiQN<(`Pc;i zjnR>iu8?N*NzoDeXb@mL{yz~N=|Kqo@6i!--4YxbqZ6Ws!M}wf6%l6;9hnRwXCVC_ zq9aXIH4q(Hi?k6PY4aXlg-(UKZ$oCnZ9LmE9l$;S3bcJ9(#E6E#dXs5!&FFd#6Pd? z_Bm#Rba9>Z*x%d*-CQ^8Op8671qnH!lNjZi3fb{svn5n{2YihT08nMuy+{`z?U{;S zN+7FgJf15Zi8ivF#zWTAu!5q0n8DT(8!)HEKxdfKdP<*dPGLRwqvMs-@l}o}R}skD zNWi3^NY7Ldz7v2U+6Rzs7VV<|Qs4DMwoRh^KNf9<@I`CUrt$v?(T*hqf2U}JLxHD7 zw6oEPA=*Qc{tu#EN>u}*y#Q&GXvg_m{eVWo?byQoO+TQq8a)|~zd=4b%kS6Pe}ucc z|1%;spEnV~Ganh)OeRZM#bX?!Oq;FLZj#&e3~KBqX7-RGTmxVQ4-qh2a=H$pw zo5;bLu*noBA1)!q?Dv?Kbo_@hA&zz0rjO{ikF+N~;>yIwv0beA7(wv1kZ}P#fE|lC z@VVqR+yZ6V5KQY$K8$$xVU|Kz+lq2r?_$L_(D_0)Kc7}{UKHBafGKQ z@fQNE!nvLHPsTGPf?8>dkMI$EgZ9!9-d5t9weOGcjF1k~;36gAe#mfVWXv=z{bSzG zzr7TuC>ePJ6qIN&uCgbaGvQ^hTsB zCgC7>Ab_0&d<;iA7r+4me&bG0TL4E1*yi+%ppB4%^e1tyJN+ZziUBAmcl#y)*#JtG zJ8k#Cr8b@t>}2Mc;8M8R@0#JWb}}W{$(-qCpVP~pW%R-R?r<8jU7p>HoK+kRb8OKL ze8Qt8WsG+86P`*3I>Ddv^2z4gYGs4uxO3lD8>*OYtCa=-aa(NxfIqmcroH?rACKSQ z@P5YcGWyf9KIdV)kJj&VeqrEHY5I;|Kj&{s5uvkN2%hn!N7R z?_XUCu{@>#DB;18DF9-<2-MtZ$8UmufobUhXhtc11n^w|#QQW6M;sSqtPC$4#av@2n)hj2APun(JI5C)y9t20!r3>Mh4P5^@a?fp_{b z3p}o`(dka==W+aq;3QCLJTs>8F#AYTMqN2V#~+xG)?Lq?jtn4eXS6Y}0=6$U(KF)# zDcb#-_RUv3TWV+3lE3ENhfeqeoyH*`_P{fYJ@yKKRAE($K$rBn1gmn(gSZ|<1r4I$ z2<6!yW9%RAAn#$AsHc|EZx^lqn)e9Re?uz5#aXo*S3R{Qzv8E{e*2nd21;JGb9SVq zWW+bkB|~uEYa${yfi}0IBu2+}A=~N(cUzGEs?*^_XNR;8j`17$u^o-y^UEas%-Ih=@NCZS*V2B%PiwuX z75#)?d>as?&HjnU_jG`ZwxS`f&S;p8v{jGx$jgfvTf#WA4d?K;^vAfIwFI5*)^-Dp zzc|o*JeoI|ns(9IUO1hoCqMh3TXxFg)u(wF5C|~t!?_5M_ZLU=(5j~Kl6m{ zbeGdMeYjvpy;0qfkH%}Mq*O22ZInPXvTw&tA1&lKkFoV!kN8KB*6}!x?{PGMh#2F^ z2=wbH2h;-)A)=CEqXdXD9wt+ug&yb8#T(}_c4L4=j|q*@*<{a4;q+OMW%OphfqDxI^k{p;$>d0clJC;ioWM^J{!80>g14EF zj9Bxz@N9h=KPad3#BN6j%6M$Mfacjt@xCR=#yJRZLT;E{Q-0w?@e6|0zwi!z|6cu; zwgnfn-S1t=#HDfkKi1rxbRjhF5F+qYau;^0bZK0aT(O!l-)R8TP_68K#+FeD0BBzG z?RNJM_vo0dxR36>1X@7X(XF^z?siPn+gp!Gb=Ycbozw0ha z?3wyqcTqBbCguZ!6eXjd#cf9d&_=LgBt9*8F9Dx{-?rNgZe1E0urXsQ;%4hCqd68#v`{D$hr%KY*fWet59xiMw4X4RFKHCD2@+Sg;`SS@L=?2%HtXxW41 z;_>urOmpfh%S&o27c}P2ol|{DWnZ?S6k*Nk+4ZwhyL4I1zD+ftobHR+ZZs&Lh2Lzf zU=I#PazI7jqG#n!@+WFTly6bkkXJpS>Wxhbe+hijZN_GP_uGMo&hzljt>gLu~lr=15Rh^l(q@O%io?pZ? zgc_6cm(plZ+{oU?5bDb+@XLpdl~oNmi==a_s)oAxCBz6uza}uhp{%~Xy0)rh&fICN zk6_^7!8zD7ThM=iU)>h7JrF}3$_2mZcYWs8Qqz*UhWvJO8Zj$$X-CfsOw+%2^d2Th za6VZZT`0%KJ_uDBw4kiK@j^_;FmSM}v95uI6lnfJIfbv%HWkX5e4w_!P+l*`7cebl zpcKhRXv>Gooszym+u7)BdfluFc48I{3M?rpn^xD*$m+EN!{rGPw++QnRoTL6mE&rw zYpWX>w&GfLM|r1~A18;q`m(p+7EPbs$aZO=Bjqd^w==YDZDg`mO$ zJf~f|E@oBT!0F1y0CO(aE*d2#@n5w|N6DkZ=*K4-8pRw4dFiLU2LyQS{`XOGs*GDX znlD$rK>DelrHHPhD3`P+i^3x%G^0j0njl5x!oVQY6P@zBUkV zFwCheYbc*lLVPJ{ESol~lD(wQ2TKPr^<|Bi%vvyIBM{^G;mIOd;kRlZ6v}f#K&ZW^_~Z zQmFczxeb-6Ig9hVRFHuwoV&3QGSBYzj2bBkN5EVOp-f>cESL4Jtnm*(B@CVf5N1p@A+kOX0zBH+8vYR zP7$<66~Fx5eIVHk?<8U0~fi;}NW;f4qZZ0&1?wXlJB{wHif!y|GOIs|nzCJ)58J&gA zuWlqYsV^(9Zd}O5KyztY8u0_al?)`Z3ABi@FM1$dU0dEzNrvV-^a9gdKcjMXWeE^f zVy@{2^N8njSR%TbUD-IJu3`?$7RI@Q_O?xq&~{uThs4t*?z-vI=fKR&?ULJySTZ;T#s(LA$6F8lSFPihf$6Lr#nd zfmtGZQ^CC8kFoxJr+r^4Pv_5T#bxq^GJbV{<}@#A0rb9MIw{GsZn54m{2JSit25*W zc$@?`LSH5pHH#bBy`|coa{1d}x|fHBl?zCBwEe^7(VDAL4$26p8K|qBSBdq7u5w_m z$l+jZksmNEi&<_dtb<4P=5NPX1bYnCqB}`5%4#cSRhBeV;#Z#MRkFL9g)65!)T(0? zDeinWQ@f>7{#9Pwk!ibwzy@r;wGZ3KZM5&^%gNe(H_BO|bo|t;gF=mE)&H5UcG(%37 za`Uu)Gvv$*Wr%0P+&PUULOIz0AS@?@bVZ=7q9U-O(GLRB`Zl*mrV{Y5+BVxx7}~eM zZsXUVr)p2lkgt>zVQ`iVlp^pe<5R2Ul%%T>EN^xMC@g8L!0b1WpuN6XitNg^U~((T zZ788(GWt!xvRTztwIz*p=DuIT6pWcLq7H(#TAR9DRhc zQr93B)i8ST-PAvpq=#q8>HHn-{aNyZGA>AvVP6qB4jiedn~Qb01jYg?f}gw6ct1H( z>su=qTj)qr+fXV0+>ze-pa~PUfx;q?;tF;n60^!KS;%UV1;^*&?Tlx&C+e_13a7$%K0n9&EkU7=mb67?53Y^m&i>(79pc{&%x?f&bFAoT% z_dSHHkdewAr|qeiqhn)GwW6%Cj6K~SEN-ZqEtt-_Yv0w&?c`s`9Q2WMW&EUp?g*k%sr2a9 zt#4np4pUZMH+yznE&B`>fF>IMmmqm6lc$UXe_)v4mWXot`5;5lpgi|OtNveC*BTpD z6@<_3pi-q&XqKhzE~$1)K`OK$mezKm;ERGSl!pk)vg~f@((T^m-rYWYK&u87tgos= zV>IF;K4bKUV$fJ)^oKuuMq^YopfPAP5j94liTcescem9)O}p9NduHaFnQ!KvGq*RH z&KDKZr?L~76e4{7ql9Q(Bh>txazyj}h#o!a*&}PRAdYj6LS#3*I7*sdI)ocP_G>pR zFH-~sB`x(Mf_l`pql4-utQx73*H_Rr+}TGpp@${l3+I&*K}fHRq=2R;L3N!l>K-A% zrPcRiX}vi(HUi-2L_E3}W|g^4Fe&04pIc1ldqa&J@25pRnO0lCeFSJy&%*>CHBecJ zRfMgLmJJ>%8U7@H*iSn=W5UhK%1>jdI);dYbmLZ0q`q#2N2=n8+jx9{DvCdWE;|!W zE|pdD!+dgp7I|J_{~+Gdi8iw!dYE4uqy=6a#{YhhqBDmkEg9y;DJb5thz=DO*i~3f zUGU%ywBbUT;39yN%A^pU-d-!VGST>T+#0{jt=oC%2C5BM7ecv^G@Aq{EHP`eUkW;v zY*+kTF;$(v5FfT?t=?p8lMY34kU4Jhf)t`?dvaYhEt@O5xwYE?F2k-zN!)FMzr~Zg zV5QIC58T@2Ew502CtVWMBa}>@4~Q$M%7svJ3x(?k{)Z;b@dkjX4cTZm8FNFPjCOZL z<2}=eJ9!E+(~EF#rf~+dva2 zO%EcC4GY*H7@H?*J&{bh!r)VOqN`a5ZBr8$1*z2QU&3$PL@PaE_UtA9rPC0Y>_ne> z3g1o)pghk;x}wPxE-PD-^Q1x`CL84cgJLc9udddDQxxWO^4Bv_ZNzzOFU?6Xp;xP;QQVu%91m5|1*u3ZIfsZ;z&GX(;22Ea5mu#8b8f|!*`L6dU!M8el{ zZakX;7zlQJi2R-te0qo)SJnUwk;o(*L<}@+B|EfxqaZ&f=TMTln zLUPPJO&pft0Fi92m7aup0k^jt95LN;GtI-`{o$MG!!nuG3T(x?bLk$(EVQ=rqA&{I z-M3KH;;lfwZuPj-`7o}b`JV212&C0JP*XG>&0yV*n!S$4Z=u>s89LxPuaZfsg*HfU zE~Rj6i|;vu+KO6$_nmOqua1CHOz}?Hic9hEjowlo+)pzI^PhP9Tna6C5<+F{L#(;YPTHe3<7QW+EWE%&eapx8Q)p_b+}^e_+FOe+#iF5YL>sJHf5dBUqawl} zMLs-*+UYmg|3Cwk6CS1TUm?1faC(J@!!SxGd>Kih8Hfw3SNXi#5k;@y^|#XpL3zv> zPrxgc9NTodQ>s){5sRTlzM5O^ApcHz&#IMiR1so;sl{|(N%So(uumZaI8`(y9fL4_~!BmnR0Cb^JszXujCR&AasrIse$LdICq#*ZDO#^8Pd znGscHmrAMO_P8+YjF&f4aOO`is1)@w0ZgupksN4%gbP*p2vXbMcT&v-a-0oh#gH8t zWC_`~<(6GnTPZ)o>J+pbO%E#XW!y1Be!}Qdo*t&K=Lvp#glez-eSSd@lo7w4WvuTy zumiDoS_25FZ|%+-)N}&nq@u3cwSR-!rtwx5*^R5UW@6n*uDgpGuBw4G-HI!s30f<> zUK8T3q>Zv*=OB{CqiB<6Kmtua=s8?Hp6pXH*i2J7ljpGKg}*+Vs;4~*1!i(iw>n&_ z_{$m8gm=WC3=I0CfT%IcVwh!i5bFUrck#x%Y0c*2g;KsAwfr$4pd+Kx^I!NCwX0+G z7Fd@Io!5O)*aiX2QJ+8oYdco8u8pi~ZC|}AvZ`ZK`$n}EW$;*tVm>s4jZFHV`jc_6 zlc2awSPF*~C1E9FM>QY-%02w&JyagfPOKKXZ`+k$dp+3wcAq$##Qv;~ee!(L%@_uf z-$?OV${#GG`~06l0L#cS6Ts|5l2xbYDE{RVn%5!+jUnBHc8@`}K2S;+1LVX}1ouQ1p${ZmW~V_K^&NB?M_buWn%h4l z9*$}N4!$~_Mr1$6o>6M{RyXkSQ51#M>v+c~E%dD7yGN<7W+MRW+6yL;!qZ|Er6@j(mrR}H zxvHd>XFNbY!udy`dXIbd@p})@Z13+^^0iELB4>zSXr!}hjzT8})KkxNT>^HKiFBg< zNH>tG@T8hooJp2vDS!STg|;7E1XO|wpF(nXV*}bg^45#VEy)q>B>n&C_rHln3ZZwD zY!)|}byp5GqIw%5=~l#`SYk<)Og4nxjT3$W{GgZwV^*@&!n72g;g^`U1xF?{i#n=i zZedBNrN7|$hbX@IVb_a}~={AV5M1y*%_zK&pTtB!MJA5|U5_HV7(31$@v4 zJ6NNFpm-@NO;OQn!7D0yEvRrsMT*yg4ZiR5l;jEE6}|WK`{(!Y%I=&gXU?2C=ggTi z^DIxj5PD#L=$cMJVew)%*&3wB_~yaM$mNSCa}-$?<6)B-n=CF422o^F>r%=>DSX?t z93+JTi&$JfC$gZtVrD^p&Aj{>71Q#oYpP1ir!fbWcQ8xh1?!4PzmD}9uY!ioLMMeu-im@S*X-W87g9A z33j^%s+F}5E434WuPuGx5v|-7f?S3UEBUl(R*|!CTf7+LQf=)%<_a>Y_NM2xZ~1=S zF}RpBiMyscLOkA>*xdYXle@I<(e9dAmWn0Z=TB`hG&8+zhauhj^lj0v|A1j5m-1zN zc;1NX`0%U7jjx(nP&jGyjPlB9QwL|1j<|sjpEI{?M9J{tQPU?DRoBd(H-Ew6;I(-p z7S-|B=zlE>nYx%8wgc$PpP4d;kE`COi5s;BtN?#(7#+A}^;zUQ?M?VWd53*g@aPZwS*~C~TML9k68#Rh-Qb9& zuP54Pxo9RW7tN$aYCMw`>5`d*L`3_M909ja!Lbd1IjO&F`3 zfuK$5G1w#M^8*?p|3^cO{GFj{Bc)zcx`LM*>gHa)8+wV$I*12FRpzBnex>32x`*>o5NL0XUTgSt#{jYS*%a%6ZkQdDlNQ5mEXqrw{i zyL{>}RJabXQyYj1Zv|}gg%a@u6Y8zD4x+r+9Uiop>YV{)4pToTXbjq*RXj%lyL?sy zk8}jE(-&3`9|COic?_8PskK5fEEv=oFsy;X6M!64FB^zM8c36l7+h96JOoIc0Tnt3 z$R>C9wCJQZRrAh?Wv13=05!1X1fYi2M*-R7`#o)gA#SV5UXa=~w)}t1UO>w)YcHTg zux?S9UsZ`5Qc$-Sn!4=6+*l3KI0(RF0EYmCX#kW)XKDj`LmL=Rl~mCN!*_z=YfxWn zs3X(Sh$@l6Zxz+H{4av z96>s6E%S+T$MCk?DbEN`h$h`WYArKlTq2WWk?#sm2@)Zgv-%RUS!CHTsr7l9X{#4e zA100rk+fUYET`^j2+~efvlIP8Sip(%HK=1W=b;u(mprJl*1M-~6110r&>yf7lK|>xeFsQ2uPSsBkSaPV zbPSNnITiX4kjgoNh@LfYTMiTcRm4R@V|+reHLtaIVJnC%xXPiq!g`wggF;y#1mDX= z-7i6UAM!{zYcWzmTRNnj$RnXXCp6@3MILeUj47`UdBn{Vro0Wvvqd5Es3~(jGA(j; zbgSe8znXk+cxcZ7*7+hzPsRA?Vob6Um!ehPijcZ-x~h>U|;gv~9%#NDDzAQ}YYz z0F$r;nrrX|z$7k#78<-BFbPZ`OM}+{CLsx^O8_PtFez97gJD5kZiE1aSxeUT3@h{L zJ)J;O@8l?wI{qV!R6$362!O?>V?GE#^buO%IfoYY3?`G;6PX=BO8vmHL5KWXdp8&5 z*JAUcA(UM)xgIiB?p$FRgwPiu=fq_O!_dSZPx^CM@TU>Q5+pz1LUzEGE2zsxe69dR zWW9XLAMq!k0;DZK-TTQ6fz|{>0$Kt%gsFgdTg$wmv{_7q-Vk0UfIw)dK$4~Q*hKHK zM^kjEcIL_zV0#2#6Le6Q%&e#sWhN}F=4 z$)&Q&%dKfatGegYd?!pM5#%7^GlW`eAQZdBTqKYY3X>NQJ2Px0vEpGf83-Xs>c#wA z=&AkliQ2{+o9Ylm5YDja0ec!I-~3OT#6Un;Oaqo`gILodGXzUO)VAu_I!Tu40WWPx zBYh}Ar;-Ik&^&?ytB3cpH0;vGe`+=DPc!xXBDR%qkWAcxZ`ZJ! zq;BM%ZK8sz?`9>d65!aS`NQG*qW{OZ`Y|vO#KOIj_+U!K%}}Elsk9fjlhJhe?BxAf z@Rdp=Zd+`p!MC5#jAWyC^4k<*JhJZl31bdY$l&HxRqy`|% zSB4K*IIpvTQSQzZ)=6eePk5wgHcG;H_6STt)Wi0Q?`lI+TX4J0EC~-9pIhbE<9$%(;q}iicr`RE|2->Xg zym_BC>nJs*8>^7C{`h{>QfE2^^ts(cHqaA7px2NEFP5QYSAfmqB2-u}u@u^+p3`9* zG^!y&9Xp8Qbh*ORS-~S@jw87u?N`?T)YWT*^bMj)NWCc)yNZ*T=LG*NPw(Tr0H zgAB(K-JPaLZ3xpHh$5R4i=o7-mWJ%91p?1qL5u;8ii<*V0m6cs42r;9-gv}^)&4;d zT1KIBKlb8&t4R74^jSe0mM79R@YX`=3bW7AiZ~63R#8|_V5O}rWvYBYRTmZ%wLu^l zLThX&YJ=-4gUN^^Fp2J_2ckU8Md4fG6d3?a;^tm)iyzU_gxf-M65b2p#M;WGh#C0; zJ`VT-p0K5G_$&zSA^;okg{Trju2&jOhqUIG{Y>iMbE^U>ZH25#>*TJ1_+Y5+tZ;1! zrq-H62j_`l$%F4z%Y9t+f@0z6gVqqqF&raR{T?YwT~wq5FFbeJFB}r!ml2DId@OXB zjSx(yDp<5M_(N4kG=LCwnLkDxjJjZMj4uYuAK2ny3B+L_h|w5KVSAJ{Fxa6p*r79+ z3SEH^e9E=$qJr4RfuRnx!B>ngl=vD-eD%c=MX?$~vFw4l5FeGH*tUQe@{TeL?`WqQ zIS)ffFsXW@u!Kcz&nLM!(|9e+VOlz8OP+e-&eI9JocjTDBuO`bb_e^Ud z1g!GJG+!R^tzOkZE%ci_vfTrg9*Wr`)AJJ;qud&1qoq&JqX1~h#QI0 zBj4?3*caq7hMWiG*3FZm!DNrmf{mt@Z9zpeFK8aq2ZYz6SK6myF;$JSSKV+_sltN( z4haDl?NSA41L{yv)!Pu4(LyV`oA*ja3=0tk;vNaZ3 z?hL-bo?jVXTzXstyt2rmzhMUjF3fi0EvfCIEvb!cr|Iz9X4;bK))8WiIW+A^ak2yj(@XVUv~xsT z{gEl+$E1Wd-CHFlK|uR?Y`P^!vk(y1*pREln4*KWOAR@Q2>~$;hTKd{?|_b0b)RkZ zmi!`OTz)3O+ks31n-dzUuEaeyWl za0wdnR=a;et%+$4Tfo|{|4H_0b+CkCH`E%YX`dM8&kaMC)&c%^k%nW>1h z9g7I<7T1v>)*R>n5R*NFU8XfmpAu3M8a;#8t2@^4v|*4q{)I0LuyK(2THGtZjDjB) z`Q;8BgmXXN+VTGXe@tYUI+5yPfdw+~7w0ipe+EM{jKxshJy19tvqjfz;?#>a@D;Eo z*|CcWb4f=rn^FsD9nE*b#q<3j6`JN7m<}O=j=MEd3*dl_S1&C|n{aapB7v9=^^)w1 zmap#G-%po>uw3N|ZcMZV6D?qyAst4p^dLUGYvkvA`LhOe%uKJH!15uQN~T2TRQ2GuXOyro;bO>4C6 zjc#5$KP-RJr#C)R`_kt$_49G{^R)WewjbrsRX?BY_e3kxwIqI#W#$)IW-gtUmHu;a z`y^~Y3Dj-gfSG^3`5^hsK#N>3F!rxCO%T`s**z$g50bM7)$yn0_XiEeXVbwF2%0u{ z^`FI>He@EobL)^&H2-zTXg)sc(>JX)TkE{YbJT4LfRWvg(RVgT7^s3f3H@# zs5DzIT}7p|DQ(pD0EMF5J}#}HV(b#6yOA(Z=SHbzn+(KHt7Y4c4WDNbzmj5c%`I!& zs!<0xadO0%sRA1&?;7*5)>x794CsFH>Oh&ZC1X-fKbj6ituQ%$kpf9}pR*sC0Z9O_O;v=;R1q6j z5ie5(hYU`++k`lmjunw&r#yK=T$&Es8l$i^LLuKhA(wl$y*;6sFw`sb1aC!5D;oxy zT^Ns73-)^{K+ZtB8dIYaC@hqyVieO(%i_c74$Ug2y38Lf54t9?zb6YTw5XvI>FgCp zV2HJ-u85~4<5G`V;JGNJ%<^M7m-69zf-N@4NtIet&}zz?uJJ`-0(2K9q6T*V44VaB zAH60Hy#DE$w9z;egtYo12nD|SY4KWIN+|;k(%#?@in$W#7igID527IW;8JpoTA))3 z^^#$j6jvj~&8C}b1LUgwb+Mta-4-d;@5G--tyDI_wVIsZ2&e8sec^JC$(;h>(t9>+ zODs~LKXSvRr|;dz)F@Z<9Nc6CmQeZ5$r+AN@;pSeIXfk;W9W3mTrFs*ehf~8;)oRC zgjD-Q5NPp*_QO7$us(Mm&_P^i=M*kWg$ZMzG`=uz8b%I`5x6`@-U~unJ{KJ$;)}R| zJrlO&^;`(mK);}OAo!yDdDQbdnkx)?n7p#!fh!$!n@ns_u`D7a{D))TKjp8CJ^Zp` zA7Jxh5%qcH)rHZmv?PTjEz@yeMaQLHqRN}(Ly?2jRfS=7q4@GY3IjQz(j6}1FZkv} zfP=#tlm!IIQUg17Y>PH+flyT(F{7v=H!aHMq4JobG&?M&Hvl|KiejSFG{nv4neIbq zB?7t~Ek9lqK-D*j(*2>}igffIxF=09Rb&G(Dc)vUT4Ff5jwv3A^}MvW4euo1T|A$+ zkz=No;4?Tio#)7pOnnpLJ$G6Tt{6Q!ty$z)idknvHSpCD`#$W6jfPIWna2phn>mmCMKJ*DHlQRII|;R-Yb6D@%#IlZh!>nJrIY*F(i zPD_N}?gj$X11o7QfXE=9PNM00_HWLREG1Q}Xki7qkIQfhPH!-Jsypj683fnLQ_k5AtPE7B_`#DvO zL(n-YfQw~tP^FdwscVWm)1>>uB&^Io=sj7J$zeg_#!0+ogw>`D3xW+;eh2EAz)u$fFFgI=ZXv zi^T`bH$@`C*lH%-%PfO&o#GPtm!n-S0)_@d<0nwgF$3gqDI zVcYtemYh$JCq0xPADx}TA9!lcEjB(zUcE3;-n4Ltzy`@bFHFb$`MA0)$*(VrlY1{( zgh|`KXo~t7BX?fhO-;3wA6o2FQ(5x2i+cl2Zg2p$0k;;S+FC5aa$-hY-{{rENH z2)_Mz5MSFyZ5n5jcRzK#7okT^)fjzPyqzDAwuu1=O9Y1lOa2-5MZ`Lo5@gU?&yYGS z7jDnu(zZ3*`v|<3{Lao4-fP?UJHrJ2u55kwc_;V)TW0Zgk`Fx#HK9v`0p74`4#VLe zv&tdQ^@!1VzUfx*0oyy^=CfRP$@$M^wQ#C*1t^3}Cr7g=E(jn_`UWhOPUFMp#B~*k zA}ZUT8woq&+}#x0@z(0+=-qvi0*DZ2gAmA@w>!o}hau92(~vK~+ji{sbKYHke@`_& zhweS*>h7np(c2elsLkh#Y9ekD~48{baOnB*G zV(DWq)#1#|)dZ{~BA=Eg9qh#Kme(F0B(MJ{M*i_&8DA&+k4DScZ^R}#!EcqBE;s9S z?Cb*{Zg}g*M+Uhp$dqq>C3#!Mn@hP`J;n*EfvJhZ)`S`#Jru$3kT<pFh5T=(M*&?kTRrM0AAd~&O|$Eg-7SKj^h+bS=|^PA+a z56`L}LbUZ5E`ln=5pLse!MVfiFSIkl%VYO1|(;yjG`q$R#CK zx#ZnsD!t*|c8E6ZdAE{p+SdBLW+JT1m=CUk4SMW@0m%CI2Q95?=gI14j1va9o?}VimmO~x@h$CebuoKQ-QRB8dVD+I_ShH0xcE`+^Kz@#GUc={ zcYz-tf0?0vrnp@Vn#APdFZ#BMBze!ErH@HBVWSN*;_|Rw$LoH6^yyUxKY0~r7307KCP7F?3%VFtS=6;vAr*o?n69AKRv3LDQZ(y-_&voBZVAD7o~EpYM}botbNUn(A2*Ac&Dq zpABzD)pZh7%o+)jj*Ur2RFdS;XBP{{&dbw}C!keI>w2QGp%$gXYIm9z(|rmq>1r=Z zCpAjCe>+DNMKTQ*`HgQw`2~6C@h0->uX@t*vu>$r`El#ZPd$zY)lyo1u%ZyzqTj;rx#>|Dls`(>eL%;YxK-k@DoPqb{~64X*2@7G-R` zMY*&VS(K&c`b0m7An_%mB!mAuC2JpQD<4>y7NZ?E(S9VlCVZ3m;=>DS%DjZ5Xp z7ZPkgUWbULSI#~kE4ThFk-sMo#^*u$v~8!N2s!V!82%6y+U}qXH)Yt?P|~R;Yc&j1 z?Rz=we4_2^B`6C~+kGqtk#V>o<7GADS;|lm36Cw2vwuslt*0EVua)v?wE3=o=@QK$oUr%ZLd+jN`tUp%@?+7#rMf?qFAnPX1lQ=`TYgxq1uu7&4vAP z!G(D76MUaNA8&h`iqw9@1IQZsTReaAwkByp`FQcbdF}fSz)Jw%qUGCGP(v%x zD*Sq08OM2m4^*z@ybqTC9s4;?;@y8;1zPEY92WR7qzyt(={w}W|G{qLoK{9V1&+;t zS|V}0jp9O)(nRD5F=zBDYyipF;HoMQN}2MxjnCzuDhn)pLNe{_ECGtrVZ#uVZ~*4B z0YChvL|pOP@q>kb$(5lZ@9R<{*Yx3Cque9%1&uNS7Cu(AFrPBc&i^j3AxcvRpGegbT;OFRl%6i$MNihccv~&GW2cLQ0f%?A^YE2Z`1d>ZR^a{I_?H)X z*+*t`1w{odXBL!}D+A~8l+1Q$)fInu(Uwgqm{Cw(Sj;||?`4$#BmP40 zr^3qGc|10J5I}RM?Uh~g__C1tPFg8aU$M2aXg-g1psF_FJLdD&Lf*B?o=P609G%bW zLYge}vN)8VyH>e%0bl7{0XPM4oznDLp309X1Fz-NJzX(+tR8F({>Cc%ujMIxobu_l zcxCxzrF0?h&&MlIF66`cVTCV3+0}}F5s&2)lunCyV)#TfnuI?${)k1_D8-9_I$Bw= zh_{H(M^5kA)io6}8;@u5j@K6<_EuDY@+tT$#GiS*MSzR(H&xHa7vuPAsQ>Zz+|{b6 zc*^W)`K9GkD?Xi}b&pT}fQz#xtQS7%sZvU6c}nnGCuaiuQ}KogjLj4n6CMGuVKQS> zl0zl^?q;mqhLT@7>Uvzj<+z%$0q-Ge7q_a|@L~Ce3HKdF!ZwCxRDW_Fh_f#?!7XK> zxnov+hGJX7n}jcWiLuFVGnR8dw+tSFSy$RF;r?JL^{~%&VT6GU;C`pQG_L`Ucp}7U zKReu%F;aBevrRQ(o^v>D$4oWiMn~A+Gr=)7yVLaqBx@_M#I!{7XGzQ$8>N17A9p)` zCOOa_Udm&TbeuQiaM-)s=VlvKfCm|lGE+uux){M6pSDucuj84Hl{B&gZnrY-I-X?h zD1)2Ig6nvClDCer_QZ*OB>C#2^7S8+!69YObv!2U$J|wZxQ;jFAxe{_JSVXKALwe7 zBTUDpP19-xnV+f!_TEaxQa&yDkv8y>?2NU&PKdF!2Vgv5wCQgx4DSoz5P*ybCxmD_85I4=Ep2AoYhq^C0+-_{9aiicxks6IJ&yxHYp?%{1ZBfq z7z7PKx}KoP0RALFFK^_bN{{6{+#0ulu~y3P8$jE7rQ`-)9_$Y09BG2ShR3^O$mAF! z9MQ!6R~UJQaOsS6B$?>;0l1Xz=*x2Q_KiGBS$rdpQ^_kqOCqoH|A4$&!lje9-b~)s zKS7?dZzJp`7#bazeFUm;u`p-u#tQX=T3}zN%vsK-ai)B{oL2~Y-d2XM;EB#MP1GF& zmFgAHjQPqP$PL@_mZ|_uh= zg(~#v3(gs)F$XS8jciJ}3cn%MT6C?1#>IpZyIm^rJ|GBSDUKX zb1JQV$G@_bi8pco6_cIXiAY{*({`q{Q4SZYAl&h}4l5n%xF={o zWD*>;ix*58eFk!;J!lf%)yEHs>>z85P}U#Y2^ z(#F%bQ)IAlMwn#P^8 z)f#Sp!8EubySUR;fEszg2q)ZaQ{7d)zajq&b0lKLs_#E-9CtGJbtVZI@kExWC$7uy!^8_?7ebUG;DwB?$_V^HUG$G=UAkT%Pc5@d}{QUB=wu_@9mQ7z~p zOXMX>v;hFDP&lkmknJR3QcrAd$OIjtdN4m;)%?I&gz52;>B&YKW+$A?&Sa!jlM_xR zXN_8mHW>6=G@SN-Fr46@HLVMsQ6%2`&?${aCHg1<^+dyGH;DEjZ4liP=?0=FtF@wy z`S*@)%h)`sF(|^mAWItxeGXf0O|-wl2gYcv9s`&0pA)T zd3ctKdf$q4+Sg)p7xjFQ0QBmjUXK!h9$nPqIRem`i#qdSQ~Mt~f_~Uaz#HQkloxNC z3zWt)EY9f|Z!$Mz@fZvL01}e{+=E6Xy7!ujsrkQ9W;}zgj&QeXZa}CXv@-AC(IAf+ z7bbXv#Q^33AbDL2Zmgm7q@H>obyTe=u`$l6F_++MER}t{e;}0&LW%K1w*GLz*R|{j z$horhUX|N(RNau?h zn-5%nH(QU6fa(WS0>Dtj^++3vco1oQJj#J}yy=xK_@3K%$}rVO@tS;;$pGqolv)C= z)JI{_)0G9c@g_V@QEuZIaTi`@tiQ-un_dDJwjv?E@dRTp{Ghyd8y^;20IRn?9HmWD zT)#nnw<0~{MvK#RFX@ur&Rs%inyU)FVX95)TLcRG(_UN2mj3}DC`5##P+Qt!MtE3;9d@#KxX zOohd;QpS@v!RpR$Z}g8`+7;QHCX0j`D#bk;QLMMWJi%u#CfI$-OymR*`Ky^HErVWl z(V47w5hY>>8wjA$GCK)@@r>Bcn>$Dlj7JlOj#&l_S=qsx*gKiHkp8mO<4!kaj7)$L zg?0V~{>)MI6KvDk?>z+I9Dt#c(?yPsHxlVI9;P}u83g>ElVf!Kdp-{H+9A_Dfuc=z zgm*mB;|QJPv=2cVPr3Rzv{LV^l1c~tjz^_d#mD74vrpA9Y6yq&B)i!?9$LVgz&}=( zIAy~f2+Orr_T9l-c&6RO*uz-3+FWmYElW9f2j7U2JMZLI@s7%=J9#U* zRA!Kk1|$^2w9u!5ft08N@;sHA0_-NOIdL@Uw}H6d-ynP z^C#WI+Y3K9ly&#;8-rhLW$cuLv)s4CPql&pKrkWqY_!{O;AsrGXIrUdTdC~Zi^{%j zMJ^UQNM*nEYTWL(R&K&+Jh{I`M^W9QRM*aX(JrCE0wAZAqfvD`*Xp06`XY~UEK^>- zmuK=Pl(YC6eBnH@dvnXudtgp3Xz9888GGn`Ej<|{dqYn@HwmF50i#6y;WxqxYH23) z2XWEGO7VR>Ra$gEWA`8untLOHh&fb9qEkHv;X}GUw9^s5r6H2vi;!fY z&z2jnu+R0TKDV0tJb2}OQrIIg@`eM5_!8Uh1Y-^nKkraZZREZ9Lkgm$Bl%oq+5MLx z>YB?i!sl;bL`S6S8IcFz${7)*w0Hmkt+`5{2d=Q=t)`9-nmayv3m0aGa3;#i?GN&F?o{?X$eRSKu&dwcMfn4kr11CJAmRpKc&l*cT8xr& zRPrQBK1YcctEpOYDiu5ckn@Zs!5*4sXcaQvv_w0YIpa81%Ena=S>jDqaF&sy)>&q< z>N)QLZ@Ot+A`jY@mfg@%#-|=ftn%qv9vNw0Yi_yUlHh2oJo6Cm9qih)p?=N=htpA7 zAF)BF8yyj@7Z6$>fR$VY9sn>Iz~~a}WY+?iM?g659R4|gH3Zbf17j57t)o^CJ3Nj? zozyw7kO;d`2_{=v_%L3ef@aXA?g#2L6h~?o9C&)6M(F1rcrCpI&V#cB0oRyAb@AUvG0bn(=%}1L0SD&Fr z!n_n7SWbnTyqAp*7a1wFHnb<&_J)!rH;p1*Fs;qDwU7&?D35PcUv5n3*0q2 zW_ijH`JYa)z<^pCHYGs+)1$CM!xaBxJTXGJ4kSc4D|K~Q@8C+8$9O_$w|$Jw$Ieas z8ytzAO5tNTQrx6`{TLq*?EN7Q(n2j35G3&3e-&doyI3L)0V@y^YoQr1% zFm^A1^lTBPJrxLgD-$>Ij#+!QGe!u~YpqxemjRy`vmc|REFWcMQjh;AVC<(4m3^Cd z>xfRb;xLg=?FLJK@&d2IH}lxwD2&mT3ExAg#M&yZ2GgRBB5M@7KleAr9;9+B+N^pS zXTPsA)~*d0^7mbgWn#=KunV2N`KAuEf!!$nyAJGxA@#hW1M|@7Q#u0m%o!vyMcK^T z@pR?2%{(!F4o2DSbK65$fQ*MWXRl@7{seCtd{Zrj-P9g~{XbyZey6C}45P^M&wY$_ zvk-cI35H(Dz^ImCS{?uwgm;Lco@W>fg~@OBPdeS#eYhQ{KK zhp-ia``F=X%q@c5$U1%pV>d!VI($dX+fY^~<%=h9N>jE_88-RYCpEj$`f0l#_><-$;8~PKqO^5#gVh1dmo@FkY3Vs z?qCoB*ODq;Jq>7;3tMp1H5zC>h314RP{M8yfJn@F=vFAp``Oq6KxEaDj17#<1yyRv zG@QE!F|el8CN+aGoRzbt)aHfxS{t?GKufKST9OI@sD%isCATiYf#CZ9wg%DYAs=Ha z!8*05%{azhCjjV#CrBy>_GRo}prfgXX%aVX!H$ujUm&A9M=};iRJ{uEV8X3*I^P98 zwfJ>^jgHujpzyngH9BGgX!7$Mt)v%~{I&+G7*RzKnx#$0!7uP7+zgHML)k5xx-xd` zL&iFlqwnSgjO{|-UAlp4Cz>8c(=HvL62F0}J78tHprIK4IQ9q74;2W&Um$wBtix~M zE07Xl13oORpy>xNp5V9_(D5Z^C214fhp#}$J}#y}ymCHO(;$C2W1Cfx_86k_*+9mUFqf!lm(ZK>P)mC|BclY_l;awPoDIo3@X0W&lR6MJehADdfc%em zGkfW90}nDj<}vO&O&OEFgUZt*-aHeg?rUHpemv%9>`~>~r{I#l_7((e9Jh=BS8Bi& zN(*;GJHhm@soc_WJ7d=)KWsF&WN+5ey^$8yX!VDo{%b8DDlcMOI>KyLs{aFS&A8Lg2rY#CX45_Ze6 z4Y0?cbQpe8^&tq(RvLILkZHP*Q2~BI5TZU3f?Uk2VeB7335bg&utKl?6Tm2R_WIK} zKmHE!hO1$c{vL*sa{%f9tcSVy4b{?C<3C(@ji|`z2WOCqH=~$B{`o)Zz{H!eEdQhd zOdJdbeM2p&1J)HPGZ8FOd)N%EBtp`Nkb*86A!@z&GREGgMpHdpJhp_fk)HuT-(vV( zSW;j&(#B)SPI#WNTQDhURseTxWek^pS=tHc_=OHIFJOp@x=S0zVxhr=ASnL$3NBO; z1|sM#tOl=tt^*sh;FKG~KL(lHMMI+DXKiEbZ{VqlZs-=qR)3EY;?ie(uyy)btHy-p zF!;g);Jc;Z8OEN(*izo$mNUB~B)_!yWhGm3v%iR#BPxSQh z1K`~tjFt+b6viGUNj11wzLN_{`=L7@yc4F-A6UZKqT{06t9D~65w}`M4vU}%2B7m$9 zA)9ssV@2S7pE!&$2xD|J0Rwme(capDk8T*KlF5a1yqxNkQvz#6ae8OUx~d{c;kU-Fe{JJs7cNLJ4EvW1gc& zAq=&ev1d-9bQE>J3d|S2Ldx>oUdBq#FxI*^Y(LV%*BPtP~ctbh5i^nx> z2}vFf?mW~J{>jH`8r9yVDN-q#ya4K_Bt669qJ}}bTg-qq2(!?Im~%TUo-*(m-lB6k z{FnGb8`ro}RZAE0kTVh%Wc%}sEg@hnfF~EhH3#K*VUCMxHRXwCc=uqt&e({@B7X~S z>)O``l1{)J(dpU(fRr<}1J2ubwgdb1C$(Rg{c#fvi|4c-gvB$Sv}w+OU2JcFFa{LS zco%Fk9*StZLNLsq`ZWEU02yKSFB+qXwYLQo#)FPhZOvL4AV}+%=Z-YN*`32-*iW`- zs6kBt*#r~4sY9AM!gT7?{2N8Cdom5(&T^)o79!k)r`ZlgBa5Y@e;4Xc-lmXHZ1&fOdjKM+D4AH;%Dag`=KEg??g zT!ruEIoz+b-HrbsXqNKeZd{L=rM!x-h$(kKL}5dR?1V{pVjW}K6uyTi#8+>FWe||> zPz~EvRtWs*S-69$wA;f|o8IyRHm<|DWy@|X$WVqRaSiFdNH2n`QJ^f`!=Ibd;Q`tg zB6b`=51YWvXDx^b2mp+dp(tTOds4W&Z(;0%Pf@uix2#%&DFJDeel=IiAByzV3$=Vo ze>sh@MarFfc>(t-zwYIuvR_+|*gdEn)QnsFVT_#sb%UzlZ#{@}CQ2_rUw?;H*0gM( zQo9eTb7QxL2^dloZI3a@?hqSKa@~On%Ol~dbcYJl^^ZCLV2%&%)Bw*xg6Bv7mH5z& z-5|P0sr|Jvu9cAHbCgD}-up4^xF`%a!s%FJQjU!GxihL43OiCE0I1s~B=>5I5u?0! zSKib$3pTx$fEheFoK7a{2q@1)!~jDJvO@$KV><^x8=GSQhH5-RtUN_K1M)?q!lF<$ z{L>L>(;1Ljxjy=nM}>bJ{Rv+FQVlqZCB8)OjADz+k-p5;rOU<_>rmH-FYcqXIlc%o z)$n5YFBssFIIRntIs7$bacjpcH>KfGSY|6<9KgBGJxchCJPlW6b6@1i zJVF`$B2N##0i`>d1O(@twolp_BOv5q_J5e*|Hk<1SasX)`VO*p4qamThz;5Yg8<{X zGQ%H5hToeE1b<-k3GE-){CrfoywUGUMjxG!(H{#Mdm{axj6PL0j6TxF-N^S};<>@S zw<7QkJsfMX)nM?(GZycpzi8qyU4&T#T{Ir;B8)c`O_pOFq3SD4#dI(ol4DecicW&Y zdT(!!-7M7(Y2qa-urm%C3>#q|4#0Ra+Tf;;`P5Xs7-T+_)F+F1DN=t(#h3WUS5R%{ ztBhk~Vzir#uwd%*AFnb}4ZTzE?N~)mP@i$}YX1z&*Z2(QANTK$Hm$N~0d@e@fH<@t zn~iL&(xdY1KgS=@+3X^m^O-rBn;snGy-o|<7BJ90xTguoghjgIxUhE9N#zIRa zJ@Xj*@`#f23XkC{l>x7CsrfB3$}Nm_uXW!xP-72$cE2f z;t9Bz=}OJ3yhZ4jM;NPE%MnlUVF#~lew7al_J0>h@b-@-2J6VL7!N5 zfr2{tDXrcC@EEsPvDAx{UdqLrARP}-IszCIp2ZYWixSSUy4DXuxUb|oC;(N<yr&3T;tZHR2WbI5PN(fv!5qd($yxL=OVre%hz*xxZtGX5jMNc%IU4C`08Tvun# z@Tr&U8Z}zgs1fAzcUn0Xfmq|=Yj}&OTjAx6BkI@iNXH6u=~}E)uEj$T9nc2nv_}s& znxg)fyoLR+X_*dL%0umaTT%_ZnwxIu*iCI*pIhzchBe>_338A9z+_X#M!17dnlhZ@ zIBpgy(lH*FY$=$bO=kWXL|YbV^OukLn_7qYQ_j7H>&q|FoWyB!LTK^gTN74p+Soi7O-bqR&xtnv|LK&(D|K(+qI|DM;I5L6?d6UP z)9mtBxz#?xH2wT7On15|BLr&ZZfnliAK|{v4F5d^&fX+b4nNGDjhpzta5Be3kYeNE z@8JzDZNFLlIQGnkm1%GCzX_-IE6InrKREUUP1|FNu)FNq0n+~)UT#82L%bDwL%JW6 z1rwKoC2~4+KgMF`V&y~Fhf~S32u!qml(E~WM8=LZ?n%a$QOREHJ#w$nP!|F<6V|$6 ztyD+92zJB|lN5IqP6?P04NAp1t>G*xuO8xEf(te<_L>vtY76kI@32b;Q66!vB`oR` zZ2eIH@#=%rVKA#mfg_NC`WJ!Z^um3DiHe-;lUm5yU_0dq`h>9dk<=t5P-X|;Xk8l zE!7%DvICX)#5hZH=_~3#a=QQ=cJ^4@5+x(IT=Z(LVKe77=xz z?0;;qhP}h1COrjXu^#9>qXq1pgC%#7tOE}JvE6})#AR6SC6?nIZpL@D^b)&!A|2A0)j@W7UjKi? z>d8#$eT>JBgABInrcEP#CN6`>`Ar$g^sdl4llCRkyFy79Yu|IN8*q^JZBZtF$fJYR z-C?>hbVBPL2%r)`60YTJMi3~ zb)$K-c-`j5c1B&C+^BEcOi*%;@W`N;ggAPx|PEJIWZcC)u0AA{jQ&3V+Ig_ zw}ZUmF!2hyZH%JW-55o%B;`tQ zG!mQAi^Q$$B6vn1-4x+?!UX>}5e|d@Mu_7B;Ps(T3USyIL5=bJi3mqWYJY_h zjv#aY`LOmg%@G46#vsCx4jN04{tpq3TB@o?IMySrM>y1xY2&XCYwM$Rord&pMb*Un zdA7Gr4_I#ir1edaHXa{c2`8;TN`({;yaKHU>Bf_cYjA1y9%hVmC){iXeRL;Ww}Txa zC+9SpqFv1)LS8Itszxt`*N_1K8ts~cbWfzc*WlL$$XXhYcZDO#MkdpE$ZTF@{u;}z zZbrue8_Z}>wWE~;Txv&QHt$5o%cnrNH?mzTg zPYL5n*H3szklB~?X~;~x8Na!bfL)jIq_!8_u3J!JA2GJ05a|lT`hA3e!GhDZ0VQVu zkPJmdz{zyrH?GA_z) z&QuP6%F~l~yrj2^;C9+l8PB9hYNf<~#)t6H%GA$zQ(?y=%FUngjL;tn;5a4Yz-+KH z>hl8Sh0l18U~n=FRSNR@h-uzifu|>csi9U^5b1G9U-O{T={lSbJ`nJM)9KAdljQ)4 zKX2tqLV5$zMOWkW*9%}L0iVIAKA#VtjeuXc(|Z=c2?Dk{y>YZR@*(|sylYl)2s|_Z zh2(h`1IPxDzszZy4e#1`^0B$;VS*>a<9^r-U$VK$$L8jW9B#?z1HVo7*8^k;nIlYF z{Gt=#j(H|mEA&nLSd03&PmWNQ9pkC`8O@Z5jjogx^cCY9u9Trc{f)8#KGTh|$vU9k zD4Pf1cW#s^(~k2o`0a{4$N9rXhswc!A-d{R{`oI{74mlAps14=`Og{XOn*wg5}fWg zW+)54;#qv7^5|E*8QzjP^c8Osu^HPh<0%;=jC5>P&VR)-g_mwuGQZ|sgL0WsiuHdz z{+F5yXmHLCAfJ1pz5x&yKw#$~JATb`8@lWWsAMwtxE=;D4#152AvX^J%RB;hai8l} zl&mLU43DAEjyoOS0jW}Wl1D`hG!am;MTl|V zrK~u~vxN^W%CjeVhfvSw=p`OOuHxqrJHP!K9@T8blQ37WA-hU78J`NU7Q1)iSp0qD zJqE*?5HR z)#@=yr&ByDRzu`Oo42ThF7)78qbxjyW4&d{##4N{@XC`)=xLt82khu@n%f1wLFsXp zxAg363Y+%2)8RyChm`qe`R)9~4)3>ovA}QKvHCln&GB;6zVCSp9#l?#&l5ZSgx`LG zxwGC3n`}I`Rk%J61gsghA$k2>t&z?^+N#BL#AV|U3Q&6fz!Ui#Wg@u}YFFvkW*EW_0#oVgNlD;x%C zAV_gK6f`@dqgaV_9PGD2+>z&SBL_y_hP#tSE927EyAR;x80;jRADMA(&<5NScx+P# z(}07l#6YU@Vht5dR*Tq9qXfe6ulsQ+hw;mHclsWTPUr7nRhTt`Y!5meg&_N=-W_qx zk)aPkEy>OZYTZ#$o>7GEKHdf)hvP=zsRSMx9Wi~qfm1En zMl^oSdf@BuO!m&6a|DEo(RN&^FK0)ar2CIQ+lQuytQ|pcR((Zq*&@NKre|zTc0JlrD6uCEeEGMja@%OhL8SCvbV1N&rCn z?zG{9{1Nw~k7}5$xJ2$=09BZaCRW_~c00yv?X72o3hr+G5=IFbQtQ2PJ^CSl>OFB2 zJX!ExEwN{5*U;6HxzllF+-PHc0heg?HtNWS;?u(7p#a8@!Oa14t_`cVGi`stqHrAi zribD<0wZXI3L81O2thZ_x$%;mBglEwtu@o|ELqUdiajyPqyI)-RYCc*;%cg>nKQ|^v~gqT$BC*diwpD1i|5sJ zon2kJptw8hGnuh#OJ`QjNNwA85xWUh3TNQ=42xJDgi$NV>9B|`>W6}o;=<`{i4!i7 z`b&E=N~>$wQ_5@o#ki*Q+ZG_Es_O(5Zx>&?N!?izaMx7i&nYhKI=f?cHcoL45c8tx zH#e#)XO!0D7t~X+T`3L1l6N?DEpWilSmxfGuljbv`jDe@eyd@}h#O`K)bgrd0G4NAccD&w--9 z%P<-;3TxPh7+GaO5q?3irg&NvP7>)HYFbsr+qZjh$RuxoMmX=S;ubw@HIhCaT zV*h?Qi@LKzK%#T8{UUaAmI1W^>pn%h+2zzSzoM#Zv+5em7G1K@^7QH3vmgFEFkiEM|#_1u6UE#ZqN;n%Fju zejcQH_RRb#^J|K$F@}6~B3PVKHAHOX+XaL(LBZ6D8Aa>>#Hg|WOv*2qQc+dIaP33! zw-ZN4l!N0#3+7KL9$j8qURuNM?4WEd5_c&_hl)-33gx$T}d-5xY&fahNy>H`9&}6VrrK zsfug37)ZLge%9NyTg2M72h)pdbViL(1`QXJ`AbUaaB+AP{ggvhjXE8wM9~SBa;8#D z;V&vDhl{DgcWssMJaMA$W{hxf@q9KO5?EbR#OSvtNb2)v7St4$uvF#dJaKG`FJOi= z;&O8qG5UX8G^jl^;ZFF28q^LmnxKS@5EF||k0Nwc?2|t5cq%HU&#q*2`9l?alJLm` z4aOFgLc|N^>!Y{}^`}%97gQCNM9FrFwNy)(Jkl+8@$Ix z;3xk};aaQ^yD5jN@y6T}(V|nSSR(dPwmQV5w9r-tg>7>{KK*)9QANHg%Bsj$vu_3} z?~D{vMEo3r(luF3Rz7MXy0}a6UnPziB(*`O71iKod0~EaO+giu5ktspYhdjF75pBN z83+~oxt>$)F-5EEp>|Ni9?Jf!#5fV}m}oYqbd8u69y7&211!&hG{tv=7#q&~CZgLc z!d;Bvqr~^|8sON@W|-nKpe8?ur-89aCIL zt{7Cds+iF`yQ&dX2Mpiyma$@TB>De^1yF$UxuxYr>}W1}-#<`{Ol3ax7&ewxHMR{&NM=RQ)adC@LLX6&ig;r6h@bSJxF z>eOo3mf3CFbZ152-OS>d?EG-$^+_Urk%ZWiWMLB^$RE1Jj=~4Sl)P)iY+j-)xkilf zB!UB~ura(SP5P9cOcz&RkBY0RV4dkswYo$W7pcp`UggVc#BQPYb%)ec6_nOgGn|s_ zxG7h>i7Wdii>*VxfT)yU=?XQmvBbm7R81vS zc)?BLQpE6!Wjp3)id%U68(_b-2n?vVU1Z^gDO-xfQ{i-(4h@Uvsp^3{;j~T+Zqv3+ zmajv02PntKxMNUQQ9h>_%Lv`dzQgiLM%$_a52!8f;cL(3?-tgLnQ^} zMKg-?tBR|OtL7B5s(Oja=>QdK5lu=u7kjJ~Q^lXffgs@t7YzQb%F*k{qRkUiluEnU zGK@~0>b04@s-%>N(UJ7aSH_%c{>})ce~CCTGHMX+4i;mlPCpq@Jd5GV99Wi2N^cD( zJ4o-pt0QN)fUGTe?o!y&^MF=&7m}30rDEt+ZFeN&n&L4E|^w~H;OlviYsF2=i+A9OzoIY{!2x9jk>I} zSY=3==ua98t6c9CP&Cq5f!WJtOxfC7i1E(DoEMV=kx#>BxysfuG1h%M_&;*&kP67$ zL}keJqK_69`;MQ>#L-;%qOCGwhBz^74XDW@?_eN)NtrEHo|_?#3DS=l7nhS)m9LUj zRWO&)Pg+i`sG3_)RRmkBi$0^vTlx7_)AB3uGtVv1p(X}UKx+}JLX7gvOfd|<3i9eq@k!z5 z4)x}HN+k1x1w|FJvC!tjUO-`nD=`&fx$s#>C2y2?Kp8$wY}evleWFy0Fc8WB0WM-w zkeE@hU_L8LQJFg%KS#J)d9+f@45N!5kVk!H4=SHlimf`Xf$D3cfg}1R1Q<3Ri$ry4 zVKvLHUr=*8VC_7NiP!7}UcsaVQ&N`C6639P&%0&e=1#DF> zu)3;ZrpkO=Wcz5A*i3w}B~xzcF18Wz3k2HwzAs7i@QMGgt80yo;=00j_qZe`U~pZp zG4`4TyLJdR_L>;%2EXF8sT*oj14=4F*URqOJMrv;o%J(>;1uyFQS1WA3H)e{qEkW;shTQnrG}KIYNfV7qe@X#HT}-Lv$oYgwq?!Sx%WK2^PMyIp5eg^ z#RE}DF&fhvL*yCE#??juhM6U(*vuS4Zk31dLQMPgx-Ct$f##+r_;egfi=+~XR8n1r z|BI^869^F0!B?|XzONM00Y1Sl^)=FdC+A~u9OOVG(js*e^088C4oDu(pxwIa=8s0` zXtgEKE<9FJ0U@%|F#^(EVy1Y_B;@&EML%Yf7={M}^+Jo-vlW`G2iTlniLEmCnz?U` z>WkMy&kL3wf`cp6PkFwXO8L?l6?op}cgCn6RAAjWm6rYja@61;p71D!4kNO~)$ibE z<1|_@13~r0oMAhw{sk@(2-0RkYY)CvNEL*lFyC#bNq%#JHhFI}@NXt4T)1P&{Gh`h zJ<6S@=$!DQ2lLw0uOH!mJWspoq>YN0lB607fHS>A^k5+NIG&8Z<;iO~d5~($AFG3X zVP#nhN`FjL79N$nO*Qo>K3hPQ8~zPc=tSpsE3!u;iku9N8nBm)6Xi>;sHWzXvcX!A zPcZcB-0=bx(;Lv&fi`bhnR*v+sgZI>7?f1*#i-TaV94`r)YkCC|5=6}LyB~%B0{31OZ@WH{IAuAm+iG`9qYMNG>6!UvrcbN86NUtbU zCy;1MB6Cz7&lh()327+~XBPbvR$5~I!XpC_rs`w1F_yhLkiWOs5R z3~FH}^GDDj$F?AeT?i})Y5M=FkNa`)L+uFfvO0y<@j0(9Ap4_ zXf8XKLj?lV59_Ggys=HmK2u5O)dYl@a#T$duRcLvgy+n=W4`rmn({oy9Y-+PN`B@D zRW?@d#H^%f;?m9p?$v}zmkBaS2e$Bn+0R$MLr<1JgYmL) z9m`uVo7e$J4p0d5{7W}io}~4upThWhGf^eS8Qm}mK@V7C;O+?}rweT`0WqeDSO&%- z9cPoNWGE@@MLMk-gEywzV5FTIMd3{AC~qPC4I=-=9xA?8Mb~|DQqv9c3&8wYH&4Gz zE&e_+G_%YJkU!z;Zfyv?ytuBF{6#;9x+VXWzDDwR^)p=_xUphkFdW3=K&!W;<;sG* zF{YAZTp$64JxEJM2xRYY^S;`E{A^QKAn|Z=T;X68zt>7WLKjW`4-nat=GR`K+GnqA z%uxp^HT?4dV-2q3wqy1CQ)9rtSDthAZORZzj_B!h*BF{Edn(z&s)c88>TRx=qHRxo zvY5?;H06=b2%2gRSQ%iVl(m$NDr6eO%9Kw=F?!S*QFkB?O^%}0AbjZ&o|&SW$+dX5FUHMDuV6KJ)H9|9M{Fn>$y@em2rl)paM1*izDKg*-FoNE+4vE+C zCz!Z{&${H`YB!XmD~nJRK+91xSp1IOuFf5yot-`1U7@btJw3ZofBR^fVm_q6W;Obj zQ7Z}}@YluSPUkiyy)U(Gz(`v$)Dk;KtsnZqe z6R|8MP2iK+ICoY8vdY7hUnsktb0Juuwu*aRr4o7{0MXg%^{xCb#Eh&z5=RwJmzVbP zrPnBbwUVs^Kuqn!>i0H(_9_*7f2AjMRxWv{Tu$vR(aK_R1K;-Gdky#k&$yqe9;^)n z8==Fa9Aqjkl-_KjlTaLHtMJ;FH$OlrkB6@_RekGdJ&Y7uy@Dw18Xl@B^3jE*bv$Vl zEum~_ZT)39oiJuc$#!eQdj^M*im7SHL}&Y777Ya%;v0*J*FnHy1^YROR+!eH}@vy!_5)#zTB<_Z8dV7X=ykX zDpbR>XQ|BlvCSRlsFMGFmVBPAoOh1CzPY4*M?2y(%4Yv^ALRg8G z!m8*q*d%tAK7ioFR5`_WIGpBttFWr@X0cHekh2gV$ACpH!zdVdIwd43WWY7!&}$tT zsdUXI$yM*+*bchS;O`^qh8lP>v2Sr>_Wl3LcnXd==FO>79_uyw!F4tMXo+1j*rF$P z5UZTwD+~wZGO$wsdtS44_1Jqm*kTk?KE}mT=`*tcm4p+?NBHH diff --git a/wasm_for_tests/tx_proposal_code.wasm b/wasm_for_tests/tx_proposal_code.wasm index 47f531479d56c1d3bb155054de3a96a4222e7dac..f21646697ffc0f8d4eb2d09bb05471ea86d12b30 100755 GIT binary patch delta 33212 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 delta 32769 zcmchA2Vhji*8j}CTeF*Fchd`D(*sE$p@be-iiBRIx3Hx5kc3_q1r!Aoyux5Xu%m(? z=)-~vR#YrJMNv@@EGR12v7rCoxpz0YQT!h7eee6<_uR~xa^}pLbIzPOckb}Rul5Ij zv9BBIGc3i!W->NYUh4C4-%OKFeULIx0)Nd~4kabjl_I%ZQad-qTU%G-Eo_=!IIp3i zse}c|v+HG9G*%4m6T%)?(CV0luG zTlUC#QWO42c~Uk0tWtK#WxjXL9ANDj>&BRydn}cn<9gUp>G@0#M^}2z>S1@K=O;a! zTIu<%8Ma$(o@@_y$Vq%qa5%8v-&~}1wHvUnxo`CKxV{4VdPWbUub1^O`g*+?wp(<4 zg#rBq47wRLhPAS}DhkonT0e|B$Ut8k^cB$8W<89)?ojfLv18u&6WXJC7-&!EVPHM2 zhk^B+9tPGQl>3b7+H6S&zfi`=5y~IN6yHjHHBi4+52Kq6dKleo*2C!LZas`{?r(LbLtm%$70}l?J&eB2>tXbD;dAALDQ3(A`fLngj~)ivC-gAT zKC6d;_7y!0v~MUw&9T1UPq(J_Dt#?ry-p7U>qb2cthec5V7;>$wsRe0>|o5{KXvsk z;68fBe59{{zCPE(=<6FjjJ|$U+?E5%Da&w)4OMcj>3b$yLnY@S)XHEi4{~Vq7-*ae zY$g1#a@_VEe&4h&=SP)^!7t%AF(ePalR`d}S;3jvq(0(l@N8lMYTqlkZXDmNF!Jp2Waax1{Fe zNfx){W*(`@bN*-L!?5_M=Tr$x`VyxVfW7afauZw6Z;e!y6@x1#N}S%7=vB!&xciM9yeUAkAq4smJIuz__m*tiCX=QbXG=5&$-C?|xBrE2QZ49#K&}LBT4q~!LyYw@@GhFq%yRx4}bQ&()WTD zZC)C3yMe#0RE_*H%5BVMED4sX$rC*%$>3ol4L&zBD)poKqW4{+!uc)A^P{qYt%Q^% zndrx&{5~quVvX}i9@%YG;zy6=R;6xqDz_*b)ZZsY4>TuPXl=0UF^_4Ksq4k#sttVK zp3f&4IHZS{Mkt30gOooCgX63W(+9>eo1OLl_?tVAZ9V+cy+dsVWbTQXGLiF}l-X1J zna+^}S(T2J?UWN!t)cIH573DDwO4vJeR4p#uChj1QfN_XrUjYaq^fr1Kv8#oLb+mk zq;hE5#MJ$iNhUnL5`%ykIT^!J0vX{MQnY6e6$h(rHla-&-==&sy$`2!q%vs6WWGk( zGNX4K*oxkmBQ=q$V&|yLlc3d*`Ay1CGiIwp3sV*sI-3V+Qywg|G(%y{sh~Z76k;`h z>+5D(pHsf^MkL|TnHD8XMt*5yT7 zrB)F15WLh{M<_Rxy7m~#Msm|9KcYh$I!sfRmOlnO-io$Cb~IIaO<LnLgOdfDnBvCbo+r5>eMbqM8R%h{*C@3$ckpwH zvo?<(R0?Y6VZ!#;=Ctv5Nv6niP$ekPO!Ayig6o#^FO~ImJu{n0b5uejk3qmex{SWy zSUDhJev#*%@4r`ms#^%IHq@s}e}Dy*Q{52EN3Yzk4VLVoT@%beBU!n&a)okJ{dkzY zv-Oe9W++|hJlh!o0hS!~u`rbA3=N@rwv&6N%ytEgV5!zjNoY(0v7W}>e7mx=vA5|* zOqHrN?UgSYZPJQwmGd*|Rj~P3QT-^Q=XB9#m@Pq-Hsw=jcUJ|K|o|@bIb-3Fg%Xgbp$TNhYGl;C3ia&B=AN%9N4$ z$DGdbXlDU)4TFO@T7|2vWNIa$!pONEw6eFLLLFtx+@g?3zXX{$i*%=;NeTCvS9 zC2QO`|Hyc4u_$*N`}1znG_27lJ|?N3gw#>2o~Hph!kG=k`@k)eC$upsD9PeByG?F$ zWs+1i%+L?KvQ#DlrauPyqikLf4U-nEl_^gxXkTt|2UjHpdlt`5vQ{O+zPs_q0wlId zj9s3Mnid#+3f1erszga`LAfDrI~bN|mHR;y4OK}n{qB$^T98?i z)ooKoFN`)2Dy4d1C#(cp77jC^pDL^t=N88FWy8TfwF|j*7nN!ka+R(N8C_W2vfDOS z!!El+l!8TVB{p2CSd*y zLmTXMP(?YkINIiiWrEKxj;{2>V2~b#;UXxEt*aO>QU&bOV==X=qRd{B7X}t5NkddJ zEme>O2}68*$yH#1XX!>BtsGsN7iXv8x(!KYTHX7(&6o*0Ew~o9UCH)EwFv-j=$OH6 zCv(FvQm{7)*t{^$nAPRJof$6Tm)Y$aL0H_b%YwPx4rz0{Dzm_?r+veNZ7QftS(ZuS ze)Y2FEl#Q&>UJuNmUoIY6X%)|ot}40Dx;GIqtL0`dPRTkRE}Q}hu>eX=#1ZvSEh59 zGV#jpj;PCmCCTSDpa*Cn2-$MwTY98DLjQ^_RXM%9jSgd?GGK*E#Tu*BujnuYf{byh zdR^s_hF} zxu2=#0CK4|Mxo8^g4&S~xgcjz%Knv=PM4z%)--OzkD07qu+rsDWx-~*v7Nk$V|fc36l`%@++m7k)s5V) zY+lvDZm0S)jc%;(cIBN_k1Ff0$#kHOYUrWv5PE}8dGnghveCno`fF3nVVDfUam%&& z@gZb(AT`EzQtu?z-@Ph{_cxBk^oMv3DL-7>Ha$eORqfjy+@*F_h*DwBfpq;PjA!US$;SDqAa52B5UzA}y_azov*-=LZ&*oXt48c-*o>QJ)AD^%sex85fQN4`|sM8Gpp!~dkbjTh0 ztXq|dH%y%IF0%X%kmSjz^!!s_1%A!TdKeqhXY?>O$B*k__&B@u@cn!2$`J0`j@=+8 zg;sl;hhjsXY#Im$MBy6^qG3^hMT2Nq6c^DT10V`tXpj*QMFKPktC@#(@ET+WM9~Kg zvH&`KT6ycn#DuT(bb-!K^za8t*oGn=v1i_f6y7re{ttvW_TD4|bi(F_F z0TECN68i{GWbj)WjzZ4yjY+M>8`@?IXP zx=EoP1BoxRnLMIk=CObx)g6NEgQuuLXbu;LOcC5qDbPLPq9s1S0*CU}O$$R#!|n4+ zi~%m}w3~Ah-a=M8iNQ64D2G>ij!_i}b58If<^G#H@fVa2ZXTj!+>)|q#4WdTOZXr- zUNP=)<;Pop3VRann_-)i<7STxt?;}|`{@wRQT(A$0^027 zl_?DK6RaG$Z8=wz$y@eG*Z-{e?ua%0aUPW&O5N5-{4zVP1JY+dD4}4)`&6KzKlFoAwKbMMro47% zob=!i)R%PVd-c!lKPX!OZB#Q&>#2=V9pVaQ?p@`yk3Vr&8{TIHV$2@;!3;xIIBglE zexBd1c!t4rL9~}?Wn|MhbY3m-@ScppPAfg{iHkgss%Q*98hbK6tf3(oW$cFg=kbpe zaqrXwTD-_(fgfrz_&f~jrU|G$e0Cg`t36@cKIcmHJ%hBE5&6=H8ST4gK`Xf5y%S^u zb1QT1e}#O<{trx}KU*It<*z8_?SuH~JtMa7JP&r(QhOFWxCjxR zJwNQcVHST#ta9;@G39kNB^?{Q3pzHG)Yo;a_11Wcz1cP1idylVi%;PF#n3RmJh5|w zgBZb1&vvk3`1_TCu?YMBnrrqRI)06&2Lg7DuM5gWk^6Zau|6u>oj zgOG^70eBPOaDw;V9Kp>zB7m;b90!w-j~5ecp!i25e>&JO*TH0Dl{7Xn$KETWcpc|6 z#kbMC7r#|>h~ZU1%_Hd`5|8kX;@ub?rHxzs7{kZ%6Jkg#A8QR?;9$`}bWYqA%aeI; zaWIxo<;O%y9KV{k*}FZCua?B91nv^K2|PM;{rB9~p}1t$oU+1-+S0o4YKQ|`>uyPeXV-;%>cml5y4Hk!dB#p1Mx8sj!9JX^wPHeBp6L6M5brm28qMR2i-IMOnJ^k%nUra&s#5ruQ7={m9G_j z6L~HlC}t<}@ZiZC8C!WAWQ?1HlE z68$_V16*8%bTdI)|9yf2T#QIM4+Z%P2e&`LSp5%bfqAOvkPeZ3 zQEW`-b!nb|s)Ed$Id1-nY$)5ZKL$2jlXA;qk(t3$Gk<$ets4@UoIur~uy~!`P|KL) zFf$fr6^k->`{-LC_`Lid*Pp;sGCv+<@i@C>=!YJN=z4?J$Sn#yzyE^F^J73(S#_!e7jwVfE7 z33D;9hqaCAx7+|S#s+Liun*Je(17Xv7&EWb;Tzb~8et0S(bA+~T)b(bj^ZJsBkgzT zhB)-_j^r}(JiI*^)s-r%xPrELJH zg5w3446=EdHIm)DPT#yvO0b`9*Fs|E(~$(2AJG}1+&ZJ%vQ;nJt+0z?1T!WHs&W7yua?>2+G}_rpHQPJKjj zsm12i&2xuopstqcG6oLeR&zvt3!;IsJlOP;j+kLcmp?oIT zGRTu^-`7X&Un?HeBMcdVs;JP3h%)QNXJ8D!nD{_C0uM2pTD2l`D7XF{nOgtD{)WzF z&2$FvgRF~^$;=r#(sOqio#x3pP7QyITW#^Eu@x9c$lPxFSer7f|Kab4THfx`(nrc9 zZe{i%I!PG*SqzFTkLa@0PFh)*CymK}wlL1(zVI2)>Chyr=^LGx4DFe2c|3=;@IPgC za9h^eAPtWAFB>GkJ$eK5kUet#mW%$+0fI4dkukDh@>D})BSYi{L`KL-Mrbqu7$7GZ zpk+wI__)aU>_S>KJT5XkC)8RIepdczI9>lb9G_0U|9u0y*yosiRtr$=bYPwiQjMW5vnQ)XEJm&}#+k3nY{^J}z+kj=(bY)r z0?WqC(K=Zgd5tl_Y|~|=SWPbT?|xC}MaWX7nmU++ySCs>*~r7qr*s(^3!r$1bv7iU z4Nn(2MLc{KwQ{Bc{|TaaRF+Nc94lzb8M(cUI*uj)o!Y3=90JgvjruDf0Dal0ubBY; zz8_UkP04x*9vx%qq#M`BXsab$XKcvsG3Kg=yvzscq2uE03w6aq(R?w=0?*JXF8dF< zm1L;T$edT9!B%Qq0UQKC!a51UdV+jCaCa_k%~z$ifT{V}s#BcIhv1X%`amrX2_wi|e}Z zxR7q!VD=CW=&};q=_|zEERw0y00r{=Clh%scmfvNpu)v!>=}2ZIem)0F2qp zV;tw8VmScRwZ*(#x0@PsJ5O?6kBkBokIpfgY&n5B1)Lvgj_lY1r#cNT^S#+E86IB` ztI>2pSEbJ>BP}h>PpZ+NI%OukEgS7|U5Y6)-LF&G(ft!Ne-?BONaLxRKkL_wi#xQI zt-65@NaxYa`3iF8(@4ie+9ln3Iy&0OOjHVaFf>nKnOwm+jMaw>@2tM4J(=TH}+UH&c{PXWO>0%)|%OhOQN z#{2{E1rmh7qY1+wx+P`IULJ4$UPnXvi^gF4NnOU+SeRAV{Ppl}a>5z&b?KPsECo;i zV1x%^hxANJr|?kK>6uS}&goHmzf_-xIX45}I-uy1<8q!wdYjgd`6SYKH2#mM_jk6R zN{6<1SpP<6=HE1oYLgKocpJ0cZ64v}@y&iSRq?yc;!t;-c=&m@INP1Kx98r>SQ(s< zE-Ou2MQRUz2Vx}$d+_Y$6?Jjh% z6VAYscOk+-&Q}iAHS_*7$QA`hP6tb?>WERQ^$V!J%p)zs#6!J#J3e2$k3Yk%ynyTh z+%V!+OqD}4&@B-)!rbQGid@Z|o3Z)a>X z;*EJ%b0+1&21aaogt0nePBxFQFK6tG0qOQAEkhVGqAsqb^xDl-Djx2``$(?}@m(KY z#52Xje4bhU=Qx#1=SSuF<5H8LL4g29J<`nqj8y?wqBat|7~ z^fe;X@^rDRKTnt5+$!$tk4RTGb{iI~r@40;+PH3jt<3;1s)Li+dZ46$N*+SVZ77); zD0w6qiwc!IZiqD>0T6g{UpGWpUesrNg4M8fl{XAAx+>@+SFO{xO8^OS-T~f|x(srg zO=ongZpKH!B6l#42saPcRm(kKh_!s(Mch4r_b-)GbqKdwtd^ASx{TW`F56Os-8V&{ zI|60^*acvGIX17u0URX2$$PqP18{n)M$YTg|HxMueGmvgm2^J+et zO8>vC<|6enyeeA{t&qi(!8~VjtH|6=%f%vdPTlZwcU!_P^4dyQBYT-C6qZF6rv`KQ zX2Mp$<9bO~V!&Y&>-^fX3HFFdA$T1koj^)X!aALSjkSEt$mRV{!P*k=2=)Na?iC{o z_*Hnvccg$9_+CKd+7M#k@|-OQZU4wv`)g$`fBhiv9tN-p%|juS1@8c8hi{si9%8Hq z0pkF?@(;!qVO3~vMVsk@vCCfqKnQwwV=VNa0M4OW!L^KC_k+Kr$5zHZ_zl2W6PLen zDU8h^i0aL`g|Sb55)b0dP{a37H#xpx0kWS;=Z9g$0x7HyF}nke-bQw9Cky+dq4aN zsRGNUG@t6n(_ct9!@~^Z*%M#q42xV3+$jXSP!u4wv=>`1VK& zV?U#;&nZ*2ZjGTGm?AzOh8K2Yg=096H159<-Ka@lQx%fnai3F$8Q{r&HOXWDj9N|r zztl1e|4!n;5n|&y5dRItGwpqJD_w^y!>MPrtehTzqy<*|d<<;z6?ef6M%8XpfChnV zWbNF6kO<{ZY_fl9UH+uIoX zg#apfqy(+u?50wikJBOc1W<`{f!2mfeDX>-;?zhj`WWUzhPSO}*;JUxoX7jMNB zAr4L~{xgY!r zE#-z^9>D5>^nmf)aOgU%&Pdc>n+bUZgDLG^#MnuUm+CyV9<p0F94%7`p&Hq)O$R zKn127m6()|Su+d;n@jD{z zDv)L;fqJbEV{?cD_%2J1>aPI<05Hi)+IJY;6DcECkX05#1;a4f@DCt_w>83-0e%(e1RFB~D{1&RbSC!TmGXCpm`#DfSp(f0@e_b; z06v8|ScYmT*K;l%A}T(IhJE)Va(19NvNI+D>m&g_Ic*JO|GWla83KpusVVhvpciAu zUj;xt%!7&%At^*v5=w{=wOUyPW77yI4aQQtjIkpp0HAOA{hJ`1kg1f(ScEt4M^uIY zBY={fjD7tFR5;}{G&$L)rj+1_17JSIpz6C(U zJ$MWBmc~cJ|M4Nlx`U-Ewx|aY0RP@!t>j6@6dEh4F{wQay-&K61nlESu@+!(ZC~St z#(gj<5SWbjxZ!XVOb?}zFJq>u4yA9q1`$-uG1bW(z}Rd|7xJ0(Gn7p3Gz%(@J~Nin zG`$Gt1;fsm2jCwd`m0~H5_Pr*!uxQekB^Y&}GR9+_)gJXENR#+<9Cs(HV>m(}SDQ@{geM$RhHZakkA{>KHZ z=3@hrKXwUY-(L`0#`8A55U@Pv3vACiW6Fx}Wb8*wv*SHGmv4nc{)ky}T#3bV!F-FTjAxg%PT6s}1Wq!B`)IfVSgO5ONJc(4l7_lFn>yh=qZ_4?e?X*_;_( zf!na;69DZ9gA+@L^o9uy5}_ZXe_<@?11_ISL0IQ&q^Cjwdp8rkcR3XAEV5^D9!^Y^ zKEm>+DSbOA@NDtg1cYI36rW81gI1kF7-T*-oB%tPo`G*XA8ecfWQP07uwjEVM2tgN z3YNCdS127v+Y*G*Ep>QBA)cJbW5(|K z32OwnRoaiS=fFy&QA^P1Rf-;50ELA(Oio8WllBEjl2fl_?C{%AsA_V=W}{U86`j8Q zw#b;o+xPkg>rqURiEDiF!D6d9@Db%62e9l@@p=GHEr#jBV6ul`HPfnzwUc-s-&x2? zP7Dfm^3JyJ27p%t%$2RSlK^G{NbZJL@Qqz)O0*~WvQTrW4u+|;nwP_F2A-5MYm)gX zeGLkDYzFHB4+0*Rbp(T8_3_7J&3Cj$6J;(16@dpGC7Zs=4uBx-veEYUbZ|~jEKZg^ znJqP_2_VyxI=sol(=0FhsZ;ycUfBy>Pst;!ruW;mph+HUwY;W-+x-fs+j*=#M2$E! z)@o}&>vc%CUnjS*->FA6HVcYE@0@7Uojf5#Jsv~nm*|y~&qC*80+0U$1Ogwwp?=`W z-o>*m)6iGo$=-ms1D3l61z=3rZoK1d)n*SOzkg}NnuQ`8LcwIuc91bohOO~o*~z(F zlb&qIlk5@4r|?|q%pT#I%Il=>pAgHZ@)Y`eAO50yHsXR8e z&u$nH3Hi7-19Cjn2sP+4o3W3-7h%(QQkwGzc#5OAq0>HSG;}0Bx+Ogb>HK)L?$l{~ zqmSP~J4(jfN$8_yAY)HJvqne&0wp6*!lbU~$xynMvFRYl-H#i_UylR4{`BfREq?^^ z%NA+*lZkL8I41eXbUrR;qk!9t!3<5~hLa(% zc%Xe~1N=JB=%n;Qpn1lOA*)_WnCLNs=llBi0b>6%yg0&q7=|?P3^(yMwsEL%G#vgD zBFqjtGjbjPc;`kfHFgvo0eC^ge-e7?PX}~zsQscy+n}z{Y)Ye7=XCI-8~_5omWdq# z1Oa}RTOAira}^Z=fFS;b+XR+JCu%~Nez0Nx;=nkTsE{l<9$YQaw$nvc07bz>_4 zppDHEilGLc;YQw8dr?$R6_$jkp`}$wQ)ua;k)^Fv_^%^NzKfs4VQSd&QGaI?wmgdT zMa~gjG<10$bpxSGN7SD}ml%^8xpcjb0cJ#_7~?VNLuZu7WfrzYDRt3-e&8y_vDTROK>mFfD^(PCigon67w%OtpjJ zoutW@SZE>i+#HnGQZ=I!jtJ>rkJ5>ti@hFYP736^v9p*Mgim8~TToo|{kKVfmT_Wa zq;{0i=Wq2to@JyuejmU&25Vn;>N7e>Xmf=f} zGErN`qi~G>sxqDx9S8rr-%6mG9gLqF@gwIgWbA(Nav9GIq3&weVTH3je?4v*lH4RKQ~-n4--V`Z4yZFddP$r__aLDe1$H<_ytbS)#)?b>gl;wjaIj61UdYhR+e2LHt_IuJkv25KHDUs zejN|9?9-R7$C_e$Xc)X{ZE#j|!N@>U)c>4kns3o9sX@zmh?%|^hs&>3v(u5Ap1L-+ zQ$};94i571VDnFfEl7iIhjaI_F2g#B8!cN!bR};SL-RP}95>8`gHKa815=lCFQ!h6 ztVC?QfMzXPn-0PV!HUCndi z-vocGyxV;*$4*J}W4Y1f(&Huq?i^dwB~(h%}hF-19E%b0A2OPax*-6ND=of)=S@CwX!w z$f1&_v1M2>T|+$!sF^gD_O_~P{uvC$U8od&ImgCXf``cDZXMxi{8J>>@}9ndTk!tI zib&K#gY5|z?1QM_T4V@y+y~$UfEe}d<3T{@sc4BI+t#)>f)&uf82Y}9>II${^+laI z->+?y?OJSbS;}-vW#o&dU`z8?UOrTbe8Cje`ZF(N{Pi<0*7_r~B{)v^pM8Xu0n!5> zp@jxWXWae2{RnMW9S`Td#PfB0j%ofFEdOIgzj|Ko>)*M#6DDorDdwZPwLF|YGN{0W z1fDQ_WH3z!hiKmzm{Yn1YG7&!%U!w*2c2%63coe*IPpnKlvaUQ46hbPt|xTDJ_Kn8 zj*#0HpmsR{IP2+p1XY(&E&r)h^TWC&LVAP;Tkh3m$n7MoktI^N=_OqTUtzVk(%FZ@Os&-Iv20T-1^vuwKcMR~=m8)z zwOSIMiZhq~&5{7p@cdV8P&N*$J=TB-*}dzaF7OKCHbb|6n}u!phXC$D%&ifcDZfv% zKsnn`{0Amt-Rl~_cR7$5fKeF^YCZaOUbBRCLErF2+y zntt^7KxTKBKwZ3_Q9qDL(z$yH>IX8c6%(n)zhk0bomIPaDO|MWV@x@q4M-Dhw6`uG zU>gr}ZU!(DKvplS^IKS;`AByhY_)xg^g5)I$`Jfa*Nrvl<2EMW8XX(kjB}aJ>Df3g z+{;?KM7yupWy0{*1}l})8Vv&>)VLCpG4SRL3%%>@j;4nG$!gOfUKMZTkiqb$|8+< z%5Y`^uwZ|b{GQb`_i~+dQD~w<2mkLv6B~fZjc(M?#7OiRc>ayhM0aZce;Jy%0;)5b zc!AKw6wp|X^#2f=SVmR-p@~gM`$H4K3vfnaB_w+n^5X8`InILs4gzpPy`RvDyqk_^ zlX{<^LJGV6`|52zqDM%_vq^CS>oRlG`E0$Cv>3oDh{Sn~#0c9b5Eci*u&VCnLq{_J zKzD7qNcTh9F#|URkeLiTj%zG!Ok^qp51Gq=*;D(6-D@qPe)~BI=mPe$p3;A{pD>r> z(eWzk_*zSZ?H!P}m4GQh;m+wG{80b_S$+fQW?4QBAo;xs5N4h1{`X~>;pN-^MwX+g z{r|Nr=b)2-EEgdCKgjY-s_K{J`AE0Oa;&e_jS+EoVr%tZx-nuMItn=J0V!gduMSHd zctqS1Zu`F@V%sGX5$t zIR}8G#_=w;?-mL}50elOVdmbtMLRhUM;$xrGCGXmE@FmcQg?le#f~N1?fLF4#)?iN z?))j%NEO(L&7t~|~DlJ_Qxe}oGf-wy}>F97%uPN%d6c;vhccp|@vkfjKEg^RSM zd<4HwG%e+`a4_zjr93(3;5O~#u-d61M@l<|=IO*fFIY_tu`}i%_QJGtJPTqU_OB2QypxhkzR*%(G8@Ve|^|l9+a;Xx+BF=(N+)SMLPB zE~^5C9a3BI?iF}j@woW?3SK--fADMOAUWpZ2fw<5CF&_KI`}o(52y#f%86Njckt_} zEBSa_KM}s1-{bF3v|YiSxMwGK1-|rA-`14v{c;6=Q*wn=H}ip&eIZ%xTpYfdXG?Dt zY+S`tb6#Doy$mfYkSx<$YO=B+QoQ8^ZNU6b*-&XLGQ{{*JOi&}maf8!`4=hzr8t7O z2^X<-8UkND2|ytacDMmpk{PSK+Z@YmpH^Wd1XMPY2ix8SPynFn4v5oHU@0fyG48fK zkCIgcOyCjbEdT;f)qFY1l9d?%Q6nK;#+MG;^>r4?ZOpF^*461H$5E~B;xLD^$EG_^N!tK|to6BdP5=Eb@`%XUhU_SXu{eS~ge5TZK0pRsRW29PXsSe?#R{CtYNiX68KN5rV0K`r=*^7`#%?8SGG z_b_bDD_7!Po_EChYk4<^b_Y^_D`!)%E&kaej$Vs@HbBe$1*g*fspYm?-JClYA1@8X z#u{}OA~#B_dnM{VqvnDbJoVzAt0A#w@zZMDxub}pHHeD4_O4yS%@SWGHeAQEgEyst zv;~BKHDdv6y9EvE{MK2BA{1z8DkA%hQi|# zPN21E^k7>@w6>%poT^1>WalKt9{*jf-nV}$V`o7x_j2P$Fyw*9biLJ5gmyV-M>r-R zJxPb-4D5Pm#znsyc|@Q57a40bX-K+S0w~Z>v09d(;W9sxdZf4Mkes{$XLCgUjks6K zB&Og`!W;gY*P`ZmUCpUa;0^i(!8hJ6N{6XKEI?WvqJ_>3 z)lcDyUyxB*`SJa#K%9udER$93E9M?<4L9jL61-_cG(LnS##2Y9$` zH_kDMS~QlPH;L67K+9;V3R-BC^8;1Y@o)7bp_2W963}vP0{m&BW#WZeuonVC(~usd zdq1s2= zahn>I0DyKhpVYQDZqqOuakkpt3$}`mRvU3l+P(n-PwkE8qylc={TyR=W7KNBw^yJa z0;t~n)j){BswD@3fzEBKCC^vlj5WrnmaIB}bE;zaCY;F7R2v^juv7b7_@;MJxwj#okq_XluC6Qc;@`rth#OBy z8T@|nO!PZAme! zgIH<>x!snqU4u|iUQ$%WA|YwojdIl$xXo^XsQy@rPVdwOOl&G?=si`%+soYr2R6yk zX{sxnTT;|}PWOC<%RofVJ<`Ysx@e-YzPh5R(A!MMY!UK_6j`c{7b6Q4+ly{t5H)M#Q$F~E9nF)qw&Dk*F5Rx^4@Q`S&7 zuaMY;!?DD0Z+(45ZCPRCoLTHS;_l#r+$H&JHIVq3*>wpUmlc3IfrE4d%$!2l215U|+WRM&tN#(r8# z;%h|5(^8i7N_XK5mn+4xm!wW{j4sD$oKsUcYe7>k#DXO#B>{Pp~ERUa+gsJFBjtiOFKd=h8&i?cn?f?}Aw+<7+EwE1KB&Zq!4#c>iAhWo&3tXGWDVdi5jL1I&8HCI-s7U~Wf68bHnRiQ3$w#sS zly%Mp*>rJGab2M*%&O!!GPh_ti<{K(;lEh_n3N!{{Xw$fBi;jNr3pjnU`KsjBY0R_ zRM^<$ZGcLGavO%Bv7#FkaaT80q}YKLmSA!wG(%mWj19tjPKuU(%@K>vNxhsyya5Dg zKNd6zzDJ63vePUR5=Q>bO~`=<^=FQL9U88C`_~+frBf z7ke3rAvG?jEn+y@BeIW4G4}5uAEg!5kPDV9{`sTygp8|rgm)K=*Xxf-X)>;{6xTf< zwF}M07&SF6t!ZL+i1oR0n20_vg$B{LGxNNSHEfH>Juh{1(56sbAT)DUMN*I=_HC0~ zv9w<(EQGp2;l<3r7%)k8vH!d@miG`n|By08{?AfaJNh!(+vqnf_dyWII5slYp}AQn zs0j{Fi81ftUuv_8^*>ADv*?}Cyox5$fqHLIMbiQ{rV5Gyem6D1$g@h!fOkI`OrU-31QUlr)vs6*scIWQ;RK-CZDYWwXY1 zh5e-y$91KpjW8y2I(LF5z{1s()ZltQCVqcFO5?+b6KxDEDVK?>?vuLXGRm{RNV)h< zGx1j`GWaA0to;jf_d{a%E}5@t#o+T!Yx z!iJK@l7_h@tVgpD<#vMxy^2EvwI%ZyUeSodFG}ZSM}kd9JEd|by`*VY zU51yD;=o%{SOi`66qs|(-N9Y%;`n>gl<2|GwE-p7)r@XRD4EUZuoz(w2VgQn$pX@s z;p%|#>6yCFZ8yqo4Ugemoj81z6fHh8%C2z|#I#`!tf#7ctUs_85mtJm?kz6%uUm9y z9Iaw=x@WolepgDfd4%bF3v90`X>9bCm9S5`ixDPyRWx1Oq}o67U+QX`)a9Ig*in3C zlHCJcn9OEpfI@zO#h3lkilRbQ+sd&tvCgn1CFDpH5-Zp@oy8cl92xQwCS>fy;dPKc zys+Q<$1_qX7w=o-aDIn4XOX9eJ`3VTlZP+_Hwd#H#ES{O9+=vaTJo_pBi-Pg$LM~? z(z=Fu-iBhG(WcW)g@p}eg>`i`Yz8{>uPRH}Ag#mF@YFT4qO7*AL0vap^Z~c7e|ENq7!V|<$<+}0C3~fvGENkb=^jX{rYC|O1H$6E zIaqTGVLYHPksVbhuv*&OU7R~7Jx9J%m(0!nX;Uo(1tTEJ#cTr-)!u~*SZ-UD(R1>; zuxG@OV7Z->j#5B2{qy`Q%<)HXvAR!$W2X%Ve(6StGYme~jK+$hMs`LwR4k%q2!duj z@WGc}V6}5qV1%-VAuDf64&l7X2F^Pp* zGuA*1o(D@&#d7z)f-ZO%g^yGdt*Ps60d0$562@Lp$G(8s_BP@VdAb6w}i`?JWae9F6SgY02OJh zs;DoVS6%_{jP56G_C5-s&aAJ9iICeFDC8!*UFGQ^mq#MXNB3)AUeW|N>!AoaCYp}# zsWyQm{#Up=UaV;4Yy+v&IC1unWD)t1a;Uuw92;BGIH$S^0iel|a*lfA1tv;(ACzKc z#A3B=%8p}Fjpz^sG8Hi;N}lBiYq5`cn8s3ZC`!JYZxapC^0*Fki3rIJ?J%0H&9lR3 zHZMF&kN)rn;JnqVcNj zpl@c2H6u^k%-07CUyR%%nNAgx(Ie|g7nzb`P#Q=4S#d=fCS`^=6eqWdVHe8%?n)Io zQWQ2Pe~;}E&RDr$JG#b9FDNRKdEoiwP2Q%8BEPi?!oqFe0T;hO+!iZGPNHvVFs9@n zYD}Iqk#-Qqi#BqAs>zIkDRYWw17(LeK|UKGAMiw~U=fVqY6BdCA6qtMM0}R8$H~e3 zHZi6hT&fHAN-i-zPEL^fRIrUFc!WoR%runDWj)b-$$V_Dn+i+4ke*_8GsGw043O~9 zDeP7fsg7#_u_Te(#Mj^qFB0~6xm`CiCgif(QMGW1#)7FT;i|mSA!luat~NdnQLAsL zE5h2r8ex16zt6*jFJ2By8v@l=MOoW)FggULI-J_hlP(tnEn=Nfj#qbZ;)8g(eLh{S zq(u{G=yY$SI-i;{z6o1LYYy8TPt#AA%4_UIKmkSqK5NJ}DK%{!CW_(@)hx3$4ZS;e z&2o3|3TFsM**6}OV#AL>6#aW*KhMr|6i>C0+r-k*b6SqoQO1JBMRnEH;4Ry#xj%Uc za=eUF!(#g$sTcJ`ppzUtuDlwxBW*zeOZeUj`9bv5taE}zk{P6`mP9q6&H zk>R=@;e1a@6YsZ`2S906hi#@?9?nz64!0a7eb`C7;FgneCyxS!6p``!v|G_$b;Q)* z1Ia8KjgpSrB~Y#fcqrIIVXC)4H=G)8HSPMJYOX{73Ie+pY`SW4vm(5+p+lOBx^}FT%#v*3}l)lJ`Tmm1@$iNiMxDguK?x zLm*C_g>JA`e)ovNVvq^7I&FG;_9Ph=IT`Za2>Q^GY(LzWW;S;czh%fh<5rTWX=CmR zxu<=AKjw4;S+=&}XE3|8nWo!>2sy(Q<}^QV@gZVzdpUg|eaM8xN%i*_-8={;Or6tx zdX}4h^VwN2*;~7S(RV~T%hS74Zk8K?iF}63C&fMQOZoDhuvEKtAo8ksXBbklzloLk&f zQmO}CTG0Rxox)*k3*wmd@Wiz6OFqySSIlK}EtVQ^&{nDGA~;J<54sO5tDntq-aTwR!XQU$eE^SiO zV2~$-(Up+ughLSPg{OlY8`{`H8um^@L}drLP1qAK-F~~SNmxZ^@oJQOGkGIH_DaxI zr;+FsLp#cy`_Sj5ptOZkMWAyo)?_diK0+fK3(k$D*%(q=R1Ld|UE5Kxr>Lf$Ws5ak zh-DvxKg9^tHdJVR-b|_r_Zpfyq_!6J7@u~Co;#(U ze7jhgBfDiBB|G>y#XzF)LKU0g zs1WuTsKa)@sJwyQtcH=Miu%J+Pzb%H52zZhd+~IVBk^x)z@fTXta}wvvZdnpPI9#L z{a~@Si=0EFO3BJ{=XL_aM}P;KL~b@germMEiY_T59v7BF%Gh?Xsk1yA5!0Y9a>|Sm z9U)QhI?rO6^{X>>#`JFs=%aOX7cwm{`cV4QAd?*BMn(sewfIfh9PG5%Fjz`;SI>y= zos;PfJ8)TxWxoqyz?KX_PDU^PwQYHCak7g%wXGWl)Xzn1L+(ZB%uf-;cdbSf9rtR|^RUx47c=W3yIXNfu#5Y~#Slp6j&y#!d3Ne`eJWf!GxF-+X Twe5W}Pu^qV4~yA-SR_eW# z+WP4+v#XZ3^p=TEHCEQu>i)Ecz59H;)xBy~*GCUEOMlg`erwO5k-z@1dp?}K_gZW3 zwZD74&K~~uoaN8YTh@-wGrHs>s<5j|RQU*SRe=k-s)VQlW*X!K=9y&g9r^i2lBslg zIlLOW*0~}>%t~$3Vq0}nb7OU7`_jtR+Uhx?|GJ(*u36;<#SDN7fI#rGDySF*fXN7o z-M^m=1t16`fC7OQp5pyu3Xw;C=x_3}s1Rvh z+T5V6=}WJqLUS;!H6Fs_JLrThoEDmL{}T=0oBj^R>40C&?_XT|`DDEqmb}3i6-AZI%B7#`TE*`rp4vFm+gchYE9-1Vq7qqTw0a zZ4##C7nnhPV1~NK^(zB7?%oi13}BplasNVqH|TKCia~pRaiU3Mr|ta3X(nwO)dy!n zkNeT!;9sFKUgK_~T-nFnM$PB$?{65>_b}J9tU6?ztLO0pA{7m6WdlcG09sXp#)nh5 zlRhwK+XAF)zSF3hRg-3DP!0Bq2&-z$wi&b_?;IX7En)UKpciJJ0~)n$S5K=2Xa?5p z&+BMlXdLv=&7nUBf4cL4(9%>zyDS>C%YS9!6qSVyGw*sV8Vy;hnYu#{-ooM@;1mh8 zYHrr2#cTUGUG4paRr}TY1KZ?!R$>plR2(F1kxF!yP<8b6on26u5z#i}Z*vB9eP$rPctQ*Pth9iRGC@W-5DT0A@C6bJUv$Cx-k z7g9gOqkHMiw3}qtFTFfU28uTh*sjqWSZ20`A?r$%pQ6?23I3(*SCJs>_EI{K{w}Mh zF?oJ7kiWSuB+r6a^3UiWYL%hLIm#i!(bK?zrU~mQcT&cBkih>wHrbz%a;&nuEB0m{ zRA_2ewme^!2}8W$Dma@h4XV2BH%u>#=*zyG?nO%yNZg36ne{fr(C4%69*!Mn$Z9k}-G$<957!Fqu z85M&$*S(eb+dFwV)9%zNC%|ATt8U}=jp|Ri-81_W>9F-Ro7j{|b7mtuhw5s$y;S!T zIO)5&3Byjw;>(`UA{!VQ*R%dYSVIJF;>9Z)IWpUwR6j45(`N6yP8dfC^{I4ldZ`szpruC^+BKI+sgmfVChU#aB!aukke15E+@J)7aOkENa=lyM2A}X zb24AG%ZZlTaMk0~(-d;`Af*e_f4d_1aHsddeXX{_rdhCxrnME>eeU#`nH`W!huY#` z1)XcV1-4Q~ds6koyEq&SULe{I9@~dIUwjUSxCW z7xL5c9@oD(AyWB9D;=u6&UEh$S7+MlNcgkJ-SdZGE?ep$JKej&vn`zUcZP>kw z#w~Ws?!w|7CSQEg!lki87uF28D z!QU^wkAzp4*cvo1x4-W7QZ1cDe8U(+Ph|*#Ntc zPnmnkhL3ond&b7m5Lnz++uD{`*IHduQ{7nIL~9<%HJ%E#i!wU)Kq3@S;HGc*UZXrX z6Ssy?(uPo4{NSCe{)Y#nvXfX@V{Kbo_1sz^Rh#)W@XI$ukyqa|XIfiL^PF1Yl}WyQ zlldLRZ$K|SnkqNPz^k-kb3CNb?#*G4>OQnN4fE1?LOQ==`1Roy0(g8a|B7Pvh5XGc zGR3{Gf_224+S!ZdR@OJwH7A$4Z`pEp2z0yOeyTYx=7$`f)cg2vgCM_CeHfN9Fq*g1 zy0hW#&VSwy*ExBBJNMWiLx}N;TE8z9Iowh@NeJ41A%^Nsj)VsH#*=<{-5Njo>|W?M zAXkXE5FrYRltAkqJpR=F`h@crL9xJro*g&*`Fm`z8xf6~>72Ed2-MQt+Aa z@C?m38-3E~4_P_KJLKYqQp9EXkAR+LG#cbiUXd%Dv zH^3_QpT7?_*tW93RFGp$WWiy2@uwWyxn52QbHXX;=NwyBly6Q8bLLSUbJq59{>Yqt z^xV%mvBxE+F3+onFN(tWGzJNCCd-qUGFAB`W$WW0C$?L1c&^-G$JMztOugMZS4z&U z-@tS2PTyR)cRG)KdY3a*B_*s^O1gFaS6WW&*51hy*5Rv@b*9esPL>k8rxhRrvr>DV z(@(H%gro|2Bp)AV<^SUxWzJ64;CRF!Q3H)RB`SHjIT3eRe25 z2FrB+Fs#6#Ii7|v+z%L=>xmnH5r`qBo=Fb;38MeS-pi})5NkPy+S=!cfK(xxYL~WG zHdeRS%oFV;LJzlNvHt8p90qxwPX}T%!ck9=iZ2;pnI~*8ZUWe(?;V0UHW@XQm2+#` z>)XYc>;Cl~c)6l#2OiZ(v<*9c`60&5e!CO=64Qla6~~tzI(*Ck7cgIqRE6K3DMS z*4F9{(e2qc28V-LCf1Vr_IdjG&mm23EXHU(dn`u451y*Ac()ShU_-T3H`UiLgt_8o z{o9+cf^AYX9+zQYuKvz=TnRJvTeI*4oYco^=!7RdvoyQ}@ReRX5!2xX{l1A<5fC(k z(KRn>t*I4z^ve_ROW5xDd=dsK@DKgF9L%uEGTGi-xwy85zZAOjD{y$qaxo9#g1&t+ z4uPHe>yxn#GWFy%Pxu$s?DGqtmWXBS$S4XZ1%5Fa>YO)&E(59|i4W1LjwEc5sZ{($rMjDjxQ{R)~Ya zF6%r)YhKdC`*5AowQRUS51xUG;5B{q415V**7J*S9{fdrx`>@UPlsY03YYZwV%&zQ arTUx2I0jdG`xt$A35If5PAtJ6P5%cVGfS`l delta 6025 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 diff --git a/wasm_for_tests/tx_write_storage_key.wasm b/wasm_for_tests/tx_write_storage_key.wasm index 44a87a74972b6bb06592b0a648b5cc5c73ae41bb..3af37f6a6349292f734d9ada7fc3500d72820fc1 100755 GIT binary patch delta 14532 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 delta 14546 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 W{utTucV5}f@W*#w*>3*6{{H|*MSBSV diff --git a/wasm_for_tests/vp_always_false.wasm b/wasm_for_tests/vp_always_false.wasm index 29b9edcabd3d6e9c4b6bc638978fa76a5e300b73..873ca4bb3684894837cccb796d5d495f7708c1d2 100755 GIT binary patch delta 1590 zcmaJ=eQZ=k5Z~Fi@7-PBT{(neOAG8>=?DF8fh#==b%E03t`zP74W(#Bs&avr>jw}7 z9?-NvNTkh%1Vh0}i9q}aaUqC712l#}h>3p~H4rseq68u#{9$5(I2 z{`NOB`|XhH(U7YrSY|ac3kO(@x~**kEZEsdNTV_Ausx0u%Qm&0y&E!@CMUU_loAbq z5*N!ObX|;Dh(;g<9(i@#5A5Wa< z5rmUm>h)^^YSLv!$}7|g%k3!^D)l&})xbTQG7=2cZN3?(Rjca#U)m?7W$iZLdwC@P zej2q9ST7{R4v$lC0A<(6xQ&sbFuz{y(YVev z&g=@I!cysOhG7qwoceS(eX`W{j2wgkaD%#D*=4{ixoklz%u<63ikQ=d#TL zpn27pNn2uYL#=F?Mq!@nNMr+o^|hWslqGHJ0fO>;doj+xw#Oi-f*lXAd&4S!OY^Wk zvh_M0yNKHG_C0+4A+>5pH^m)4TibERnq7kov3*@nu-A1x!5-{dj@Zw4FVUe&HXX=w zRdFAmz`1vxI((p$!H~@8S?!}1J}*6&GQUG?PxuX+7kUhC;A0VxNLPn?dMI?NY_B3{1_Uo*!NdpU@!=n*=n!W&oYaHe51m~m_eBwMu@g-C0whY*vk(%fr6~9c}F`8~?pJU&THzrxgVl#$=Hq6dTAMfbw7e7)UY3N>EBW NuUtHTB0`pc(xHH!p2kZ9IzZ3D0e#+tRR5+ z-J3OO#kWBJegfok|@2UIlcL1+0^y5BnmOAG>!ReIMzTHB5km^P&JRZUSv|F+% z+-GVQ)Wp&BzsOkw_V^Q|ls3N2Adjt?aY5>5xs{4mtD4PE?R~OyyAAjr2Mg{`kb00Y z6Rh+tR(gjiEY=_rlIeJ?a2dRde-;)Nxa>oiY1o6)67gy=SJEWiy4Fj{U8h01GAwRs z(uGaICUD`=U@kcEo80Yh29w8{!tPml_?52O`Jp z_!rE&6L2v}MW9N!J#60Hhlg(*y!!j`I=8SZQ=hEeqEa)hSPF_Mpe3uoq!z>O(ioKB zULJvKm{ZmR)A3kY9~Ck1gtcqRJ85lkG*kUnz8v5rF0Kf#@CuJX+ewIUL5&eGEEWKp zvOke9^=dDdy40kwzZWTDb&nu38O9db@X;2MlQ+$HKvy>^dJTx++Nw5)sFA9W!0w{? z7^|D`Z#U#U&WO3CMwv+#ds1uM#!I!kDYcq~yZ$$|Y#i~{s90Sk;MCGAIECHiCf=-X zOlDlB9T5g@ie{_K#e%Dr=m6LLdMyXTjip%Gn2Ifp`7l!rH2&y-nHXRGEtIIaD=L80 zj+M6!2a8I##iIDi+S8mxmH(x;^c2bF$z8`ymq_604Lw4a?6@jwsnh8iyuNA9quw9J zOPiLD!pzntIHOuyvpH0%z41Jtqt3N`L}#pTZvmK%SGN?=2pvr@TP^E&04c1&%PkRb zdjLP&I#cy@hN+_))Y)xc^U;u0-y6RW8CC5&`Z#(2k=Rb&oo`+d6vyn|u{gSV$Kv>* zcPYgY?pvh8vzXX3&GoDd$fuhI^!qpI+8kwsT&_~d2gGXt9Bl6u%j-TfsomM%e=`*I9B>Y4*PAeGfhu%N!J z&C8gZAq;lnckfq^R%p_}u2FdCU^8wT{E9Nesza;n1P2ef?CkN>VVX8z%8~uH@#K-D z(Q$N@22u6$i6Wn#!x)>4`#!ni%_Za{5hQuI;r!}}`GhvEYj0n(ejRiD$2tXXozF;{ zO3XA84~gwlfSwEW6AKAdb+m73-N=$Yw#Am9+I(RaFAEVYA}J=Zw;VNx2~Q`P@t7yY T=vU0f*6+M^@#9+;0nh#eprwf6 diff --git a/wasm_for_tests/vp_always_true.wasm b/wasm_for_tests/vp_always_true.wasm index 8b3edc3de407b0a3aba8e31a4b0bf13ff573b80d..c6bbbc6b59ff397d83893ee00472752f5f0b3b21 100755 GIT binary patch delta 4674 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 kv4uD&<@gaR{W1J*Tqkk#>xW-|{3+^O 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 diff --git a/wasm_for_tests/vp_eval.wasm b/wasm_for_tests/vp_eval.wasm index caadc022a595e1243cbc052a730b98ae984d66dd..35e83a753aca583921517f2be92be1e5b9233c18 100755 GIT binary patch delta 17602 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 G`2PUu?=(OF delta 16962 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

;IE3?QxC(BM*e8Z=9 z4o_+!V2ZT@WSHer592l#*yXmB0Q12iA3gwf_}ET0Zg!3YZ&Q5kp@W0q z{q0V>49;1s4cQns_Yz+bWncSR$={(d_VJBLL?auLh*l{Q&wG(5{{F7H@F&Fw zzVNTNxDiF?8}PL0Xf@9QH|j=r2SFA-GRNN6$`8MAA__mX@;lFbuezC!=r4SeCATFN z7de8Nj;mzw>cDt|kQ>%Q|}H}0hM@b5kL*oXh%_k#M++l8X@ z-MKD`8eGX=lRu5Qs<`F5hc{kL>$b-qJNkzY2R24;^tXHE+3)U&ZoGyjpQ;Ae@uw;K fudk>58~nYie9k2Z`5W|qvh)3KcfKDM|M~v`%Hh7G diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index 81f3ff61cfc51352378107c4921e0dba424c4898..2993fa519a2a02f782159523a58054640f9ff276 100755 GIT binary patch delta 19994 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 delta 20374 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 Date: Wed, 2 Nov 2022 17:07:09 +0100 Subject: [PATCH 06/10] governance: more refactor --- shared/src/ledger/governance/mod.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index 8e1232d4cb..0ea867d7b5 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -172,18 +172,11 @@ where let current_epoch = self.ctx.get_block_epoch().ok(); - let pre_counter: Option = - self.ctx.pre().read(&counter_key)?.unwrap_or_default(); - let pre_voting_start_epoch: Option = self - .ctx - .pre() - .read(&voting_start_epoch_key)? - .unwrap_or_default(); - let pre_voting_end_epoch: Option = self - .ctx - .pre() - .read(&voting_end_epoch_key)? - .unwrap_or_default(); + let pre_counter: Option = self.ctx.pre().read(&counter_key)?; + let pre_voting_start_epoch: Option = + self.ctx.pre().read(&voting_start_epoch_key)?; + let pre_voting_end_epoch: Option = + self.ctx.pre().read(&voting_end_epoch_key)?; let voter = gov_storage::get_voter_address(key); let delegation_address = gov_storage::get_vote_delegation_address(key); From 74ce0172a392414ad00711f0c4d420070102c582 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 2 Nov 2022 16:40:40 +0000 Subject: [PATCH 07/10] [ci] wasm checksums update --- wasm/checksums.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 4aad2ec376..c4c1673141 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,18 +1,18 @@ { - "tx_bond.wasm": "tx_bond.18c82eeae00649e8399bcff497449807448ab933dde172c661069f551e3cafa9.wasm", - "tx_ibc.wasm": "tx_ibc.df63b5bb9378e086da9395098bfecf4d9917c2e3a081799ed56371217a926eed.wasm", - "tx_init_account.wasm": "tx_init_account.f1f395c9e87e86f8773bf060c0da56b560434f35ac59b088e28f38501bfa3710.wasm", - "tx_init_nft.wasm": "tx_init_nft.3c5dd0e82aa99441f8401b327f28c7651742823eaacfc5d3da767518ca1d9f6a.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.0566d8208ed8608a484dee260380766921bef0e326a01b5d1a6d4cac36a10d7f.wasm", - "tx_init_validator.wasm": "tx_init_validator.7e09a954c080a7aae74b3463761feb1e161a1d288f2e0c7f7c354b1a6a87f5aa.wasm", + "tx_bond.wasm": "tx_bond.9fb0f31c3f51443b2a68bb4a1c127e573dd456547d3f46e4bd17a5ca43159285.wasm", + "tx_ibc.wasm": "tx_ibc.7eaba1123b511b95d95787a9f38ca1e9734d0400dcd0578749113e89d452439d.wasm", + "tx_init_account.wasm": "tx_init_account.d71b97412b1140f373d20b69d249bbd6dffbdef51273abb5e1a47605d137756b.wasm", + "tx_init_nft.wasm": "tx_init_nft.472df9bd8075b84e9299822430f0d43aff923f28ec9f84bf69b2ca07f7e0f6b6.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.07202afd69464b80052180fbe6670e50c92d3a2711fdb7e381f85865936a6068.wasm", + "tx_init_validator.wasm": "tx_init_validator.ff6a63fa965bcd610a26d2d36620f1738475a5c31f1b47df9c5db7ae2215d43a.wasm", "tx_mint_nft.wasm": "tx_mint_nft.3f20f1a86da43cc475ccc127428944bd177d40fbe2d2d1588c6fadd069cbe4b2.wasm", - "tx_transfer.wasm": "tx_transfer.1d70145df64271486f56dbf53591b0134f1e2464c1f2e16dafcca12ea05b309f.wasm", + "tx_transfer.wasm": "tx_transfer.00a7efcb41c94bd7fa4639f21f1248c0a918f8673c54ea55d20cfde2b2334cb1.wasm", "tx_unbond.wasm": "tx_unbond.155d5a01f28979ebeab420e2e831358610a44499fd600e269f9044686e879f6f.wasm", "tx_update_vp.wasm": "tx_update_vp.6d291dadb43545a809ba33fe26582b7984c67c65f05e363a93dbc62e06a33484.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.206bdcfbf1e640c6f5f665122f96ea55fdd6ee00807aa45d19bfe6e79974c160.wasm", - "tx_withdraw.wasm": "tx_withdraw.510e870df424e158cab0d79effd11e2c8bebaf106ffa86e18f73e0a75585a9c8.wasm", - "vp_nft.wasm": "vp_nft.ce4de0794341532b7556605415273bc05768469ba2f49c346616ba61801b6457.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.a50e428f14e16841837ec3b40c03a7b0b7ec994d15362309882a9cbe97329ff4.wasm", + "tx_withdraw.wasm": "tx_withdraw.3b2d265d050cc07bd02eb9e48d05e6c11fec92a8c2fb3f0d3f1832f2fec06ca6.wasm", + "vp_nft.wasm": "vp_nft.fdd94d15e014900f41367f357eac0dcfe64a074fc455d3f2a52daf692c9daad4.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.0cff74823844198fa789ade3da8189bdc83e67f4c306e8b008e00b940305ca39.wasm", "vp_token.wasm": "vp_token.0d10511e4d46e83b5bbc17544e17e86e2f707dfe955fdeae41ff796a7c2feb3b.wasm", - "vp_user.wasm": "vp_user.bc174b6514393330c5756d92cd6ca6450b65f5ceb08374c7407735f68f540871.wasm" + "vp_user.wasm": "vp_user.4a1204d76987b1362dd61358d45cb2f1b518ef883b1a2321102e7eb78a6796f8.wasm" } \ No newline at end of file From 6d4bc08e077fdfbb160f76f7bdce73bbc845eb25 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 16 Nov 2022 15:40:42 +0100 Subject: [PATCH 08/10] governance: added method, fmt, clippy --- shared/src/ledger/governance/mod.rs | 15 ++------------- shared/src/ledger/governance/utils.rs | 21 ++++++++++++++++++++- shared/src/ledger/parameters/mod.rs | 21 ++++++--------------- shared/src/ledger/slash_fund/mod.rs | 20 ++++++-------------- 4 files changed, 34 insertions(+), 43 deletions(-) diff --git a/shared/src/ledger/governance/mod.rs b/shared/src/ledger/governance/mod.rs index 0ea867d7b5..88a806bc39 100644 --- a/shared/src/ledger/governance/mod.rs +++ b/shared/src/ledger/governance/mod.rs @@ -9,7 +9,6 @@ pub mod utils; use std::collections::BTreeSet; -use borsh::BorshDeserialize; use thiserror::Error; use self::storage as gov_storage; @@ -540,18 +539,8 @@ where /// Validate a governance parameter pub fn is_valid_parameter(&self, tx_data: &[u8]) -> Result { - let proposal_id = u64::try_from_slice(tx_data).ok(); - match proposal_id { - Some(id) => { - let proposal_execution_key = - gov_storage::get_proposal_execution_key(id); - Ok(self - .ctx - .has_key_pre(&proposal_execution_key) - .unwrap_or(false)) - } - _ => Ok(false), - } + utils::is_proposal_accepted(self.ctx.storage, tx_data) + .map_err(Error::NativeVpError) } /// Check if a vote is from a validator diff --git a/shared/src/ledger/governance/utils.rs b/shared/src/ledger/governance/utils.rs index b63b981020..f01aaaedf0 100644 --- a/shared/src/ledger/governance/utils.rs +++ b/shared/src/ledger/governance/utils.rs @@ -7,9 +7,9 @@ use namada_proof_of_stake::types::{Slash, Slashes}; use thiserror::Error; use crate::ledger::governance::storage as gov_storage; -use crate::ledger::pos; use crate::ledger::pos::{BondId, Bonds, ValidatorSets, ValidatorTotalDeltas}; use crate::ledger::storage::{DBIter, Storage, StorageHasher, DB}; +use crate::ledger::{pos, storage_api}; use crate::types::address::Address; use crate::types::governance::{ProposalVote, TallyResult, VotePower}; use crate::types::storage::{Epoch, Key}; @@ -377,3 +377,22 @@ pub fn is_valid_validator_voting_period( voting_start_epoch < voting_end_epoch && current_epoch * 3 <= voting_start_epoch + voting_end_epoch * 2 } + +/// Check if an accepted proposal is being executed +pub fn is_proposal_accepted( + storage: &S, + tx_data: &[u8], +) -> storage_api::Result +where + S: for<'iter> storage_api::StorageRead<'iter>, +{ + let proposal_id = u64::try_from_slice(tx_data).ok(); + match proposal_id { + Some(id) => { + let proposal_execution_key = + gov_storage::get_proposal_execution_key(id); + storage.has_key(&proposal_execution_key) + } + None => Ok(false), + } +} diff --git a/shared/src/ledger/parameters/mod.rs b/shared/src/ledger/parameters/mod.rs index cc932611a6..c19252d72a 100644 --- a/shared/src/ledger/parameters/mod.rs +++ b/shared/src/ledger/parameters/mod.rs @@ -7,12 +7,11 @@ use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; use thiserror::Error; use self::storage as parameter_storage; -use super::governance::storage as gov_storage; +use super::governance::{self}; use super::storage::types::{decode, encode}; use super::storage::{types, Storage}; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::time::DurationSecs; @@ -60,19 +59,11 @@ where let result = keys_changed.iter().all(|key| { let key_type: KeyType = key.into(); match key_type { - KeyType::PARAMETER => { - let proposal_id = u64::try_from_slice(tx_data).ok(); - match proposal_id { - Some(id) => { - let proposal_execution_key = - gov_storage::get_proposal_execution_key(id); - self.ctx - .has_key_pre(&proposal_execution_key) - .unwrap_or(false) - } - _ => false, - } - } + KeyType::PARAMETER => governance::utils::is_proposal_accepted( + self.ctx.storage, + tx_data, + ) + .unwrap_or(false), KeyType::UNKNOWN_PARAMETER => false, KeyType::UNKNOWN => true, } diff --git a/shared/src/ledger/slash_fund/mod.rs b/shared/src/ledger/slash_fund/mod.rs index c9d4f7566e..92ce21ba06 100644 --- a/shared/src/ledger/slash_fund/mod.rs +++ b/shared/src/ledger/slash_fund/mod.rs @@ -5,11 +5,10 @@ use std::collections::BTreeSet; /// SlashFund storage pub mod storage; -use borsh::BorshDeserialize; use thiserror::Error; use self::storage as slash_fund_storage; -use super::governance::storage as gov_storage; +use super::governance::{self}; use super::storage_api::StorageRead; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; @@ -67,18 +66,11 @@ where if addr.ne(&ADDRESS) { return true; } - - let proposal_id = u64::try_from_slice(tx_data).ok(); - match proposal_id { - Some(id) => { - let proposal_execution_key = - gov_storage::get_proposal_execution_key(id); - self.ctx - .has_key_pre(&proposal_execution_key) - .unwrap_or(false) - } - None => false, - } + governance::utils::is_proposal_accepted( + self.ctx.storage, + tx_data, + ) + .unwrap_or(false) } KeyType::UNKNOWN_SLASH_FUND => false, KeyType::UNKNOWN => true, From e295eebbf9f9477f60e8d44f2906554a61667ed5 Mon Sep 17 00:00:00 2001 From: Gianmarco Fraccaroli <> Date: Wed, 16 Nov 2022 15:50:01 +0100 Subject: [PATCH 09/10] pos: use method --- shared/src/ledger/pos/vp.rs | 20 ++++++-------------- shared/src/ledger/slash_fund/mod.rs | 1 - 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index 8d34d70e93..698ba4e1c9 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -27,7 +27,7 @@ use super::{ ValidatorSets, ValidatorTotalDeltas, }; use crate::impl_pos_read_only; -use crate::ledger::governance::storage as gov_storage; +use crate::ledger::governance; use crate::ledger::native_vp::{ self, Ctx, CtxPostStorageRead, CtxPreStorageRead, NativeVp, }; @@ -37,7 +37,6 @@ use crate::ledger::pos::{ }; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; use crate::ledger::storage_api::{self, StorageRead}; -use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::{Key, KeySeg}; use crate::types::token; @@ -127,18 +126,11 @@ where for key in keys_changed { if is_params_key(key) { - let proposal_id = u64::try_from_slice(tx_data).ok(); - match proposal_id { - Some(id) => { - let proposal_execution_key = - gov_storage::get_proposal_execution_key(id); - return Ok(self - .ctx - .has_key_pre(&proposal_execution_key) - .unwrap_or(false)); - } - _ => return Ok(false), - } + return governance::utils::is_proposal_accepted( + self.ctx.storage, + tx_data, + ) + .map_err(Error::NativeVpError); } else if is_validator_set_key(key) { let pre = self.ctx.pre().read_bytes(key)?.and_then(|bytes| { ValidatorSets::try_from_slice(&bytes[..]).ok() diff --git a/shared/src/ledger/slash_fund/mod.rs b/shared/src/ledger/slash_fund/mod.rs index 92ce21ba06..c3bdd8976d 100644 --- a/shared/src/ledger/slash_fund/mod.rs +++ b/shared/src/ledger/slash_fund/mod.rs @@ -12,7 +12,6 @@ use super::governance::{self}; use super::storage_api::StorageRead; use crate::ledger::native_vp::{self, Ctx, NativeVp}; use crate::ledger::storage::{self as ledger_storage, StorageHasher}; -use crate::ledger::vp_env::VpEnv; use crate::types::address::{Address, InternalAddress}; use crate::types::storage::Key; use crate::types::token; From 4b95c01973a612a2b606b5c744ca4867068895f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 16 Nov 2022 16:16:02 +0100 Subject: [PATCH 10/10] changelog: add #719 --- .../improvements/719-refactor-governance-storage-api.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/719-refactor-governance-storage-api.md diff --git a/.changelog/unreleased/improvements/719-refactor-governance-storage-api.md b/.changelog/unreleased/improvements/719-refactor-governance-storage-api.md new file mode 100644 index 0000000000..fcbbffd213 --- /dev/null +++ b/.changelog/unreleased/improvements/719-refactor-governance-storage-api.md @@ -0,0 +1,2 @@ +- Refactored governance code to use storage_api. + ([#719](https://github.com/anoma/namada/pull/719)) \ No newline at end of file