From d5863faa5ed2e664a9cee887a6fad0acfc6f3a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 15 Aug 2024 11:39:59 +0100 Subject: [PATCH 1/5] cli/node: don't load ctx for node utils --- crates/apps/src/bin/namada-node/cli.rs | 8 +++--- crates/apps_lib/src/cli.rs | 34 ++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/crates/apps/src/bin/namada-node/cli.rs b/crates/apps/src/bin/namada-node/cli.rs index d0370b892b..52db0ee1a1 100644 --- a/crates/apps/src/bin/namada-node/cli.rs +++ b/crates/apps/src/bin/namada-node/cli.rs @@ -13,9 +13,9 @@ use namada_apps_lib::time::{DateTimeUtc, Utc}; use namada_node as node; pub fn main() -> Result<()> { - let (cmd, mut ctx) = cli::namada_node_cli()?; + let cmd = cli::namada_node_cli()?; match cmd { - cmds::NamadaNode::Ledger(sub) => match sub { + cli::NamadaNode::Ledger(cmd, ctx) => match cmd { cmds::Ledger::Run(cmds::LedgerRun(args)) => { let chain_ctx = ctx.take_chain_or_exit(); let wasm_dir = chain_ctx.wasm_dir(); @@ -110,7 +110,7 @@ pub fn main() -> Result<()> { ); } }, - cmds::NamadaNode::Config(sub) => match sub { + cli::NamadaNode::Config(cmd, mut ctx) => match cmd { cmds::Config::Gen(cmds::ConfigGen) => { // If the config doesn't exit, it gets generated in the context. // In here, we just need to overwrite the default chain ID, in @@ -166,7 +166,7 @@ pub fn main() -> Result<()> { std::fs::write(config_path, updated_config).unwrap(); } }, - cmds::NamadaNode::Utils(sub) => match sub { + cli::NamadaNode::Utils(sub, _global_args) => match sub { cmds::NodeUtils::TestGenesis(TestGenesis(args)) => { node::utils::test_genesis(args) } diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index af64f76c82..da0a08190d 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -8300,9 +8300,39 @@ pub fn namada_cli() -> (cmds::Namada, String) { safe_exit(2); } -pub fn namada_node_cli() -> Result<(cmds::NamadaNode, Context)> { +/// Namada node commands with loaded [`Context`] where required +pub enum NamadaNode { + Ledger(cmds::Ledger, Context), + Config(cmds::Config, Context), + Utils(cmds::NodeUtils, args::Global), +} + +pub fn namada_node_cli() -> Result { let app = namada_node_app(); - cmds::NamadaNode::parse_or_print_help(app) + let matches = app.clone().get_matches(); + match Cmd::parse(&matches) { + Some(cmd) => { + let global_args = args::Global::parse(&matches); + match cmd { + cmds::NamadaNode::Ledger(sub_cmd) => { + let context = Context::new::(global_args)?; + Ok(NamadaNode::Ledger(sub_cmd, context)) + } + cmds::NamadaNode::Config(sub_cmd) => { + let context = Context::new::(global_args)?; + Ok(NamadaNode::Config(sub_cmd, context)) + } + cmds::NamadaNode::Utils(sub_cmd) => { + Ok(NamadaNode::Utils(sub_cmd, global_args)) + } + } + } + None => { + let mut app = app; + app.print_help().unwrap(); + safe_exit(2); + } + } } #[allow(clippy::large_enum_variant)] From b81084051c2f82cbd7cea91e54ca8b4d484c577b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 15 Aug 2024 11:40:38 +0100 Subject: [PATCH 2/5] cli/client: fix clippy --- crates/apps_lib/src/cli.rs | 9 +- crates/apps_lib/src/cli/client.rs | 151 +++++++++++++----------- crates/node/src/shell/testing/client.rs | 2 +- 3 files changed, 87 insertions(+), 75 deletions(-) diff --git a/crates/apps_lib/src/cli.rs b/crates/apps_lib/src/cli.rs index da0a08190d..c98aeb1762 100644 --- a/crates/apps_lib/src/cli.rs +++ b/crates/apps_lib/src/cli.rs @@ -8335,9 +8335,9 @@ pub fn namada_node_cli() -> Result { } } -#[allow(clippy::large_enum_variant)] +/// Namada client commands with loaded [`Context`] where required pub enum NamadaClient { - WithoutContext(cmds::ClientUtils, args::Global), + WithoutContext(Box<(cmds::ClientUtils, args::Global)>), WithContext(Box<(cmds::NamadaClientWithContext, Context)>), } @@ -8353,7 +8353,10 @@ pub fn namada_client_cli() -> Result { Ok(NamadaClient::WithContext(Box::new((sub_cmd, context)))) } cmds::NamadaClient::WithoutContext(sub_cmd) => { - Ok(NamadaClient::WithoutContext(sub_cmd, global_args)) + Ok(NamadaClient::WithoutContext(Box::new(( + sub_cmd, + global_args, + )))) } } } diff --git a/crates/apps_lib/src/cli/client.rs b/crates/apps_lib/src/cli/client.rs index 61ce4a5512..5e5cc2264e 100644 --- a/crates/apps_lib/src/cli/client.rs +++ b/crates/apps_lib/src/cli/client.rs @@ -774,80 +774,89 @@ impl CliApi { } } } - cli::NamadaClient::WithoutContext(cmd, global_args) => match cmd { - // Utils cmds - ClientUtils::JoinNetwork(JoinNetwork(args)) => { - utils::join_network(global_args, args).await - } - ClientUtils::ValidateWasm(ValidateWasm(args)) => { - utils::validate_wasm(args) - } - ClientUtils::InitNetwork(InitNetwork(args)) => { - utils::init_network(global_args, args); - } - ClientUtils::GenesisBond(GenesisBond(args)) => { - utils::genesis_bond(global_args, args) - } - ClientUtils::DeriveGenesisAddresses( - DeriveGenesisAddresses(args), - ) => utils::derive_genesis_addresses(global_args, args), - ClientUtils::InitGenesisEstablishedAccount( - InitGenesisEstablishedAccount(args), - ) => utils::init_genesis_established_account(global_args, args), - ClientUtils::InitGenesisValidator(InitGenesisValidator( - args, - )) => utils::init_genesis_validator(global_args, args), - ClientUtils::PkToTmAddress(PkToTmAddress(args)) => { - utils::pk_to_tm_address(global_args, args) - } - ClientUtils::DefaultBaseDir(DefaultBaseDir(args)) => { - utils::default_base_dir(global_args, args) - } - ClientUtils::EpochSleep(EpochSleep(args)) => { - let mut ctx = cli::Context::new::(global_args) - .expect("expected to construct a context"); - let chain_ctx = ctx.borrow_mut_chain_or_exit(); - let ledger_address = chain_ctx.get(&args.ledger_address); - let client = C::from_tendermint_address(&ledger_address); - client.wait_until_node_is_synced(&io).await?; - let args = args.to_sdk(&mut ctx)?; - let namada = ctx.to_sdk(client, io); - rpc::epoch_sleep(&namada, args).await; - } - ClientUtils::ValidateGenesisTemplates( - ValidateGenesisTemplates(args), - ) => utils::validate_genesis_templates(global_args, args), - ClientUtils::SignGenesisTxs(SignGenesisTxs(args)) => { - utils::sign_genesis_tx(global_args, args).await - } - ClientUtils::ParseMigrationJson(MigrationJson(args)) => { - #[cfg(feature = "migrations")] - { - let mut update_json = String::new(); - let mut file = std::fs::File::open(args.path).expect( - "Could not fine updates file at the specified \ - path.", - ); - file.read_to_string(&mut update_json) - .expect("Unable to read the updates json file"); - let updates: namada_sdk::migrations::DbChanges = - serde_json::from_str(&update_json).expect( - "Could not parse the updates file as json", - ); - for change in updates.changes { - display_line!(io, "{}", change); - } + cli::NamadaClient::WithoutContext(cmd_box) => { + let (cmd, global_args) = *cmd_box; + match cmd { + // Utils cmds + ClientUtils::JoinNetwork(JoinNetwork(args)) => { + utils::join_network(global_args, args).await + } + ClientUtils::ValidateWasm(ValidateWasm(args)) => { + utils::validate_wasm(args) + } + ClientUtils::InitNetwork(InitNetwork(args)) => { + utils::init_network(global_args, args); + } + ClientUtils::GenesisBond(GenesisBond(args)) => { + utils::genesis_bond(global_args, args) + } + ClientUtils::DeriveGenesisAddresses( + DeriveGenesisAddresses(args), + ) => utils::derive_genesis_addresses(global_args, args), + ClientUtils::InitGenesisEstablishedAccount( + InitGenesisEstablishedAccount(args), + ) => utils::init_genesis_established_account( + global_args, + args, + ), + ClientUtils::InitGenesisValidator( + InitGenesisValidator(args), + ) => utils::init_genesis_validator(global_args, args), + ClientUtils::PkToTmAddress(PkToTmAddress(args)) => { + utils::pk_to_tm_address(global_args, args) } - #[cfg(not(feature = "migrations"))] - { - display_line!( - io, - "Can only use this function if compiled with \ - feature \"migrations\" enabled." - ) + ClientUtils::DefaultBaseDir(DefaultBaseDir(args)) => { + utils::default_base_dir(global_args, args) + } + ClientUtils::EpochSleep(EpochSleep(args)) => { + let mut ctx = cli::Context::new::(global_args) + .expect("expected to construct a context"); + let chain_ctx = ctx.borrow_mut_chain_or_exit(); + let ledger_address = + chain_ctx.get(&args.ledger_address); + let client = + C::from_tendermint_address(&ledger_address); + client.wait_until_node_is_synced(&io).await?; + let args = args.to_sdk(&mut ctx)?; + let namada = ctx.to_sdk(client, io); + rpc::epoch_sleep(&namada, args).await; + } + ClientUtils::ValidateGenesisTemplates( + ValidateGenesisTemplates(args), + ) => utils::validate_genesis_templates(global_args, args), + ClientUtils::SignGenesisTxs(SignGenesisTxs(args)) => { + utils::sign_genesis_tx(global_args, args).await + } + ClientUtils::ParseMigrationJson(MigrationJson(args)) => { + #[cfg(feature = "migrations")] + { + let mut update_json = String::new(); + let mut file = std::fs::File::open(args.path) + .expect( + "Could not fine updates file at the \ + specified path.", + ); + file.read_to_string(&mut update_json) + .expect("Unable to read the updates json file"); + let updates: namada_sdk::migrations::DbChanges = + serde_json::from_str(&update_json).expect( + "Could not parse the updates file as json", + ); + for change in updates.changes { + display_line!(io, "{}", change); + } + } + #[cfg(not(feature = "migrations"))] + { + display_line!( + io, + "Can only use this function if compiled with \ + feature \"migrations\" enabled." + ) + } } } - }, + } } Ok(()) } diff --git a/crates/node/src/shell/testing/client.rs b/crates/node/src/shell/testing/client.rs index f9921211ad..3222667684 100644 --- a/crates/node/src/shell/testing/client.rs +++ b/crates/node/src/shell/testing/client.rs @@ -44,7 +44,7 @@ pub fn run( NamadaClient::WithContext(Box::new((sub_cmd, ctx))) } cmds::NamadaClient::WithoutContext(sub_cmd) => { - NamadaClient::WithoutContext(sub_cmd, global) + NamadaClient::WithoutContext(Box::new((sub_cmd, global))) } }; rt.block_on(CliApi::handle_client_command( From aa72fc17eb18bfc8850c9e321ddc55c362ddc7f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 15 Aug 2024 11:43:43 +0100 Subject: [PATCH 3/5] changelog: add #3652 --- .changelog/unreleased/improvements/3652-ctxless-node-utils.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/improvements/3652-ctxless-node-utils.md diff --git a/.changelog/unreleased/improvements/3652-ctxless-node-utils.md b/.changelog/unreleased/improvements/3652-ctxless-node-utils.md new file mode 100644 index 0000000000..bd7a334d07 --- /dev/null +++ b/.changelog/unreleased/improvements/3652-ctxless-node-utils.md @@ -0,0 +1,2 @@ +- Do not load context for `namadan utils test-genesis` command. + ([\#3652](https://github.com/anoma/namada/pull/3652)) \ No newline at end of file From d1827268b6194ca1f4df1c7073edb6395556c5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 15 Aug 2024 13:32:42 +0100 Subject: [PATCH 4/5] node/utils/test-genesis: remove unnecessary broadcaster task --- crates/node/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/node/src/lib.rs b/crates/node/src/lib.rs index ff756f5fa3..db33bdf666 100644 --- a/crates/node/src/lib.rs +++ b/crates/node/src/lib.rs @@ -958,8 +958,6 @@ pub fn test_genesis_files( // broadcaster service let (broadcast_sender, _broadcaster_receiver) = mpsc::unbounded_channel(); - // Start dummy broadcaster - let _broadcaster = spawn_dummy_task(()); let chain_id = config.chain_id.to_string(); // start an instance of the ledger let mut shell = Shell::::new( From 9bba8fd2c2d3ee04cbdcfed546cb79321da6917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 15 Aug 2024 13:41:49 +0100 Subject: [PATCH 5/5] test/e2e/ledger_tests: add localnet genesis test using `utils test-genesis` --- .github/workflows/scripts/e2e.json | 3 ++- crates/tests/src/e2e/ledger_tests.rs | 31 +++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 5011893e3d..867edb432a 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -26,9 +26,10 @@ "e2e::ledger_tests::suspend_ledger": 30, "e2e::ledger_tests::stop_ledger_at_height": 18, "e2e::ledger_tests::change_consensus_key": 91, + "e2e::ledger_tests::test_localnet_genesis": 3, "e2e::wallet_tests::wallet_address_cmds": 1, "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, "e2e::ledger_tests::masp_txs_and_queries": 82 -} +} \ No newline at end of file diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index 010d19ad4d..afe27d577e 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -20,9 +20,10 @@ use std::time::{Duration, Instant}; use color_eyre::eyre::Result; use color_eyre::owo_colors::OwoColorize; use namada_apps_lib::cli::context::ENV_VAR_CHAIN_ID; -use namada_apps_lib::config::ethereum_bridge; use namada_apps_lib::config::utils::convert_tm_addr_to_socket_addr; +use namada_apps_lib::config::{self, ethereum_bridge}; use namada_apps_lib::facade::tendermint_config::net::Address as TendermintAddress; +use namada_apps_lib::wallet; use namada_core::chain::ChainId; use namada_core::token::NATIVE_MAX_DECIMAL_PLACES; use namada_sdk::address::Address; @@ -2556,3 +2557,31 @@ fn masp_txs_and_queries() -> Result<()> { Ok(()) } + +/// Test localnet genesis files with `namada node utils test-genesis` command. +#[test] +fn test_localnet_genesis() -> Result<()> { + let loc = format!("{}:{}", std::file!(), std::line!()); + let dir = setup::TestDir::new(); + let working_dir = working_dir(); + let genesis_path = wallet::defaults::derive_template_dir(&working_dir); + let wasm_dir = working_dir.join(config::DEFAULT_WASM_DIR); + let mut test_genesis_result = setup::run_cmd( + Bin::Node, + [ + "utils", + "test-genesis", + "--path", + &genesis_path.to_string_lossy(), + "--wasm-dir", + &wasm_dir.to_string_lossy(), + ], + Some(30), + &working_dir, + dir.path(), + loc, + )?; + test_genesis_result + .exp_string("Genesis files were dry-run successfully")?; + Ok(()) +}