From 9e41cd510cf516d834221bde606d8345c9065179 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 4 Aug 2023 23:27:52 +0200 Subject: [PATCH 01/11] add IBC e2e test with Hermes --- tests/src/e2e/helpers.rs | 108 +++++++++++ tests/src/e2e/ibc_tests.rs | 355 ++++++++++++++++++++++++++----------- tests/src/e2e/setup.rs | 89 +++++++++- 3 files changed, 452 insertions(+), 100 deletions(-) diff --git a/tests/src/e2e/helpers.rs b/tests/src/e2e/helpers.rs index 0e33d9cc87..9a6f30eda2 100644 --- a/tests/src/e2e/helpers.rs +++ b/tests/src/e2e/helpers.rs @@ -1,6 +1,8 @@ //! E2E test helpers +use std::fs::File; use std::future::Future; +use std::io::Write; use std::path::Path; use std::process::Command; use std::str::FromStr; @@ -26,6 +28,7 @@ use namada_apps::config::{Config, TendermintMode}; use namada_core::types::token::NATIVE_MAX_DECIMAL_PLACES; use namada_sdk::wallet::fs::FsWalletUtils; use namada_sdk::wallet::Wallet; +use toml::Value; use super::setup::{ self, sleep, NamadaBgCmd, NamadaCmd, Test, ENV_VAR_DEBUG, @@ -504,3 +507,108 @@ pub fn wait_for_wasm_pre_compile(ledger: &mut NamadaCmd) -> Result<()> { pub fn epochs_per_year_from_min_duration(min_duration: u64) -> u64 { 60 * 60 * 24 * 365 / min_duration } + +/// Make a Hermes config +pub fn make_hermes_config(test_a: &Test, test_b: &Test) -> Result<()> { + let mut config = toml::map::Map::new(); + + let mut global = toml::map::Map::new(); + global.insert("log_level".to_owned(), Value::String("debug".to_owned())); + config.insert("global".to_owned(), Value::Table(global)); + + let mut mode = toml::map::Map::new(); + let mut clients = toml::map::Map::new(); + clients.insert("enabled".to_owned(), Value::Boolean(true)); + clients.insert("refresh".to_owned(), Value::Boolean(true)); + clients.insert("misbehaviour".to_owned(), Value::Boolean(true)); + mode.insert("clients".to_owned(), Value::Table(clients)); + + let mut connections = toml::map::Map::new(); + connections.insert("enabled".to_owned(), Value::Boolean(false)); + mode.insert("connections".to_owned(), Value::Table(connections)); + + let mut channels = toml::map::Map::new(); + channels.insert("enabled".to_owned(), Value::Boolean(false)); + mode.insert("channels".to_owned(), Value::Table(channels)); + + let mut packets = toml::map::Map::new(); + packets.insert("enabled".to_owned(), Value::Boolean(true)); + packets.insert("clear_interval".to_owned(), Value::Integer(10)); + packets.insert("clear_on_start".to_owned(), Value::Boolean(false)); + packets.insert("tx_confirmation".to_owned(), Value::Boolean(true)); + mode.insert("packets".to_owned(), Value::Table(packets)); + + config.insert("mode".to_owned(), Value::Table(mode)); + + let mut telemetry = toml::map::Map::new(); + telemetry.insert("enabled".to_owned(), Value::Boolean(false)); + telemetry.insert("host".to_owned(), Value::String("127.0.0.1".to_owned())); + telemetry.insert("port".to_owned(), Value::Integer(3001)); + config.insert("telemetry".to_owned(), Value::Table(telemetry)); + + let chains = vec![ + make_hermes_chain_config(test_a), + make_hermes_chain_config(test_b), + ]; + + config.insert("chains".to_owned(), Value::Array(chains)); + + let toml_string = toml::to_string(&Value::Table(config)).unwrap(); + let hermes_dir = test_a.test_dir.as_ref().join("hermes"); + std::fs::create_dir_all(&hermes_dir).unwrap(); + let config_path = hermes_dir.join("config.toml"); + let mut file = File::create(config_path).unwrap(); + file.write_all(toml_string.as_bytes()).map_err(|e| { + eyre!(format!("Writing a Hermes config failed: {}", e,)) + })?; + // One Hermes config.toml is OK, but add one more config.toml to execute + // Hermes from test_b + let hermes_dir = test_b.test_dir.as_ref().join("hermes"); + std::fs::create_dir_all(&hermes_dir).unwrap(); + let config_path = hermes_dir.join("config.toml"); + let mut file = File::create(config_path).unwrap(); + file.write_all(toml_string.as_bytes()).map_err(|e| { + eyre!(format!("Writing a Hermes config failed: {}", e,)) + })?; + + Ok(()) +} + +fn make_hermes_chain_config(test: &Test) -> Value { + let chain_id = test.net.chain_id.as_str(); + let rpc_addr = get_actor_rpc(test, &Who::Validator(0)); + + let mut table = toml::map::Map::new(); + table.insert("mode".to_owned(), Value::String("push".to_owned())); + let url = format!("ws://{}/websocket", rpc_addr); + table.insert("url".to_owned(), Value::String(url)); + table.insert("batch_delay".to_owned(), Value::String("500ms".to_owned())); + let event_source = Value::Table(table); + + let mut chain = toml::map::Map::new(); + chain.insert("id".to_owned(), Value::String(chain_id.to_owned())); + chain.insert("type".to_owned(), Value::String("Namada".to_owned())); + chain.insert( + "rpc_addr".to_owned(), + Value::String(format!("http://{rpc_addr}")), + ); + // The grpc isn't used for Namada, but it's required + chain.insert( + "grpc_addr".to_owned(), + Value::String("http://127.0.0.1:9090".to_owned()), + ); + chain.insert("event_source".to_owned(), event_source); + chain.insert("account_prefix".to_owned(), Value::String("".to_owned())); + chain.insert( + "key_name".to_owned(), + Value::String(setup::constants::CHRISTEL_KEY.to_owned()), + ); + chain.insert("store_prefix".to_owned(), Value::String("ibc".to_owned())); + let mut table = toml::map::Map::new(); + table.insert("price".to_owned(), Value::Float(0.001)); + let nam_addr = find_address(test, setup::constants::NAM).unwrap(); + table.insert("denom".to_owned(), Value::String(nam_addr.to_string())); + chain.insert("gas_price".to_owned(), Value::Table(table)); + + Value::Table(chain) +} diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index d0a3ae4638..37e22daa7f 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -86,7 +86,7 @@ use crate::e2e::helpers::{ find_address, get_actor_rpc, get_validator_pk, wait_for_wasm_pre_compile, }; use crate::e2e::setup::{ - self, sleep, working_dir, Bin, NamadaCmd, Test, TestDir, Who, + self, run_hermes_cmd, setup_hermes, sleep, Bin, NamadaCmd, Test, Who, }; use crate::strings::{ LEDGER_STARTED, TX_ACCEPTED, TX_APPLIED_SUCCESS, TX_FAILED, VALIDATOR_NODE, @@ -95,51 +95,10 @@ use crate::{run, run_as}; #[test] fn run_ledger_ibc() -> Result<()> { - let (test_a, test_b) = setup_two_single_node_nets()?; - set_ethereum_bridge_mode( - &test_a, - &test_a.net.chain_id, - Who::Validator(0), - ethereum_bridge::ledger::Mode::Off, - None, - ); - set_ethereum_bridge_mode( - &test_b, - &test_b.net.chain_id, - Who::Validator(0), - ethereum_bridge::ledger::Mode::Off, - None, - ); - - // Run Chain A - let mut ledger_a = run_as!( - test_a, - Who::Validator(0), - Bin::Node, - &["ledger", "run"], - Some(40) - )?; - ledger_a.exp_string(LEDGER_STARTED)?; - // Run Chain B - let mut ledger_b = run_as!( - test_b, - Who::Validator(0), - Bin::Node, - &["ledger", "run"], - Some(40) - )?; - ledger_b.exp_string(LEDGER_STARTED)?; - ledger_a.exp_string(VALIDATOR_NODE)?; - ledger_b.exp_string(VALIDATOR_NODE)?; - - wait_for_wasm_pre_compile(&mut ledger_a)?; - wait_for_wasm_pre_compile(&mut ledger_b)?; - + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets()?; let _bg_ledger_a = ledger_a.background(); let _bg_ledger_b = ledger_b.background(); - sleep(5); - let (client_id_a, client_id_b) = create_client(&test_a, &test_b)?; let (conn_id_a, conn_id_b) = @@ -170,9 +129,8 @@ fn run_ledger_ibc() -> Result<()> { try_invalid_transfers(&test_a, &test_b, &port_id_a, &channel_id_a)?; // Transfer 50000 received over IBC on Chain B - let token = format!("{port_id_b}/{channel_id_b}/nam"); - transfer_on_chain(&test_b, BERTHA, ALBERT, token, 50000, BERTHA_KEY)?; - check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_b)?; + transfer_received_token(&port_id_b, &channel_id_b, &test_a, &test_b)?; + check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_a, &test_b)?; // Transfer 50000 back from the origin-specific account on Chain B to Chain // A @@ -215,6 +173,142 @@ fn run_ledger_ibc() -> Result<()> { Ok(()) } +#[test] +fn run_ledger_ibc_with_hermes() -> Result<()> { + let (ledger_a, ledger_b, test_a, test_b) = run_two_nets()?; + let _bg_ledger_a = ledger_a.background(); + let _bg_ledger_b = ledger_b.background(); + + setup_hermes(&test_a, &test_b)?; + let port_id_a = "transfer".parse().unwrap(); + let port_id_b = "transfer".parse().unwrap(); + let (channel_id_a, channel_id_b) = + create_channel_with_hermes(&test_a, &test_b)?; + + // Start relaying + let hermes = run_hermes(&test_a)?; + let _bg_hermes = hermes.background(); + + // Transfer 100000 from the normal account on Chain A to Chain B + let receiver = find_address(&test_b, BERTHA)?; + transfer( + &test_a, + ALBERT, + receiver.to_string(), + NAM, + "100000", + ALBERT_KEY, + &port_id_a, + &channel_id_a, + None, + None, + None, + false, + )?; + wait_for_packet_relay(&port_id_a, &channel_id_a, &test_a)?; + check_balances(&port_id_b, &channel_id_b, &test_a, &test_b)?; + + // Transfer 50000 received over IBC on Chain B + transfer_received_token(&port_id_b, &channel_id_b, &test_a, &test_b)?; + check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_a, &test_b)?; + + // Transfer 50000 back from the origin-specific account on Chain B to Chain + // A + let receiver = find_address(&test_a, ALBERT)?; + // Chain A was the source for the sent token + let org_token_addr = find_address(&test_a, NAM)?.to_string(); + let ibc_denom = format!("{port_id_b}/{channel_id_b}/{org_token_addr}"); + // Send a token from Chain B + transfer( + &test_b, + BERTHA, + receiver.to_string(), + ibc_denom, + "50000", + BERTHA_KEY, + &port_id_b, + &channel_id_b, + None, + None, + None, + false, + )?; + wait_for_packet_relay(&port_id_a, &channel_id_a, &test_a)?; + check_balances_after_back(&port_id_b, &channel_id_b, &test_a, &test_b)?; + + // Transfer a token and it will time out and refund + let receiver = find_address(&test_b, BERTHA)?; + // Send a token from Chain A + transfer( + &test_a, + ALBERT, + receiver.to_string(), + NAM, + "100000", + ALBERT_KEY, + &port_id_a, + &channel_id_a, + None, + Some(Duration::new(0, 0)), + None, + false, + )?; + // wait for the timeout and the refund + wait_for_packet_relay(&port_id_a, &channel_id_a, &test_a)?; + // The balance should not be changed + check_balances_after_back(&port_id_b, &channel_id_b, &test_a, &test_b)?; + + Ok(()) +} + +fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { + let (test_a, test_b) = setup_two_single_node_nets()?; + set_ethereum_bridge_mode( + &test_a, + &test_a.net.chain_id, + Who::Validator(0), + ethereum_bridge::ledger::Mode::Off, + None, + ); + set_ethereum_bridge_mode( + &test_b, + &test_b.net.chain_id, + Who::Validator(0), + ethereum_bridge::ledger::Mode::Off, + None, + ); + + // Run Chain A + let mut ledger_a = run_as!( + test_a, + Who::Validator(0), + Bin::Node, + &["ledger", "run"], + Some(40) + )?; + ledger_a.exp_string(LEDGER_STARTED)?; + // Run Chain B + let mut ledger_b = run_as!( + test_b, + Who::Validator(0), + Bin::Node, + &["ledger", "run"], + Some(40) + )?; + ledger_b.exp_string(LEDGER_STARTED)?; + ledger_a.exp_string(VALIDATOR_NODE)?; + ledger_b.exp_string(VALIDATOR_NODE)?; + + wait_for_wasm_pre_compile(&mut ledger_a)?; + wait_for_wasm_pre_compile(&mut ledger_b)?; + + // Wait for a first block + ledger_a.exp_string("Committed block hash")?; + ledger_b.exp_string("Committed block hash")?; + + Ok((ledger_a, ledger_b, test_a, test_b)) +} + /// Set up two Namada chains to talk to each other via IBC. fn setup_two_single_node_nets() -> Result<(Test, Test)> { const ANOTHER_PROXY_APP: u16 = 27659u16; @@ -229,42 +323,14 @@ fn setup_two_single_node_nets() -> Result<(Test, Test)> { setup::set_validators(1, genesis, base_dir, |_| 0) }; let test_a = setup::network(update_genesis, None)?; - let test_b = Test { - working_dir: working_dir(), - test_dir: TestDir::new(), - net: test_a.net.clone(), - async_runtime: Default::default(), - }; - for entry in std::fs::read_dir(test_a.test_dir.path()).unwrap() { - let entry = entry.unwrap(); - if entry.path().is_dir() { - copy_dir::copy_dir( - entry.path(), - test_b.test_dir.path().join(entry.file_name()), - ) - .map_err(|e| { - eyre!( - "Failed copying directory from test_a to test_b with {}", - e - ) - })?; - } else { - std::fs::copy( - entry.path(), - test_b.test_dir.path().join(entry.file_name()), - ) - .map_err(|e| { - eyre!("Failed copying file from test_a to test_b with {}", e) - })?; - } - } + let test_b = setup::network(update_genesis, None)?; let genesis_b_dir = test_b .test_dir .path() .join(namada_apps::client::utils::NET_ACCOUNTS_DIR) .join("validator-0"); let mut genesis_b = chain::Finalized::read_toml_files( - &genesis_b_dir.join(test_a.net.chain_id.as_str()), + &genesis_b_dir.join(test_b.net.chain_id.as_str()), ) .map_err(|_| eyre!("Could not read genesis files from test b"))?; // chain b's validator needs to listen on a different port than chain a's @@ -298,12 +364,12 @@ fn setup_two_single_node_nets() -> Result<(Test, Test)> { + setup::ANOTHER_CHAIN_PORT_OFFSET; validator_tx.tx.data.net_address.set_port(new_port); genesis_b - .write_toml_files(&genesis_b_dir.join(test_a.net.chain_id.as_str())) + .write_toml_files(&genesis_b_dir.join(test_b.net.chain_id.as_str())) .map_err(|_| eyre!("Could not write genesis toml files for test_b"))?; // modify chain b to use different ports for cometbft let mut config = namada_apps::config::Config::load( &genesis_b_dir, - &test_a.net.chain_id, + &test_b.net.chain_id, Some(TendermintMode::Validator), ); let proxy_app = &mut config.ledger.cometbft.proxy_app; @@ -313,13 +379,95 @@ fn setup_two_single_node_nets() -> Result<(Test, Test)> { let p2p_addr = &mut config.ledger.cometbft.p2p.laddr; set_port(p2p_addr, ANOTHER_P2P); config - .write(&genesis_b_dir, &test_a.net.chain_id, true) + .write(&genesis_b_dir, &test_b.net.chain_id, true) .map_err(|e| { eyre!("Unable to modify chain b's config file due to {}", e) })?; Ok((test_a, test_b)) } +fn create_channel_with_hermes( + test_a: &Test, + test_b: &Test, +) -> Result<(ChannelId, ChannelId)> { + let args = [ + "create", + "channel", + "--a-chain", + &test_a.net.chain_id.to_string(), + "--b-chain", + &test_b.net.chain_id.to_string(), + "--a-port", + "transfer", + "--b-port", + "transfer", + "--new-client-connection", + "--yes", + ]; + + let mut hermes = run_hermes_cmd(test_a, args, Some(120))?; + let (channel_id_a, channel_id_b) = + get_channel_ids_from_hermes_output(&mut hermes)?; + hermes.assert_success(); + + Ok((channel_id_a, channel_id_b)) +} + +fn get_channel_ids_from_hermes_output( + hermes: &mut NamadaCmd, +) -> Result<(ChannelId, ChannelId)> { + let (_, matched) = + hermes.exp_regex("channel handshake already finished .*")?; + + let regex = regex::Regex::new(r"channel-[0-9]+").unwrap(); + let mut iter = regex.find_iter(&matched); + let channel_id_a = iter.next().unwrap().as_str().parse().unwrap(); + let channel_id_b = iter.next().unwrap().as_str().parse().unwrap(); + + Ok((channel_id_a, channel_id_b)) +} + +fn run_hermes(test: &Test) -> Result { + let args = ["start"]; + let mut hermes = run_hermes_cmd(test, args, Some(40))?; + hermes.exp_string("Hermes has started")?; + Ok(hermes) +} + +fn wait_for_packet_relay( + port_id: &PortId, + channel_id: &ChannelId, + test: &Test, +) -> Result<()> { + let args = [ + "--json", + "query", + "packet", + "pending", + "--chain", + test.net.chain_id.as_str(), + "--port", + port_id.as_str(), + "--channel", + channel_id.as_str(), + ]; + for _ in 0..10 { + sleep(10); + let mut hermes = run_hermes_cmd(test, args, Some(40))?; + // Check no pending packet + if hermes + .exp_string( + "\"dst\":{\"unreceived_acks\":[],\"unreceived_packets\":[]},\"\ + src\":{\"unreceived_acks\":[],\"unreceived_packets\":[]}", + ) + .is_ok() + { + return Ok(()); + } + } + Err(eyre!("Pending packet is still left")) +} + 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); @@ -907,7 +1055,8 @@ fn transfer_back( let receiver = find_address(test_a, ALBERT)?; // Chain A was the source for the sent token - let ibc_denom = format!("{port_id_b}/{channel_id_b}/nam"); + let org_nam_addr = find_address(test_a, NAM).unwrap(); + let ibc_denom = format!("{port_id_b}/{channel_id_b}/{org_nam_addr}"); // Send a token from Chain B let height = transfer( test_b, @@ -1436,12 +1585,13 @@ fn check_balances( client.assert_success(); // Check the balance on Chain B - let trace_path = format!("{}/{}", &dest_port_id, &dest_channel_id); + let org_nam_addr = find_address(test_a, NAM).unwrap(); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_nam_addr}"); let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); let query_args = vec![ - "balance", "--owner", BERTHA, "--token", NAM, "--node", &rpc_b, + "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc_b, ]; - let expected = format!("{}/nam: 100000", trace_path); + let expected = format!("{ibc_denom}: 100000"); let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; client.exp_string(&expected)?; client.assert_success(); @@ -1452,25 +1602,29 @@ fn check_balances( fn check_balances_after_non_ibc( port_id: &PortId, channel_id: &ChannelId, - test: &Test, + test_a: &Test, + test_b: &Test, ) -> Result<()> { // Check the balance on Chain B - let trace_path = format!("{}/{}", port_id, channel_id); + let org_nam_addr = find_address(test_a, NAM).unwrap(); + let ibc_denom = format!("{port_id}/{channel_id}/{org_nam_addr}"); // Check the source - let rpc = get_actor_rpc(test, Who::Validator(0)); - let query_args = - vec!["balance", "--owner", BERTHA, "--token", NAM, "--node", &rpc]; - let expected = format!("{}/nam: 50000", trace_path); - let mut client = run!(test, Bin::Client, query_args, Some(40))?; + let rpc = get_actor_rpc(test_b, Who::Validator(0)); + let query_args = vec![ + "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc, + ]; + let expected = format!("{ibc_denom}: 50000"); + let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; client.exp_string(&expected)?; client.assert_success(); - // Check the target - let query_args = - vec!["balance", "--owner", ALBERT, "--token", NAM, "--node", &rpc]; - let expected = format!("{}/nam: 50000", trace_path); - let mut client = run!(test, Bin::Client, query_args, Some(40))?; + // Check the traget + let query_args = vec![ + "balance", "--owner", ALBERT, "--token", &ibc_denom, "--node", &rpc, + ]; + let expected = format!("{ibc_denom}: 50000"); + let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; client.exp_string(&expected)?; client.assert_success(); @@ -1503,12 +1657,13 @@ fn check_balances_after_back( client.assert_success(); // Check the balance on Chain B - let trace_path = format!("{}/{}", dest_port_id, dest_channel_id); + let org_nam_addr = find_address(test_a, NAM).unwrap(); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_nam_addr}"); let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); let query_args = vec![ - "balance", "--owner", BERTHA, "--token", NAM, "--node", &rpc_b, + "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc_b, ]; - let expected = format!("{}/nam: 0", trace_path); + let expected = format!("{ibc_denom}: 0"); let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; client.exp_string(&expected)?; client.assert_success(); @@ -1522,6 +1677,8 @@ fn check_shielded_balances( test_a: &Test, test_b: &Test, ) -> Result<()> { + let org_btc_addr = find_address(test_a, BTC).unwrap().to_string(); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_btc_addr}"); // Check the balance on Chain B let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); // PA(B) on Chain B has received BTC on chain A @@ -1536,7 +1693,7 @@ fn check_shielded_balances( "--node", &rpc_b, ]; - let expected = format!("{}/{}/btc: 10", dest_port_id, dest_channel_id); + let expected = format!("{ibc_denom}: 10"); let mut client = run!(test_b, Bin::Client, query_args, Some(40))?; client.exp_string(&expected)?; client.assert_success(); diff --git a/tests/src/e2e/setup.rs b/tests/src/e2e/setup.rs index 1db62a2fe1..9ee353eda0 100644 --- a/tests/src/e2e/setup.rs +++ b/tests/src/e2e/setup.rs @@ -39,7 +39,7 @@ use rand::Rng; use serde_json; use tempfile::{tempdir, tempdir_in, TempDir}; -use crate::e2e::helpers::generate_bin_command; +use crate::e2e::helpers::{generate_bin_command, make_hermes_config}; /// For `color_eyre::install`, which fails if called more than once in the same /// process @@ -1141,6 +1141,93 @@ pub fn sleep(seconds: u64) { thread::sleep(time::Duration::from_secs(seconds)); } +pub fn setup_hermes(test_a: &Test, test_b: &Test) -> Result<()> { + println!("\n{}", "Setting up Hermes".underline().green(),); + + make_hermes_config(test_a, test_b)?; + + for test in [test_a, test_b] { + let chain_id = test.net.chain_id.as_str(); + let chain_dir = test.test_dir.as_ref().join(chain_id); + let wallet = wallet::wallet_file(chain_dir); + let args = [ + "keys", + "add", + "--chain", + chain_id, + "--key-file", + &wallet.to_string_lossy(), + ]; + let mut hermes = run_hermes_cmd(test, args, Some(10))?; + hermes.assert_success(); + } + + Ok(()) +} + +pub fn run_hermes_cmd( + test: &Test, + args: I, + timeout_sec: Option, +) -> Result +where + I: IntoIterator, + S: AsRef, +{ + let mut run_cmd = Command::new("hermes"); + let hermes_dir = test.test_dir.as_ref().join("hermes"); + run_cmd.current_dir(hermes_dir.clone()); + let config_path = hermes_dir.join("config.toml"); + run_cmd.args(["--config", &config_path.to_string_lossy()]); + run_cmd.args(args); + + let args: String = + run_cmd.get_args().map(|s| s.to_string_lossy()).join(" "); + let cmd_str = + format!("{} {}", run_cmd.get_program().to_string_lossy(), args); + + let session = Session::spawn(run_cmd).map_err(|e| { + eyre!( + "\n\n{}: {}\n{}: {}", + "Failed to run Hermes".underline().red(), + cmd_str, + "Error".underline().red(), + e + ) + })?; + + let log_path = { + let mut rng = rand::thread_rng(); + let log_dir = test.get_base_dir(&Who::NonValidator).join("logs"); + std::fs::create_dir_all(&log_dir)?; + log_dir.join(format!( + "{}-hermes-{}.log", + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_micros(), + rng.gen::() + )) + }; + let logger = OpenOptions::new() + .write(true) + .create_new(true) + .open(&log_path)?; + let mut session = expectrl::session::log(session, logger).unwrap(); + + session.set_expect_timeout(timeout_sec.map(std::time::Duration::from_secs)); + + let cmd_process = NamadaCmd { + session, + cmd_str, + log_path, + }; + + println!("{}:\n{}", "> Running".underline().green(), &cmd_process); + + Ok(cmd_process) +} + #[allow(dead_code)] pub mod constants { // Paths to the WASMs used for tests From d8a3da6ba3f5a3688397110c0acd90014dd85804 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 9 Aug 2023 13:09:31 +0200 Subject: [PATCH 02/11] CI runs IBC e2e test with Hermes --- .github/workflows/scripts/e2e.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 8817c9b6d7..097db9ab0e 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -1,6 +1,7 @@ { "e2e::eth_bridge_tests::everything": 4, "e2e::ibc_tests::run_ledger_ibc": 155, + "e2e::ibc_tests::run_ledger_ibc_with_hermes": 130, "e2e::eth_bridge_tests::test_add_to_bridge_pool": 10, "e2e::ledger_tests::double_signing_gets_slashed": 12, "e2e::ledger_tests::invalid_transactions": 13, @@ -32,4 +33,4 @@ "e2e::wallet_tests::wallet_encrypted_key_cmds": 1, "e2e::wallet_tests::wallet_encrypted_key_cmds_env_var": 1, "e2e::wallet_tests::wallet_unencrypted_key_cmds": 1 -} \ No newline at end of file +} From 6946d3429e58646f2f0a2f467cc2149afa6fd9e8 Mon Sep 17 00:00:00 2001 From: yito88 Date: Wed, 9 Aug 2023 20:54:22 +0200 Subject: [PATCH 03/11] fix e2e script --- .github/workflows/scripts/schedule-e2e.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scripts/schedule-e2e.py b/.github/workflows/scripts/schedule-e2e.py index d174fb4c75..b207377e40 100644 --- a/.github/workflows/scripts/schedule-e2e.py +++ b/.github/workflows/scripts/schedule-e2e.py @@ -8,7 +8,7 @@ NIGHTLY_VERSION = open("rust-nightly-version", "r").read().strip() E2E_FILE = ".github/workflows/scripts/e2e.json" -CARGO_TEST_COMMAND = "cargo +{} test {} -- --test-threads=1 --nocapture" +CARGO_TEST_COMMAND = "cargo +{} test {} -- --test-threads=1 --nocapture --exact" MACHINES = [{'tasks': [], 'time': [], 'total_time': 0} for _ in range(N_OF_MACHINES)] @@ -73,4 +73,4 @@ def find_freer_machine(): print(" Run locally with: {}".format(test_command)) if has_failures: - exit(1) \ No newline at end of file + exit(1) From 289533f9fa3c7dd5a492515ea7d7aa6dd1eea91e Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 10 Aug 2023 12:30:16 +0200 Subject: [PATCH 04/11] fix waiting for the second block --- tests/src/e2e/ibc_tests.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index 37e22daa7f..5813f9286c 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -82,9 +82,7 @@ use setup::constants::*; use tendermint_light_client::components::io::{Io, ProdIo as TmLightClientIo}; use super::setup::set_ethereum_bridge_mode; -use crate::e2e::helpers::{ - find_address, get_actor_rpc, get_validator_pk, wait_for_wasm_pre_compile, -}; +use crate::e2e::helpers::{find_address, get_actor_rpc, get_validator_pk}; use crate::e2e::setup::{ self, run_hermes_cmd, setup_hermes, sleep, Bin, NamadaCmd, Test, Who, }; @@ -299,8 +297,9 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { ledger_a.exp_string(VALIDATOR_NODE)?; ledger_b.exp_string(VALIDATOR_NODE)?; - wait_for_wasm_pre_compile(&mut ledger_a)?; - wait_for_wasm_pre_compile(&mut ledger_b)?; + // wait for the first block + ledger_a.exp_regex("Committed block .* height: 2")?; + ledger_b.exp_regex("Committed block .* height: 2")?; // Wait for a first block ledger_a.exp_string("Committed block hash")?; From 5bbe33467ad725c88909e3254b6c2311f60e01ca Mon Sep 17 00:00:00 2001 From: yito88 Date: Tue, 15 Aug 2023 15:20:10 +0200 Subject: [PATCH 05/11] for clippy --- tests/src/e2e/ibc_tests.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index 5813f9286c..bb8437af10 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -82,7 +82,9 @@ use setup::constants::*; use tendermint_light_client::components::io::{Io, ProdIo as TmLightClientIo}; use super::setup::set_ethereum_bridge_mode; -use crate::e2e::helpers::{find_address, get_actor_rpc, get_validator_pk}; +use crate::e2e::helpers::{ + find_address, get_actor_rpc, get_validator_pk, wait_for_wasm_pre_compile, +}; use crate::e2e::setup::{ self, run_hermes_cmd, setup_hermes, sleep, Bin, NamadaCmd, Test, Who, }; @@ -297,6 +299,9 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { ledger_a.exp_string(VALIDATOR_NODE)?; ledger_b.exp_string(VALIDATOR_NODE)?; + wait_for_wasm_pre_compile(&mut ledger_a)?; + wait_for_wasm_pre_compile(&mut ledger_b)?; + // wait for the first block ledger_a.exp_regex("Committed block .* height: 2")?; ledger_b.exp_regex("Committed block .* height: 2")?; From 1cd28b863de9eb10864b658a6fb1bcacdacb8559 Mon Sep 17 00:00:00 2001 From: yito88 Date: Tue, 15 Aug 2023 15:45:18 +0200 Subject: [PATCH 06/11] wait for compiling --- tests/src/e2e/ibc_tests.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index bb8437af10..37e22daa7f 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -302,10 +302,6 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { wait_for_wasm_pre_compile(&mut ledger_a)?; wait_for_wasm_pre_compile(&mut ledger_b)?; - // wait for the first block - ledger_a.exp_regex("Committed block .* height: 2")?; - ledger_b.exp_regex("Committed block .* height: 2")?; - // Wait for a first block ledger_a.exp_string("Committed block hash")?; ledger_b.exp_string("Committed block hash")?; From 318e313333a767c0c11e8f282bd474f2245f73da Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 23 Nov 2023 23:27:01 +0100 Subject: [PATCH 07/11] add sleep --- tests/src/e2e/ibc_tests.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index 37e22daa7f..f8f631698f 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -302,9 +302,7 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { wait_for_wasm_pre_compile(&mut ledger_a)?; wait_for_wasm_pre_compile(&mut ledger_b)?; - // Wait for a first block - ledger_a.exp_string("Committed block hash")?; - ledger_b.exp_string("Committed block hash")?; + sleep(5); Ok((ledger_a, ledger_b, test_a, test_b)) } From 38406f7a10e9e6ee152993b9de7293330a94dda2 Mon Sep 17 00:00:00 2001 From: yito88 Date: Thu, 30 Nov 2023 11:05:24 +0100 Subject: [PATCH 08/11] build hermes in CI --- .github/workflows/build-and-test.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index b470c58d66..2984e05883 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -648,11 +648,18 @@ jobs: curl -o cometbft.tar.gz -LO https://github.com/cometbft/cometbft/releases/download/v${{ matrix.comet_bft }}/cometbft_${{ matrix.comet_bft }}_linux_amd64.tar.gz tar -xvzf cometbft.tar.gz mv cometbft /usr/local/bin - - name: Download Hermes + - name: Clone Hermes repo + uses: actions/checkout@v4 + with: + repository: https://github.com/heliaxdev/hermes + ref: ${{ matrix.hermes }} + path: hermes + - name: Build Hermes run: | - curl -o hermes.tar.gz -LO https://github.com/heliaxdev/hermes/releases/download/v${{ matrix.hermes }}/hermes-v${{ matrix.hermes }}-x86_64-unknown-linux-gnu.tar.gz - tar -xvzf hermes.tar.gz - mv hermes /usr/local/bin + cd hermes + sed -i 's|git = "https://github.com/anoma/namada"\ntag = .*|# git = "https://github.com/anoma/namada"\npath = "../../../sdk"|' crates/relayer/Cargo.toml + cargo build --bin hermes + cp target/debug/hermes /usr/local/bin - name: Change permissions run: | chmod +x target/release/namada From c0a1cae68c6e403ee1ed7752cf04dd36d7760753 Mon Sep 17 00:00:00 2001 From: yito88 Date: Fri, 8 Dec 2023 23:53:52 +0100 Subject: [PATCH 09/11] set chain ID --- tests/src/e2e/helpers.rs | 4 +- tests/src/e2e/ibc_tests.rs | 73 +++++++++++++++++++---------------- tests/src/e2e/ledger_tests.rs | 2 +- tests/src/e2e/setup.rs | 2 +- 4 files changed, 45 insertions(+), 36 deletions(-) diff --git a/tests/src/e2e/helpers.rs b/tests/src/e2e/helpers.rs index 9a6f30eda2..6d75ea2829 100644 --- a/tests/src/e2e/helpers.rs +++ b/tests/src/e2e/helpers.rs @@ -21,6 +21,7 @@ use namada::types::address::Address; use namada::types::key::*; use namada::types::storage::Epoch; use namada::types::token; +use namada_apps::cli::context::ENV_VAR_CHAIN_ID; use namada_apps::config::genesis::chain::DeriveEstablishedAddress; use namada_apps::config::genesis::templates; use namada_apps::config::utils::convert_tm_addr_to_socket_addr; @@ -576,7 +577,7 @@ pub fn make_hermes_config(test_a: &Test, test_b: &Test) -> Result<()> { fn make_hermes_chain_config(test: &Test) -> Value { let chain_id = test.net.chain_id.as_str(); - let rpc_addr = get_actor_rpc(test, &Who::Validator(0)); + let rpc_addr = get_actor_rpc(test, Who::Validator(0)); let mut table = toml::map::Map::new(); table.insert("mode".to_owned(), Value::String("push".to_owned())); @@ -606,6 +607,7 @@ fn make_hermes_chain_config(test: &Test) -> Value { chain.insert("store_prefix".to_owned(), Value::String("ibc".to_owned())); let mut table = toml::map::Map::new(); table.insert("price".to_owned(), Value::Float(0.001)); + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let nam_addr = find_address(test, setup::constants::NAM).unwrap(); table.insert("denom".to_owned(), Value::String(nam_addr.to_string())); chain.insert("gas_price".to_owned(), Value::Table(table)); diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index f8f631698f..be9762591a 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -64,6 +64,7 @@ use namada::types::address::{Address, InternalAddress}; use namada::types::key::PublicKey; use namada::types::storage::{BlockHeight, Key}; use namada::types::token::Amount; +use namada_apps::cli::context::ENV_VAR_CHAIN_ID; use namada_apps::client::rpc::{ query_pos_parameters, query_storage_value, query_storage_value_bytes, }; @@ -129,8 +130,9 @@ fn run_ledger_ibc() -> Result<()> { try_invalid_transfers(&test_a, &test_b, &port_id_a, &channel_id_a)?; // Transfer 50000 received over IBC on Chain B - transfer_received_token(&port_id_b, &channel_id_b, &test_a, &test_b)?; - check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_a, &test_b)?; + let token = format!("{port_id_b}/{channel_id_b}/nam"); + transfer_on_chain(&test_b, BERTHA, ALBERT, token, 50000, BERTHA_KEY)?; + check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_b)?; // Transfer 50000 back from the origin-specific account on Chain B to Chain // A @@ -190,6 +192,7 @@ fn run_ledger_ibc_with_hermes() -> Result<()> { let _bg_hermes = hermes.background(); // Transfer 100000 from the normal account on Chain A to Chain B + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let receiver = find_address(&test_b, BERTHA)?; transfer( &test_a, @@ -209,15 +212,16 @@ fn run_ledger_ibc_with_hermes() -> Result<()> { check_balances(&port_id_b, &channel_id_b, &test_a, &test_b)?; // Transfer 50000 received over IBC on Chain B - transfer_received_token(&port_id_b, &channel_id_b, &test_a, &test_b)?; - check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_a, &test_b)?; + let token = format!("{port_id_b}/{channel_id_b}/nam"); + transfer_on_chain(&test_b, BERTHA, ALBERT, token, 50000, BERTHA_KEY)?; + check_balances_after_non_ibc(&port_id_b, &channel_id_b, &test_b)?; // Transfer 50000 back from the origin-specific account on Chain B to Chain // A + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); let receiver = find_address(&test_a, ALBERT)?; // Chain A was the source for the sent token - let org_token_addr = find_address(&test_a, NAM)?.to_string(); - let ibc_denom = format!("{port_id_b}/{channel_id_b}/{org_token_addr}"); + let ibc_denom = format!("{port_id_b}/{channel_id_b}/nam"); // Send a token from Chain B transfer( &test_b, @@ -237,6 +241,7 @@ fn run_ledger_ibc_with_hermes() -> Result<()> { check_balances_after_back(&port_id_b, &channel_id_b, &test_a, &test_b)?; // Transfer a token and it will time out and refund + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let receiver = find_address(&test_b, BERTHA)?; // Send a token from Chain A transfer( @@ -279,22 +284,14 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { ); // Run Chain A - let mut ledger_a = run_as!( - test_a, - Who::Validator(0), - Bin::Node, - &["ledger", "run"], - Some(40) - )?; + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); + let mut ledger_a = + run_as!(test_a, Who::Validator(0), Bin::Node, &["ledger"], Some(40))?; ledger_a.exp_string(LEDGER_STARTED)?; // Run Chain B - let mut ledger_b = run_as!( - test_b, - Who::Validator(0), - Bin::Node, - &["ledger", "run"], - Some(40) - )?; + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); + let mut ledger_b = + run_as!(test_b, Who::Validator(0), Bin::Node, &["ledger"], Some(40))?; ledger_b.exp_string(LEDGER_STARTED)?; ledger_a.exp_string(VALIDATOR_NODE)?; ledger_b.exp_string(VALIDATOR_NODE)?; @@ -891,6 +888,7 @@ fn transfer_token( channel_id_a: &ChannelId, ) -> Result<()> { // Send a token from Chain A + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let receiver = find_address(test_b, BERTHA)?; let height = transfer( test_a, @@ -956,6 +954,7 @@ fn try_invalid_transfers( port_id_a: &PortId, channel_id_a: &ChannelId, ) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let receiver = find_address(test_b, BERTHA)?; // invalid amount @@ -1017,6 +1016,7 @@ fn transfer_on_chain( amount: u64, signer: impl AsRef, ) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let rpc = get_actor_rpc(test, Who::Validator(0)); let tx_args = [ "transfer", @@ -1050,11 +1050,11 @@ fn transfer_back( port_id_b: &PortId, channel_id_b: &ChannelId, ) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); let receiver = find_address(test_a, ALBERT)?; // Chain A was the source for the sent token - let org_nam_addr = find_address(test_a, NAM).unwrap(); - let ibc_denom = format!("{port_id_b}/{channel_id_b}/{org_nam_addr}"); + let ibc_denom = format!("{port_id_b}/{channel_id_b}/nam"); // Send a token from Chain B let height = transfer( test_b, @@ -1114,6 +1114,7 @@ fn transfer_timeout( port_id_a: &PortId, channel_id_a: &ChannelId, ) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let receiver = find_address(test_b, BERTHA)?; // Send a token from Chain A @@ -1169,6 +1170,8 @@ fn shielded_transfer( // Get masp proof for the following IBC transfer from the destination chain // It will send 10 BTC from Chain A to PA(B) on Chain B let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); + // Chain B will receive Chain A's BTC + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); let output_folder = test_b.test_dir.path().to_string_lossy(); // PA(B) on Chain B will receive BTC on chain A let token_addr = find_address(test_a, BTC)?; @@ -1190,6 +1193,7 @@ fn shielded_transfer( "--node", &rpc_b, ]; + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let mut client = run!(test_b, Bin::Client, args, Some(120))?; let file_path = get_shielded_transfer_path(&mut client)?; client.assert_success(); @@ -1321,6 +1325,7 @@ fn submit_ibc_tx( signer: &str, wait_reveal_pk: bool, ) -> Result { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let data_path = test.test_dir.path().join("tx.data"); let data = make_ibc_data(message); std::fs::write(&data_path, data).expect("writing data failed"); @@ -1369,6 +1374,7 @@ fn transfer( expected_err: Option<&str>, wait_reveal_pk: bool, ) -> Result { + std::env::set_var(ENV_VAR_CHAIN_ID, test.net.chain_id.to_string()); let rpc = get_actor_rpc(test, Who::Validator(0)); let channel_id = channel_id.to_string(); @@ -1565,6 +1571,7 @@ fn check_balances( test_b: &Test, ) -> Result<()> { // Check the balances on Chain A + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); let rpc_a = get_actor_rpc(test_a, Who::Validator(0)); // Check the escrowed balance let escrow = Address::Internal(InternalAddress::Ibc).to_string(); @@ -1583,8 +1590,8 @@ fn check_balances( client.assert_success(); // Check the balance on Chain B - let org_nam_addr = find_address(test_a, NAM).unwrap(); - let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_nam_addr}"); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/nam"); + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); let query_args = vec![ "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc_b, @@ -1600,13 +1607,11 @@ fn check_balances( fn check_balances_after_non_ibc( port_id: &PortId, channel_id: &ChannelId, - test_a: &Test, test_b: &Test, ) -> Result<()> { + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); // Check the balance on Chain B - let org_nam_addr = find_address(test_a, NAM).unwrap(); - let ibc_denom = format!("{port_id}/{channel_id}/{org_nam_addr}"); - + let ibc_denom = format!("{port_id}/{channel_id}/nam"); // Check the source let rpc = get_actor_rpc(test_b, Who::Validator(0)); let query_args = vec![ @@ -1637,6 +1642,7 @@ fn check_balances_after_back( test_b: &Test, ) -> Result<()> { // Check the balances on Chain A + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); let rpc_a = get_actor_rpc(test_a, Who::Validator(0)); // Check the escrowed balance let escrow = Address::Internal(InternalAddress::Ibc).to_string(); @@ -1655,8 +1661,8 @@ fn check_balances_after_back( client.assert_success(); // Check the balance on Chain B - let org_nam_addr = find_address(test_a, NAM).unwrap(); - let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_nam_addr}"); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/nam"); + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); let query_args = vec![ "balance", "--owner", BERTHA, "--token", &ibc_denom, "--node", &rpc_b, @@ -1675,12 +1681,13 @@ fn check_shielded_balances( test_a: &Test, test_b: &Test, ) -> Result<()> { - let org_btc_addr = find_address(test_a, BTC).unwrap().to_string(); - let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/{org_btc_addr}"); // Check the balance on Chain B - let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); + std::env::set_var(ENV_VAR_CHAIN_ID, test_a.net.chain_id.to_string()); // PA(B) on Chain B has received BTC on chain A let token_addr = find_address(test_a, BTC)?.to_string(); + std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); + let rpc_b = get_actor_rpc(test_b, Who::Validator(0)); + let ibc_denom = format!("{dest_port_id}/{dest_channel_id}/btc"); let query_args = vec![ "balance", "--owner", diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index ca123601a1..ef275857d8 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -76,7 +76,7 @@ fn start_namada_ledger_node( Ok(node) } -fn start_namada_ledger_node_wait_wasm( +pub fn start_namada_ledger_node_wait_wasm( test: &Test, idx: Option, timeout_sec: Option, diff --git a/tests/src/e2e/setup.rs b/tests/src/e2e/setup.rs index 9ee353eda0..a29b09f4cc 100644 --- a/tests/src/e2e/setup.rs +++ b/tests/src/e2e/setup.rs @@ -1198,7 +1198,7 @@ where let log_path = { let mut rng = rand::thread_rng(); - let log_dir = test.get_base_dir(&Who::NonValidator).join("logs"); + let log_dir = test.get_base_dir(Who::NonValidator).join("logs"); std::fs::create_dir_all(&log_dir)?; log_dir.join(format!( "{}-hermes-{}.log", From 3fa1c5e768a3bb7ceb69efac07fc8b9ba71cd64a Mon Sep 17 00:00:00 2001 From: yito88 Date: Sat, 9 Dec 2023 00:01:06 +0100 Subject: [PATCH 10/11] add changelog --- .../unreleased/testing/773-ibc-e2e-hermes.md | 2 ++ .github/workflows/build-and-test.yml | 15 ++++----------- 2 files changed, 6 insertions(+), 11 deletions(-) create mode 100644 .changelog/unreleased/testing/773-ibc-e2e-hermes.md diff --git a/.changelog/unreleased/testing/773-ibc-e2e-hermes.md b/.changelog/unreleased/testing/773-ibc-e2e-hermes.md new file mode 100644 index 0000000000..13d55e0548 --- /dev/null +++ b/.changelog/unreleased/testing/773-ibc-e2e-hermes.md @@ -0,0 +1,2 @@ +- Add IBC E2E test with Hermes + ([\#773](https://github.com/anoma/namada/issues/773)) \ No newline at end of file diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 2984e05883..b470c58d66 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -648,18 +648,11 @@ jobs: curl -o cometbft.tar.gz -LO https://github.com/cometbft/cometbft/releases/download/v${{ matrix.comet_bft }}/cometbft_${{ matrix.comet_bft }}_linux_amd64.tar.gz tar -xvzf cometbft.tar.gz mv cometbft /usr/local/bin - - name: Clone Hermes repo - uses: actions/checkout@v4 - with: - repository: https://github.com/heliaxdev/hermes - ref: ${{ matrix.hermes }} - path: hermes - - name: Build Hermes + - name: Download Hermes run: | - cd hermes - sed -i 's|git = "https://github.com/anoma/namada"\ntag = .*|# git = "https://github.com/anoma/namada"\npath = "../../../sdk"|' crates/relayer/Cargo.toml - cargo build --bin hermes - cp target/debug/hermes /usr/local/bin + curl -o hermes.tar.gz -LO https://github.com/heliaxdev/hermes/releases/download/v${{ matrix.hermes }}/hermes-v${{ matrix.hermes }}-x86_64-unknown-linux-gnu.tar.gz + tar -xvzf hermes.tar.gz + mv hermes /usr/local/bin - name: Change permissions run: | chmod +x target/release/namada From 9a1c1b1ca4006c548086f1c6f0f990c89f9db795 Mon Sep 17 00:00:00 2001 From: yito88 Date: Mon, 11 Dec 2023 10:30:07 +0100 Subject: [PATCH 11/11] clean unneeded stuff --- tests/src/e2e/ibc_tests.rs | 2 +- tests/src/e2e/ledger_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/e2e/ibc_tests.rs b/tests/src/e2e/ibc_tests.rs index be9762591a..fe398a0b39 100644 --- a/tests/src/e2e/ibc_tests.rs +++ b/tests/src/e2e/ibc_tests.rs @@ -288,12 +288,12 @@ fn run_two_nets() -> Result<(NamadaCmd, NamadaCmd, Test, Test)> { let mut ledger_a = run_as!(test_a, Who::Validator(0), Bin::Node, &["ledger"], Some(40))?; ledger_a.exp_string(LEDGER_STARTED)?; + ledger_a.exp_string(VALIDATOR_NODE)?; // Run Chain B std::env::set_var(ENV_VAR_CHAIN_ID, test_b.net.chain_id.to_string()); let mut ledger_b = run_as!(test_b, Who::Validator(0), Bin::Node, &["ledger"], Some(40))?; ledger_b.exp_string(LEDGER_STARTED)?; - ledger_a.exp_string(VALIDATOR_NODE)?; ledger_b.exp_string(VALIDATOR_NODE)?; wait_for_wasm_pre_compile(&mut ledger_a)?; diff --git a/tests/src/e2e/ledger_tests.rs b/tests/src/e2e/ledger_tests.rs index ef275857d8..ca123601a1 100644 --- a/tests/src/e2e/ledger_tests.rs +++ b/tests/src/e2e/ledger_tests.rs @@ -76,7 +76,7 @@ fn start_namada_ledger_node( Ok(node) } -pub fn start_namada_ledger_node_wait_wasm( +fn start_namada_ledger_node_wait_wasm( test: &Test, idx: Option, timeout_sec: Option,