From dc9e4fd1ddfa00d1b88b40fd1885033645fee9ef Mon Sep 17 00:00:00 2001 From: satan Date: Wed, 26 Jul 2023 12:15:21 +0200 Subject: [PATCH 01/54] [feat]: Allow eth-oracle to be activated / deactivated via config updates sent from ledger --- .../lib/node/ledger/ethereum_oracle/mod.rs | 114 ++++++++++++++++++ .../lib/node/ledger/shell/finalize_block.rs | 6 +- apps/src/lib/node/ledger/shell/init_chain.rs | 2 +- apps/src/lib/node/ledger/shell/mod.rs | 37 ++++-- ethereum_bridge/src/oracle/config.rs | 3 + .../src/storage/eth_bridge_queries.rs | 24 +++- 6 files changed, 172 insertions(+), 14 deletions(-) diff --git a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs index 1e967b12b4..4c1638eaf6 100644 --- a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs +++ b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs @@ -243,6 +243,18 @@ impl Oracle { _ => None, } } + + /// If the bridge has been deactivated, block here until a new + /// config is passed that reactivates the bridge + async fn wait_on_reactivation(&mut self) -> Config { + loop { + if let Some(Command::UpdateConfig(c)) = self.control.recv().await { + if c.active { + return c; + } + } + } + } } /// Block until an initial configuration is received via the command channel. @@ -394,6 +406,9 @@ async fn run_oracle_aux(mut oracle: Oracle) { if let Some(new_config) = oracle.update_config() { config = new_config; } + if !config.active { + config = oracle.wait_on_reactivation().await; + } next_block_to_process += 1.into(); } } @@ -981,6 +996,105 @@ mod test_oracle { oracle.await.expect("Test failed"); } + /// Test that Ethereum oracle can be deactivate and reactivated + /// via config updates. + /// NOTE: This test can flake due to async channel race + /// conditions. + #[tokio::test] + async fn test_oracle_reactivation() { + let TestPackage { + oracle, + eth_recv, + controller, + mut blocks_processed_recv, + mut control_sender, + } = setup(); + let config = Config::default(); + let oracle = start_with_default_config( + oracle, + &mut control_sender, + config.clone(), + ) + .await; + + // set the height of the chain such that there are some blocks deep + // enough to be considered confirmed by the oracle + let confirmed_block_height = 9; // all blocks up to and including this block will have enough confirmations + let min_confirmations = u64::from(config.min_confirmations); + controller.apply_cmd(TestCmd::NewHeight(Uint256::from( + min_confirmations + confirmed_block_height - 3, + ))); + + // check that the oracle indeed processes the expected blocks + for height in 0u64..(confirmed_block_height - 4) { + let block_processed = timeout( + std::time::Duration::from_secs(3), + blocks_processed_recv.recv(), + ) + .await + .expect("Timed out waiting for block to be checked") + .unwrap(); + assert_eq!(block_processed, Uint256::from(height)); + } + + // Deactivate the bridge before all confirmed events are confirmed and + // processed There is a very fine needle to thread here. A block + // must be processed **after** this config is sent in order for + // the updated config to be received. However, this test can + // flake due to channel race conditions. + control_sender + .try_send(Command::UpdateConfig(Config { + active: false, + ..Default::default() + })) + .expect("Test failed"); + std::thread::sleep(Duration::from_secs(1)); + controller.apply_cmd(TestCmd::NewHeight(Uint256::from( + min_confirmations + confirmed_block_height - 4, + ))); + + let block_processed = timeout( + std::time::Duration::from_secs(3), + blocks_processed_recv.recv(), + ) + .await + .expect("Timed out waiting for block to be checked") + .unwrap(); + assert_eq!(block_processed, Uint256::from(confirmed_block_height - 4)); + + // check that the oracle hasn't yet checked any further blocks + // TODO: check this in a deterministic way rather than just waiting a + // bit + let res = timeout( + std::time::Duration::from_secs(3), + blocks_processed_recv.recv(), + ) + .await; + assert!(res.is_err()); + + // reactivate the bridge and check that the oracle + // processed the rest of the confirmed blocks + control_sender + .try_send(Command::UpdateConfig(Default::default())) + .expect("Test failed"); + + controller.apply_cmd(TestCmd::NewHeight(Uint256::from( + min_confirmations + confirmed_block_height, + ))); + for height in (confirmed_block_height - 3)..=confirmed_block_height { + let block_processed = timeout( + std::time::Duration::from_secs(3), + blocks_processed_recv.recv(), + ) + .await + .expect("Timed out waiting for block to be checked") + .unwrap(); + assert_eq!(block_processed, Uint256::from(height)); + } + drop(eth_recv); + oracle.await.expect("Test failed"); + } + /// Test that if the Ethereum RPC endpoint returns a latest block that is /// more than one block later than the previous latest block we received, we /// still check all the blocks in between diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 2f178eb47e..a756f39c25 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -136,6 +136,7 @@ where // Tracks the accepted transactions self.wl_storage.storage.block.results = BlockResults::default(); + let mut changed_keys = BTreeSet::new(); for (tx_index, processed_tx) in req.txs.iter().enumerate() { let tx = if let Ok(tx) = Tx::try_from(processed_tx.tx.as_ref()) { tx @@ -421,7 +422,7 @@ where ) .map_err(Error::TxApply) { - Ok(result) => { + Ok(ref mut result) => { if result.is_accepted() { tracing::trace!( "all VPs accepted transaction {} storage \ @@ -429,6 +430,7 @@ where tx_event["hash"], result ); + changed_keys.append(&mut result.changed_keys); stats.increment_successful_txs(); self.wl_storage.commit_tx(); if !tx_event.contains_key("code") { @@ -531,7 +533,7 @@ where self.update_epoch(&mut response); // send the latest oracle configs. These may have changed due to // governance. - self.update_eth_oracle(); + self.update_eth_oracle(&changed_keys); } if !req.proposer_address.is_empty() { diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index ef08373789..b88f44c939 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -204,7 +204,7 @@ where if let Some(config) = genesis.ethereum_bridge_params { tracing::debug!("Initializing Ethereum bridge storage."); config.init_storage(&mut self.wl_storage); - self.update_eth_oracle(); + self.update_eth_oracle(&Default::default()); } else { self.wl_storage .write_bytes( diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 2b7a0b7ac7..d2b7cc8390 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -548,7 +548,7 @@ where // TODO: config event log params event_log: EventLog::default(), }; - shell.update_eth_oracle(); + shell.update_eth_oracle(&Default::default()); shell } @@ -928,14 +928,18 @@ where } /// If a handle to an Ethereum oracle was provided to the [`Shell`], attempt - /// to send it an updated configuration, using an initial configuration + /// to send it an updated configuration, using a configuration /// based on Ethereum bridge parameters in blockchain storage. /// /// This method must be safe to call even before ABCI `InitChain` has been /// called (i.e. when storage is empty), as we may want to do this check /// every time the shell starts up (including the first time ever at which /// time storage will be empty). - fn update_eth_oracle(&mut self) { + /// + /// This method is also called during `FinalizeBlock` to update the oracle + /// if relevant storage changes have occurred. This includes deactivating + /// and reactivating the bridge. + fn update_eth_oracle(&mut self, changed_keys: &BTreeSet) { if let ShellMode::Validator { eth_oracle: Some(EthereumOracleChannels { control_sender, .. }), .. @@ -961,18 +965,32 @@ where ); return; } - if !self.wl_storage.ethbridge_queries().is_bridge_active() { - tracing::info!( - "Not starting oracle as the Ethereum bridge is disabled" - ); - return; - } let Some(config) = EthereumBridgeConfig::read(&self.wl_storage) else { tracing::info!( "Not starting oracle as the Ethereum bridge config couldn't be found in storage" ); return; }; + let active = + if !self.wl_storage.ethbridge_queries().is_bridge_active() { + if !changed_keys + .contains(ð_bridge::storage::active_key()) + { + tracing::info!( + "Not starting oracle as the Ethereum bridge is \ + disabled" + ); + return; + } else { + tracing::info!( + "Disabling oracle as the bridge has been disabled" + ); + false + } + } else { + true + }; + let start_block = self .wl_storage .storage @@ -998,6 +1016,7 @@ where bridge_contract: config.contracts.bridge.address, governance_contract: config.contracts.governance.address, start_block, + active, }; tracing::info!( ?config, diff --git a/ethereum_bridge/src/oracle/config.rs b/ethereum_bridge/src/oracle/config.rs index 4ddb3ede1d..45c7325897 100644 --- a/ethereum_bridge/src/oracle/config.rs +++ b/ethereum_bridge/src/oracle/config.rs @@ -16,6 +16,8 @@ pub struct Config { pub governance_contract: EthAddress, /// The earliest Ethereum block from which events may be processed. pub start_block: ethereum_structs::BlockHeight, + /// The status of the Ethereum bridge (active / inactive) + pub active: bool, } // TODO: this production Default implementation is temporary, there should be no @@ -29,6 +31,7 @@ impl std::default::Default for Config { bridge_contract: EthAddress([0; 20]), governance_contract: EthAddress([1; 20]), start_block: 0.into(), + active: true, } } } diff --git a/ethereum_bridge/src/storage/eth_bridge_queries.rs b/ethereum_bridge/src/storage/eth_bridge_queries.rs index 827745def0..cafe6815db 100644 --- a/ethereum_bridge/src/storage/eth_bridge_queries.rs +++ b/ethereum_bridge/src/storage/eth_bridge_queries.rs @@ -37,14 +37,34 @@ pub enum SendValsetUpd { AtPrevHeight, } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + PartialEq, + Eq, + Hash, + Ord, + PartialOrd, +)] /// An enum indicating if the Ethereum bridge is enabled. pub enum EthBridgeStatus { Disabled, Enabled(EthBridgeEnabled), } -#[derive(Debug, Clone, BorshDeserialize, BorshSerialize)] +#[derive( + Debug, + Clone, + BorshDeserialize, + BorshSerialize, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, +)] /// Enum indicating if the bridge was initialized at genesis /// or a later epoch. pub enum EthBridgeEnabled { From 0c7aff512992bfe592934c5cb964717cf54a7518 Mon Sep 17 00:00:00 2001 From: satan Date: Wed, 26 Jul 2023 16:52:20 +0200 Subject: [PATCH 02/54] [fix]: Fixed block height typo in test --- apps/src/lib/node/ledger/ethereum_oracle/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs index 4c1638eaf6..c2a0f22147 100644 --- a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs +++ b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs @@ -1022,7 +1022,7 @@ mod test_oracle { let confirmed_block_height = 9; // all blocks up to and including this block will have enough confirmations let min_confirmations = u64::from(config.min_confirmations); controller.apply_cmd(TestCmd::NewHeight(Uint256::from( - min_confirmations + confirmed_block_height - 3, + min_confirmations + confirmed_block_height - 5, ))); // check that the oracle indeed processes the expected blocks From ecb89e2db45a2660eb0a7893ec695386b39bd34e Mon Sep 17 00:00:00 2001 From: satan Date: Thu, 17 Aug 2023 15:50:35 +0200 Subject: [PATCH 03/54] [chore]: Add changelog --- .../unreleased/improvements/1764-halt-oracle-from-ledger.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changelog/unreleased/improvements/1764-halt-oracle-from-ledger.md diff --git a/.changelog/unreleased/improvements/1764-halt-oracle-from-ledger.md b/.changelog/unreleased/improvements/1764-halt-oracle-from-ledger.md new file mode 100644 index 0000000000..8921ac4529 --- /dev/null +++ b/.changelog/unreleased/improvements/1764-halt-oracle-from-ledger.md @@ -0,0 +1,5 @@ +Allow the ethereum oracle to be activated / deactivated via config +updates sent from ledger. This allows governance to shut down the +ledger without restarts. Otherwise, disconnecting from Ethereum will +result in the ledger crashing. +([\#1764](https://github.com/anoma/namada/pull/1764)) From 06372330d08e6eb7143f9596c0853b7c3b50d412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 07:34:19 +0200 Subject: [PATCH 04/54] core/storage: change the default start height of first epoch to 1 --- core/src/types/storage.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index ad0c14f499..019323930c 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -1161,13 +1161,12 @@ pub struct Epochs { /// Invariant: the values must be sorted in ascending order. pub first_block_heights: Vec, } - impl Default for Epochs { - /// Initialize predecessor epochs, assuming starting on the epoch 0 and - /// block height 0. + /// Initialize predecessor epochs, assuming start of the first epoch at + /// block height 1. fn default() -> Self { Self { - first_block_heights: vec![BlockHeight::default()], + first_block_heights: vec![BlockHeight(1)], } } } @@ -1618,7 +1617,7 @@ mod tests { println!("epochs {:#?}", epochs); assert_eq!( epochs.get_start_height_of_epoch(Epoch(0)), - Some(BlockHeight(0)) + Some(BlockHeight(1)) ); assert_eq!(epochs.get_epoch(BlockHeight(0)), Some(Epoch(0))); From da2358b0a95042d843d975ca77b93e1346aed8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 07:34:50 +0200 Subject: [PATCH 05/54] core/storage: set the initial height from genesis --- core/src/ledger/storage/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index 81be7e48a6..66903fa2cd 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -963,6 +963,11 @@ where } = parameters.epoch_duration; self.next_epoch_min_start_height = initial_height + min_num_of_blocks; self.next_epoch_min_start_time = genesis_time + min_duration; + // The default start height in `Epochs` is set to 1, we override it + // here in case it differs at genesis + self.block.pred_epochs = Epochs { + first_block_heights: vec![initial_height], + }; self.update_epoch_in_merkle_tree() } From 686328cd3b427c5eef1e5c4b694929711c9b9d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 09:19:06 +0200 Subject: [PATCH 06/54] core/storage: add `BlockHeight::first` and `sentinel` --- core/src/ledger/storage/mod.rs | 4 ++-- core/src/types/storage.rs | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index 66903fa2cd..ef8ba38f33 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -142,8 +142,8 @@ pub struct BlockStorage { pub hash: BlockHash, /// From the start of `FinalizeBlock` until the end of `Commit`, this is /// height of the block that is going to be committed. Otherwise, it is the - /// height of the most recently committed block, or `BlockHeight(0)` if no - /// block has been committed yet. + /// height of the most recently committed block, or `BlockHeight::sentinel` + /// (0) if no block has been committed yet. pub height: BlockHeight, /// From the start of `FinalizeBlock` until the end of `Commit`, this is /// height of the block that is going to be committed. Otherwise it is the diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index 019323930c..42629f6a0b 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -155,9 +155,9 @@ impl BlockResults { } } -/// Height of a block, i.e. the level. +/// Height of a block, i.e. the level. The `default` is the +/// [`BlockHeight::sentinel`] value, which doesn't correspond to any block. #[derive( - Default, Clone, Copy, BorshSerialize, @@ -174,6 +174,12 @@ impl BlockResults { )] pub struct BlockHeight(pub u64); +impl Default for BlockHeight { + fn default() -> Self { + Self::sentinel() + } +} + impl Display for BlockHeight { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) @@ -267,6 +273,17 @@ impl TryFrom for BlockHeight { } } impl BlockHeight { + /// The first block height 1. + pub const fn first() -> Self { + Self(1) + } + + /// A sentinel value block height 0 may be used before any block is + /// committed or in queries to read from the latest committed block. + pub const fn sentinel() -> Self { + Self(0) + } + /// Get the height of the next block pub fn next_height(&self) -> BlockHeight { BlockHeight(self.0 + 1) From 8d0d4588b406724e6b5ee957870a36db8706cd94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 18 Oct 2023 11:29:03 +0200 Subject: [PATCH 07/54] core/storage/epochs: Change pred `Epochs` default to be empty --- core/src/ledger/storage/mod.rs | 8 ++++++-- core/src/types/storage.rs | 14 ++++---------- ethereum_bridge/src/test_utils.rs | 6 ++++++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index ef8ba38f33..658ab81e70 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -963,8 +963,6 @@ where } = parameters.epoch_duration; self.next_epoch_min_start_height = initial_height + min_num_of_blocks; self.next_epoch_min_start_time = genesis_time + min_duration; - // The default start height in `Epochs` is set to 1, we override it - // here in case it differs at genesis self.block.pred_epochs = Epochs { first_block_heights: vec![initial_height], }; @@ -1302,6 +1300,12 @@ mod tests { minimum_gas_price: BTreeMap::default(), }; parameters.init_storage(&mut wl_storage).unwrap(); + // Initialize pred_epochs to the current height + wl_storage + .storage + .block + .pred_epochs + .new_epoch(wl_storage.storage.block.height); let epoch_before = wl_storage.storage.last_epoch; assert_eq!(epoch_before, wl_storage.storage.block.epoch); diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index 42629f6a0b..861ca88f18 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -1165,6 +1165,7 @@ impl Mul for Epoch { #[derive( Clone, Debug, + Default, PartialEq, Eq, PartialOrd, @@ -1178,15 +1179,6 @@ pub struct Epochs { /// Invariant: the values must be sorted in ascending order. pub first_block_heights: Vec, } -impl Default for Epochs { - /// Initialize predecessor epochs, assuming start of the first epoch at - /// block height 1. - fn default() -> Self { - Self { - first_block_heights: vec![BlockHeight(1)], - } - } -} impl Epochs { /// Record start of a new epoch at the given block height @@ -1630,7 +1622,9 @@ mod tests { #[test] fn test_predecessor_epochs_and_heights() { - let mut epochs = Epochs::default(); + let mut epochs = Epochs { + first_block_heights: vec![BlockHeight::first()], + }; println!("epochs {:#?}", epochs); assert_eq!( epochs.get_start_height_of_epoch(Epoch(0)), diff --git a/ethereum_bridge/src/test_utils.rs b/ethereum_bridge/src/test_utils.rs index 9c24e9edfa..b8c580f137 100644 --- a/ethereum_bridge/src/test_utils.rs +++ b/ethereum_bridge/src/test_utils.rs @@ -227,6 +227,12 @@ pub fn init_storage_with_validators( .write(&protocol_pk_key(validator), protocol_key) .expect("Test failed"); } + // Initialize pred_epochs to the current height + wl_storage + .storage + .block + .pred_epochs + .new_epoch(wl_storage.storage.block.height); wl_storage.commit_block().expect("Test failed"); all_keys From 8ca7666502490706190086c324222984f74ec09f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 18 Oct 2023 11:29:59 +0200 Subject: [PATCH 08/54] apps/shell/finalize_block: remove first epoch workaround --- apps/src/lib/node/ledger/shell/finalize_block.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 53252065f1..ffb722112f 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -702,11 +702,8 @@ where .pred_epochs .first_block_heights[last_epoch.0 as usize] .0; - let num_blocks_in_last_epoch = if first_block_of_last_epoch == 0 { - self.wl_storage.storage.block.height.0 - 1 - } else { - self.wl_storage.storage.block.height.0 - first_block_of_last_epoch - }; + let num_blocks_in_last_epoch = + self.wl_storage.storage.block.height.0 - first_block_of_last_epoch; // Read the rewards accumulator and calculate the new rewards products // for the previous epoch From f1de1df5bf459474c42148e9e1e38e23cb2a1b51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 08:01:38 +0200 Subject: [PATCH 09/54] test/app/ledger: fix merkle tree pruning test --- apps/src/lib/node/ledger/storage/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index 659f561cce..537d4e9ad4 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -498,8 +498,9 @@ mod tests { None, Some(5), ); + let new_epoch_start = BlockHeight(1); storage - .begin_block(BlockHash::default(), BlockHeight(1)) + .begin_block(BlockHash::default(), new_epoch_start) .expect("begin_block failed"); let key = Key::parse("key").expect("cannot parse the key string"); @@ -509,12 +510,13 @@ mod tests { .expect("write failed"); storage.block.epoch = storage.block.epoch.next(); - storage.block.pred_epochs.new_epoch(BlockHeight(1)); + storage.block.pred_epochs.new_epoch(new_epoch_start); let batch = PersistentStorage::batch(); storage.commit_block(batch).expect("commit failed"); + let new_epoch_start = BlockHeight(6); storage - .begin_block(BlockHash::default(), BlockHeight(6)) + .begin_block(BlockHash::default(), new_epoch_start) .expect("begin_block failed"); let key = Key::parse("key2").expect("cannot parse the key string"); @@ -524,18 +526,19 @@ mod tests { .expect("write failed"); storage.block.epoch = storage.block.epoch.next(); - storage.block.pred_epochs.new_epoch(BlockHeight(6)); + storage.block.pred_epochs.new_epoch(new_epoch_start); let batch = PersistentStorage::batch(); storage.commit_block(batch).expect("commit failed"); let result = storage.get_merkle_tree(1.into()); assert!(result.is_ok(), "The tree at Height 1 should be restored"); + let new_epoch_start = BlockHeight(11); storage - .begin_block(BlockHash::default(), BlockHeight(11)) + .begin_block(BlockHash::default(), new_epoch_start) .expect("begin_block failed"); storage.block.epoch = storage.block.epoch.next(); - storage.block.pred_epochs.new_epoch(BlockHeight(11)); + storage.block.pred_epochs.new_epoch(new_epoch_start); let batch = PersistentStorage::batch(); storage.commit_block(batch).expect("commit failed"); From 742978e0390b21c3cc920b8093f835c1427779fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 08:27:50 +0200 Subject: [PATCH 10/54] test/core/storage: fix pred epochs & heights test --- core/src/types/storage.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index 861ca88f18..8a56d16d4a 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -1640,14 +1640,15 @@ mod tests { Some(BlockHeight(10)) ); assert_eq!(epochs.get_epoch(BlockHeight(0)), Some(Epoch(0))); + assert_eq!(epochs.get_epoch_start_height(BlockHeight(0)), None); assert_eq!( - epochs.get_epoch_start_height(BlockHeight(0)), - Some(BlockHeight(0)) + epochs.get_epoch_start_height(BlockHeight(1)), + Some(BlockHeight(1)) ); assert_eq!(epochs.get_epoch(BlockHeight(9)), Some(Epoch(0))); assert_eq!( epochs.get_epoch_start_height(BlockHeight(9)), - Some(BlockHeight(0)) + Some(BlockHeight(1)) ); assert_eq!(epochs.get_epoch(BlockHeight(10)), Some(Epoch(1))); assert_eq!( From 3ea8305ee392bd6098beb15496a0f976a7217473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 17 Oct 2023 08:29:21 +0200 Subject: [PATCH 11/54] changelog: add #1993 --- .changelog/unreleased/bug-fixes/1993-fst-epoch-start-height.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/1993-fst-epoch-start-height.md diff --git a/.changelog/unreleased/bug-fixes/1993-fst-epoch-start-height.md b/.changelog/unreleased/bug-fixes/1993-fst-epoch-start-height.md new file mode 100644 index 0000000000..856a1508ce --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1993-fst-epoch-start-height.md @@ -0,0 +1,2 @@ +- Fix the start block height of the first epoch. + ([\#1993](https://github.com/anoma/namada/pull/1993)) \ No newline at end of file From ed9138d2a3a94000301c7246b816a3862fe1e4b7 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Thu, 19 Oct 2023 15:01:26 +0100 Subject: [PATCH 12/54] Relocate eth event nonce validation --- .../lib/node/ledger/shell/vote_extensions.rs | 6 +- .../shell/vote_extensions/eth_events.rs | 132 +++++++----------- .../src/storage/eth_bridge_queries.rs | 49 ++++++- 3 files changed, 98 insertions(+), 89 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/vote_extensions.rs b/apps/src/lib/node/ledger/shell/vote_extensions.rs index 658c35a121..55bdb3c855 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions.rs @@ -35,10 +35,8 @@ pub enum VoteExtensionError { ValsetUpdProofAvailable, #[error("The length of the transfers and their validity map differ")] TransfersLenMismatch, - #[error("The bridge pool nonce in the vote extension is invalid")] - InvalidBpNonce, - #[error("The transfer to Namada nonce in the vote extension is invalid")] - InvalidNamNonce, + #[error("The nonce in the Ethereum event is invalid")] + InvalidEthEventNonce, #[error("The vote extension was issued for an unexpected block height")] UnexpectedBlockHeight, #[error("The vote extension was issued for an unexpected epoch")] diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs index 0dd85bfd70..55e3be8ff6 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs @@ -144,11 +144,8 @@ where /// an [`ethereum_events::Vext`]. /// /// The supplied Ethereum events must be ordered in - /// ascending ordering, and must not contain any dupes. - /// - /// A detailed description of the validation applied - /// to each event kind can be found in the docstring - /// of [`Shell::validate_eth_event`]. + /// ascending ordering, must not contain any dupes + /// and must have valid nonces. fn validate_eth_events( &self, ext: ðereum_events::Vext, @@ -170,79 +167,17 @@ where ); return Err(VoteExtensionError::HaveDupesOrNonSorted); } - ext.ethereum_events - .iter() - .try_for_each(|event| self.validate_eth_event(event)) - } - - /// Valdidate an [`EthereumEvent`] against the current state - /// of the ledger. - /// - /// # Event kinds - /// - /// In this section, we shall describe the checks perform for - /// each kind of relevant Ethereum event. - /// - /// ## Transfers to Ethereum - /// - /// We need to check if the nonce in the event corresponds to - /// the most recent bridge pool nonce. Unless the nonces match, - /// no state updates derived from the event should be applied. - /// In case the nonces are different, we reject the event, and - /// thus the inclusion of its container Ethereum events vote - /// extension. - /// - /// ## Transfers to Namada - /// - /// For a transfers to Namada event to be considered valid, - /// the nonce of this kind of event must not be lower than - /// the one stored in Namada. - fn validate_eth_event( - &self, - event: &EthereumEvent, - ) -> std::result::Result<(), VoteExtensionError> { - // TODO: on the transfer events, maybe perform additional checks: - // - some token asset is not whitelisted - // - do we have enough balance for the transfer - // in practice, some events may have a variable degree of garbage - // data in them; we can simply rely on quorum decisions to filter - // out such events, which will time out in storage - match event { - EthereumEvent::TransfersToEthereum { - nonce: ext_nonce, .. - } => { - let current_bp_nonce = - self.wl_storage.ethbridge_queries().get_bridge_pool_nonce(); - if ¤t_bp_nonce != ext_nonce { - tracing::debug!( - %current_bp_nonce, - %ext_nonce, - "The Ethereum events vote extension's BP nonce is \ - invalid" - ); - return Err(VoteExtensionError::InvalidBpNonce); - } - } - EthereumEvent::TransfersToNamada { - nonce: ext_nonce, .. - } => { - let next_nam_transfers_nonce = self - .wl_storage - .ethbridge_queries() - .get_next_nam_transfers_nonce(); - if &next_nam_transfers_nonce > ext_nonce { - tracing::debug!( - ?event, - %next_nam_transfers_nonce, - "Attempt to replay a transfer to Namada event" - ); - return Err(VoteExtensionError::InvalidNamNonce); - } + ext.ethereum_events.iter().try_for_each(|event| { + if self + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(event) + { + Ok(()) + } else { + Err(VoteExtensionError::InvalidEthEventNonce) } - // consider other ethereum event kinds valid - _ => {} - } - Ok(()) + }) } /// Checks the channel from the Ethereum oracle monitoring @@ -416,6 +351,7 @@ mod test_vote_extensions { NestedSubKey, SubKey, }; use namada::eth_bridge::storage::bridge_pool; + use namada::ledger::eth_bridge::EthBridgeQueries; use namada::ledger::pos::PosQueries; use namada::proof_of_stake::types::WeightedValidator; use namada::proof_of_stake::{ @@ -474,55 +410,83 @@ mod test_vote_extensions { // eth transfers with the same nonce as the bp nonce in storage are // valid shell - .validate_eth_event(&EthereumEvent::TransfersToEthereum { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToEthereum { nonce, transfers: vec![], relayer: gen_established_address(), }) + .then_some(()) + .ok_or(()) .expect("Test failed"); // eth transfers with different nonces are invalid shell - .validate_eth_event(&EthereumEvent::TransfersToEthereum { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToEthereum { nonce: nonce + 1, transfers: vec![], relayer: gen_established_address(), }) + .then_some(()) + .ok_or(()) .expect_err("Test failed"); shell - .validate_eth_event(&EthereumEvent::TransfersToEthereum { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToEthereum { nonce: nonce - 1, transfers: vec![], relayer: gen_established_address(), }) + .then_some(()) + .ok_or(()) .expect_err("Test failed"); // nam transfers with nonces >= the nonce in storage are valid shell - .validate_eth_event(&EthereumEvent::TransfersToNamada { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToNamada { nonce, transfers: vec![], }) + .then_some(()) + .ok_or(()) .expect("Test failed"); shell - .validate_eth_event(&EthereumEvent::TransfersToNamada { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToNamada { nonce: nonce + 5, transfers: vec![], }) + .then_some(()) + .ok_or(()) .expect("Test failed"); // nam transfers with lower nonces are invalid shell - .validate_eth_event(&EthereumEvent::TransfersToNamada { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToNamada { nonce: nonce - 1, transfers: vec![], }) + .then_some(()) + .ok_or(()) .expect_err("Test failed"); shell - .validate_eth_event(&EthereumEvent::TransfersToNamada { + .wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&EthereumEvent::TransfersToNamada { nonce: nonce - 2, transfers: vec![], }) + .then_some(()) + .ok_or(()) .expect_err("Test failed"); } diff --git a/ethereum_bridge/src/storage/eth_bridge_queries.rs b/ethereum_bridge/src/storage/eth_bridge_queries.rs index 5e2f7b6399..58b4ce4cdb 100644 --- a/ethereum_bridge/src/storage/eth_bridge_queries.rs +++ b/ethereum_bridge/src/storage/eth_bridge_queries.rs @@ -10,7 +10,7 @@ use namada_core::types::address::Address; use namada_core::types::eth_abi::Encode; use namada_core::types::eth_bridge_pool::PendingTransfer; use namada_core::types::ethereum_events::{ - EthAddress, GetEventNonce, TransferToEthereum, Uint, + EthAddress, EthereumEvent, GetEventNonce, TransferToEthereum, Uint, }; use namada_core::types::keccak::KeccakHash; use namada_core::types::storage::{BlockHeight, Epoch, Key as StorageKey}; @@ -534,6 +534,53 @@ where .expect("Reading from storage should not fail") .zip(Some(pending_key)) } + + /// Valdidate an [`EthereumEvent`]'s nonce against the current + /// state of the ledger. + /// + /// # Event kinds + /// + /// In this section, we shall describe the checks perform for + /// each kind of relevant Ethereum event. + /// + /// ## Transfers to Ethereum + /// + /// We need to check if the nonce in the event corresponds to + /// the most recent bridge pool nonce. Unless the nonces match, + /// no state updates derived from the event should be applied. + /// In case the nonces are different, we reject the event, and + /// thus the inclusion of its container Ethereum events vote + /// extension. + /// + /// ## Transfers to Namada + /// + /// For a transfers to Namada event to be considered valid, + /// the nonce of this kind of event must not be lower than + /// the one stored in Namada. + pub fn validate_eth_event_nonce(&self, event: &EthereumEvent) -> bool { + match event { + EthereumEvent::TransfersToEthereum { + nonce: ext_nonce, .. + } => { + let current_bp_nonce = self.get_bridge_pool_nonce(); + if ¤t_bp_nonce != ext_nonce { + return false; + } + } + EthereumEvent::TransfersToNamada { + nonce: ext_nonce, .. + } => { + let next_nam_transfers_nonce = + self.get_next_nam_transfers_nonce(); + if &next_nam_transfers_nonce > ext_nonce { + return false; + } + } + // consider other ethereum event kinds valid + _ => {} + } + true + } } /// Number of tokens to mint after receiving a "transfer From 0dba83bcc6264cc596dd2fb080cbc98b4aef26a2 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Thu, 19 Oct 2023 15:01:58 +0100 Subject: [PATCH 13/54] Discard eth events from oracle with invalid nonces --- apps/src/lib/node/ledger/shell/mod.rs | 30 ++++++++++++++----- .../shell/vote_extensions/eth_events.rs | 5 +++- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index a1c17fe450..f32633935b 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -256,18 +256,32 @@ impl EthereumReceiver { } } - /// Pull messages from the channel and add to queue - /// Since vote extensions require ordering of ethereum - /// events, we do that here. We also de-duplicate events - pub fn fill_queue(&mut self) { + /// Pull Ethereum events from the oracle and queue them to + /// be voted on. + /// + /// Since vote extensions require ordering of Ethereum + /// events, we do that here. We also de-duplicate events. + /// Events may be filtered out of the queue with a provided + /// predicate. + pub fn fill_queue(&mut self, mut keep_event: F) + where + F: FnMut(&EthereumEvent) -> bool, + { let mut new_events = 0; + let mut filtered_events = 0; while let Ok(eth_event) = self.channel.try_recv() { - if self.queue.insert(eth_event) { + if keep_event(ð_event) && self.queue.insert(eth_event) { new_events += 1; - }; + } else { + filtered_events += 1; + } } - if new_events > 0 { - tracing::info!(n = new_events, "received Ethereum events"); + if new_events + filtered_events > 0 { + tracing::info!( + new_events, + filtered_events, + "received Ethereum events" + ); } } diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs index 55e3be8ff6..0116076cd7 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs @@ -183,6 +183,7 @@ where /// Checks the channel from the Ethereum oracle monitoring /// the fullnode and retrieves all seen Ethereum events. pub fn new_ethereum_events(&mut self) -> Vec { + let queries = self.wl_storage.ethbridge_queries(); match &mut self.mode { ShellMode::Validator { eth_oracle: @@ -191,7 +192,9 @@ where }), .. } => { - ethereum_receiver.fill_queue(); + ethereum_receiver.fill_queue(|event| { + queries.validate_eth_event_nonce(event) + }); ethereum_receiver.get_events() } _ => vec![], From 8a4cf40a76eaa155c6ea299634be13d765a8fb42 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 20 Oct 2023 14:33:50 +0100 Subject: [PATCH 14/54] Disregard state updates from eth events with outdated nonces --- .../src/protocol/transactions/ethereum_events/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs index 8b71bb26c4..3c5090bb7f 100644 --- a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs +++ b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs @@ -23,6 +23,7 @@ use super::ChangedKeys; use crate::protocol::transactions::utils; use crate::protocol::transactions::votes::update::NewVotes; use crate::protocol::transactions::votes::{self, calculate_new}; +use crate::storage::eth_bridge_queries::EthBridgeQueries; use crate::storage::vote_tallies::{self, Keys}; impl utils::GetVoters for &HashSet { @@ -63,7 +64,16 @@ where protocol transaction" ); - let updates = events.into_iter().map(Into::::into).collect(); + let updates = events + .into_iter() + .filter_map(|multisigned| { + // NB: discard events with outdated nonces + wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(&multisigned.event) + .then(|| EthMsgUpdate::from(multisigned)) + }) + .collect(); let voting_powers = utils::get_voting_powers(wl_storage, &updates)?; From f44d5ff57d58a507531758ba8198d962d7e3b415 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 20 Oct 2023 14:47:15 +0100 Subject: [PATCH 15/54] Only propose eth events with up to date nonces --- .../lib/node/ledger/shell/vote_extensions.rs | 16 ++++++++++++++-- .../ledger/shell/vote_extensions/eth_events.rs | 18 +++++++++--------- 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/vote_extensions.rs b/apps/src/lib/node/ledger/shell/vote_extensions.rs index 55bdb3c855..8a4511f4fd 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions.rs @@ -426,8 +426,20 @@ where } }; match (&tx).try_into().ok()? { - EthereumTxData::EthEventsVext(_) - | EthereumTxData::BridgePoolVext(_) => Some(tx_bytes.clone()), + EthereumTxData::BridgePoolVext(_) => Some(tx_bytes.clone()), + EthereumTxData::EthEventsVext(ext) => { + // NB: only propose events with at least + // one valid nonce + ext.data + .ethereum_events + .iter() + .any(|event| { + self.wl_storage + .ethbridge_queries() + .validate_eth_event_nonce(event) + }) + .then(|| tx_bytes.clone()) + } EthereumTxData::ValSetUpdateVext(ext) => { // only include non-stale validator set updates // in block proposals. it might be sitting long diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs index 0116076cd7..e1206e3a56 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs @@ -167,17 +167,17 @@ where ); return Err(VoteExtensionError::HaveDupesOrNonSorted); } - ext.ethereum_events.iter().try_for_each(|event| { - if self - .wl_storage + // for the proposal to be valid, at least one of the + // event's nonces must be valid + if ext.ethereum_events.iter().any(|event| { + self.wl_storage .ethbridge_queries() .validate_eth_event_nonce(event) - { - Ok(()) - } else { - Err(VoteExtensionError::InvalidEthEventNonce) - } - }) + }) { + Ok(()) + } else { + Err(VoteExtensionError::InvalidEthEventNonce) + } } /// Checks the channel from the Ethereum oracle monitoring From 80781cbe35fab45e8b2b45e282c5f9b653f6ec04 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 20 Oct 2023 15:00:19 +0100 Subject: [PATCH 16/54] Fix unit tests --- .../src/lib/node/ledger/shell/finalize_block.rs | 2 +- .../ledger/shell/vote_extensions/eth_events.rs | 17 ++++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index 53252065f1..c25b867756 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -1760,7 +1760,7 @@ mod test_finalize_block { transfer }; let ethereum_event = EthereumEvent::TransfersToEthereum { - nonce: 0u64.into(), + nonce: 1u64.into(), transfers: vec![transfer], relayer: bertha, }; diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs index e1206e3a56..0ec5c50e71 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs @@ -526,7 +526,12 @@ mod test_vote_extensions { nonce: 0.into(), transfers: vec![], }; + let event_4 = EthereumEvent::TransfersToNamada { + nonce: 1.into(), + transfers: vec![], + }; + // send valid events tokio_test::block_on(oracle.send(event_1.clone())) .expect("Test failed"); tokio_test::block_on(oracle.send(event_3.clone())) @@ -542,16 +547,22 @@ mod test_vote_extensions { .collect(); assert_eq!(expected_events, got_events); + // we cannot get two transfer to ethereum events within + // the same block height on ethereum. this is because we + // require a confirmation eth event on namada to increment + // the bridge pool nonce. this event should get ignored + tokio_test::block_on(oracle.send(event_2)).expect("Test failed"); + // check that we queue and de-duplicate events - tokio_test::block_on(oracle.send(event_2.clone())) - .expect("Test failed"); tokio_test::block_on(oracle.send(event_3.clone())) .expect("Test failed"); + tokio_test::block_on(oracle.send(event_4.clone())) + .expect("Test failed"); let got_events: [EthereumEvent; 3] = shell.new_ethereum_events().try_into().expect("Test failed"); let expected_events: Vec<_> = - std::collections::BTreeSet::from([event_1, event_2, event_3]) + std::collections::BTreeSet::from([event_1, event_3, event_4]) .into_iter() .collect(); assert_eq!(expected_events, got_events); From 0c0c80194b7b1bc4a42cc71c92c99f1b9e0de3f5 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 23 Oct 2023 11:18:07 +0100 Subject: [PATCH 17/54] Test replaying eth events with outdated nonces --- .../transactions/ethereum_events/mod.rs | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs index 3c5090bb7f..e9ff768fa0 100644 --- a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs +++ b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs @@ -872,4 +872,89 @@ mod tests { (_, Some(_)) => {} }); } + + /// Test that [`MultiSignedEthEvent`]s with outdated nonces do + /// not result in votes in storage. + #[test] + fn test_apply_derived_tx_outdated_nonce() -> Result<()> { + let (mut wl_storage, _) = test_utils::setup_default_storage(); + + let new_multisigned = |nonce: u64| { + let (validator, _) = test_utils::default_validator(); + let event = EthereumEvent::TransfersToNamada { + nonce: nonce.into(), + transfers: vec![TransferToNamada { + amount: Amount::from(100), + asset: DAI_ERC20_ETH_ADDRESS, + receiver: validator.clone(), + }], + }; + let signers = BTreeSet::from([(validator, BlockHeight(100))]); + ( + MultiSignedEthEvent { + event: event.clone(), + signers, + }, + event, + ) + }; + macro_rules! nonce_ok { + ($nonce:expr) => { + let (multisigned, event) = new_multisigned($nonce); + let tx_result = + apply_derived_tx(&mut wl_storage, vec![multisigned])?; + + let eth_msg_keys = vote_tallies::Keys::from(&event); + assert!( + tx_result.changed_keys.contains(ð_msg_keys.seen()), + "The Ethereum event should have been seen", + ); + assert_eq!( + wl_storage + .ethbridge_queries() + .get_next_nam_transfers_nonce(), + ($nonce + 1).into(), + "The transfers to Namada nonce should have been \ + incremented", + ); + }; + } + macro_rules! nonce_err { + ($nonce:expr) => { + let (multisigned, event) = new_multisigned($nonce); + let tx_result = + apply_derived_tx(&mut wl_storage, vec![multisigned])?; + + let eth_msg_keys = vote_tallies::Keys::from(&event); + assert!( + !tx_result.changed_keys.contains(ð_msg_keys.seen()), + "The Ethereum event should have been ignored", + ); + assert_eq!( + wl_storage + .ethbridge_queries() + .get_next_nam_transfers_nonce(), + NEXT_NONCE_TO_PROCESS.into(), + "The transfers to Namada nonce should not have changed", + ); + }; + } + + // update storage with valid events + const NEXT_NONCE_TO_PROCESS: u64 = 3; + for nonce in 0..NEXT_NONCE_TO_PROCESS { + nonce_ok!(nonce); + } + + // attempts to replay events with older nonces should + // result in the events getting ignored + for nonce in 0..NEXT_NONCE_TO_PROCESS { + nonce_err!(nonce); + } + + // process new valid event + nonce_ok!(NEXT_NONCE_TO_PROCESS); + + Ok(()) + } } From dd487fa40dd1f57c85642c63132f1270280529dc Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 23 Oct 2023 14:16:34 +0100 Subject: [PATCH 18/54] Test eth events with outdated nonces during CheckTx --- apps/src/lib/node/ledger/shell/mod.rs | 69 +++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index f32633935b..0dee860735 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -2201,6 +2201,75 @@ mod abciplus_mempool_tests { ); } + /// Test that Ethereum events with outdated nonces are + /// not validated by `CheckTx`. + #[test] + fn test_outdated_nonce_mempool_validate() { + use namada::types::storage::InnerEthEventsQueue; + + const LAST_HEIGHT: BlockHeight = BlockHeight(3); + + let (mut shell, _recv, _, _) = test_utils::setup_at_height(LAST_HEIGHT); + shell + .wl_storage + .storage + .eth_events_queue + // sent transfers to namada nonce to 5 + .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); + + let (protocol_key, _, _) = wallet::defaults::validator_keys(); + + // only bad events + { + let ethereum_event = EthereumEvent::TransfersToNamada { + nonce: 3u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr: wallet::defaults::validator_address(), + block_height: LAST_HEIGHT, + ethereum_events: vec![ethereum_event], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let rsp = shell.mempool_validate(&tx, Default::default()); + assert!(rsp.code != 0, "Validation should have failed"); + } + + // at least one good event + { + let e1 = EthereumEvent::TransfersToNamada { + nonce: 3u64.into(), + transfers: vec![], + }; + let e2 = EthereumEvent::TransfersToNamada { + nonce: 5u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr: wallet::defaults::validator_address(), + block_height: LAST_HEIGHT, + ethereum_events: vec![e1, e2], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let rsp = shell.mempool_validate(&tx, Default::default()); + assert!(rsp.code == 0, "Validation should have passed"); + } + } + /// Test that we do not include protocol txs in the mempool, /// voting on ethereum events or signing bridge pool roots /// and nonces if the bridge is inactive. From adac29f81278fd5031ec491a2250b05e21ac8049 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 23 Oct 2023 14:16:42 +0100 Subject: [PATCH 19/54] Test eth events with outdated nonces during PrepareProposal --- .../lib/node/ledger/shell/prepare_proposal.rs | 117 +++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index 3687a6d39b..9e7ba6b373 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -514,10 +514,12 @@ mod test_prepare_proposal { #[cfg(feature = "abcipp")] use namada::types::key::common; use namada::types::key::RefTo; - use namada::types::storage::BlockHeight; + use namada::types::storage::{BlockHeight, InnerEthEventsQueue}; use namada::types::token; use namada::types::token::Amount; - use namada::types::transaction::protocol::EthereumTxData; + use namada::types::transaction::protocol::{ + ethereum_tx_data_variants, EthereumTxData, + }; use namada::types::transaction::{Fee, TxType, WrapperTx}; #[cfg(feature = "abcipp")] use namada::types::vote_extensions::bridge_pool_roots; @@ -1652,4 +1654,115 @@ mod test_prepare_proposal { eprintln!("Proposal: {:?}", result.txs); assert!(result.txs.is_empty()); } + + /// Test that Ethereum events with outdated nonces are + /// not proposed during `PrepareProposal`. + #[test] + fn test_outdated_nonce_proposal() { + const LAST_HEIGHT: BlockHeight = BlockHeight(3); + + let (mut shell, _recv, _, _) = test_utils::setup_at_height(LAST_HEIGHT); + shell + .wl_storage + .storage + .eth_events_queue + // sent transfers to namada nonce to 5 + .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); + + let (protocol_key, _, _) = wallet::defaults::validator_keys(); + let validator_addr = wallet::defaults::validator_address(); + + // test an extension containing solely events with + // bad nonces + { + let ethereum_event = EthereumEvent::TransfersToNamada { + // outdated nonce (3 < 5) + nonce: 3u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr: validator_addr.clone(), + block_height: LAST_HEIGHT, + ethereum_events: vec![ethereum_event], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let req = RequestPrepareProposal { + txs: vec![tx], + ..Default::default() + }; + let proposed_txs = + shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| { + Tx::try_from(tx_bytes.as_slice()).expect("Test failed") + }); + // since no events with valid nonces are contained in the vote + // extension, we drop it from the proposal + for tx in proposed_txs { + if ethereum_tx_data_variants::EthEventsVext::try_from(&tx) + .is_ok() + { + panic!( + "No ethereum events should have been found in the \ + proposal" + ); + } + } + } + + // test an extension containing at least one event + // with a good nonce + { + let event1 = EthereumEvent::TransfersToNamada { + // outdated nonce (3 < 5) + nonce: 3u64.into(), + transfers: vec![], + }; + let event2 = EthereumEvent::TransfersToNamada { + // outdated nonce (10 >= 5) + nonce: 10u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr, + block_height: LAST_HEIGHT, + ethereum_events: vec![event1, event2.clone()], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let req = RequestPrepareProposal { + txs: vec![tx], + ..Default::default() + }; + let proposed_txs = + shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| { + Tx::try_from(tx_bytes.as_slice()).expect("Test failed") + }); + // find the event with the good nonce + let mut ext = 'ext: { + for tx in proposed_txs { + if let Ok(ext) = + ethereum_tx_data_variants::EthEventsVext::try_from(&tx) + { + break 'ext ext; + } + } + panic!("No ethereum events found in proposal"); + }; + assert_eq!(ext.data.ethereum_events.len(), 2); + let found_event = ext.data.ethereum_events.remove(1); + assert_eq!(found_event, event2); + } + } } From df9c8ce3c3c1489da15e3f894914ebe54b38251b Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 23 Oct 2023 14:21:09 +0100 Subject: [PATCH 20/54] Test eth events with outdated nonces during ProcessProposal --- .../lib/node/ledger/shell/process_proposal.rs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index ab544de3f8..f81445aab8 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -2912,4 +2912,76 @@ mod test_process_proposal { ); } } + + /// Test that Ethereum events with outdated nonces are + /// not validated by `ProcessProposal`. + #[test] + fn test_outdated_nonce_process_proposal() { + use namada::types::storage::InnerEthEventsQueue; + + const LAST_HEIGHT: BlockHeight = BlockHeight(3); + + let (mut shell, _recv, _, _) = test_utils::setup_at_height(LAST_HEIGHT); + shell + .wl_storage + .storage + .eth_events_queue + // sent transfers to namada nonce to 5 + .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); + + let (protocol_key, _, _) = wallet::defaults::validator_keys(); + + // only bad events + { + let ethereum_event = EthereumEvent::TransfersToNamada { + // outdated nonce (3 < 5) + nonce: 3u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr: wallet::defaults::validator_address(), + block_height: LAST_HEIGHT, + ethereum_events: vec![ethereum_event], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let req = ProcessProposal { txs: vec![tx] }; + let rsp = shell.process_proposal(req); + assert!(rsp.is_err()); + } + + // at least one good event + { + let e1 = EthereumEvent::TransfersToNamada { + nonce: 3u64.into(), + transfers: vec![], + }; + let e2 = EthereumEvent::TransfersToNamada { + nonce: 5u64.into(), + transfers: vec![], + }; + let ext = { + let ext = ethereum_events::Vext { + validator_addr: wallet::defaults::validator_address(), + block_height: LAST_HEIGHT, + ethereum_events: vec![e1, e2], + } + .sign(&protocol_key); + assert!(ext.verify(&protocol_key.ref_to()).is_ok()); + ext + }; + let tx = EthereumTxData::EthEventsVext(ext) + .sign(&protocol_key, shell.chain_id.clone()) + .to_bytes(); + let req = ProcessProposal { txs: vec![tx] }; + let rsp = shell.process_proposal(req); + assert!(rsp.is_ok()); + } + } } From 4dbc621a0ee63c5b1dd37a78123915866b56a2b7 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Mon, 23 Oct 2023 14:30:52 +0100 Subject: [PATCH 21/54] Changelog for #2035 --- .changelog/unreleased/bug-fixes/2035-outdated-eth-nonces.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/2035-outdated-eth-nonces.md diff --git a/.changelog/unreleased/bug-fixes/2035-outdated-eth-nonces.md b/.changelog/unreleased/bug-fixes/2035-outdated-eth-nonces.md new file mode 100644 index 0000000000..b0d728eaaf --- /dev/null +++ b/.changelog/unreleased/bug-fixes/2035-outdated-eth-nonces.md @@ -0,0 +1,2 @@ +- Fix Ethereum event validation/state updates when more than one validator is + running the chain ([\#2035](https://github.com/anoma/namada/pull/2035)) \ No newline at end of file From b3a240d9b64abea6af2fbdddb6c19af1a0582d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 10:02:14 +0100 Subject: [PATCH 22/54] wasm: add validator support to vp_user --- wasm/wasm_source/src/vp_user.rs | 304 ++++++++++++++++++++++++++++++-- 1 file changed, 286 insertions(+), 18 deletions(-) diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index 28bfcbdc9f..c6b7d6920e 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -1,16 +1,20 @@ -//! A basic user VP. +//! A basic user VP supports both non-validator and validator accounts. //! //! This VP currently provides a signature verification against a public key for //! sending tokens (receiving tokens is permissive). //! //! It allows to bond, unbond and withdraw tokens to and from PoS system with a -//! valid signature. +//! valid signature(s). +//! +//! For validator a tx to change a validator's commission rate or metadata +//! requires a valid signature(s) only from the validator. //! //! Any other storage key changes are allowed only with a valid signature. use namada_vp_prelude::storage::KeySeg; use namada_vp_prelude::*; use once_cell::unsync::Lazy; +use proof_of_stake::types::ValidatorState; enum KeyType<'a> { Token { owner: &'a Address }, @@ -104,14 +108,14 @@ fn validate_tx( } } KeyType::PoS => { - // Allow the account to be used in PoS + // Bond or unbond let bond_id = proof_of_stake::storage::is_bond_key(key) .map(|(bond_id, _)| bond_id) .or_else(|| { proof_of_stake::storage::is_unbond_key(key) .map(|(bond_id, _, _)| bond_id) }); - let valid = match bond_id { + let valid_bond_or_unbond_change = match bond_id { Some(bond_id) => { // Bonds and unbonds changes for this address // must be signed @@ -122,12 +126,81 @@ fn validate_tx( true } }; - debug_log!( - "PoS key {} {}", - key, - if valid { "accepted" } else { "rejected" } - ); - valid + // Commission rate changes must be signed by the validator + let comm = + proof_of_stake::storage::is_validator_commission_rate_key( + key, + ); + let valid_commission_rate_change = match comm { + Some((validator, _epoch)) => { + *validator == addr && *valid_sig + } + None => true, + }; + // Metadata changes must be signed by the validator whose + // metadata is manipulated + let metadata = + proof_of_stake::storage::is_validator_metadata_key(key); + let valid_metadata_change = match metadata { + Some(address) => *address == addr && *valid_sig, + None => true, + }; + + // Changes due to unjailing, deactivating, and reactivating are + // marked by changes in validator state + let state_change = + proof_of_stake::storage::is_validator_state_key(key); + let valid_state_change = match state_change { + Some((address, epoch)) => { + let params_pre = + proof_of_stake::read_pos_params(&ctx.pre())?; + let state_pre = + proof_of_stake::validator_state_handle(address) + .get(&ctx.pre(), epoch, ¶ms_pre)?; + + let params_post = + proof_of_stake::read_pos_params(&ctx.post())?; + let state_post = + proof_of_stake::validator_state_handle(address) + .get(&ctx.post(), epoch, ¶ms_post)?; + + match (state_pre, state_post) { + (Some(pre), Some(post)) => { + if + // Deactivation case + (matches!( + pre, + ValidatorState::Consensus + | ValidatorState::BelowCapacity + | ValidatorState::BelowThreshold + ) && post == ValidatorState::Inactive) + // Reactivation case + || pre == ValidatorState::Inactive + && post != ValidatorState::Inactive + // Unjail case + || pre == ValidatorState::Jailed + && matches!( + post, + ValidatorState::Consensus + | ValidatorState::BelowCapacity + | ValidatorState::BelowThreshold + ) + { + *address == addr && *valid_sig + } else { + true + } + } + _ => true, + } + } + None => true, + }; + + valid_bond_or_unbond_change + && valid_commission_rate_change + && valid_state_change + && valid_metadata_change } KeyType::GovernanceVote(voter) => { if voter == &addr { @@ -398,10 +471,10 @@ mod tests { ); } - /// Test that a PoS action that must be authorized is rejected without a - /// valid signature. + /// Test that a non-validator PoS action that must be authorized is rejected + /// without a valid signature. #[test] - fn test_unsigned_pos_action_rejected() { + fn test_unsigned_non_validator_pos_action_rejected() { // Init PoS genesis let pos_params = PosParams::default(); let validator = address::testing::established_address_3(); @@ -454,7 +527,7 @@ mod tests { // be able to transfer from it tx_env.credit_tokens(&vp_owner, &token, amount); - // Initialize VP environment from a transaction + // Initialize VP environment from non-validator PoS actions vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { // Bond the tokens, then unbond some of them tx::ctx() @@ -478,10 +551,100 @@ mod tests { ); } - /// Test that a PoS action that must be authorized is accepted with a valid - /// signature. + /// Test that a validator PoS action that must be authorized is rejected + /// without a valid signature. + #[test] + fn test_unsigned_validator_pos_action_rejected() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); + let eth_hot_key = key::testing::keypair_4().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator.clone(), + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key, + eth_cold_key, + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let target = address::testing::established_address_3(); + let token = address::nam(); + let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); + let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); + let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&target, &token]); + tx_env.init_account_storage(&validator, vec![public_key], 1); + // write the denomination of NAM into storage + storage_api::token::write_denom( + &mut tx_env.wl_storage, + &token, + token::NATIVE_MAX_DECIMAL_PLACES.into(), + ) + .unwrap(); + + // Credit the tokens to the validator before running the transaction to + // be able to transfer from it + tx_env.credit_tokens(&validator, &token, amount); + + // Validator PoS actions + vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { + // Bond the tokens, then unbond some of them + tx::ctx() + .bond_tokens(Some(&validator), &validator, bond_amount) + .unwrap(); + tx::ctx() + .unbond_tokens(Some(&validator), &validator, unbond_amount) + .unwrap(); + tx::ctx().deactivate_validator(&validator).unwrap(); + tx::ctx() + .change_validator_metadata( + &validator, + Some("email".to_owned()), + Some("desc".to_owned()), + Some("website".to_owned()), + Some("discord".to_owned()), + Some(Dec::new(6, 2).unwrap()), + ) + .unwrap(); + }); + + let vp_env = vp_host_env::take(); + let mut tx_data = Tx::from_type(TxType::Raw); + tx_data.set_data(Data::new(vec![])); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + !validate_tx(&CTX, tx_data, validator, keys_changed, verifiers) + .unwrap() + ); + } + + /// Test that a non-validator PoS action that must be authorized is accepted + /// with a valid signature. #[test] - fn test_signed_pos_action_accepted() { + fn test_signed_non_validator_pos_action_accepted() { // Init PoS genesis let pos_params = PosParams::default(); let validator = address::testing::established_address_3(); @@ -539,7 +702,7 @@ mod tests { // be able to transfer from it tx_env.credit_tokens(&vp_owner, &token, amount); - // Initialize VP environment from a transaction + // Initialize VP environment from non-validator PoS actions vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { // Bond the tokens, then unbond some of them tx::ctx() @@ -573,6 +736,111 @@ mod tests { ); } + /// Test that a validator PoS action that must be authorized is accepted + /// with a valid signature. + #[test] + fn test_signed_validator_pos_action_accepted() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator.clone(), + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key: key::common::PublicKey::Secp256k1( + key::testing::gen_keypair::() + .ref_to(), + ), + eth_cold_key: key::common::PublicKey::Secp256k1( + key::testing::gen_keypair::() + .ref_to(), + ), + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let target = address::testing::established_address_3(); + let token = address::nam(); + let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); + let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); + let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); + + // Spawn the accounts to be able to modify their storage + tx_env.spawn_accounts([&target, &token]); + tx_env.init_account_storage(&validator, vec![public_key.clone()], 1); + + // write the denomination of NAM into storage + storage_api::token::write_denom( + &mut tx_env.wl_storage, + &token, + token::NATIVE_MAX_DECIMAL_PLACES.into(), + ) + .unwrap(); + + // Credit the tokens to the VP owner before running the transaction to + // be able to transfer from it + tx_env.credit_tokens(&validator, &token, amount); + + // Validator PoS actions + vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { + // Bond the tokens, then unbond some of them + tx::ctx() + .bond_tokens(Some(&validator), &validator, bond_amount) + .unwrap(); + tx::ctx() + .unbond_tokens(Some(&validator), &validator, unbond_amount) + .unwrap(); + tx::ctx().deactivate_validator(&validator).unwrap(); + tx::ctx() + .change_validator_metadata( + &validator, + Some("email".to_owned()), + Some("desc".to_owned()), + Some("website".to_owned()), + Some("discord".to_owned()), + Some(Dec::new(6, 2).unwrap()), + ) + .unwrap(); + }); + + let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); + + let mut vp_env = vp_host_env::take(); + let mut tx = vp_env.tx.clone(); + tx.set_data(Data::new(vec![])); + tx.set_code(Code::new(vec![], None)); + tx.add_section(Section::Signature(Signature::new( + vec![tx.raw_header_hash()], + pks_map.index_secret_keys(vec![secret_key]), + None, + ))); + let signed_tx = tx.clone(); + vp_env.tx = signed_tx.clone(); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + validate_tx(&CTX, signed_tx, validator, keys_changed, verifiers) + .unwrap() + ); + } + /// Test that a transfer on with accounts other than self is accepted. #[test] fn test_transfer_between_other_parties_accepted() { From 0cd12bb685aab39891ffa8ab84c8aedfd29691de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 10:11:48 +0100 Subject: [PATCH 23/54] remove vp_validator and replace usage with vp_user --- apps/src/lib/bench_utils.rs | 2 +- apps/src/lib/config/genesis.rs | 2 +- apps/src/lib/config/genesis/transactions.rs | 2 +- benches/host_env.rs | 4 +- benches/txs.rs | 14 +- benches/vps.rs | 10 +- genesis/README.md | 2 +- genesis/localnet/validity-predicates.toml | 4 - genesis/starter/validity-predicates.toml | 4 - sdk/src/lib.rs | 11 +- sdk/src/signing.rs | 7 - sdk/src/tx.rs | 2 - wasm/wasm_source/Cargo.toml | 1 - wasm/wasm_source/Makefile | 1 - wasm/wasm_source/src/lib.rs | 2 - wasm/wasm_source/src/vp_validator.rs | 1135 ------------------- 16 files changed, 23 insertions(+), 1180 deletions(-) delete mode 100644 wasm/wasm_source/src/vp_validator.rs diff --git a/apps/src/lib/bench_utils.rs b/apps/src/lib/bench_utils.rs index 551bf49abd..a718cacbed 100644 --- a/apps/src/lib/bench_utils.rs +++ b/apps/src/lib/bench_utils.rs @@ -90,7 +90,7 @@ pub use namada_sdk::tx::{ TX_RESIGN_STEWARD, TX_REVEAL_PK as TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL as TX_VOTE_PROPOSAL_WASM, - TX_WITHDRAW_WASM, VP_USER_WASM, VP_VALIDATOR_WASM, + TX_WITHDRAW_WASM, VP_USER_WASM, }; use namada_sdk::wallet::Wallet; use namada_sdk::NamadaImpl; diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index b1fac85e81..32d2fcf3ae 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -380,7 +380,7 @@ pub fn make_dev_genesis( address, tx: transactions::ValidatorAccountTx { alias: alias.clone(), - vp: "vp_validator".to_string(), + vp: "vp_user".to_string(), commission_rate: Dec::new(5, 2).expect("This can't fail"), max_commission_rate_change: Dec::new(1, 2) .expect("This can't fail"), diff --git a/apps/src/lib/config/genesis/transactions.rs b/apps/src/lib/config/genesis/transactions.rs index d457ef87f5..b617b5a3bf 100644 --- a/apps/src/lib/config/genesis/transactions.rs +++ b/apps/src/lib/config/genesis/transactions.rs @@ -153,7 +153,7 @@ pub fn init_validator( validator_wallet.eth_cold_key.ref_to(), ), // No custom validator VPs yet - vp: "vp_validator".to_string(), + vp: "vp_user".to_string(), commission_rate, max_commission_rate_change, email, diff --git a/benches/host_env.rs b/benches/host_env.rs index 3b096f11ec..289b0eb564 100644 --- a/benches/host_env.rs +++ b/benches/host_env.rs @@ -9,7 +9,7 @@ use namada::proto::Signature; use namada::vm::wasm::TxCache; use namada_apps::bench_utils::{ BenchShell, TX_INIT_PROPOSAL_WASM, TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, - TX_UPDATE_ACCOUNT_WASM, VP_VALIDATOR_WASM, WASM_DIR, + TX_UPDATE_ACCOUNT_WASM, VP_USER_WASM, WASM_DIR, }; use namada_apps::wallet::defaults; use namada_apps::wasm_loader; @@ -68,7 +68,7 @@ fn compile_wasm(c: &mut Criterion) { TX_INIT_PROPOSAL_WASM, TX_REVEAL_PK_WASM, TX_UPDATE_ACCOUNT_WASM, - VP_VALIDATOR_WASM, + VP_USER_WASM, ] { let wasm_code = wasm_loader::read_wasm_or_exit(WASM_DIR, tx); txs.insert(tx, wasm_code); diff --git a/benches/txs.rs b/benches/txs.rs index 02d6c9c22d..98f4d45a9d 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -51,7 +51,7 @@ use namada_apps::bench_utils::{ TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, - TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_VALIDATOR_WASM, + TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_USER_WASM, }; use namada_apps::wallet::defaults; use sha2::Digest; @@ -369,11 +369,11 @@ fn reveal_pk(c: &mut Criterion) { fn update_account(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::albert_address(), @@ -412,11 +412,11 @@ fn init_account(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let extra_hash = Hash( extra_section @@ -613,11 +613,11 @@ fn init_validator(c: &mut Criterion) { let shell = BenchShell::default(); let validator_vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( validator_vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let extra_hash = Hash( extra_section diff --git a/benches/vps.rs b/benches/vps.rs index d101b2a4a9..366887d1fa 100644 --- a/benches/vps.rs +++ b/benches/vps.rs @@ -22,7 +22,7 @@ use namada_apps::bench_utils::{ generate_foreign_key_tx, BenchShell, TX_BOND_WASM, TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL_WASM, - VP_USER_WASM, VP_VALIDATOR_WASM, + VP_USER_WASM, }; use namada_apps::wallet::defaults; use sha2::Digest; @@ -70,11 +70,11 @@ fn vp_user(c: &mut Criterion) { ); let vp_validator_hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let extra_section = Section::ExtraData(Code::from_hash( vp_validator_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::albert_address(), @@ -322,7 +322,7 @@ fn vp_implicit(c: &mut Criterion) { fn vp_validator(c: &mut Criterion) { let shell = BenchShell::default(); let vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_VALIDATOR_WASM)) + .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) .unwrap(); let mut group = c.benchmark_group("vp_validator"); @@ -361,7 +361,7 @@ fn vp_validator(c: &mut Criterion) { let extra_section = Section::ExtraData(Code::from_hash( vp_code_hash, - Some(VP_VALIDATOR_WASM.to_string()), + Some(VP_USER_WASM.to_string()), )); let data = UpdateAccount { addr: defaults::validator_address(), diff --git a/genesis/README.md b/genesis/README.md index 894e3d602c..1aec869104 100644 --- a/genesis/README.md +++ b/genesis/README.md @@ -56,7 +56,7 @@ An unsigned `validator_account` tx example: ```toml [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" net_address = "127.0.0.1:27656" diff --git a/genesis/localnet/validity-predicates.toml b/genesis/localnet/validity-predicates.toml index 907e7c522b..0216abe982 100644 --- a/genesis/localnet/validity-predicates.toml +++ b/genesis/localnet/validity-predicates.toml @@ -8,7 +8,3 @@ filename = "vp_implicit.wasm" [wasm.vp_user] filename = "vp_user.wasm" -# Default validator VP -[wasm.vp_validator] -filename = "vp_validator.wasm" - diff --git a/genesis/starter/validity-predicates.toml b/genesis/starter/validity-predicates.toml index 9c9e76fc83..242cc1c5c5 100644 --- a/genesis/starter/validity-predicates.toml +++ b/genesis/starter/validity-predicates.toml @@ -8,10 +8,6 @@ filename = "vp_implicit.wasm" [wasm.vp_user] filename = "vp_user.wasm" -# Default validator VP -[wasm.vp_validator] -filename = "vp_validator.wasm" - # Token VP [wasm.vp_token] filename = "vp_token.wasm" diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index f5c0ae37fa..b7b549f5d6 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -3,7 +3,6 @@ extern crate alloc; pub use namada_core::{ibc, ibc_proto, proto, tendermint, tendermint_proto}; #[cfg(feature = "tendermint-rpc")] pub use tendermint_rpc; -use tx::{TX_INIT_ACCOUNT_WASM, VP_VALIDATOR_WASM}; pub use { bip39, borsh, masp_primitives, masp_proofs, namada_core as core, namada_proof_of_stake as proof_of_stake, zeroize, @@ -55,10 +54,10 @@ use crate::tx::{ ProcessTxResponse, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, - TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_PROPOSAL, - TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, - TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, - TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, + TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, + TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, + TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, + TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, }; @@ -366,7 +365,7 @@ pub trait Namada<'a>: Sized { eth_cold_key: None, eth_hot_key: None, protocol_key: None, - validator_vp_code_path: PathBuf::from(VP_VALIDATOR_WASM), + validator_vp_code_path: PathBuf::from(VP_USER_WASM), unsafe_dont_encrypt: false, tx_code_path: PathBuf::from(TX_INIT_VALIDATOR_WASM), tx: self.tx_builder(), diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index 6784be92ba..c6262d9dd0 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -54,7 +54,6 @@ use crate::tx::{ TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, - VP_VALIDATOR_WASM, }; pub use crate::wallet::store::AddressVpType; use crate::wallet::{Wallet, WalletIo}; @@ -1067,8 +1066,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; @@ -1113,8 +1110,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; @@ -1314,8 +1309,6 @@ pub async fn to_ledger_vector<'a>( })?; let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { "User".to_string() - } else if extra.tag == Some(VP_VALIDATOR_WASM.to_string()) { - "Validator".to_string() } else { HEXLOWER.encode(&extra.code.hash().0) }; diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index 9378615890..e26bbff4e2 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -92,8 +92,6 @@ pub const TX_TRANSFER_WASM: &str = "tx_transfer.wasm"; pub const TX_IBC_WASM: &str = "tx_ibc.wasm"; /// User validity predicate WASM path pub const VP_USER_WASM: &str = "vp_user.wasm"; -/// Validator validity predicate WASM path -pub const VP_VALIDATOR_WASM: &str = "vp_validator.wasm"; /// Bond WASM path pub const TX_BOND_WASM: &str = "tx_bond.wasm"; /// Unbond WASM path diff --git a/wasm/wasm_source/Cargo.toml b/wasm/wasm_source/Cargo.toml index 8e8e3efe4e..c4025c1207 100644 --- a/wasm/wasm_source/Cargo.toml +++ b/wasm/wasm_source/Cargo.toml @@ -38,7 +38,6 @@ tx_resign_steward = ["namada_tx_prelude"] vp_implicit = ["namada_vp_prelude", "once_cell"] vp_token = ["namada_vp_prelude"] vp_user = ["namada_vp_prelude", "once_cell"] -vp_validator = ["namada_vp_prelude", "once_cell"] [dependencies] namada_tx_prelude = {path = "../../tx_prelude", optional = true} diff --git a/wasm/wasm_source/Makefile b/wasm/wasm_source/Makefile index 6772a2e739..2da935ba7c 100644 --- a/wasm/wasm_source/Makefile +++ b/wasm/wasm_source/Makefile @@ -29,7 +29,6 @@ wasms += tx_update_steward_commission wasms += tx_resign_steward wasms += vp_implicit wasms += vp_user -wasms += vp_validator # Build all wasms in release mode all: $(wasms) diff --git a/wasm/wasm_source/src/lib.rs b/wasm/wasm_source/src/lib.rs index ae3d121f2c..e44ac1564e 100644 --- a/wasm/wasm_source/src/lib.rs +++ b/wasm/wasm_source/src/lib.rs @@ -47,5 +47,3 @@ pub mod tx_withdraw; pub mod vp_implicit; #[cfg(feature = "vp_user")] pub mod vp_user; -#[cfg(feature = "vp_validator")] -pub mod vp_validator; diff --git a/wasm/wasm_source/src/vp_validator.rs b/wasm/wasm_source/src/vp_validator.rs deleted file mode 100644 index 2c104c13d8..0000000000 --- a/wasm/wasm_source/src/vp_validator.rs +++ /dev/null @@ -1,1135 +0,0 @@ -//! A basic validator VP. -//! -//! Like the user VP, this VP currently provides a signature verification -//! against a public key for sending tokens (receiving tokens is permissive). -//! -//! It allows to bond, unbond and withdraw tokens to and from PoS system with a -//! valid signature. -//! -//! Currently, the only difference with respect to the user VP is for a tx to -//! change a validator's commission rate: we require a valid signature only from -//! the validator whose commission rate is being changed. -//! -//! Any other storage key changes are allowed only with a valid signature. - -use namada_vp_prelude::storage::KeySeg; -use namada_vp_prelude::*; -use once_cell::unsync::Lazy; -use proof_of_stake::types::ValidatorState; - -enum KeyType<'a> { - Token { owner: &'a Address }, - PoS, - Vp(&'a Address), - PgfStward(&'a Address), - GovernanceVote(&'a Address), - Unknown, -} - -impl<'a> From<&'a storage::Key> for KeyType<'a> { - fn from(key: &'a storage::Key) -> KeyType<'a> { - if let Some([_, owner]) = token::is_any_token_balance_key(key) { - Self::Token { owner } - } else if proof_of_stake::storage::is_pos_key(key) { - Self::PoS - } else if gov_storage::keys::is_vote_key(key) { - let voter_address = gov_storage::keys::get_voter_address(key); - if let Some(address) = voter_address { - Self::GovernanceVote(address) - } else { - Self::Unknown - } - } else if let Some(address) = pgf_storage::keys::is_stewards_key(key) { - Self::PgfStward(address) - } else if let Some(address) = key.is_validity_predicate() { - Self::Vp(address) - } else { - Self::Unknown - } - } -} - -#[validity_predicate(gas = 134761)] -fn validate_tx( - ctx: &Ctx, - tx_data: Tx, - addr: Address, - keys_changed: BTreeSet, - verifiers: BTreeSet
, -) -> VpResult { - debug_log!( - "vp_validator called with user addr: {}, key_changed: {:?}, \ - verifiers: {:?}", - addr, - keys_changed, - verifiers - ); - - let valid_sig = Lazy::new(|| { - matches!(verify_signatures(ctx, &tx_data, &addr), Ok(true)) - }); - - if !is_valid_tx(ctx, &tx_data)? { - return reject(); - } - - for key in keys_changed.iter() { - let key_type: KeyType = key.into(); - let is_valid = match key_type { - KeyType::Token { owner, .. } => { - if owner == &addr { - let pre: token::Amount = - ctx.read_pre(key)?.unwrap_or_default(); - let post: token::Amount = - ctx.read_post(key)?.unwrap_or_default(); - let change = post.change() - pre.change(); - // debit has to signed, credit doesn't - let valid = change.non_negative() || *valid_sig; - debug_log!( - "token key: {}, change: {:?}, valid_sig: {}, valid \ - modification: {}", - key, - change, - *valid_sig, - valid - ); - valid - } else { - debug_log!( - "This address ({}) is not of owner ({}) of token key: \ - {}", - addr, - owner, - key - ); - // If this is not the owner, allow any change - true - } - } - KeyType::PoS => { - // Bond or unbond - let bond_id = proof_of_stake::storage::is_bond_key(key) - .map(|(bond_id, _)| bond_id) - .or_else(|| { - proof_of_stake::storage::is_unbond_key(key) - .map(|(bond_id, _, _)| bond_id) - }); - let valid_bond_or_unbond_change = match bond_id { - Some(bond_id) => { - // Bonds and unbonds changes for this address - // must be signed - bond_id.source != addr || *valid_sig - } - None => { - // Any other PoS changes are allowed without signature - true - } - }; - // Commission rate changes must be signed by the validator - let comm = - proof_of_stake::storage::is_validator_commission_rate_key( - key, - ); - let valid_commission_rate_change = match comm { - Some((validator, _epoch)) => { - *validator == addr && *valid_sig - } - None => true, - }; - // Metadata changes must be signed by the validator whose - // metadata is manipulated - let metadata = - proof_of_stake::storage::is_validator_metadata_key(key); - let valid_metadata_change = match metadata { - Some(address) => *address == addr && *valid_sig, - None => true, - }; - - // Changes due to unjailing, deactivating, and reactivating are - // marked by changes in validator state - let state_change = - proof_of_stake::storage::is_validator_state_key(key); - let valid_state_change = match state_change { - Some((address, epoch)) => { - let params_pre = - proof_of_stake::read_pos_params(&ctx.pre())?; - let state_pre = - proof_of_stake::validator_state_handle(address) - .get(&ctx.pre(), epoch, ¶ms_pre)?; - - let params_post = - proof_of_stake::read_pos_params(&ctx.post())?; - let state_post = - proof_of_stake::validator_state_handle(address) - .get(&ctx.post(), epoch, ¶ms_post)?; - - match (state_pre, state_post) { - (Some(pre), Some(post)) => { - if - // Deactivation case - (matches!( - pre, - ValidatorState::Consensus - | ValidatorState::BelowCapacity - | ValidatorState::BelowThreshold - ) && post == ValidatorState::Inactive) - // Reactivation case - || pre == ValidatorState::Inactive - && post != ValidatorState::Inactive - // Unjail case - || pre == ValidatorState::Jailed - && matches!( - post, - ValidatorState::Consensus - | ValidatorState::BelowCapacity - | ValidatorState::BelowThreshold - ) - { - *address == addr && *valid_sig - } else { - true - } - } - _ => true, - } - } - None => true, - }; - - let valid = valid_bond_or_unbond_change - && valid_commission_rate_change - && valid_state_change - && valid_metadata_change; - debug_log!( - "PoS key {} {}", - key, - if valid { "accepted" } else { "rejected" } - ); - valid - } - KeyType::GovernanceVote(voter) => { - if voter == &addr { - *valid_sig - } else { - true - } - } - KeyType::PgfStward(address) => { - if address == &addr { - *valid_sig - } else { - true - } - } - KeyType::Vp(owner) => { - let has_post: bool = ctx.has_key_post(key)?; - if owner == &addr { - if has_post { - let vp_hash: Vec = - ctx.read_bytes_post(key)?.unwrap(); - *valid_sig && is_vp_whitelisted(ctx, &vp_hash)? - } else { - false - } - } else { - let vp_hash: Vec = ctx.read_bytes_post(key)?.unwrap(); - is_vp_whitelisted(ctx, &vp_hash)? - } - } - KeyType::Unknown => { - if key.segments.get(0) == Some(&addr.to_db_key()) { - // Unknown changes to this address space require a valid - // signature - *valid_sig - } else { - // Unknown changes anywhere else are permitted - true - } - } - }; - if !is_valid { - debug_log!("key {} modification failed vp", key); - return reject(); - } - } - - accept() -} - -#[cfg(test)] -mod tests { - use address::testing::arb_non_internal_address; - use namada::ledger::pos::{GenesisValidator, OwnedPosParams}; - use namada::proto::{Code, Data, Signature}; - use namada::types::dec::Dec; - use namada::types::storage::Epoch; - use namada::types::transaction::TxType; - use namada_test_utils::TestWasms; - // Use this as `#[test]` annotation to enable logging - use namada_tests::log::test; - use namada_tests::native_vp::pos::init_pos; - use namada_tests::tx::{self, tx_host_env, TestTxEnv}; - use namada_tests::vp::vp_host_env::storage::Key; - use namada_tests::vp::*; - use namada_tx_prelude::{StorageWrite, TxEnv}; - use namada_vp_prelude::account::AccountPublicKeysMap; - use namada_vp_prelude::key::RefTo; - use proptest::prelude::*; - use storage::testing::arb_account_storage_key_no_vp; - - use super::*; - - /// Test that no-op transaction (i.e. no storage modifications) accepted. - #[test] - fn test_no_op_transaction() { - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let addr: Address = address::testing::established_address_1(); - let keys_changed: BTreeSet = BTreeSet::default(); - let verifiers: BTreeSet
= BTreeSet::default(); - - // The VP env must be initialized before calling `validate_tx` - vp_host_env::init(); - - assert!( - validate_tx(&CTX, tx_data, addr, keys_changed, verifiers).unwrap() - ); - } - - /// Test that a credit transfer is accepted. - #[test] - fn test_credit_transfer_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let source = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &source, &token]); - - // Credit the tokens to the source before running the transaction to be - // able to transfer from it - tx_env.credit_tokens(&source, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - &source, - address, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a debit transfer without a valid signature is rejected. - #[test] - fn test_unsigned_debit_transfer_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let target = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &target, &token]); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - address, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a debit transfer with a valid signature is accepted. - #[test] - fn test_signed_debit_transfer_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let target = address::testing::established_address_2(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &target, &token]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - address, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a PoS action that must be authorized is rejected without a - /// valid signature. - #[test] - fn test_unsigned_pos_action_rejected() { - // Init PoS genesis - let pos_params = OwnedPosParams::default(); - let validator = address::testing::established_address_3(); - let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); - let consensus_key = key::testing::keypair_2().ref_to(); - let protocol_key = key::testing::keypair_1().ref_to(); - let eth_cold_key = key::testing::keypair_3().ref_to(); - let eth_hot_key = key::testing::keypair_4().ref_to(); - let commission_rate = Dec::new(5, 2).unwrap(); - let max_commission_rate_change = Dec::new(1, 2).unwrap(); - - let genesis_validators = [GenesisValidator { - address: validator.clone(), - tokens: initial_stake, - consensus_key, - protocol_key, - commission_rate, - max_commission_rate_change, - eth_hot_key, - eth_cold_key, - metadata: Default::default(), - }]; - - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - - // Initialize a tx environment - let mut tx_env = tx_host_env::take(); - - let secret_key = key::testing::keypair_1(); - let public_key = secret_key.ref_to(); - let vp_owner: Address = address::testing::established_address_2(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); - let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&target, &token]); - tx_env.init_account_storage(&vp_owner, vec![public_key], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&vp_owner, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Bond the tokens, then unbond some of them - tx::ctx() - .bond_tokens(Some(&vp_owner), &validator, bond_amount) - .unwrap(); - tx::ctx() - .unbond_tokens(Some(&vp_owner), &validator, unbond_amount) - .unwrap(); - tx::ctx() - .change_validator_commission_rate( - &validator, - &Dec::new(6, 2).unwrap(), - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a PoS action that must be authorized is accepted with a valid - /// signature. - #[test] - fn test_signed_pos_action_accepted() { - // Init PoS genesis - let pos_params = OwnedPosParams::default(); - let validator = address::testing::established_address_3(); - let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); - let consensus_key = key::testing::keypair_2().ref_to(); - let protocol_key = key::testing::keypair_1().ref_to(); - let commission_rate = Dec::new(5, 2).unwrap(); - let max_commission_rate_change = Dec::new(1, 2).unwrap(); - - let genesis_validators = [GenesisValidator { - address: validator.clone(), - tokens: initial_stake, - consensus_key, - protocol_key, - commission_rate, - max_commission_rate_change, - eth_hot_key: key::common::PublicKey::Secp256k1( - key::testing::gen_keypair::() - .ref_to(), - ), - eth_cold_key: key::common::PublicKey::Secp256k1( - key::testing::gen_keypair::() - .ref_to(), - ), - metadata: Default::default(), - }]; - - init_pos(&genesis_validators[..], &pos_params, Epoch(0)); - - // Initialize a tx environment - let mut tx_env = tx_host_env::take(); - - let secret_key = key::testing::keypair_1(); - let public_key = secret_key.ref_to(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - let bond_amount = token::Amount::from_uint(5_098_123, 0).unwrap(); - let unbond_amount = token::Amount::from_uint(3_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&validator, &target, &token]); - tx_env.init_account_storage(&validator, vec![public_key.clone()], 1); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&validator, &token, amount); - // write the denomination of NAM into storage - storage_api::token::write_denom( - &mut tx_env.wl_storage, - &token, - token::NATIVE_MAX_DECIMAL_PLACES.into(), - ) - .unwrap(); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(validator.clone(), tx_env, |_address| { - // Bond the tokens, then unbond some of them - tx::ctx() - .bond_tokens(Some(&validator), &validator, bond_amount) - .unwrap(); - tx::ctx() - .unbond_tokens(Some(&validator), &validator, unbond_amount) - .unwrap(); - tx::ctx().deactivate_validator(&validator).unwrap(); - tx::ctx() - .change_validator_metadata( - &validator, - Some("email".to_owned()), - Some("desc".to_owned()), - Some("website".to_owned()), - Some("discord".to_owned()), - Some(Dec::new(6, 2).unwrap()), - ) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![secret_key]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, validator, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a transfer on with accounts other than self is accepted. - #[test] - fn test_transfer_between_other_parties_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let source = address::testing::established_address_2(); - let target = address::testing::established_address_3(); - let token = address::nam(); - let amount = token::Amount::from_uint(10_098_123, 0).unwrap(); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner, &source, &target, &token]); - - // Credit the tokens to the VP owner before running the transaction to - // be able to transfer from it - tx_env.credit_tokens(&source, &token, amount); - let amount = token::DenominatedAmount { - amount, - denom: token::NATIVE_MAX_DECIMAL_PLACES.into(), - }; - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - tx::ctx().insert_verifier(address).unwrap(); - // Apply transfer in a transaction - tx_host_env::token::transfer( - tx::ctx(), - &source, - &target, - &token, - amount, - ) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - prop_compose! { - /// Generates an account address and a storage key inside its storage. - fn arb_account_storage_subspace_key() - // Generate an address - (address in arb_non_internal_address()) - // Generate a storage key other than its VP key (VP cannot be - // modified directly via `write`, it has to be modified via - // `tx::update_validity_predicate`. - (storage_key in arb_account_storage_key_no_vp(address.clone()), - // Use the generated address too - address in Just(address)) - -> (Address, Key) { - (address, storage_key) - } - } - - proptest! { - /// Test that an unsigned tx that performs arbitrary storage writes or - /// deletes to the account is rejected. - #[test] - fn test_unsigned_arb_storage_write_rejected( - (vp_owner, storage_key) in arb_account_storage_subspace_key(), - // Generate bytes to write. If `None`, delete from the key instead - storage_value in any::>>(), - ) { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - // Spawn all the accounts in the storage key to be able to modify - // their storage - let storage_key_addresses = storage_key.find_addresses(); - tx_env.spawn_accounts(storage_key_addresses); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Write or delete some data in the transaction - if let Some(value) = &storage_value { - tx::ctx().write(&storage_key, value).unwrap(); - } else { - tx::ctx().delete(&storage_key).unwrap(); - } - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!(!validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers).unwrap()); - } - } - - proptest! { - /// Test that a signed tx that performs arbitrary storage writes or - /// deletes to the account is accepted. - #[test] - fn test_signed_arb_storage_write( - (vp_owner, storage_key) in arb_account_storage_subspace_key(), - // Generate bytes to write. If `None`, delete from the key instead - storage_value in any::>>(), - ) { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - - // Spawn all the accounts in the storage key to be able to modify - // their storage - let storage_key_addresses = storage_key.find_addresses(); - tx_env.spawn_accounts(storage_key_addresses); - - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |_address| { - // Write or delete some data in the transaction - if let Some(value) = &storage_value { - tx::ctx().write(&storage_key, value).unwrap(); - } else { - tx::ctx().delete(&storage_key).unwrap(); - } - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!(validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers).unwrap()); - } - } - - /// Test that a validity predicate update without a valid signature is - /// rejected. - #[test] - fn test_unsigned_vp_update_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let vp_env = vp_host_env::take(); - let mut tx_data = Tx::from_type(TxType::Raw); - tx_data.set_data(Data::new(vec![])); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update with a valid signature is - /// accepted. - #[test] - fn test_signed_vp_update_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - tx_env.init_parameters(None, None, None, None); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update is rejected if not whitelisted - #[test] - fn test_signed_vp_update_not_whitelisted_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - tx_env.init_parameters( - None, - Some(vec!["some_hash".to_string()]), - None, - None, - ); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a validity predicate update is accepted if whitelisted - #[test] - fn test_signed_vp_update_whitelisted_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - None, - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - /// Test that a tx is rejected if not whitelisted - #[test] - fn test_tx_not_whitelisted_rejected() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - Some(vec!["some_hash".to_string()]), - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_data(Data::new(vec![])); - tx.set_code(Code::new(vec![], None)); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - !validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } - - #[test] - fn test_tx_whitelisted_accepted() { - // Initialize a tx environment - let mut tx_env = TestTxEnv::default(); - - let vp_owner = address::testing::established_address_1(); - let keypair = key::testing::keypair_1(); - let public_key = keypair.ref_to(); - let vp_code = TestWasms::VpAlwaysTrue.read_bytes(); - let vp_hash = sha256(&vp_code); - // for the update - tx_env.store_wasm_code(vp_code); - - // hardcoded hash of VP_ALWAYS_TRUE_WASM - tx_env.init_parameters( - None, - Some(vec![vp_hash.to_string()]), - None, - None, - ); - - // Spawn the accounts to be able to modify their storage - tx_env.spawn_accounts([&vp_owner]); - tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); - - // Initialize VP environment from a transaction - vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { - // Update VP in a transaction - tx::ctx() - .update_validity_predicate(address, vp_hash, &None) - .unwrap(); - }); - - let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); - - let mut vp_env = vp_host_env::take(); - let mut tx = vp_env.tx.clone(); - tx.set_code(Code::new(vec![], None)); - tx.set_data(Data::new(vec![])); - tx.add_section(Section::Signature(Signature::new( - vec![tx.raw_header_hash()], - pks_map.index_secret_keys(vec![keypair]), - None, - ))); - let signed_tx = tx.clone(); - vp_env.tx = signed_tx.clone(); - let keys_changed: BTreeSet = - vp_env.all_touched_storage_keys(); - let verifiers: BTreeSet
= BTreeSet::default(); - vp_host_env::set(vp_env); - assert!( - validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) - .unwrap() - ); - } -} From 352c9fc1349720dd0e8ee58c98f8557d9f5ada5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 10:27:39 +0100 Subject: [PATCH 24/54] genesis/localnet: regen validator --- .../pre-genesis/validator-0/transactions.toml | 28 +++++++++--------- .../validator-0/validator-wallet.toml | 12 ++++---- genesis/localnet/transactions.toml | 29 ++++++++++--------- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/genesis/localnet/src/pre-genesis/validator-0/transactions.toml b/genesis/localnet/src/pre-genesis/validator-0/transactions.toml index bd03907dae..85c174edc2 100644 --- a/genesis/localnet/src/pre-genesis/validator-0/transactions.toml +++ b/genesis/localnet/src/pre-genesis/validator-0/transactions.toml @@ -1,34 +1,34 @@ [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" email = "null@null.net" net_address = "127.0.0.1:27656" [validator_account.account_key] -pk = "tpknam1qzuaykg8nrmzuaefut39aaxl0gl66y62285cnwe37gq0a96qaf4qgp5yqtw" -authorization = "signam1qpcvzjdqkvhud9lez3exq3vy7dnp4kyjgsk92yx5cslwzjs0q9czx8ajxztx5pftx9hsf9w2shh6rt0uv6xeyu30ljqkrqj6hnrwn5gqfd9pwf" +pk = "tpknam1qpg2tsrplvhu3fd7z7tq5ztc2ne3s7e2ahjl2a2cddufrzdyr752g666ytj" +authorization = "signam1qzyc89wynvm4n7eq7jglv4d8upaxu38mkkktykjjtgqygmk4sq97ffxermz5wpur4rqr8gk6fze5uvc4u7q4qzqsr285gungdyhv2acgna2ltq" [validator_account.consensus_key] -pk = "tpknam1qpudpptwfh9u5mhvksrguyqk6wvyhus0kf2cs9qr0xuq9k4fepldgqv3ztq" -authorization = "signam1qpuhmvgl330cr3acugaddhn6q9xdw3577h3mv9yszau2smxmn7yvmn2yplfym4sk30r2hz943989sd68umu70e4wsk5q6j2gzzjfg4q0qjvz6f" +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qzt7ww0q00punp93jrvtkq62n4rk8y5d90tllmlkzr0z7urwfdkn7z8ttne92utwskl6ves4qp66r60tg2xqr568ranwfhcm0665wncqq4t5gx" [validator_account.protocol_key] -pk = "tpknam1qzxs6kchkustgjxld3xz0u3c8gfnkvda042vp06auk6zfrru5hhxqqvyxq6" -authorization = "signam1qztaxmfgncmv5jn9tak0au2ryzxwxrlhn2qyfx4fgewuv5p7jelpfpqe9mlp7y73vsw7r8hu509swj8mumgryswu38m7mvxn9asqn0cq7aqvjp" +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qqeaqzj9fu0xsu7pvrkwla5asxde2wak7fslst0p79vxxydt40tzdj54js7dmjvqs2quygqqwup8z2cfffvm86ff8cud6gzel9g40ycw25wp5d" [validator_account.tendermint_node_key] -pk = "tpknam1qzckzn2rc4pr26e0clxajgcllasr6tke4yqrsu7wskw89uka29zykram505" -authorization = "signam1qrgvyj39ljlequl20hx2mz9wpuyjl8lj826c0upy9agt4txuyyusuqkhdmm2aajglupssqcsx8nv62etua6vn0duzrucut4m74nmhscwy3knc3" +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qrq7x5e7svuddy8dyr3xpcdt6a07u6sky0n5qnv5z757g33t5zm3jnnh9uhh073g05n8jx8rmdu5r2djhwh6few6u329u9cld4c7ynsw2592h8" [validator_account.eth_hot_key] -pk = "tpknam1qyp8znkp023autwqh2cy6c6vhnz8vsm4p6w9ngpnnamqk6dj5w6ktxqjnd0qj" -authorization = "signam1q9fd4nkz8df5ajh6jrsn6mrt0apvn4266walr8pnczl0xtn847u6usdemslvusseerhrd6hftse8zfch5tlpmqp4y9xz3563mu0d26hnqq942mt2" +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1qyrvwveg76nrz2ppnsl0em82gcl4p90cqw8eadyzcvk59e2dx0jqja8ln9l9j79sxzhhh5gdggduz78vtthzj5nzs0xvpwhjuh3hymapqq07qxzm" [validator_account.eth_cold_key] -pk = "tpknam1qyp4aw7a07f4ltuq3f0c4sgyq3kzgh6z40w8jt40wl7uhfj7e3m3u9qr792xg" -authorization = "signam1qyqcc7wstsnuadu75jnwg8hxz34nglxj9h9yqyx2c4qqdpxw50ff60hu0swfj7xdkz34tgl9e50jlmzphkgtpw3gg0hsgp35lhsl6rmeqqq28kph" +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1q992kq4ymfl6v8arc2s2tn0w7c4f48wx6fxry9qxv2qk8zvjan8q7j9rxg73cx0f5l56fy53x2jgwv7vy8jtxzucckdzgnxc5tpzajs4qq8r02r2" [[transfer]] token = "nam" @@ -41,4 +41,4 @@ signature = "signam1qz8ch7n6jp7g7hvnzkhmprhqc5umd0gatarlttm7gpcdx6g8hmgqffdq67fn source = "validator-0" validator = "validator-0" amount = "100000" -signature = "signam1qrd7wg2sdla73z7626r2ep8895d9ed4ljq37nz6kmy2rcm36yqjugw6vle7kl70l0d585t382s9vd28k2duwz0lu7ux0vua6aaarjssgdf46n2" +signature = "signam1qqukrz3js2pgzrne90u5f7y4mstrzvmzcq7eelml9m3lzrh9zwpf0vhgjq0rsw4ufj4ffdx8ew74uxkk4df649pg6qq5fgwyqa9mpfcyvskk67" diff --git a/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml b/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml index 4f3db8b8b0..2e0107b173 100644 --- a/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml +++ b/genesis/localnet/src/pre-genesis/validator-0/validator-wallet.toml @@ -1,8 +1,8 @@ -account_key = "unencrypted:00eaa8829ff8932ffad86c4b0ad1ed2f2870c12ca49f03b50e4b34d360daa24268" -consensus_key = "unencrypted:00aabd79879fce99cb528f92d8ea4593241dd49507ff456be52ca2aee98c728338" -eth_cold_key = "unencrypted:0181901af21f92e997c78c61337475d1975c8d29591601e36ace3952d7094d9447" -tendermint_node_key = "unencrypted:00afc7747d1e6d76293553864bbf482d061f1932f83b978b24ba4957dcfcda987c" +account_key = "unencrypted:0024204e13c51b26ed9b42c05647bc46b3821bb453e53d194962ede57ce5ec66ac" +consensus_key = "unencrypted:0037a44681b64d42497e2229516479f83e5344a7a30e8316bde45881a1ec745359" +eth_cold_key = "unencrypted:010d34fcb42383f0babe7c86203f07bf4134f0756a630eb07923f21c90cc068602" +tendermint_node_key = "unencrypted:002f2e94bb5834e18433343345baf47b2b5d4e1ef4d46ba0f876d3d2c89d831419" [validator_keys] -protocol_keypair = "ED25519_SK_PREFIX00b0da066a528a0e1221e6453f9d10143b07a675a250c66603e8a7e98bdbb8cf19" -eth_bridge_keypair = "SECP256K1_SK_PREFIX0133deb418af6af5c62aecbde3dc3a0ff62ea20c0c8e33cf703d0f5e35248e5ab1" +protocol_keypair = "ED25519_SK_PREFIX00610677d4c52ab8ca5e8abe7dfb40246a271a03069fded6099763cbc41e04df02" +eth_bridge_keypair = "SECP256K1_SK_PREFIX01a81af251a711382d6b649a44b36ac5d4f41106f356e1f2fb33c001e91ffaa169" diff --git a/genesis/localnet/transactions.toml b/genesis/localnet/transactions.toml index cafe123854..0662c5147b 100644 --- a/genesis/localnet/transactions.toml +++ b/genesis/localnet/transactions.toml @@ -7,35 +7,35 @@ [[validator_account]] alias = "validator-0" -vp = "vp_validator" +vp = "vp_user" commission_rate = "0.05" max_commission_rate_change = "0.01" email = "null@null.net" net_address = "127.0.0.1:27656" [validator_account.account_key] -pk = "tpknam1qzuaykg8nrmzuaefut39aaxl0gl66y62285cnwe37gq0a96qaf4qgp5yqtw" -authorization = "signam1qpcvzjdqkvhud9lez3exq3vy7dnp4kyjgsk92yx5cslwzjs0q9czx8ajxztx5pftx9hsf9w2shh6rt0uv6xeyu30ljqkrqj6hnrwn5gqfd9pwf" +pk = "tpknam1qpg2tsrplvhu3fd7z7tq5ztc2ne3s7e2ahjl2a2cddufrzdyr752g666ytj" +authorization = "signam1qzyc89wynvm4n7eq7jglv4d8upaxu38mkkktykjjtgqygmk4sq97ffxermz5wpur4rqr8gk6fze5uvc4u7q4qzqsr285gungdyhv2acgna2ltq" [validator_account.consensus_key] -pk = "tpknam1qpudpptwfh9u5mhvksrguyqk6wvyhus0kf2cs9qr0xuq9k4fepldgqv3ztq" -authorization = "signam1qpuhmvgl330cr3acugaddhn6q9xdw3577h3mv9yszau2smxmn7yvmn2yplfym4sk30r2hz943989sd68umu70e4wsk5q6j2gzzjfg4q0qjvz6f" +pk = "tpknam1qr9u5py97pdmcvnrxhzuuv79ydv5rw7r9z402sucwt6h0lvmmmwqy2wrweg" +authorization = "signam1qzt7ww0q00punp93jrvtkq62n4rk8y5d90tllmlkzr0z7urwfdkn7z8ttne92utwskl6ves4qp66r60tg2xqr568ranwfhcm0665wncqq4t5gx" [validator_account.protocol_key] -pk = "tpknam1qzxs6kchkustgjxld3xz0u3c8gfnkvda042vp06auk6zfrru5hhxqqvyxq6" -authorization = "signam1qztaxmfgncmv5jn9tak0au2ryzxwxrlhn2qyfx4fgewuv5p7jelpfpqe9mlp7y73vsw7r8hu509swj8mumgryswu38m7mvxn9asqn0cq7aqvjp" +pk = "tpknam1qrenhfdphzpszlr7fzand6qgmppge430g3a2lquqzhz64fkve5mq2hdfjaa" +authorization = "signam1qqeaqzj9fu0xsu7pvrkwla5asxde2wak7fslst0p79vxxydt40tzdj54js7dmjvqs2quygqqwup8z2cfffvm86ff8cud6gzel9g40ycw25wp5d" [validator_account.tendermint_node_key] -pk = "tpknam1qzckzn2rc4pr26e0clxajgcllasr6tke4yqrsu7wskw89uka29zykram505" -authorization = "signam1qrgvyj39ljlequl20hx2mz9wpuyjl8lj826c0upy9agt4txuyyusuqkhdmm2aajglupssqcsx8nv62etua6vn0duzrucut4m74nmhscwy3knc3" +pk = "tpknam1qpgcgptcjl22hl2te2uqnp33aqjmvfaud3a3f3sgtxezg7uu5rsv6d2flr3" +authorization = "signam1qrq7x5e7svuddy8dyr3xpcdt6a07u6sky0n5qnv5z757g33t5zm3jnnh9uhh073g05n8jx8rmdu5r2djhwh6few6u329u9cld4c7ynsw2592h8" [validator_account.eth_hot_key] -pk = "tpknam1qyp8znkp023autwqh2cy6c6vhnz8vsm4p6w9ngpnnamqk6dj5w6ktxqjnd0qj" -authorization = "signam1q9fd4nkz8df5ajh6jrsn6mrt0apvn4266walr8pnczl0xtn847u6usdemslvusseerhrd6hftse8zfch5tlpmqp4y9xz3563mu0d26hnqq942mt2" +pk = "tpknam1qypnh98mexms8edj8rcwu0cayx0459p39dwzsffxrr394mf4cse707qcctyrx" +authorization = "signam1qyrvwveg76nrz2ppnsl0em82gcl4p90cqw8eadyzcvk59e2dx0jqja8ln9l9j79sxzhhh5gdggduz78vtthzj5nzs0xvpwhjuh3hymapqq07qxzm" [validator_account.eth_cold_key] -pk = "tpknam1qyp4aw7a07f4ltuq3f0c4sgyq3kzgh6z40w8jt40wl7uhfj7e3m3u9qr792xg" -authorization = "signam1qyqcc7wstsnuadu75jnwg8hxz34nglxj9h9yqyx2c4qqdpxw50ff60hu0swfj7xdkz34tgl9e50jlmzphkgtpw3gg0hsgp35lhsl6rmeqqq28kph" +pk = "tpknam1qypz8zr0w8lsz3s98vh4p974xuxeedpecj9s2l3326r3kdz4tc0snrcpnc8yv" +authorization = "signam1q992kq4ymfl6v8arc2s2tn0w7c4f48wx6fxry9qxv2qk8zvjan8q7j9rxg73cx0f5l56fy53x2jgwv7vy8jtxzucckdzgnxc5tpzajs4qq8r02r2" [[transfer]] token = "nam" @@ -48,7 +48,8 @@ signature = "signam1qz8ch7n6jp7g7hvnzkhmprhqc5umd0gatarlttm7gpcdx6g8hmgqffdq67fn source = "validator-0" validator = "validator-0" amount = "100000" -signature = "signam1qrd7wg2sdla73z7626r2ep8895d9ed4ljq37nz6kmy2rcm36yqjugw6vle7kl70l0d585t382s9vd28k2duwz0lu7ux0vua6aaarjssgdf46n2" +signature = "signam1qqukrz3js2pgzrne90u5f7y4mstrzvmzcq7eelml9m3lzrh9zwpf0vhgjq0rsw4ufj4ffdx8ew74uxkk4df649pg6qq5fgwyqa9mpfcyvskk67" + # 2. From 7de64272819719887bdc1e2087e25f7d25884886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 12:05:28 +0100 Subject: [PATCH 25/54] changelog: add #2202 --- .../unreleased/improvements/2202-combine-user-validator-vp.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2202-combine-user-validator-vp.md diff --git a/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md b/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md new file mode 100644 index 0000000000..030af2ca17 --- /dev/null +++ b/.changelog/unreleased/improvements/2202-combine-user-validator-vp.md @@ -0,0 +1,2 @@ +- Combined the user and the validator VP into one. + ([\#2202](https://github.com/anoma/namada/pull/2202)) \ No newline at end of file From 50bb9379ab44b8e881f7eca0f2142109ec2405b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 12:10:42 +0100 Subject: [PATCH 26/54] deliberately empty From affe06519b7587358332423966179a2f055ba185 Mon Sep 17 00:00:00 2001 From: yito88 Date: Tue, 21 Nov 2023 10:22:35 +0100 Subject: [PATCH 27/54] prune merkle trees of bridge pool --- apps/src/lib/node/ledger/storage/mod.rs | 9 +++ core/src/ledger/storage/mod.rs | 97 ++++++++++++++++++++----- 2 files changed, 86 insertions(+), 20 deletions(-) diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index 52c10d4a17..e6208fc800 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -55,6 +55,7 @@ mod tests { use itertools::Itertools; use namada::core::ledger::masp_conversions::update_allowed_conversions; + use namada::ledger::eth_bridge::storage::bridge_pool; use namada::ledger::gas::STORAGE_ACCESS_GAS_PER_BYTE; use namada::ledger::ibc::storage::ibc_key; use namada::ledger::parameters::{EpochDuration, Parameters}; @@ -62,6 +63,7 @@ mod tests { use namada::ledger::storage::{types, StoreType, WlStorage}; use namada::ledger::storage_api::{self, StorageWrite}; use namada::types::chain::ChainId; + use namada::types::ethereum_events::Uint; use namada::types::hash::Hash; use namada::types::storage::{BlockHash, BlockHeight, Key}; use namada::types::time::DurationSecs; @@ -487,6 +489,9 @@ mod tests { let value_bytes = types::encode(&storage.block.height); storage.write(&key, value_bytes)?; } + let key = bridge_pool::get_nonce_key(); + let bytes = types::encode(&Uint::default()); + storage.write(&key, bytes)?; // Update and commit let hash = BlockHash::default(); @@ -581,6 +586,10 @@ mod tests { None, Some(5), ); + let key = bridge_pool::get_nonce_key(); + let bytes = types::encode(&Uint::default()); + storage.write(&key, bytes).unwrap(); + storage .begin_block(BlockHash::default(), BlockHeight(1)) .expect("begin_block failed"); diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index b338b3518b..f888482fd6 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -25,7 +25,9 @@ pub use wl_storage::{ }; use super::gas::MEMORY_ACCESS_GAS_PER_BYTE; -use crate::ledger::eth_bridge::storage::bridge_pool::is_pending_transfer_key; +use crate::ledger::eth_bridge::storage::bridge_pool::{ + self, is_pending_transfer_key, +}; use crate::ledger::gas::{ STORAGE_ACCESS_GAS_PER_BYTE, STORAGE_WRITE_GAS_PER_BYTE, }; @@ -39,6 +41,7 @@ use crate::ledger::storage::merkle_tree::{ use crate::tendermint::merkle::proof::ProofOps; use crate::types::address::{Address, EstablishedAddressGen, InternalAddress}; use crate::types::chain::{ChainId, CHAIN_ID_LENGTH}; +use crate::types::ethereum_events::Uint; use crate::types::ethereum_structs; use crate::types::hash::{Error as HashError, Hash}; use crate::types::internal::{ExpiredTxsQueue, TxQueue}; @@ -1144,25 +1147,7 @@ where if self.block.epoch.0 == 0 { return Ok(()); } - if let Some(limit) = self.storage_read_past_height_limit { - if self.get_last_block_height().0 <= limit { - return Ok(()); - } - - let min_height = (self.get_last_block_height().0 - limit).into(); - if let Some(epoch) = self.block.pred_epochs.get_epoch(min_height) { - if epoch.0 == 0 { - return Ok(()); - } - // Remove stores at the previous epoch because the Merkle tree - // stores at the starting height of the epoch would be used to - // restore stores at a height (> min_height) in the epoch - for st in StoreType::iter_provable() { - self.db.prune_merkle_tree_store(batch, st, epoch.prev())?; - } - } - } - // remove non-provable stores at the previous epoch + // Prune non-provable stores at the previous epoch for st in StoreType::iter_non_provable() { self.db.prune_merkle_tree_store( batch, @@ -1170,6 +1155,32 @@ where self.block.epoch.prev(), )?; } + // Prune provable stores + let oldest_epoch = self.get_oldest_epoch(); + if oldest_epoch.0 > 0 { + // Remove stores at the previous epoch because the Merkle tree + // stores at the starting height of the epoch would be used to + // restore stores at a height (> oldest_height) in the epoch + for st in StoreType::iter_provable() { + self.db.prune_merkle_tree_store( + batch, + st, + oldest_epoch.prev(), + )?; + } + + // Prune the BridgePool subtree stores with invalid nonce + let mut epoch = self.get_oldest_epoch_with_valid_nonce()?; + while oldest_epoch < epoch { + epoch = epoch.prev(); + self.db.prune_merkle_tree_store( + batch, + &StoreType::BridgePool, + epoch, + )?; + } + } + Ok(()) } @@ -1182,6 +1193,52 @@ where .unwrap_or_default() } + /// Get the oldest epoch where we can read a value + pub fn get_oldest_epoch(&self) -> Epoch { + let oldest_height = match self.storage_read_past_height_limit { + Some(limit) if limit < self.get_last_block_height().0 => { + (self.get_last_block_height().0 - limit).into() + } + _ => BlockHeight(1), + }; + self.block + .pred_epochs + .get_epoch(oldest_height) + .unwrap_or_default() + } + + /// Get oldest epoch which has the valid signed nonce of the bridge pool + pub fn get_oldest_epoch_with_valid_nonce(&self) -> Result { + let nonce_key = bridge_pool::get_nonce_key(); + let (bytes, _) = self.read(&nonce_key)?; + let bytes = bytes.expect("Bridge pool nonce should exits"); + let current_nonce = + Uint::try_from_slice(&bytes).map_err(Error::BorshCodingError)?; + let (mut epoch, _) = self.get_last_epoch(); + // We don't need to check the older epochs because their Merkle tree + // snapshots have been already removed + let oldest_epoch = self.get_oldest_epoch(); + // Look up the last valid epoch which has the previous nonce of the + // current one. It has the previous nonce, but it was + // incremented during the epoch. + while 0 < epoch.0 && oldest_epoch <= epoch { + epoch = epoch.prev(); + let height = + match self.block.pred_epochs.get_start_height_of_epoch(epoch) { + Some(h) => h, + None => continue, + }; + let (bytes, _) = self.read_with_height(&nonce_key, height)?; + let bytes = bytes.expect("Bridge pool nonce should exits"); + let nonce = Uint::try_from_slice(&bytes) + .map_err(Error::BorshCodingError)?; + if nonce < current_nonce { + break; + } + } + Ok(epoch) + } + /// Check it the given transaction's hash is already present in storage pub fn has_replay_protection_entry(&self, hash: &Hash) -> Result { self.db.has_replay_protection_entry(hash) From 5388f93b9bf1bdbabd1cb71ad0c704645a46f8d1 Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Tue, 21 Nov 2023 19:53:17 +0100 Subject: [PATCH 28/54] Charges wrapper gas for network usage --- core/src/ledger/gas.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/src/ledger/gas.rs b/core/src/ledger/gas.rs index 092c0ba3b2..fc09636766 100644 --- a/core/src/ledger/gas.rs +++ b/core/src/ledger/gas.rs @@ -35,6 +35,8 @@ const STORAGE_OCCUPATION_GAS_PER_BYTE: u64 = // codebase. For these two reasons we just set an arbitrary value (based on // actual SSDs latency) per byte here const PHYSICAL_STORAGE_LATENCY_PER_BYTE: u64 = 75; +// This is based on the global avarage bandwidth +const NETWORK_TRANSMISSION_GAS_PER_BYTE: u64 = 13; /// The cost of accessing data from memory (both read and write mode), per byte pub const MEMORY_ACCESS_GAS_PER_BYTE: u64 = 2; @@ -273,13 +275,18 @@ impl TxGasMeter { /// Add the gas required by a wrapper transaction which is comprised of: /// - cost of validating the wrapper tx /// - space that the transaction requires in the block + /// - cost of downloading (as part of the block) the transaction bytes over + /// the network pub fn add_wrapper_gas(&mut self, tx_bytes: &[u8]) -> Result<()> { self.consume(WRAPPER_TX_VALIDATION_GAS)?; let bytes_len = tx_bytes.len() as u64; self.consume( bytes_len - .checked_mul(STORAGE_OCCUPATION_GAS_PER_BYTE) + .checked_mul( + STORAGE_OCCUPATION_GAS_PER_BYTE + + NETWORK_TRANSMISSION_GAS_PER_BYTE, + ) .ok_or(Error::GasOverflow)?, ) } From cb85b5cb6e4f7c32ccec693e80cd48c127b8db3e Mon Sep 17 00:00:00 2001 From: yito88 Date: Tue, 21 Nov 2023 21:29:14 +0100 Subject: [PATCH 29/54] add test and changelog --- .../improvements/2110-prune-bp-merkle-tree.md | 2 + apps/src/lib/node/ledger/storage/mod.rs | 44 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 .changelog/unreleased/improvements/2110-prune-bp-merkle-tree.md diff --git a/.changelog/unreleased/improvements/2110-prune-bp-merkle-tree.md b/.changelog/unreleased/improvements/2110-prune-bp-merkle-tree.md new file mode 100644 index 0000000000..4abce31ec0 --- /dev/null +++ b/.changelog/unreleased/improvements/2110-prune-bp-merkle-tree.md @@ -0,0 +1,2 @@ +- Prune merkle tree of bridge pool + ([\#2110](https://github.com/anoma/namada/issues/2110)) \ No newline at end of file diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index e6208fc800..2fd1fc5aa8 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -586,9 +586,10 @@ mod tests { None, Some(5), ); - let key = bridge_pool::get_nonce_key(); - let bytes = types::encode(&Uint::default()); - storage.write(&key, bytes).unwrap(); + let bp_nonce_key = bridge_pool::get_nonce_key(); + let nonce = Uint::default(); + let bytes = types::encode(&nonce); + storage.write(&bp_nonce_key, bytes).unwrap(); storage .begin_block(BlockHash::default(), BlockHeight(1)) @@ -615,6 +616,13 @@ mod tests { .write(&key, types::encode(&value)) .expect("write failed"); + let nonce = nonce + 1; + let bytes = types::encode(&nonce); + storage.write(&bp_nonce_key, bytes).unwrap(); + + let bytes = types::encode(&Uint::default()); + storage.write(&bp_nonce_key, bytes).unwrap(); + storage.block.epoch = storage.block.epoch.next(); storage.block.pred_epochs.new_epoch(BlockHeight(6)); let batch = PersistentStorage::batch(); @@ -626,6 +634,11 @@ mod tests { storage .begin_block(BlockHash::default(), BlockHeight(11)) .expect("begin_block failed"); + + let nonce = nonce + 1; + let bytes = types::encode(&nonce); + storage.write(&bp_nonce_key, bytes).unwrap(); + storage.block.epoch = storage.block.epoch.next(); storage.block.pred_epochs.new_epoch(BlockHeight(11)); let batch = PersistentStorage::batch(); @@ -639,7 +652,30 @@ mod tests { "The tree at Height 5 shouldn't be able to be restored" ); let result = storage.get_merkle_tree(6.into(), Some(StoreType::Ibc)); - assert!(result.is_ok(), "The tree should be restored"); + assert!(result.is_ok(), "The ibc tree should be restored"); + let result = + storage.get_merkle_tree(6.into(), Some(StoreType::BridgePool)); + assert!(result.is_ok(), "The bridge pool tree should be restored"); + + storage + .begin_block(BlockHash::default(), BlockHeight(12)) + .expect("begin_block failed"); + + let nonce = nonce + 1; + let bytes = types::encode(&nonce); + storage.write(&bp_nonce_key, bytes).unwrap(); + storage.block.epoch = storage.block.epoch.next(); + storage.block.pred_epochs.new_epoch(BlockHeight(12)); + let batch = PersistentStorage::batch(); + storage.commit_block(batch).expect("commit failed"); + + // ibc tree should be able to be restored + let result = storage.get_merkle_tree(6.into(), Some(StoreType::Ibc)); + assert!(result.is_ok(), "The ibc tree should be restored"); + // bridge pool tree should be pruned because of the nonce + let result = + storage.get_merkle_tree(6.into(), Some(StoreType::BridgePool)); + assert!(result.is_err(), "The bridge pool tree should be pruned"); } /// Test the prefix iterator with RocksDB. From 13ce9672280d1585213a9360b53a5bd80dda02ca Mon Sep 17 00:00:00 2001 From: Marco Granelli Date: Wed, 22 Nov 2023 10:44:55 +0100 Subject: [PATCH 30/54] Changelog #2205 --- .changelog/unreleased/improvements/2205-network-gas.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2205-network-gas.md diff --git a/.changelog/unreleased/improvements/2205-network-gas.md b/.changelog/unreleased/improvements/2205-network-gas.md new file mode 100644 index 0000000000..77891ac403 --- /dev/null +++ b/.changelog/unreleased/improvements/2205-network-gas.md @@ -0,0 +1,2 @@ +- Charge gas for network usage. + ([\#2205](https://github.com/anoma/namada/pull/2205)) \ No newline at end of file From 20943a796034913e62430492072162f89a67ec3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 18:20:21 +0100 Subject: [PATCH 31/54] replace tx_init_validator with tx_become_validator --- apps/src/lib/bench_utils.rs | 8 +- apps/src/lib/cli.rs | 188 ++++++++++++++++++-- apps/src/lib/cli/client.rs | 24 +++ apps/src/lib/client/tx.rs | 177 ++++++++++-------- benches/txs.rs | 24 +-- core/src/types/transaction/pos.rs | 15 +- encoding_spec/src/main.rs | 2 +- sdk/src/args.rs | 39 +++- sdk/src/lib.rs | 42 ++++- sdk/src/signing.rs | 47 +---- sdk/src/tx.rs | 4 +- tx_prelude/src/proof_of_stake.rs | 34 ++-- wasm/wasm_source/Cargo.toml | 2 +- wasm/wasm_source/Makefile | 2 +- wasm/wasm_source/src/lib.rs | 4 +- wasm/wasm_source/src/tx_become_validator.rs | 44 +++++ wasm/wasm_source/src/tx_init_validator.rs | 64 ------- 17 files changed, 471 insertions(+), 249 deletions(-) create mode 100644 wasm/wasm_source/src/tx_become_validator.rs delete mode 100644 wasm/wasm_source/src/tx_init_validator.rs diff --git a/apps/src/lib/bench_utils.rs b/apps/src/lib/bench_utils.rs index a718cacbed..e0df703dd3 100644 --- a/apps/src/lib/bench_utils.rs +++ b/apps/src/lib/bench_utils.rs @@ -80,15 +80,15 @@ use namada_sdk::masp::{ self, ShieldedContext, ShieldedTransfer, ShieldedUtils, }; pub use namada_sdk::tx::{ - TX_BOND_WASM, TX_BRIDGE_POOL_WASM, + TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM as TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM as TX_CHANGE_VALIDATOR_METADATA_WASM, TX_CLAIM_REWARDS_WASM, TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, TX_INIT_PROPOSAL as TX_INIT_PROPOSAL_WASM, - TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, - TX_RESIGN_STEWARD, TX_REVEAL_PK as TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, - TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, + TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, + TX_REVEAL_PK as TX_REVEAL_PK_WASM, TX_TRANSFER_WASM, TX_UNBOND_WASM, + TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL as TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_USER_WASM, }; diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 3bb7f5c7ad..f6ac24a6fd 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -223,6 +223,7 @@ pub mod cmds { .subcommand(TxInitProposal::def().display_order(1)) .subcommand(TxVoteProposal::def().display_order(1)) // PoS transactions + .subcommand(TxBecomeValidator::def().display_order(2)) .subcommand(TxInitValidator::def().display_order(2)) .subcommand(TxUnjailValidator::def().display_order(2)) .subcommand(TxDeactivateValidator::def().display_order(2)) @@ -276,6 +277,8 @@ pub mod cmds { let tx_update_account = Self::parse_with_ctx(matches, TxUpdateAccount); let tx_init_account = Self::parse_with_ctx(matches, TxInitAccount); + let tx_become_validator = + Self::parse_with_ctx(matches, TxBecomeValidator); let tx_init_validator = Self::parse_with_ctx(matches, TxInitValidator); let tx_unjail_validator = @@ -346,6 +349,7 @@ pub mod cmds { .or(tx_reveal_pk) .or(tx_init_proposal) .or(tx_vote_proposal) + .or(tx_become_validator) .or(tx_init_validator) .or(tx_commission_rate_change) .or(tx_change_consensus_key) @@ -426,6 +430,7 @@ pub mod cmds { QueryResult(QueryResult), TxUpdateAccount(TxUpdateAccount), TxInitAccount(TxInitAccount), + TxBecomeValidator(TxBecomeValidator), TxInitValidator(TxInitValidator), TxCommissionRateChange(TxCommissionRateChange), TxChangeConsensusKey(TxChangeConsensusKey), @@ -1395,6 +1400,25 @@ pub mod cmds { } } + #[derive(Clone, Debug)] + pub struct TxBecomeValidator(pub args::TxBecomeValidator); + + impl SubCmd for TxBecomeValidator { + const CMD: &'static str = "become-validator"; + + fn parse(matches: &ArgMatches) -> Option { + matches.subcommand_matches(Self::CMD).map(|matches| { + TxBecomeValidator(args::TxBecomeValidator::parse(matches)) + }) + } + + fn def() -> App { + App::new(Self::CMD) + .about("Send a signed transaction to become a validator.") + .add_args::>() + } + } + #[derive(Clone, Debug)] pub struct TxInitValidator(pub args::TxInitValidator); @@ -1410,8 +1434,8 @@ pub mod cmds { fn def() -> App { App::new(Self::CMD) .about( - "Send a signed transaction to create a new validator \ - account.", + "Send a signed transaction to create a established \ + account and then become a validator.", ) .add_args::>() } @@ -2833,12 +2857,12 @@ pub mod args { use namada::types::transaction::GasLimit; pub use namada_sdk::args::*; pub use namada_sdk::tx::{ - TX_BOND_WASM, TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM, - TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM, - TX_CLAIM_REWARDS_WASM, TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, - TX_INIT_ACCOUNT_WASM, TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, - TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, - TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, + TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, + TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, + TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, + TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, + TX_INIT_PROPOSAL, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, + TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, @@ -4019,6 +4043,140 @@ pub mod args { } } + impl CliToSdk> for TxBecomeValidator { + fn to_sdk(self, ctx: &mut Context) -> TxBecomeValidator { + let tx = self.tx.to_sdk(ctx); + let chain_ctx = ctx.borrow_mut_chain_or_exit(); + TxBecomeValidator:: { + tx, + scheme: self.scheme, + address: chain_ctx.get(&self.address), + consensus_key: self + .consensus_key + .map(|x| chain_ctx.get_cached(&x)), + eth_cold_key: self + .eth_cold_key + .map(|x| chain_ctx.get_cached(&x)), + eth_hot_key: self.eth_hot_key.map(|x| chain_ctx.get_cached(&x)), + protocol_key: self.protocol_key.map(|x| chain_ctx.get(&x)), + commission_rate: self.commission_rate, + max_commission_rate_change: self.max_commission_rate_change, + email: self.email, + description: self.description, + website: self.website, + discord_handle: self.discord_handle, + unsafe_dont_encrypt: self.unsafe_dont_encrypt, + tx_code_path: self.tx_code_path.to_path_buf(), + } + } + } + + impl Args for TxBecomeValidator { + fn parse(matches: &ArgMatches) -> Self { + let tx = Tx::parse(matches); + let address = ADDRESS.parse(matches); + let scheme = SCHEME.parse(matches); + let consensus_key = VALIDATOR_CONSENSUS_KEY.parse(matches); + let eth_cold_key = VALIDATOR_ETH_COLD_KEY.parse(matches); + let eth_hot_key = VALIDATOR_ETH_HOT_KEY.parse(matches); + let protocol_key = PROTOCOL_KEY.parse(matches); + let commission_rate = COMMISSION_RATE.parse(matches); + let max_commission_rate_change = + MAX_COMMISSION_RATE_CHANGE.parse(matches); + let email = EMAIL.parse(matches); + let description = DESCRIPTION_OPT.parse(matches); + let website = WEBSITE_OPT.parse(matches); + let discord_handle = DISCORD_OPT.parse(matches); + let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); + let tx_code_path = PathBuf::from(TX_BECOME_VALIDATOR_WASM); + Self { + tx, + address, + scheme, + consensus_key, + eth_cold_key, + eth_hot_key, + protocol_key, + commission_rate, + max_commission_rate_change, + email, + description, + website, + discord_handle, + unsafe_dont_encrypt, + tx_code_path, + } + } + + fn def(app: App) -> App { + app.add_args::>() + .arg(ADDRESS.def().help( + "Address of an account that will become a validator.", + )) + .arg(SCHEME.def().help( + "The key scheme/type used for the validator keys. \ + Currently supports ed25519 and secp256k1.", + )) + .arg(VALIDATOR_CONSENSUS_KEY.def().help( + "A consensus key for the validator account. A new one \ + will be generated if none given. Note that this must be \ + ed25519.", + )) + .arg(VALIDATOR_ETH_COLD_KEY.def().help( + "An Eth cold key for the validator account. A new one \ + will be generated if none given. Note that this must be \ + secp256k1.", + )) + .arg(VALIDATOR_ETH_HOT_KEY.def().help( + "An Eth hot key for the validator account. A new one will \ + be generated if none given. Note that this must be \ + secp256k1.", + )) + .arg(PROTOCOL_KEY.def().help( + "A public key for signing protocol transactions. A new \ + one will be generated if none given.", + )) + .arg(COMMISSION_RATE.def().help( + "The commission rate charged by the validator for \ + delegation rewards. Expressed as a decimal between 0 and \ + 1. This is a required parameter.", + )) + .arg(MAX_COMMISSION_RATE_CHANGE.def().help( + "The maximum change per epoch in the commission rate \ + charged by the validator for delegation rewards. \ + Expressed as a decimal between 0 and 1. This is a \ + required parameter.", + )) + .arg(EMAIL_OPT.def().help( + "The desired new validator email. To remove the existing \ + email, pass an empty string to this argument.", + )) + .arg(DESCRIPTION_OPT.def().help( + "The desired new validator description. To remove the \ + existing description, pass an empty string to this \ + argument.", + )) + .arg(WEBSITE_OPT.def().help( + "The desired new validator website. To remove the \ + existing website, pass an empty string to this argument.", + )) + .arg(DISCORD_OPT.def().help( + "The desired new validator discord handle. To remove the \ + existing discord handle, pass an empty string to this \ + argument.", + )) + .arg(VALIDATOR_CODE_PATH.def().help( + "The path to the validity predicate WASM code to be used \ + for the validator account. Uses the default validator VP \ + if none specified.", + )) + .arg(UNSAFE_DONT_ENCRYPT.def().help( + "UNSAFE: Do not encrypt the generated keypairs. Do not \ + use this for keys used in a live network.", + )) + } + } + impl CliToSdk> for TxInitValidator { fn to_sdk(self, ctx: &mut Context) -> TxInitValidator { let tx = self.tx.to_sdk(ctx); @@ -4050,7 +4208,12 @@ pub mod args { .validator_vp_code_path .to_path_buf(), unsafe_dont_encrypt: self.unsafe_dont_encrypt, - tx_code_path: self.tx_code_path.to_path_buf(), + tx_init_account_code_path: self + .tx_init_account_code_path + .to_path_buf(), + tx_become_validator_code_path: self + .tx_become_validator_code_path + .to_path_buf(), } } } @@ -4075,7 +4238,9 @@ pub mod args { .parse(matches) .unwrap_or_else(|| PathBuf::from(VP_USER_WASM)); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); - let tx_code_path = PathBuf::from(TX_INIT_VALIDATOR_WASM); + let tx_init_account_code_path = PathBuf::from(TX_INIT_ACCOUNT_WASM); + let tx_become_validator_code_path = + PathBuf::from(TX_BECOME_VALIDATOR_WASM); let threshold = THRESOLD.parse(matches); Self { tx, @@ -4094,7 +4259,8 @@ pub mod args { discord_handle, validator_vp_code_path, unsafe_dont_encrypt, - tx_code_path, + tx_init_account_code_path, + tx_become_validator_code_path, } } diff --git a/apps/src/lib/cli/client.rs b/apps/src/lib/cli/client.rs index d4f81483fb..4d56c1e9c1 100644 --- a/apps/src/lib/cli/client.rs +++ b/apps/src/lib/cli/client.rs @@ -106,6 +106,30 @@ impl CliApi { ) } } + Sub::TxBecomeValidator(TxBecomeValidator(mut args)) => { + let client = client.unwrap_or_else(|| { + C::from_tendermint_address( + &mut args.tx.ledger_address, + ) + }); + client.wait_until_node_is_synced(io).await?; + let args = args.to_sdk(&mut ctx); + let cli::context::ChainContext { + mut wallet, + mut config, + mut shielded, + native_token, + } = ctx.take_chain_or_exit(); + let namada = NamadaImpl::native_new( + &client, + &mut wallet, + &mut shielded, + io, + native_token, + ); + tx::submit_become_validator(&namada, &mut config, args) + .await?; + } Sub::TxInitValidator(TxInitValidator(mut args)) => { let client = client.unwrap_or_else(|| { C::from_tendermint_address( diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 0317ec43f3..c88d231a99 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -19,7 +19,7 @@ use namada::types::address::{Address, ImplicitAddress}; use namada::types::dec::Dec; use namada::types::io::Io; use namada::types::key::{self, *}; -use namada::types::transaction::pos::{ConsensusKeyChange, InitValidator}; +use namada::types::transaction::pos::{BecomeValidator, ConsensusKeyChange}; use namada_sdk::rpc::{TxBroadcastData, TxResponse}; use namada_sdk::wallet::alias::validator_consensus_key; use namada_sdk::{display_line, edisplay_line, error, signing, tx, Namada}; @@ -316,7 +316,7 @@ where pub async fn submit_init_account<'a, N: Namada<'a>>( namada: &N, args: args::TxInitAccount, -) -> Result<(), error::Error> +) -> Result, error::Error> where ::Error: std::fmt::Display, { @@ -332,10 +332,13 @@ where signing::generate_test_vector(namada, &tx).await?; - namada.submit(tx, &args.tx).await?; + let result = namada.submit(tx, &args.tx).await?; + if let ProcessTxResponse::Applied(response) = result { + return Ok(response.initialized_accounts.first().cloned()); + } } - Ok(()) + Ok(None) } pub async fn submit_change_consensus_key<'a>( @@ -482,14 +485,13 @@ pub async fn submit_change_consensus_key<'a>( Ok(()) } -pub async fn submit_init_validator<'a>( +pub async fn submit_become_validator<'a>( namada: &impl Namada<'a>, config: &mut crate::config::Config, - args::TxInitValidator { + args::TxBecomeValidator { tx: tx_args, + address, scheme, - account_keys, - threshold, consensus_key, eth_cold_key, eth_hot_key, @@ -500,10 +502,9 @@ pub async fn submit_init_validator<'a>( website, description, discord_handle, - validator_vp_code_path, unsafe_dont_encrypt, - tx_code_path: _, - }: args::TxInitValidator, + tx_code_path, + }: args::TxBecomeValidator, ) -> Result<(), error::Error> { let tx_args = args::Tx { chain_id: tx_args @@ -521,17 +522,6 @@ pub async fn submit_init_validator<'a>( let validator_key_alias = format!("{}-key", alias); let consensus_key_alias = validator_consensus_key(&alias.clone().into()); let protocol_key_alias = format!("{}-protocol-key", alias); - - let threshold = match threshold { - Some(threshold) => threshold, - None => { - if account_keys.len() == 1 { - 1u8 - } else { - safe_exit(1) - } - } - }; let eth_hot_key_alias = format!("{}-eth-hot-key", alias); let eth_cold_key_alias = format!("{}-eth-cold-key", alias); @@ -655,11 +645,6 @@ pub async fn submit_init_validator<'a>( ) .map_err(|err| error::Error::Other(err.to_string()))?; - let validator_vp_code_hash = - query_wasm_code_hash(namada, validator_vp_code_path.to_str().unwrap()) - .await - .unwrap(); - // Validate the commission rate data if commission_rate > Dec::one() || commission_rate < Dec::zero() { edisplay_line!( @@ -695,20 +680,14 @@ pub async fn submit_init_validator<'a>( } let tx_code_hash = - query_wasm_code_hash(namada, args::TX_INIT_VALIDATOR_WASM) + query_wasm_code_hash(namada, tx_code_path.to_string_lossy()) .await .unwrap(); let chain_id = tx_args.chain_id.clone().unwrap(); let mut tx = Tx::new(chain_id, tx_args.expiration); - let extra_section_hash = tx.add_extra_section_from_hash( - validator_vp_code_hash, - Some(validator_vp_code_path.to_string_lossy().into_owned()), - ); - - let data = InitValidator { - account_keys, - threshold, + let data = BecomeValidator { + address: address.clone(), consensus_key: consensus_key.ref_to(), eth_cold_key: key::secp256k1::PublicKey::try_from_pk(ð_cold_pk) .unwrap(), @@ -721,11 +700,20 @@ pub async fn submit_init_validator<'a>( description, website, discord_handle, - validator_vp_code_hash: extra_section_hash, }; // Put together all the PKs that we have to sign with to verify ownership - let mut all_pks = data.account_keys.clone(); + let account = namada_sdk::rpc::get_account_info(namada.client(), &address) + .await? + .unwrap_or_else(|| { + edisplay_line!( + namada.io(), + "Unable to query account keys for address {address}." + ); + safe_exit(1) + }); + let mut all_pks: Vec<_> = + account.public_keys_map.pk_to_idx.into_keys().collect(); all_pks.push(consensus_key.to_public()); all_pks.push(eth_cold_pk); all_pks.push(eth_hot_pk); @@ -733,7 +721,7 @@ pub async fn submit_init_validator<'a>( tx.add_code_from_hash( tx_code_hash, - Some(args::TX_INIT_VALIDATOR_WASM.to_string()), + Some(args::TX_BECOME_VALIDATOR_WASM.to_string()), ) .add_data(data); @@ -758,38 +746,14 @@ pub async fn submit_init_validator<'a>( signing::generate_test_vector(namada, &tx).await?; - let result = namada.submit(tx, &tx_args).await?.initialized_accounts(); + namada.submit(tx, &tx_args).await?.initialized_accounts(); if !tx_args.dry_run { - let (validator_address_alias, validator_address) = match &result[..] - { - // There should be 1 account for the validator itself - [validator_address] => { - if let Some(alias) = - namada.wallet().await.find_alias(validator_address) - { - (alias.clone(), validator_address.clone()) - } else { - edisplay_line!( - namada.io(), - "Expected one account to be created" - ); - safe_exit(1) - } - } - _ => { - edisplay_line!( - namada.io(), - "Expected one account to be created" - ); - safe_exit(1) - } - }; // add validator address and keys to the wallet namada .wallet_mut() .await - .add_validator_data(validator_address, validator_keys); + .add_validator_data(address.clone(), validator_keys); namada .wallet_mut() .await @@ -819,12 +783,7 @@ pub async fn submit_init_validator<'a>( display_line!(namada.io(), ""); display_line!( namada.io(), - "The validator's addresses and keys were stored in the wallet:" - ); - display_line!( - namada.io(), - " Validator address \"{}\"", - validator_address_alias + "The keys for validator \"{alias}\" were stored in the wallet:" ); display_line!( namada.io(), @@ -857,6 +816,82 @@ pub async fn submit_init_validator<'a>( Ok(()) } +pub async fn submit_init_validator<'a>( + namada: &impl Namada<'a>, + config: &mut crate::config::Config, + args::TxInitValidator { + tx: tx_args, + scheme, + account_keys, + threshold, + consensus_key, + eth_cold_key, + eth_hot_key, + protocol_key, + commission_rate, + max_commission_rate_change, + email, + website, + description, + discord_handle, + validator_vp_code_path, + unsafe_dont_encrypt, + tx_init_account_code_path, + tx_become_validator_code_path, + }: args::TxInitValidator, +) -> Result<(), error::Error> { + let address = submit_init_account( + namada, + args::TxInitAccount { + tx: tx_args.clone(), + vp_code_path: validator_vp_code_path, + tx_code_path: tx_init_account_code_path, + public_keys: account_keys, + threshold, + }, + ) + .await?; + + if tx_args.dry_run { + eprintln!( + "Cannot proceed to become validator in dry-run as no account has \ + been created" + ); + safe_exit(1); + } + let address = address.unwrap_or_else(|| { + eprintln!( + "Something went wrong with transaction to initialize an account \ + as no address has been created. Cannot proceed to become \ + validator." + ); + safe_exit(1); + }); + + submit_become_validator( + namada, + config, + args::TxBecomeValidator { + tx: tx_args, + address, + scheme, + consensus_key, + eth_cold_key, + eth_hot_key, + protocol_key, + commission_rate, + max_commission_rate_change, + email, + description, + website, + discord_handle, + tx_code_path: tx_become_validator_code_path, + unsafe_dont_encrypt, + }, + ) + .await +} + pub async fn submit_transfer<'a>( namada: &impl Namada<'a>, args: args::TxTransfer, diff --git a/benches/txs.rs b/benches/txs.rs index 98f4d45a9d..97a4e16945 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -12,7 +12,7 @@ use namada::core::types::key::{ }; use namada::core::types::token::Amount; use namada::core::types::transaction::account::{InitAccount, UpdateAccount}; -use namada::core::types::transaction::pos::{InitValidator, MetaDataChange}; +use namada::core::types::transaction::pos::{BecomeValidator, MetaDataChange}; use namada::ibc::core::ics02_client::client_type::ClientType; use namada::ibc::core::ics03_connection::connection::Counterparty; use namada::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; @@ -43,15 +43,15 @@ use namada::types::transaction::pos::{ }; use namada_apps::bench_utils::{ BenchShell, BenchShieldedCtx, ALBERT_PAYMENT_ADDRESS, ALBERT_SPENDING_KEY, - BERTHA_PAYMENT_ADDRESS, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, - TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_VALIDATOR_COMMISSION_WASM, - TX_CHANGE_VALIDATOR_METADATA_WASM, TX_CLAIM_REWARDS_WASM, - TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, - TX_INIT_PROPOSAL_WASM, TX_INIT_VALIDATOR_WASM, - TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, - TX_REVEAL_PK_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, - TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, - TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, VP_USER_WASM, + BERTHA_PAYMENT_ADDRESS, TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, + TX_BRIDGE_POOL_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, + TX_CHANGE_VALIDATOR_COMMISSION_WASM, TX_CHANGE_VALIDATOR_METADATA_WASM, + TX_CLAIM_REWARDS_WASM, TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, + TX_INIT_ACCOUNT_WASM, TX_INIT_PROPOSAL_WASM, TX_REACTIVATE_VALIDATOR_WASM, + TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK_WASM, TX_UNBOND_WASM, + TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, + TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL_WASM, TX_WITHDRAW_WASM, + VP_USER_WASM, }; use namada_apps::wallet::defaults; use sha2::Digest; @@ -625,7 +625,7 @@ fn init_validator(c: &mut Criterion) { .finalize_reset() .into(), ); - let data = InitValidator { + let data = BecomeValidator { account_keys: vec![defaults::albert_keypair().to_public()], threshold: 1, consensus_key, @@ -641,7 +641,7 @@ fn init_validator(c: &mut Criterion) { validator_vp_code_hash: extra_hash, }; let tx = shell.generate_tx( - TX_INIT_VALIDATOR_WASM, + TX_BECOME_VALIDATOR_WASM, data, None, Some(vec![extra_section]), diff --git a/core/src/types/transaction/pos.rs b/core/src/types/transaction/pos.rs index bec1a066e8..f44be68d85 100644 --- a/core/src/types/transaction/pos.rs +++ b/core/src/types/transaction/pos.rs @@ -5,11 +5,10 @@ use serde::{Deserialize, Serialize}; use crate::types::address::Address; use crate::types::dec::Dec; -use crate::types::hash::Hash; use crate::types::key::{common, secp256k1}; use crate::types::token; -/// A tx data type to initialize a new validator account. +/// A tx data type to become a validator account. #[derive( Debug, Clone, @@ -20,13 +19,9 @@ use crate::types::token; Serialize, Deserialize, )] -pub struct InitValidator { - /// Public key to be written into the account's storage. This can be used - /// for signature verification of transactions for the newly created - /// account. - pub account_keys: Vec, - /// The minimum number of signatures needed - pub threshold: u8, +pub struct BecomeValidator { + /// Address of an account that will become a validator. + pub address: Address, /// A key to be used for signing blocks and votes on blocks. pub consensus_key: common::PublicKey, /// An Eth bridge governance public key @@ -49,8 +44,6 @@ pub struct InitValidator { pub website: Option, /// The validator's discord handle pub discord_handle: Option, - /// The VP code for validator account - pub validator_vp_code_hash: Hash, } /// A bond is a validator's self-bond or a delegation from non-validator to a diff --git a/encoding_spec/src/main.rs b/encoding_spec/src/main.rs index 4365fd4a01..be9efdc113 100644 --- a/encoding_spec/src/main.rs +++ b/encoding_spec/src/main.rs @@ -82,7 +82,7 @@ fn main() -> Result<(), Box> { let init_account_schema = schema_container_of::(); let init_validator_schema = - schema_container_of::(); + schema_container_of::(); let token_transfer_schema = schema_container_of::(); let update_account = schema_container_of::(); diff --git a/sdk/src/args.rs b/sdk/src/args.rs index 3359c08ec4..23f1643233 100644 --- a/sdk/src/args.rs +++ b/sdk/src/args.rs @@ -723,6 +723,41 @@ impl TxInitAccount { } } +/// Transaction to initialize a new account +#[derive(Clone, Debug)] +pub struct TxBecomeValidator { + /// Common tx arguments + pub tx: Tx, + /// Address of an account that will become a validator. + pub address: C::Address, + /// Signature scheme + pub scheme: SchemeType, + /// Consensus key + pub consensus_key: Option, + /// Ethereum cold key + pub eth_cold_key: Option, + /// Ethereum hot key + pub eth_hot_key: Option, + /// Protocol key + pub protocol_key: Option, + /// Commission rate + pub commission_rate: Dec, + /// Maximum commission rate change + pub max_commission_rate_change: Dec, + /// The validator email + pub email: String, + /// The validator description + pub description: Option, + /// The validator website + pub website: Option, + /// The validator's discord handle + pub discord_handle: Option, + /// Path to the TX WASM code file + pub tx_code_path: PathBuf, + /// Don't encrypt the keypair + pub unsafe_dont_encrypt: bool, +} + /// Transaction to initialize a new account #[derive(Clone, Debug)] pub struct TxInitValidator { @@ -757,7 +792,9 @@ pub struct TxInitValidator { /// Path to the VP WASM code file pub validator_vp_code_path: PathBuf, /// Path to the TX WASM code file - pub tx_code_path: PathBuf, + pub tx_init_account_code_path: PathBuf, + /// Path to the TX WASM code file + pub tx_become_validator_code_path: PathBuf, /// Don't encrypt the keypair pub unsafe_dont_encrypt: bool, } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index b7b549f5d6..04a2c63943 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -51,11 +51,11 @@ use crate::rpc::{ use crate::signing::SigningTxData; use crate::token::DenominatedAmount; use crate::tx::{ - ProcessTxResponse, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, - TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, - TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, - TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, - TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, + ProcessTxResponse, TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, + TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM, + TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM, + TX_CLAIM_REWARDS_WASM, TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, + TX_INIT_ACCOUNT_WASM, TX_INIT_PROPOSAL, TX_REACTIVATE_VALIDATOR_WASM, TX_REDELEGATE_WASM, TX_RESIGN_STEWARD, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_UPDATE_STEWARD_COMMISSION, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, @@ -348,6 +348,33 @@ pub trait Namada<'a>: Sized { } } + /// Make a TxBecomeValidator builder from the given minimum set of arguments + fn new_become_validator( + &self, + address: Address, + commission_rate: Dec, + max_commission_rate_change: Dec, + email: String, + ) -> args::TxBecomeValidator { + args::TxBecomeValidator { + address, + commission_rate, + max_commission_rate_change, + scheme: SchemeType::Ed25519, + consensus_key: None, + eth_cold_key: None, + eth_hot_key: None, + protocol_key: None, + unsafe_dont_encrypt: false, + tx_code_path: PathBuf::from(TX_BECOME_VALIDATOR_WASM), + tx: self.tx_builder(), + email, + description: None, + website: None, + discord_handle: None, + } + } + /// Make a TxInitValidator builder from the given minimum set of arguments fn new_init_validator( &self, @@ -367,7 +394,10 @@ pub trait Namada<'a>: Sized { protocol_key: None, validator_vp_code_path: PathBuf::from(VP_USER_WASM), unsafe_dont_encrypt: false, - tx_code_path: PathBuf::from(TX_INIT_VALIDATOR_WASM), + tx_init_account_code_path: PathBuf::from(TX_INIT_ACCOUNT_WASM), + tx_become_validator_code_path: PathBuf::from( + TX_BECOME_VALIDATOR_WASM, + ), tx: self.tx_builder(), email, description: None, diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index c6262d9dd0..dd75e942f0 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -27,7 +27,7 @@ use namada_core::types::transaction::account::{InitAccount, UpdateAccount}; use namada_core::types::transaction::governance::{ InitProposalData, VoteProposalData, }; -use namada_core::types::transaction::pos::InitValidator; +use namada_core::types::transaction::pos::BecomeValidator; use namada_core::types::transaction::{pos, Fee}; use prost::Message; use rand::rngs::OsRng; @@ -48,10 +48,10 @@ use crate::masp::make_asset_type; use crate::proto::{MaspBuilder, Section, Tx}; use crate::rpc::validate_amount; use crate::tx::{ - TX_BOND_WASM, TX_CHANGE_COMMISSION_WASM, TX_CHANGE_CONSENSUS_KEY_WASM, - TX_CHANGE_METADATA_WASM, TX_CLAIM_REWARDS_WASM, - TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, TX_INIT_ACCOUNT_WASM, - TX_INIT_PROPOSAL, TX_INIT_VALIDATOR_WASM, TX_REACTIVATE_VALIDATOR_WASM, + TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_CHANGE_COMMISSION_WASM, + TX_CHANGE_CONSENSUS_KEY_WASM, TX_CHANGE_METADATA_WASM, + TX_CLAIM_REWARDS_WASM, TX_DEACTIVATE_VALIDATOR_WASM, TX_IBC_WASM, + TX_INIT_ACCOUNT_WASM, TX_INIT_PROPOSAL, TX_REACTIVATE_VALIDATOR_WASM, TX_REVEAL_PK, TX_TRANSFER_WASM, TX_UNBOND_WASM, TX_UNJAIL_VALIDATOR_WASM, TX_UPDATE_ACCOUNT_WASM, TX_VOTE_PROPOSAL, TX_WITHDRAW_WASM, VP_USER_WASM, }; @@ -1091,8 +1091,8 @@ pub async fn to_ledger_vector<'a>( format!("Threshold : {}", init_account.threshold), format!("VP type : {}", HEXLOWER.encode(&extra.code.hash().0)), ]); - } else if code_sec.tag == Some(TX_INIT_VALIDATOR_WASM.to_string()) { - let init_validator = InitValidator::try_from_slice( + } else if code_sec.tag == Some(TX_BECOME_VALIDATOR_WASM.to_string()) { + let init_validator = BecomeValidator::try_from_slice( &tx.data() .ok_or_else(|| Error::Other("Invalid Data".to_string()))?, ) @@ -1102,27 +1102,9 @@ pub async fn to_ledger_vector<'a>( tv.name = "Init_Validator_0".to_string(); - let extra = tx - .get_section(&init_validator.validator_vp_code_hash) - .and_then(|x| Section::extra_data_sec(x.as_ref())) - .ok_or_else(|| { - Error::Other("unable to load vp code".to_string()) - })?; - let vp_code = if extra.tag == Some(VP_USER_WASM.to_string()) { - "User".to_string() - } else { - HEXLOWER.encode(&extra.code.hash().0) - }; - tv.output.extend(vec!["Type : Init Validator".to_string()]); - tv.output.extend( - init_validator - .account_keys - .iter() - .map(|k| format!("Account key : {}", k)), - ); tv.output.extend(vec![ - format!("Threshold : {}", init_validator.threshold), + format!("Address : {}", init_validator.address), format!("Consensus key : {}", init_validator.consensus_key), format!("Ethereum cold key : {}", init_validator.eth_cold_key), format!("Ethereum hot key : {}", init_validator.eth_hot_key), @@ -1144,16 +1126,9 @@ pub async fn to_ledger_vector<'a>( tv.output .push(format!("Discord handle : {}", discord_handle)); } - tv.output.push(format!("Validator VP type : {}", vp_code)); - tv.output_expert.extend( - init_validator - .account_keys - .iter() - .map(|k| format!("Account key : {}", k)), - ); tv.output_expert.extend(vec![ - format!("Threshold : {}", init_validator.threshold), + format!("Address : {}", init_validator.address), format!("Consensus key : {}", init_validator.consensus_key), format!("Ethereum cold key : {}", init_validator.eth_cold_key), format!("Ethereum hot key : {}", init_validator.eth_hot_key), @@ -1176,10 +1151,6 @@ pub async fn to_ledger_vector<'a>( tv.output_expert .push(format!("Discord handle : {}", discord_handle)); } - tv.output_expert.push(format!( - "Validator VP type : {}", - HEXLOWER.encode(&extra.code.hash().0) - )); } else if code_sec.tag == Some(TX_INIT_PROPOSAL.to_string()) { let init_proposal_data = InitProposalData::try_from_slice( &tx.data() diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index e26bbff4e2..9f269ac806 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -70,8 +70,8 @@ use crate::{display_line, edisplay_line, Namada}; /// Initialize account transaction WASM pub const TX_INIT_ACCOUNT_WASM: &str = "tx_init_account.wasm"; -/// Initialize validator transaction WASM path -pub const TX_INIT_VALIDATOR_WASM: &str = "tx_init_validator.wasm"; +/// Become validator transaction WASM path +pub const TX_BECOME_VALIDATOR_WASM: &str = "tx_become_validator.wasm"; /// Unjail validator transaction WASM path pub const TX_UNJAIL_VALIDATOR_WASM: &str = "tx_unjail_validator.wasm"; /// Deactivate validator transaction WASM path diff --git a/tx_prelude/src/proof_of_stake.rs b/tx_prelude/src/proof_of_stake.rs index ec5f6f0ab8..4c78e23609 100644 --- a/tx_prelude/src/proof_of_stake.rs +++ b/tx_prelude/src/proof_of_stake.rs @@ -1,9 +1,8 @@ //! Proof of Stake system integration with functions for transactions use namada_core::types::dec::Dec; -use namada_core::types::hash::Hash; use namada_core::types::key::common; -use namada_core::types::transaction::pos::InitValidator; +use namada_core::types::transaction::pos::BecomeValidator; use namada_core::types::{key, token}; pub use namada_proof_of_stake::parameters::PosParams; use namada_proof_of_stake::types::ValidatorMetaData; @@ -12,7 +11,7 @@ use namada_proof_of_stake::{ change_validator_commission_rate, change_validator_metadata, claim_reward_tokens, deactivate_validator, reactivate_validator, read_pos_params, redelegate_tokens, unbond_tokens, unjail_validator, - withdraw_tokens, BecomeValidator, + withdraw_tokens, }; pub use namada_proof_of_stake::{parameters, types, ResultSlashing}; @@ -114,11 +113,10 @@ impl Ctx { /// Attempt to initialize a validator account. On success, returns the /// initialized validator account's address. - pub fn init_validator( + pub fn become_validator( &mut self, - InitValidator { - account_keys, - threshold, + BecomeValidator { + address, consensus_key, eth_cold_key, eth_hot_key, @@ -129,29 +127,17 @@ impl Ctx { description, website, discord_handle, - validator_vp_code_hash: _, - }: InitValidator, - validator_vp_code_hash: Hash, - validator_vp_code_tag: &Option, + }: BecomeValidator, ) -> EnvResult
{ let current_epoch = self.get_block_epoch()?; - // Init validator account - let validator_address = - self.init_account(validator_vp_code_hash, validator_vp_code_tag)?; - storage_api::account::init_account_storage( - self, - &validator_address, - &account_keys, - threshold, - )?; let eth_cold_key = key::common::PublicKey::Secp256k1(eth_cold_key); let eth_hot_key = key::common::PublicKey::Secp256k1(eth_hot_key); - let params = read_pos_params(self)?; - become_validator(BecomeValidator { + + become_validator(namada_proof_of_stake::BecomeValidator { storage: self, params: ¶ms, - address: &validator_address, + address: &address, consensus_key: &consensus_key, protocol_key: &protocol_key, eth_cold_key: ð_cold_key, @@ -168,7 +154,7 @@ impl Ctx { offset_opt: None, })?; - Ok(validator_address) + Ok(address) } /// Deactivate validator diff --git a/wasm/wasm_source/Cargo.toml b/wasm/wasm_source/Cargo.toml index c4025c1207..8e198626c2 100644 --- a/wasm/wasm_source/Cargo.toml +++ b/wasm/wasm_source/Cargo.toml @@ -23,7 +23,7 @@ tx_from_intent = ["namada_tx_prelude"] tx_ibc = ["namada_tx_prelude"] tx_init_account = ["namada_tx_prelude"] tx_init_proposal = ["namada_tx_prelude"] -tx_init_validator = ["namada_tx_prelude"] +tx_become_validator = ["namada_tx_prelude"] tx_reactivate_validator = ["namada_tx_prelude"] tx_redelegate = ["namada_tx_prelude"] tx_reveal_pk = ["namada_tx_prelude"] diff --git a/wasm/wasm_source/Makefile b/wasm/wasm_source/Makefile index 2da935ba7c..f01292af1e 100644 --- a/wasm/wasm_source/Makefile +++ b/wasm/wasm_source/Makefile @@ -15,7 +15,7 @@ wasms += tx_deactivate_validator wasms += tx_ibc wasms += tx_init_account wasms += tx_init_proposal -wasms += tx_init_validator +wasms += tx_become_validator wasms += tx_redelegate wasms += tx_reactivate_validator wasms += tx_reveal_pk diff --git a/wasm/wasm_source/src/lib.rs b/wasm/wasm_source/src/lib.rs index e44ac1564e..4e27cb92ad 100644 --- a/wasm/wasm_source/src/lib.rs +++ b/wasm/wasm_source/src/lib.rs @@ -1,3 +1,5 @@ +#[cfg(feature = "tx_become_validator")] +pub mod tx_become_validator; #[cfg(feature = "tx_bond")] pub mod tx_bond; #[cfg(feature = "tx_bridge_pool")] @@ -18,8 +20,6 @@ pub mod tx_ibc; pub mod tx_init_account; #[cfg(feature = "tx_init_proposal")] pub mod tx_init_proposal; -#[cfg(feature = "tx_init_validator")] -pub mod tx_init_validator; #[cfg(feature = "tx_reactivate_validator")] pub mod tx_reactivate_validator; #[cfg(feature = "tx_redelegate")] diff --git a/wasm/wasm_source/src/tx_become_validator.rs b/wasm/wasm_source/src/tx_become_validator.rs new file mode 100644 index 0000000000..4f959f6921 --- /dev/null +++ b/wasm/wasm_source/src/tx_become_validator.rs @@ -0,0 +1,44 @@ +//! A tx to initialize a new validator account with a given public keys and a +//! validity predicates. + +use namada_tx_prelude::transaction::pos::BecomeValidator; +use namada_tx_prelude::*; + +#[transaction(gas = 4395397)] +fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { + let signed = tx_data; + let data = signed.data().ok_or_err_msg("Missing data").map_err(|err| { + ctx.set_commitment_sentinel(); + err + })?; + let become_validator = BecomeValidator::try_from_slice(&data[..]) + .wrap_err("failed to decode InitValidator")?; + debug_log!("apply_tx called to init a new validator account"); + + // Check that the tx has been signed with all the keys to be used for the + // validator account + let all_pks = vec![ + become_validator.consensus_key.clone(), + key::common::PublicKey::Secp256k1( + become_validator.eth_cold_key.clone(), + ), + key::common::PublicKey::Secp256k1(become_validator.eth_hot_key.clone()), + become_validator.protocol_key.clone(), + ]; + if !matches!(verify_signatures_of_pks(ctx, &signed, all_pks), Ok(true)) { + debug_log!("Keys ownership signature verification failed"); + panic!() + } + + // Register the validator in PoS + match ctx.become_validator(become_validator) { + Ok(validator_address) => { + debug_log!("Created validator {}", validator_address.encode(),) + } + Err(err) => { + debug_log!("Validator creation failed with: {}", err); + panic!() + } + } + Ok(()) +} diff --git a/wasm/wasm_source/src/tx_init_validator.rs b/wasm/wasm_source/src/tx_init_validator.rs deleted file mode 100644 index f7aa70997b..0000000000 --- a/wasm/wasm_source/src/tx_init_validator.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! A tx to initialize a new validator account with a given public keys and a -//! validity predicates. - -use namada_tx_prelude::transaction::pos::InitValidator; -use namada_tx_prelude::*; - -#[transaction(gas = 4395397)] -fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { - let signed = tx_data; - let data = signed.data().ok_or_err_msg("Missing data").map_err(|err| { - ctx.set_commitment_sentinel(); - err - })?; - let init_validator = InitValidator::try_from_slice(&data[..]) - .wrap_err("failed to decode InitValidator")?; - debug_log!("apply_tx called to init a new validator account"); - - // Get the validator vp code from the extra section - let validator_vp_code_sec = signed - .get_section(&init_validator.validator_vp_code_hash) - .ok_or_err_msg("validator vp section not found") - .map_err(|err| { - ctx.set_commitment_sentinel(); - err - })? - .extra_data_sec() - .ok_or_err_msg("validator vp section must be tagged as extra") - .map_err(|err| { - ctx.set_commitment_sentinel(); - err - })?; - - // Check that the tx has been signed with all the keys to be used for the - // validator account - let mut all_pks = init_validator.account_keys.clone(); - all_pks.push(init_validator.consensus_key.clone()); - all_pks.push(key::common::PublicKey::Secp256k1( - init_validator.eth_cold_key.clone(), - )); - all_pks.push(key::common::PublicKey::Secp256k1( - init_validator.eth_hot_key.clone(), - )); - all_pks.push(init_validator.protocol_key.clone()); - if !matches!(verify_signatures_of_pks(ctx, &signed, all_pks), Ok(true)) { - debug_log!("Keys ownership signature verification failed"); - panic!() - } - - // Register the validator in PoS - match ctx.init_validator( - init_validator, - validator_vp_code_sec.code.hash(), - &validator_vp_code_sec.tag, - ) { - Ok(validator_address) => { - debug_log!("Created validator {}", validator_address.encode(),) - } - Err(err) => { - debug_log!("Validator creation failed with: {}", err); - panic!() - } - } - Ok(()) -} From 69bde2c05e73d06fe9b8242ae0d23f7c37aa8386 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 21 Nov 2023 18:24:30 +0100 Subject: [PATCH 32/54] PoS: add checks for `become_validator` --- apps/src/lib/client/rpc.rs | 8 +++ apps/src/lib/client/tx.rs | 107 +++++++++++++++++++++++++------------ core/src/types/address.rs | 10 ++++ proof_of_stake/src/lib.rs | 36 +++++++++++++ sdk/src/queries/vp/pos.rs | 15 ++++++ sdk/src/rpc.rs | 8 +++ 6 files changed, 150 insertions(+), 34 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index f696a0602b..27b4f95c3e 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -2318,6 +2318,14 @@ pub async fn is_delegator_at( .unwrap() } +/// Check if the given address is a known validator. +pub async fn has_bonds( + client: &C, + address: &Address, +) -> bool { + namada_sdk::rpc::has_bonds(client, address).await.unwrap() +} + /// Check if the address exists on chain. Established address exists if it has a /// stored validity predicate. Implicit and internal addresses always return /// true. diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index c88d231a99..af0ac2de83 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -513,6 +513,79 @@ pub async fn submit_become_validator<'a>( .or_else(|| Some(config.ledger.chain_id.clone())), ..tx_args.clone() }; + + // Check that the address is established + if !address.is_established() { + edisplay_line!( + namada.io(), + "The given address {address} is not established. Only established \ + address can become a validator.", + ); + if !tx_args.force { + safe_exit(1) + } + }; + + // Check that the address is not already a validator + if rpc::is_validator(namada.client(), &address).await { + edisplay_line!( + namada.io(), + "The given address {address} is already a validator", + ); + if !tx_args.force { + safe_exit(1) + } + }; + + // If the address is not yet a validator, it cannot have self-bonds, but it + // may have delegations. It has to unbond those before it can become a + // validator. + if rpc::has_bonds(namada.client(), &address).await { + edisplay_line!( + namada.io(), + "The given address {address} has delegations and therefore cannot \ + become a validator. To become a validator, you have to unbond \ + your delegations first.", + ); + if !tx_args.force { + safe_exit(1) + } + } + + // Validate the commission rate data + if commission_rate > Dec::one() || commission_rate < Dec::zero() { + edisplay_line!( + namada.io(), + "The validator commission rate must not exceed 1.0 or 100%, and \ + it must be 0 or positive" + ); + if !tx_args.force { + safe_exit(1) + } + } + if max_commission_rate_change > Dec::one() + || max_commission_rate_change < Dec::zero() + { + edisplay_line!( + namada.io(), + "The validator maximum change in commission rate per epoch must \ + not exceed 1.0 or 100%" + ); + if !tx_args.force { + safe_exit(1) + } + } + // Validate the email + if email.is_empty() { + edisplay_line!( + namada.io(), + "The validator email must not be an empty string" + ); + if !tx_args.force { + safe_exit(1) + } + } + let alias = tx_args .initialized_account_alias .as_ref() @@ -645,40 +718,6 @@ pub async fn submit_become_validator<'a>( ) .map_err(|err| error::Error::Other(err.to_string()))?; - // Validate the commission rate data - if commission_rate > Dec::one() || commission_rate < Dec::zero() { - edisplay_line!( - namada.io(), - "The validator commission rate must not exceed 1.0 or 100%, and \ - it must be 0 or positive" - ); - if !tx_args.force { - safe_exit(1) - } - } - if max_commission_rate_change > Dec::one() - || max_commission_rate_change < Dec::zero() - { - edisplay_line!( - namada.io(), - "The validator maximum change in commission rate per epoch must \ - not exceed 1.0 or 100%" - ); - if !tx_args.force { - safe_exit(1) - } - } - // Validate the email - if email.is_empty() { - edisplay_line!( - namada.io(), - "The validator email must not be an empty string" - ); - if !tx_args.force { - safe_exit(1) - } - } - let tx_code_hash = query_wasm_code_hash(namada, tx_code_path.to_string_lossy()) .await diff --git a/core/src/types/address.rs b/core/src/types/address.rs index 2543fc7f54..44373695a3 100644 --- a/core/src/types/address.rs +++ b/core/src/types/address.rs @@ -282,6 +282,16 @@ impl Address { } } } + + /// If the address established? + pub fn is_established(&self) -> bool { + matches!(self, Address::Established(_)) + } + + /// If the address implicit? + pub fn is_implicit(&self) -> bool { + matches!(self, Address::Implicit(_)) + } } impl string_encoding::Format for Address { diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 5aa6fb6f07..3aabb58ca6 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -2764,6 +2764,28 @@ where } = args; let offset = offset_opt.unwrap_or(params.pipeline_len); + if !address.is_established() { + return Err(storage_api::Error::new_const( + "The given address {address} is not established. Only established \ + address can become a validator.", + )); + } + + if is_validator(storage, address)? { + return Err(storage_api::Error::new_const( + "The given address is already a validator", + )); + } + + // If the address is not yet a validator, it cannot have self-bonds, but it + // may have delegations. + if has_bonds(storage, address)? { + return Err(storage_api::Error::new_const( + "The given address has delegations and therefore cannot become a \ + validator. Unbond first.", + )); + } + // This will fail if the key is already being used try_insert_consensus_key(storage, consensus_key)?; @@ -3623,6 +3645,20 @@ where Ok(delegations) } +/// Find if the given source address has any bonds. +pub fn has_bonds(storage: &S, source: &Address) -> storage_api::Result +where + S: StorageRead, +{ + let max_epoch = Epoch(u64::MAX); + let delegations = find_delegations(storage, source, &max_epoch)?; + Ok(!delegations + .values() + .cloned() + .sum::() + .is_zero()) +} + /// Find PoS slashes applied to a validator, if any pub fn find_validator_slashes( storage: &S, diff --git a/sdk/src/queries/vp/pos.rs b/sdk/src/queries/vp/pos.rs index 8a464179f1..0a4777514a 100644 --- a/sdk/src/queries/vp/pos.rs +++ b/sdk/src/queries/vp/pos.rs @@ -113,6 +113,9 @@ router! {POS, ( "consensus_keys" ) -> BTreeSet = consensus_key_set, + ( "has_bonds" / [source: Address] ) + -> bool = has_bonds, + } /// Enriched bonds data with extra information calculated from the data queried @@ -597,6 +600,18 @@ where namada_proof_of_stake::get_consensus_key_set(ctx.wl_storage) } +/// Find if the given source address has any bonds. +fn has_bonds( + ctx: RequestCtx<'_, D, H, V, T>, + source: Address, +) -> storage_api::Result +where + D: 'static + DB + for<'iter> DBIter<'iter> + Sync, + H: 'static + StorageHasher + Sync, +{ + namada_proof_of_stake::has_bonds(ctx.wl_storage, &source) +} + /// Client-only methods for the router type are composed from router functions. #[cfg(any(test, feature = "async-client"))] pub mod client_only_methods { diff --git a/sdk/src/rpc.rs b/sdk/src/rpc.rs index 0d0d69a79b..3e18c686b9 100644 --- a/sdk/src/rpc.rs +++ b/sdk/src/rpc.rs @@ -213,6 +213,14 @@ pub async fn is_delegator_at( ) } +/// Find if the given source address has any bonds. +pub async fn has_bonds( + client: &C, + source: &Address, +) -> Result { + convert_response::(RPC.vp().pos().has_bonds(client, source).await) +} + /// Get the set of consensus keys registered in the network pub async fn get_consensus_keys( client: &C, From 6ab8fc6f32136376d0b7bc69eaa87a040ee663e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 22 Nov 2023 11:22:23 +0100 Subject: [PATCH 33/54] wasm/vp_user: add authorization for tx_become_validator --- wasm/wasm_source/src/vp_user.rs | 184 +++++++++++++++++++++++++++++++- 1 file changed, 183 insertions(+), 1 deletion(-) diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index c6b7d6920e..390bc389fb 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -191,6 +191,10 @@ fn validate_tx( true } } + (None, Some(_post)) => { + // Becoming a validator must be authorized + *valid_sig + } _ => true, } } @@ -259,7 +263,7 @@ mod tests { use namada::proto::{Code, Data, Signature}; use namada::types::dec::Dec; use namada::types::storage::Epoch; - use namada::types::transaction::TxType; + use namada::types::transaction::{self, TxType}; use namada_test_utils::TestWasms; // Use this as `#[test]` annotation to enable logging use namada_tests::log::test; @@ -551,6 +555,90 @@ mod tests { ); } + /// Test that a PoS action to become validator that must be authorized is + /// rejected without a valid signature. + #[test] + fn test_unsigned_become_validator_pos_action_rejected() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); + let eth_hot_key = key::testing::keypair_4().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator, + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key, + eth_cold_key, + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let vp_owner: Address = address::testing::established_address_2(); + + // Spawn the accounts to be able to modify their storage + tx_env.init_account_storage(&vp_owner, vec![public_key], 1); + + // Initialize VP environment from PoS action to become a validator + vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { + let consensus_key = key::common::PublicKey::Ed25519( + key::testing::gen_keypair::().ref_to(), + ); + let protocol_key = key::common::PublicKey::Ed25519( + key::testing::gen_keypair::().ref_to(), + ); + let eth_cold_key = + key::testing::gen_keypair::() + .ref_to(); + let eth_hot_key = + key::testing::gen_keypair::() + .ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + let args = transaction::pos::BecomeValidator { + address: address.clone(), + consensus_key, + eth_cold_key, + eth_hot_key, + protocol_key, + commission_rate, + max_commission_rate_change, + email: "cucumber@tastes.good".to_string(), + description: None, + website: None, + discord_handle: None, + }; + tx::ctx().become_validator(args).unwrap(); + }); + + let vp_env = vp_host_env::take(); + let mut tx_data = Tx::from_type(TxType::Raw); + tx_data.set_data(Data::new(vec![])); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + !validate_tx(&CTX, tx_data, vp_owner, keys_changed, verifiers) + .unwrap() + ); + } + /// Test that a validator PoS action that must be authorized is rejected /// without a valid signature. #[test] @@ -736,6 +824,100 @@ mod tests { ); } + /// Test that a signed PoS action to become validator that must be + /// authorized is accepted with a valid signature. + #[test] + fn test_signed_become_validator_pos_action_accepted() { + // Init PoS genesis + let pos_params = PosParams::default(); + let validator = address::testing::established_address_3(); + let initial_stake = token::Amount::from_uint(10_098_123, 0).unwrap(); + let consensus_key = key::testing::keypair_2().ref_to(); + let protocol_key = key::testing::keypair_1().ref_to(); + let eth_cold_key = key::testing::keypair_3().ref_to(); + let eth_hot_key = key::testing::keypair_4().ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + + let genesis_validators = [GenesisValidator { + address: validator, + tokens: initial_stake, + consensus_key, + protocol_key, + commission_rate, + max_commission_rate_change, + eth_hot_key, + eth_cold_key, + metadata: Default::default(), + }]; + + init_pos(&genesis_validators[..], &pos_params, Epoch(0)); + + // Initialize a tx environment + let mut tx_env = tx_host_env::take(); + + let secret_key = key::testing::keypair_1(); + let public_key = secret_key.ref_to(); + let vp_owner: Address = address::testing::established_address_2(); + + // Spawn the accounts to be able to modify their storage + tx_env.init_account_storage(&vp_owner, vec![public_key.clone()], 1); + + // Initialize VP environment from PoS action to become a validator + vp_host_env::init_from_tx(vp_owner.clone(), tx_env, |address| { + let consensus_key = key::common::PublicKey::Ed25519( + key::testing::gen_keypair::().ref_to(), + ); + let protocol_key = key::common::PublicKey::Ed25519( + key::testing::gen_keypair::().ref_to(), + ); + let eth_cold_key = + key::testing::gen_keypair::() + .ref_to(); + let eth_hot_key = + key::testing::gen_keypair::() + .ref_to(); + let commission_rate = Dec::new(5, 2).unwrap(); + let max_commission_rate_change = Dec::new(1, 2).unwrap(); + let args = transaction::pos::BecomeValidator { + address: address.clone(), + consensus_key, + eth_cold_key, + eth_hot_key, + protocol_key, + commission_rate, + max_commission_rate_change, + email: "cucumber@tastes.good".to_string(), + description: None, + website: None, + discord_handle: None, + }; + tx::ctx().become_validator(args).unwrap(); + }); + + let pks_map = AccountPublicKeysMap::from_iter(vec![public_key]); + + let mut vp_env = vp_host_env::take(); + let mut tx = vp_env.tx.clone(); + tx.set_data(Data::new(vec![])); + tx.set_code(Code::new(vec![], None)); + tx.add_section(Section::Signature(Signature::new( + vec![tx.raw_header_hash()], + pks_map.index_secret_keys(vec![secret_key]), + None, + ))); + let signed_tx = tx.clone(); + vp_env.tx = signed_tx.clone(); + let keys_changed: BTreeSet = + vp_env.all_touched_storage_keys(); + let verifiers: BTreeSet
= BTreeSet::default(); + vp_host_env::set(vp_env); + assert!( + validate_tx(&CTX, signed_tx, vp_owner, keys_changed, verifiers) + .unwrap() + ); + } + /// Test that a validator PoS action that must be authorized is accepted /// with a valid signature. #[test] From b315986f74cc3a860427f6a94399f190c851d1e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 22 Nov 2023 12:49:56 +0100 Subject: [PATCH 34/54] test/pos: `become_validator` fails on account with delegations --- apps/src/lib/node/ledger/shell/init_chain.rs | 2 +- .../shell/vote_extensions/bridge_pool_vext.rs | 30 ++++--- ethereum_bridge/src/test_utils.rs | 30 ++++--- proof_of_stake/src/lib.rs | 36 ++++---- proof_of_stake/src/tests.rs | 87 +++++++++++++++---- proof_of_stake/src/tests/state_machine.rs | 30 ++++--- proof_of_stake/src/tests/state_machine_v2.rs | 30 ++++--- tx_prelude/src/proof_of_stake.rs | 38 ++++---- 8 files changed, 172 insertions(+), 111 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/init_chain.rs b/apps/src/lib/node/ledger/shell/init_chain.rs index aad1fcc362..1f612b2f26 100644 --- a/apps/src/lib/node/ledger/shell/init_chain.rs +++ b/apps/src/lib/node/ledger/shell/init_chain.rs @@ -448,8 +448,8 @@ where // TODO: replace pos::init_genesis validators arg with // init_genesis_validator from here if let Err(err) = pos::namada_proof_of_stake::become_validator( + &mut self.wl_storage, BecomeValidator { - storage: &mut self.wl_storage, params, address, consensus_key: &consensus_key.pk.raw, diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs index 2486d2d442..5e4f34ac2c 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/bridge_pool_vext.rs @@ -249,20 +249,22 @@ mod test_bp_vote_extensions { let hot_key = gen_secp256k1_keypair(); let cold_key = gen_secp256k1_keypair(); - become_validator(BecomeValidator { - storage: &mut shell.wl_storage, - params: ¶ms, - address: &bertha_address(), - consensus_key: &consensus_key.ref_to(), - protocol_key: &protocol_key.ref_to(), - eth_hot_key: &hot_key.ref_to(), - eth_cold_key: &cold_key.ref_to(), - current_epoch: 0.into(), - commission_rate: Default::default(), - max_commission_rate_change: Default::default(), - metadata: Default::default(), - offset_opt: None, - }) + become_validator( + &mut shell.wl_storage, + BecomeValidator { + params: ¶ms, + address: &bertha_address(), + consensus_key: &consensus_key.ref_to(), + protocol_key: &protocol_key.ref_to(), + eth_hot_key: &hot_key.ref_to(), + eth_cold_key: &cold_key.ref_to(), + current_epoch: 0.into(), + commission_rate: Default::default(), + max_commission_rate_change: Default::default(), + metadata: Default::default(), + offset_opt: None, + }, + ) .expect("Test failed"); // we advance forward to the next epoch diff --git a/ethereum_bridge/src/test_utils.rs b/ethereum_bridge/src/test_utils.rs index 3552b27bf9..cbaf10b38e 100644 --- a/ethereum_bridge/src/test_utils.rs +++ b/ethereum_bridge/src/test_utils.rs @@ -270,20 +270,22 @@ pub fn append_validators_to_storage( let eth_cold_key = &keys.eth_gov.ref_to(); let eth_hot_key = &keys.eth_bridge.ref_to(); - become_validator(BecomeValidator { - storage: wl_storage, - params: ¶ms, - address: &validator, - consensus_key, - protocol_key, - eth_cold_key, - eth_hot_key, - current_epoch, - commission_rate: Dec::new(5, 2).unwrap(), - max_commission_rate_change: Dec::new(1, 2).unwrap(), - metadata: Default::default(), - offset_opt: Some(1), - }) + become_validator( + wl_storage, + BecomeValidator { + params: ¶ms, + address: &validator, + consensus_key, + protocol_key, + eth_cold_key, + eth_hot_key, + current_epoch, + commission_rate: Dec::new(5, 2).unwrap(), + max_commission_rate_change: Dec::new(1, 2).unwrap(), + metadata: Default::default(), + offset_opt: Some(1), + }, + ) .expect("Test failed"); credit_tokens(wl_storage, &staking_token, &validator, stake) .expect("Test failed"); diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 3aabb58ca6..6e77eb4c04 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -2714,9 +2714,7 @@ where } /// Arguments to [`become_validator`]. -pub struct BecomeValidator<'a, S> { - /// Storage implementation. - pub storage: &'a mut S, +pub struct BecomeValidator<'a> { /// Proof-of-stake parameters. pub params: &'a PosParams, /// The validator's address. @@ -2743,13 +2741,13 @@ pub struct BecomeValidator<'a, S> { /// Initialize data for a new validator. pub fn become_validator( - args: BecomeValidator<'_, S>, + storage: &mut S, + args: BecomeValidator<'_>, ) -> storage_api::Result<()> where S: StorageRead + StorageWrite, { let BecomeValidator { - storage, params, address, consensus_key, @@ -5861,20 +5859,22 @@ pub mod test_utils { metadata, } in validators { - become_validator(BecomeValidator { + become_validator( storage, - params, - address: &address, - consensus_key: &consensus_key, - protocol_key: &protocol_key, - eth_cold_key: ð_cold_key, - eth_hot_key: ð_hot_key, - current_epoch, - commission_rate, - max_commission_rate_change, - metadata, - offset_opt: Some(0), - })?; + BecomeValidator { + params, + address: &address, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate, + max_commission_rate_change, + metadata, + offset_opt: Some(0), + }, + )?; // Credit token amount to be bonded to the validator address so it // can be bonded let staking_token = staking_token_address(storage); diff --git a/proof_of_stake/src/tests.rs b/proof_of_stake/src/tests.rs index 6beedb955d..0398a7b3d7 100644 --- a/proof_of_stake/src/tests.rs +++ b/proof_of_stake/src/tests.rs @@ -1027,7 +1027,25 @@ fn test_become_validator_aux( ); assert!(!is_validator(&s, &new_validator).unwrap()); - // Initialize the validator account + // Credit the `new_validator` account + let staking_token = staking_token_address(&s); + let amount = token::Amount::from_uint(100_500_000, 0).unwrap(); + // Credit twice the amount as we're gonna bond it in delegation first, then + // self-bond + credit_tokens(&mut s, &staking_token, &new_validator, amount * 2).unwrap(); + + // Add a delegation from `new_validator` to `genesis_validator` + let genesis_validator = &validators.first().unwrap().address; + bond_tokens( + &mut s, + Some(&new_validator), + genesis_validator, + amount, + current_epoch, + None, + ) + .unwrap(); + let consensus_key = new_validator_consensus_key.to_public(); let protocol_sk = common_sk_from_simple_seed(0); let protocol_key = protocol_sk.to_public(); @@ -1037,21 +1055,57 @@ fn test_become_validator_aux( let eth_cold_key = key::common::PublicKey::Secp256k1( key::testing::gen_keypair::().ref_to(), ); - become_validator(BecomeValidator { - storage: &mut s, - params: ¶ms, - address: &new_validator, - consensus_key: &consensus_key, - protocol_key: &protocol_key, - eth_cold_key: ð_cold_key, - eth_hot_key: ð_hot_key, + + // Try to become a validator - it should fail as there is a delegation + let result = become_validator( + &mut s, + BecomeValidator { + params: ¶ms, + address: &new_validator, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate: Dec::new(5, 2).expect("Dec creation failed"), + max_commission_rate_change: Dec::new(5, 2) + .expect("Dec creation failed"), + metadata: Default::default(), + offset_opt: None, + }, + ); + assert!(result.is_err()); + assert!(!is_validator(&s, &new_validator).unwrap()); + + // Unbond the delegation + unbond_tokens( + &mut s, + Some(&new_validator), + genesis_validator, + amount, current_epoch, - commission_rate: Dec::new(5, 2).expect("Dec creation failed"), - max_commission_rate_change: Dec::new(5, 2) - .expect("Dec creation failed"), - metadata: Default::default(), - offset_opt: None, - }) + false, + ) + .unwrap(); + + // Try to become a validator account again - it should pass now + become_validator( + &mut s, + BecomeValidator { + params: ¶ms, + address: &new_validator, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate: Dec::new(5, 2).expect("Dec creation failed"), + max_commission_rate_change: Dec::new(5, 2) + .expect("Dec creation failed"), + metadata: Default::default(), + offset_opt: None, + }, + ) .unwrap(); assert!(is_validator(&s, &new_validator).unwrap()); @@ -1066,9 +1120,6 @@ fn test_become_validator_aux( current_epoch = advance_epoch(&mut s, ¶ms); // Self-bond to the new validator - let staking_token = staking_token_address(&s); - let amount = token::Amount::from_uint(100_500_000, 0).unwrap(); - credit_tokens(&mut s, &staking_token, &new_validator, amount).unwrap(); bond_tokens(&mut s, None, &new_validator, amount, current_epoch, None) .unwrap(); diff --git a/proof_of_stake/src/tests/state_machine.rs b/proof_of_stake/src/tests/state_machine.rs index 9681c6f409..781d276105 100644 --- a/proof_of_stake/src/tests/state_machine.rs +++ b/proof_of_stake/src/tests/state_machine.rs @@ -264,20 +264,22 @@ impl StateMachineTest for ConcretePosState { tracing::debug!("\nCONCRETE Init validator"); let current_epoch = state.current_epoch(); - super::become_validator(super::BecomeValidator { - storage: &mut state.s, - params: ¶ms, - address: &address, - consensus_key: &consensus_key, - protocol_key: &protocol_key, - eth_cold_key: ð_cold_key, - eth_hot_key: ð_hot_key, - current_epoch, - commission_rate, - max_commission_rate_change, - metadata: Default::default(), - offset_opt: None, - }) + super::become_validator( + &mut state.s, + super::BecomeValidator { + params: ¶ms, + address: &address, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate, + max_commission_rate_change, + metadata: Default::default(), + offset_opt: None, + }, + ) .unwrap(); let params = read_pos_params(&state.s).unwrap(); diff --git a/proof_of_stake/src/tests/state_machine_v2.rs b/proof_of_stake/src/tests/state_machine_v2.rs index 70b0216d0b..cf59a59238 100644 --- a/proof_of_stake/src/tests/state_machine_v2.rs +++ b/proof_of_stake/src/tests/state_machine_v2.rs @@ -1992,20 +1992,22 @@ impl StateMachineTest for ConcretePosState { tracing::debug!("\nCONCRETE Init validator"); let current_epoch = state.current_epoch(); - super::become_validator(super::BecomeValidator { - storage: &mut state.s, - params: ¶ms, - address: &address, - consensus_key: &consensus_key, - protocol_key: &protocol_key, - eth_cold_key: ð_cold_key, - eth_hot_key: ð_hot_key, - current_epoch, - commission_rate, - max_commission_rate_change, - metadata: Default::default(), - offset_opt: None, - }) + super::become_validator( + &mut state.s, + super::BecomeValidator { + params: ¶ms, + address: &address, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate, + max_commission_rate_change, + metadata: Default::default(), + offset_opt: None, + }, + ) .unwrap(); let params = read_pos_params(&state.s).unwrap(); diff --git a/tx_prelude/src/proof_of_stake.rs b/tx_prelude/src/proof_of_stake.rs index 4c78e23609..15250e760a 100644 --- a/tx_prelude/src/proof_of_stake.rs +++ b/tx_prelude/src/proof_of_stake.rs @@ -134,25 +134,27 @@ impl Ctx { let eth_hot_key = key::common::PublicKey::Secp256k1(eth_hot_key); let params = read_pos_params(self)?; - become_validator(namada_proof_of_stake::BecomeValidator { - storage: self, - params: ¶ms, - address: &address, - consensus_key: &consensus_key, - protocol_key: &protocol_key, - eth_cold_key: ð_cold_key, - eth_hot_key: ð_hot_key, - current_epoch, - commission_rate, - max_commission_rate_change, - metadata: ValidatorMetaData { - email, - description, - website, - discord_handle, + become_validator( + self, + namada_proof_of_stake::BecomeValidator { + params: ¶ms, + address: &address, + consensus_key: &consensus_key, + protocol_key: &protocol_key, + eth_cold_key: ð_cold_key, + eth_hot_key: ð_hot_key, + current_epoch, + commission_rate, + max_commission_rate_change, + metadata: ValidatorMetaData { + email, + description, + website, + discord_handle, + }, + offset_opt: None, }, - offset_opt: None, - })?; + )?; Ok(address) } From 3736701629ff23366d43f11f1f82a3cbc1e9e50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 22 Nov 2023 12:58:20 +0100 Subject: [PATCH 35/54] benches: update for `become_validator` --- benches/txs.rs | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/benches/txs.rs b/benches/txs.rs index 97a4e16945..f41ca0c896 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -25,11 +25,11 @@ use namada::ibc::core::ics24_host::identifier::{ ClientId, ConnectionId, PortId, }; use namada::ledger::eth_bridge::read_native_erc20_address; -use namada::ledger::storage_api::StorageRead; +use namada::ledger::storage_api::{StorageRead, StorageWrite}; use namada::proof_of_stake::types::SlashType; use namada::proof_of_stake::{self, read_pos_params, KeySeg}; use namada::proto::{Code, Section}; -use namada::types::address::Address; +use namada::types::address::{self, Address}; use namada::types::eth_bridge_pool::{GasFee, PendingTransfer}; use namada::types::hash::Hash; use namada::types::key::{ed25519, secp256k1, PublicKey, RefTo}; @@ -586,8 +586,9 @@ fn vote_proposal(c: &mut Criterion) { group.finish(); } -fn init_validator(c: &mut Criterion) { +fn become_validator(c: &mut Criterion) { let mut csprng = rand::rngs::OsRng {}; + let address = address::testing::established_address_1(); let consensus_key_sk = ed25519::SigScheme::generate(&mut csprng) .try_to_sk::() .unwrap(); @@ -612,22 +613,8 @@ fn init_validator(c: &mut Criterion) { let protocol_key = protocol_key_sk.to_public(); let shell = BenchShell::default(); - let validator_vp_code_hash: Hash = shell - .read_storage_key(&Key::wasm_hash(VP_USER_WASM)) - .unwrap(); - let extra_section = Section::ExtraData(Code::from_hash( - validator_vp_code_hash, - Some(VP_USER_WASM.to_string()), - )); - let extra_hash = Hash( - extra_section - .hash(&mut sha2::Sha256::new()) - .finalize_reset() - .into(), - ); let data = BecomeValidator { - account_keys: vec![defaults::albert_keypair().to_public()], - threshold: 1, + address: address.clone(), consensus_key, eth_cold_key, eth_hot_key, @@ -638,13 +625,12 @@ fn init_validator(c: &mut Criterion) { description: None, website: None, discord_handle: None, - validator_vp_code_hash: extra_hash, }; let tx = shell.generate_tx( TX_BECOME_VALIDATOR_WASM, data, None, - Some(vec![extra_section]), + None, vec![ &defaults::albert_keypair(), &consensus_key_sk, @@ -654,9 +640,22 @@ fn init_validator(c: &mut Criterion) { ], ); - c.bench_function("init_validator", |b| { + c.bench_function("become_validator", |b| { b.iter_batched_ref( - BenchShell::default, + || { + let mut shell = BenchShell::default(); + // Initialize the account to be able to use it + shell + .wl_storage + .write_bytes( + &namada::types::storage::Key::validity_predicate( + &address, + ), + vec![], + ) + .unwrap(); + shell + }, |shell| shell.execute_tx(&tx), criterion::BatchSize::SmallInput, ) @@ -1089,7 +1088,7 @@ criterion_group!( init_account, init_proposal, vote_proposal, - init_validator, + become_validator, change_validator_commission, ibc, unjail_validator, From 4b3fe18739c6cacfeadb4d75eb9939f8b5666828 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Wed, 22 Nov 2023 13:52:04 +0100 Subject: [PATCH 36/54] changelog: add #2208 --- .../improvements/2208-init-validator-wo-account.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .changelog/unreleased/improvements/2208-init-validator-wo-account.md diff --git a/.changelog/unreleased/improvements/2208-init-validator-wo-account.md b/.changelog/unreleased/improvements/2208-init-validator-wo-account.md new file mode 100644 index 0000000000..f12ec7704f --- /dev/null +++ b/.changelog/unreleased/improvements/2208-init-validator-wo-account.md @@ -0,0 +1,9 @@ +- A new `tx_become_validator` replaces `tx_init_validator`. This tx doesn't + initialize a new account and instead it modifies an existing established + address to become a validator. This currently requires that there are no + delegations on the source account before it can become a validator (if there + are some, they have to be unbonded, but they don't have to be withdrawn). + A new client command `become-validator` is added that requires an `--address`. + The client command `init-validator` is kept for convenience and updated to + send `tx_init_account` tx before `tx_become_validator`. + ([\#2208](https://github.com/anoma/namada/pull/2208)) \ No newline at end of file From 127c8188c81e651f0f2fbeab5a1c178ff433fd6d Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 22 Nov 2023 13:38:09 -0800 Subject: [PATCH 37/54] cli: fix metadata args to validator initialization txs --- apps/src/lib/cli.rs | 44 ++++++++------------------------------------ 1 file changed, 8 insertions(+), 36 deletions(-) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index f6ac24a6fd..412f289789 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -4147,24 +4147,10 @@ pub mod args { Expressed as a decimal between 0 and 1. This is a \ required parameter.", )) - .arg(EMAIL_OPT.def().help( - "The desired new validator email. To remove the existing \ - email, pass an empty string to this argument.", - )) - .arg(DESCRIPTION_OPT.def().help( - "The desired new validator description. To remove the \ - existing description, pass an empty string to this \ - argument.", - )) - .arg(WEBSITE_OPT.def().help( - "The desired new validator website. To remove the \ - existing website, pass an empty string to this argument.", - )) - .arg(DISCORD_OPT.def().help( - "The desired new validator discord handle. To remove the \ - existing discord handle, pass an empty string to this \ - argument.", - )) + .arg(EMAIL.def().help("The validator's email.")) + .arg(DESCRIPTION_OPT.def().help("The validator's description.")) + .arg(WEBSITE_OPT.def().help("The validator's website.")) + .arg(DISCORD_OPT.def().help("The validator's discord handle.")) .arg(VALIDATOR_CODE_PATH.def().help( "The path to the validity predicate WASM code to be used \ for the validator account. Uses the default validator VP \ @@ -4305,24 +4291,10 @@ pub mod args { Expressed as a decimal between 0 and 1. This is a \ required parameter.", )) - .arg(EMAIL_OPT.def().help( - "The desired new validator email. To remove the existing \ - email, pass an empty string to this argument.", - )) - .arg(DESCRIPTION_OPT.def().help( - "The desired new validator description. To remove the \ - existing description, pass an empty string to this \ - argument.", - )) - .arg(WEBSITE_OPT.def().help( - "The desired new validator website. To remove the \ - existing website, pass an empty string to this argument.", - )) - .arg(DISCORD_OPT.def().help( - "The desired new validator discord handle. To remove the \ - existing discord handle, pass an empty string to this \ - argument.", - )) + .arg(EMAIL.def().help("The validator's email.")) + .arg(DESCRIPTION_OPT.def().help("The validator's description.")) + .arg(WEBSITE_OPT.def().help("The validator's website.")) + .arg(DISCORD_OPT.def().help("The validator's discord handle.")) .arg(VALIDATOR_CODE_PATH.def().help( "The path to the validity predicate WASM code to be used \ for the validator account. Uses the default validator VP \ From 0863e04143c03611c58b9e2b259caf3f1b226fa6 Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 22 Nov 2023 13:17:39 -0800 Subject: [PATCH 38/54] cli: fix help and err messages --- apps/src/lib/cli.rs | 2 +- apps/src/lib/client/tx.rs | 10 +++++----- proof_of_stake/src/lib.rs | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 412f289789..0bab1938cb 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -1434,7 +1434,7 @@ pub mod cmds { fn def() -> App { App::new(Self::CMD) .about( - "Send a signed transaction to create a established \ + "Send a signed transaction to create an established \ account and then become a validator.", ) .add_args::>() diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index af0ac2de83..7f2f2f930b 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -518,8 +518,8 @@ pub async fn submit_become_validator<'a>( if !address.is_established() { edisplay_line!( namada.io(), - "The given address {address} is not established. Only established \ - address can become a validator.", + "The given address {address} is not established. Only an \ + established address can become a validator.", ); if !tx_args.force { safe_exit(1) @@ -557,7 +557,7 @@ pub async fn submit_become_validator<'a>( edisplay_line!( namada.io(), "The validator commission rate must not exceed 1.0 or 100%, and \ - it must be 0 or positive" + it must be 0 or positive." ); if !tx_args.force { safe_exit(1) @@ -569,7 +569,7 @@ pub async fn submit_become_validator<'a>( edisplay_line!( namada.io(), "The validator maximum change in commission rate per epoch must \ - not exceed 1.0 or 100%" + not exceed 1.0 or 100%, and it must be 0 or positive." ); if !tx_args.force { safe_exit(1) @@ -579,7 +579,7 @@ pub async fn submit_become_validator<'a>( if email.is_empty() { edisplay_line!( namada.io(), - "The validator email must not be an empty string" + "The validator email must not be an empty string." ); if !tx_args.force { safe_exit(1) diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index 6e77eb4c04..4ab419905b 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -2764,8 +2764,8 @@ where if !address.is_established() { return Err(storage_api::Error::new_const( - "The given address {address} is not established. Only established \ - address can become a validator.", + "The given address {address} is not established. Only an \ + established address can become a validator.", )); } From 8159327a0296aa766bf009aad6e317fca7f3772d Mon Sep 17 00:00:00 2001 From: brentstone Date: Wed, 22 Nov 2023 14:19:31 -0800 Subject: [PATCH 39/54] fix docstrings --- apps/src/lib/client/rpc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index 27b4f95c3e..788e54a80b 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -2288,7 +2288,7 @@ pub async fn get_public_key( rpc::get_public_key_at(client, address, index).await } -/// Check if the given address is a known validator. +/// Check if the given address has any bonds. pub async fn is_validator( client: &C, address: &Address, @@ -2318,7 +2318,7 @@ pub async fn is_delegator_at( .unwrap() } -/// Check if the given address is a known validator. +/// Check if the given address has any bonds. pub async fn has_bonds( client: &C, address: &Address, From ff68f7b85d84671b59d0e7e767dc8ff3bc986469 Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 23 Nov 2023 22:42:43 +0100 Subject: [PATCH 40/54] remove unneeded write --- apps/src/lib/node/ledger/storage/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index 2fd1fc5aa8..0a433fd8f6 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -620,9 +620,6 @@ mod tests { let bytes = types::encode(&nonce); storage.write(&bp_nonce_key, bytes).unwrap(); - let bytes = types::encode(&Uint::default()); - storage.write(&bp_nonce_key, bytes).unwrap(); - storage.block.epoch = storage.block.epoch.next(); storage.block.pred_epochs.new_epoch(BlockHeight(6)); let batch = PersistentStorage::batch(); From 970c1803ec80e7eda3b40b6e106fa454e59224b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Fri, 24 Nov 2023 09:24:40 +0100 Subject: [PATCH 41/54] fixup! Merge branch 'tomas/combine-user-validator-vp' (#2202) --- ...D6D32B22A46CEDD254F52B6C69E813898FE60B.bin | Bin 0 -> 10382 bytes ...A57D1F470F585C2F4633E5103CB67AE2726938.bin | Bin 0 -> 7448 bytes ...13CAF693649A17FBEE435298C9C1624C6060F2.bin | Bin 0 -> 7448 bytes ...5DB11F0B17E6564F3AA56244770F24B56FC18B.bin | Bin 0 -> 7448 bytes ...3F779253B53A9A0BD62FD3DF8F6FCF4AF1E145.bin | Bin 17018 -> 0 bytes ...BF9BC175A70082068C8785BDDBF49DCCA4BE66.bin | Bin 7448 -> 0 bytes ...BD9698F791D337CEF8DE82C684C1A1279D772E.bin | Bin 0 -> 9649 bytes ...2279865699251D54141F79A4989D5343D72681.bin | Bin 0 -> 7448 bytes ...92A006D0519A21D3F1D72D7D930324584CD2DE.bin | Bin 0 -> 9941 bytes ...C89879834677F926130D56EB5E4067728EB5CF.bin | Bin 10382 -> 0 bytes ...BE50202AF004DFD895A721EDA284D96B253ACC.bin | Bin 7448 -> 0 bytes ...1508A065BC804ED18DA58F0064137E1251EED.bin} | Bin 9941 -> 9941 bytes ...3CEA99A9BC66B2BAB03D4ABA1AE57B12596061.bin | Bin 7448 -> 0 bytes ...F136D4522BAFC99E0E81FD54A28A38E8419CFC.bin | Bin 20518 -> 0 bytes ...596406702B1323505211981C8DABB0FDC6B41B.bin | Bin 0 -> 24494 bytes ...6D2CF14C7F9E90A8588BA75DA0D2860F36E2CB.bin | Bin 9649 -> 0 bytes ...396732D2EBF77728D2772EB251123DF2CEF6A1.bin | Bin 9941 -> 0 bytes ...5CF776D5DE7C9153D67B7FDF22ED6F35558738.bin | Bin 24494 -> 0 bytes ...DBA1FDB2515DF33D43611F2860B8D3C178B474.bin | Bin 7448 -> 0 bytes ...0F348721EF5366FDD8E62B9062254B2D286E0F.bin | Bin 0 -> 15257 bytes ...57D436A33F919BC377C8C6EE7A8DC8D210A6D9.bin | Bin 0 -> 17018 bytes ...D2D1A30B9CFAD55AA750B6CC36A4BD55D6BD2B.bin | Bin 0 -> 15597 bytes ...6C8B75587507CA52981F48FD1FC9C5BE0BEE43.bin | Bin 15257 -> 0 bytes ...AF47822630FC911AF7F91B196C540372EC0E8.bin} | Bin 7448 -> 7448 bytes 24 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 test_fixtures/masp_proofs/0075192A544500F2AD0C92E1A2D6D32B22A46CEDD254F52B6C69E813898FE60B.bin create mode 100644 test_fixtures/masp_proofs/341E00D564C672701199B58E69A57D1F470F585C2F4633E5103CB67AE2726938.bin create mode 100644 test_fixtures/masp_proofs/4F74C729C8F775EF554F4475BD13CAF693649A17FBEE435298C9C1624C6060F2.bin create mode 100644 test_fixtures/masp_proofs/51034B90AF95B8899A631D37B45DB11F0B17E6564F3AA56244770F24B56FC18B.bin delete mode 100644 test_fixtures/masp_proofs/51EF94B13138B91DB3081F95193F779253B53A9A0BD62FD3DF8F6FCF4AF1E145.bin delete mode 100644 test_fixtures/masp_proofs/544F7432B95E26E312105FB804BF9BC175A70082068C8785BDDBF49DCCA4BE66.bin create mode 100644 test_fixtures/masp_proofs/5F7D9B39ABA3A1CF6A124CFC26BD9698F791D337CEF8DE82C684C1A1279D772E.bin create mode 100644 test_fixtures/masp_proofs/650AB811C362FB33B9190DDA9D2279865699251D54141F79A4989D5343D72681.bin create mode 100644 test_fixtures/masp_proofs/68380B89FFFC47364F7AA8D3F992A006D0519A21D3F1D72D7D930324584CD2DE.bin delete mode 100644 test_fixtures/masp_proofs/6DD5A788D36258E9D5FEF454DBC89879834677F926130D56EB5E4067728EB5CF.bin delete mode 100644 test_fixtures/masp_proofs/6E92D0B97A65FB5ADFA6371A6CBE50202AF004DFD895A721EDA284D96B253ACC.bin rename test_fixtures/masp_proofs/{B947FEFC6EC94A041657FF3A9420D5BB3FDEB1199EF712C059C80C4DBF6F3ED8.bin => 75FB5C5ECE98BF9246CED847F2F1508A065BC804ED18DA58F0064137E1251EED.bin} (54%) delete mode 100644 test_fixtures/masp_proofs/8032CA7B951C625E43F48AEBD53CEA99A9BC66B2BAB03D4ABA1AE57B12596061.bin delete mode 100644 test_fixtures/masp_proofs/8A79BF5E0292339E70287DB626F136D4522BAFC99E0E81FD54A28A38E8419CFC.bin create mode 100644 test_fixtures/masp_proofs/A14785AC0F54CDB43F6DCE5AFB596406702B1323505211981C8DABB0FDC6B41B.bin delete mode 100644 test_fixtures/masp_proofs/A8A9963AC2983B576BAE4DE9BA6D2CF14C7F9E90A8588BA75DA0D2860F36E2CB.bin delete mode 100644 test_fixtures/masp_proofs/AEA19C9B07742FF5F6D759B171396732D2EBF77728D2772EB251123DF2CEF6A1.bin delete mode 100644 test_fixtures/masp_proofs/C788F9057C615CCE7B260BB8BF5CF776D5DE7C9153D67B7FDF22ED6F35558738.bin delete mode 100644 test_fixtures/masp_proofs/CBF4087F2AB578C83A736E4598DBA1FDB2515DF33D43611F2860B8D3C178B474.bin create mode 100644 test_fixtures/masp_proofs/CD50FD3DE1D59F43FBD6F3ED220F348721EF5366FDD8E62B9062254B2D286E0F.bin create mode 100644 test_fixtures/masp_proofs/CEC3CA2BCC727589C923B70A3F57D436A33F919BC377C8C6EE7A8DC8D210A6D9.bin create mode 100644 test_fixtures/masp_proofs/EDB31EB869290C1252C3395D7ED2D1A30B9CFAD55AA750B6CC36A4BD55D6BD2B.bin delete mode 100644 test_fixtures/masp_proofs/EDE8DC791D02098C5C199CAF2F6C8B75587507CA52981F48FD1FC9C5BE0BEE43.bin rename test_fixtures/masp_proofs/{90502CEAE917AE038FDA2337AFB0464F2130123149D5691B85C35AABC49FA2BD.bin => F6021F5E0CC7E0346EEF9BDF849AF47822630FC911AF7F91B196C540372EC0E8.bin} (52%) diff --git a/test_fixtures/masp_proofs/0075192A544500F2AD0C92E1A2D6D32B22A46CEDD254F52B6C69E813898FE60B.bin b/test_fixtures/masp_proofs/0075192A544500F2AD0C92E1A2D6D32B22A46CEDD254F52B6C69E813898FE60B.bin new file mode 100644 index 0000000000000000000000000000000000000000..6e8d6b3ae4fdf9e073b8e193f0299373355ef47e GIT binary patch literal 10382 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 CT{X)9 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/4F74C729C8F775EF554F4475BD13CAF693649A17FBEE435298C9C1624C6060F2.bin b/test_fixtures/masp_proofs/4F74C729C8F775EF554F4475BD13CAF693649A17FBEE435298C9C1624C6060F2.bin new file mode 100644 index 0000000000000000000000000000000000000000..d235345ec7e87e1395512c5da04dce64b9cc5e96 GIT binary patch literal 7448 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/51034B90AF95B8899A631D37B45DB11F0B17E6564F3AA56244770F24B56FC18B.bin b/test_fixtures/masp_proofs/51034B90AF95B8899A631D37B45DB11F0B17E6564F3AA56244770F24B56FC18B.bin new file mode 100644 index 0000000000000000000000000000000000000000..e64778b23802f2989e244dede85f5d6543acef70 GIT binary patch literal 7448 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 diff --git a/test_fixtures/masp_proofs/544F7432B95E26E312105FB804BF9BC175A70082068C8785BDDBF49DCCA4BE66.bin b/test_fixtures/masp_proofs/544F7432B95E26E312105FB804BF9BC175A70082068C8785BDDBF49DCCA4BE66.bin deleted file mode 100644 index 1636c1394f086ad2f8bb900c9ad58e1fc5e4caef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7448 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 diff --git a/test_fixtures/masp_proofs/5F7D9B39ABA3A1CF6A124CFC26BD9698F791D337CEF8DE82C684C1A1279D772E.bin b/test_fixtures/masp_proofs/5F7D9B39ABA3A1CF6A124CFC26BD9698F791D337CEF8DE82C684C1A1279D772E.bin new file mode 100644 index 0000000000000000000000000000000000000000..4ff46ab0b35d86cce94c270e6cac5bfb64c5afef GIT binary patch literal 9649 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%0A}3TGI3Vry3_g!@x_#UbXQeN%B}b}S^1GTq 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/6DD5A788D36258E9D5FEF454DBC89879834677F926130D56EB5E4067728EB5CF.bin b/test_fixtures/masp_proofs/6DD5A788D36258E9D5FEF454DBC89879834677F926130D56EB5E4067728EB5CF.bin deleted file mode 100644 index 94f997688ba6215afe7dba75785ff44eb9cd9d65..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10382 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 yQm)ULrC^#S;f-urKbk{I+BPA&yozg=~ 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 A)&Kwi diff --git a/test_fixtures/masp_proofs/8032CA7B951C625E43F48AEBD53CEA99A9BC66B2BAB03D4ABA1AE57B12596061.bin b/test_fixtures/masp_proofs/8032CA7B951C625E43F48AEBD53CEA99A9BC66B2BAB03D4ABA1AE57B12596061.bin deleted file mode 100644 index b983254f6b6b56c0574db0d1880140d8aa00309c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7448 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 RzPIoH>u>&k^=*pAe*+GM4_^QP literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/A8A9963AC2983B576BAE4DE9BA6D2CF14C7F9E90A8588BA75DA0D2860F36E2CB.bin b/test_fixtures/masp_proofs/A8A9963AC2983B576BAE4DE9BA6D2CF14C7F9E90A8588BA75DA0D2860F36E2CB.bin deleted file mode 100644 index e475b08f8b72978c2a6cf90280bec31fc71997bb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9649 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 S`T6eG_!p=Db^hxv(0>8E_ROCE diff --git a/test_fixtures/masp_proofs/AEA19C9B07742FF5F6D759B171396732D2EBF77728D2772EB251123DF2CEF6A1.bin b/test_fixtures/masp_proofs/AEA19C9B07742FF5F6D759B171396732D2EBF77728D2772EB251123DF2CEF6A1.bin deleted file mode 100644 index 4b7967cf8517fcab5932ceb352630a2cdb92311b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9941 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 diff --git a/test_fixtures/masp_proofs/C788F9057C615CCE7B260BB8BF5CF776D5DE7C9153D67B7FDF22ED6F35558738.bin b/test_fixtures/masp_proofs/C788F9057C615CCE7B260BB8BF5CF776D5DE7C9153D67B7FDF22ED6F35558738.bin deleted file mode 100644 index d3c3a5c24181bdbe0be7e43634ce4e5cd0ac396a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24494 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 u;ob6nK|>OYA(L2 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/CEC3CA2BCC727589C923B70A3F57D436A33F919BC377C8C6EE7A8DC8D210A6D9.bin b/test_fixtures/masp_proofs/CEC3CA2BCC727589C923B70A3F57D436A33F919BC377C8C6EE7A8DC8D210A6D9.bin new file mode 100644 index 0000000000000000000000000000000000000000..3f3374c98bf75f51e4f37abbf5aa29931822c009 GIT binary patch literal 17018 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 literal 0 HcmV?d00001 diff --git a/test_fixtures/masp_proofs/EDB31EB869290C1252C3395D7ED2D1A30B9CFAD55AA750B6CC36A4BD55D6BD2B.bin b/test_fixtures/masp_proofs/EDB31EB869290C1252C3395D7ED2D1A30B9CFAD55AA750B6CC36A4BD55D6BD2B.bin new file mode 100644 index 0000000000000000000000000000000000000000..b8e866408a4b4a0413989eac2d5d04784c89a636 GIT binary patch literal 15597 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 diff --git a/test_fixtures/masp_proofs/90502CEAE917AE038FDA2337AFB0464F2130123149D5691B85C35AABC49FA2BD.bin b/test_fixtures/masp_proofs/F6021F5E0CC7E0346EEF9BDF849AF47822630FC911AF7F91B196C540372EC0E8.bin similarity index 52% rename from test_fixtures/masp_proofs/90502CEAE917AE038FDA2337AFB0464F2130123149D5691B85C35AABC49FA2BD.bin rename to test_fixtures/masp_proofs/F6021F5E0CC7E0346EEF9BDF849AF47822630FC911AF7F91B196C540372EC0E8.bin index 44754a7a468bd33137f1d504b5f7e3d54f8ed301..c04d382648da88cf1bc3174b5dfe8bd888b15220 100644 GIT binary patch delta 2133 zcmc(gX;c#E8plylBMeDKM>7kv#-(i1!37m1vrOhQ%DigO{!II2O zBazAwaW9v!Oc6EH6jziCO>p5-HtrX@U*^m`=X%e%ALcpd`SkvO=Xsz1|2^l;waT?3 z$N>NVby)*tJ?7X4#`ZL!VoLmY8q5w{Y0#^lIK$92y9mX=l>H|ltnXOnP`!LsfKw^4s# z3E$wi{*3U2@+S)P{5surh@Kn6F2OFLBTf8B51(?3pHBQY`XBH&cIJCrO=$b*Kl87f zy1q}Y^s7%{j!g{rB0j$B0QSp{H!Rrb&DJLw%GvMTOtj%qw(>F7kerh| zd^1x>OprY*6DU(|=D;`QF=d%@vwc}iP@FvBf4Sy{Gk=NW|B3R?NfQ2sC;>o@BCZI? zYTyu+%_lCL&hQReqS&$@he@9xwWNzGN3(?Qy3EbZr&E6=jFR!XWLBF?2i2H6R52zz zW=ErC^Sw!a+Ys=TPg&sI;1* zXc9ba61tL@DMDOX#6eGI8A@}ajDY$6BAf{*+DH4i+hujCw+YhY9D%aE(TMsNa_OFT4 z6s@B6D6(I1pYJd5VYNeL^KFPO28kWwW{ZeSSP0zdJJPZm4kO+*z2A!*{5pZsbG7cPRSbvRSg^lTe$~js2UZm$h`XKt7YIV%bFuCd56BY*6(Ko`7ZoQ>#-36> z1ig1P5GCEy7v0rA-D$TL^xia3BNb>M;C%1Xx(c>YYmxqXsEl=PEDy={$M1d%GV-k^ zIU$aIU`aJ(^ZBqHY;ahN6B)M8LfhiF1xZiKb@Nw$j+3l1>@<%qs%gV^(T(WW8dH9AhTYNONS%d|fE^_P z-IXVj_l`g-4J_)sS8!W~f{|hgvMP?ZmNWUF&8-%x6AH<=taaQ6)#ZX26D~}s4G{~w z=XxdfzdR^o)O*D+Af35Gr570JMq}c+0iieKesXU^S!E)Ra4CAuPIP+If#hr8)qicI zkfC*rp6J~9jCO}VD+z)SE!@&N)U{2Cq>h9#!&c$JYnmQsV;rmI46&`lV}|hE#f0sa zwg(3#rKNoT-+_}*ydf}@`x(0)+{~%B_M^xhmVOWiPHDbRypyoEjwk62(QKAVa48=P zarY3(XUBpY@o*?E|e3J73QCD1k=A52k~bZ;AZI?j_EbqYi-kkiyzW z`o-lC$Z!1zUg&rTx4fEiS3NF*%oIO@4-!2~3g`ssc&kdV@frOQ@|-U zVYQL()y8(caww2?dwa0q2~1nT*IcL(YM+YaQknv5u^^`Jmi}!nWu@nQ?af|{L(90$ zIhG?wKA;=V$$z#}vqy9hmaGg)XfTBX?|n@PDckjcApl2V!*}D^g-f9--c|ZL#*|l8YF1WoyY16O~<>EZI0+bvP zMUQp8!?|{oUnk$(n!`S8ibc{JeZ|cDk(&kEa7`2o%FleB%EmvkQ9#nn&i(%a7T5^I delta 2133 zcmc(gc{JPU8pnf>)EbmFMVqR%v_q|-y(L5iwIsyac2HAP8>TaM;<$9EE%npVpw_B2 zw5g<#RxEANWok>bQd@)SHbE>YS50*O>6v@ZbTRgRgo1@ z3oeS#NvuUlg=AwXe2;3+`U^iBQb8bZ+7VIa0!NZhk;1 z1^R5>>o^Yt%b6k?(6hptma6dDY)GsH*}<7aZFR)C(|Wsohq0b}U?-?_IfOXuD}=87 z3x6=gyBsH>ZY|^i?-bl^&`#Iv9qX(HIxbyfFSH6$f~DvDkyElOi3tB*wLg3mD&5|+ z{q_;X^h;Ol>+~nRq~*v95s46CePU;eIpabg5Cbzs#2xYlcZ`IFQ1Wk2*4%{Q#-unr zIOyHy+#9%0*vf%S>NA*Velj7`d~vgSxyhd+z?(l$1=f|^ZG?F~75Aat8bfhfKh&G8 zBp{1yJx|4FCzOiGU4WfYVmHt;IYcq(s52QVT7b>hXjJijoY!zK-R4j{``BxI; znIxuhq|Wlmr?AOGKJe?y_pE_3Ra1m+PFSnlw7y(b-my`8DH^`}`k2gM5VnhBI~Cnp zh$c`4s-pR7q3u4>%w=8{f8tJ;>dgV*0Ni8yS0C{-WAnSZJ4>NAmuCf5QEeI(w3VMM zFg4u-S8y_^GYR@n54cvI_k!*^xNoHL?6mzz)RNnLxp&|Cvv$FoN+iteHv>wOf3QUT zg{v?3&PlaB8`mHamkbBWMdTB%Pj=61_rt4AN`Y0DLxf@BW`7 z7ruDAJ%UR#HyD{8WOm8of>^0Vt;_y@%%rWCXOM#j>AQslMqZ!qIOdCD$h=u&;(-y*y_f4(&7j!B@9>EXSKY--8IBThumYYd0p33W8uWEYMp8P zN_pDFk-5-O$;_PuJijO7Y4x=6%ZU$^SfNHT*rDG~`&hqGz&^v&_qXQd3@U@embg(W zH?;l{Xng;HyG&CGbWx#1JF|U(UN@aGic0OMh&D{87&?n@B*+&$tn0E<%{KD11=MTZ zdZ0$HT|e4BJ^0U6`HlQYz2s#xz$TCxS^E2EbR%Zm zQ*f-VjG~Zx#4~7*d_iMGl(kgdt~R3Ep2ZV>%MBlh-4EsSTs)q~2f*1KJxidSQ#!^_ zNjX^usk~7?X*$bl;mxlh-N%PcLQ{82Q=YS;%e><$tcKZO{lb3mF9R2m{({+(>Xyy( zKC}|J!i+JNz^g!b{}gbgJA3`4$;-#?2aDT6I(ZD9xYDB9&;`4ct43b0YWvw26@y&Z zLo{n*lJFcrCy$S5fgg=?Ei|QY^fLbZEd~}BQNF{%;>*zGUc~rX9c*ynw5gg*Pue-4 zGTuEyIdaYFu9#cBU6zYmZ<&{Unyr)bgvao&F=p((s2Uw@**URKx;qR4kZ+Gq(iu>?!Ch zDRFdt6pvw<9ezi$gh0r<@Z5}aO&%1L`e@cgMR6vv+x4WccVw2vda(f#t4ESzhZPQ^ zJHweOQy&L(Y(H7zJwIqYPO~0`?j5*+{u(qxN-|lZTEw{QTADh%^^JThFz{L3;7`hB B6g>a{ From 4b08cf58f088baae7589e204afed7b9bcc707643 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 24 Nov 2023 23:18:11 +0100 Subject: [PATCH 42/54] ibc-rs 0.48.0 --- Cargo.lock | 485 +++++++++++++++--- Cargo.toml | 6 + apps/src/lib/bench_utils.rs | 88 ++-- apps/src/lib/cli.rs | 2 +- apps/src/lib/client/tx.rs | 2 +- core/Cargo.toml | 9 +- core/src/ledger/ibc/context/client.rs | 80 ++- core/src/ledger/ibc/context/common.rs | 43 +- core/src/ledger/ibc/context/execution.rs | 33 +- core/src/ledger/ibc/context/mod.rs | 6 +- core/src/ledger/ibc/context/router.rs | 6 +- core/src/ledger/ibc/context/token_transfer.rs | 13 +- core/src/ledger/ibc/context/transfer_mod.rs | 27 +- core/src/ledger/ibc/context/validation.rs | 52 +- core/src/ledger/ibc/mod.rs | 38 +- core/src/ledger/ibc/storage.rs | 17 +- core/src/types/address.rs | 2 +- core/src/types/ibc.rs | 4 +- core/src/types/token.rs | 2 +- sdk/Cargo.toml | 4 - sdk/src/args.rs | 2 +- sdk/src/events/log/dumb_queries.rs | 12 +- sdk/src/lib.rs | 2 +- sdk/src/queries/router.rs | 4 +- sdk/src/queries/shell.rs | 5 +- sdk/src/signing.rs | 4 +- sdk/src/tx.rs | 19 +- shared/Cargo.toml | 8 +- shared/src/ledger/native_vp/ibc/mod.rs | 143 +++--- tests/Cargo.toml | 3 +- tests/src/e2e/ibc_tests.rs | 133 +++-- tests/src/vm_host_env/ibc.rs | 100 ++-- tests/src/vm_host_env/mod.rs | 2 +- wasm/Cargo.lock | 480 ++++++++++++++--- 34 files changed, 1253 insertions(+), 583 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a760f39701..c0c77999b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -500,7 +500,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.10.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "unicode-normalization", "zeroize", ] @@ -597,7 +597,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -762,9 +762,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde 1.0.190", ] @@ -1000,13 +1000,13 @@ dependencies = [ "bincode", "bs58", "coins-core", - "digest 0.10.6", + "digest 0.10.7", "getrandom 0.2.10", "hmac 0.12.1", "k256", "lazy_static", "serde 1.0.190", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -1023,7 +1023,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -1036,13 +1036,13 @@ dependencies = [ "base64 0.21.0", "bech32 0.7.3", "bs58", - "digest 0.10.6", + "digest 0.10.7", "generic-array 0.14.7", "hex", "ripemd", "serde 1.0.190", "serde_derive", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -1559,9 +1559,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", @@ -1651,7 +1651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" dependencies = [ "der", - "digest 0.10.6", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -1734,7 +1734,7 @@ checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.6", + "digest 0.10.7", "ff", "generic-array 0.14.7", "group", @@ -1861,7 +1861,7 @@ checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes", "ctr", - "digest 0.10.6", + "digest 0.10.7", "hex", "hmac 0.12.1", "pbkdf2 0.11.0", @@ -1869,7 +1869,7 @@ dependencies = [ "scrypt", "serde 1.0.190", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", "uuid 0.8.2", @@ -2169,7 +2169,7 @@ dependencies = [ "ethers-core", "hex", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2749,7 +2749,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -2891,40 +2891,353 @@ dependencies = [ [[package]] name = "ibc" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "184eb22140cb4143bbcf7ddc8fdfeb9cc058ef73a6066f8ea78162e69d3565d1" +version = "0.48.0" +dependencies = [ + "ibc-apps", + "ibc-clients", + "ibc-core", + "ibc-core-host-cosmos", + "ibc-derive 0.4.0", + "ibc-primitives", +] + +[[package]] +name = "ibc-app-transfer" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer-types", + "ibc-core", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-transfer-types" +version = "0.48.0" dependencies = [ - "bytes", "derive_more", "displaydoc", - "ibc-derive", + "ibc-core", "ibc-proto", - "ics23", - "num-traits 0.2.15", - "parking_lot", "primitive-types", + "serde 1.0.190", + "uint", +] + +[[package]] +name = "ibc-apps" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer", +] + +[[package]] +name = "ibc-client-tendermint" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", + "serde 1.0.190", + "tendermint", + "tendermint-light-client-verifier", +] + +[[package]] +name = "ibc-client-tendermint-types" +version = "0.48.0" +dependencies = [ + "bytes", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", "prost 0.12.1", "serde 1.0.190", - "serde-json-wasm", - "serde_derive", - "sha2 0.10.6", - "subtle-encoding", "tendermint", "tendermint-light-client-verifier", "tendermint-proto", - "tendermint-testgen", - "time", - "tracing", - "typed-builder", - "uint", +] + +[[package]] +name = "ibc-clients" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint", +] + +[[package]] +name = "ibc-core" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-channel" +version = "0.48.0" +dependencies = [ + "ibc-core-channel-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-channel-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client" +version = "0.48.0" +dependencies = [ + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-client-context" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-derive 0.4.0", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-commitment-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde 1.0.190", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-connection" +version = "0.48.0" +dependencies = [ + "ibc-core-client", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-connection-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-handler" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-handler-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-host-cosmos" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-app-transfer-types", + "ibc-client-tendermint", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "serde 1.0.190", +] + +[[package]] +name = "ibc-core-router" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-router-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde 1.0.190", + "subtle-encoding", + "tendermint", ] [[package]] name = "ibc-derive" -version = "0.3.0" +version = "0.4.0" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "ibc-derive" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92f1528535e9ca495badb76c143bdd4763c1c9d987f59d1f8b47963ba0c11674" +checksum = "df07bf5bc1e65e291506b7497633e07967e49b36a8db10cda77a8fd686eb4548" dependencies = [ "darling", "proc-macro2", @@ -2932,11 +3245,24 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "ibc-primitives" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-proto", + "prost 0.12.1", + "serde 1.0.190", + "tendermint", + "time", +] + [[package]] name = "ibc-proto" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63042806bb2f662ca1c68026231900cfe13361136ddfd0dd09bcb315056a22b8" +checksum = "93cbf4cbe9e5113cc7c70f3208a7029b2205c629502cbb2ae7ea0a09a97d3005" dependencies = [ "base64 0.21.0", "bytes", @@ -2948,6 +3274,25 @@ dependencies = [ "tendermint-proto", ] +[[package]] +name = "ibc-testkit" +version = "0.48.0" +dependencies = [ + "bytes", + "derive_more", + "displaydoc", + "ibc", + "ibc-proto", + "parking_lot", + "primitive-types", + "prost 0.12.1", + "subtle-encoding", + "tendermint", + "tendermint-testgen", + "tracing", + "typed-builder", +] + [[package]] name = "ics23" version = "0.11.0" @@ -2961,7 +3306,7 @@ dependencies = [ "prost 0.12.1", "ripemd", "serde 1.0.190", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", ] @@ -3208,7 +3553,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.6", + "sha2 0.10.8", "signature 2.1.0", ] @@ -3263,7 +3608,7 @@ dependencies = [ "ledger-zondax-generic", "prost 0.11.9", "prost-types 0.11.9", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -3532,7 +3877,7 @@ dependencies = [ "num-traits 0.2.15", "rand 0.8.5", "rand_core 0.6.4", - "sha2 0.10.6", + "sha2 0.10.8", "subtle 2.4.1", "zcash_encoding", ] @@ -3749,6 +4094,7 @@ dependencies = [ "eyre", "fd-lock", "futures", + "ibc-testkit", "itertools 0.10.5", "k256", "loupe", @@ -3922,8 +4268,9 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive", + "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ibc-proto", + "ibc-testkit", "ics23", "impl-num-traits", "index-set", @@ -4105,6 +4452,7 @@ dependencies = [ "eyre", "fs_extra", "hyper", + "ibc-testkit", "itertools 0.10.5", "lazy_static", "namada", @@ -4724,7 +5072,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "password-hash", ] @@ -4734,7 +5082,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4743,7 +5091,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "hmac 0.12.1", ] @@ -4968,9 +5316,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -5510,7 +5858,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -5812,7 +6160,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] @@ -6047,7 +6395,7 @@ checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -6077,13 +6425,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -6092,7 +6440,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] @@ -6142,7 +6490,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -6433,7 +6781,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" dependencies = [ "bytes", - "digest 0.10.6", + "digest 0.10.7", "ed25519 2.2.2", "ed25519-consensus 2.1.0", "flex-error", @@ -6448,7 +6796,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.6", + "sha2 0.10.8", "signature 2.1.0", "subtle 2.4.1", "subtle-encoding", @@ -6989,11 +7337,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -7013,9 +7360,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -7024,9 +7371,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -7120,18 +7467,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c6a006a6d3d6a6f143fda41cf4d1ad35110080687628c9f2117bd3cc7924f3" +checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fa054ee5e2346187d631d2f1d1fd3b33676772d6d03a2d84e1c5213b31674ee" +checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index c1fa8f6d03..8965f60323 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,6 +81,12 @@ flate2 = "1.0.22" fs_extra = "1.2.0" futures = "0.3" git2 = "0.13.25" +#ibc = {version = "0.48.0", default-features = false, features = ["serde"]} +ibc = {path = "../../cosmos/ibc-rs/ibc", default-features = false, features = ["serde"]} +ibc-derive = "0.4.0" +ibc-proto = {version = "0.38.0", default-features = false} +#ibc-testkit = {version = "0.48.0", default-features = false} +ibc-testkit = {path = "../../cosmos/ibc-rs/ibc-testkit", default-features = false} ics23 = "0.11.0" index-set = {git = "https://github.com/heliaxdev/index-set", tag = "v0.8.0", features = ["serialize-borsh", "serialize-serde"]} itertools = "0.10.0" diff --git a/apps/src/lib/bench_utils.rs b/apps/src/lib/bench_utils.rs index 551bf49abd..b069c7ec29 100644 --- a/apps/src/lib/bench_utils.rs +++ b/apps/src/lib/bench_utils.rs @@ -19,39 +19,39 @@ use namada::core::types::address::{self, Address}; use namada::core::types::key::common::SecretKey; use namada::core::types::storage::Key; use namada::core::types::token::{Amount, Transfer}; -use namada::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use namada::ibc::applications::transfer::packet::PacketData; -use namada::ibc::applications::transfer::PrefixedCoin; -use namada::ibc::clients::ics07_tendermint::client_state::{ - AllowUpdate, ClientState, +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::clients::tendermint::client_state::ClientState; +use namada::ibc::clients::tendermint::consensus_state::ConsensusState; +use namada::ibc::clients::tendermint::types::{ + AllowUpdate, ClientState as ClientStateType, + ConsensusState as ConsensusStateType, TrustThreshold, }; -use namada::ibc::clients::ics07_tendermint::consensus_state::ConsensusState; -use namada::ibc::clients::ics07_tendermint::trust_threshold::TrustThreshold; -use namada::ibc::core::ics02_client::client_type::ClientType; -use namada::ibc::core::ics03_connection::connection::{ - ConnectionEnd, Counterparty, State as ConnectionState, -}; -use namada::ibc::core::ics03_connection::version::Version; -use namada::ibc::core::ics04_channel::channel::{ +use namada::ibc::core::channel::types::channel::{ ChannelEnd, Counterparty as ChannelCounterparty, Order, State, }; -use namada::ibc::core::ics04_channel::timeout::TimeoutHeight; -use namada::ibc::core::ics04_channel::Version as ChannelVersion; -use namada::ibc::core::ics23_commitment::commitment::{ +use namada::ibc::core::channel::types::timeout::TimeoutHeight; +use namada::ibc::core::channel::types::Version as ChannelVersion; +use namada::ibc::core::client::types::Height as IbcHeight; +use namada::ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentRoot, }; -use namada::ibc::core::ics23_commitment::specs::ProofSpecs; -use namada::ibc::core::ics24_host::identifier::{ +use namada::ibc::core::commitment_types::specs::ProofSpecs; +use namada::ibc::core::connection::types::version::Version; +use namada::ibc::core::connection::types::{ + ConnectionEnd, Counterparty, State as ConnectionState, +}; +use namada::ibc::core::host::types::identifiers::{ ChainId as IbcChainId, ChannelId as NamadaChannelId, ChannelId, ClientId, - ConnectionId, ConnectionId as NamadaConnectionId, PortId as NamadaPortId, - PortId, + ClientType, ConnectionId, ConnectionId as NamadaConnectionId, + PortId as NamadaPortId, PortId, }; -use namada::ibc::core::ics24_host::path::Path as IbcPath; -use namada::ibc::core::timestamp::Timestamp as IbcTimestamp; -use namada::ibc::core::Msg; -use namada::ibc::Height as IbcHeight; -use namada::ibc_proto::google::protobuf::Any; -use namada::ibc_proto::protobuf::Protobuf; +use namada::ibc::core::host::types::path::{ + ClientConsensusStatePath, ClientStatePath, Path as IbcPath, +}; +use namada::ibc::primitives::proto::{Any, Protobuf}; +use namada::ibc::primitives::{Msg, Timestamp as IbcTimestamp}; use namada::ledger::dry_run_tx; use namada::ledger::gas::TxGasMeter; use namada::ledger::ibc::storage::{channel_key, connection_key}; @@ -424,15 +424,11 @@ impl BenchShell { ClientId::new(ClientType::new("01-tendermint").unwrap(), 1) .unwrap(); let client_state_key = addr_key.join(&Key::from( - IbcPath::ClientState( - namada::ibc::core::ics24_host::path::ClientStatePath( - client_id.clone(), - ), - ) - .to_string() - .to_db_key(), + IbcPath::ClientState(ClientStatePath(client_id.clone())) + .to_string() + .to_db_key(), )); - let client_state = ClientState::new( + let client_state = ClientStateType::new( IbcChainId::from_str(&ChainId::default().to_string()).unwrap(), TrustThreshold::ONE_THIRD, std::time::Duration::new(100, 0), @@ -446,8 +442,9 @@ impl BenchShell { after_misbehaviour: true, }, ) - .unwrap(); - let bytes = >::encode_vec(&client_state); + .unwrap() + .into(); + let bytes = >::encode_vec(client_state); self.wl_storage .storage .write(&client_state_key, bytes) @@ -457,25 +454,24 @@ impl BenchShell { let now: namada::tendermint::Time = DateTimeUtc::now().try_into().unwrap(); let consensus_key = addr_key.join(&Key::from( - IbcPath::ClientConsensusState( - namada::ibc::core::ics24_host::path::ClientConsensusStatePath { - client_id: client_id.clone(), - epoch: 0, - height: 1, - }, - ) + IbcPath::ClientConsensusState(ClientConsensusStatePath { + client_id: client_id.clone(), + revision_number: 0, + revision_height: 1, + }) .to_string() .to_db_key(), )); - let consensus_state = ConsensusState { + let consensus_state = ConsensusStateType { timestamp: now, root: CommitmentRoot::from_bytes(&[]), next_validators_hash: Hash::Sha256([0u8; 32]), - }; + } + .into(); let bytes = - >::encode_vec(&consensus_state); + >::encode_vec(consensus_state); self.wl_storage .storage .write(&consensus_key, bytes) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 3bb7f5c7ad..a251fc2b30 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -2818,7 +2818,7 @@ pub mod args { use std::path::PathBuf; use std::str::FromStr; - use namada::ibc::core::ics24_host::identifier::{ChannelId, PortId}; + use namada::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada::types::address::Address; use namada::types::chain::{ChainId, ChainIdPrefix}; use namada::types::dec::Dec; diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 0317ec43f3..be1738b262 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -13,7 +13,7 @@ use namada::core::ledger::governance::cli::offline::{ use namada::core::ledger::governance::cli::onchain::{ DefaultProposal, PgfFundingProposal, PgfStewardProposal, ProposalVote, }; -use namada::ibc::applications::transfer::Memo; +use namada::ibc::apps::transfer::types::Memo; use namada::proto::{CompressedSignature, Section, Signer, Tx}; use namada::types::address::{Address, ImplicitAddress}; use namada::types::dec::Dec; diff --git a/core/Cargo.toml b/core/Cargo.toml index 53ee824077..08961be424 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -17,12 +17,12 @@ default = ["rand"] mainnet = [] wasm-runtime = ["rayon"] rand = ["dep:rand", "rand_core"] -ibc-mocks = ["ibc/mocks" ] ethers-derive = [ "ethbridge-structs/ethers-derive" ] # for integration tests and test utilies testing = [ + "ibc-testkit", "rand", "proptest", ] @@ -42,9 +42,10 @@ ed25519-consensus.workspace = true ethabi.workspace = true ethbridge-structs.workspace = true eyre.workspace = true -ibc = { version = "0.47.0", default-features = false, features = ["serde"]} -ibc-derive = { version = "0.3.0"} -ibc-proto = {version = "0.37.1", default-features = false} +ibc.workspace = true +ibc-derive.workspace = true +ibc-proto.workspace = true +ibc-testkit = {workspace = true, optional = true} ics23.workspace = true impl-num-traits = "0.1.2" index-set.workspace = true diff --git a/core/src/ledger/ibc/context/client.rs b/core/src/ledger/ibc/context/client.rs index 5c771a0712..0000432c76 100644 --- a/core/src/ledger/ibc/context/client.rs +++ b/core/src/ledger/ibc/context/client.rs @@ -1,37 +1,35 @@ //! AnyClientState and AnyConsensusState for IBC context use ibc_derive::ConsensusState; +#[cfg(feature = "testing")] +use ibc_testkit::testapp::ibc::clients::mock::client_state::MockClientContext; +#[cfg(feature = "testing")] +use ibc_testkit::testapp::ibc::clients::mock::client_state::MockClientState; +#[cfg(feature = "testing")] +use ibc_testkit::testapp::ibc::clients::mock::consensus_state::MockConsensusState; use prost::Message; -use crate::ibc::clients::ics07_tendermint::client_state::ClientState as TmClientState; -use crate::ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; -use crate::ibc::clients::ics07_tendermint::{ +use crate::ibc::clients::tendermint::client_state::ClientState as TmClientState; +use crate::ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; +use crate::ibc::clients::tendermint::context::{ CommonContext, ExecutionContext as TmExecutionContext, ValidationContext as TmValidationContext, }; -use crate::ibc::core::ics02_client::client_state::{ - ClientStateCommon, ClientStateExecution, ClientStateValidation, Status, - UpdateKind, +use crate::ibc::core::client::context::client_state::{ + ClientStateCommon, ClientStateExecution, ClientStateValidation, }; -use crate::ibc::core::ics02_client::client_type::ClientType; -use crate::ibc::core::ics02_client::error::ClientError; -use crate::ibc::core::ics02_client::{ +use crate::ibc::core::client::context::{ ClientExecutionContext, ClientValidationContext, }; -use crate::ibc::core::ics23_commitment::commitment::{ +use crate::ibc::core::client::types::error::ClientError; +use crate::ibc::core::client::types::{Height, Status, UpdateKind}; +use crate::ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentProofBytes, CommitmentRoot, }; -use crate::ibc::core::ics24_host::identifier::ClientId; -use crate::ibc::core::ics24_host::path::Path; -use crate::ibc::core::ExecutionContext; -#[cfg(feature = "ibc-mocks")] -use crate::ibc::mock::client_state::MockClientContext; -#[cfg(feature = "ibc-mocks")] -use crate::ibc::mock::client_state::MockClientState; -#[cfg(feature = "ibc-mocks")] -use crate::ibc::mock::consensus_state::MockConsensusState; -use crate::ibc::Height; -use crate::ibc_proto::google::protobuf::Any; +use crate::ibc::core::host::types::identifiers::{ClientId, ClientType}; +use crate::ibc::core::host::types::path::Path; +use crate::ibc::core::host::ExecutionContext; +use crate::ibc::primitives::proto::Any; // TODO: #[derive(ClientState)] doesn't support contexts with contexts generic // for now @@ -41,7 +39,7 @@ pub enum AnyClientState { /// Tendermint client state Tendermint(TmClientState), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] /// Mock client state for testing Mock(MockClientState), } @@ -52,7 +50,7 @@ impl From for AnyClientState { } } -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] impl From for AnyClientState { fn from(cs: MockClientState) -> Self { Self::Mock(cs) @@ -63,7 +61,7 @@ impl From for Any { fn from(client_state: AnyClientState) -> Self { match client_state { AnyClientState::Tendermint(cs) => cs.into(), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => cs.into(), } } @@ -73,7 +71,7 @@ impl TryFrom for AnyClientState { type Error = ClientError; fn try_from(client_state: Any) -> Result { - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] if let Ok(cs) = MockClientState::try_from(client_state.clone()) { return Ok(cs.into()); } @@ -93,7 +91,7 @@ pub enum AnyConsensusState { /// Tendermint consensus state Tendermint(TmConsensusState), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] /// Mock consensus state for testing Mock(MockConsensusState), } @@ -104,7 +102,7 @@ impl From for AnyConsensusState { } } -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] impl From for AnyConsensusState { fn from(cs: MockConsensusState) -> Self { Self::Mock(cs) @@ -117,7 +115,7 @@ impl TryFrom for TmConsensusState { fn try_from(any: AnyConsensusState) -> Result { match any { AnyConsensusState::Tendermint(cs) => Ok(cs), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] _ => Err(ClientError::UnknownConsensusStateType { consensus_state_type: "Only Tendermint client state type is \ supported" @@ -127,7 +125,7 @@ impl TryFrom for TmConsensusState { } } -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] impl TryFrom for MockConsensusState { type Error = ClientError; @@ -146,7 +144,7 @@ impl TryFrom for AnyConsensusState { type Error = ClientError; fn try_from(consensus_state: Any) -> Result { - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] if let Ok(cs) = MockConsensusState::try_from(consensus_state.clone()) { return Ok(cs.into()); } @@ -179,7 +177,7 @@ impl ClientStateCommon for AnyClientState { AnyClientState::Tendermint(cs) => { cs.verify_consensus_state(consensus_state) } - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => { cs.verify_consensus_state(consensus_state) } @@ -189,7 +187,7 @@ impl ClientStateCommon for AnyClientState { fn client_type(&self) -> ClientType { match self { AnyClientState::Tendermint(cs) => cs.client_type(), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => cs.client_type(), } } @@ -197,7 +195,7 @@ impl ClientStateCommon for AnyClientState { fn latest_height(&self) -> Height { match self { AnyClientState::Tendermint(cs) => cs.latest_height(), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => cs.latest_height(), } } @@ -210,7 +208,7 @@ impl ClientStateCommon for AnyClientState { AnyClientState::Tendermint(cs) => { cs.validate_proof_height(proof_height) } - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => cs.validate_proof_height(proof_height), } } @@ -231,7 +229,7 @@ impl ClientStateCommon for AnyClientState { proof_upgrade_consensus_state, root, ), - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => cs.verify_upgrade_client( upgraded_client_state, upgraded_consensus_state, @@ -254,7 +252,7 @@ impl ClientStateCommon for AnyClientState { AnyClientState::Tendermint(cs) => { cs.verify_membership(prefix, proof, root, path, value) } - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => { cs.verify_membership(prefix, proof, root, path, value) } @@ -272,7 +270,7 @@ impl ClientStateCommon for AnyClientState { AnyClientState::Tendermint(cs) => { cs.verify_non_membership(prefix, proof, root, path) } - #[cfg(feature = "ibc-mocks")] + #[cfg(feature = "testing")] AnyClientState::Mock(cs) => { cs.verify_non_membership(prefix, proof, root, path) } @@ -280,7 +278,7 @@ impl ClientStateCommon for AnyClientState { } } -#[cfg(not(feature = "ibc-mocks"))] +#[cfg(not(feature = "testing"))] impl ClientStateValidation for AnyClientState where V: ClientValidationContext + TmValidationContext, @@ -331,7 +329,7 @@ where } } -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] impl ClientStateValidation for AnyClientState where V: ClientValidationContext + TmValidationContext + MockClientContext, @@ -400,7 +398,7 @@ where } } -#[cfg(not(feature = "ibc-mocks"))] +#[cfg(not(feature = "testing"))] impl ClientStateExecution for AnyClientState where E: ExecutionContext + TmExecutionContext, @@ -468,7 +466,7 @@ where } } -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] impl ClientStateExecution for AnyClientState where E: ExecutionContext + TmExecutionContext + MockClientContext, diff --git a/core/src/ledger/ibc/context/common.rs b/core/src/ledger/ibc/context/common.rs index d823b005d7..e8245babdd 100644 --- a/core/src/ledger/ibc/context/common.rs +++ b/core/src/ledger/ibc/context/common.rs @@ -7,31 +7,30 @@ use sha2::Digest; use super::client::{AnyClientState, AnyConsensusState}; use super::storage::IbcStorageContext; -use crate::ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; -use crate::ibc::core::ics02_client::consensus_state::ConsensusState; -use crate::ibc::core::ics02_client::error::ClientError; -use crate::ibc::core::ics02_client::height::Height; -use crate::ibc::core::ics03_connection::connection::ConnectionEnd; -use crate::ibc::core::ics03_connection::error::ConnectionError; -use crate::ibc::core::ics04_channel::channel::ChannelEnd; -use crate::ibc::core::ics04_channel::commitment::{ +use crate::ibc::clients::tendermint::consensus_state::ConsensusState as TmConsensusState; +use crate::ibc::clients::tendermint::types::ConsensusState as TmConsensusStateType; +use crate::ibc::core::channel::types::channel::ChannelEnd; +use crate::ibc::core::channel::types::commitment::{ AcknowledgementCommitment, PacketCommitment, }; -use crate::ibc::core::ics04_channel::error::{ChannelError, PacketError}; -use crate::ibc::core::ics04_channel::packet::{Receipt, Sequence}; -use crate::ibc::core::ics04_channel::timeout::TimeoutHeight; -use crate::ibc::core::ics24_host::identifier::{ - ChannelId, ClientId, ConnectionId, PortId, +use crate::ibc::core::channel::types::error::{ChannelError, PacketError}; +use crate::ibc::core::channel::types::packet::Receipt; +use crate::ibc::core::channel::types::timeout::TimeoutHeight; +use crate::ibc::core::client::context::consensus_state::ConsensusState; +use crate::ibc::core::client::types::error::ClientError; +use crate::ibc::core::client::types::Height; +use crate::ibc::core::connection::types::error::ConnectionError; +use crate::ibc::core::connection::types::ConnectionEnd; +use crate::ibc::core::handler::types::error::ContextError; +use crate::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, ConnectionId, PortId, Sequence, }; -use crate::ibc::core::timestamp::Timestamp; -use crate::ibc::core::ContextError; -use crate::ibc_proto::google::protobuf::Any; -use crate::ibc_proto::protobuf::Protobuf; +use crate::ibc::primitives::proto::{Any, Protobuf}; +use crate::ibc::primitives::Timestamp; use crate::ledger::ibc::storage; use crate::ledger::parameters::storage::get_max_expected_time_per_block_key; use crate::ledger::storage_api; use crate::tendermint::Time as TmTime; -use crate::tendermint_proto::Protobuf as TmProtobuf; use crate::types::storage::{BlockHeight, Key}; use crate::types::time::DurationSecs; @@ -292,8 +291,12 @@ pub trait IbcCommonContext: IbcStorageContext { .next_validators_hash .try_into() .expect("The hash should be converted"); - let consensus_state = - TmConsensusState::new(commitment_root, time, next_validators_hash); + let consensus_state: TmConsensusState = TmConsensusStateType::new( + commitment_root, + time, + next_validators_hash, + ) + .into(); Ok(consensus_state.into()) } diff --git a/core/src/ledger/ibc/context/execution.rs b/core/src/ledger/ibc/context/execution.rs index 893cd67702..bdebb242ef 100644 --- a/core/src/ledger/ibc/context/execution.rs +++ b/core/src/ledger/ibc/context/execution.rs @@ -3,23 +3,26 @@ use super::client::{AnyClientState, AnyConsensusState}; use super::common::IbcCommonContext; use super::IbcContext; -use crate::ibc::core::events::IbcEvent; -use crate::ibc::core::ics02_client::ClientExecutionContext; -use crate::ibc::core::ics03_connection::connection::ConnectionEnd; -use crate::ibc::core::ics04_channel::channel::ChannelEnd; -use crate::ibc::core::ics04_channel::commitment::{ +use crate::ibc::core::channel::types::channel::ChannelEnd; +use crate::ibc::core::channel::types::commitment::{ AcknowledgementCommitment, PacketCommitment, }; -use crate::ibc::core::ics04_channel::packet::{Receipt, Sequence}; -use crate::ibc::core::ics24_host::identifier::{ClientId, ConnectionId}; -use crate::ibc::core::ics24_host::path::{ +use crate::ibc::core::channel::types::packet::Receipt; +use crate::ibc::core::client::context::ClientExecutionContext; +use crate::ibc::core::client::types::Height; +use crate::ibc::core::connection::types::ConnectionEnd; +use crate::ibc::core::handler::types::error::ContextError; +use crate::ibc::core::handler::types::events::IbcEvent; +use crate::ibc::core::host::types::identifiers::{ + ClientId, ConnectionId, Sequence, +}; +use crate::ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, CommitmentPath, ConnectionPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; -use crate::ibc::core::timestamp::Timestamp; -use crate::ibc::core::{ContextError, ExecutionContext}; -use crate::ibc::Height; +use crate::ibc::core::host::ExecutionContext; +use crate::ibc::primitives::Timestamp; use crate::ledger::ibc::storage; impl ClientExecutionContext for IbcContext @@ -47,8 +50,8 @@ where ) -> Result<(), ContextError> { let client_id = consensus_state_path.client_id; let height = Height::new( - consensus_state_path.epoch, - consensus_state_path.height, + consensus_state_path.revision_number, + consensus_state_path.revision_height, )?; self.inner.borrow_mut().store_consensus_state( &client_id, @@ -63,8 +66,8 @@ where ) -> Result<(), ContextError> { let client_id = consensus_state_path.client_id; let height = Height::new( - consensus_state_path.epoch, - consensus_state_path.height, + consensus_state_path.revision_number, + consensus_state_path.revision_height, )?; self.inner .borrow_mut() diff --git a/core/src/ledger/ibc/context/mod.rs b/core/src/ledger/ibc/context/mod.rs index b57819eec1..b661bf2f09 100644 --- a/core/src/ledger/ibc/context/mod.rs +++ b/core/src/ledger/ibc/context/mod.rs @@ -14,8 +14,8 @@ use std::fmt::Debug; use std::rc::Rc; use std::time::Duration; -use crate::ibc::core::ics23_commitment::specs::ProofSpecs; -use crate::ibc::core::ics24_host::identifier::ChainId as IbcChainId; +use crate::ibc::core::commitment_types::specs::ProofSpecs; +use crate::ibc::core::host::types::identifiers::ChainId as IbcChainId; /// IBC context to handle IBC-related data #[derive(Debug)] @@ -58,7 +58,7 @@ pub struct ValidationParams { impl Default for ValidationParams { fn default() -> Self { Self { - chain_id: IbcChainId::new("non-init-chain", 0) + chain_id: IbcChainId::new("non-init-chain") .expect("Convert the default chain ID shouldn't fail"), proof_specs: ProofSpecs::default(), unbonding_period: Duration::default(), diff --git a/core/src/ledger/ibc/context/router.rs b/core/src/ledger/ibc/context/router.rs index daba314a5d..cc9abca1fc 100644 --- a/core/src/ledger/ibc/context/router.rs +++ b/core/src/ledger/ibc/context/router.rs @@ -4,8 +4,10 @@ use std::collections::HashMap; use std::rc::Rc; use super::super::ModuleWrapper; -use crate::ibc::core::ics24_host::identifier::PortId; -use crate::ibc::core::router::{Module, ModuleId, Router}; +use crate::ibc::core::host::types::identifiers::PortId; +use crate::ibc::core::router::module::Module; +use crate::ibc::core::router::router::Router; +use crate::ibc::core::router::types::module::ModuleId; /// IBC router #[derive(Debug, Default)] diff --git a/core/src/ledger/ibc/context/token_transfer.rs b/core/src/ledger/ibc/context/token_transfer.rs index 4c41b8c956..c358049bc2 100644 --- a/core/src/ledger/ibc/context/token_transfer.rs +++ b/core/src/ledger/ibc/context/token_transfer.rs @@ -4,15 +4,14 @@ use std::cell::RefCell; use std::rc::Rc; use super::common::IbcCommonContext; -use crate::ibc::applications::transfer::coin::PrefixedCoin; -use crate::ibc::applications::transfer::context::{ +use crate::ibc::apps::transfer::context::{ TokenTransferExecutionContext, TokenTransferValidationContext, }; -use crate::ibc::applications::transfer::denom::PrefixedDenom; -use crate::ibc::applications::transfer::error::TokenTransferError; -use crate::ibc::core::ics04_channel::error::ChannelError; -use crate::ibc::core::ics24_host::identifier::{ChannelId, PortId}; -use crate::ibc::core::ContextError; +use crate::ibc::apps::transfer::types::error::TokenTransferError; +use crate::ibc::apps::transfer::types::{PrefixedCoin, PrefixedDenom}; +use crate::ibc::core::channel::types::error::ChannelError; +use crate::ibc::core::handler::types::error::ContextError; +use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; use crate::ledger::ibc::storage; use crate::ledger::storage_api::token::read_denom; use crate::types::address::{Address, InternalAddress}; diff --git a/core/src/ledger/ibc/context/transfer_mod.rs b/core/src/ledger/ibc/context/transfer_mod.rs index b3951e24de..5bc18b35c3 100644 --- a/core/src/ledger/ibc/context/transfer_mod.rs +++ b/core/src/ledger/ibc/context/transfer_mod.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use super::common::IbcCommonContext; use super::token_transfer::TokenTransferContext; -use crate::ibc::applications::transfer::context::{ +use crate::ibc::apps::transfer::module::{ on_acknowledgement_packet_execute, on_acknowledgement_packet_validate, on_chan_close_confirm_execute, on_chan_close_confirm_validate, on_chan_close_init_execute, on_chan_close_init_validate, @@ -17,18 +17,19 @@ use crate::ibc::applications::transfer::context::{ on_recv_packet_execute, on_timeout_packet_execute, on_timeout_packet_validate, }; -use crate::ibc::applications::transfer::error::TokenTransferError; -use crate::ibc::applications::transfer::MODULE_ID_STR; -use crate::ibc::core::ics04_channel::acknowledgement::Acknowledgement; -use crate::ibc::core::ics04_channel::channel::{Counterparty, Order}; -use crate::ibc::core::ics04_channel::error::{ChannelError, PacketError}; -use crate::ibc::core::ics04_channel::packet::Packet; -use crate::ibc::core::ics04_channel::Version; -use crate::ibc::core::ics24_host::identifier::{ +use crate::ibc::apps::transfer::types::error::TokenTransferError; +use crate::ibc::apps::transfer::types::MODULE_ID_STR; +use crate::ibc::core::channel::types::acknowledgement::Acknowledgement; +use crate::ibc::core::channel::types::channel::{Counterparty, Order}; +use crate::ibc::core::channel::types::error::{ChannelError, PacketError}; +use crate::ibc::core::channel::types::packet::Packet; +use crate::ibc::core::channel::types::Version; +use crate::ibc::core::host::types::identifiers::{ ChannelId, ConnectionId, PortId, }; -use crate::ibc::core::router::{Module, ModuleExtras, ModuleId}; -use crate::ibc::Signer; +use crate::ibc::core::router::module::Module; +use crate::ibc::core::router::types::module::{ModuleExtras, ModuleId}; +use crate::ibc::primitives::Signer; /// IBC module wrapper for getting the reference of the module pub trait ModuleWrapper: Module { @@ -331,8 +332,8 @@ fn into_packet_error(error: TokenTransferError) -> PacketError { #[cfg(any(test, feature = "testing"))] pub mod testing { use super::*; - use crate::ibc::applications::transfer::ack_success_b64; - use crate::ibc::core::ics04_channel::acknowledgement::AcknowledgementStatus; + use crate::ibc::apps::transfer::types::ack_success_b64; + use crate::ibc::core::channel::types::acknowledgement::AcknowledgementStatus; /// Dummy IBC module for token transfer #[derive(Debug)] diff --git a/core/src/ledger/ibc/context/validation.rs b/core/src/ledger/ibc/context/validation.rs index ffc0585c8c..8ecd55fe0b 100644 --- a/core/src/ledger/ibc/context/validation.rs +++ b/core/src/ledger/ibc/context/validation.rs @@ -1,35 +1,37 @@ //! ValidationContext implementation for IBC +#[cfg(feature = "testing")] +use ibc_testkit::testapp::ibc::clients::mock::client_state::MockClientState; + use super::client::{AnyClientState, AnyConsensusState}; use super::common::IbcCommonContext; use super::IbcContext; -use crate::ibc::clients::ics07_tendermint::{ +use crate::ibc::clients::tendermint::context::{ CommonContext as TmCommonContext, ValidationContext as TmValidationContext, }; -use crate::ibc::core::ics02_client::error::ClientError; -use crate::ibc::core::ics02_client::ClientValidationContext; -use crate::ibc::core::ics03_connection::connection::ConnectionEnd; -use crate::ibc::core::ics04_channel::channel::ChannelEnd; -use crate::ibc::core::ics04_channel::commitment::{ +use crate::ibc::core::channel::types::channel::ChannelEnd; +use crate::ibc::core::channel::types::commitment::{ AcknowledgementCommitment, PacketCommitment, }; -use crate::ibc::core::ics04_channel::packet::{Receipt, Sequence}; -use crate::ibc::core::ics23_commitment::commitment::CommitmentPrefix; -use crate::ibc::core::ics23_commitment::specs::ProofSpecs; -use crate::ibc::core::ics24_host::identifier::{ - ChainId, ClientId, ConnectionId, +use crate::ibc::core::channel::types::packet::Receipt; +use crate::ibc::core::client::context::ClientValidationContext; +use crate::ibc::core::client::types::error::ClientError; +use crate::ibc::core::client::types::Height; +use crate::ibc::core::commitment_types::commitment::CommitmentPrefix; +use crate::ibc::core::commitment_types::specs::ProofSpecs; +use crate::ibc::core::connection::types::ConnectionEnd; +use crate::ibc::core::handler::types::error::ContextError; +use crate::ibc::core::host::types::identifiers::{ + ChainId, ClientId, ConnectionId, Sequence, }; -use crate::ibc::core::ics24_host::path::{ +use crate::ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConsensusStatePath, CommitmentPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, }; -use crate::ibc::core::timestamp::Timestamp; -use crate::ibc::core::{ContextError, ValidationContext}; -use crate::ibc::hosts::tendermint::ValidateSelfClientContext; -#[cfg(any(feature = "ibc-mocks-abcipp", feature = "ibc-mocks"))] -use crate::ibc::mock::client_state::MockClientState; -use crate::ibc::{Height, Signer}; -use crate::ibc_proto::google::protobuf::Any; +use crate::ibc::core::host::ValidationContext; +use crate::ibc::cosmos_host::ValidateSelfClientContext; +use crate::ibc::primitives::proto::Any; +use crate::ibc::primitives::{Signer, Timestamp}; use crate::ledger::ibc::storage; const COMMITMENT_PREFIX: &[u8] = b"ibc"; @@ -85,9 +87,9 @@ where } } -#[cfg(feature = "ibc-mocks")] -use crate::ibc::mock::client_state::MockClientContext; -#[cfg(feature = "ibc-mocks")] +#[cfg(feature = "testing")] +use ibc_testkit::testapp::ibc::clients::mock::client_state::MockClientContext; +#[cfg(feature = "testing")] impl MockClientContext for IbcContext where C: IbcCommonContext, @@ -164,8 +166,8 @@ where client_cons_state_path: &ClientConsensusStatePath, ) -> Result { let height = Height::new( - client_cons_state_path.epoch, - client_cons_state_path.height, + client_cons_state_path.revision_number, + client_cons_state_path.revision_height, )?; self.inner .borrow() @@ -205,7 +207,7 @@ where &self, counterparty_client_state: Any, ) -> Result<(), ContextError> { - #[cfg(any(feature = "ibc-mocks-abcipp", feature = "ibc-mocks"))] + #[cfg(feature = "testing")] { if MockClientState::try_from(counterparty_client_state.clone()) .is_ok() diff --git a/core/src/ledger/ibc/mod.rs b/core/src/ledger/ibc/mod.rs index 2a4919100e..808ed013af 100644 --- a/core/src/ledger/ibc/mod.rs +++ b/core/src/ledger/ibc/mod.rs @@ -18,19 +18,23 @@ pub use context::ValidationParams; use prost::Message; use thiserror::Error; -use crate::ibc::applications::transfer::error::TokenTransferError; -use crate::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use crate::ibc::applications::transfer::{ - is_receiver_chain_source, send_transfer_execute, send_transfer_validate, - PrefixedDenom, TracePrefix, +use crate::ibc::apps::transfer::handler::{ + send_transfer_execute, send_transfer_validate, }; -use crate::ibc::core::ics04_channel::msgs::PacketMsg; -use crate::ibc::core::ics24_host::identifier::{ - ChannelId, IdentifierError, PortId, +use crate::ibc::apps::transfer::types::error::TokenTransferError; +use crate::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use crate::ibc::apps::transfer::types::{ + is_receiver_chain_source, PrefixedDenom, TracePrefix, }; -use crate::ibc::core::router::ModuleId; -use crate::ibc::core::{execute, validate, MsgEnvelope, RouterError}; -use crate::ibc_proto::google::protobuf::Any; +use crate::ibc::core::channel::types::msgs::PacketMsg; +use crate::ibc::core::entrypoint::{execute, validate}; +use crate::ibc::core::handler::types::error::ContextError; +use crate::ibc::core::handler::types::msgs::MsgEnvelope; +use crate::ibc::core::host::types::error::IdentifierError; +use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; +use crate::ibc::core::router::types::error::RouterError; +use crate::ibc::core::router::types::module::ModuleId; +use crate::ibc::primitives::proto::Any; use crate::types::address::{Address, MASP}; use crate::types::ibc::{ get_shielded_transfer, is_ibc_denom, EVENT_TYPE_DENOM_TRACE, @@ -45,14 +49,12 @@ pub enum Error { DecodingData(prost::DecodeError), #[error("Decoding message error: {0}")] DecodingMessage(RouterError), - #[error("IBC storage error: {0}")] - IbcStorage(storage::Error), #[error("IBC execution error: {0}")] - Execution(RouterError), + Execution(ContextError), #[error("IBC token transfer error: {0}")] TokenTransfer(TokenTransferError), #[error("IBC validation error: {0}")] - Validation(RouterError), + Validation(ContextError), #[error("IBC module doesn't exist")] NoModule, #[error("Denom error: {0}")] @@ -114,8 +116,8 @@ where .map_err(Error::TokenTransfer) } Err(_) => { - let envelope = - MsgEnvelope::try_from(any_msg).map_err(Error::Execution)?; + let envelope = MsgEnvelope::try_from(any_msg) + .map_err(Error::DecodingMessage)?; execute(&mut self.ctx, &mut self.router, envelope.clone()) .map_err(Error::Execution)?; // For receiving the token to a shielded address @@ -230,7 +232,7 @@ where } Err(_) => { let envelope = MsgEnvelope::try_from(any_msg) - .map_err(Error::Validation)?; + .map_err(Error::DecodingMessage)?; validate(&self.ctx, &self.router, envelope) .map_err(Error::Validation) } diff --git a/core/src/ledger/ibc/storage.rs b/core/src/ledger/ibc/storage.rs index dae7d8d0d2..eeaecd2efa 100644 --- a/core/src/ledger/ibc/storage.rs +++ b/core/src/ledger/ibc/storage.rs @@ -5,12 +5,11 @@ use std::str::FromStr; use sha2::{Digest, Sha256}; use thiserror::Error; -use crate::ibc::core::ics02_client::height::Height; -use crate::ibc::core::ics04_channel::packet::Sequence; -use crate::ibc::core::ics24_host::identifier::{ - ChannelId, ClientId, ConnectionId, PortId, +use crate::ibc::core::client::types::Height; +use crate::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, ConnectionId, PortId, Sequence, }; -use crate::ibc::core::ics24_host::path::{ +use crate::ibc::core::host::types::path::{ AckPath, ChannelEndPath, ClientConnectionPath, ClientConsensusStatePath, ClientStatePath, CommitmentPath, ConnectionPath, Path, PortPath, ReceiptPath, SeqAckPath, SeqRecvPath, SeqSendPath, @@ -81,8 +80,8 @@ pub fn client_state_key(client_id: &ClientId) -> Key { pub fn consensus_state_key(client_id: &ClientId, height: Height) -> Key { let path = Path::ClientConsensusState(ClientConsensusStatePath { client_id: client_id.clone(), - epoch: height.revision_number(), - height: height.revision_height(), + revision_number: height.revision_number(), + revision_height: height.revision_height(), }); ibc_key(path.to_string()) .expect("Creating a key for the consensus state shouldn't fail") @@ -92,8 +91,8 @@ pub fn consensus_state_key(client_id: &ClientId, height: Height) -> Key { pub fn consensus_state_prefix(client_id: &ClientId) -> Key { let path = Path::ClientConsensusState(ClientConsensusStatePath { client_id: client_id.clone(), - epoch: 0, - height: 0, + revision_number: 0, + revision_height: 0, }); let suffix = "/0-0".to_string(); let path = path.to_string(); diff --git a/core/src/types/address.rs b/core/src/types/address.rs index 2543fc7f54..b444ef756b 100644 --- a/core/src/types/address.rs +++ b/core/src/types/address.rs @@ -14,7 +14,7 @@ use data_encoding::HEXUPPER; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; -use crate::ibc::Signer; +use crate::ibc::primitives::Signer; use crate::impl_display_and_from_str_via_format; use crate::types::ethereum_events::EthAddress; use crate::types::ibc::IbcTokenHash; diff --git a/core/src/types/ibc.rs b/core/src/types/ibc.rs index 9490f1efdc..2f04e11709 100644 --- a/core/src/types/ibc.rs +++ b/core/src/types/ibc.rs @@ -11,8 +11,8 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use super::address::HASH_LEN; -use crate::ibc::applications::transfer::{Memo, PrefixedDenom, TracePath}; -use crate::ibc::core::events::{ +use crate::ibc::apps::transfer::types::{Memo, PrefixedDenom, TracePath}; +use crate::ibc::core::handler::types::events::{ Error as IbcEventError, IbcEvent as RawIbcEvent, }; use crate::tendermint::abci::Event as AbciEvent; diff --git a/core/src/types/token.rs b/core/src/types/token.rs index 5c319b7da6..2becc07151 100644 --- a/core/src/types/token.rs +++ b/core/src/types/token.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use super::dec::POS_DECIMAL_PRECISION; -use crate::ibc::applications::transfer::Amount as IbcAmount; +use crate::ibc::apps::transfer::types::Amount as IbcAmount; use crate::ledger::storage as ledger_storage; use crate::ledger::storage_api::token::read_denom; use crate::ledger::storage_api::{self, StorageRead, StorageWrite}; diff --git a/sdk/Cargo.toml b/sdk/Cargo.toml index 713f99e035..e1a36a2d09 100644 --- a/sdk/Cargo.toml +++ b/sdk/Cargo.toml @@ -41,10 +41,6 @@ async-client = [ "async-trait", ] -ibc-mocks = [ - "namada_core/ibc-mocks", -] - # for integration tests and test utilies testing = [ "namada_core/testing", diff --git a/sdk/src/args.rs b/sdk/src/args.rs index 3359c08ec4..f80256b6c5 100644 --- a/sdk/src/args.rs +++ b/sdk/src/args.rs @@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize}; use zeroize::Zeroizing; use crate::eth_bridge::bridge_pool; -use crate::ibc::core::ics24_host::identifier::{ChannelId, PortId}; +use crate::ibc::core::host::types::identifiers::{ChannelId, PortId}; use crate::signing::SigningTxData; use crate::{rpc, tx, Namada}; diff --git a/sdk/src/events/log/dumb_queries.rs b/sdk/src/events/log/dumb_queries.rs index 44988fb0dc..8a639b5a1b 100644 --- a/sdk/src/events/log/dumb_queries.rs +++ b/sdk/src/events/log/dumb_queries.rs @@ -12,9 +12,10 @@ use namada_core::types::hash::Hash; use namada_core::types::storage::BlockHeight; use crate::events::{Event, EventType}; -use crate::ibc::core::ics04_channel::packet::Sequence; -use crate::ibc::core::ics24_host::identifier::{ChannelId, ClientId, PortId}; -use crate::ibc::Height as IbcHeight; +use crate::ibc::core::client::types::Height as IbcHeight; +use crate::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, PortId, Sequence, +}; /// A [`QueryMatcher`] verifies if a Namada event matches a /// given Tendermint query. @@ -65,8 +66,9 @@ impl QueryMatcher { client_id: ClientId, consensus_height: BlockHeight, ) -> Self { - use crate::ibc::core::ics02_client::events::{ + use crate::ibc::core::client::types::events::{ CLIENT_ID_ATTRIBUTE_KEY, CONSENSUS_HEIGHTS_ATTRIBUTE_KEY, + UPDATE_CLIENT_EVENT, }; let mut attributes = HashMap::new(); @@ -79,7 +81,7 @@ impl QueryMatcher { .to_string(), ); Self { - event_type: EventType::Ibc("update_client".to_string()), + event_type: EventType::Ibc(UPDATE_CLIENT_EVENT.to_string()), attributes, } } diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index f5c0ae37fa..5c31194990 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -32,6 +32,7 @@ use std::path::PathBuf; use std::str::FromStr; use args::{InputAmount, SdkTypes}; +use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada_core::types::address::Address; use namada_core::types::dec::Dec; use namada_core::types::ethereum_events::EthAddress; @@ -42,7 +43,6 @@ use namada_core::types::token::NATIVE_MAX_DECIMAL_PLACES; use namada_core::types::transaction::GasLimit; use tokio::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -use crate::ibc::core::ics24_host::identifier::{ChannelId, PortId}; use crate::io::Io; use crate::masp::{ShieldedContext, ShieldedUtils}; use crate::proto::Tx; diff --git a/sdk/src/queries/router.rs b/sdk/src/queries/router.rs index b632097738..c78c0a6fcd 100644 --- a/sdk/src/queries/router.rs +++ b/sdk/src/queries/router.rs @@ -830,7 +830,7 @@ macro_rules! router { /// You can expand the `handlers!` macro invocation with e.g.: /// ```shell -/// cargo expand ledger::queries::router::test_rpc_handlers --features "ibc-mocks, testing, wasm-runtime, tendermint-rpc" --tests --lib +/// cargo expand ledger::queries::router::test_rpc_handlers --features "testing, wasm-runtime, tendermint-rpc" --tests --lib /// ``` #[cfg(test)] mod test_rpc_handlers { @@ -959,7 +959,7 @@ mod test_rpc_handlers { /// You can expand the `router!` macro invocation with e.g.: /// ```shell -/// cargo expand ledger::queries::router::test_rpc --features "ibc-mocks, testing, wasm-runtime, tendermint-rpc" --tests --lib +/// cargo expand ledger::queries::router::test_rpc --features "testing, wasm-runtime, tendermint-rpc" --tests --lib /// ``` #[cfg(test)] mod test_rpc { diff --git a/sdk/src/queries/shell.rs b/sdk/src/queries/shell.rs index c8e907671f..23f7441cae 100644 --- a/sdk/src/queries/shell.rs +++ b/sdk/src/queries/shell.rs @@ -24,8 +24,9 @@ use namada_core::types::transaction::TxResult; use self::eth_bridge::{EthBridge, ETH_BRIDGE}; use crate::events::log::dumb_queries; use crate::events::{Event, EventType}; -use crate::ibc::core::ics04_channel::packet::Sequence; -use crate::ibc::core::ics24_host::identifier::{ChannelId, ClientId, PortId}; +use crate::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, PortId, Sequence, +}; use crate::queries::types::{RequestCtx, RequestQuery}; use crate::queries::{require_latest_height, EncodedResponseQuery}; use crate::tendermint::merkle::proof::ProofOps; diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index 6784be92ba..a9bdece9d9 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -41,8 +41,8 @@ use crate::core::ledger::governance::storage::vote::{ StorageProposalVote, VoteType, }; use crate::error::{EncodingError, Error, TxError}; -use crate::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use crate::ibc_proto::google::protobuf::Any; +use crate::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use crate::ibc::primitives::proto::Any; use crate::io::*; use crate::masp::make_asset_type; use crate::proto::{MaspBuilder, Section, Tx}; diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index 9378615890..dd8315bb7a 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -16,13 +16,13 @@ use masp_primitives::transaction::components::transparent::fees::{ InputView as TransparentInputView, OutputView as TransparentOutputView, }; use masp_primitives::transaction::components::I128Sum; -use namada_core::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use namada_core::ibc::applications::transfer::packet::PacketData; -use namada_core::ibc::applications::transfer::PrefixedCoin; -use namada_core::ibc::core::ics04_channel::timeout::TimeoutHeight; -use namada_core::ibc::core::timestamp::Timestamp as IbcTimestamp; -use namada_core::ibc::core::Msg; -use namada_core::ibc::Height as IbcHeight; +use namada_core::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use namada_core::ibc::apps::transfer::types::packet::PacketData; +use namada_core::ibc::apps::transfer::types::PrefixedCoin; +use namada_core::ibc::core::channel::types::timeout::TimeoutHeight; +use namada_core::ibc::core::client::types::Height as IbcHeight; +use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; +use namada_core::ibc::primitives::{Msg, Timestamp as IbcTimestamp}; use namada_core::ledger::governance::cli::onchain::{ DefaultProposal, OnChainProposal, PgfFundingProposal, PgfStewardProposal, ProposalVote, @@ -53,7 +53,6 @@ use namada_proof_of_stake::types::{CommissionPair, ValidatorState}; use crate::args::{self, InputAmount}; use crate::control_flow::time; use crate::error::{EncodingError, Error, QueryError, Result, TxError}; -use crate::ibc::core::ics24_host::identifier::{ChannelId, PortId}; use crate::io::Io; use crate::masp::TransferErr::Build; use crate::masp::{make_asset_type, ShieldedContext, ShieldedTransfer}; @@ -2617,8 +2616,8 @@ async fn get_ibc_src_port_channel<'a>( dest_port_id: &PortId, dest_channel_id: &ChannelId, ) -> Result<(PortId, ChannelId)> { - use crate::ibc::core::ics04_channel::channel::ChannelEnd; - use crate::ibc_proto::protobuf::Protobuf; + use crate::ibc::core::channel::types::channel::ChannelEnd; + use crate::ibc::primitives::proto::Protobuf; let channel_key = channel_key(dest_port_id, dest_channel_id); let bytes = rpc::query_storage_value_bytes( diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 2d83a73498..87ae575175 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -53,11 +53,6 @@ http-client = [ "tendermint-rpc/http-client" ] -ibc-mocks = [ - "namada_core/ibc-mocks", - "namada_sdk/ibc-mocks", -] - # for integration tests and test utilies testing = [ "namada_core/testing", @@ -144,7 +139,7 @@ tokio = {workspace = true, default-features = false, features = ["sync"]} wasmtimer = "0.2.0" [dev-dependencies] -namada_core = {path = "../core", default-features = false, features = ["testing", "ibc-mocks"]} +namada_core = {path = "../core", default-features = false, features = ["testing"]} namada_ethereum_bridge = {path = "../ethereum_bridge", default-features = false, features = ["testing"]} namada_proof_of_stake = {path = "../proof_of_stake", default-features = false, features = ["testing"]} namada_test_utils = {path = "../test_utils"} @@ -152,6 +147,7 @@ assert_matches.workspace = true async-trait.workspace = true base58.workspace = true byte-unit.workspace = true +ibc-testkit.workspace = true k256.workspace = true pretty_assertions.workspace = true proptest.workspace = true diff --git a/shared/src/ledger/native_vp/ibc/mod.rs b/shared/src/ledger/native_vp/ibc/mod.rs index 78e1378baa..cd0a1e5680 100644 --- a/shared/src/ledger/native_vp/ibc/mod.rs +++ b/shared/src/ledger/native_vp/ibc/mod.rs @@ -22,7 +22,7 @@ use namada_core::types::storage::Key; use namada_proof_of_stake::read_pos_params; use thiserror::Error; -use crate::ibc::core::ics24_host::identifier::ChainId as IbcChainId; +use crate::ibc::core::host::types::identifiers::ChainId as IbcChainId; use crate::ledger::ibc::storage::{calc_hash, is_ibc_denom_key, is_ibc_key}; use crate::ledger::native_vp::{self, Ctx, NativeVp, VpEnv}; use crate::ledger::parameters::read_epoch_duration_parameter; @@ -313,6 +313,11 @@ mod tests { use borsh::BorshDeserialize; use borsh_ext::BorshSerializeExt; + use ibc_testkit::testapp::ibc::clients::mock::client_state::{ + client_type, MockClientState, MOCK_CLIENT_TYPE, + }; + use ibc_testkit::testapp::ibc::clients::mock::consensus_state::MockConsensusState; + use ibc_testkit::testapp::ibc::clients::mock::header::MockHeader; use namada_core::ledger::gas::TxGasMeter; use namada_core::ledger::governance::parameters::GovernanceParameters; use prost::Message; @@ -333,72 +338,64 @@ mod tests { }; use crate::core::types::address::{nam, InternalAddress}; use crate::core::types::storage::Epoch; - use crate::ibc::applications::transfer::coin::PrefixedCoin; - use crate::ibc::applications::transfer::denom::TracePrefix; - use crate::ibc::applications::transfer::events::{ + use crate::ibc::apps::transfer::types::events::{ AckEvent, DenomTraceEvent, RecvEvent, TimeoutEvent, TransferEvent, }; - use crate::ibc::applications::transfer::msgs::transfer::MsgTransfer; - use crate::ibc::applications::transfer::packet::PacketData; - use crate::ibc::applications::transfer::{ack_success_b64, VERSION}; - use crate::ibc::core::events::{ - IbcEvent as RawIbcEvent, MessageEvent, ModuleEvent, - }; - use crate::ibc::core::ics02_client::events::{CreateClient, UpdateClient}; - use crate::ibc::core::ics02_client::msgs::create_client::MsgCreateClient; - use crate::ibc::core::ics02_client::msgs::update_client::MsgUpdateClient; - use crate::ibc::core::ics03_connection::connection::{ - ConnectionEnd, Counterparty as ConnCounterparty, State as ConnState, - }; - use crate::ibc::core::ics03_connection::events::{ - OpenAck as ConnOpenAck, OpenConfirm as ConnOpenConfirm, - OpenInit as ConnOpenInit, OpenTry as ConnOpenTry, - }; - use crate::ibc::core::ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck; - use crate::ibc::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOpenConfirm; - use crate::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; - use crate::ibc::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; - use crate::ibc::core::ics03_connection::version::{ - get_compatible_versions, Version as ConnVersion, + use crate::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; + use crate::ibc::apps::transfer::types::packet::PacketData; + use crate::ibc::apps::transfer::types::{ + ack_success_b64, PrefixedCoin, TracePrefix, VERSION, }; - use crate::ibc::core::ics04_channel::acknowledgement::{ + use crate::ibc::core::channel::types::acknowledgement::{ Acknowledgement, AcknowledgementStatus, }; - use crate::ibc::core::ics04_channel::channel::{ + use crate::ibc::core::channel::types::channel::{ ChannelEnd, Counterparty as ChanCounterparty, Order, State as ChanState, }; - use crate::ibc::core::ics04_channel::commitment::PacketCommitment; - use crate::ibc::core::ics04_channel::events::{ + use crate::ibc::core::channel::types::commitment::PacketCommitment; + use crate::ibc::core::channel::types::events::{ AcknowledgePacket, OpenAck as ChanOpenAck, OpenConfirm as ChanOpenConfirm, OpenInit as ChanOpenInit, OpenTry as ChanOpenTry, ReceivePacket, SendPacket, TimeoutPacket, WriteAcknowledgement, }; - use crate::ibc::core::ics04_channel::msgs::{ + use crate::ibc::core::channel::types::msgs::{ MsgAcknowledgement, MsgChannelOpenAck, MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeout, MsgTimeoutOnClose, }; - use crate::ibc::core::ics04_channel::packet::{Packet, Sequence}; - use crate::ibc::core::ics04_channel::timeout::TimeoutHeight; - use crate::ibc::core::ics04_channel::Version as ChanVersion; - use crate::ibc::core::ics23_commitment::commitment::{ + use crate::ibc::core::channel::types::packet::Packet; + use crate::ibc::core::channel::types::timeout::TimeoutHeight; + use crate::ibc::core::channel::types::Version as ChanVersion; + use crate::ibc::core::client::types::events::{CreateClient, UpdateClient}; + use crate::ibc::core::client::types::msgs::{ + MsgCreateClient, MsgUpdateClient, + }; + use crate::ibc::core::client::types::Height; + use crate::ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentProofBytes, }; - use crate::ibc::core::ics24_host::identifier::{ - ChannelId, ClientId, ConnectionId, PortId, + use crate::ibc::core::connection::types::events::{ + OpenAck as ConnOpenAck, OpenConfirm as ConnOpenConfirm, + OpenInit as ConnOpenInit, OpenTry as ConnOpenTry, + }; + use crate::ibc::core::connection::types::msgs::{ + MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit, + MsgConnectionOpenTry, }; - use crate::ibc::core::timestamp::Timestamp; - use crate::ibc::core::Msg; - use crate::ibc::mock::client_state::{ - client_type, MockClientState, MOCK_CLIENT_TYPE, + use crate::ibc::core::connection::types::version::Version as ConnVersion; + use crate::ibc::core::connection::types::{ + ConnectionEnd, Counterparty as ConnCounterparty, State as ConnState, + }; + use crate::ibc::core::handler::types::events::{ + IbcEvent as RawIbcEvent, MessageEvent, }; - use crate::ibc::mock::consensus_state::MockConsensusState; - use crate::ibc::mock::header::MockHeader; - use crate::ibc::Height; - use crate::ibc_proto::google::protobuf::Any; - use crate::ibc_proto::ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry; - use crate::ibc_proto::protobuf::Protobuf; + use crate::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, ConnectionId, PortId, Sequence, + }; + use crate::ibc::core::router::types::event::ModuleEvent; + use crate::ibc::primitives::proto::{Any, Protobuf}; + use crate::ibc::primitives::{Msg, Timestamp}; use crate::ledger::gas::VpGasMeter; use crate::ledger::parameters::storage::{ get_epoch_duration_storage_key, get_max_expected_time_per_block_key, @@ -408,7 +405,6 @@ mod tests { use crate::ledger::{ibc, pos}; use crate::proto::{Code, Data, Section, Signature, Tx}; use crate::tendermint::time::Time as TmTime; - use crate::tendermint_proto::Protobuf as TmProtobuf; use crate::types::key::testing::keypair_1; use crate::types::storage::{BlockHash, BlockHeight, TxIndex}; use crate::types::time::DurationSecs; @@ -480,7 +476,7 @@ mod tests { timestamp: Timestamp::now(), }; let client_state = MockClientState::new(header); - let bytes = Protobuf::::encode_vec(&client_state); + let bytes = Protobuf::::encode_vec(client_state); wl_storage .write_log .write(&client_state_key, bytes) @@ -488,7 +484,7 @@ mod tests { // insert a mock consensus state let consensus_key = consensus_state_key(&client_id, height); let consensus_state = MockConsensusState::new(header); - let bytes = Protobuf::::encode_vec(&consensus_state); + let bytes = Protobuf::::encode_vec(consensus_state); wl_storage .write_log .write(&consensus_key, bytes) @@ -682,7 +678,7 @@ mod tests { }; // client state let client_state_key = client_state_key(&get_client_id()); - let bytes = Protobuf::::encode_vec(&client_state); + let bytes = Protobuf::::encode_vec(client_state); wl_storage .write_log .write(&client_state_key, bytes) @@ -690,7 +686,7 @@ mod tests { keys_changed.insert(client_state_key); // client consensus let consensus_key = consensus_state_key(&client_id, height); - let bytes = Protobuf::::encode_vec(&consensus_state); + let bytes = Protobuf::::encode_vec(consensus_state); wl_storage .write_log .write(&consensus_key, bytes) @@ -780,7 +776,7 @@ mod tests { // insert only client state let client_state = MockClientState::new(header); let client_state_key = client_state_key(&get_client_id()); - let bytes = Protobuf::::encode_vec(&client_state); + let bytes = Protobuf::::encode_vec(client_state); wl_storage .write_log .write(&client_state_key, bytes) @@ -866,7 +862,7 @@ mod tests { }; // client state let client_state = MockClientState::new(header); - let bytes = Protobuf::::encode_vec(&client_state); + let bytes = Protobuf::::encode_vec(client_state); wl_storage .write_log .write(&client_state_key, bytes) @@ -875,7 +871,7 @@ mod tests { // consensus state let consensus_key = consensus_state_key(&client_id, height); let consensus_state = MockConsensusState::new(header); - let bytes = Protobuf::::encode_vec(&consensus_state); + let bytes = Protobuf::::encode_vec(consensus_state); wl_storage .write_log .write(&consensus_key, bytes) @@ -913,7 +909,7 @@ mod tests { client_type(), consensus_height, vec![consensus_height], - Protobuf::::encode_vec(&header), + Protobuf::::encode_vec(header), )); let message_event = RawIbcEvent::Message(MessageEvent::Client); wl_storage @@ -1190,29 +1186,22 @@ mod tests { }; let client_state = MockClientState::new(header); let proof_height = Height::new(0, 1).unwrap(); - // Convert a message from RawMsgConnectionOpenTry - // because MsgConnectionOpenTry cannot be created directly #[allow(deprecated)] - let msg: MsgConnectionOpenTry = RawMsgConnectionOpenTry { - client_id: get_client_id().as_str().to_string(), - client_state: Some(client_state.into()), - counterparty: Some(get_conn_counterparty().into()), - delay_period: 0, - counterparty_versions: get_compatible_versions() - .iter() - .map(|v| v.clone().into()) - .collect(), - proof_init: dummy_proof().into(), - proof_height: Some(proof_height.into()), - proof_consensus: dummy_proof().into(), - consensus_height: Some(client_state.latest_height().into()), - proof_client: dummy_proof().into(), - signer: "account0".to_string(), + let msg = MsgConnectionOpenTry { + client_id_on_b: get_client_id(), + client_state_of_b_on_a: client_state.into(), + counterparty: get_conn_counterparty(), + versions_on_a: vec![ConnVersion::default()], + proofs_height_on_a: proof_height, + proof_conn_end_on_a: dummy_proof(), + proof_client_state_of_b_on_a: dummy_proof(), + proof_consensus_state_of_b_on_a: dummy_proof(), + consensus_height_of_b_on_a: client_state.latest_height(), + delay_period: Duration::from_secs(0), + signer: "account0".to_string().into(), + proof_consensus_state_of_b: Some(dummy_proof()), previous_connection_id: ConnectionId::default().to_string(), - host_consensus_state_proof: dummy_proof().into(), - } - .try_into() - .expect("invalid message"); + }; // insert a TryOpen connection let conn_id = get_connection_id(); diff --git a/tests/Cargo.toml b/tests/Cargo.toml index de9b821ac9..bfc6df073b 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -21,7 +21,7 @@ wasm-runtime = ["namada/wasm-runtime"] integration = ["namada_apps/integration"] [dependencies] -namada = {path = "../shared", features = ["testing", "ibc-mocks"]} +namada = {path = "../shared", features = ["testing"]} namada_core = {path = "../core", features = ["testing"]} namada_sdk = {path = "../sdk"} namada_test_utils = {path = "../test_utils"} @@ -34,6 +34,7 @@ concat-idents.workspace = true copy_dir = "0.1.3" derivative.workspace = true hyper = {version = "0.14.20", features = ["full"]} +ibc-testkit.workspace = true lazy_static.workspace = true num-traits.workspace = true prost.workspace = true diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index e1b3479d6e..7afc278e97 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -17,39 +17,41 @@ use std::path::PathBuf; use color_eyre::eyre::Result; use eyre::eyre; -use namada::ibc::applications::transfer::VERSION as ICS20_VERSION; -use namada::ibc::clients::ics07_tendermint::client_state::{ - AllowUpdate, ClientState as TmClientState, +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; +use namada::ibc::clients::tendermint::types::{ + AllowUpdate, ClientState as TmClientStateType, Header as IbcTmHeader, + TrustThreshold, }; -use namada::ibc::clients::ics07_tendermint::consensus_state::ConsensusState as TmConsensusState; -use namada::ibc::clients::ics07_tendermint::header::Header as IbcTmHeader; -use namada::ibc::clients::ics07_tendermint::trust_threshold::TrustThreshold; -use namada::ibc::core::ics02_client::msgs::create_client::MsgCreateClient; -use namada::ibc::core::ics02_client::msgs::update_client::MsgUpdateClient; -use namada::ibc::core::ics03_connection::connection::Counterparty as ConnCounterparty; -use namada::ibc::core::ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck; -use namada::ibc::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOpenConfirm; -use namada::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; -use namada::ibc::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; -use namada::ibc::core::ics03_connection::version::Version as ConnVersion; -use namada::ibc::core::ics04_channel::channel::Order as ChanOrder; -use namada::ibc::core::ics04_channel::msgs::{ +use namada::ibc::core::channel::types::channel::Order as ChanOrder; +use namada::ibc::core::channel::types::msgs::{ MsgAcknowledgement, MsgChannelOpenAck, MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeout, }; -use namada::ibc::core::ics04_channel::packet::Packet; -use namada::ibc::core::ics04_channel::timeout::TimeoutHeight; -use namada::ibc::core::ics04_channel::Version as ChanVersion; -use namada::ibc::core::ics23_commitment::commitment::{ +use namada::ibc::core::channel::types::packet::Packet; +use namada::ibc::core::channel::types::timeout::TimeoutHeight; +use namada::ibc::core::channel::types::Version as ChanVersion; +use namada::ibc::core::client::context::client_state::ClientStateCommon; +use namada::ibc::core::client::types::msgs::{ + MsgCreateClient, MsgUpdateClient, +}; +use namada::ibc::core::client::types::Height; +use namada::ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentProofBytes, }; -use namada::ibc::core::ics23_commitment::merkle::MerkleProof; -use namada::ibc::core::ics24_host::identifier::{ +use namada::ibc::core::commitment_types::merkle::MerkleProof; +use namada::ibc::core::connection::types::msgs::{ + MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit, + MsgConnectionOpenTry, +}; +use namada::ibc::core::connection::types::version::Version as ConnVersion; +use namada::ibc::core::connection::types::Counterparty as ConnCounterparty; +use namada::ibc::core::host::types::identifiers::{ ChainId, ChannelId, ClientId, ConnectionId, PortId, }; -use namada::ibc::core::Msg; -use namada::ibc::{Height, Signer}; -use namada::ibc_proto::google::protobuf::Any; +use namada::ibc::primitives::proto::Any; +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}; @@ -299,7 +301,7 @@ fn setup_two_single_node_nets() -> Result<(Test, Test)> { fn create_client(test_a: &Test, test_b: &Test) -> Result<(ClientId, ClientId)> { let height = query_height(test_b)?; let client_state = make_client_state(test_b, height); - let height = client_state.latest_height; + let height = client_state.latest_height(); let message = MsgCreateClient { client_state: client_state.into(), consensus_state: make_consensus_state(test_b, height)?.into(), @@ -309,7 +311,7 @@ fn create_client(test_a: &Test, test_b: &Test) -> Result<(ClientId, ClientId)> { let height = query_height(test_a)?; let client_state = make_client_state(test_a, height); - let height = client_state.latest_height; + let height = client_state.latest_height(); let message = MsgCreateClient { client_state: client_state.into(), consensus_state: make_consensus_state(test_a, height)?.into(), @@ -350,7 +352,7 @@ fn make_client_state(test: &Test, height: Height) -> TmClientState { let max_clock_drift = Duration::new(60, 0); let chain_id = ChainId::from_str(test.net.chain_id.as_str()).unwrap(); - TmClientState::new( + TmClientStateType::new( chain_id, TrustThreshold::default(), Duration::from_secs(trusting_period), @@ -365,6 +367,7 @@ fn make_client_state(test: &Test, height: Height) -> TmClientState { }, ) .unwrap() + .into() } fn make_consensus_state( @@ -396,7 +399,7 @@ fn update_client_with_height( }; let client_state = TmClientState::try_from(cs) .expect("the state should be a TmClientState"); - let trusted_height = client_state.latest_height; + let trusted_height = client_state.latest_height(); update_client( src_test, @@ -496,15 +499,22 @@ fn connection_handshake( Some(conn_id_a.clone()), commitment_prefix(), ); - let msg = make_msg_conn_open_try( - client_id_b.clone(), - client_state, + #[allow(deprecated)] + let msg = MsgConnectionOpenTry { + client_id_on_b: client_id_b.clone(), + client_state_of_b_on_a: client_state.clone().into(), counterparty, - conn_proof, - client_state_proof, - consensus_proof, - height_a, - ); + versions_on_a: vec![ConnVersion::default()], + proofs_height_on_a: height_a, + proof_conn_end_on_a: conn_proof, + proof_client_state_of_b_on_a: client_state_proof, + proof_consensus_state_of_b_on_a: consensus_proof, + consensus_height_of_b_on_a: client_state.latest_height(), + delay_period: Duration::from_secs(0), + signer: "test".to_string().into(), + proof_consensus_state_of_b: None, + previous_connection_id: ConnectionId::default().to_string(), + }; // Update the client state of Chain A on Chain B update_client_with_height(test_a, test_b, client_id_b, height_a)?; // OpenTryConnection on Chain B @@ -518,7 +528,7 @@ fn connection_handshake( let conn_proof = get_connection_proof(test_b, &conn_id_b, height_b)?; let (client_state, client_state_proof, consensus_proof) = get_client_states(test_b, client_id_b, height_b)?; - let consensus_height_of_a_on_b = client_state.latest_height; + let consensus_height_of_a_on_b = client_state.latest_height(); let msg = MsgConnectionOpenAck { conn_id_on_a: conn_id_a.clone(), conn_id_on_b: conn_id_b.clone(), @@ -695,7 +705,7 @@ fn get_client_states( .expect("the state should be a TmClientState"); let client_state_proof = convert_proof(tm_proof)?; - let height = client_state.latest_height; + let height = client_state.latest_height(); let ibc_height = Height::new(0, height.revision_height()).unwrap(); let key = consensus_state_key(client_id, ibc_height); let (_, tm_proof) = query_value_with_proof(test, &key, Some(query_height))?; @@ -1527,40 +1537,6 @@ fn signer() -> Signer { "signer".to_string().into() } -/// Helper function to make the MsgConnectionOpenTry because it has a private -/// field -fn make_msg_conn_open_try( - client_id: ClientId, - client_state: TmClientState, - counterparty: ConnCounterparty, - conn_proof: CommitmentProofBytes, - client_state_proof: CommitmentProofBytes, - consensus_proof: CommitmentProofBytes, - proofs_height: Height, -) -> MsgConnectionOpenTry { - use namada::ibc_proto::ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry; - - let consensus_height = client_state.latest_height; - #[allow(deprecated)] - RawMsgConnectionOpenTry { - client_id: client_id.as_str().to_string(), - client_state: Some(client_state.into()), - counterparty: Some(counterparty.into()), - delay_period: 0, - counterparty_versions: vec![ConnVersion::default().into()], - proof_init: conn_proof.into(), - proof_height: Some(proofs_height.into()), - proof_client: client_state_proof.into(), - proof_consensus: consensus_proof.into(), - consensus_height: Some(consensus_height.into()), - signer: "signer".to_string(), - previous_connection_id: ConnectionId::default().to_string(), - host_consensus_state_proof: vec![], - } - .try_into() - .expect("invalid message") -} - fn get_client_id_from_events(events: &Vec) -> Option { get_attribute_from_events(events, "client_id").map(|v| v.parse().unwrap()) } @@ -1600,7 +1576,16 @@ fn get_packet_from_events(events: &Vec) -> Option { if !attributes.contains_key("packet_src_port") { continue; } - let mut packet = Packet::default(); + let mut packet = Packet { + seq_on_a: 0.into(), + port_id_on_a: PortId::transfer(), + chan_id_on_a: ChannelId::default(), + port_id_on_b: PortId::transfer(), + chan_id_on_b: ChannelId::default(), + data: vec![], + timeout_height_on_b: TimeoutHeight::default(), + timeout_timestamp_on_b: Timestamp::default(), + }; for (key, val) in attributes { match key.as_str() { "packet_src_port" => packet.port_id_on_a = val.parse().unwrap(), diff --git a/tests/src/vm_host_env/ibc.rs b/tests/src/vm_host_env/ibc.rs index 3ca3705fa9..5bc58a9775 100644 --- a/tests/src/vm_host_env/ibc.rs +++ b/tests/src/vm_host_env/ibc.rs @@ -1,50 +1,51 @@ use core::time::Duration; use std::collections::HashMap; -use namada::ibc::applications::transfer::coin::PrefixedCoin; -use namada::ibc::applications::transfer::error::TokenTransferError; -use namada::ibc::applications::transfer::msgs::transfer::MsgTransfer; -use namada::ibc::applications::transfer::packet::PacketData; -use namada::ibc::applications::transfer::{ack_success_b64, VERSION}; -use namada::ibc::core::ics02_client::msgs::create_client::MsgCreateClient; -use namada::ibc::core::ics02_client::msgs::update_client::MsgUpdateClient; -use namada::ibc::core::ics02_client::msgs::upgrade_client::MsgUpgradeClient; -use namada::ibc::core::ics03_connection::connection::{ - ConnectionEnd, Counterparty as ConnCounterparty, State as ConnState, +use ibc_testkit::testapp::ibc::clients::mock::client_state::{ + client_type, MockClientState, +}; +use ibc_testkit::testapp::ibc::clients::mock::consensus_state::MockConsensusState; +use ibc_testkit::testapp::ibc::clients::mock::header::MockHeader; +use namada::ibc::apps::transfer::types::error::TokenTransferError; +use namada::ibc::apps::transfer::types::msgs::transfer::MsgTransfer; +use namada::ibc::apps::transfer::types::packet::PacketData; +use namada::ibc::apps::transfer::types::{ + ack_success_b64, PrefixedCoin, VERSION, }; -use namada::ibc::core::ics03_connection::msgs::conn_open_ack::MsgConnectionOpenAck; -use namada::ibc::core::ics03_connection::msgs::conn_open_confirm::MsgConnectionOpenConfirm; -use namada::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; -use namada::ibc::core::ics03_connection::msgs::conn_open_try::MsgConnectionOpenTry; -use namada::ibc::core::ics03_connection::version::Version as ConnVersion; -use namada::ibc::core::ics04_channel::acknowledgement::{ +use namada::ibc::core::channel::types::acknowledgement::{ AcknowledgementStatus, StatusValue, }; -use namada::ibc::core::ics04_channel::channel::{ +use namada::ibc::core::channel::types::channel::{ ChannelEnd, Counterparty as ChanCounterparty, Order, State as ChanState, }; -use namada::ibc::core::ics04_channel::msgs::{ +use namada::ibc::core::channel::types::msgs::{ MsgAcknowledgement, MsgChannelCloseConfirm, MsgChannelCloseInit, MsgChannelOpenAck, MsgChannelOpenConfirm, MsgChannelOpenInit, MsgChannelOpenTry, MsgRecvPacket, MsgTimeout, MsgTimeoutOnClose, }; -pub use namada::ibc::core::ics04_channel::packet::{Packet, Sequence}; -use namada::ibc::core::ics04_channel::timeout::TimeoutHeight; -use namada::ibc::core::ics04_channel::Version as ChanVersion; -use namada::ibc::core::ics23_commitment::commitment::{ +pub use namada::ibc::core::channel::types::packet::Packet; +use namada::ibc::core::channel::types::timeout::TimeoutHeight; +use namada::ibc::core::channel::types::Version as ChanVersion; +use namada::ibc::core::client::types::msgs::{ + MsgCreateClient, MsgUpdateClient, MsgUpgradeClient, +}; +use namada::ibc::core::client::types::Height; +use namada::ibc::core::commitment_types::commitment::{ CommitmentPrefix, CommitmentProofBytes, }; -pub use namada::ibc::core::ics24_host::identifier::{ - ChannelId, ClientId, ConnectionId, PortId, +use namada::ibc::core::connection::types::msgs::{ + MsgConnectionOpenAck, MsgConnectionOpenConfirm, MsgConnectionOpenInit, + MsgConnectionOpenTry, +}; +use namada::ibc::core::connection::types::version::Version as ConnVersion; +use namada::ibc::core::connection::types::{ + ConnectionEnd, Counterparty as ConnCounterparty, State as ConnState, +}; +pub use namada::ibc::core::host::types::identifiers::{ + ChannelId, ClientId, ConnectionId, PortId, Sequence, }; -use namada::ibc::core::timestamp::Timestamp; -use namada::ibc::mock::client_state::{client_type, MockClientState}; -use namada::ibc::mock::consensus_state::MockConsensusState; -use namada::ibc::mock::header::MockHeader; -use namada::ibc::Height; -use namada::ibc_proto::google::protobuf::Any; -use namada::ibc_proto::ibc::core::connection::v1::MsgConnectionOpenTry as RawMsgConnectionOpenTry; -use namada::ibc_proto::protobuf::Protobuf; +use namada::ibc::primitives::proto::{Any, Protobuf}; +use namada::ibc::primitives::Timestamp; use namada::ledger::gas::VpGasMeter; pub use namada::ledger::ibc::storage::{ ack_key, channel_counter_key, channel_key, client_counter_key, @@ -71,7 +72,6 @@ use namada::ledger::{ibc, pos}; use namada::proof_of_stake::OwnedPosParams; use namada::proto::Tx; use namada::tendermint::time::Time as TmTime; -use namada::tendermint_proto::Protobuf as TmProtobuf; use namada::types::address::{self, Address, InternalAddress}; use namada::types::hash::Hash; use namada::types::storage::{ @@ -301,12 +301,12 @@ pub fn prepare_client() -> (ClientId, Any, HashMap>) { // client state let client_id = client_id(); let key = client_state_key(&client_id); - let bytes = Protobuf::::encode_vec(&client_state); + let bytes = Protobuf::::encode_vec(client_state); writes.insert(key, bytes); // consensus state let height = client_state.latest_height(); let key = consensus_state_key(&client_id, height); - let bytes = Protobuf::::encode_vec(&consensus_state); + let bytes = Protobuf::::encode_vec(consensus_state); writes.insert(key, bytes); // client update time let key = client_update_timestamp_key(&client_id); @@ -463,26 +463,22 @@ pub fn msg_connection_open_try( client_state: Any, ) -> MsgConnectionOpenTry { let consensus_height = Height::new(0, 1).expect("invalid height"); - // Convert a message from RawMsgConnectionOpenTry - // because MsgConnectionOpenTry cannot be created directly #[allow(deprecated)] - RawMsgConnectionOpenTry { - client_id: client_id.as_str().to_string(), + MsgConnectionOpenTry { + client_id_on_b: client_id, + client_state_of_b_on_a: client_state.into(), + counterparty: dummy_connection_counterparty(), + versions_on_a: vec![ConnVersion::default()], + proofs_height_on_a: dummy_proof_height(), + proof_conn_end_on_a: dummy_proof(), + proof_client_state_of_b_on_a: dummy_proof(), + proof_consensus_state_of_b_on_a: dummy_proof(), + consensus_height_of_b_on_a: consensus_height, + delay_period: Duration::from_secs(0), + signer: "test".to_string().into(), + proof_consensus_state_of_b: Some(dummy_proof()), previous_connection_id: ConnectionId::default().to_string(), - client_state: Some(client_state), - counterparty: Some(dummy_connection_counterparty().into()), - delay_period: 0, - counterparty_versions: vec![ConnVersion::default().into()], - proof_height: Some(dummy_proof_height().into()), - proof_init: dummy_proof().into(), - proof_client: dummy_proof().into(), - proof_consensus: dummy_proof().into(), - consensus_height: Some(consensus_height.into()), - signer: "test".to_string(), - host_consensus_state_proof: dummy_proof().into(), } - .try_into() - .expect("invalid message") } pub fn msg_connection_open_ack( diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index 25fe337ce2..2c80213eb7 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -23,7 +23,7 @@ mod tests { use borsh_ext::BorshSerializeExt; use itertools::Itertools; - use namada::ibc::core::Msg; + use namada::ibc::primitives::Msg; use namada::ledger::ibc::storage as ibc_storage; use namada::ledger::native_vp::ibc::{ get_dummy_header as tm_dummy_header, Error as IbcError, diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 66a3bb5817..9bfafd899a 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -369,7 +369,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.10.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "unicode-normalization", "zeroize", ] @@ -450,7 +450,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -594,9 +594,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -766,13 +766,13 @@ dependencies = [ "bincode", "bs58", "coins-core", - "digest 0.10.6", + "digest 0.10.7", "getrandom 0.2.10", "hmac 0.12.1", "k256", "lazy_static", "serde", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -789,7 +789,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -802,13 +802,13 @@ dependencies = [ "base64 0.21.0", "bech32 0.7.3", "bs58", - "digest 0.10.6", + "digest 0.10.7", "generic-array 0.14.7", "hex", "ripemd", "serde", "serde_derive", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -1206,9 +1206,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", @@ -1286,7 +1286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" dependencies = [ "der", - "digest 0.10.6", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -1346,7 +1346,7 @@ checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.6", + "digest 0.10.7", "ff", "generic-array 0.14.7", "group", @@ -1461,7 +1461,7 @@ checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes", "ctr", - "digest 0.10.6", + "digest 0.10.7", "hex", "hmac 0.12.1", "pbkdf2 0.11.0", @@ -1469,7 +1469,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", "uuid", @@ -1765,7 +1765,7 @@ dependencies = [ "ethers-core", "hex", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2211,7 +2211,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -2328,40 +2328,353 @@ dependencies = [ [[package]] name = "ibc" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "184eb22140cb4143bbcf7ddc8fdfeb9cc058ef73a6066f8ea78162e69d3565d1" +version = "0.48.0" +dependencies = [ + "ibc-apps", + "ibc-clients", + "ibc-core", + "ibc-core-host-cosmos", + "ibc-derive 0.4.0", + "ibc-primitives", +] + +[[package]] +name = "ibc-app-transfer" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer-types", + "ibc-core", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-transfer-types" +version = "0.48.0" dependencies = [ - "bytes", "derive_more", "displaydoc", - "ibc-derive", + "ibc-core", "ibc-proto", - "ics23", - "num-traits", - "parking_lot", "primitive-types", + "serde", + "uint", +] + +[[package]] +name = "ibc-apps" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer", +] + +[[package]] +name = "ibc-client-tendermint" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", + "serde", + "tendermint", + "tendermint-light-client-verifier", +] + +[[package]] +name = "ibc-client-tendermint-types" +version = "0.48.0" +dependencies = [ + "bytes", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", "prost 0.12.1", "serde", - "serde-json-wasm", - "serde_derive", - "sha2 0.10.6", - "subtle-encoding", "tendermint", "tendermint-light-client-verifier", "tendermint-proto", - "tendermint-testgen", - "time", - "tracing", - "typed-builder", - "uint", +] + +[[package]] +name = "ibc-clients" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint", +] + +[[package]] +name = "ibc-core" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-channel" +version = "0.48.0" +dependencies = [ + "ibc-core-channel-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-channel-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client" +version = "0.48.0" +dependencies = [ + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-client-context" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-derive 0.4.0", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-commitment-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-connection" +version = "0.48.0" +dependencies = [ + "ibc-core-client", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-connection-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-handler" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-handler-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-host-cosmos" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-app-transfer-types", + "ibc-client-tendermint", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "serde", +] + +[[package]] +name = "ibc-core-router" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-router-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", ] [[package]] name = "ibc-derive" -version = "0.3.0" +version = "0.4.0" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "ibc-derive" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92f1528535e9ca495badb76c143bdd4763c1c9d987f59d1f8b47963ba0c11674" +checksum = "df07bf5bc1e65e291506b7497633e07967e49b36a8db10cda77a8fd686eb4548" dependencies = [ "darling", "proc-macro2", @@ -2369,11 +2682,24 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "ibc-primitives" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-proto", + "prost 0.12.1", + "serde", + "tendermint", + "time", +] + [[package]] name = "ibc-proto" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63042806bb2f662ca1c68026231900cfe13361136ddfd0dd09bcb315056a22b8" +checksum = "93cbf4cbe9e5113cc7c70f3208a7029b2205c629502cbb2ae7ea0a09a97d3005" dependencies = [ "base64 0.21.0", "bytes", @@ -2385,6 +2711,25 @@ dependencies = [ "tendermint-proto", ] +[[package]] +name = "ibc-testkit" +version = "0.48.0" +dependencies = [ + "bytes", + "derive_more", + "displaydoc", + "ibc", + "ibc-proto", + "parking_lot", + "primitive-types", + "prost 0.12.1", + "subtle-encoding", + "tendermint", + "tendermint-testgen", + "tracing", + "typed-builder", +] + [[package]] name = "ics23" version = "0.11.0" @@ -2398,7 +2743,7 @@ dependencies = [ "prost 0.12.1", "ripemd", "serde", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", ] @@ -2636,7 +2981,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.6", + "sha2 0.10.8", "signature", ] @@ -2790,7 +3135,7 @@ dependencies = [ "num-traits", "rand 0.8.5", "rand_core 0.6.4", - "sha2 0.10.6", + "sha2 0.10.8", "subtle 2.4.1", "zcash_encoding", ] @@ -3012,8 +3357,9 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive", + "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ibc-proto", + "ibc-testkit", "ics23", "impl-num-traits", "index-set", @@ -3155,6 +3501,7 @@ dependencies = [ "copy_dir", "derivative", "hyper", + "ibc-testkit", "lazy_static", "namada", "namada_core", @@ -3649,7 +3996,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "password-hash", ] @@ -3659,7 +4006,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3668,7 +4015,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "hmac 0.12.1", ] @@ -3816,9 +4163,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -4337,7 +4684,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4582,7 +4929,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] @@ -4806,13 +5153,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4821,7 +5168,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] @@ -4849,7 +5196,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -5086,7 +5433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" dependencies = [ "bytes", - "digest 0.10.6", + "digest 0.10.7", "ed25519", "ed25519-consensus 2.1.0", "flex-error", @@ -5101,7 +5448,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.6", + "sha2 0.10.8", "signature", "subtle 2.4.1", "subtle-encoding", @@ -5468,11 +5815,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -5481,9 +5827,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -5492,9 +5838,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -5543,18 +5889,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c6a006a6d3d6a6f143fda41cf4d1ad35110080687628c9f2117bd3cc7924f3" +checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fa054ee5e2346187d631d2f1d1fd3b33676772d6d03a2d84e1c5213b31674ee" +checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" dependencies = [ "proc-macro2", "quote", From 3a631f189d9135bcde1ff0df8b686f85e1768f7c Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 24 Nov 2023 23:55:27 +0100 Subject: [PATCH 43/54] remove ibc-proto dependency --- Cargo.lock | 2 +- Cargo.toml | 1 - core/Cargo.toml | 1 - core/src/lib.rs | 2 +- sdk/src/lib.rs | 2 +- shared/src/lib.rs | 2 +- tests/Cargo.toml | 1 + tests/src/e2e/ibc_tests.rs | 8 ++------ wasm/Cargo.lock | 2 +- 9 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c0c77999b0..943aec97c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4269,7 +4269,6 @@ dependencies = [ "eyre", "ibc", "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ibc-proto", "ibc-testkit", "ics23", "impl-num-traits", @@ -4453,6 +4452,7 @@ dependencies = [ "fs_extra", "hyper", "ibc-testkit", + "ics23", "itertools 0.10.5", "lazy_static", "namada", diff --git a/Cargo.toml b/Cargo.toml index 8965f60323..527d69e1fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -84,7 +84,6 @@ git2 = "0.13.25" #ibc = {version = "0.48.0", default-features = false, features = ["serde"]} ibc = {path = "../../cosmos/ibc-rs/ibc", default-features = false, features = ["serde"]} ibc-derive = "0.4.0" -ibc-proto = {version = "0.38.0", default-features = false} #ibc-testkit = {version = "0.48.0", default-features = false} ibc-testkit = {path = "../../cosmos/ibc-rs/ibc-testkit", default-features = false} ics23 = "0.11.0" diff --git a/core/Cargo.toml b/core/Cargo.toml index 08961be424..f13473dda0 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -44,7 +44,6 @@ ethbridge-structs.workspace = true eyre.workspace = true ibc.workspace = true ibc-derive.workspace = true -ibc-proto.workspace = true ibc-testkit = {workspace = true, optional = true} ics23.workspace = true impl-num-traits = "0.1.2" diff --git a/core/src/lib.rs b/core/src/lib.rs index a4db54712b..cbc9588201 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -12,7 +12,7 @@ pub mod ledger; pub mod proto; pub mod types; -pub use {ibc, ibc_proto, tendermint, tendermint_proto}; +pub use {ibc, tendermint, tendermint_proto}; // A handy macro for tests #[cfg(test)] diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 5c31194990..9d1ae3c57f 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -1,6 +1,6 @@ extern crate alloc; -pub use namada_core::{ibc, ibc_proto, proto, tendermint, tendermint_proto}; +pub use namada_core::{ibc, proto, tendermint, tendermint_proto}; #[cfg(feature = "tendermint-rpc")] pub use tendermint_rpc; use tx::{TX_INIT_ACCOUNT_WASM, VP_VALIDATOR_WASM}; diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 0b0304ab3d..5937c345c9 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -6,7 +6,7 @@ #![deny(rustdoc::broken_intra_doc_links)] #![deny(rustdoc::private_intra_doc_links)] -pub use namada_core::{ibc, ibc_proto, tendermint, tendermint_proto}; +pub use namada_core::{ibc, tendermint, tendermint_proto}; #[cfg(feature = "tendermint-rpc")] pub use tendermint_rpc; pub use {bip39, namada_core as core, namada_proof_of_stake as proof_of_stake}; diff --git a/tests/Cargo.toml b/tests/Cargo.toml index bfc6df073b..f4ed0fbc34 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -35,6 +35,7 @@ copy_dir = "0.1.3" derivative.workspace = true hyper = {version = "0.14.20", features = ["full"]} ibc-testkit.workspace = true +ics23.workspace = true lazy_static.workspace = true num-traits.workspace = true prost.workspace = true diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index 7afc278e97..9d18bb54e5 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -1385,19 +1385,15 @@ fn query_value_with_proof( } fn convert_proof(tm_proof: TmProof) -> Result { - use namada::ibc_proto::ibc::core::commitment::v1::MerkleProof as RawMerkleProof; - use namada::ibc_proto::ics23::CommitmentProof; - let mut proofs = Vec::new(); - for op in &tm_proof.ops { - let mut parsed = CommitmentProof { proof: None }; + let mut parsed = ics23::CommitmentProof { proof: None }; prost::Message::merge(&mut parsed, op.data.as_slice()) .expect("merging CommitmentProof failed"); proofs.push(parsed); } - let merkle_proof = MerkleProof::from(RawMerkleProof { proofs }); + let merkle_proof = MerkleProof { proofs }; CommitmentProofBytes::try_from(merkle_proof).map_err(|e| { eyre!("Proof conversion to CommitmentProofBytes failed: {}", e) }) diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 9bfafd899a..e2e65e5fcb 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3358,7 +3358,6 @@ dependencies = [ "eyre", "ibc", "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ibc-proto", "ibc-testkit", "ics23", "impl-num-traits", @@ -3502,6 +3501,7 @@ dependencies = [ "derivative", "hyper", "ibc-testkit", + "ics23", "lazy_static", "namada", "namada_core", From cbd6694600da57fabdc627d370fdf8b6609ccf45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Mon, 27 Nov 2023 10:48:28 +0100 Subject: [PATCH 44/54] wasm: handle cache loading errors --- .../src/vm/wasm/compilation_cache/common.rs | 74 +++++++++++++------ 1 file changed, 51 insertions(+), 23 deletions(-) diff --git a/shared/src/vm/wasm/compilation_cache/common.rs b/shared/src/vm/wasm/compilation_cache/common.rs index f866188970..cd95100d25 100644 --- a/shared/src/vm/wasm/compilation_cache/common.rs +++ b/shared/src/vm/wasm/compilation_cache/common.rs @@ -156,16 +156,22 @@ impl Cache { return Ok(Some((module.clone(), store()))); } - let (module, store) = file_load_module(&self.dir, hash); - tracing::info!( - "{} found {} in file cache.", - N::name(), - hash.to_string() - ); - // Put into cache, ignore result if it's full - let _ = in_memory.put_with_weight(*hash, module.clone()); + if let Ok((module, store)) = + file_load_module(&self.dir, hash) + { + tracing::info!( + "{} found {} in file cache.", + N::name(), + hash.to_string() + ); + // Put into cache, ignore result if it's full + let _ = + in_memory.put_with_weight(*hash, module.clone()); - return Ok(Some((module, store))); + return Ok(Some((module, store))); + } else { + return Ok(None); + } } Some(Compilation::Compiling) => { drop(progress); @@ -183,11 +189,15 @@ impl Cache { let (module, store) = if module_file_exists(&self.dir, hash) { tracing::info!( - "Loading {} {} from file.", + "Trying to load {} {} from file.", N::name(), hash.to_string() ); - file_load_module(&self.dir, hash) + if let Ok(res) = file_load_module(&self.dir, hash) { + res + } else { + return Ok(None); + } } else { return Ok(None); }; @@ -246,13 +256,18 @@ impl Cache { return Ok(Some((module.clone(), store()))); } - let (module, store) = file_load_module(&self.dir, hash); - tracing::info!( - "{} found {} in file cache.", - N::name(), - hash.to_string() - ); - return Ok(Some((module, store))); + if let Ok((module, store)) = + file_load_module(&self.dir, hash) + { + tracing::info!( + "{} found {} in file cache.", + N::name(), + hash.to_string() + ); + return Ok(Some((module, store))); + } else { + return Ok(None); + } } Some(Compilation::Compiling) => { drop(progress); @@ -270,11 +285,15 @@ impl Cache { return if module_file_exists(&self.dir, hash) { tracing::info!( - "Loading {} {} from file.", + "Trying to load {} {} from file.", N::name(), hash.to_string() ); - Ok(Some(file_load_module(&self.dir, hash))) + if let Ok(res) = file_load_module(&self.dir, hash) { + return Ok(Some(res)); + } else { + return Ok(None); + } } else { Ok(None) }; @@ -478,13 +497,22 @@ fn file_write_module(dir: impl AsRef, module: &Module, hash: &Hash) { fs_cache.store(CacheHash::new(hash.0), module).unwrap(); } -fn file_load_module(dir: impl AsRef, hash: &Hash) -> (Module, Store) { +fn file_load_module( + dir: impl AsRef, + hash: &Hash, +) -> Result<(Module, Store), wasmer::DeserializeError> { use wasmer_cache::Cache; let fs_cache = fs_cache(dir, hash); let store = store(); let hash = CacheHash::new(hash.0); - let module = unsafe { fs_cache.load(&store, hash) }.unwrap(); - (module, store) + let module = unsafe { fs_cache.load(&store, hash) }; + if let Err(err) = module.as_ref() { + tracing::error!( + "Error loading cached wasm {}: {err}.", + hash.to_string() + ); + } + Ok((module?, store)) } fn fs_cache(dir: impl AsRef, hash: &Hash) -> FileSystemCache { From 85957df5ad5f08afd587417f230fc8c97b8660a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Mon, 27 Nov 2023 11:01:31 +0100 Subject: [PATCH 45/54] changelog: add #2215 --- .changelog/unreleased/improvements/2215-vp-less-permissive.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2215-vp-less-permissive.md diff --git a/.changelog/unreleased/improvements/2215-vp-less-permissive.md b/.changelog/unreleased/improvements/2215-vp-less-permissive.md new file mode 100644 index 0000000000..57faf65be7 --- /dev/null +++ b/.changelog/unreleased/improvements/2215-vp-less-permissive.md @@ -0,0 +1,2 @@ +- Handle errors on loading WASMs from file-system compilation cache. + ([\#2215](https://github.com/anoma/namada/pull/2215)) \ No newline at end of file From 3b6b982e9a62da955a8832201dd8e97dfdd0b691 Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 Nov 2023 15:00:44 +0100 Subject: [PATCH 46/54] revert chain ID format --- core/src/types/chain.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/core/src/types/chain.rs b/core/src/types/chain.rs index 2b22a13812..2c7c815a14 100644 --- a/core/src/types/chain.rs +++ b/core/src/types/chain.rs @@ -10,9 +10,8 @@ use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use thiserror::Error; -/// The length of the chain ID string. Tendermint's MAX_LENGTH is 50, and ibc-rs -/// would append a maximum of 21 characters. -pub const CHAIN_ID_LENGTH: usize = 29; +/// The length of the chain ID string +pub const CHAIN_ID_LENGTH: usize = 30; /// The maximum length of chain ID prefix pub const CHAIN_ID_PREFIX_MAX_LEN: usize = 19; /// Separator between chain ID prefix and the generated hash @@ -174,7 +173,7 @@ impl ProposalBytes { } /// Release default chain ID. Must be [`CHAIN_ID_LENGTH`] long. -pub const DEFAULT_CHAIN_ID: &str = "namada-internal.00000000000-0"; +pub const DEFAULT_CHAIN_ID: &str = "namada-internal.00000000000000"; /// Chain ID #[derive( @@ -208,10 +207,10 @@ impl ChainId { let mut hasher = Sha256::new(); hasher.update(genesis_bytes); // less `1` for chain ID prefix separator char - let width = CHAIN_ID_LENGTH - 3 - prefix.len(); + let width = CHAIN_ID_LENGTH - 1 - prefix.len(); // lowercase hex of the first `width` chars of the hash let hash = format!("{:.width$x}", hasher.finalize(), width = width,); - let raw = format!("{}{}{}-0", prefix, CHAIN_ID_PREFIX_SEP, hash); + let raw = format!("{}{}{}", prefix, CHAIN_ID_PREFIX_SEP, hash); ChainId(raw) } @@ -227,10 +226,10 @@ impl ChainId { let mut hasher = Sha256::new(); hasher.update(genesis_bytes); // less `1` for chain ID prefix separator char - let width = CHAIN_ID_LENGTH - 3 - prefix.len(); + let width = CHAIN_ID_LENGTH - 1 - prefix.len(); // lowercase hex of the first `width` chars of the hash let expected_hash = - format!("{:.width$x}-0", hasher.finalize(), width = width,); + format!("{:.width$x}", hasher.finalize(), width = width,); if hash != expected_hash { errors.push(ChainIdValidationError::InvalidHash( expected_hash, From 50bba4be65f4a313175e602bb416058b69e1282b Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 Nov 2023 17:01:55 +0100 Subject: [PATCH 47/54] fix bench --- benches/native_vps.rs | 19 +- benches/txs.rs | 19 +- core/src/ledger/ibc/mod.rs | 12 +- shared/src/ledger/native_vp/ibc/mod.rs | 16 +- tests/src/vm_host_env/ibc.rs | 2 +- tests/src/vm_host_env/mod.rs | 2 +- wasm_for_tests/wasm_source/Cargo.lock | 482 +++++++++++++++++++++---- 7 files changed, 446 insertions(+), 106 deletions(-) diff --git a/benches/native_vps.rs b/benches/native_vps.rs index fdaed5d1f9..413f307729 100644 --- a/benches/native_vps.rs +++ b/benches/native_vps.rs @@ -14,16 +14,15 @@ use namada::core::ledger::storage_api::{StorageRead, StorageWrite}; use namada::core::types::address::{self, Address}; use namada::core::types::token::{Amount, Transfer}; use namada::eth_bridge::storage::whitelist; -use namada::ibc::core::ics02_client::client_type::ClientType; -use namada::ibc::core::ics03_connection::connection::Counterparty; -use namada::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; -use namada::ibc::core::ics03_connection::version::Version; -use namada::ibc::core::ics04_channel::channel::Order; -use namada::ibc::core::ics04_channel::msgs::MsgChannelOpenInit; -use namada::ibc::core::ics04_channel::Version as ChannelVersion; -use namada::ibc::core::ics23_commitment::commitment::CommitmentPrefix; -use namada::ibc::core::ics24_host::identifier::{ - ClientId, ConnectionId, PortId, +use namada::ibc::core::channel::types::channel::Order; +use namada::ibc::core::channel::types::msgs::MsgChannelOpenInit; +use namada::ibc::core::channel::types::Version as ChannelVersion; +use namada::ibc::core::commitment_types::commitment::CommitmentPrefix; +use namada::ibc::core::connection::types::msgs::MsgConnectionOpenInit; +use namada::ibc::core::connection::types::version::Version; +use namada::ibc::core::connection::types::Counterparty; +use namada::ibc::core::host::types::identifiers::{ + ClientId, ClientType, ConnectionId, PortId, }; use namada::ledger::eth_bridge::read_native_erc20_address; use namada::ledger::gas::{TxGasMeter, VpGasMeter}; diff --git a/benches/txs.rs b/benches/txs.rs index 02d6c9c22d..c492ac90dc 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -13,16 +13,15 @@ use namada::core::types::key::{ use namada::core::types::token::Amount; use namada::core::types::transaction::account::{InitAccount, UpdateAccount}; use namada::core::types::transaction::pos::{InitValidator, MetaDataChange}; -use namada::ibc::core::ics02_client::client_type::ClientType; -use namada::ibc::core::ics03_connection::connection::Counterparty; -use namada::ibc::core::ics03_connection::msgs::conn_open_init::MsgConnectionOpenInit; -use namada::ibc::core::ics03_connection::version::Version; -use namada::ibc::core::ics04_channel::channel::Order; -use namada::ibc::core::ics04_channel::msgs::MsgChannelOpenInit; -use namada::ibc::core::ics04_channel::Version as ChannelVersion; -use namada::ibc::core::ics23_commitment::commitment::CommitmentPrefix; -use namada::ibc::core::ics24_host::identifier::{ - ClientId, ConnectionId, PortId, +use namada::ibc::core::channel::types::channel::Order; +use namada::ibc::core::channel::types::msgs::MsgChannelOpenInit; +use namada::ibc::core::channel::types::Version as ChannelVersion; +use namada::ibc::core::commitment_types::commitment::CommitmentPrefix; +use namada::ibc::core::connection::types::msgs::MsgConnectionOpenInit; +use namada::ibc::core::connection::types::version::Version; +use namada::ibc::core::connection::types::Counterparty; +use namada::ibc::core::host::types::identifiers::{ + ClientId, ClientType, ConnectionId, PortId, }; use namada::ledger::eth_bridge::read_native_erc20_address; use namada::ledger::storage_api::StorageRead; diff --git a/core/src/ledger/ibc/mod.rs b/core/src/ledger/ibc/mod.rs index 808ed013af..1b01017d3f 100644 --- a/core/src/ledger/ibc/mod.rs +++ b/core/src/ledger/ibc/mod.rs @@ -49,14 +49,10 @@ pub enum Error { DecodingData(prost::DecodeError), #[error("Decoding message error: {0}")] DecodingMessage(RouterError), - #[error("IBC execution error: {0}")] - Execution(ContextError), + #[error("IBC context error: {0}")] + Context(Box), #[error("IBC token transfer error: {0}")] TokenTransfer(TokenTransferError), - #[error("IBC validation error: {0}")] - Validation(ContextError), - #[error("IBC module doesn't exist")] - NoModule, #[error("Denom error: {0}")] Denom(String), #[error("Invalid chain ID: {0}")] @@ -119,7 +115,7 @@ where let envelope = MsgEnvelope::try_from(any_msg) .map_err(Error::DecodingMessage)?; execute(&mut self.ctx, &mut self.router, envelope.clone()) - .map_err(Error::Execution)?; + .map_err(|e| Error::Context(Box::new(e)))?; // For receiving the token to a shielded address self.handle_masp_tx(&envelope)?; // the current ibc-rs execution doesn't store the denom for the @@ -234,7 +230,7 @@ where let envelope = MsgEnvelope::try_from(any_msg) .map_err(Error::DecodingMessage)?; validate(&self.ctx, &self.router, envelope) - .map_err(Error::Validation) + .map_err(|e| Error::Context(Box::new(e))) } } } diff --git a/shared/src/ledger/native_vp/ibc/mod.rs b/shared/src/ledger/native_vp/ibc/mod.rs index cd0a1e5680..a4ca254537 100644 --- a/shared/src/ledger/native_vp/ibc/mod.rs +++ b/shared/src/ledger/native_vp/ibc/mod.rs @@ -41,8 +41,6 @@ pub enum Error { IbcAction(ActionError), #[error("State change error: {0}")] StateChange(String), - #[error("Denom error: {0}")] - Denom(String), #[error("IBC event error: {0}")] IbcEvent(String), } @@ -175,7 +173,7 @@ where pipeline_len * epoch_duration.min_duration.0; Ok(ValidationParams { chain_id: IbcChainId::from_str(&chain_id) - .map_err(|e| Error::IbcAction(ActionError::ChainId(e)))?, + .map_err(ActionError::ChainId)?, proof_specs: proof_specs.into(), unbonding_period: Duration::from_secs(unbonding_period_secs), upgrade_path: Vec::new(), @@ -186,24 +184,26 @@ where for key in keys_changed { if let Some((_, hash)) = is_ibc_denom_key(key) { match self.ctx.read_post::(key).map_err(|e| { - Error::Denom(format!( + ActionError::Denom(format!( "Getting the denom failed: Key {}, Error {}", key, e )) })? { Some(denom) => { if calc_hash(&denom) != hash { - return Err(Error::Denom(format!( + return Err(ActionError::Denom(format!( "The denom is invalid: Key {}, Denom {}", key, denom - ))); + )) + .into()); } } None => { - return Err(Error::Denom(format!( + return Err(ActionError::Denom(format!( "The corresponding denom wasn't stored: Key {}", key - ))); + )) + .into()); } } } diff --git a/tests/src/vm_host_env/ibc.rs b/tests/src/vm_host_env/ibc.rs index 5bc58a9775..fda711ad0d 100644 --- a/tests/src/vm_host_env/ibc.rs +++ b/tests/src/vm_host_env/ibc.rs @@ -466,7 +466,7 @@ pub fn msg_connection_open_try( #[allow(deprecated)] MsgConnectionOpenTry { client_id_on_b: client_id, - client_state_of_b_on_a: client_state.into(), + client_state_of_b_on_a: client_state, counterparty: dummy_connection_counterparty(), versions_on_a: vec![ConnVersion::default()], proofs_height_on_a: dummy_proof_height(), diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index 2c80213eb7..eed12a6112 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -1039,7 +1039,7 @@ mod tests { // VP should fail because the transfer channel cannot be closed assert!(matches!( result.expect_err("validation succeeded unexpectedly"), - IbcError::IbcAction(IbcActionError::Execution(_)), + IbcError::IbcAction(IbcActionError::Context(_)), )); } diff --git a/wasm_for_tests/wasm_source/Cargo.lock b/wasm_for_tests/wasm_source/Cargo.lock index 133935e7f0..5b56bae4fa 100644 --- a/wasm_for_tests/wasm_source/Cargo.lock +++ b/wasm_for_tests/wasm_source/Cargo.lock @@ -369,7 +369,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.10.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "unicode-normalization", "zeroize", ] @@ -450,7 +450,7 @@ dependencies = [ "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -594,9 +594,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" dependencies = [ "serde", ] @@ -766,13 +766,13 @@ dependencies = [ "bincode", "bs58", "coins-core", - "digest 0.10.6", + "digest 0.10.7", "getrandom 0.2.10", "hmac 0.12.1", "k256", "lazy_static", "serde", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -789,7 +789,7 @@ dependencies = [ "once_cell", "pbkdf2 0.12.1", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", ] @@ -802,13 +802,13 @@ dependencies = [ "base64 0.21.0", "bech32 0.7.3", "bs58", - "digest 0.10.6", + "digest 0.10.7", "generic-array 0.14.7", "hex", "ripemd", "serde", "serde_derive", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", ] @@ -1206,9 +1206,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", "const-oid", @@ -1286,7 +1286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0997c976637b606099b9985693efa3581e84e41f5c11ba5255f88711058ad428" dependencies = [ "der", - "digest 0.10.6", + "digest 0.10.7", "elliptic-curve", "rfc6979", "serdect", @@ -1346,7 +1346,7 @@ checksum = "968405c8fdc9b3bf4df0a6638858cc0b52462836ab6b1c87377785dd09cf1c0b" dependencies = [ "base16ct", "crypto-bigint", - "digest 0.10.6", + "digest 0.10.7", "ff", "generic-array 0.14.7", "group", @@ -1461,7 +1461,7 @@ checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" dependencies = [ "aes", "ctr", - "digest 0.10.6", + "digest 0.10.7", "hex", "hmac 0.12.1", "pbkdf2 0.11.0", @@ -1469,7 +1469,7 @@ dependencies = [ "scrypt", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", "thiserror", "uuid", @@ -1765,7 +1765,7 @@ dependencies = [ "ethers-core", "hex", "rand 0.8.5", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", "tracing", ] @@ -2211,7 +2211,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -2328,40 +2328,353 @@ dependencies = [ [[package]] name = "ibc" -version = "0.47.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "184eb22140cb4143bbcf7ddc8fdfeb9cc058ef73a6066f8ea78162e69d3565d1" +version = "0.48.0" +dependencies = [ + "ibc-apps", + "ibc-clients", + "ibc-core", + "ibc-core-host-cosmos", + "ibc-derive 0.4.0", + "ibc-primitives", +] + +[[package]] +name = "ibc-app-transfer" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer-types", + "ibc-core", + "serde-json-wasm", +] + +[[package]] +name = "ibc-app-transfer-types" +version = "0.48.0" dependencies = [ - "bytes", "derive_more", "displaydoc", - "ibc-derive", + "ibc-core", "ibc-proto", - "ics23", - "num-traits", - "parking_lot", "primitive-types", + "serde", + "uint", +] + +[[package]] +name = "ibc-apps" +version = "0.48.0" +dependencies = [ + "ibc-app-transfer", +] + +[[package]] +name = "ibc-client-tendermint" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", + "serde", + "tendermint", + "tendermint-light-client-verifier", +] + +[[package]] +name = "ibc-client-tendermint-types" +version = "0.48.0" +dependencies = [ + "bytes", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", "prost 0.12.1", "serde", - "serde-json-wasm", - "serde_derive", - "sha2 0.10.6", - "subtle-encoding", "tendermint", "tendermint-light-client-verifier", "tendermint-proto", - "tendermint-testgen", - "time", - "tracing", - "typed-builder", - "uint", +] + +[[package]] +name = "ibc-clients" +version = "0.48.0" +dependencies = [ + "ibc-client-tendermint", +] + +[[package]] +name = "ibc-core" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-channel" +version = "0.48.0" +dependencies = [ + "ibc-core-channel-types", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-channel-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client" +version = "0.48.0" +dependencies = [ + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-client-context" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-derive 0.4.0", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-client-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-commitment-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-connection" +version = "0.48.0" +dependencies = [ + "ibc-core-client", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-primitives", + "prost 0.12.1", +] + +[[package]] +name = "ibc-core-connection-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-handler" +version = "0.48.0" +dependencies = [ + "ibc-core-channel", + "ibc-core-client", + "ibc-core-commitment-types", + "ibc-core-connection", + "ibc-core-handler-types", + "ibc-core-host", + "ibc-core-router", + "ibc-primitives", +] + +[[package]] +name = "ibc-core-handler-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-host-cosmos" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-app-transfer-types", + "ibc-client-tendermint", + "ibc-core-client-context", + "ibc-core-client-types", + "ibc-core-commitment-types", + "ibc-core-connection-types", + "ibc-core-handler-types", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "prost 0.12.1", + "serde", + "sha2 0.10.8", + "subtle-encoding", + "tendermint", +] + +[[package]] +name = "ibc-core-host-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-primitives", + "serde", +] + +[[package]] +name = "ibc-core-router" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-channel-types", + "ibc-core-host-types", + "ibc-core-router-types", + "ibc-primitives", + "prost 0.12.1", + "subtle-encoding", +] + +[[package]] +name = "ibc-core-router-types" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-core-host-types", + "ibc-primitives", + "ibc-proto", + "ics23", + "prost 0.12.1", + "serde", + "subtle-encoding", + "tendermint", ] [[package]] name = "ibc-derive" -version = "0.3.0" +version = "0.4.0" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "ibc-derive" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92f1528535e9ca495badb76c143bdd4763c1c9d987f59d1f8b47963ba0c11674" +checksum = "df07bf5bc1e65e291506b7497633e07967e49b36a8db10cda77a8fd686eb4548" dependencies = [ "darling", "proc-macro2", @@ -2369,11 +2682,24 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "ibc-primitives" +version = "0.48.0" +dependencies = [ + "derive_more", + "displaydoc", + "ibc-proto", + "prost 0.12.1", + "serde", + "tendermint", + "time", +] + [[package]] name = "ibc-proto" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63042806bb2f662ca1c68026231900cfe13361136ddfd0dd09bcb315056a22b8" +checksum = "93cbf4cbe9e5113cc7c70f3208a7029b2205c629502cbb2ae7ea0a09a97d3005" dependencies = [ "base64 0.21.0", "bytes", @@ -2385,6 +2711,25 @@ dependencies = [ "tendermint-proto", ] +[[package]] +name = "ibc-testkit" +version = "0.48.0" +dependencies = [ + "bytes", + "derive_more", + "displaydoc", + "ibc", + "ibc-proto", + "parking_lot", + "primitive-types", + "prost 0.12.1", + "subtle-encoding", + "tendermint", + "tendermint-testgen", + "tracing", + "typed-builder", +] + [[package]] name = "ics23" version = "0.11.0" @@ -2398,7 +2743,7 @@ dependencies = [ "prost 0.12.1", "ripemd", "serde", - "sha2 0.10.6", + "sha2 0.10.8", "sha3", ] @@ -2636,7 +2981,7 @@ dependencies = [ "elliptic-curve", "once_cell", "serdect", - "sha2 0.10.6", + "sha2 0.10.8", "signature", ] @@ -2790,7 +3135,7 @@ dependencies = [ "num-traits", "rand 0.8.5", "rand_core 0.6.4", - "sha2 0.10.6", + "sha2 0.10.8", "subtle 2.4.1", "zcash_encoding", ] @@ -3012,8 +3357,8 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive", - "ibc-proto", + "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ibc-testkit", "ics23", "impl-num-traits", "index-set", @@ -3155,6 +3500,8 @@ dependencies = [ "copy_dir", "derivative", "hyper", + "ibc-testkit", + "ics23", "lazy_static", "namada", "namada_core", @@ -3642,7 +3989,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "password-hash", ] @@ -3652,7 +3999,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -3661,7 +4008,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ca0b5a68607598bf3bad68f32227a8164f6254833f84eafaac409cd6746c31" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "hmac 0.12.1", ] @@ -3809,9 +4156,9 @@ dependencies = [ [[package]] name = "primitive-types" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" +checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" dependencies = [ "fixed-hash", "impl-codec", @@ -4330,7 +4677,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4575,7 +4922,7 @@ dependencies = [ "hmac 0.12.1", "pbkdf2 0.11.0", "salsa20", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] @@ -4799,13 +5146,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", - "digest 0.10.6", + "digest 0.10.7", ] [[package]] @@ -4814,7 +5161,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "keccak", ] @@ -4842,7 +5189,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" dependencies = [ - "digest 0.10.6", + "digest 0.10.7", "rand_core 0.6.4", ] @@ -5079,7 +5426,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc2294fa667c8b548ee27a9ba59115472d0a09c2ba255771092a7f1dcf03a789" dependencies = [ "bytes", - "digest 0.10.6", + "digest 0.10.7", "ed25519", "ed25519-consensus 2.1.0", "flex-error", @@ -5094,7 +5441,7 @@ dependencies = [ "serde_bytes", "serde_json", "serde_repr", - "sha2 0.10.6", + "sha2 0.10.8", "signature", "subtle 2.4.1", "subtle-encoding", @@ -5461,11 +5808,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "log", "pin-project-lite", "tracing-attributes", @@ -5474,9 +5820,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -5485,9 +5831,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -5525,18 +5871,18 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typed-builder" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c6a006a6d3d6a6f143fda41cf4d1ad35110080687628c9f2117bd3cc7924f3" +checksum = "e47c0496149861b7c95198088cbf36645016b1a0734cf350c50e2a38e070f38a" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fa054ee5e2346187d631d2f1d1fd3b33676772d6d03a2d84e1c5213b31674ee" +checksum = "982ee4197351b5c9782847ef5ec1fdcaf50503fb19d68f9771adae314e72b492" dependencies = [ "proc-macro2", "quote", From 1898905ea60a59326440b142e515db753d95406a Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 Nov 2023 18:26:12 +0100 Subject: [PATCH 48/54] update ibc-rs to 0.48.1 --- Cargo.lock | 116 +++++++++++++++++--------- Cargo.toml | 6 +- wasm/Cargo.lock | 116 +++++++++++++++++--------- wasm_for_tests/wasm_source/Cargo.lock | 116 +++++++++++++++++--------- 4 files changed, 236 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 943aec97c1..6bfe6f5982 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2891,19 +2891,23 @@ dependencies = [ [[package]] name = "ibc" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "429b6aca6624a9364878e28c90311438c2621a8270942d80732b2651ac38ac74" dependencies = [ "ibc-apps", "ibc-clients", "ibc-core", "ibc-core-host-cosmos", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", ] [[package]] name = "ibc-app-transfer" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b177b343385d9654d99be4709b5ed1574d41f91dfa4044b2d26d688be4179d7c" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2912,7 +2916,9 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f92a3eda225e5c86e7bb6501c95986583ac541c4369d3c528349d81390f947" dependencies = [ "derive_more", "displaydoc", @@ -2925,14 +2931,18 @@ dependencies = [ [[package]] name = "ibc-apps" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4be40d55ed2dea9f2d05b902a3586f20850c723e4bdbfc4fb0ebe7a66ca5e40" dependencies = [ "ibc-app-transfer", ] [[package]] name = "ibc-client-tendermint" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119aa5873214228bf69bded3f20022b9ae1bc35b6841d295afcd73e53db05ccf" dependencies = [ "ibc-client-tendermint-types", "ibc-core-client", @@ -2948,7 +2958,9 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f21679016931b332b295a761e65cc122dc6fbfb98444148b681ad3aaa474665" dependencies = [ "bytes", "displaydoc", @@ -2966,14 +2978,18 @@ dependencies = [ [[package]] name = "ibc-clients" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c660323e93107a136aa3dbc412b7fa2eafd315c2fe71184096a43800f8ca5" dependencies = [ "ibc-client-tendermint", ] [[package]] name = "ibc-core" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "100d9d0aa67432c5078a8a1c818e3fc990a193be6d35ed0abeda5b340d16c1da" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2987,7 +3003,9 @@ dependencies = [ [[package]] name = "ibc-core-channel" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebaa37629ac029f914dfe552ab5dad01ddb240ec885ed0ae68221cbea4e9bfc" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -3002,7 +3020,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2ba72c56c411b1e0ce6dc3f5e1fa1de9e6c84891f425b7be8a9e1705964378" dependencies = [ "derive_more", "displaydoc", @@ -3021,7 +3041,9 @@ dependencies = [ [[package]] name = "ibc-core-client" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c4fac8e05201795073dee8c93d5afe9dfeac9aec2412b4a2b0c5f0d1e1d725" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -3034,7 +3056,9 @@ dependencies = [ [[package]] name = "ibc-core-client-context" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b82abd9489021730d59ab2d00e9438d3711e8e78ecba4d083b64f833301682b" dependencies = [ "derive_more", "displaydoc", @@ -3042,7 +3066,7 @@ dependencies = [ "ibc-core-commitment-types", "ibc-core-handler-types", "ibc-core-host-types", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", "prost 0.12.1", "subtle-encoding", @@ -3051,7 +3075,9 @@ dependencies = [ [[package]] name = "ibc-core-client-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafdbf6db5dab4c8ad610b6940e23b4f8abd0a6ac5e8e2801415a95defd4a583" dependencies = [ "derive_more", "displaydoc", @@ -3067,7 +3093,9 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4256b0216fc49024bac7e01c61b9bb055e31914ffe9ce6f468d7ce496a9357" dependencies = [ "derive_more", "displaydoc", @@ -3081,7 +3109,9 @@ dependencies = [ [[package]] name = "ibc-core-connection" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e237b70b9ba0177a4e59ac9048fffac2ac44c334703cc0ae403ad221450850" dependencies = [ "ibc-core-client", "ibc-core-connection-types", @@ -3093,7 +3123,9 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca841416fa29626423917099092f3698ae2735074cb3fe42936ddf6b2ccbf2f7" dependencies = [ "derive_more", "displaydoc", @@ -3110,7 +3142,9 @@ dependencies = [ [[package]] name = "ibc-core-handler" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47e5e5a006aa0fc87ec3f5fb1e0ef6dd5aeea5079fa927d799d526c44329987" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -3124,7 +3158,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3d59a8a5eb2069530c42783b4fef63472a89e0e9242334351df1bb58aaf542" dependencies = [ "derive_more", "displaydoc", @@ -3144,7 +3180,9 @@ dependencies = [ [[package]] name = "ibc-core-host" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aa63c895c0e5a75e42fe859b8fd4250c12bfa8b9c6b114f94c927ecfad38a03" dependencies = [ "derive_more", "displaydoc", @@ -3162,7 +3200,9 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a325862af6c20b0df3d27c072a2d802a7232dc1666214d738cdfbd9a9c99720" dependencies = [ "derive_more", "displaydoc", @@ -3185,7 +3225,9 @@ dependencies = [ [[package]] name = "ibc-core-host-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616955da310febbe93c0569a2feebd9f57cafed3eee5a56b0c3bb953a75f6089" dependencies = [ "derive_more", "displaydoc", @@ -3195,7 +3237,9 @@ dependencies = [ [[package]] name = "ibc-core-router" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31fe115da73e0616bdb44400fa6b11ca251648d070c4ff419d58e27804d30243" dependencies = [ "derive_more", "displaydoc", @@ -3209,7 +3253,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1fbb0bbbdeafa7ac989ba1693ed46d22e0e3eb0bdae478544e31157a4fdba6" dependencies = [ "derive_more", "displaydoc", @@ -3223,16 +3269,6 @@ dependencies = [ "tendermint", ] -[[package]] -name = "ibc-derive" -version = "0.4.0" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "ibc-derive" version = "0.4.0" @@ -3247,7 +3283,9 @@ dependencies = [ [[package]] name = "ibc-primitives" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5edea4685267fd68514c87e7aa3a62712340c4cff6903f088a9ab571428a08a" dependencies = [ "derive_more", "displaydoc", @@ -3276,7 +3314,9 @@ dependencies = [ [[package]] name = "ibc-testkit" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f550c91648f3db6474880e18cd2bd294096a99b30621aa01a9059b71e3612d98" dependencies = [ "bytes", "derive_more", @@ -4268,7 +4308,7 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ibc-derive", "ibc-testkit", "ics23", "impl-num-traits", diff --git a/Cargo.toml b/Cargo.toml index 527d69e1fa..be18088e90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,11 +81,9 @@ flate2 = "1.0.22" fs_extra = "1.2.0" futures = "0.3" git2 = "0.13.25" -#ibc = {version = "0.48.0", default-features = false, features = ["serde"]} -ibc = {path = "../../cosmos/ibc-rs/ibc", default-features = false, features = ["serde"]} +ibc = {version = "0.48.1", default-features = false, features = ["serde"]} ibc-derive = "0.4.0" -#ibc-testkit = {version = "0.48.0", default-features = false} -ibc-testkit = {path = "../../cosmos/ibc-rs/ibc-testkit", default-features = false} +ibc-testkit = {version = "0.48.1", default-features = false} ics23 = "0.11.0" index-set = {git = "https://github.com/heliaxdev/index-set", tag = "v0.8.0", features = ["serialize-borsh", "serialize-serde"]} itertools = "0.10.0" diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index e2e65e5fcb..0c6177bd22 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -2328,19 +2328,23 @@ dependencies = [ [[package]] name = "ibc" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "429b6aca6624a9364878e28c90311438c2621a8270942d80732b2651ac38ac74" dependencies = [ "ibc-apps", "ibc-clients", "ibc-core", "ibc-core-host-cosmos", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", ] [[package]] name = "ibc-app-transfer" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b177b343385d9654d99be4709b5ed1574d41f91dfa4044b2d26d688be4179d7c" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2349,7 +2353,9 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f92a3eda225e5c86e7bb6501c95986583ac541c4369d3c528349d81390f947" dependencies = [ "derive_more", "displaydoc", @@ -2362,14 +2368,18 @@ dependencies = [ [[package]] name = "ibc-apps" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4be40d55ed2dea9f2d05b902a3586f20850c723e4bdbfc4fb0ebe7a66ca5e40" dependencies = [ "ibc-app-transfer", ] [[package]] name = "ibc-client-tendermint" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119aa5873214228bf69bded3f20022b9ae1bc35b6841d295afcd73e53db05ccf" dependencies = [ "ibc-client-tendermint-types", "ibc-core-client", @@ -2385,7 +2395,9 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f21679016931b332b295a761e65cc122dc6fbfb98444148b681ad3aaa474665" dependencies = [ "bytes", "displaydoc", @@ -2403,14 +2415,18 @@ dependencies = [ [[package]] name = "ibc-clients" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c660323e93107a136aa3dbc412b7fa2eafd315c2fe71184096a43800f8ca5" dependencies = [ "ibc-client-tendermint", ] [[package]] name = "ibc-core" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "100d9d0aa67432c5078a8a1c818e3fc990a193be6d35ed0abeda5b340d16c1da" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2424,7 +2440,9 @@ dependencies = [ [[package]] name = "ibc-core-channel" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebaa37629ac029f914dfe552ab5dad01ddb240ec885ed0ae68221cbea4e9bfc" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2439,7 +2457,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2ba72c56c411b1e0ce6dc3f5e1fa1de9e6c84891f425b7be8a9e1705964378" dependencies = [ "derive_more", "displaydoc", @@ -2458,7 +2478,9 @@ dependencies = [ [[package]] name = "ibc-core-client" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c4fac8e05201795073dee8c93d5afe9dfeac9aec2412b4a2b0c5f0d1e1d725" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2471,7 +2493,9 @@ dependencies = [ [[package]] name = "ibc-core-client-context" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b82abd9489021730d59ab2d00e9438d3711e8e78ecba4d083b64f833301682b" dependencies = [ "derive_more", "displaydoc", @@ -2479,7 +2503,7 @@ dependencies = [ "ibc-core-commitment-types", "ibc-core-handler-types", "ibc-core-host-types", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", "prost 0.12.1", "subtle-encoding", @@ -2488,7 +2512,9 @@ dependencies = [ [[package]] name = "ibc-core-client-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafdbf6db5dab4c8ad610b6940e23b4f8abd0a6ac5e8e2801415a95defd4a583" dependencies = [ "derive_more", "displaydoc", @@ -2504,7 +2530,9 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4256b0216fc49024bac7e01c61b9bb055e31914ffe9ce6f468d7ce496a9357" dependencies = [ "derive_more", "displaydoc", @@ -2518,7 +2546,9 @@ dependencies = [ [[package]] name = "ibc-core-connection" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e237b70b9ba0177a4e59ac9048fffac2ac44c334703cc0ae403ad221450850" dependencies = [ "ibc-core-client", "ibc-core-connection-types", @@ -2530,7 +2560,9 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca841416fa29626423917099092f3698ae2735074cb3fe42936ddf6b2ccbf2f7" dependencies = [ "derive_more", "displaydoc", @@ -2547,7 +2579,9 @@ dependencies = [ [[package]] name = "ibc-core-handler" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47e5e5a006aa0fc87ec3f5fb1e0ef6dd5aeea5079fa927d799d526c44329987" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2561,7 +2595,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3d59a8a5eb2069530c42783b4fef63472a89e0e9242334351df1bb58aaf542" dependencies = [ "derive_more", "displaydoc", @@ -2581,7 +2617,9 @@ dependencies = [ [[package]] name = "ibc-core-host" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aa63c895c0e5a75e42fe859b8fd4250c12bfa8b9c6b114f94c927ecfad38a03" dependencies = [ "derive_more", "displaydoc", @@ -2599,7 +2637,9 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a325862af6c20b0df3d27c072a2d802a7232dc1666214d738cdfbd9a9c99720" dependencies = [ "derive_more", "displaydoc", @@ -2622,7 +2662,9 @@ dependencies = [ [[package]] name = "ibc-core-host-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616955da310febbe93c0569a2feebd9f57cafed3eee5a56b0c3bb953a75f6089" dependencies = [ "derive_more", "displaydoc", @@ -2632,7 +2674,9 @@ dependencies = [ [[package]] name = "ibc-core-router" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31fe115da73e0616bdb44400fa6b11ca251648d070c4ff419d58e27804d30243" dependencies = [ "derive_more", "displaydoc", @@ -2646,7 +2690,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1fbb0bbbdeafa7ac989ba1693ed46d22e0e3eb0bdae478544e31157a4fdba6" dependencies = [ "derive_more", "displaydoc", @@ -2660,16 +2706,6 @@ dependencies = [ "tendermint", ] -[[package]] -name = "ibc-derive" -version = "0.4.0" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "ibc-derive" version = "0.4.0" @@ -2684,7 +2720,9 @@ dependencies = [ [[package]] name = "ibc-primitives" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5edea4685267fd68514c87e7aa3a62712340c4cff6903f088a9ab571428a08a" dependencies = [ "derive_more", "displaydoc", @@ -2713,7 +2751,9 @@ dependencies = [ [[package]] name = "ibc-testkit" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f550c91648f3db6474880e18cd2bd294096a99b30621aa01a9059b71e3612d98" dependencies = [ "bytes", "derive_more", @@ -3357,7 +3397,7 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ibc-derive", "ibc-testkit", "ics23", "impl-num-traits", diff --git a/wasm_for_tests/wasm_source/Cargo.lock b/wasm_for_tests/wasm_source/Cargo.lock index 5b56bae4fa..7fe9190e24 100644 --- a/wasm_for_tests/wasm_source/Cargo.lock +++ b/wasm_for_tests/wasm_source/Cargo.lock @@ -2328,19 +2328,23 @@ dependencies = [ [[package]] name = "ibc" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "429b6aca6624a9364878e28c90311438c2621a8270942d80732b2651ac38ac74" dependencies = [ "ibc-apps", "ibc-clients", "ibc-core", "ibc-core-host-cosmos", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", ] [[package]] name = "ibc-app-transfer" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b177b343385d9654d99be4709b5ed1574d41f91dfa4044b2d26d688be4179d7c" dependencies = [ "ibc-app-transfer-types", "ibc-core", @@ -2349,7 +2353,9 @@ dependencies = [ [[package]] name = "ibc-app-transfer-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95f92a3eda225e5c86e7bb6501c95986583ac541c4369d3c528349d81390f947" dependencies = [ "derive_more", "displaydoc", @@ -2362,14 +2368,18 @@ dependencies = [ [[package]] name = "ibc-apps" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4be40d55ed2dea9f2d05b902a3586f20850c723e4bdbfc4fb0ebe7a66ca5e40" dependencies = [ "ibc-app-transfer", ] [[package]] name = "ibc-client-tendermint" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "119aa5873214228bf69bded3f20022b9ae1bc35b6841d295afcd73e53db05ccf" dependencies = [ "ibc-client-tendermint-types", "ibc-core-client", @@ -2385,7 +2395,9 @@ dependencies = [ [[package]] name = "ibc-client-tendermint-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f21679016931b332b295a761e65cc122dc6fbfb98444148b681ad3aaa474665" dependencies = [ "bytes", "displaydoc", @@ -2403,14 +2415,18 @@ dependencies = [ [[package]] name = "ibc-clients" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c660323e93107a136aa3dbc412b7fa2eafd315c2fe71184096a43800f8ca5" dependencies = [ "ibc-client-tendermint", ] [[package]] name = "ibc-core" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "100d9d0aa67432c5078a8a1c818e3fc990a193be6d35ed0abeda5b340d16c1da" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2424,7 +2440,9 @@ dependencies = [ [[package]] name = "ibc-core-channel" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebaa37629ac029f914dfe552ab5dad01ddb240ec885ed0ae68221cbea4e9bfc" dependencies = [ "ibc-core-channel-types", "ibc-core-client", @@ -2439,7 +2457,9 @@ dependencies = [ [[package]] name = "ibc-core-channel-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2ba72c56c411b1e0ce6dc3f5e1fa1de9e6c84891f425b7be8a9e1705964378" dependencies = [ "derive_more", "displaydoc", @@ -2458,7 +2478,9 @@ dependencies = [ [[package]] name = "ibc-core-client" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06c4fac8e05201795073dee8c93d5afe9dfeac9aec2412b4a2b0c5f0d1e1d725" dependencies = [ "ibc-core-client-context", "ibc-core-client-types", @@ -2471,7 +2493,9 @@ dependencies = [ [[package]] name = "ibc-core-client-context" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b82abd9489021730d59ab2d00e9438d3711e8e78ecba4d083b64f833301682b" dependencies = [ "derive_more", "displaydoc", @@ -2479,7 +2503,7 @@ dependencies = [ "ibc-core-commitment-types", "ibc-core-handler-types", "ibc-core-host-types", - "ibc-derive 0.4.0", + "ibc-derive", "ibc-primitives", "prost 0.12.1", "subtle-encoding", @@ -2488,7 +2512,9 @@ dependencies = [ [[package]] name = "ibc-core-client-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafdbf6db5dab4c8ad610b6940e23b4f8abd0a6ac5e8e2801415a95defd4a583" dependencies = [ "derive_more", "displaydoc", @@ -2504,7 +2530,9 @@ dependencies = [ [[package]] name = "ibc-core-commitment-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed4256b0216fc49024bac7e01c61b9bb055e31914ffe9ce6f468d7ce496a9357" dependencies = [ "derive_more", "displaydoc", @@ -2518,7 +2546,9 @@ dependencies = [ [[package]] name = "ibc-core-connection" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e237b70b9ba0177a4e59ac9048fffac2ac44c334703cc0ae403ad221450850" dependencies = [ "ibc-core-client", "ibc-core-connection-types", @@ -2530,7 +2560,9 @@ dependencies = [ [[package]] name = "ibc-core-connection-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca841416fa29626423917099092f3698ae2735074cb3fe42936ddf6b2ccbf2f7" dependencies = [ "derive_more", "displaydoc", @@ -2547,7 +2579,9 @@ dependencies = [ [[package]] name = "ibc-core-handler" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47e5e5a006aa0fc87ec3f5fb1e0ef6dd5aeea5079fa927d799d526c44329987" dependencies = [ "ibc-core-channel", "ibc-core-client", @@ -2561,7 +2595,9 @@ dependencies = [ [[package]] name = "ibc-core-handler-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3d59a8a5eb2069530c42783b4fef63472a89e0e9242334351df1bb58aaf542" dependencies = [ "derive_more", "displaydoc", @@ -2581,7 +2617,9 @@ dependencies = [ [[package]] name = "ibc-core-host" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aa63c895c0e5a75e42fe859b8fd4250c12bfa8b9c6b114f94c927ecfad38a03" dependencies = [ "derive_more", "displaydoc", @@ -2599,7 +2637,9 @@ dependencies = [ [[package]] name = "ibc-core-host-cosmos" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a325862af6c20b0df3d27c072a2d802a7232dc1666214d738cdfbd9a9c99720" dependencies = [ "derive_more", "displaydoc", @@ -2622,7 +2662,9 @@ dependencies = [ [[package]] name = "ibc-core-host-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616955da310febbe93c0569a2feebd9f57cafed3eee5a56b0c3bb953a75f6089" dependencies = [ "derive_more", "displaydoc", @@ -2632,7 +2674,9 @@ dependencies = [ [[package]] name = "ibc-core-router" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31fe115da73e0616bdb44400fa6b11ca251648d070c4ff419d58e27804d30243" dependencies = [ "derive_more", "displaydoc", @@ -2646,7 +2690,9 @@ dependencies = [ [[package]] name = "ibc-core-router-types" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1fbb0bbbdeafa7ac989ba1693ed46d22e0e3eb0bdae478544e31157a4fdba6" dependencies = [ "derive_more", "displaydoc", @@ -2660,16 +2706,6 @@ dependencies = [ "tendermint", ] -[[package]] -name = "ibc-derive" -version = "0.4.0" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "ibc-derive" version = "0.4.0" @@ -2684,7 +2720,9 @@ dependencies = [ [[package]] name = "ibc-primitives" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5edea4685267fd68514c87e7aa3a62712340c4cff6903f088a9ab571428a08a" dependencies = [ "derive_more", "displaydoc", @@ -2713,7 +2751,9 @@ dependencies = [ [[package]] name = "ibc-testkit" -version = "0.48.0" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f550c91648f3db6474880e18cd2bd294096a99b30621aa01a9059b71e3612d98" dependencies = [ "bytes", "derive_more", @@ -3357,7 +3397,7 @@ dependencies = [ "ethbridge-structs", "eyre", "ibc", - "ibc-derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ibc-derive", "ibc-testkit", "ics23", "impl-num-traits", From 10779f08199329f8720353361fa21afa302d9a0d Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 27 Nov 2023 20:49:11 +0100 Subject: [PATCH 49/54] add changelog --- .../unreleased/improvements/2153-revert-chain-id-format.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/2153-revert-chain-id-format.md diff --git a/.changelog/unreleased/improvements/2153-revert-chain-id-format.md b/.changelog/unreleased/improvements/2153-revert-chain-id-format.md new file mode 100644 index 0000000000..d3ca2c0a15 --- /dev/null +++ b/.changelog/unreleased/improvements/2153-revert-chain-id-format.md @@ -0,0 +1,2 @@ +- Revert the chain ID format by upgrading ibc-rs to 0.48.1 + ([\#2153](https://github.com/anoma/namada/issues/2153)) \ No newline at end of file From 5a3af44cd12a83c4f2fe1e0172ed0ab49d7b0c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 28 Nov 2023 07:56:49 +0100 Subject: [PATCH 50/54] fixup! Merge branch 'tomas/fst-epoch-start-height' (#1993) --- apps/src/lib/node/ledger/storage/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index 99cf99389d..3d4b86b215 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -492,8 +492,7 @@ mod tests { let hash = BlockHash::default(); let height = BlockHeight(1); storage.begin_block(hash, height)?; - // Epoch 1 - storage.block.epoch = storage.block.epoch.next(); + // Epoch 0 storage.block.pred_epochs.new_epoch(height); let mut batch = PersistentStorage::batch(); for (height, key, write_type) in blocks_write_type.clone() { @@ -592,7 +591,6 @@ mod tests { .write(&key, types::encode(&value)) .expect("write failed"); - storage.block.epoch = storage.block.epoch.next(); storage.block.pred_epochs.new_epoch(new_epoch_start); let batch = PersistentStorage::batch(); storage.commit_block(batch).expect("commit failed"); From a1116967836d81f6efab14e731293a9bdbc454c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 28 Nov 2023 08:33:08 +0100 Subject: [PATCH 51/54] fixup! Merge branch 'bat/feature/disable-oracle-gov' (#1764) --- apps/src/lib/node/ledger/shell/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 275a3b4eff..b849c2c5c1 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -1018,10 +1018,10 @@ where ); return; } - let config = EthereumOracleConfig::read(&self.wl_storage).expect( - "The oracle config must be present in storage, since the \ - bridge is enabled", - ); + let Some(config) = EthereumOracleConfig::read(&self.wl_storage) else { + tracing::info!("Not starting oracle as the Ethereum bridge config couldn't be found in storage"); + return; + }; let active = if !self.wl_storage.ethbridge_queries().is_bridge_active() { if !changed_keys From 1a321b28213177582740a9a814bb22558d10abee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Tue, 28 Nov 2023 08:38:20 +0100 Subject: [PATCH 52/54] fixup! Merge branch 'tiago/outdated-eth-nonces' (#2035) --- apps/src/lib/node/ledger/shell/mod.rs | 12 +++++++++--- apps/src/lib/node/ledger/shell/prepare_proposal.rs | 10 +++++----- apps/src/lib/node/ledger/shell/process_proposal.rs | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 7735ba4ee3..8e33bf87bb 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -2410,7 +2410,7 @@ mod shell_tests { // sent transfers to namada nonce to 5 .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); - let (protocol_key, _, _) = wallet::defaults::validator_keys(); + let (protocol_key, _) = wallet::defaults::validator_keys(); // only bad events { @@ -2432,7 +2432,10 @@ mod shell_tests { .sign(&protocol_key, shell.chain_id.clone()) .to_bytes(); let rsp = shell.mempool_validate(&tx, Default::default()); - assert!(rsp.code != 0, "Validation should have failed"); + assert!( + rsp.code != ErrorCodes::Ok.into(), + "Validation should have failed" + ); } // at least one good event @@ -2459,7 +2462,10 @@ mod shell_tests { .sign(&protocol_key, shell.chain_id.clone()) .to_bytes(); let rsp = shell.mempool_validate(&tx, Default::default()); - assert!(rsp.code == 0, "Validation should have passed"); + assert!( + rsp.code == ErrorCodes::Ok.into(), + "Validation should have passed" + ); } } diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index 8c3a4958ed..6a4ca7ab2d 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -1393,7 +1393,7 @@ mod test_prepare_proposal { // sent transfers to namada nonce to 5 .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); - let (protocol_key, _, _) = wallet::defaults::validator_keys(); + let (protocol_key, _) = wallet::defaults::validator_keys(); let validator_addr = wallet::defaults::validator_address(); // test an extension containing solely events with @@ -1418,12 +1418,12 @@ mod test_prepare_proposal { .sign(&protocol_key, shell.chain_id.clone()) .to_bytes(); let req = RequestPrepareProposal { - txs: vec![tx], + txs: vec![tx.into()], ..Default::default() }; let proposed_txs = shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| { - Tx::try_from(tx_bytes.as_slice()).expect("Test failed") + Tx::try_from(tx_bytes.as_ref()).expect("Test failed") }); // since no events with valid nonces are contained in the vote // extension, we drop it from the proposal @@ -1466,12 +1466,12 @@ mod test_prepare_proposal { .sign(&protocol_key, shell.chain_id.clone()) .to_bytes(); let req = RequestPrepareProposal { - txs: vec![tx], + txs: vec![tx.into()], ..Default::default() }; let proposed_txs = shell.prepare_proposal(req).txs.into_iter().map(|tx_bytes| { - Tx::try_from(tx_bytes.as_slice()).expect("Test failed") + Tx::try_from(tx_bytes.as_ref()).expect("Test failed") }); // find the event with the good nonce let mut ext = 'ext: { diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index 531e4edb24..7fad385eda 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -2136,7 +2136,7 @@ mod test_process_proposal { // sent transfers to namada nonce to 5 .transfers_to_namada = InnerEthEventsQueue::new_at(5.into()); - let (protocol_key, _, _) = wallet::defaults::validator_keys(); + let (protocol_key, _) = wallet::defaults::validator_keys(); // only bad events { From 7453f412637e0f2d0512df0ad6fe9e250b3a17a1 Mon Sep 17 00:00:00 2001 From: Murisi Tarusenga Date: Tue, 28 Nov 2023 19:23:01 +0200 Subject: [PATCH 53/54] Removed uses of lifetimes in the SDKs Namada trait and NamadaImpl implementation. --- apps/src/bin/namada-client/main.rs | 2 +- apps/src/bin/namada-relayer/main.rs | 2 +- apps/src/lib/bench_utils.rs | 33 ++- apps/src/lib/cli/client.rs | 206 +++++++++--------- apps/src/lib/cli/context.rs | 14 +- apps/src/lib/cli/relayer.rs | 42 ++-- apps/src/lib/client/rpc.rs | 131 +++++------ apps/src/lib/client/tx.rs | 86 ++++---- .../lib/node/ledger/shell/testing/client.rs | 4 +- benches/native_vps.rs | 4 +- benches/txs.rs | 13 +- sdk/src/args.rs | 88 ++++---- sdk/src/eth_bridge/bridge_pool.rs | 20 +- sdk/src/eth_bridge/validator_set.rs | 6 +- sdk/src/lib.rs | 82 ++++--- sdk/src/masp.rs | 12 +- sdk/src/rpc.rs | 22 +- sdk/src/signing.rs | 42 ++-- sdk/src/tx.rs | 156 ++++++------- 19 files changed, 476 insertions(+), 489 deletions(-) diff --git a/apps/src/bin/namada-client/main.rs b/apps/src/bin/namada-client/main.rs index 770dcf5367..9fdea9c51d 100644 --- a/apps/src/bin/namada-client/main.rs +++ b/apps/src/bin/namada-client/main.rs @@ -16,7 +16,7 @@ async fn main() -> Result<()> { CliApi::handle_client_command::( None, cli::namada_client_cli()?, - &CliIo, + CliIo, ) .await } diff --git a/apps/src/bin/namada-relayer/main.rs b/apps/src/bin/namada-relayer/main.rs index f9d98a2a4e..1eb2679e28 100644 --- a/apps/src/bin/namada-relayer/main.rs +++ b/apps/src/bin/namada-relayer/main.rs @@ -14,5 +14,5 @@ async fn main() -> Result<()> { let cmd = cli::namada_relayer_cli()?; // run the CLI - CliApi::handle_relayer_command::(None, cmd, &CliIo).await + CliApi::handle_relayer_command::(None, cmd, CliIo).await } diff --git a/apps/src/lib/bench_utils.rs b/apps/src/lib/bench_utils.rs index 551bf49abd..59c6c5cbdb 100644 --- a/apps/src/lib/bench_utils.rs +++ b/apps/src/lib/bench_utils.rs @@ -93,7 +93,7 @@ pub use namada_sdk::tx::{ TX_WITHDRAW_WASM, VP_USER_WASM, VP_VALIDATOR_WASM, }; use namada_sdk::wallet::Wallet; -use namada_sdk::NamadaImpl; +use namada_sdk::{Namada, NamadaImpl}; use namada_test_utils::tx_data::TxWriteData; use rand_core::OsRng; use sha2::{Digest, Sha256}; @@ -819,11 +819,11 @@ impl Default for BenchShieldedCtx { impl BenchShieldedCtx { pub fn generate_masp_tx( - &mut self, + mut self, amount: Amount, source: TransferSource, target: TransferTarget, - ) -> Tx { + ) -> (Self, Tx) { let denominated_amount = DenominatedAmount { amount, denom: 0.into(), @@ -840,12 +840,13 @@ impl BenchShieldedCtx { &[], )) .unwrap(); + let native_token = self.shell.wl_storage.storage.native_token.clone(); let namada = NamadaImpl::native_new( - &self.shell, - &mut self.wallet, - &mut self.shielded, - &StdIo, - self.shell.wl_storage.storage.native_token.clone(), + self.shell, + self.wallet, + self.shielded, + StdIo, + native_token, ); let shielded = async_runtime .block_on( @@ -877,7 +878,7 @@ impl BenchShieldedCtx { ) }); - self.shell.generate_tx( + let tx = namada.client().generate_tx( TX_TRANSFER_WASM, Transfer { source: source.effective_address(), @@ -890,6 +891,18 @@ impl BenchShieldedCtx { shielded, None, vec![&defaults::albert_keypair()], - ) + ); + let NamadaImpl { + client, + wallet, + shielded, + .. + } = namada; + let ctx = Self { + shielded: shielded.into_inner(), + shell: client, + wallet: wallet.into_inner(), + }; + (ctx, tx) } } diff --git a/apps/src/lib/cli/client.rs b/apps/src/lib/cli/client.rs index d4f81483fb..45a58d8132 100644 --- a/apps/src/lib/cli/client.rs +++ b/apps/src/lib/cli/client.rs @@ -12,7 +12,7 @@ impl CliApi { pub async fn handle_client_command( client: Option, cmd: cli::NamadaClient, - io: &IO, + io: IO, ) -> Result<()> where C: CliClient, @@ -29,9 +29,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); let dry_run = args.tx.dry_run || args.tx.dry_run_wrapper; tx::submit_custom(&namada, args).await?; @@ -42,7 +42,7 @@ impl CliApi { .save() .unwrap_or_else(|err| eprintln!("{}", err)); } else { - io.println( + namada.io().println( "Transaction dry run. No addresses have been \ saved.", ) @@ -54,9 +54,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_transfer(&namada, args).await?; } Sub::TxIbcTransfer(TxIbcTransfer(mut args)) => { @@ -65,9 +65,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_ibc_transfer(&namada, args).await?; } Sub::TxUpdateAccount(TxUpdateAccount(mut args)) => { @@ -76,9 +76,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_update_account(&namada, args).await?; } Sub::TxInitAccount(TxInitAccount(mut args)) => { @@ -87,9 +87,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); let dry_run = args.tx.dry_run || args.tx.dry_run_wrapper; tx::submit_init_account(&namada, args).await?; @@ -100,7 +100,7 @@ impl CliApi { .save() .unwrap_or_else(|err| eprintln!("{}", err)); } else { - io.println( + namada.io().println( "Transaction dry run. No addresses have been \ saved.", ) @@ -112,18 +112,18 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); let cli::context::ChainContext { - mut wallet, + wallet, mut config, - mut shielded, + shielded, native_token, } = ctx.take_chain_or_exit(); let namada = NamadaImpl::native_new( - &client, - &mut wallet, - &mut shielded, + client, + wallet, + shielded, io, native_token, ); @@ -136,9 +136,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_init_proposal(&namada, args).await?; } Sub::TxVoteProposal(TxVoteProposal(mut args)) => { @@ -147,9 +147,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_vote_proposal(&namada, args).await?; } Sub::TxRevealPk(TxRevealPk(mut args)) => { @@ -158,9 +158,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_reveal_pk(&namada, args).await?; } Sub::Bond(Bond(mut args)) => { @@ -169,9 +169,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_bond(&namada, args).await?; } Sub::Unbond(Unbond(mut args)) => { @@ -180,9 +180,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_unbond(&namada, args).await?; } Sub::Withdraw(Withdraw(mut args)) => { @@ -191,9 +191,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_withdraw(&namada, args).await?; } Sub::ClaimRewards(ClaimRewards(mut args)) => { @@ -202,9 +202,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_claim_rewards(&namada, args).await?; } Sub::Redelegate(Redelegate(mut args)) => { @@ -213,9 +213,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_redelegate(&namada, args).await?; } Sub::TxCommissionRateChange(TxCommissionRateChange( @@ -226,9 +226,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_validator_commission_change(&namada, args) .await?; } @@ -240,18 +240,18 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); let cli::context::ChainContext { - mut wallet, + wallet, mut config, - mut shielded, + shielded, native_token, } = ctx.take_chain_or_exit(); let namada = NamadaImpl::native_new( - &client, - &mut wallet, - &mut shielded, + client, + wallet, + shielded, io, native_token, ); @@ -268,9 +268,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_validator_metadata_change(&namada, args) .await?; } @@ -282,9 +282,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_bridge_pool_tx(&namada, args).await?; } Sub::TxUnjailValidator(TxUnjailValidator(mut args)) => { @@ -293,9 +293,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_unjail_validator(&namada, args).await?; } Sub::TxDeactivateValidator(TxDeactivateValidator( @@ -306,9 +306,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_deactivate_validator(&namada, args).await?; } Sub::TxReactivateValidator(TxReactivateValidator( @@ -319,9 +319,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_reactivate_validator(&namada, args).await?; } Sub::TxUpdateStewardCommission( @@ -332,9 +332,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_update_steward_commission(&namada, args) .await?; } @@ -344,9 +344,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::submit_resign_steward(&namada, args).await?; } // Ledger queries @@ -354,8 +354,8 @@ impl CliApi { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut args.ledger_address) }); - client.wait_until_node_is_synced(io).await?; - let namada = ctx.to_sdk(&client, io); + client.wait_until_node_is_synced(&io).await?; + let namada = ctx.to_sdk(client, io); rpc::query_and_print_epoch(&namada).await; } Sub::QueryValidatorState(QueryValidatorState(mut args)) => { @@ -364,9 +364,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_and_print_validator_state(&namada, args) .await; } @@ -376,9 +376,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_transfers(&namada, args).await; } Sub::QueryConversions(QueryConversions(mut args)) => { @@ -387,17 +387,17 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_conversions(&namada, args).await; } Sub::QueryBlock(QueryBlock(mut args)) => { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut args.ledger_address) }); - client.wait_until_node_is_synced(io).await?; - let namada = ctx.to_sdk(&client, io); + client.wait_until_node_is_synced(&io).await?; + let namada = ctx.to_sdk(client, io); rpc::query_block(&namada).await; } Sub::QueryBalance(QueryBalance(mut args)) => { @@ -406,9 +406,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_balance(&namada, args).await; } Sub::QueryBonds(QueryBonds(mut args)) => { @@ -417,9 +417,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_bonds(&namada, args) .await .expect("expected successful query of bonds"); @@ -430,9 +430,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_bonded_stake(&namada, args).await; } Sub::QueryCommissionRate(QueryCommissionRate(mut args)) => { @@ -441,9 +441,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_and_print_commission_rate(&namada, args) .await; } @@ -453,9 +453,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_and_print_metadata(&namada, args).await; } Sub::QuerySlashes(QuerySlashes(mut args)) => { @@ -464,9 +464,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_slashes(&namada, args).await; } Sub::QueryDelegations(QueryDelegations(mut args)) => { @@ -475,9 +475,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_delegations(&namada, args).await; } Sub::QueryFindValidator(QueryFindValidator(mut args)) => { @@ -486,9 +486,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_find_validator(&namada, args).await; } Sub::QueryResult(QueryResult(mut args)) => { @@ -497,9 +497,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_result(&namada, args).await; } Sub::QueryRawBytes(QueryRawBytes(mut args)) => { @@ -508,9 +508,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_raw_bytes(&namada, args).await; } Sub::QueryProposal(QueryProposal(mut args)) => { @@ -519,9 +519,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_proposal(&namada, args).await; } Sub::QueryProposalResult(QueryProposalResult(mut args)) => { @@ -530,9 +530,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_proposal_result(&namada, args).await; } Sub::QueryProtocolParameters(QueryProtocolParameters( @@ -543,9 +543,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_protocol_parameters(&namada, args).await; } Sub::QueryPgf(QueryPgf(mut args)) => { @@ -554,9 +554,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_pgf(&namada, args).await; } Sub::QueryAccount(QueryAccount(mut args)) => { @@ -565,9 +565,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::query_account(&namada, args).await; } Sub::SignTx(SignTx(mut args)) => { @@ -576,9 +576,9 @@ impl CliApi { &mut args.tx.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::sign_tx(&namada, args).await?; } Sub::GenIbcShieldedTransafer(GenIbcShieldedTransafer( @@ -589,9 +589,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); tx::gen_ibc_shielded_transfer(&namada, args).await?; } } @@ -625,9 +625,9 @@ impl CliApi { let mut ledger_address = args.ledger_address.clone(); let client = C::from_tendermint_address(&mut ledger_address); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); rpc::epoch_sleep(&namada, args).await; } Utils::ValidateGenesisTemplates(ValidateGenesisTemplates( diff --git a/apps/src/lib/cli/context.rs b/apps/src/lib/cli/context.rs index 51c8ba4eac..92a1d2eaa1 100644 --- a/apps/src/lib/cli/context.rs +++ b/apps/src/lib/cli/context.rs @@ -165,22 +165,18 @@ impl Context { } /// Make an implementation of Namada from this object and parameters. - pub fn to_sdk<'a, C, IO>( - &'a mut self, - client: &'a C, - io: &'a IO, - ) -> impl Namada + pub fn to_sdk(self, client: C, io: IO) -> impl Namada where C: namada::ledger::queries::Client + Sync, IO: Io, { - let chain_ctx = self.borrow_mut_chain_or_exit(); + let chain_ctx = self.take_chain_or_exit(); NamadaImpl::native_new( client, - &mut chain_ctx.wallet, - &mut chain_ctx.shielded, + chain_ctx.wallet, + chain_ctx.shielded, io, - chain_ctx.native_token.clone(), + chain_ctx.native_token, ) } } diff --git a/apps/src/lib/cli/relayer.rs b/apps/src/lib/cli/relayer.rs index 1dee9b784e..7dc360db4f 100644 --- a/apps/src/lib/cli/relayer.rs +++ b/apps/src/lib/cli/relayer.rs @@ -12,7 +12,7 @@ impl CliApi { pub async fn handle_relayer_command( client: Option, cmd: cli::NamadaRelayer, - io: &impl Io, + io: impl Io, ) -> Result<()> where C: CliClient, @@ -29,9 +29,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk(&mut ctx); - let namada = ctx.to_sdk(&client, io); + let namada = ctx.to_sdk(client, io); bridge_pool::recommend_batch(&namada, args).await?; } } @@ -45,9 +45,9 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk_ctxless(); - bridge_pool::construct_proof(&client, io, args).await?; + bridge_pool::construct_proof(&client, &io, args).await?; } EthBridgePoolWithoutCtx::RelayProof(RelayProof(mut args)) => { let client = client.unwrap_or_else(|| { @@ -55,12 +55,12 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let eth_client = get_eth_rpc_client(&args.eth_rpc_endpoint).await; let args = args.to_sdk_ctxless(); bridge_pool::relay_bridge_pool_proof( - eth_client, &client, io, args, + eth_client, &client, &io, args, ) .await?; } @@ -70,8 +70,8 @@ impl CliApi { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut query.ledger_address) }); - client.wait_until_node_is_synced(io).await?; - bridge_pool::query_bridge_pool(&client, io).await?; + client.wait_until_node_is_synced(&io).await?; + bridge_pool::query_bridge_pool(&client, &io).await?; } EthBridgePoolWithoutCtx::QuerySigned( QuerySignedBridgePool(mut query), @@ -79,8 +79,8 @@ impl CliApi { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut query.ledger_address) }); - client.wait_until_node_is_synced(io).await?; - bridge_pool::query_signed_bridge_pool(&client, io).await?; + client.wait_until_node_is_synced(&io).await?; + bridge_pool::query_signed_bridge_pool(&client, &io).await?; } EthBridgePoolWithoutCtx::QueryRelays(QueryRelayProgress( mut query, @@ -88,8 +88,8 @@ impl CliApi { let client = client.unwrap_or_else(|| { C::from_tendermint_address(&mut query.ledger_address) }); - client.wait_until_node_is_synced(io).await?; - bridge_pool::query_relay_progress(&client, io).await?; + client.wait_until_node_is_synced(&io).await?; + bridge_pool::query_relay_progress(&client, &io).await?; } }, cli::NamadaRelayer::ValidatorSet(sub) => match sub { @@ -101,10 +101,10 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk_ctxless(); validator_set::query_bridge_validator_set( - &client, io, args, + &client, &io, args, ) .await?; } @@ -116,10 +116,10 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk_ctxless(); validator_set::query_governnace_validator_set( - &client, io, args, + &client, &io, args, ) .await?; } @@ -131,10 +131,10 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let args = args.to_sdk_ctxless(); validator_set::query_validator_set_update_proof( - &client, io, args, + &client, &io, args, ) .await?; } @@ -146,12 +146,12 @@ impl CliApi { &mut args.query.ledger_address, ) }); - client.wait_until_node_is_synced(io).await?; + client.wait_until_node_is_synced(&io).await?; let eth_client = get_eth_rpc_client(&args.eth_rpc_endpoint).await; let args = args.to_sdk_ctxless(); validator_set::relay_validator_set_update( - eth_client, &client, io, args, + eth_client, &client, &io, args, ) .await?; } diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index f696a0602b..d0e97bc234 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -65,8 +65,8 @@ use crate::facade::tendermint_rpc::error::Error as TError; /// /// If a response is not delivered until `deadline`, we exit the cli with an /// error. -pub async fn query_tx_status<'a>( - namada: &impl Namada<'a>, +pub async fn query_tx_status( + namada: &impl Namada, status: namada_sdk::rpc::TxEventQuery<'_>, deadline: Instant, ) -> Event { @@ -76,14 +76,14 @@ pub async fn query_tx_status<'a>( } /// Query and print the epoch of the last committed block -pub async fn query_and_print_epoch<'a>(context: &impl Namada<'a>) -> Epoch { +pub async fn query_and_print_epoch(context: &impl Namada) -> Epoch { let epoch = rpc::query_epoch(context.client()).await.unwrap(); display_line!(context.io(), "Last committed epoch: {}", epoch); epoch } /// Query the last committed block -pub async fn query_block<'a>(context: &impl Namada<'a>) { +pub async fn query_block(context: &impl Namada) { let block = namada_sdk::rpc::query_block(context.client()) .await .unwrap(); @@ -114,8 +114,8 @@ pub async fn query_results( } /// Query the specified accepted transfers from the ledger -pub async fn query_transfers<'a>( - context: &impl Namada<'a>, +pub async fn query_transfers( + context: &impl Namada, args: args::QueryTransfers, ) { let query_token = args.token; @@ -250,7 +250,7 @@ pub async fn query_transfers<'a>( } /// Query the raw bytes of given storage key -pub async fn query_raw_bytes<'a, N: Namada<'a>>( +pub async fn query_raw_bytes( context: &N, args: args::QueryRawBytes, ) { @@ -281,10 +281,7 @@ pub async fn query_raw_bytes<'a, N: Namada<'a>>( } /// Query token balance(s) -pub async fn query_balance<'a>( - context: &impl Namada<'a>, - args: args::QueryBalance, -) { +pub async fn query_balance(context: &impl Namada, args: args::QueryBalance) { // Query the balances of shielded or transparent account types depending on // the CLI arguments match &args.owner { @@ -309,8 +306,8 @@ pub async fn query_balance<'a>( } /// Query token balance(s) -pub async fn query_transparent_balance<'a>( - context: &impl Namada<'a>, +pub async fn query_transparent_balance( + context: &impl Namada, args: args::QueryBalance, ) { let prefix = Key::from( @@ -386,8 +383,8 @@ pub async fn query_transparent_balance<'a>( } /// Query the token pinned balance(s) -pub async fn query_pinned_balance<'a>( - context: &impl Namada<'a>, +pub async fn query_pinned_balance( + context: &impl Namada, args: args::QueryBalance, ) { // Map addresses to token names @@ -549,8 +546,8 @@ pub async fn query_pinned_balance<'a>( } } -async fn print_balances<'a>( - context: &impl Namada<'a>, +async fn print_balances( + context: &impl Namada, balances: impl Iterator, token: Option<&Address>, target: Option<&Address>, @@ -629,8 +626,8 @@ async fn print_balances<'a>( } } -async fn lookup_token_alias<'a>( - context: &impl Namada<'a>, +async fn lookup_token_alias( + context: &impl Namada, token: &Address, owner: &Address, ) -> String { @@ -649,8 +646,8 @@ async fn lookup_token_alias<'a>( } /// Returns pairs of token alias and token address -async fn query_tokens<'a>( - context: &impl Namada<'a>, +async fn query_tokens( + context: &impl Namada, base_token: Option<&Address>, owner: Option<&Address>, ) -> BTreeMap { @@ -708,8 +705,8 @@ async fn query_tokens<'a>( tokens } -async fn get_ibc_denom_alias<'a>( - context: &impl Namada<'a>, +async fn get_ibc_denom_alias( + context: &impl Namada, ibc_denom: impl AsRef, ) -> String { let wallet = context.wallet().await; @@ -729,10 +726,7 @@ async fn get_ibc_denom_alias<'a>( } /// Query Proposals -pub async fn query_proposal<'a>( - context: &impl Namada<'a>, - args: args::QueryProposal, -) { +pub async fn query_proposal(context: &impl Namada, args: args::QueryProposal) { let current_epoch = query_and_print_epoch(context).await; if let Some(id) = args.proposal_id { @@ -781,8 +775,8 @@ pub async fn query_proposal_by_id( } /// Query token shielded balance(s) -pub async fn query_shielded_balance<'a>( - context: &impl Namada<'a>, +pub async fn query_shielded_balance( + context: &impl Namada, args: args::QueryBalance, ) { // Used to control whether balances for all keys or a specific key are @@ -1050,8 +1044,8 @@ pub async fn query_shielded_balance<'a>( } } -pub async fn print_decoded_balance<'a>( - context: &impl Namada<'a>, +pub async fn print_decoded_balance( + context: &impl Namada, decoded_balance: MaspAmount, epoch: Epoch, ) { @@ -1072,8 +1066,8 @@ pub async fn print_decoded_balance<'a>( } } -pub async fn print_decoded_balance_with_epoch<'a>( - context: &impl Namada<'a>, +pub async fn print_decoded_balance_with_epoch( + context: &impl Namada, decoded_balance: MaspAmount, ) { let tokens = context @@ -1110,8 +1104,8 @@ pub async fn get_token_balance( .unwrap() } -pub async fn query_proposal_result<'a>( - context: &impl Namada<'a>, +pub async fn query_proposal_result( + context: &impl Namada, args: args::QueryProposalResult, ) { if args.proposal_id.is_some() { @@ -1250,10 +1244,7 @@ pub async fn query_proposal_result<'a>( } } -pub async fn query_account<'a>( - context: &impl Namada<'a>, - args: args::QueryAccount, -) { +pub async fn query_account(context: &impl Namada, args: args::QueryAccount) { let account = rpc::get_account_info(context.client(), &args.owner) .await .unwrap(); @@ -1269,7 +1260,7 @@ pub async fn query_account<'a>( } } -pub async fn query_pgf<'a>(context: &impl Namada<'a>, _args: args::QueryPgf) { +pub async fn query_pgf(context: &impl Namada, _args: args::QueryPgf) { let stewards = query_pgf_stewards(context.client()).await; let fundings = query_pgf_fundings(context.client()).await; @@ -1320,8 +1311,8 @@ pub async fn query_pgf<'a>(context: &impl Namada<'a>, _args: args::QueryPgf) { } } -pub async fn query_protocol_parameters<'a>( - context: &impl Namada<'a>, +pub async fn query_protocol_parameters( + context: &impl Namada, _args: args::QueryProtocolParameters, ) { let governance_parameters = @@ -1578,8 +1569,8 @@ pub async fn query_pgf_parameters( unwrap_client_response::(RPC.vp().pgf().parameters(client).await) } -pub async fn query_and_print_unbonds<'a>( - context: &impl Namada<'a>, +pub async fn query_and_print_unbonds( + context: &impl Namada, source: &Address, validator: &Address, ) { @@ -1634,8 +1625,8 @@ pub async fn query_withdrawable_tokens< } /// Query PoS bond(s) and unbond(s) -pub async fn query_bonds<'a>( - context: &impl Namada<'a>, +pub async fn query_bonds( + context: &impl Namada, args: args::QueryBonds, ) -> std::io::Result<()> { let epoch = query_and_print_epoch(context).await; @@ -1758,7 +1749,7 @@ pub async fn query_bonds<'a>( } /// Query PoS bonded stake -pub async fn query_bonded_stake<'a, N: Namada<'a>>( +pub async fn query_bonded_stake( context: &N, args: args::QueryBondedStake, ) { @@ -1896,8 +1887,8 @@ pub async fn query_validator_state< } /// Query a validator's state information -pub async fn query_and_print_validator_state<'a>( - context: &impl Namada<'a>, +pub async fn query_and_print_validator_state( + context: &impl Namada, args: args::QueryValidatorState, ) { let validator = args.validator; @@ -1941,8 +1932,8 @@ pub async fn query_and_print_validator_state<'a>( } /// Query PoS validator's commission rate information -pub async fn query_and_print_commission_rate<'a>( - context: &impl Namada<'a>, +pub async fn query_and_print_commission_rate( + context: &impl Namada, args: args::QueryCommissionRate, ) { let validator = args.validator; @@ -1974,8 +1965,8 @@ pub async fn query_and_print_commission_rate<'a>( } /// Query PoS validator's metadata -pub async fn query_and_print_metadata<'a>( - context: &impl Namada<'a>, +pub async fn query_and_print_metadata( + context: &impl Namada, args: args::QueryMetaData, ) { let validator = args.validator; @@ -2051,10 +2042,7 @@ pub async fn query_and_print_metadata<'a>( } /// Query PoS slashes -pub async fn query_slashes<'a, N: Namada<'a>>( - context: &N, - args: args::QuerySlashes, -) { +pub async fn query_slashes(context: &N, args: args::QuerySlashes) { match args.validator { Some(validator) => { let validator = validator; @@ -2206,7 +2194,7 @@ pub async fn query_slashes<'a, N: Namada<'a>>( } } -pub async fn query_delegations<'a, N: Namada<'a>>( +pub async fn query_delegations( context: &N, args: args::QueryDelegations, ) { @@ -2227,7 +2215,7 @@ pub async fn query_delegations<'a, N: Namada<'a>>( } } -pub async fn query_find_validator<'a, N: Namada<'a>>( +pub async fn query_find_validator( context: &N, args: args::QueryFindValidator, ) { @@ -2264,7 +2252,7 @@ pub async fn query_find_validator<'a, N: Namada<'a>>( } /// Dry run a transaction -pub async fn dry_run_tx<'a, N: Namada<'a>>( +pub async fn dry_run_tx( context: &N, tx_bytes: Vec, ) -> Result<(), error::Error> @@ -2331,8 +2319,8 @@ pub async fn known_address( } /// Query for all conversions. -pub async fn query_conversions<'a>( - context: &impl Namada<'a>, +pub async fn query_conversions( + context: &impl Namada, args: args::QueryConversions, ) { // The chosen token type of the conversions @@ -2408,8 +2396,8 @@ pub async fn query_conversion( } /// Query a wasm code hash -pub async fn query_wasm_code_hash<'a>( - context: &impl Namada<'a>, +pub async fn query_wasm_code_hash( + context: &impl Namada, code_path: impl AsRef, ) -> Result { rpc::query_wasm_code_hash(context, code_path).await @@ -2443,8 +2431,8 @@ pub async fn query_storage_value_bytes< /// Query a range of storage values with a matching prefix and decode them with /// [`BorshDeserialize`]. Returns an iterator of the storage keys paired with /// their associated values. -pub async fn query_storage_prefix<'a, 'b, T>( - context: &'b impl Namada<'a>, +pub async fn query_storage_prefix<'b, T>( + context: &'b impl Namada, key: &storage::Key, ) -> Option> where @@ -2488,10 +2476,7 @@ pub async fn query_tx_response( /// Lookup the results of applying the specified transaction to the /// blockchain. -pub async fn query_result<'a>( - context: &impl Namada<'a>, - args: args::QueryResult, -) { +pub async fn query_result(context: &impl Namada, args: args::QueryResult) { // First try looking up application event pertaining to given hash. let tx_response = query_tx_response( context.client(), @@ -2529,7 +2514,7 @@ pub async fn query_result<'a>( } } -pub async fn epoch_sleep<'a>(context: &impl Namada<'a>, _args: args::Query) { +pub async fn epoch_sleep(context: &impl Namada, _args: args::Query) { let start_epoch = query_and_print_epoch(context).await; loop { tokio::time::sleep(core::time::Duration::from_secs(1)).await; @@ -2634,8 +2619,8 @@ fn unwrap_client_response( }) } -pub async fn compute_offline_proposal_votes<'a>( - context: &impl Namada<'a>, +pub async fn compute_offline_proposal_votes( + context: &impl Namada, proposal: &OfflineSignedProposal, votes: Vec, ) -> ProposalVotes { diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 0317ec43f3..a3610f9b7b 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -39,8 +39,8 @@ use crate::wallet::{gen_validator_keys, read_and_confirm_encryption_password}; /// Wrapper around `signing::aux_signing_data` that stores the optional /// disposable address to the wallet -pub async fn aux_signing_data<'a>( - context: &impl Namada<'a>, +pub async fn aux_signing_data( + context: &impl Namada, args: &args::Tx, owner: Option
, default_signer: Option
, @@ -69,8 +69,8 @@ pub async fn aux_signing_data<'a>( } // Sign the given transaction using a hardware wallet as a backup -pub async fn sign<'a>( - context: &impl Namada<'a>, +pub async fn sign( + context: &impl Namada, tx: &mut Tx, args: &args::Tx, signing_data: SigningTxData, @@ -200,8 +200,8 @@ pub async fn sign<'a>( } // Build a transaction to reveal the signer of the given transaction. -pub async fn submit_reveal_aux<'a>( - context: &impl Namada<'a>, +pub async fn submit_reveal_aux( + context: &impl Namada, args: args::Tx, address: &Address, ) -> Result<(), error::Error> { @@ -239,7 +239,7 @@ pub async fn submit_reveal_aux<'a>( Ok(()) } -pub async fn submit_bridge_pool_tx<'a, N: Namada<'a>>( +pub async fn submit_bridge_pool_tx( namada: &N, args: args::EthereumBridgePool, ) -> Result<(), error::Error> { @@ -263,7 +263,7 @@ pub async fn submit_bridge_pool_tx<'a, N: Namada<'a>>( Ok(()) } -pub async fn submit_custom<'a, N: Namada<'a>>( +pub async fn submit_custom( namada: &N, args: args::TxCustom, ) -> Result<(), error::Error> @@ -289,7 +289,7 @@ where Ok(()) } -pub async fn submit_update_account<'a, N: Namada<'a>>( +pub async fn submit_update_account( namada: &N, args: args::TxUpdateAccount, ) -> Result<(), error::Error> @@ -313,7 +313,7 @@ where Ok(()) } -pub async fn submit_init_account<'a, N: Namada<'a>>( +pub async fn submit_init_account( namada: &N, args: args::TxInitAccount, ) -> Result<(), error::Error> @@ -338,8 +338,8 @@ where Ok(()) } -pub async fn submit_change_consensus_key<'a>( - namada: &impl Namada<'a>, +pub async fn submit_change_consensus_key( + namada: &impl Namada, config: &mut crate::config::Config, args::ConsensusKeyChange { tx: tx_args, @@ -482,8 +482,8 @@ pub async fn submit_change_consensus_key<'a>( Ok(()) } -pub async fn submit_init_validator<'a>( - namada: &impl Namada<'a>, +pub async fn submit_init_validator( + namada: &impl Namada, config: &mut crate::config::Config, args::TxInitValidator { tx: tx_args, @@ -629,7 +629,7 @@ pub async fn submit_init_validator<'a>( } // Generate the validator keys let validator_keys = gen_validator_keys( - *namada.wallet_mut().await, + &mut *namada.wallet_mut().await, Some(eth_hot_pk.clone()), protocol_key, scheme, @@ -857,8 +857,8 @@ pub async fn submit_init_validator<'a>( Ok(()) } -pub async fn submit_transfer<'a>( - namada: &impl Namada<'a>, +pub async fn submit_transfer( + namada: &impl Namada, args: args::TxTransfer, ) -> Result<(), error::Error> { for _ in 0..2 { @@ -911,7 +911,7 @@ pub async fn submit_transfer<'a>( Ok(()) } -pub async fn submit_ibc_transfer<'a, N: Namada<'a>>( +pub async fn submit_ibc_transfer( namada: &N, args: args::TxIbcTransfer, ) -> Result<(), error::Error> @@ -935,7 +935,7 @@ where Ok(()) } -pub async fn submit_init_proposal<'a, N: Namada<'a>>( +pub async fn submit_init_proposal( namada: &N, args: args::InitProposal, ) -> Result<(), error::Error> @@ -1064,7 +1064,7 @@ where Ok(()) } -pub async fn submit_vote_proposal<'a, N: Namada<'a>>( +pub async fn submit_vote_proposal( namada: &N, args: args::VoteProposal, ) -> Result<(), error::Error> @@ -1144,7 +1144,7 @@ where Ok(()) } -pub async fn sign_tx<'a, N: Namada<'a>>( +pub async fn sign_tx( namada: &N, args::SignTx { tx: tx_args, @@ -1225,7 +1225,7 @@ where Ok(()) } -pub async fn submit_reveal_pk<'a, N: Namada<'a>>( +pub async fn submit_reveal_pk( namada: &N, args: args::RevealPk, ) -> Result<(), error::Error> @@ -1237,7 +1237,7 @@ where Ok(()) } -pub async fn submit_bond<'a, N: Namada<'a>>( +pub async fn submit_bond( namada: &N, args: args::Bond, ) -> Result<(), error::Error> @@ -1264,7 +1264,7 @@ where Ok(()) } -pub async fn submit_unbond<'a, N: Namada<'a>>( +pub async fn submit_unbond( namada: &N, args: args::Unbond, ) -> Result<(), error::Error> @@ -1290,7 +1290,7 @@ where Ok(()) } -pub async fn submit_withdraw<'a, N: Namada<'a>>( +pub async fn submit_withdraw( namada: &N, args: args::Withdraw, ) -> Result<(), error::Error> @@ -1314,7 +1314,7 @@ where Ok(()) } -pub async fn submit_claim_rewards<'a, N: Namada<'a>>( +pub async fn submit_claim_rewards( namada: &N, args: args::ClaimRewards, ) -> Result<(), error::Error> @@ -1338,7 +1338,7 @@ where Ok(()) } -pub async fn submit_redelegate<'a, N: Namada<'a>>( +pub async fn submit_redelegate( namada: &N, args: args::Redelegate, ) -> Result<(), error::Error> @@ -1361,7 +1361,7 @@ where Ok(()) } -pub async fn submit_validator_commission_change<'a, N: Namada<'a>>( +pub async fn submit_validator_commission_change( namada: &N, args: args::CommissionRateChange, ) -> Result<(), error::Error> @@ -1385,7 +1385,7 @@ where Ok(()) } -pub async fn submit_validator_metadata_change<'a, N: Namada<'a>>( +pub async fn submit_validator_metadata_change( namada: &N, args: args::MetaDataChange, ) -> Result<(), error::Error> @@ -1409,7 +1409,7 @@ where Ok(()) } -// pub async fn submit_change_consensus_key<'a, N: Namada<'a>>( +// pub async fn submit_change_consensus_key( // namada: &N, // args: args::ConsensusKeyChange, // ) -> Result<(), error::Error> @@ -1431,7 +1431,7 @@ where // Ok(()) // } -pub async fn submit_unjail_validator<'a, N: Namada<'a>>( +pub async fn submit_unjail_validator( namada: &N, args: args::TxUnjailValidator, ) -> Result<(), error::Error> @@ -1455,7 +1455,7 @@ where Ok(()) } -pub async fn submit_deactivate_validator<'a, N: Namada<'a>>( +pub async fn submit_deactivate_validator( namada: &N, args: args::TxDeactivateValidator, ) -> Result<(), error::Error> @@ -1479,7 +1479,7 @@ where Ok(()) } -pub async fn submit_reactivate_validator<'a, N: Namada<'a>>( +pub async fn submit_reactivate_validator( namada: &N, args: args::TxReactivateValidator, ) -> Result<(), error::Error> @@ -1503,7 +1503,7 @@ where Ok(()) } -pub async fn submit_update_steward_commission<'a, N: Namada<'a>>( +pub async fn submit_update_steward_commission( namada: &N, args: args::UpdateStewardCommission, ) -> Result<(), error::Error> @@ -1528,7 +1528,7 @@ where Ok(()) } -pub async fn submit_resign_steward<'a, N: Namada<'a>>( +pub async fn submit_resign_steward( namada: &N, args: args::ResignSteward, ) -> Result<(), error::Error> @@ -1553,8 +1553,8 @@ where } /// Save accounts initialized from a tx into the wallet, if any. -pub async fn save_initialized_accounts<'a>( - namada: &impl Namada<'a>, +pub async fn save_initialized_accounts( + namada: &impl Namada, args: &args::Tx, initialized_accounts: Vec
, ) { @@ -1565,8 +1565,8 @@ pub async fn save_initialized_accounts<'a>( /// the tx has been successfully included into the mempool of a validator /// /// In the case of errors in any of those stages, an error message is returned -pub async fn broadcast_tx<'a>( - namada: &impl Namada<'a>, +pub async fn broadcast_tx( + namada: &impl Namada, to_broadcast: &TxBroadcastData, ) -> Result { tx::broadcast_tx(namada, to_broadcast).await @@ -1580,15 +1580,15 @@ pub async fn broadcast_tx<'a>( /// 3. The decrypted payload of the tx has been included on the blockchain. /// /// In the case of errors in any of those stages, an error message is returned -pub async fn submit_tx<'a>( - namada: &impl Namada<'a>, +pub async fn submit_tx( + namada: &impl Namada, to_broadcast: TxBroadcastData, ) -> Result { tx::submit_tx(namada, to_broadcast).await } -pub async fn gen_ibc_shielded_transfer<'a>( - context: &impl Namada<'a>, +pub async fn gen_ibc_shielded_transfer( + context: &impl Namada, args: args::GenIbcShieldedTransafer, ) -> Result<(), error::Error> { if let Some(shielded_transfer) = diff --git a/apps/src/lib/node/ledger/shell/testing/client.rs b/apps/src/lib/node/ledger/shell/testing/client.rs index 5e4c04b07f..4343cf6a7d 100644 --- a/apps/src/lib/node/ledger/shell/testing/client.rs +++ b/apps/src/lib/node/ledger/shell/testing/client.rs @@ -48,7 +48,7 @@ pub fn run( rt.block_on(CliApi::handle_client_command( Some(node), cmd, - &TestingIo, + TestingIo, )) } Bin::Wallet => { @@ -84,7 +84,7 @@ pub fn run( rt.block_on(CliApi::handle_relayer_command( Some(node), cmd, - &TestingIo, + TestingIo, )) } } diff --git a/benches/native_vps.rs b/benches/native_vps.rs index fdaed5d1f9..448caa9b9c 100644 --- a/benches/native_vps.rs +++ b/benches/native_vps.rs @@ -495,7 +495,7 @@ fn setup_storage_for_masp_verification( .to_owned(); // Shield some tokens for Albert - let shield_tx = shielded_ctx.generate_masp_tx( + let (mut shielded_ctx, shield_tx) = shielded_ctx.generate_masp_tx( amount, TransferSource::Address(defaults::albert_address()), TransferTarget::PaymentAddress(albert_payment_addr), @@ -504,7 +504,7 @@ fn setup_storage_for_masp_verification( shielded_ctx.shell.wl_storage.commit_tx(); shielded_ctx.shell.commit(); - let signed_tx = match bench_name { + let (mut shielded_ctx, signed_tx) = match bench_name { "shielding" => shielded_ctx.generate_masp_tx( amount, TransferSource::Address(defaults::albert_address()), diff --git a/benches/txs.rs b/benches/txs.rs index 02d6c9c22d..b369aff3d7 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -83,16 +83,17 @@ fn transfer(c: &mut Criterion) { .to_owned(); // Shield some tokens for Albert - let shield_tx = shielded_ctx.generate_masp_tx( - amount, - TransferSource::Address(defaults::albert_address()), - TransferTarget::PaymentAddress(albert_payment_addr), - ); + let (mut shielded_ctx, shield_tx) = shielded_ctx + .generate_masp_tx( + amount, + TransferSource::Address(defaults::albert_address()), + TransferTarget::PaymentAddress(albert_payment_addr), + ); shielded_ctx.shell.execute_tx(&shield_tx); shielded_ctx.shell.wl_storage.commit_tx(); shielded_ctx.shell.commit(); - let signed_tx = match bench_name { + let (shielded_ctx, signed_tx) = match bench_name { "transparent" => shielded_ctx.generate_masp_tx( amount, TransferSource::Address(defaults::albert_address()), diff --git a/sdk/src/args.rs b/sdk/src/args.rs index 3359c08ec4..2eec2ee88a 100644 --- a/sdk/src/args.rs +++ b/sdk/src/args.rs @@ -175,9 +175,9 @@ impl TxCustom { impl TxCustom { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_custom(context, self).await @@ -281,9 +281,9 @@ impl TxTransfer { impl TxTransfer { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &mut self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_transfer(context, self).await @@ -395,9 +395,9 @@ impl TxIbcTransfer { impl TxIbcTransfer { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_ibc_transfer(context, self).await @@ -484,9 +484,9 @@ impl InitProposal { impl InitProposal { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { let current_epoch = rpc::query_epoch(context.client()).await?; @@ -641,9 +641,9 @@ impl VoteProposal { impl VoteProposal { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { let current_epoch = rpc::query_epoch(context.client()).await?; @@ -714,9 +714,9 @@ impl TxInitAccount { impl TxInitAccount { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_init_account(context, self).await @@ -832,9 +832,9 @@ impl TxUpdateAccount { impl TxUpdateAccount { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_update_account(context, self).await @@ -910,9 +910,9 @@ impl Bond { impl Bond { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_bond(context, self).await @@ -937,9 +937,9 @@ pub struct Unbond { impl Unbond { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<( crate::proto::Tx, SigningTxData, @@ -1010,9 +1010,9 @@ pub struct Redelegate { impl Redelegate { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData)> { tx::build_redelegation(context, self).await } @@ -1091,9 +1091,9 @@ impl RevealPk { impl RevealPk { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_reveal_pk(context, &self.tx, &self.public_key).await @@ -1175,9 +1175,9 @@ impl Withdraw { impl Withdraw { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_withdraw(context, self).await @@ -1212,9 +1212,9 @@ impl TxBuilder for ClaimRewards { impl ClaimRewards { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_claim_rewards(context, self).await @@ -1345,9 +1345,9 @@ impl CommissionRateChange { impl CommissionRateChange { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_validator_commission_change(context, self).await @@ -1404,9 +1404,9 @@ pub struct ConsensusKeyChange { // impl ConsensusKeyChange { // /// Build a transaction from this builder -// pub async fn build<'a>( +// pub async fn build( // &self, -// context: &impl Namada<'a>, +// context: &impl Namada, // ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, // Option)> { // tx::build_change_consensus_key(context, self).await @@ -1463,9 +1463,9 @@ impl MetaDataChange { impl MetaDataChange { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_validator_metadata_change(context, self).await @@ -1519,9 +1519,9 @@ impl UpdateStewardCommission { impl UpdateStewardCommission { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_update_steward_commission(context, self).await @@ -1568,9 +1568,9 @@ impl ResignSteward { impl ResignSteward { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_resign_steward(context, self).await @@ -1617,9 +1617,9 @@ impl TxUnjailValidator { impl TxUnjailValidator { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_unjail_validator(context, self).await @@ -1666,9 +1666,9 @@ impl TxDeactivateValidator { impl TxDeactivateValidator { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_deactivate_validator(context, self).await @@ -1715,9 +1715,9 @@ impl TxReactivateValidator { impl TxReactivateValidator { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( &self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { tx::build_reactivate_validator(context, self).await @@ -2288,9 +2288,9 @@ impl EthereumBridgePool { impl EthereumBridgePool { /// Build a transaction from this builder - pub async fn build<'a>( + pub async fn build( self, - context: &impl Namada<'a>, + context: &impl Namada, ) -> crate::error::Result<(crate::proto::Tx, SigningTxData, Option)> { bridge_pool::build_bridge_pool_tx(context, self).await diff --git a/sdk/src/eth_bridge/bridge_pool.rs b/sdk/src/eth_bridge/bridge_pool.rs index e682521987..efd2989d58 100644 --- a/sdk/src/eth_bridge/bridge_pool.rs +++ b/sdk/src/eth_bridge/bridge_pool.rs @@ -47,7 +47,7 @@ use crate::{ /// Craft a transaction that adds a transfer to the Ethereum bridge pool. pub async fn build_bridge_pool_tx( - context: &impl Namada<'_>, + context: &impl Namada, args::EthereumBridgePool { tx: tx_args, nut, @@ -113,7 +113,7 @@ pub async fn build_bridge_pool_tx( /// Perform client validation checks on a Bridge pool transfer. #[allow(clippy::too_many_arguments)] async fn validate_bridge_pool_tx( - context: &impl Namada<'_>, + context: &impl Namada, force: bool, nut: bool, asset: EthAddress, @@ -316,7 +316,7 @@ struct BridgePoolResponse<'pool> { /// Query the contents of the Ethereum bridge pool. /// Prints out a json payload. -pub async fn query_bridge_pool<'a>( +pub async fn query_bridge_pool( client: &(impl Client + Sync), io: &impl Io, ) -> Result, Error> { @@ -353,7 +353,7 @@ pub async fn query_bridge_pool<'a>( /// Query the contents of the Ethereum bridge pool that /// is covered by the latest signed root. /// Prints out a json payload. -pub async fn query_signed_bridge_pool<'a>( +pub async fn query_signed_bridge_pool( client: &(impl Client + Sync), io: &impl Io, ) -> Result, Error> { @@ -392,7 +392,7 @@ pub async fn query_signed_bridge_pool<'a>( /// backing each `TransferToEthereum` event. /// /// Prints a json payload. -pub async fn query_relay_progress<'a>( +pub async fn query_relay_progress( client: &(impl Client + Sync), io: &impl Io, ) -> Result<(), Error> { @@ -417,7 +417,7 @@ pub async fn query_relay_progress<'a>( /// Internal methdod to construct a proof that a set of transfers are in the /// bridge pool. -async fn construct_bridge_pool_proof<'a>( +async fn construct_bridge_pool_proof( client: &(impl Client + Sync), io: &impl Io, args: GenBridgePoolProofReq<'_, '_>, @@ -513,7 +513,7 @@ struct BridgePoolProofResponse { /// Construct a merkle proof of a batch of transfers in /// the bridge pool and return it to the user (as opposed /// to relaying it to ethereum). -pub async fn construct_proof<'a>( +pub async fn construct_proof( client: &(impl Client + Sync), io: &impl Io, args: args::BridgePoolProof, @@ -562,7 +562,7 @@ pub async fn construct_proof<'a>( } /// Relay a validator set update, signed off for a given epoch. -pub async fn relay_bridge_pool_proof<'a, E>( +pub async fn relay_bridge_pool_proof( eth_client: Arc, client: &(impl Client + Sync), io: &impl Io, @@ -794,8 +794,8 @@ mod recommendations { /// Recommend the most economical batch of transfers to relay based /// on a conversion rate estimates from NAM to ETH and gas usage /// heuristics. - pub async fn recommend_batch<'a>( - context: &impl Namada<'a>, + pub async fn recommend_batch( + context: &impl Namada, args: args::RecommendBatch, ) -> Result<(), Error> { // get transfers that can already been relayed but are awaiting a quorum diff --git a/sdk/src/eth_bridge/validator_set.rs b/sdk/src/eth_bridge/validator_set.rs index 1b7a77466d..e92e5c545e 100644 --- a/sdk/src/eth_bridge/validator_set.rs +++ b/sdk/src/eth_bridge/validator_set.rs @@ -270,7 +270,7 @@ impl From> for RelayResult { /// Query an ABI encoding of the validator set to be installed /// at the given epoch, and its associated proof. -pub async fn query_validator_set_update_proof<'a>( +pub async fn query_validator_set_update_proof( client: &(impl Client + Sync), io: &impl Io, args: args::ValidatorSetProof, @@ -298,7 +298,7 @@ pub async fn query_validator_set_update_proof<'a>( } /// Query an ABI encoding of the Bridge validator set at a given epoch. -pub async fn query_bridge_validator_set<'a>( +pub async fn query_bridge_validator_set( client: &(impl Client + Sync), io: &impl Io, args: args::BridgeValidatorSet, @@ -326,7 +326,7 @@ pub async fn query_bridge_validator_set<'a>( } /// Query an ABI encoding of the Governance validator set at a given epoch. -pub async fn query_governnace_validator_set<'a>( +pub async fn query_governnace_validator_set( client: &(impl Client + Sync), io: &impl Io, args: args::GovernanceValidatorSet, diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index f5c0ae37fa..719b12d8e7 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -66,42 +66,38 @@ use crate::wallet::{Wallet, WalletIo, WalletStorage}; #[async_trait::async_trait(?Send)] /// An interface for high-level interaction with the Namada SDK -pub trait Namada<'a>: Sized { +pub trait Namada: Sized { /// A client with async request dispatcher method - type Client: 'a + queries::Client + Sync; + type Client: queries::Client + Sync; /// Captures the interactive parts of the wallet's functioning - type WalletUtils: 'a + WalletIo + WalletStorage; + type WalletUtils: WalletIo + WalletStorage; /// Abstracts platform specific details away from the logic of shielded pool /// operations. - type ShieldedUtils: 'a + ShieldedUtils; + type ShieldedUtils: ShieldedUtils; /// Captures the input/output streams used by this object - type Io: 'a + Io; + type Io: Io; /// Obtain the client for communicating with the ledger - fn client(&self) -> &'a Self::Client; + fn client(&self) -> &Self::Client; /// Obtain the input/output handle for this context - fn io(&self) -> &'a Self::Io; + fn io(&self) -> &Self::Io; /// Obtain read guard on the wallet - async fn wallet( - &self, - ) -> RwLockReadGuard<&'a mut Wallet>; + async fn wallet(&self) -> RwLockReadGuard>; /// Obtain write guard on the wallet - async fn wallet_mut( - &self, - ) -> RwLockWriteGuard<&'a mut Wallet>; + async fn wallet_mut(&self) -> RwLockWriteGuard>; /// Obtain read guard on the shielded context async fn shielded( &self, - ) -> RwLockReadGuard<&'a mut ShieldedContext>; + ) -> RwLockReadGuard>; /// Obtain write guard on the shielded context async fn shielded_mut( &self, - ) -> RwLockWriteGuard<&'a mut ShieldedContext>; + ) -> RwLockWriteGuard>; /// Return the native token fn native_token(&self) -> Address; @@ -537,7 +533,7 @@ pub trait Namada<'a>: Sized { } /// Provides convenience methods for common Namada interactions -pub struct NamadaImpl<'a, C, U, V, I> +pub struct NamadaImpl where C: queries::Client + Sync, U: WalletIo, @@ -545,20 +541,20 @@ where I: Io, { /// Used to send and receive messages from the ledger - pub client: &'a C, + pub client: C, /// Stores the addresses and keys required for ledger interactions - pub wallet: RwLock<&'a mut Wallet>, + pub wallet: RwLock>, /// Stores the current state of the shielded pool - pub shielded: RwLock<&'a mut ShieldedContext>, + pub shielded: RwLock>, /// Captures the input/output streams used by this object - pub io: &'a I, + pub io: I, /// The address of the native token native_token: Address, /// The default builder for a Tx prototype: args::Tx, } -impl<'a, C, U, V, I> NamadaImpl<'a, C, U, V, I> +impl NamadaImpl where C: queries::Client + Sync, U: WalletIo, @@ -567,10 +563,10 @@ where { /// Construct a new Namada context with the given native token address pub fn native_new( - client: &'a C, - wallet: &'a mut Wallet, - shielded: &'a mut ShieldedContext, - io: &'a I, + client: C, + wallet: Wallet, + shielded: ShieldedContext, + io: I, native_token: Address, ) -> Self { NamadaImpl { @@ -609,12 +605,12 @@ where /// Construct a new Namada context looking up the native token address pub async fn new( - client: &'a C, - wallet: &'a mut Wallet, - shielded: &'a mut ShieldedContext, - io: &'a I, - ) -> crate::error::Result> { - let native_token = query_native_token(client).await?; + client: C, + wallet: Wallet, + shielded: ShieldedContext, + io: I, + ) -> crate::error::Result> { + let native_token = query_native_token(&client).await?; Ok(NamadaImpl::native_new( client, wallet, @@ -626,7 +622,7 @@ where } #[async_trait::async_trait(?Send)] -impl<'a, C, U, V, I> Namada<'a> for NamadaImpl<'a, C, U, V, I> +impl Namada for NamadaImpl where C: queries::Client + Sync, U: WalletIo + WalletStorage, @@ -647,41 +643,37 @@ where self.native_token.clone() } - fn io(&self) -> &'a Self::Io { - self.io + fn io(&self) -> &Self::Io { + &self.io } - fn client(&self) -> &'a Self::Client { - self.client + fn client(&self) -> &Self::Client { + &self.client } - async fn wallet( - &self, - ) -> RwLockReadGuard<&'a mut Wallet> { + async fn wallet(&self) -> RwLockReadGuard> { self.wallet.read().await } - async fn wallet_mut( - &self, - ) -> RwLockWriteGuard<&'a mut Wallet> { + async fn wallet_mut(&self) -> RwLockWriteGuard> { self.wallet.write().await } async fn shielded( &self, - ) -> RwLockReadGuard<&'a mut ShieldedContext> { + ) -> RwLockReadGuard> { self.shielded.read().await } async fn shielded_mut( &self, - ) -> RwLockWriteGuard<&'a mut ShieldedContext> { + ) -> RwLockWriteGuard> { self.shielded.write().await } } /// Allow the prototypical Tx builder to be modified -impl<'a, C, U, V, I> args::TxBuilder for NamadaImpl<'a, C, U, V, I> +impl args::TxBuilder for NamadaImpl where C: queries::Client + Sync, U: WalletIo, diff --git a/sdk/src/masp.rs b/sdk/src/masp.rs index 68459688e0..9a18f2200d 100644 --- a/sdk/src/masp.rs +++ b/sdk/src/masp.rs @@ -1220,9 +1220,9 @@ impl ShieldedContext { /// of the specified asset type. Return the total value accumulated plus /// notes and the corresponding diversifiers/merkle paths that were used to /// achieve the total value. - pub async fn collect_unspent_notes<'a>( + pub async fn collect_unspent_notes( &mut self, - context: &impl Namada<'a>, + context: &impl Namada, vk: &ViewingKey, target: I128Sum, target_epoch: Epoch, @@ -1407,9 +1407,9 @@ impl ShieldedContext { /// the epoch of the transaction or even before, so exchange all these /// amounts to the epoch of the transaction in order to get the value that /// would have been displayed in the epoch of the transaction. - pub async fn compute_exchanged_pinned_balance<'a>( + pub async fn compute_exchanged_pinned_balance( &mut self, - context: &impl Namada<'a>, + context: &impl Namada, owner: PaymentAddress, viewing_key: &ViewingKey, ) -> Result<(MaspAmount, Epoch), Error> { @@ -1497,8 +1497,8 @@ impl ShieldedContext { /// UTXOs are sometimes used to make transactions balanced, but it is /// understood that transparent account changes are effected only by the /// amounts and signatures specified by the containing Transfer object. - pub async fn gen_shielded_transfer<'a>( - context: &impl Namada<'a>, + pub async fn gen_shielded_transfer( + context: &impl Namada, source: &TransferSource, target: &TransferTarget, token: &Address, diff --git a/sdk/src/rpc.rs b/sdk/src/rpc.rs index 0d0d69a79b..8d29992b72 100644 --- a/sdk/src/rpc.rs +++ b/sdk/src/rpc.rs @@ -52,8 +52,8 @@ use crate::{display_line, edisplay_line, error, Namada}; /// /// If a response is not delivered until `deadline`, we exit the cli with an /// error. -pub async fn query_tx_status<'a>( - context: &impl Namada<'a>, +pub async fn query_tx_status( + context: &impl Namada, status: TxEventQuery<'_>, deadline: time::Instant, ) -> Result { @@ -276,8 +276,8 @@ pub async fn query_conversions( } /// Query a wasm code hash -pub async fn query_wasm_code_hash<'a>( - context: &impl Namada<'a>, +pub async fn query_wasm_code_hash( + context: &impl Namada, code_path: impl AsRef, ) -> Result { let hash_key = Key::wasm_hash(code_path.as_ref()); @@ -360,7 +360,7 @@ pub async fn query_storage_value_bytes( /// Query a range of storage values with a matching prefix and decode them with /// [`BorshDeserialize`]. Returns an iterator of the storage keys paired with /// their associated values. -pub async fn query_storage_prefix<'a, 'b, N: Namada<'a>, T>( +pub async fn query_storage_prefix<'a, 'b, N: Namada, T>( context: &'b N, key: &storage::Key, ) -> Result>, error::Error> @@ -464,7 +464,7 @@ pub async fn query_tx_events( } /// Dry run a transaction -pub async fn dry_run_tx<'a, N: Namada<'a>>( +pub async fn dry_run_tx( context: &N, tx_bytes: Vec, ) -> Result { @@ -842,8 +842,8 @@ pub async fn get_public_key_at( } /// Query a validator's unbonds for a given epoch -pub async fn query_and_print_unbonds<'a>( - context: &impl Namada<'a>, +pub async fn query_and_print_unbonds( + context: &impl Namada, source: &Address, validator: &Address, ) -> Result<(), error::Error> { @@ -982,7 +982,7 @@ pub async fn enriched_bonds_and_unbonds( } /// Get the correct representation of the amount given the token type. -pub async fn validate_amount<'a, N: Namada<'a>>( +pub async fn validate_amount( context: &N, amount: InputAmount, token: &Address, @@ -1043,7 +1043,7 @@ pub async fn validate_amount<'a, N: Namada<'a>>( } /// Wait for a first block and node to be synced. -pub async fn wait_until_node_is_synched<'a>( +pub async fn wait_until_node_is_synched( client: &(impl Client + Sync), io: &impl Io, ) -> Result<(), Error> { @@ -1140,7 +1140,7 @@ pub async fn format_denominated_amount( } /// Look up the IBC denomination from a IbcToken. -pub async fn query_ibc_denom<'a, N: Namada<'a>>( +pub async fn query_ibc_denom( context: &N, token: &Address, owner: Option<&Address>, diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index 6784be92ba..3fb44a5100 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -86,8 +86,8 @@ pub struct SigningTxData { /// for it from the wallet. If the keypair is encrypted but a password is not /// supplied, then it is interactively prompted. Errors if the key cannot be /// found or loaded. -pub async fn find_pk<'a>( - context: &impl Namada<'a>, +pub async fn find_pk( + context: &impl Namada, addr: &Address, ) -> Result { match addr { @@ -167,8 +167,8 @@ pub fn find_key_by_pk( /// signer. Return the given signing key or public key of the given signer if /// possible. If no explicit signer given, use the `default`. If no `default` /// is given, an `Error` is returned. -pub async fn tx_signers<'a>( - context: &impl Namada<'a>, +pub async fn tx_signers( + context: &impl Namada, args: &args::Tx, default: Option
, ) -> Result, Error> { @@ -226,8 +226,8 @@ pub async fn default_sign( /// hashes needed for monitoring the tx on chain. /// /// If it is a dry run, it is not put in a wrapper, but returned as is. -pub async fn sign_tx<'a, F: std::future::Future>>( - context: &impl Namada<'a>, +pub async fn sign_tx>>( + context: &impl Namada, args: &args::Tx, tx: &mut Tx, signing_data: SigningTxData, @@ -260,7 +260,7 @@ pub async fn sign_tx<'a, F: std::future::Future>>( if used_pubkeys.contains(public_key) { None } else { - match find_key_by_pk(*wallet, args, public_key) { + match find_key_by_pk(&mut wallet, args, public_key) { Ok(secret_key) => { used_pubkeys.insert(public_key.clone()); Some(secret_key) @@ -301,7 +301,7 @@ pub async fn sign_tx<'a, F: std::future::Future>>( // Lock the wallet just long enough to extract a key from it without // interfering with the sign closure call let mut wallet = context.wallet_mut().await; - find_key_by_pk(*wallet, args, &signing_data.fee_payer) + find_key_by_pk(&mut wallet, args, &signing_data.fee_payer) }; match key { Ok(fee_payer_keypair) => { @@ -321,8 +321,8 @@ pub async fn sign_tx<'a, F: std::future::Future>>( /// Return the necessary data regarding an account to be able to generate a /// multisignature section -pub async fn aux_signing_data<'a>( - context: &impl Namada<'a>, +pub async fn aux_signing_data( + context: &impl Namada, args: &args::Tx, owner: Option
, default_signer: Option
, @@ -390,8 +390,8 @@ pub async fn aux_signing_data<'a>( }) } -pub async fn init_validator_signing_data<'a>( - context: &impl Namada<'a>, +pub async fn init_validator_signing_data( + context: &impl Namada, args: &args::Tx, validator_keys: Vec, ) -> Result { @@ -450,7 +450,7 @@ pub struct TxSourcePostBalance { /// wrapper and its payload which is needed for monitoring its /// progress on chain. #[allow(clippy::too_many_arguments)] -pub async fn wrap_tx<'a, N: Namada<'a>>( +pub async fn wrap_tx( context: &N, tx: &mut Tx, args: &args::Tx, @@ -734,8 +734,8 @@ fn make_ledger_amount_addr( /// Adds a Ledger output line describing a given transaction amount and asset /// type -async fn make_ledger_amount_asset<'a>( - context: &impl Namada<'a>, +async fn make_ledger_amount_asset( + context: &impl Namada, tokens: &HashMap, output: &mut Vec, amount: u64, @@ -829,8 +829,8 @@ fn format_outputs(output: &mut Vec) { /// Adds a Ledger output for the sender and destination for transparent and MASP /// transactions -pub async fn make_ledger_masp_endpoints<'a>( - context: &impl Namada<'a>, +pub async fn make_ledger_masp_endpoints( + context: &impl Namada, tokens: &HashMap, output: &mut Vec, transfer: &Transfer, @@ -904,8 +904,8 @@ pub async fn make_ledger_masp_endpoints<'a>( /// Internal method used to generate transaction test vectors #[cfg(feature = "std")] -pub async fn generate_test_vector<'a>( - context: &impl Namada<'a>, +pub async fn generate_test_vector( + context: &impl Namada, tx: &Tx, ) -> Result<(), Error> { use std::env; @@ -1014,8 +1014,8 @@ impl<'a> Display for LedgerProposalType<'a> { /// Converts the given transaction to the form that is displayed on the Ledger /// device -pub async fn to_ledger_vector<'a>( - context: &impl Namada<'a>, +pub async fn to_ledger_vector( + context: &impl Namada, tx: &Tx, ) -> Result { // To facilitate lookups of human-readable token names diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index 9378615890..fc710c9847 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -173,8 +173,8 @@ pub fn dump_tx(io: &IO, args: &args::Tx, tx: Tx) { /// Prepare a transaction for signing and submission by adding a wrapper header /// to it. #[allow(clippy::too_many_arguments)] -pub async fn prepare_tx<'a>( - context: &impl Namada<'a>, +pub async fn prepare_tx( + context: &impl Namada, args: &args::Tx, tx: &mut Tx, fee_payer: common::PublicKey, @@ -192,8 +192,8 @@ pub async fn prepare_tx<'a>( /// Submit transaction and wait for result. Returns a list of addresses /// initialized in the transaction if any. In dry run, this is always empty. -pub async fn process_tx<'a>( - context: &impl Namada<'a>, +pub async fn process_tx( + context: &impl Namada, args: &args::Tx, tx: Tx, ) -> Result { @@ -266,8 +266,8 @@ pub async fn has_revealed_pk( } /// Submit transaction to reveal the given public key -pub async fn build_reveal_pk<'a>( - context: &impl Namada<'a>, +pub async fn build_reveal_pk( + context: &impl Namada, args: &args::Tx, public_key: &common::PublicKey, ) -> Result<(Tx, SigningTxData, Option)> { @@ -292,8 +292,8 @@ pub async fn build_reveal_pk<'a>( /// the tx has been successfully included into the mempool of a node /// /// In the case of errors in any of those stages, an error message is returned -pub async fn broadcast_tx<'a>( - context: &impl Namada<'a>, +pub async fn broadcast_tx( + context: &impl Namada, to_broadcast: &TxBroadcastData, ) -> Result { let (tx, wrapper_tx_hash, decrypted_tx_hash) = match to_broadcast { @@ -355,8 +355,8 @@ pub async fn broadcast_tx<'a>( /// 3. The decrypted payload of the tx has been included on the blockchain. /// /// In the case of errors in any of those stages, an error message is returned -pub async fn submit_tx<'a>( - context: &impl Namada<'a>, +pub async fn submit_tx( + context: &impl Namada, to_broadcast: TxBroadcastData, ) -> Result { let (_, wrapper_hash, decrypted_hash) = match &to_broadcast { @@ -446,7 +446,7 @@ pub fn decode_component( } /// Save accounts initialized from a tx into the wallet, if any. -pub async fn save_initialized_accounts<'a, N: Namada<'a>>( +pub async fn save_initialized_accounts( context: &N, args: &args::Tx, initialized_accounts: Vec
, @@ -506,8 +506,8 @@ pub async fn save_initialized_accounts<'a, N: Namada<'a>>( } /// Submit validator comission rate change -pub async fn build_validator_commission_change<'a>( - context: &impl Namada<'a>, +pub async fn build_validator_commission_change( + context: &impl Namada, args::CommissionRateChange { tx: tx_args, validator, @@ -618,8 +618,8 @@ pub async fn build_validator_commission_change<'a>( } /// Submit validator metadata change -pub async fn build_validator_metadata_change<'a>( - context: &impl Namada<'a>, +pub async fn build_validator_metadata_change( + context: &impl Namada, args::MetaDataChange { tx: tx_args, validator, @@ -747,8 +747,8 @@ pub async fn build_validator_metadata_change<'a>( } /// Craft transaction to update a steward commission -pub async fn build_update_steward_commission<'a>( - context: &impl Namada<'a>, +pub async fn build_update_steward_commission( + context: &impl Namada, args::UpdateStewardCommission { tx: tx_args, steward, @@ -806,8 +806,8 @@ pub async fn build_update_steward_commission<'a>( } /// Craft transaction to resign as a steward -pub async fn build_resign_steward<'a>( - context: &impl Namada<'a>, +pub async fn build_resign_steward( + context: &impl Namada, args::ResignSteward { tx: tx_args, steward, @@ -846,8 +846,8 @@ pub async fn build_resign_steward<'a>( } /// Submit transaction to unjail a jailed validator -pub async fn build_unjail_validator<'a>( - context: &impl Namada<'a>, +pub async fn build_unjail_validator( + context: &impl Namada, args::TxUnjailValidator { tx: tx_args, validator, @@ -953,8 +953,8 @@ pub async fn build_unjail_validator<'a>( } /// Submit transaction to deactivate a validator -pub async fn build_deactivate_validator<'a>( - context: &impl Namada<'a>, +pub async fn build_deactivate_validator( + context: &impl Namada, args::TxDeactivateValidator { tx: tx_args, validator, @@ -1024,8 +1024,8 @@ pub async fn build_deactivate_validator<'a>( } /// Submit transaction to deactivate a validator -pub async fn build_reactivate_validator<'a>( - context: &impl Namada<'a>, +pub async fn build_reactivate_validator( + context: &impl Namada, args::TxReactivateValidator { tx: tx_args, validator, @@ -1094,8 +1094,8 @@ pub async fn build_reactivate_validator<'a>( } /// Redelegate bonded tokens from one validator to another -pub async fn build_redelegation<'a>( - context: &impl Namada<'a>, +pub async fn build_redelegation( + context: &impl Namada, args::Redelegate { tx: tx_args, src_validator, @@ -1274,8 +1274,8 @@ pub async fn build_redelegation<'a>( } /// Submit transaction to withdraw an unbond -pub async fn build_withdraw<'a>( - context: &impl Namada<'a>, +pub async fn build_withdraw( + context: &impl Namada, args::Withdraw { tx: tx_args, validator, @@ -1357,8 +1357,8 @@ pub async fn build_withdraw<'a>( } /// Submit transaction to withdraw an unbond -pub async fn build_claim_rewards<'a>( - context: &impl Namada<'a>, +pub async fn build_claim_rewards( + context: &impl Namada, args::ClaimRewards { tx: tx_args, validator, @@ -1405,8 +1405,8 @@ pub async fn build_claim_rewards<'a>( } /// Submit a transaction to unbond -pub async fn build_unbond<'a>( - context: &impl Namada<'a>, +pub async fn build_unbond( + context: &impl Namada, args::Unbond { tx: tx_args, validator, @@ -1512,8 +1512,8 @@ pub async fn build_unbond<'a>( } /// Query the unbonds post-tx -pub async fn query_unbonds<'a>( - context: &impl Namada<'a>, +pub async fn query_unbonds( + context: &impl Namada, args: args::Unbond, latest_withdrawal_pre: Option<(Epoch, token::Amount)>, ) -> Result<()> { @@ -1583,8 +1583,8 @@ pub async fn query_unbonds<'a>( } /// Submit a transaction to bond -pub async fn build_bond<'a>( - context: &impl Namada<'a>, +pub async fn build_bond( + context: &impl Namada, args::Bond { tx: tx_args, validator, @@ -1697,8 +1697,8 @@ pub async fn build_bond<'a>( } /// Build a default proposal governance -pub async fn build_default_proposal<'a>( - context: &impl Namada<'a>, +pub async fn build_default_proposal( + context: &impl Namada, args::InitProposal { tx, proposal_data: _, @@ -1750,8 +1750,8 @@ pub async fn build_default_proposal<'a>( } /// Build a proposal vote -pub async fn build_vote_proposal<'a>( - context: &impl Namada<'a>, +pub async fn build_vote_proposal( + context: &impl Namada, args::VoteProposal { tx, proposal_id, @@ -1837,8 +1837,8 @@ pub async fn build_vote_proposal<'a>( } /// Build a pgf funding proposal governance -pub async fn build_pgf_funding_proposal<'a>( - context: &impl Namada<'a>, +pub async fn build_pgf_funding_proposal( + context: &impl Namada, args::InitProposal { tx, proposal_data: _, @@ -1882,8 +1882,8 @@ pub async fn build_pgf_funding_proposal<'a>( } /// Build a pgf funding proposal governance -pub async fn build_pgf_stewards_proposal<'a>( - context: &impl Namada<'a>, +pub async fn build_pgf_stewards_proposal( + context: &impl Namada, args::InitProposal { tx, proposal_data: _, @@ -1928,8 +1928,8 @@ pub async fn build_pgf_stewards_proposal<'a>( } /// Submit an IBC transfer -pub async fn build_ibc_transfer<'a>( - context: &impl Namada<'a>, +pub async fn build_ibc_transfer( + context: &impl Namada, args: &args::TxIbcTransfer, ) -> Result<(Tx, SigningTxData, Option)> { let default_signer = Some(args.source.clone()); @@ -2057,8 +2057,8 @@ pub async fn build_ibc_transfer<'a>( /// Abstraction for helping build transactions #[allow(clippy::too_many_arguments)] -pub async fn build<'a, F, D>( - context: &impl Namada<'a>, +pub async fn build( + context: &impl Namada, tx_args: &crate::args::Tx, path: PathBuf, data: D, @@ -2083,8 +2083,8 @@ where } #[allow(clippy::too_many_arguments)] -async fn build_pow_flag<'a, F, D>( - context: &impl Namada<'a>, +async fn build_pow_flag( + context: &impl Namada, tx_args: &crate::args::Tx, path: PathBuf, mut data: D, @@ -2126,9 +2126,9 @@ where /// Try to decode the given asset type and add its decoding to the supplied set. /// Returns true only if a new decoding has been added to the given set. -async fn add_asset_type<'a>( +async fn add_asset_type( asset_types: &mut HashSet<(Address, MaspDenom, Epoch)>, - context: &impl Namada<'a>, + context: &impl Namada, asset_type: AssetType, ) -> bool { if let Some(asset_type) = context @@ -2146,8 +2146,8 @@ async fn add_asset_type<'a>( /// Collect the asset types used in the given Builder and decode them. This /// function provides the data necessary for offline wallets to present asset /// type information. -async fn used_asset_types<'a, P, R, K, N>( - context: &impl Namada<'a>, +async fn used_asset_types( + context: &impl Namada, builder: &Builder, ) -> std::result::Result, RpcError> { let mut asset_types = HashSet::new(); @@ -2180,7 +2180,7 @@ async fn used_asset_types<'a, P, R, K, N>( } /// Submit an ordinary transfer -pub async fn build_transfer<'a, N: Namada<'a>>( +pub async fn build_transfer( context: &N, args: &mut args::TxTransfer, ) -> Result<(Tx, SigningTxData, Option)> { @@ -2351,8 +2351,8 @@ pub async fn build_transfer<'a, N: Namada<'a>>( } /// Submit a transaction to initialize an account -pub async fn build_init_account<'a>( - context: &impl Namada<'a>, +pub async fn build_init_account( + context: &impl Namada, args::TxInitAccount { tx: tx_args, vp_code_path, @@ -2406,8 +2406,8 @@ pub async fn build_init_account<'a>( } /// Submit a transaction to update a VP -pub async fn build_update_account<'a>( - context: &impl Namada<'a>, +pub async fn build_update_account( + context: &impl Namada, args::TxUpdateAccount { tx: tx_args, vp_code_path, @@ -2488,8 +2488,8 @@ pub async fn build_update_account<'a>( } /// Submit a custom transaction -pub async fn build_custom<'a>( - context: &impl Namada<'a>, +pub async fn build_custom( + context: &impl Namada, args::TxCustom { tx: tx_args, code_path, @@ -2539,7 +2539,7 @@ pub async fn build_custom<'a>( } /// Generate IBC shielded transfer -pub async fn gen_ibc_shielded_transfer<'a, N: Namada<'a>>( +pub async fn gen_ibc_shielded_transfer( context: &N, args: args::GenIbcShieldedTransafer, ) -> Result> { @@ -2612,8 +2612,8 @@ pub async fn gen_ibc_shielded_transfer<'a, N: Namada<'a>>( } } -async fn get_ibc_src_port_channel<'a>( - context: &impl Namada<'a>, +async fn get_ibc_src_port_channel( + context: &impl Namada, dest_port_id: &PortId, dest_channel_id: &ChannelId, ) -> Result<(PortId, ChannelId)> { @@ -2654,9 +2654,9 @@ async fn get_ibc_src_port_channel<'a>( }) } -async fn expect_dry_broadcast<'a>( +async fn expect_dry_broadcast( to_broadcast: TxBroadcastData, - context: &impl Namada<'a>, + context: &impl Namada, ) -> Result { match to_broadcast { TxBroadcastData::DryRun(tx) => { @@ -2678,10 +2678,10 @@ fn lift_rpc_error(res: std::result::Result) -> Result { /// Returns the given validator if the given address is a validator, /// otherwise returns an error, force forces the address through even /// if it isn't a validator -async fn known_validator_or_err<'a>( +async fn known_validator_or_err( validator: Address, force: bool, - context: &impl Namada<'a>, + context: &impl Namada, ) -> Result
{ // Check that the validator address exists on chain let is_validator = rpc::is_validator(context.client(), &validator).await?; @@ -2704,10 +2704,10 @@ async fn known_validator_or_err<'a>( /// general pattern for checking if an address exists on the chain, or /// throwing an error if it's not forced. Takes a generic error /// message and the error type. -async fn address_exists_or_err<'a, F>( +async fn address_exists_or_err( addr: Address, force: bool, - context: &impl Namada<'a>, + context: &impl Namada, message: String, err: F, ) -> Result
@@ -2730,10 +2730,10 @@ where /// Returns the given source address if the given address exists on chain /// otherwise returns an error, force forces the address through even /// if it isn't on chain -async fn source_exists_or_err<'a>( +async fn source_exists_or_err( token: Address, force: bool, - context: &impl Namada<'a>, + context: &impl Namada, ) -> Result
{ let message = format!("The source address {} doesn't exist on chain.", token); @@ -2746,10 +2746,10 @@ async fn source_exists_or_err<'a>( /// Returns the given target address if the given address exists on chain /// otherwise returns an error, force forces the address through even /// if it isn't on chain -async fn target_exists_or_err<'a>( +async fn target_exists_or_err( token: Address, force: bool, - context: &impl Namada<'a>, + context: &impl Namada, ) -> Result
{ let message = format!("The target address {} doesn't exist on chain.", token); @@ -2762,7 +2762,7 @@ async fn target_exists_or_err<'a>( /// Checks the balance at the given address is enough to transfer the /// given amount, along with the balance even existing. Force /// overrides this. Returns the updated balance for fee check if necessary -async fn check_balance_too_low_err<'a, N: Namada<'a>>( +async fn check_balance_too_low_err( token: &Address, source: &Address, amount: token::Amount, @@ -2825,8 +2825,8 @@ async fn check_balance_too_low_err<'a, N: Namada<'a>>( } } -async fn query_wasm_code_hash_buf<'a>( - context: &impl Namada<'a>, +async fn query_wasm_code_hash_buf( + context: &impl Namada, path: &Path, ) -> Result { query_wasm_code_hash(context, path.to_string_lossy()).await From 8afe908fc7adda9e28efca842e0de20cde8d1c22 Mon Sep 17 00:00:00 2001 From: Murisi Tarusenga Date: Tue, 28 Nov 2023 20:50:27 +0200 Subject: [PATCH 54/54] Added changelog entry. --- .changelog/unreleased/SDK/2225-remove-sdk-lifetimes.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/SDK/2225-remove-sdk-lifetimes.md diff --git a/.changelog/unreleased/SDK/2225-remove-sdk-lifetimes.md b/.changelog/unreleased/SDK/2225-remove-sdk-lifetimes.md new file mode 100644 index 0000000000..e02e6f8880 --- /dev/null +++ b/.changelog/unreleased/SDK/2225-remove-sdk-lifetimes.md @@ -0,0 +1,2 @@ +- Removed uses of lifetimes in the SDKs Namada trait and implementation + ([\#2225](https://github.com/anoma/namada/pull/2225)) \ No newline at end of file