From c7118f221fba9a6a5f413995aaba704dbcbb72b8 Mon Sep 17 00:00:00 2001 From: yito88 Date: Sun, 3 Dec 2023 10:49:58 +0100 Subject: [PATCH 1/7] pgf over ibc --- apps/src/lib/client/rpc.rs | 4 +- .../lib/node/ledger/shell/finalize_block.rs | 1 + apps/src/lib/node/ledger/shell/governance.rs | 49 +++--- apps/src/lib/node/ledger/shell/mod.rs | 1 + core/src/ledger/governance/cli/onchain.rs | 20 +-- .../src/ledger/governance/storage/proposal.rs | 154 +++++++++++++++--- core/src/ledger/pgf/inflation.rs | 51 +++--- core/src/ledger/pgf/storage/keys.rs | 2 +- core/src/types/token.rs | 8 +- core/src/types/transaction/governance.rs | 18 +- tests/src/e2e/ledger_tests.rs | 17 +- 11 files changed, 221 insertions(+), 104 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index bc57f58f14..26538b8b85 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -1304,8 +1304,8 @@ pub async fn query_pgf(context: &impl Namada, _args: args::QueryPgf) { context.io(), "{:4}- {} for {}", "", - funding.detail.target, - funding.detail.amount.to_string_native() + funding.detail.target(), + funding.detail.amount().to_string_native() ); } } diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 0e46577a0d..3311077044 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -4,6 +4,7 @@ use data_encoding::HEXUPPER; use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; use masp_proofs::bls12_381; +use namada::core::ledger::inflation; use namada::core::ledger::masp_conversions::update_allowed_conversions; use namada::core::ledger::pgf::inflation as pgf_inflation; use namada::core::types::storage::KeySeg; diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 4991310d09..5883a03478 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use namada::core::ledger::governance::storage::keys as gov_storage; use namada::core::ledger::governance::storage::proposal::{ - AddRemove, PGFAction, ProposalType, StoragePgfFunding, + AddRemove, PGFAction, PGFTarget, ProposalType, StoragePgfFunding, }; use namada::core::ledger::governance::utils::{ compute_proposal_result, ProposalVotes, TallyResult, TallyType, TallyVote, @@ -341,14 +341,15 @@ where Ok(true) } -fn execute_pgf_payment_proposal( - storage: &mut S, +fn execute_pgf_payment_proposal( + storage: &mut WlStorage, token: &Address, payments: Vec, proposal_id: u64, ) -> Result where - S: StorageRead + StorageWrite, + D: DB + for<'iter> DBIter<'iter> + Sync + 'static, + H: StorageHasher + Sync + 'static, { for payment in payments { match payment { @@ -356,49 +357,55 @@ where AddRemove::Add(target) => { pgf_storage::fundings_handle().insert( storage, - target.target.clone(), + target.target().clone(), StoragePgfFunding::new(target.clone(), proposal_id), )?; tracing::info!( "Execute ContinousPgf from proposal id {}: set {} to \ {}.", proposal_id, - target.amount.to_string_native(), - target.target + target.amount().to_string_native(), + target.target() ); } AddRemove::Remove(target) => { pgf_storage::fundings_handle() - .remove(storage, &target.target)?; + .remove(storage, &target.target())?; tracing::info!( "Execute ContinousPgf from proposal id {}: set {} to \ {}.", proposal_id, - target.amount.to_string_native(), - target.target + target.amount().to_string_native(), + target.target() ); } }, PGFAction::Retro(target) => { - match token::transfer( - storage, - token, - &ADDRESS, - &target.target, - target.amount, - ) { + let result = match &target { + PGFTarget::Internal(target) => token::transfer( + storage, + token, + &ADDRESS, + &target.target, + target.amount, + ), + PGFTarget::Ibc(target) => { + ibc::transfer_over_ibc(storage, token, &ADDRESS, target) + } + }; + match result { Ok(()) => tracing::info!( "Execute RetroPgf from proposal id {}: sent {} to {}.", proposal_id, - target.amount.to_string_native(), - target.target + target.amount().to_string_native(), + target.target() ), Err(e) => tracing::warn!( "Error in RetroPgf transfer from proposal id {}, \ amount {} to {}: {}", proposal_id, - target.amount.to_string_native(), - target.target, + target.amount().to_string_native(), + target.target(), e ), } diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index e8d5da8b83..3319d0e9cd 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -8,6 +8,7 @@ pub mod block_alloc; mod finalize_block; mod governance; +mod ibc; mod init_chain; pub use init_chain::InitChainValidation; pub mod prepare_proposal; diff --git a/core/src/ledger/governance/cli/onchain.rs b/core/src/ledger/governance/cli/onchain.rs index 60e70ddf7d..bbfd25ca70 100644 --- a/core/src/ledger/governance/cli/onchain.rs +++ b/core/src/ledger/governance/cli/onchain.rs @@ -10,6 +10,7 @@ use super::validation::{ ProposalValidation, }; use crate::ledger::governance::parameters::GovernanceParameters; +use crate::ledger::governance::storage::proposal::PGFTarget; use crate::ledger::storage_api::token; use crate::types::address::Address; use crate::types::storage::Epoch; @@ -277,9 +278,9 @@ impl PgfAction { )] pub struct PgfFunding { /// Pgf continuous funding - pub continuous: Vec, + pub continuous: Vec, /// pgf retro fundings - pub retro: Vec, + pub retro: Vec, } /// Pgf continous funding @@ -288,7 +289,7 @@ pub struct PgfFunding { )] pub struct PgfContinous { /// Pgf target - pub target: PgfFundingTarget, + pub target: PGFTarget, /// Pgf action pub action: PgfAction, } @@ -299,18 +300,7 @@ pub struct PgfContinous { )] pub struct PgfRetro { /// Pgf retro target - pub target: PgfFundingTarget, -} - -/// Pgf Target -#[derive( - Debug, Clone, BorshSerialize, BorshDeserialize, Serialize, Deserialize, -)] -pub struct PgfFundingTarget { - /// Target amount - pub amount: token::Amount, - /// Target address - pub address: Address, + pub target: PGFTarget, } /// Represent an proposal vote diff --git a/core/src/ledger/governance/storage/proposal.rs b/core/src/ledger/governance/storage/proposal.rs index 13e1aecae1..9b91baac45 100644 --- a/core/src/ledger/governance/storage/proposal.rs +++ b/core/src/ledger/governance/storage/proposal.rs @@ -5,6 +5,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use serde::{Deserialize, Serialize}; use thiserror::Error; +use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; use crate::ledger::governance::cli::onchain::{ PgfAction, PgfContinous, PgfRetro, PgfSteward, StewardsUpdate, }; @@ -81,13 +82,130 @@ pub enum AddRemove { Eq, PartialOrd, )] -pub struct PGFTarget { +pub enum PGFTarget { + /// Funding target on this chain + Internal(PGFInternalTarget), + /// Funding target on another chain + Ibc(PGFIbcTarget), +} + +impl PGFTarget { + /// Returns the funding target as String + pub fn target(&self) -> String { + match self { + PGFTarget::Internal(t) => t.target.to_string(), + PGFTarget::Ibc(t) => t.target.clone(), + } + } + + /// Returns the funding amount + pub fn amount(&self) -> Amount { + match self { + PGFTarget::Internal(t) => t.amount, + PGFTarget::Ibc(t) => t.amount, + } + } +} + +/// The target of a PGF payment +#[derive( + Debug, + Clone, + PartialEq, + BorshSerialize, + BorshDeserialize, + Serialize, + Deserialize, + Ord, + Eq, + PartialOrd, +)] +pub struct PGFInternalTarget { /// The target address pub target: Address, /// The amount of token to fund the target address pub amount: Amount, } +/// The target of a PGF payment +#[derive( + Debug, Clone, PartialEq, Serialize, Deserialize, Ord, Eq, PartialOrd, +)] +pub struct PGFIbcTarget { + /// The target address on the target chain + pub target: String, + /// The amount of token to fund the target address + pub amount: Amount, + /// Port ID to fund + pub port_id: PortId, + /// Channel ID to fund + pub channel_id: ChannelId, +} + +impl BorshSerialize for PGFIbcTarget { + fn serialize( + &self, + writer: &mut W, + ) -> std::io::Result<()> { + BorshSerialize::serialize(&self.target, writer)?; + BorshSerialize::serialize(&self.amount, writer)?; + BorshSerialize::serialize(&self.port_id.to_string(), writer)?; + BorshSerialize::serialize(&self.channel_id.to_string(), writer) + } +} + +impl borsh::BorshDeserialize for PGFIbcTarget { + fn deserialize_reader( + reader: &mut R, + ) -> std::io::Result { + use std::io::{Error, ErrorKind}; + let target: String = BorshDeserialize::deserialize_reader(reader)?; + let amount: Amount = BorshDeserialize::deserialize_reader(reader)?; + let port_id: String = BorshDeserialize::deserialize_reader(reader)?; + let port_id: PortId = port_id.parse().map_err(|err| { + Error::new( + ErrorKind::InvalidData, + format!("Error decoding port ID: {}", err), + ) + })?; + let channel_id: String = BorshDeserialize::deserialize_reader(reader)?; + let channel_id: ChannelId = channel_id.parse().map_err(|err| { + Error::new( + ErrorKind::InvalidData, + format!("Error decoding channel ID: {}", err), + ) + })?; + Ok(Self { + target, + amount, + port_id, + channel_id, + }) + } +} + +impl borsh::BorshSchema for PGFIbcTarget { + fn add_definitions_recursively( + definitions: &mut BTreeMap< + borsh::schema::Declaration, + borsh::schema::Definition, + >, + ) { + let fields = borsh::schema::Fields::NamedFields(vec![ + ("target".into(), String::declaration()), + ("amount".into(), Amount::declaration()), + ("port_id".into(), String::declaration()), + ("channel_id".into(), String::declaration()), + ]); + let definition = borsh::schema::Definition::Struct { fields }; + definitions.insert(Self::declaration(), definition); + } + + fn declaration() -> borsh::schema::Declaration { + std::any::type_name::().into() + } +} + /// The actions that a PGF Steward can propose to execute #[derive( Debug, @@ -168,35 +286,22 @@ impl TryFrom for AddRemove
{ } } -impl TryFrom for PGFAction { - type Error = ProposalTypeError; - - fn try_from(value: PgfContinous) -> Result { +impl From for PGFAction { + fn from(value: PgfContinous) -> Self { match value.action { PgfAction::Add => { - Ok(PGFAction::Continuous(AddRemove::Add(PGFTarget { - target: value.target.address, - amount: value.target.amount, - }))) + PGFAction::Continuous(AddRemove::Add(value.target)) } PgfAction::Remove => { - Ok(PGFAction::Continuous(AddRemove::Remove(PGFTarget { - target: value.target.address, - amount: value.target.amount, - }))) + PGFAction::Continuous(AddRemove::Remove(value.target)) } } } } -impl TryFrom for PGFAction { - type Error = ProposalTypeError; - - fn try_from(value: PgfRetro) -> Result { - Ok(PGFAction::Retro(PGFTarget { - target: value.target.address, - amount: value.target.amount, - })) +impl From for PGFAction { + fn from(value: PgfRetro) -> Self { + PGFAction::Retro(value.target) } } @@ -319,6 +424,9 @@ pub mod testing { use proptest::{collection, option, prop_compose}; use super::*; + use crate::ledger::governance::storage::proposal::{ + PGFInternalTarget, PGFTarget, + }; use crate::types::address::testing::arb_non_internal_address; use crate::types::hash::testing::arb_hash; use crate::types::token::testing::arb_amount; @@ -341,10 +449,10 @@ pub mod testing { target in arb_non_internal_address(), amount in arb_amount(), ) -> PGFTarget { - PGFTarget { + PGFTarget::Internal(PGFInternalTarget { target, amount, - } + }) } } diff --git a/core/src/ledger/pgf/inflation.rs b/core/src/ledger/pgf/inflation.rs index 30dd4191fd..2360afe4b4 100644 --- a/core/src/ledger/pgf/inflation.rs +++ b/core/src/ledger/pgf/inflation.rs @@ -1,5 +1,6 @@ //! PGF lib code. +use crate::ledger::governance::storage::proposal::PGFTarget; use crate::ledger::parameters::storage as params_storage; use crate::ledger::storage_api::pgf::{ get_parameters, get_payments, get_stewards, @@ -46,26 +47,36 @@ where pgf_fundings.sort_by(|a, b| a.id.cmp(&b.id)); for funding in pgf_fundings { - if storage_api::token::transfer( - storage, - &staking_token, - &super::ADDRESS, - &funding.detail.target, - funding.detail.amount, - ) - .is_ok() - { - tracing::info!( - "Paying {} tokens for {} project.", - funding.detail.amount.to_string_native(), - &funding.detail.target, - ); - } else { - tracing::warn!( - "Failed to pay {} tokens for {} project.", - funding.detail.amount.to_string_native(), - &funding.detail.target, - ); + let result = match &funding.detail { + PGFTarget::Internal(target) => storage_api::token::transfer( + storage, + &staking_token, + &super::ADDRESS, + &target.target, + target.amount, + ), + PGFTarget::Ibc(target) => ibc::transfer_over_ibc( + storage, + &staking_token, + &super::ADDRESS, + target, + ), + }; + match result { + Ok(()) => { + tracing::info!( + "Paying {} tokens for {} project.", + funding.detail.amount().to_string_native(), + &funding.detail.target(), + ); + } + Err(_) => { + tracing::warn!( + "Failed to pay {} tokens for {} project.", + funding.detail.amount().to_string_native(), + &funding.detail.target(), + ); + } } } diff --git a/core/src/ledger/pgf/storage/keys.rs b/core/src/ledger/pgf/storage/keys.rs index 96768ac494..8ca22f8303 100644 --- a/core/src/ledger/pgf/storage/keys.rs +++ b/core/src/ledger/pgf/storage/keys.rs @@ -63,7 +63,7 @@ pub fn fundings_key_prefix() -> Key { } /// LazyMap handler for the pgf fundings substorage -pub fn fundings_handle() -> LazyMap { +pub fn fundings_handle() -> LazyMap { LazyMap::open(fundings_key_prefix()) } diff --git a/core/src/types/token.rs b/core/src/types/token.rs index d738086e7b..8774414526 100644 --- a/core/src/types/token.rs +++ b/core/src/types/token.rs @@ -962,9 +962,15 @@ impl MaspDenom { } } +impl From for IbcAmount { + fn from(amount: Amount) -> Self { + primitive_types::U256(amount.raw.0).into() + } +} + impl From for IbcAmount { fn from(amount: DenominatedAmount) -> Self { - primitive_types::U256(amount.canonical().amount.raw.0).into() + amount.canonical().amount.into() } } diff --git a/core/src/types/transaction/governance.rs b/core/src/types/transaction/governance.rs index 8e43b488e3..5876d8de60 100644 --- a/core/src/types/transaction/governance.rs +++ b/core/src/types/transaction/governance.rs @@ -8,7 +8,7 @@ use crate::ledger::governance::cli::onchain::{ DefaultProposal, PgfFundingProposal, PgfStewardProposal, }; use crate::ledger::governance::storage::proposal::{ - AddRemove, PGFAction, PGFTarget, ProposalType, + AddRemove, PGFAction, ProposalType, }; use crate::ledger::governance::storage::vote::StorageProposalVote; use crate::types::address::Address; @@ -124,12 +124,8 @@ impl TryFrom for InitProposalData { .continuous .iter() .cloned() - .map(|funding| { - let target = PGFTarget { - target: funding.address, - amount: funding.amount, - }; - if funding.amount.is_zero() { + .map(|target| { + if target.amount().is_zero() { PGFAction::Continuous(AddRemove::Remove(target)) } else { PGFAction::Continuous(AddRemove::Add(target)) @@ -142,13 +138,7 @@ impl TryFrom for InitProposalData { .retro .iter() .cloned() - .map(|funding| { - let target = PGFTarget { - target: funding.address, - amount: funding.amount, - }; - PGFAction::Retro(target) - }) + .map(PGFAction::Retro) .collect::>(); let extra_data = [continuous_fundings, retro_fundings].concat(); diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index ca123601a1..f6494b355d 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -27,7 +27,10 @@ use namada_apps::config::ethereum_bridge; use namada_apps::config::utils::convert_tm_addr_to_socket_addr; use namada_apps::facade::tendermint_config::net::Address as TendermintAddress; use namada_core::ledger::governance::cli::onchain::{ - PgfFunding, PgfFundingTarget, StewardsUpdate, + PgfFunding, StewardsUpdate, +}; +use namada_core::ledger::governance::storage::proposal::{ + PGFInternalTarget, PGFTarget, }; use namada_core::types::token::NATIVE_MAX_DECIMAL_PLACES; use namada_sdk::masp::fs::FsShieldedUtils; @@ -2317,14 +2320,14 @@ fn pgf_governance_proposal() -> Result<()> { let christel = find_address(&test, CHRISTEL)?; let pgf_funding = PgfFunding { - continuous: vec![PgfFundingTarget { + continuous: vec![PGFTarget::Internal(PGFInternalTarget { amount: token::Amount::from_u64(10), - address: bertha.clone(), - }], - retro: vec![PgfFundingTarget { + target: bertha.clone(), + })], + retro: vec![PGFTarget::Internal(PGFInternalTarget { amount: token::Amount::from_u64(5), - address: christel, - }], + target: christel, + })], }; let valid_proposal_json_path = From 0b137e43c03a8c9e24b0d1304aaf98b5744a5bba Mon Sep 17 00:00:00 2001 From: yito88 Date: Sun, 3 Dec 2023 10:51:51 +0100 Subject: [PATCH 2/7] add ibc --- apps/src/lib/node/ledger/shell/ibc.rs | 186 ++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 apps/src/lib/node/ledger/shell/ibc.rs diff --git a/apps/src/lib/node/ledger/shell/ibc.rs b/apps/src/lib/node/ledger/shell/ibc.rs new file mode 100644 index 0000000000..82b8426bd9 --- /dev/null +++ b/apps/src/lib/node/ledger/shell/ibc.rs @@ -0,0 +1,186 @@ +//! Implementation of `IbcActions` with the protocol storage + +use std::cell::RefCell; +use std::rc::Rc; + +use namada::core::ledger::governance::storage::proposal::PGFIbcTarget; +use namada::core::ledger::ibc::{ + IbcActions, IbcCommonContext, IbcStorageContext, +}; +use namada::core::ledger::storage_api::Error; +use namada::ibc::applications::transfer::msgs::transfer::MsgTransfer; +use namada::ibc::applications::transfer::packet::PacketData; +use namada::ibc::applications::transfer::PrefixedCoin; +use namada::ibc::core::ics04_channel::timeout::TimeoutHeight; +use namada::ibc::core::Msg; +use namada::ledger::parameters::read_epoch_duration_parameter; +use namada::ledger::storage::wl_storage::WriteLogAndStorage; +use namada::ledger::storage::write_log::WriteLog; +use namada::ledger::storage::{DBIter, Storage, StorageHasher, WlStorage, DB}; +use namada::ledger::storage_api::{self, token, ResultExt, StorageWrite}; +use namada::tendermint::Time as TmTime; +use namada::types::address::{Address, InternalAddress}; +use namada::types::hash::Hash; +use namada::types::ibc::{IbcEvent, IbcShieldedTransfer}; +use namada::types::time::DateTimeUtc; +use namada::types::token::DenominatedAmount; + +#[derive(Debug)] +pub struct IbcProtocolContext<'a, D, H> +where + D: DB + for<'iter> DBIter<'iter>, + H: StorageHasher, +{ + wl_storage: &'a mut WlStorage, +} + +impl WriteLogAndStorage for IbcProtocolContext<'_, D, H> +where + D: DB + for<'iter> DBIter<'iter>, + H: StorageHasher, +{ + type D = D; + type H = H; + + fn write_log(&self) -> &WriteLog { + self.wl_storage.write_log() + } + + fn write_log_mut(&mut self) -> &mut WriteLog { + self.wl_storage.write_log_mut() + } + + fn storage(&self) -> &Storage { + self.wl_storage.storage() + } + + fn split_borrow(&mut self) -> (&mut WriteLog, &Storage) { + self.wl_storage.split_borrow() + } + + fn write_tx_hash( + &mut self, + hash: Hash, + ) -> namada::ledger::storage::write_log::Result<()> { + self.wl_storage.write_tx_hash(hash) + } +} + +impl IbcStorageContext for IbcProtocolContext<'_, D, H> +where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, +{ + fn emit_ibc_event(&mut self, event: IbcEvent) -> Result<(), Error> { + self.wl_storage.write_log.emit_ibc_event(event); + Ok(()) + } + + /// Get IBC events + fn get_ibc_events( + &self, + event_type: impl AsRef, + ) -> Result, Error> { + Ok(self + .wl_storage + .write_log + .get_ibc_events() + .iter() + .filter(|event| event.event_type == event_type.as_ref()) + .cloned() + .collect()) + } + + /// Transfer token + fn transfer_token( + &mut self, + src: &Address, + dest: &Address, + token: &Address, + amount: DenominatedAmount, + ) -> Result<(), Error> { + token::transfer(self, token, src, dest, amount.amount) + } + + /// Handle masp tx + fn handle_masp_tx( + &mut self, + _shielded: &IbcShieldedTransfer, + ) -> Result<(), Error> { + unimplemented!("No MASP transfer in an IBC protocol transaction") + } + + /// Mint token + fn mint_token( + &mut self, + target: &Address, + token: &Address, + amount: DenominatedAmount, + ) -> Result<(), Error> { + token::credit_tokens(self.wl_storage, token, target, amount.amount)?; + let minter_key = token::minter_key(token); + self.wl_storage + .write(&minter_key, Address::Internal(InternalAddress::Ibc)) + } + + /// Burn token + fn burn_token( + &mut self, + target: &Address, + token: &Address, + amount: DenominatedAmount, + ) -> Result<(), Error> { + token::burn(self.wl_storage, token, target, amount.amount) + } + + fn log_string(&self, message: String) { + tracing::trace!(message); + } +} + +impl IbcCommonContext for IbcProtocolContext<'_, D, H> +where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, +{ +} + +pub fn transfer_over_ibc( + wl_storage: &mut WlStorage, + token: &Address, + source: &Address, + target: &PGFIbcTarget, +) -> storage_api::Result<()> +where + D: DB + for<'iter> DBIter<'iter> + 'static, + H: StorageHasher + 'static, +{ + let token = PrefixedCoin { + denom: token.to_string().parse().expect("invalid token"), + amount: target.amount.into(), + }; + let packet_data = PacketData { + token, + sender: source.to_string().into(), + receiver: target.target.clone().into(), + memo: String::default().into(), + }; + let timeout_timestamp = DateTimeUtc::now() + + read_epoch_duration_parameter(wl_storage)?.min_duration; + let timeout_timestamp = + TmTime::try_from(timeout_timestamp).into_storage_result()?; + let ibc_message = MsgTransfer { + port_id_on_a: target.port_id.clone(), + chan_id_on_a: target.channel_id.clone(), + packet_data, + timeout_height_on_b: TimeoutHeight::Never, + timeout_timestamp_on_b: timeout_timestamp.into(), + }; + let any_msg = ibc_message.to_any(); + let mut data = vec![]; + prost::Message::encode(&any_msg, &mut data).into_storage_result()?; + + let ctx = IbcProtocolContext { wl_storage }; + let mut actions = IbcActions::new(Rc::new(RefCell::new(ctx))); + actions.execute(&data).into_storage_result() +} From aa93c4d2daf33f52cabc6f7c348e428b1b2cbe14 Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 11 Dec 2023 20:26:52 +0100 Subject: [PATCH 3/7] fix for 0.28.0 --- apps/src/lib/node/ledger/shell/ibc.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/ibc.rs b/apps/src/lib/node/ledger/shell/ibc.rs index 82b8426bd9..305f2b5954 100644 --- a/apps/src/lib/node/ledger/shell/ibc.rs +++ b/apps/src/lib/node/ledger/shell/ibc.rs @@ -8,11 +8,11 @@ use namada::core::ledger::ibc::{ IbcActions, IbcCommonContext, IbcStorageContext, }; use namada::core::ledger::storage_api::Error; -use namada::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use namada::ibc::applications::transfer::packet::PacketData; -use namada::ibc::applications::transfer::PrefixedCoin; -use namada::ibc::core::ics04_channel::timeout::TimeoutHeight; -use namada::ibc::core::Msg; +use namada::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use namada::ibc::apps::transfer::types::packet::PacketData; +use namada::ibc::apps::transfer::types::PrefixedCoin; +use namada::ibc::core::channel::types::timeout::TimeoutHeight; +use namada::ibc::primitives::Msg; use namada::ledger::parameters::read_epoch_duration_parameter; use namada::ledger::storage::wl_storage::WriteLogAndStorage; use namada::ledger::storage::write_log::WriteLog; From 9fded35963a54e06ac3f9fcba751986af565acff Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 13 Dec 2023 21:16:46 +0100 Subject: [PATCH 4/7] add E2E test --- .../lib/node/ledger/shell/finalize_block.rs | 13 +- apps/src/lib/node/ledger/shell/governance.rs | 9 +- apps/src/lib/node/ledger/shell/mod.rs | 1 - core/src/ledger/pgf/inflation.rs | 17 +- .../src/ledger/storage_api}/ibc.rs | 54 ++-- core/src/ledger/storage_api/mod.rs | 1 + tests/src/e2e/ibc_tests.rs | 273 +++++++++++++++++- tests/src/e2e/ledger_tests.rs | 2 +- 8 files changed, 313 insertions(+), 57 deletions(-) rename {apps/src/lib/node/ledger/shell => core/src/ledger/storage_api}/ibc.rs (76%) diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 3311077044..c23bc617e4 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -4,7 +4,6 @@ use data_encoding::HEXUPPER; use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; use masp_proofs::bls12_381; -use namada::core::ledger::inflation; use namada::core::ledger::masp_conversions::update_allowed_conversions; use namada::core::ledger::pgf::inflation as pgf_inflation; use namada::core::types::storage::KeySeg; @@ -144,7 +143,7 @@ where // Invariant: Process slashes before inflation as they may affect // the rewards in the current epoch. self.process_slashes(); - self.apply_inflation(current_epoch)?; + self.apply_inflation(current_epoch, &mut response)?; } // Consensus set liveness check @@ -660,7 +659,11 @@ where /// account, then update the reward products of the validators. This is /// executed while finalizing the first block of a new epoch and is applied /// with respect to the previous epoch. - fn apply_inflation(&mut self, current_epoch: Epoch) -> Result<()> { + fn apply_inflation( + &mut self, + current_epoch: Epoch, + response: &mut shim::response::FinalizeBlock, + ) -> Result<()> { let last_epoch = current_epoch.prev(); // Get the number of blocks in the last epoch @@ -683,6 +686,10 @@ where // Pgf inflation pgf_inflation::apply_inflation(&mut self.wl_storage)?; + for ibc_event in self.wl_storage.write_log_mut().take_ibc_events() { + let event = Event::from(ibc_event.clone()); + response.events.push(event); + } Ok(()) } diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index 5883a03478..aea626e725 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -18,7 +18,7 @@ use namada::ledger::pos::BondId; use namada::ledger::protocol; use namada::ledger::storage::types::encode; use namada::ledger::storage::{DBIter, StorageHasher, DB}; -use namada::ledger::storage_api::{pgf, token, StorageWrite}; +use namada::ledger::storage_api::{ibc, pgf, token, StorageWrite}; use namada::proof_of_stake::bond_amount; use namada::proof_of_stake::parameters::PosParams; use namada::proof_of_stake::storage::read_total_stake; @@ -136,6 +136,13 @@ where id ); + for ibc_event in + shell.wl_storage.write_log_mut().take_ibc_events() + { + let event = Event::from(ibc_event.clone()); + response.events.push(event); + } + ProposalEvent::pgf_payments_proposal_event(id, result) .into() } diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 3319d0e9cd..e8d5da8b83 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -8,7 +8,6 @@ pub mod block_alloc; mod finalize_block; mod governance; -mod ibc; mod init_chain; pub use init_chain::InitChainValidation; pub mod prepare_proposal; diff --git a/core/src/ledger/pgf/inflation.rs b/core/src/ledger/pgf/inflation.rs index 2360afe4b4..a647829345 100644 --- a/core/src/ledger/pgf/inflation.rs +++ b/core/src/ledger/pgf/inflation.rs @@ -2,18 +2,23 @@ use crate::ledger::governance::storage::proposal::PGFTarget; use crate::ledger::parameters::storage as params_storage; +use crate::ledger::storage::{DBIter, StorageHasher, WlStorage, DB}; +use crate::ledger::storage_api::ibc::transfer_over_ibc; use crate::ledger::storage_api::pgf::{ get_parameters, get_payments, get_stewards, }; -use crate::ledger::storage_api::token::credit_tokens; -use crate::ledger::storage_api::{self, StorageRead, StorageWrite}; +use crate::ledger::storage_api::token::{credit_tokens, transfer}; +use crate::ledger::storage_api::{self, StorageRead}; use crate::types::dec::Dec; use crate::types::token; /// Apply the PGF inflation. -pub fn apply_inflation(storage: &mut S) -> storage_api::Result<()> +pub fn apply_inflation( + storage: &mut WlStorage, +) -> storage_api::Result<()> where - S: StorageRead + StorageWrite, + D: DB + for<'iter> DBIter<'iter> + Sync + 'static, + H: StorageHasher + Sync + 'static, { let pgf_parameters = get_parameters(storage)?; let staking_token = storage.get_native_token()?; @@ -48,14 +53,14 @@ where for funding in pgf_fundings { let result = match &funding.detail { - PGFTarget::Internal(target) => storage_api::token::transfer( + PGFTarget::Internal(target) => transfer( storage, &staking_token, &super::ADDRESS, &target.target, target.amount, ), - PGFTarget::Ibc(target) => ibc::transfer_over_ibc( + PGFTarget::Ibc(target) => transfer_over_ibc( storage, &staking_token, &super::ADDRESS, diff --git a/apps/src/lib/node/ledger/shell/ibc.rs b/core/src/ledger/storage_api/ibc.rs similarity index 76% rename from apps/src/lib/node/ledger/shell/ibc.rs rename to core/src/ledger/storage_api/ibc.rs index 305f2b5954..9fc69ff784 100644 --- a/apps/src/lib/node/ledger/shell/ibc.rs +++ b/core/src/ledger/storage_api/ibc.rs @@ -3,28 +3,26 @@ use std::cell::RefCell; use std::rc::Rc; -use namada::core::ledger::governance::storage::proposal::PGFIbcTarget; -use namada::core::ledger::ibc::{ - IbcActions, IbcCommonContext, IbcStorageContext, -}; -use namada::core::ledger::storage_api::Error; -use namada::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; -use namada::ibc::apps::transfer::types::packet::PacketData; -use namada::ibc::apps::transfer::types::PrefixedCoin; -use namada::ibc::core::channel::types::timeout::TimeoutHeight; -use namada::ibc::primitives::Msg; -use namada::ledger::parameters::read_epoch_duration_parameter; -use namada::ledger::storage::wl_storage::WriteLogAndStorage; -use namada::ledger::storage::write_log::WriteLog; -use namada::ledger::storage::{DBIter, Storage, StorageHasher, WlStorage, DB}; -use namada::ledger::storage_api::{self, token, ResultExt, StorageWrite}; -use namada::tendermint::Time as TmTime; -use namada::types::address::{Address, InternalAddress}; -use namada::types::hash::Hash; -use namada::types::ibc::{IbcEvent, IbcShieldedTransfer}; -use namada::types::time::DateTimeUtc; -use namada::types::token::DenominatedAmount; - +use crate::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use crate::ibc::apps::transfer::types::packet::PacketData; +use crate::ibc::apps::transfer::types::PrefixedCoin; +use crate::ibc::core::channel::types::timeout::TimeoutHeight; +use crate::ibc::primitives::Msg; +use crate::ledger::governance::storage::proposal::PGFIbcTarget; +use crate::ledger::ibc::{IbcActions, IbcCommonContext, IbcStorageContext}; +use crate::ledger::parameters::read_epoch_duration_parameter; +use crate::ledger::storage::wl_storage::WriteLogAndStorage; +use crate::ledger::storage::write_log::{self, WriteLog}; +use crate::ledger::storage::{DBIter, Storage, StorageHasher, WlStorage, DB}; +use crate::ledger::storage_api::{self, token, Error, ResultExt, StorageWrite}; +use crate::tendermint::Time as TmTime; +use crate::types::address::{Address, InternalAddress}; +use crate::types::hash::Hash; +use crate::types::ibc::{IbcEvent, IbcShieldedTransfer}; +use crate::types::time::DateTimeUtc; +use crate::types::token::DenominatedAmount; + +/// IBC protocol context #[derive(Debug)] pub struct IbcProtocolContext<'a, D, H> where @@ -58,10 +56,7 @@ where self.wl_storage.split_borrow() } - fn write_tx_hash( - &mut self, - hash: Hash, - ) -> namada::ledger::storage::write_log::Result<()> { + fn write_tx_hash(&mut self, hash: Hash) -> write_log::Result<()> { self.wl_storage.write_tx_hash(hash) } } @@ -99,7 +94,7 @@ where token: &Address, amount: DenominatedAmount, ) -> Result<(), Error> { - token::transfer(self, token, src, dest, amount.amount) + token::transfer(self, token, src, dest, amount.amount()) } /// Handle masp tx @@ -117,7 +112,7 @@ where token: &Address, amount: DenominatedAmount, ) -> Result<(), Error> { - token::credit_tokens(self.wl_storage, token, target, amount.amount)?; + token::credit_tokens(self.wl_storage, token, target, amount.amount())?; let minter_key = token::minter_key(token); self.wl_storage .write(&minter_key, Address::Internal(InternalAddress::Ibc)) @@ -130,7 +125,7 @@ where token: &Address, amount: DenominatedAmount, ) -> Result<(), Error> { - token::burn(self.wl_storage, token, target, amount.amount) + token::burn(self.wl_storage, token, target, amount.amount()) } fn log_string(&self, message: String) { @@ -145,6 +140,7 @@ where { } +/// Transfer tokens over IBC pub fn transfer_over_ibc( wl_storage: &mut WlStorage, token: &Address, diff --git a/core/src/ledger/storage_api/mod.rs b/core/src/ledger/storage_api/mod.rs index ad239b2f4c..473a2bfcf6 100644 --- a/core/src/ledger/storage_api/mod.rs +++ b/core/src/ledger/storage_api/mod.rs @@ -5,6 +5,7 @@ pub mod account; pub mod collections; mod error; pub mod governance; +pub mod ibc; pub mod key; pub mod pgf; pub mod token; diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index fe398a0b39..d6986cc170 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -12,11 +12,15 @@ use core::convert::TryFrom; use core::str::FromStr; use core::time::Duration; -use std::collections::HashMap; -use std::path::PathBuf; +use std::collections::{BTreeSet, HashMap}; +use std::path::{Path, PathBuf}; use color_eyre::eyre::Result; use eyre::eyre; +use namada::core::ledger::governance::cli::onchain::PgfFunding; +use namada::core::ledger::governance::storage::proposal::{ + PGFIbcTarget, PGFTarget, +}; use namada::ibc::apps::transfer::types::VERSION as ICS20_VERSION; use namada::ibc::clients::tendermint::client_state::ClientState as TmClientState; use namada::ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; @@ -55,6 +59,7 @@ use namada::ibc::primitives::{Msg, Signer, Timestamp}; use namada::ledger::events::EventType; use namada::ledger::ibc::storage::*; use namada::ledger::parameters::{storage as param_storage, EpochDuration}; +use namada::ledger::pgf::ADDRESS as PGF_ADDRESS; use namada::ledger::queries::RPC; use namada::ledger::storage::ics23_specs::ibc_proof_specs; use namada::ledger::storage::traits::Sha256Hasher; @@ -62,7 +67,7 @@ use namada::tendermint::abci::Event as AbciEvent; use namada::tendermint::block::Height as TmHeight; use namada::types::address::{Address, InternalAddress}; use namada::types::key::PublicKey; -use namada::types::storage::{BlockHeight, Key}; +use namada::types::storage::{BlockHeight, Epoch, Key}; use namada::types::token::Amount; use namada_apps::cli::context::ENV_VAR_CHAIN_ID; use namada_apps::client::rpc::{ @@ -84,8 +89,11 @@ use tendermint_light_client::components::io::{Io, ProdIo as TmLightClientIo}; use super::setup::set_ethereum_bridge_mode; use crate::e2e::helpers::{ - find_address, get_actor_rpc, get_validator_pk, wait_for_wasm_pre_compile, + epochs_per_year_from_min_duration, find_address, get_actor_rpc, get_epoch, + get_established_addr_from_pregenesis, get_validator_pk, + wait_for_wasm_pre_compile, }; +use crate::e2e::ledger_tests::prepare_proposal_data; use crate::e2e::setup::{ self, run_hermes_cmd, setup_hermes, sleep, Bin, NamadaCmd, Test, Who, }; @@ -96,7 +104,12 @@ use crate::{run, run_as}; #[test] fn run_ledger_ibc() -> Result<()> { - let (ledger_a, ledger_b, test_a, test_b) = run_two_nets()?; + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = 31536; + setup::set_validators(1, genesis, base_dir, |_| 0) + }; + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); let _bg_ledger_b = ledger_b.background(); @@ -177,7 +190,12 @@ fn run_ledger_ibc() -> Result<()> { #[test] fn run_ledger_ibc_with_hermes() -> Result<()> { - let (ledger_a, ledger_b, test_a, test_b) = run_two_nets()?; + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = 31536; + setup::set_validators(1, genesis, base_dir, |_| 0) + }; + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; let _bg_ledger_a = ledger_a.background(); let _bg_ledger_b = ledger_b.background(); @@ -266,8 +284,88 @@ fn run_ledger_ibc_with_hermes() -> Result<()> { Ok(()) } -fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { - let (test_a, test_b) = setup_two_single_node_nets()?; +#[test] +fn pgf_over_ibc_with_hermes() -> Result<()> { + let update_genesis = + |mut genesis: templates::All, base_dir: &_| { + genesis.parameters.parameters.epochs_per_year = + epochs_per_year_from_min_duration(10); + // for the trusting period of IBC client + genesis.parameters.pos_params.pipeline_len = 10; + genesis.parameters.parameters.max_proposal_bytes = + Default::default(); + genesis.parameters.pgf_params.stewards = + BTreeSet::from_iter([get_established_addr_from_pregenesis( + ALBERT_KEY, base_dir, &genesis, + ) + .unwrap()]); + setup::set_validators(1, genesis, base_dir, |_| 0) + }; + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets(update_genesis)?; + let _bg_ledger_a = ledger_a.background(); + let _bg_ledger_b = ledger_b.background(); + + setup_hermes(&test_a, &test_b)?; + let port_id_a = "transfer".parse().unwrap(); + let port_id_b = "transfer".parse().unwrap(); + let (channel_id_a, channel_id_b) = + create_channel_with_hermes(&test_a, &test_b)?; + + // Start relaying + let hermes = run_hermes(&test_a)?; + let _bg_hermes = hermes.background(); + + // Transfer to PGF account + transfer_on_chain( + &test_a, + ALBERT, + PGF_ADDRESS.to_string(), + NAM, + 100, + ALBERT_KEY, + )?; + + // Proposal on Chain A + // Delegate some token + delegate_token(&test_a)?; + let rpc_a = get_actor_rpc(&test_a, Who::Validator(0)); + let mut epoch = get_epoch(&test_a, &rpc_a).unwrap(); + let delegated = epoch + 10u64; + while epoch <= delegated { + sleep(5); + epoch = get_epoch(&test_a, &rpc_a).unwrap(); + } + // funding proposal + let start_epoch = + propose_funding(&test_a, &test_b, &port_id_a, &channel_id_a)?; + let mut epoch = get_epoch(&test_a, &rpc_a).unwrap(); + // Vote + while epoch <= start_epoch { + sleep(5); + epoch = get_epoch(&test_a, &rpc_a).unwrap(); + } + submit_votes(&test_a)?; + + // wait for the grace + let grace_epoch = start_epoch + 12u64 + 6u64; + while epoch <= grace_epoch { + sleep(5); + epoch = get_epoch(&test_a, &rpc_a).unwrap(); + } + + // Check balances after funding over IBC + check_funded_balances(&port_id_b, &channel_id_b, &test_b)?; + + Ok(()) +} + +fn run_two_nets( + update_genesis: impl FnMut( + templates::All, + &Path, + ) -> templates::All, +) -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { + let (test_a, test_b) = setup_two_single_node_nets(update_genesis)?; set_ethereum_bridge_mode( &test_a, &test_a.net.chain_id, @@ -305,19 +403,19 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { } /// Set up two Namada chains to talk to each other via IBC. -fn setup_two_single_node_nets() -> Result<(Test, Test)> { +fn setup_two_single_node_nets( + mut update_genesis: impl FnMut( + templates::All, + &Path, + ) -> templates::All, +) -> Result<(Test, Test)> { const ANOTHER_PROXY_APP: u16 = 27659u16; const ANOTHER_RPC: u16 = 27660u16; const ANOTHER_P2P: u16 = 26655u16; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); - // epoch per 100 seconds - let update_genesis = - |mut genesis: templates::All, base_dir: &_| { - genesis.parameters.parameters.epochs_per_year = 31536; - setup::set_validators(1, genesis, base_dir, |_| 0) - }; - let test_a = setup::network(update_genesis, None)?; + + let test_a = setup::network(&mut update_genesis, None)?; let test_b = setup::network(update_genesis, None)?; let genesis_b_dir = test_b .test_dir @@ -1427,6 +1525,121 @@ fn transfer( } } +fn delegate_token(test: &Test) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); + let rpc = get_actor_rpc(test, Who::Validator(0)); + let tx_args = vec![ + "bond", + "--validator", + "validator-0", + "--source", + BERTHA, + "--amount", + "900", + "--node", + &rpc, + ]; + let mut client = run!(test, Bin::Client, tx_args, Some(40))?; + client.exp_string(TX_ACCEPTED)?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + Ok(()) +} + +fn propose_funding( + test_a: &Test, + test_b: &Test, + src_port_id: &PortId, + src_channel_id: &ChannelId, +) -> Result { + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); + let bertha = find_address(test_b, BERTHA)?; + let christel = find_address(test_b, CHRISTEL)?; + + let pgf_funding = PgfFunding { + continuous: vec![PGFTarget::Ibc(PGFIbcTarget { + amount: Amount::from_u64(10), + target: bertha.to_string(), + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + })], + retro: vec![PGFTarget::Ibc(PGFIbcTarget { + amount: Amount::from_u64(5), + target: christel.to_string(), + port_id: src_port_id.clone(), + channel_id: src_channel_id.clone(), + })], + }; + + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); + let albert = find_address(test_a, ALBERT)?; + let rpc_a = get_actor_rpc(test_a, Who::Validator(0)); + let epoch = get_epoch(test_a, &rpc_a)?; + let start_epoch = (epoch.0 + 3) / 3 * 3; + let proposal_json_path = + prepare_proposal_data(test_a, albert, pgf_funding, start_epoch); + + let submit_proposal_args = vec![ + "init-proposal", + "--pgf-funding", + "--data-path", + proposal_json_path.to_str().unwrap(), + "--node", + &rpc_a, + ]; + let mut client = run!(test_a, Bin::Client, submit_proposal_args, Some(40))?; + client.exp_string(TX_ACCEPTED)?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + Ok(start_epoch.into()) +} + +fn submit_votes(test: &Test) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); + let rpc = get_actor_rpc(test, Who::Validator(0)); + + let submit_proposal_vote = vec![ + "vote-proposal", + "--proposal-id", + "0", + "--vote", + "yay", + "--address", + "validator-0", + "--node", + &rpc, + ]; + let mut client = run_as!( + test, + Who::Validator(0), + Bin::Client, + submit_proposal_vote, + Some(40) + )?; + client.exp_string(TX_ACCEPTED)?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + + // Send different yay vote from delegator to check majority on 1/3 + let submit_proposal_vote_delagator = vec![ + "vote-proposal", + "--proposal-id", + "0", + "--vote", + "yay", + "--address", + BERTHA, + "--node", + &rpc, + ]; + let mut client = + run!(test, Bin::Client, submit_proposal_vote_delagator, Some(40))?; + client.exp_string(TX_ACCEPTED)?; + client.exp_string(TX_APPLIED_SUCCESS)?; + client.assert_success(); + Ok(()) +} + fn check_tx_height(test: &Test, client: &mut NamadaCmd) -> Result { let (_unread, matched) = client.exp_regex(r"height .*")?; // Expecting e.g. "height 1337." @@ -1705,6 +1918,34 @@ fn check_shielded_balances( Ok(()) } +fn check_funded_balances( + dest_port_id: &PortId, + dest_channel_id: &ChannelId, + test_b: &Test, +) -> Result<()> { + // Check the balance on Chain B + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/nam"); + let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); + let query_args = vec![ + "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc_b, + ]; + let expected = format!("{ibc_denom}: 10"); + let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; + client.exp_string(&expected)?; + client.assert_success(); + + let query_args = vec![ + "balance", "--owner", CHRISTEL, "--token", &ibc_denom, "--node", &rpc_b, + ]; + let expected = format!("{ibc_denom}: 5"); + let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; + client.exp_string(&expected)?; + client.assert_success(); + + Ok(()) +} + fn signer() -> Signer { "signer".to_string().into() } diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index f6494b355d..299de13e96 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -3041,7 +3041,7 @@ fn test_epoch_sleep() -> Result<()> { /// Prepare proposal data in the test's temp dir from the given source address. /// This can be submitted with "init-proposal" command. -fn prepare_proposal_data( +pub fn prepare_proposal_data( test: &setup::Test, source: Address, data: impl serde::Serialize, From f72e2612300ffbae08e96de45d071120572f9d35 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 13 Dec 2023 21:44:30 +0100 Subject: [PATCH 5/7] add changelog --- .changelog/unreleased/features/1395-pgf-ibc.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 .changelog/unreleased/features/1395-pgf-ibc.md diff --git a/.changelog/unreleased/features/1395-pgf-ibc.md b/.changelog/unreleased/features/1395-pgf-ibc.md new file mode 100644 index 0000000000..e4743c49fa --- /dev/null +++ b/.changelog/unreleased/features/1395-pgf-ibc.md @@ -0,0 +1 @@ +- PGF over IBC ([\#1395](https://github.com/anoma/namada/issues/1395)) \ No newline at end of file From c4f0b4f9d03338286baba135c5b6e9b573ae72b8 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 13 Dec 2023 23:50:12 +0100 Subject: [PATCH 6/7] add new e2e --- .github/workflows/scripts/e2e.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 097db9ab0e..b5438cfbc8 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -2,6 +2,7 @@ "e2e::eth_bridge_tests::everything": 4, "e2e::ibc_tests::run_ledger_ibc": 155, "e2e::ibc_tests::run_ledger_ibc_with_hermes": 130, + "e2e::ibc_tests::pgf_over_ibc_with_hermes": 240, "e2e::eth_bridge_tests::test_add_to_bridge_pool": 10, "e2e::ledger_tests::double_signing_gets_slashed": 12, "e2e::ledger_tests::invalid_transactions": 13, From e9433e3f6c431cb9530cb8e0daac2f12fdb13c2c Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 3 Jan 2024 12:27:12 +0100 Subject: [PATCH 7/7] fix to add the height in IBC event --- apps/src/lib/node/ledger/shell/finalize_block.rs | 5 ++++- apps/src/lib/node/ledger/shell/governance.rs | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index c23bc617e4..d41957582f 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -687,7 +687,10 @@ where // Pgf inflation pgf_inflation::apply_inflation(&mut self.wl_storage)?; for ibc_event in self.wl_storage.write_log_mut().take_ibc_events() { - let event = Event::from(ibc_event.clone()); + let mut event = Event::from(ibc_event.clone()); + // Add the height for IBC event query + let height = self.wl_storage.storage.get_last_block_height() + 1; + event["height"] = height.to_string(); response.events.push(event); } diff --git a/apps/src/lib/node/ledger/shell/governance.rs b/apps/src/lib/node/ledger/shell/governance.rs index aea626e725..42d97b0bea 100644 --- a/apps/src/lib/node/ledger/shell/governance.rs +++ b/apps/src/lib/node/ledger/shell/governance.rs @@ -139,7 +139,14 @@ where for ibc_event in shell.wl_storage.write_log_mut().take_ibc_events() { - let event = Event::from(ibc_event.clone()); + let mut event = Event::from(ibc_event.clone()); + // Add the height for IBC event query + let height = shell + .wl_storage + .storage + .get_last_block_height() + + 1; + event["height"] = height.to_string(); response.events.push(event); }