diff --git a/.changelog/unreleased/improvements/3833-pre-genesis-chain-id.md b/.changelog/unreleased/improvements/3833-pre-genesis-chain-id.md new file mode 100644 index 0000000000..3927553acc --- /dev/null +++ b/.changelog/unreleased/improvements/3833-pre-genesis-chain-id.md @@ -0,0 +1,2 @@ +- Let user customize the pre-genesis chain-id via environment variable + ([\#3833](https://github.com/anoma/namada/pull/3833)) \ No newline at end of file diff --git a/.github/workflows/scripts/e2e.json b/.github/workflows/scripts/e2e.json index 3bf6805313..107820fdd5 100644 --- a/.github/workflows/scripts/e2e.json +++ b/.github/workflows/scripts/e2e.json @@ -29,5 +29,6 @@ "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 + "e2e::ledger_tests::masp_txs_and_queries": 82, + "e2e::ledger_tests::test_genesis_chain_id_change": 35 } \ No newline at end of file diff --git a/crates/apps_lib/src/config/genesis/transactions.rs b/crates/apps_lib/src/config/genesis/transactions.rs index 4ab224db20..1277d19dd4 100644 --- a/crates/apps_lib/src/config/genesis/transactions.rs +++ b/crates/apps_lib/src/config/genesis/transactions.rs @@ -1,6 +1,7 @@ //! Genesis transactions use std::collections::{BTreeMap, BTreeSet}; +use std::env; use std::fmt::Debug; use std::net::SocketAddr; @@ -46,6 +47,7 @@ use crate::config::genesis::{utils, GenesisAddress}; use crate::wallet::{CliWalletUtils, WalletTransport}; /// Dummy chain id used to sign [`Tx`] objects at pre-genesis. +pub const NAMADA_GENESIS_TX_ENV_VAR: &str = "NAMADA_GENESIS_TX_CHAIN_ID"; const NAMADA_GENESIS_TX_CHAIN_ID: &str = "namada-genesis"; /// Helper trait to fetch tx data to sign. @@ -62,6 +64,15 @@ pub trait TxToSign { fn get_owner(&self) -> GenesisAddress; } +/// Get the genesis chain ID from "NAMADA_GENESIS_TX_CHAIN_ID" env var, if set, +/// or the default +pub fn genesis_chain_id() -> ChainId { + ChainId( + env::var(NAMADA_GENESIS_TX_ENV_VAR) + .unwrap_or_else(|_| NAMADA_GENESIS_TX_CHAIN_ID.to_string()), + ) +} + /// Return a dummy set of tx arguments to sign with the /// hardware wallet. fn get_tx_args(use_device: bool) -> TxArgs { @@ -107,7 +118,7 @@ fn pre_genesis_tx_timestamp() -> DateTimeUtc { /// Return a ready to sign genesis [`Tx`]. fn get_tx_to_sign(tag: impl AsRef, data: impl BorshSerialize) -> Tx { let mut tx = Tx::from_type(TxType::Raw); - tx.header.chain_id = ChainId(NAMADA_GENESIS_TX_CHAIN_ID.to_string()); + tx.header.chain_id = genesis_chain_id(); tx.header.timestamp = pre_genesis_tx_timestamp(); tx.set_code(Code { salt: [0; 8], diff --git a/crates/node/src/utils.rs b/crates/node/src/utils.rs index b2c02f40b2..7f2ef01b37 100644 --- a/crates/node/src/utils.rs +++ b/crates/node/src/utils.rs @@ -19,7 +19,10 @@ pub fn test_genesis(args: TestGenesis, global_args: args::Global) { check_can_sign, } = args; - let templates = genesis::templates::load_and_validate(&path).unwrap(); + let Some(templates) = genesis::templates::load_and_validate(&path) else { + eprintln!("Unable to load the genesis templates"); + cli::safe_exit(1); + }; let genesis = genesis::chain::finalize( templates, FromStr::from_str("namada-dryrun").unwrap(), diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index f7a0c8e727..4ba8f540cb 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -10,6 +10,7 @@ //! `NAMADA_E2E_KEEP_TEMP=true`. #![allow(clippy::type_complexity)] +use std::env; use std::fmt::Display; use std::path::PathBuf; use std::process::Command; @@ -2597,7 +2598,6 @@ fn masp_txs_and_queries() -> Result<()> { /// 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 base_dir = setup::TestDir::new(); let working_dir = working_dir(); let genesis_path = wallet::defaults::derive_template_dir(&working_dir); @@ -2634,12 +2634,107 @@ fn test_localnet_genesis() -> Result<()> { Some(30), &working_dir, &base_dir, - loc, + format!("{}:{}", std::file!(), std::line!()), )?; test_genesis_result .exp_string("Genesis files were dry-run successfully")?; test_genesis_result.exp_string("Able to sign with")?; test_genesis_result.exp_string("Able to sign with")?; test_genesis_result.exp_string("Able to sign with")?; + + // Use a non-default "NAMADA_GENESIS_TX_CHAIN_ID" + env::set_var( + config::genesis::transactions::NAMADA_GENESIS_TX_ENV_VAR, + "e2e-test-genesis", + ); + + 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, + &base_dir, + format!("{}:{}", std::file!(), std::line!()), + )?; + // Signature should be invalid now + test_genesis_result.exp_string("Invalid validator account signature")?; + test_genesis_result.exp_string("Invalid bond tx signature")?; + test_genesis_result.exp_string("Invalid bond tx signature")?; + test_genesis_result.assert_failure(); + + Ok(()) +} + +/// Test change of genesis chain ID via "NAMADA_GENESIS_TX_CHAIN_ID" env var +#[test] +fn test_genesis_chain_id_change() -> Result<()> { + // Use a non-default "NAMADA_GENESIS_TX_CHAIN_ID" + env::set_var( + config::genesis::transactions::NAMADA_GENESIS_TX_ENV_VAR, + "e2e-test-genesis", + ); + + let working_dir = working_dir(); + let wasm_dir = working_dir.join(config::DEFAULT_WASM_DIR); + + let test = setup::network( + |mut genesis, base_dir: &_| { + // Empty the transactions as their signatures are invalid - created + // with the default genesis chain ID + genesis.transactions = Default::default(); + genesis.parameters.pgf_params.stewards = Default::default(); + + setup::set_validators(1, genesis, base_dir, |_| 0u16, vec![]) + }, + None, + ) + .unwrap(); + + let genesis_templates = test.test_dir.path().join("templates"); + let base_dir = test.get_base_dir(Who::Validator(0)); + let mut test_genesis_result = setup::run_cmd( + Bin::Node, + [ + "utils", + "test-genesis", + "--path", + &genesis_templates.to_string_lossy(), + "--wasm-dir", + &wasm_dir.to_string_lossy(), + ], + Some(30), + &working_dir, + &base_dir, + format!("{}:{}", std::file!(), std::line!()), + )?; + test_genesis_result + .exp_string("Genesis files were dry-run successfully")?; + + set_ethereum_bridge_mode( + &test, + &test.net.chain_id, + Who::Validator(0), + ethereum_bridge::ledger::Mode::Off, + None, + ); + + // Unset the chain ID - the transaction signatures have been validated at + // init-network so we don't need it anymore + env::remove_var(config::genesis::transactions::NAMADA_GENESIS_TX_ENV_VAR); + // Start the ledger as a validator + let _bg_validator_0 = + start_namada_ledger_node_wait_wasm(&test, Some(0), Some(40))? + .background(); + + let rpc = get_actor_rpc(&test, Who::Validator(0)); + wait_for_block_height(&test, &rpc, 2, 30)?; + Ok(()) } diff --git a/crates/tests/src/e2e/setup.rs b/crates/tests/src/e2e/setup.rs index f246aacd67..1ab6fd9570 100644 --- a/crates/tests/src/e2e/setup.rs +++ b/crates/tests/src/e2e/setup.rs @@ -1100,6 +1100,13 @@ where Bin::Relayer => ("namadar", "info"), }; + let mut args = args.into_iter().peekable(); + let is_node_ledger = matches!(bin, Bin::Node) + && args + .peek() + .map(|fst_arg| fst_arg.as_ref() == "ledger") + .unwrap_or_default(); + let mut run_cmd = generate_bin_command( bin_name, &working_dir.as_ref().join("Cargo.toml"), @@ -1168,7 +1175,7 @@ where println!("{}:\n{}", "> Running".underline().green(), &cmd_process); - if let Bin::Node = &bin { + if is_node_ledger { // When running a node command, we need to wait a bit before checking // status sleep(1);