diff --git a/.changelog/unreleased/improvements/2658-allow-http-url-cli.md b/.changelog/unreleased/improvements/2658-allow-http-url-cli.md new file mode 100644 index 0000000000..5118893e08 --- /dev/null +++ b/.changelog/unreleased/improvements/2658-allow-http-url-cli.md @@ -0,0 +1,2 @@ +- Allow users to input http/https url as ledger urls. + ([\#2658](https://github.com/anoma/namada/pull/2658)) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 9ae92171d8..b821c9a16c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4288,6 +4288,7 @@ dependencies = [ "tar", "tempfile", "tendermint-config", + "tendermint-rpc", "test-log", "thiserror", "tokio", diff --git a/crates/apps/Cargo.toml b/crates/apps/Cargo.toml index d141c53981..72b1161e6a 100644 --- a/crates/apps/Cargo.toml +++ b/crates/apps/Cargo.toml @@ -127,6 +127,7 @@ sysinfo.workspace = true tar.workspace = true tempfile.workspace = true tendermint-config.workspace = true +tendermint-rpc.workspace = true thiserror.workspace = true tokio = {workspace = true, features = ["full"]} toml.workspace = true diff --git a/crates/apps/src/lib/cli.rs b/crates/apps/src/lib/cli.rs index 3e84538f0f..8bb36b09f8 100644 --- a/crates/apps/src/lib/cli.rs +++ b/crates/apps/src/lib/cli.rs @@ -2882,7 +2882,7 @@ pub mod args { use crate::config::genesis::GenesisAddress; use crate::config::{self, Action, ActionAtHeight}; use crate::facade::tendermint::Timeout; - use crate::facade::tendermint_config::net::Address as TendermintAddress; + use crate::facade::tendermint_rpc::Url; pub const ADDRESS: Arg = arg("address"); pub const ALIAS_OPT: ArgOpt = ALIAS.opt(); @@ -3012,10 +3012,10 @@ pub mod args { scheme is not supplied, it is assumed to be TCP."; pub const CONFIG_RPC_LEDGER_ADDRESS: ArgDefaultFromCtx = arg_default_from_ctx("node", DefaultFn(|| "".to_string())); - pub const LEDGER_ADDRESS: ArgDefault = arg("node") - .default(DefaultFn(|| { - let raw = "127.0.0.1:26657"; - TendermintAddress::from_str(raw).unwrap() + pub const LEDGER_ADDRESS: ArgDefault = + arg("node").default(DefaultFn(|| { + let raw = "http://127.0.0.1:26657"; + Url::from_str(raw).unwrap() })); pub const LIST_FIND_ADDRESSES_ONLY: ArgFlag = flag("addr"); pub const LIST_FIND_KEYS_ONLY: ArgFlag = flag("keys"); @@ -5915,7 +5915,7 @@ pub mod args { type EthereumAddress = String; type Keypair = WalletKeypair; type PublicKey = WalletPublicKey; - type TendermintAddress = tendermint_config::net::Address; + type TendermintAddress = tendermint_rpc::Url; type TransferSource = WalletTransferSource; type TransferTarget = WalletTransferTarget; type ViewingKey = WalletViewingKey; diff --git a/crates/apps/src/lib/cli/api.rs b/crates/apps/src/lib/cli/api.rs index 3a5db7d33e..29b271b4d7 100644 --- a/crates/apps/src/lib/cli/api.rs +++ b/crates/apps/src/lib/cli/api.rs @@ -3,12 +3,12 @@ use namada::types::io::Io; use namada_sdk::error::Error; use namada_sdk::queries::Client; use namada_sdk::rpc::wait_until_node_is_synched; -use tendermint_config::net::Address as TendermintAddress; +use tendermint_rpc::Url as TendermintUrl; /// Trait for clients that can be used with the CLI. #[async_trait::async_trait(?Send)] pub trait CliClient: Client + Sync { - fn from_tendermint_address(address: &TendermintAddress) -> Self; + fn from_tendermint_address(address: &TendermintUrl) -> Self; async fn wait_until_node_is_synced( &self, io: &impl Io, @@ -17,7 +17,7 @@ pub trait CliClient: Client + Sync { #[async_trait::async_trait(?Send)] impl CliClient for HttpClient { - fn from_tendermint_address(address: &TendermintAddress) -> Self { + fn from_tendermint_address(address: &TendermintUrl) -> Self { HttpClient::new(address.clone()).unwrap() } diff --git a/crates/apps/src/lib/cli/context.rs b/crates/apps/src/lib/cli/context.rs index b9653e9fb2..673c185cda 100644 --- a/crates/apps/src/lib/cli/context.rs +++ b/crates/apps/src/lib/cli/context.rs @@ -18,7 +18,6 @@ use namada_sdk::masp::fs::FsShieldedUtils; use namada_sdk::masp::ShieldedContext; use namada_sdk::wallet::Wallet; use namada_sdk::{Namada, NamadaImpl}; -use tendermint_config::net::Address as TendermintAddress; use super::args; use crate::cli::utils; @@ -74,7 +73,7 @@ pub type WalletPublicKey = FromContext; pub type WalletBalanceOwner = FromContext; /// RPC address of a locally configured node -pub type ConfigRpcAddress = FromContext; +pub type ConfigRpcAddress = FromContext; /// Address that defaults to the native token address. #[derive(Clone, Debug)] @@ -95,8 +94,8 @@ impl FromStr for AddrOrNativeToken { } } -impl From for ConfigRpcAddress { - fn from(value: TendermintAddress) -> Self { +impl From for ConfigRpcAddress { + fn from(value: tendermint_rpc::Url) -> Self { FromContext::new(value.to_string()) } } @@ -464,13 +463,16 @@ impl ArgFromContext for AddrOrNativeToken { } } -impl ArgFromContext for TendermintAddress { +impl ArgFromContext for tendermint_rpc::Url { fn arg_from_ctx( ctx: &ChainContext, raw: impl AsRef, ) -> Result { if raw.as_ref().is_empty() { - return Ok(ctx.config.ledger.cometbft.rpc.laddr.clone()); + return Self::from_str( + &ctx.config.ledger.cometbft.rpc.laddr.to_string().replace("tpc", "http"), + ) + .map_err(|err| format!("Invalid Tendermint address: {err}")); } Self::from_str(raw.as_ref()) .map_err(|err| format!("Invalid Tendermint address: {err}")) diff --git a/crates/apps/src/lib/config/genesis/transactions.rs b/crates/apps/src/lib/config/genesis/transactions.rs index 68a3040eb8..7515e2e5e2 100644 --- a/crates/apps/src/lib/config/genesis/transactions.rs +++ b/crates/apps/src/lib/config/genesis/transactions.rs @@ -73,10 +73,8 @@ fn get_tx_args(use_device: bool) -> TxArgs { output_folder: None, force: false, broadcast_only: false, - ledger_address: tendermint_config::net::Address::from_str( - "127.0.0.1:26657", - ) - .unwrap(), + ledger_address: tendermint_rpc::Url::from_str("http://127.0.0.1:26657") + .unwrap(), initialized_account_alias: None, wallet_alias_force: false, fee_amount: None, diff --git a/crates/apps/src/lib/node/ledger/shell/testing/client.rs b/crates/apps/src/lib/node/ledger/shell/testing/client.rs index 6f34737f22..397473453b 100644 --- a/crates/apps/src/lib/node/ledger/shell/testing/client.rs +++ b/crates/apps/src/lib/node/ledger/shell/testing/client.rs @@ -2,7 +2,6 @@ use clap::Command as App; use eyre::Report; use namada::types::io::Io; use namada_sdk::error::Error as SdkError; -use tendermint_config::net::Address as TendermintAddress; use super::node::MockNode; use crate::cli::api::{CliApi, CliClient}; @@ -93,7 +92,7 @@ pub fn run( #[async_trait::async_trait(?Send)] impl<'a> CliClient for &'a MockNode { - fn from_tendermint_address(_: &TendermintAddress) -> Self { + fn from_tendermint_address(_: &tendermint_rpc::Url) -> Self { unreachable!("MockNode should always be instantiated at test start.") } diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index e8d2cbcdd2..78b36d153b 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -95,12 +95,12 @@ impl NamadaTypes for SdkTypes { type Address = Address; type BalanceOwner = namada_core::types::masp::BalanceOwner; type BpConversionTable = HashMap; - type ConfigRpcTendermintAddress = tendermint_config::net::Address; + type ConfigRpcTendermintAddress = tendermint_rpc::Url; type Data = Vec; type EthereumAddress = (); type Keypair = namada_core::types::key::common::SecretKey; type PublicKey = namada_core::types::key::common::PublicKey; - type TendermintAddress = tendermint_config::net::Address; + type TendermintAddress = tendermint_rpc::Url; type TransferSource = namada_core::types::masp::TransferSource; type TransferTarget = namada_core::types::masp::TransferTarget; type ViewingKey = namada_core::types::masp::ExtendedViewingKey; diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index 74b15fbfd3..9c49ffb0af 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -127,8 +127,8 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { output_folder: None, force: false, broadcast_only: false, - ledger_address: tendermint_config::net::Address::from_str( - "127.0.0.1:26657", + ledger_address: tendermint_rpc::Url::from_str( + "http://127.0.0.1:26657", ) .unwrap(), initialized_account_alias: None, @@ -642,8 +642,8 @@ where output_folder: None, force: false, broadcast_only: false, - ledger_address: tendermint_config::net::Address::from_str( - "127.0.0.1:26657", + ledger_address: tendermint_rpc::Url::from_str( + "http://127.0.0.1:26657", ) .unwrap(), initialized_account_alias: None, diff --git a/crates/tests/src/e2e/helpers.rs b/crates/tests/src/e2e/helpers.rs index 8a24b1f304..8248057d59 100644 --- a/crates/tests/src/e2e/helpers.rs +++ b/crates/tests/src/e2e/helpers.rs @@ -177,7 +177,7 @@ pub fn get_actor_rpc(test: &Test, who: Who) -> String { Config::load(base_dir, &test.net.chain_id, Some(tendermint_mode)); let socket_addr = convert_tm_addr_to_socket_addr(&config.ledger.cometbft.rpc.laddr); - format!("{}:{}", socket_addr.ip(), socket_addr.port()) + format!("http://{}:{}", socket_addr.ip(), socket_addr.port()) } /// Get some nodes's wallet. @@ -578,6 +578,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 = rpc_addr.strip_prefix("http://").unwrap(); let mut table = toml::map::Map::new(); table.insert("mode".to_owned(), Value::String("push".to_owned())); diff --git a/crates/tests/src/e2e/ibc_tests.rs b/crates/tests/src/e2e/ibc_tests.rs index 4cd825b8c8..28ea6d735d 100644 --- a/crates/tests/src/e2e/ibc_tests.rs +++ b/crates/tests/src/e2e/ibc_tests.rs @@ -77,7 +77,6 @@ use namada_apps::config::utils::set_port; use namada_apps::config::{ethereum_bridge, TendermintMode}; use namada_apps::facade::tendermint::block::Header as TmHeader; use namada_apps::facade::tendermint::merkle::proof::ProofOps as TmProof; -use namada_apps::facade::tendermint_config::net::Address as TendermintAddress; use namada_apps::facade::tendermint_rpc::{Client, HttpClient, Url}; use namada_core::types::string_encoding::StringEncoded; use namada_sdk::masp::fs::FsShieldedUtils; @@ -594,8 +593,8 @@ fn create_client(test_a: &Test, test_b: &Test) -> Result<(ClientId, ClientId)> { fn make_client_state(test: &Test, height: Height) -> TmClientState { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); let pos_params = test.async_runtime().block_on(query_pos_parameters(&client)); @@ -717,8 +716,8 @@ fn update_client( } fn make_light_client_io(test: &Test) -> TmLightClientIo { - let addr = format!("http://{}", get_actor_rpc(test, Who::Validator(0))); - let rpc_addr = Url::from_str(&addr).unwrap(); + let rpc = get_actor_rpc(test, Who::Validator(0)); + let rpc_addr = Url::from_str(&rpc).unwrap(); let rpc_client = HttpClient::new(rpc_addr).unwrap(); let rpc_timeout = Duration::new(10, 0); @@ -1670,8 +1669,8 @@ fn make_ibc_data(message: impl Msg) -> Vec { fn query_height(test: &Test) -> Result { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); let status = test .async_runtime() @@ -1683,8 +1682,8 @@ fn query_height(test: &Test) -> Result { fn query_header(test: &Test, height: Height) -> Result { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); let height = height.revision_height() as u32; let result = test .async_runtime() @@ -1704,8 +1703,8 @@ fn check_ibc_update_query( consensus_height: BlockHeight, ) -> Result<()> { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); match test.async_runtime().block_on(RPC.shell().ibc_client_update( &client, client_id, @@ -1723,8 +1722,8 @@ fn check_ibc_packet_query( packet: &Packet, ) -> Result<()> { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); match test.async_runtime().block_on(RPC.shell().ibc_packet( &client, event_type, @@ -1746,8 +1745,8 @@ fn query_value_with_proof( height: Option, ) -> Result<(Option>, TmProof)> { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); let result = test.async_runtime().block_on(query_storage_value_bytes( &client, key, @@ -2039,8 +2038,8 @@ fn get_attributes_from_event(event: &AbciEvent) -> HashMap { fn get_events(test: &Test, height: u32) -> Result> { let rpc = get_actor_rpc(test, Who::Validator(0)); - let ledger_address = TendermintAddress::from_str(&rpc).unwrap(); - let client = HttpClient::new(ledger_address).unwrap(); + let tendermint_url = Url::from_str(&rpc).unwrap(); + let client = HttpClient::new(tendermint_url).unwrap(); let response = test .async_runtime() diff --git a/crates/tests/src/e2e/ledger_tests.rs b/crates/tests/src/e2e/ledger_tests.rs index a713314c6c..c622d9fd3f 100644 --- a/crates/tests/src/e2e/ledger_tests.rs +++ b/crates/tests/src/e2e/ledger_tests.rs @@ -954,6 +954,9 @@ fn pos_bonds() -> Result<()> { 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)?; + let validator_0_rpc = get_actor_rpc(&test, Who::Validator(0)); // 2. Submit a self-bond for the first genesis validator diff --git a/crates/tests/src/integration/masp.rs b/crates/tests/src/integration/masp.rs index deef3c1061..fd7a359164 100644 --- a/crates/tests/src/integration/masp.rs +++ b/crates/tests/src/integration/masp.rs @@ -25,7 +25,7 @@ use crate::strings::TX_APPLIED_SUCCESS; #[test] fn masp_incentives() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); // Lengthen epoch to ensure that a transaction can be constructed and @@ -697,7 +697,7 @@ fn masp_incentives() -> Result<()> { #[test] fn spend_unconverted_asset_type() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); @@ -804,7 +804,7 @@ fn spend_unconverted_asset_type() -> Result<()> { #[test] fn masp_pinned_txs() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); @@ -967,7 +967,7 @@ fn masp_txs_and_queries() -> Result<()> { // tracing::level_filters::LevelFilter::INFO, // )?; // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); @@ -1273,7 +1273,7 @@ fn masp_txs_and_queries() -> Result<()> { #[test] fn wrapper_fee_unshielding() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); let (mut node, _services) = setup::setup()?; @@ -1367,7 +1367,7 @@ fn wrapper_fee_unshielding() -> Result<()> { #[test] fn cross_epoch_tx() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); let (mut node, _services) = setup::setup()?; @@ -1454,7 +1454,7 @@ fn cross_epoch_tx() -> Result<()> { #[test] fn dynamic_assets() -> Result<()> { // This address doesn't matter for tests. But an argument is required. - let validator_one_rpc = "127.0.0.1:26567"; + let validator_one_rpc = "http://127.0.0.1:26567"; // Download the shielded pool parameters before starting node let _ = FsShieldedUtils::new(PathBuf::new()); // Lengthen epoch to ensure that a transaction can be constructed and