From 6aa7b6788b28552224714d09d914c226b584de9d Mon Sep 17 00:00:00 2001 From: "Raymond E. Pasco" Date: Tue, 30 May 2023 13:28:32 -0400 Subject: [PATCH] Merge branch 'fraccaman/fix-sdk-tx-with-hash' (#1474) into draft * fraccaman/fix-sdk-tx-with-hash: sdk: use hash instead of wasm code --- apps/src/lib/cli.rs | 59 ++++++++----------------- apps/src/lib/client/tx.rs | 20 ++++++--- shared/src/ledger/args.rs | 30 ++++++------- shared/src/ledger/tx.rs | 91 ++++++++++++++++++++++++++++----------- 4 files changed, 110 insertions(+), 90 deletions(-) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index b2a48678e4..479a9b30b1 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -2140,7 +2140,7 @@ pub mod args { sub_prefix: self.sub_prefix, amount: self.amount, native_token: ctx.native_token.clone(), - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -2195,7 +2195,7 @@ pub mod args { channel_id: self.channel_id, timeout_height: self.timeout_height, timeout_sec_offset: self.timeout_sec_offset, - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -2256,15 +2256,8 @@ pub mod args { TxInitAccount:: { tx: self.tx.to_sdk(ctx), source: ctx.get(&self.source), - vp_code: ctx.read_wasm(self.vp_code), - vp_code_path: self - .vp_code_path - .as_path() - .to_str() - .unwrap() - .to_string() - .into_bytes(), - tx_code_path: ctx.read_wasm(self.tx_code_path), + vp_code_path: self.vp_code_path.to_path_buf(), + tx_code_path: self.tx_code_path.to_path_buf(), public_key: ctx.get_cached(&self.public_key), } } @@ -2277,13 +2270,11 @@ pub mod args { let vp_code_path = CODE_PATH_OPT .parse(matches) .unwrap_or_else(|| PathBuf::from(VP_USER_WASM)); - let vp_code = vp_code_path.clone(); let tx_code_path = PathBuf::from(TX_INIT_ACCOUNT_WASM); let public_key = PUBLIC_KEY.parse(matches); Self { tx, source, - vp_code, vp_code_path, public_key, tx_code_path, @@ -2320,13 +2311,9 @@ pub mod args { max_commission_rate_change: self.max_commission_rate_change, validator_vp_code_path: self .validator_vp_code_path - .as_path() - .to_str() - .unwrap() - .to_string() - .into_bytes(), + .to_path_buf(), unsafe_dont_encrypt: self.unsafe_dont_encrypt, - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -2410,20 +2397,8 @@ pub mod args { fn to_sdk(self, ctx: &mut Context) -> TxUpdateVp { TxUpdateVp:: { tx: self.tx.to_sdk(ctx), - vp_code_path: self - .vp_code_path - .as_path() - .to_str() - .unwrap() - .to_string() - .into_bytes(), - tx_code_path: self - .tx_code_path - .as_path() - .to_str() - .unwrap() - .to_string() - .into_bytes(), + vp_code_path: self.vp_code_path, + tx_code_path: self.tx_code_path, addr: ctx.get(&self.addr), } } @@ -2465,7 +2440,7 @@ pub mod args { amount: self.amount, source: self.source.map(|x| ctx.get(&x)), native_token: ctx.native_token.clone(), - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -2505,7 +2480,7 @@ pub mod args { validator: ctx.get(&self.validator), amount: self.amount, source: self.source.map(|x| ctx.get(&x)), - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -2552,7 +2527,7 @@ pub mod args { /// Native token address pub native_token: C::NativeAddress, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } impl CliToSdk> for InitProposal { @@ -2562,7 +2537,7 @@ pub mod args { proposal_data: self.proposal_data, offline: self.offline, native_token: ctx.native_token.clone(), - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path, } } } @@ -2613,7 +2588,7 @@ pub mod args { /// The proposal file path pub proposal_data: Option, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } impl CliToSdk> for VoteProposal { @@ -2624,7 +2599,7 @@ pub mod args { vote: self.vote, offline: self.offline, proposal_data: self.proposal_data, - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), proposal_pgf: self.proposal_pgf, proposal_eth: self.proposal_eth, } @@ -2849,7 +2824,7 @@ pub mod args { tx: self.tx.to_sdk(ctx), validator: ctx.get(&self.validator), source: self.source.map(|x| ctx.get(&x)), - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -3081,7 +3056,7 @@ pub mod args { tx: self.tx.to_sdk(ctx), validator: ctx.get(&self.validator), rate: self.rate, - tx_code_path: ctx.read_wasm(self.tx_code_path), + tx_code_path: self.tx_code_path.to_path_buf(), } } } @@ -3276,7 +3251,7 @@ pub mod args { gas_limit: self.gas_limit, signing_key: self.signing_key.map(|x| ctx.get_cached(&x)), signer: self.signer.map(|x| ctx.get(&x)), - tx_reveal_code_path: ctx.read_wasm(self.tx_reveal_code_path), + tx_reveal_code_path: self.tx_reveal_code_path, password: self.password, expiration: self.expiration, chain_id: self.chain_id, diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index 76f39b9046..0ce4351967 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -172,11 +172,12 @@ pub async fn submit_init_validator< .expect("DKG sessions keys should have been created") .public(); - let vp_code_path = String::from_utf8(validator_vp_code_path).unwrap(); - let validator_vp_code_hash = - query_wasm_code_hash::(client, vp_code_path) - .await - .unwrap(); + let validator_vp_code_hash = query_wasm_code_hash::( + client, + validator_vp_code_path.to_str().unwrap(), + ) + .await + .unwrap(); // Validate the commission rate data if commission_rate > Decimal::ONE || commission_rate < Decimal::ZERO { @@ -824,12 +825,17 @@ pub async fn submit_vote_proposal( .try_to_vec() .expect("Encoding proposal data shouldn't fail"); - let tx_code = args.tx_code_path; + let tx_code_hash = query_wasm_code_hash( + client, + args.tx_code_path.to_str().unwrap(), + ) + .await + .unwrap(); let mut tx = Tx::new(TxType::Raw); tx.header.chain_id = chain_id; tx.header.expiration = expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); process_tx::( client, diff --git a/shared/src/ledger/args.rs b/shared/src/ledger/args.rs index 3ddbb4125c..5aec0a28cd 100644 --- a/shared/src/ledger/args.rs +++ b/shared/src/ledger/args.rs @@ -1,4 +1,6 @@ //! Structures encapsulating SDK arguments +use std::path::PathBuf; + use namada_core::types::chain::ChainId; use namada_core::types::time::DateTimeUtc; use rust_decimal::Decimal; @@ -98,7 +100,7 @@ pub struct TxTransfer { /// Native token address pub native_token: C::NativeAddress, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// IBC transfer transaction arguments @@ -125,7 +127,7 @@ pub struct TxIbcTransfer { /// Timeout timestamp offset pub timeout_sec_offset: Option, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// Transaction to initialize a new account @@ -135,12 +137,10 @@ pub struct TxInitAccount { pub tx: Tx, /// Address of the source account pub source: C::Address, - /// Wasm VP for the new account - pub vp_code: C::Data, /// Path to the VP WASM code file for the new account - pub vp_code_path: C::Data, + pub vp_code_path: PathBuf, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, /// Public key for the new account pub public_key: C::PublicKey, } @@ -165,9 +165,9 @@ pub struct TxInitValidator { /// Maximum commission rate change pub max_commission_rate_change: Decimal, /// Path to the VP WASM code file - pub validator_vp_code_path: C::Data, + pub validator_vp_code_path: PathBuf, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, /// Don't encrypt the keypair pub unsafe_dont_encrypt: bool, } @@ -178,9 +178,9 @@ pub struct TxUpdateVp { /// Common tx arguments pub tx: Tx, /// Path to the VP WASM code file - pub vp_code_path: C::Data, + pub vp_code_path: PathBuf, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, /// Address of the account whose VP is to be updated pub addr: C::Address, } @@ -200,7 +200,7 @@ pub struct Bond { /// Native token address pub native_token: C::NativeAddress, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// Unbond arguments @@ -216,7 +216,7 @@ pub struct Unbond { /// self-bonds, the validator is also the source pub source: Option, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// Reveal public key @@ -255,7 +255,7 @@ pub struct Withdraw { /// from self-bonds, the validator is also the source pub source: Option, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// Query asset conversions @@ -327,7 +327,7 @@ pub struct TxCommissionRateChange { /// Value to which the tx changes the commission rate pub rate: Decimal, /// Path to the TX WASM code file - pub tx_code_path: C::Data, + pub tx_code_path: PathBuf, } /// Query PoS commission rate @@ -411,7 +411,7 @@ pub struct Tx { /// Sign the tx with the keypair of the public key of the given address pub signer: Option, /// Path to the TX WASM code file to reveal PK - pub tx_reveal_code_path: C::Data, + pub tx_reveal_code_path: PathBuf, /// Password to decrypt key pub password: Option>, } diff --git a/shared/src/ledger/tx.rs b/shared/src/ledger/tx.rs index d99190d79b..fa21264e0d 100644 --- a/shared/src/ledger/tx.rs +++ b/shared/src/ledger/tx.rs @@ -344,12 +344,24 @@ pub async fn submit_reveal_pk_aux< let addr: Address = public_key.into(); println!("Submitting a tx to reveal the public key for address {addr}..."); let tx_data = public_key.try_to_vec().map_err(Error::EncodeKeyFailure)?; - let tx_code = args.tx_reveal_code_path.clone(); - let mut tx = Tx::new(TxType::Raw); + + let tx_code_hash = query_wasm_code_hash( + client, + args.tx_reveal_code_path.to_str().unwrap(), + ) + .await + .unwrap(); + + let mut tx = Tx::new(TxType::Decrypted(DecryptedTx::Decrypted { + #[cfg(not(feature = "mainnet"))] + // To be able to dry-run testnet faucet withdrawal, pretend + // that we got a valid PoW + has_valid_pow: true, + })); tx.header.chain_id = args.chain_id.clone().expect("value should be there"); tx.header.expiration = args.expiration; tx.set_data(Data::new(tx_data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); // submit_tx without signing the inner tx let keypair = if let Some(signing_key) = &args.signing_key { @@ -582,7 +594,10 @@ pub async fn submit_validator_commission_change< ) -> Result<(), Error> { let epoch = rpc::query_epoch(client).await; - let tx_code = args.tx_code_path; + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); // TODO: put following two let statements in its own function let params_key = crate::ledger::pos::params_key(); @@ -649,7 +664,7 @@ pub async fn submit_validator_commission_change< tx.header.chain_id = args.tx.chain_id.clone().unwrap(); tx.header.expiration = args.tx.expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); let default_signer = args.validator.clone(); process_tx::( @@ -681,7 +696,11 @@ pub async fn submit_withdraw< .await?; let source = args.source.clone(); - let tx_code = args.tx_code_path; + + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); // Check the source's current unbond amount let bond_source = source.clone().unwrap_or_else(|| validator.clone()); @@ -714,7 +733,7 @@ pub async fn submit_withdraw< tx.header.chain_id = args.tx.chain_id.clone().unwrap(); tx.header.expiration = args.tx.expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); let default_signer = args.source.unwrap_or(args.validator); process_tx::( @@ -742,7 +761,12 @@ pub async fn submit_unbond< let source = args.source.clone(); // Check the source's current bond amount let bond_source = source.clone().unwrap_or_else(|| args.validator.clone()); - let tx_code = args.tx_code_path; + + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); + if !args.tx.force { known_validator_or_err(args.validator.clone(), args.tx.force, client) .await?; @@ -790,7 +814,7 @@ pub async fn submit_unbond< tx.header.chain_id = args.tx.chain_id.clone().unwrap(); tx.header.expiration = args.tx.expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); let default_signer = args.source.unwrap_or_else(|| args.validator.clone()); process_tx::( @@ -891,7 +915,11 @@ pub async fn submit_bond< ) .await?; - let tx_code = args.tx_code_path; + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); + let bond = pos::Bond { validator, amount: args.amount, @@ -903,7 +931,7 @@ pub async fn submit_bond< tx.header.chain_id = args.tx.chain_id.clone().unwrap(); tx.header.expiration = args.tx.expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); let default_signer = args.source.unwrap_or(args.validator); process_tx::( @@ -989,7 +1017,10 @@ pub async fn submit_ibc_transfer< ) .await?; - let tx_code = args.tx_code_path; + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); let denom = match sub_prefix { // To parse IbcToken address, remove the address prefix @@ -1039,7 +1070,7 @@ pub async fn submit_ibc_transfer< tx.header.chain_id = args.tx.chain_id.clone().unwrap(); tx.header.expiration = args.tx.expiration; tx.set_data(Data::new(data)); - tx.set_code(Code::new(tx_code)); + tx.set_code(Code::from_hash(tx_code_hash)); process_tx::( client, @@ -1212,9 +1243,10 @@ pub async fn submit_transfer< #[cfg(not(feature = "mainnet"))] let is_source_faucet = rpc::is_faucet_account(client, &source).await; - let tx_code_hash = query_wasm_code_hash(client, TX_TRANSFER_WASM) - .await - .unwrap(); + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); // Loop twice in case the first submission attempt fails for _ in 0..2 { @@ -1339,12 +1371,16 @@ pub async fn submit_init_account< args: args::TxInitAccount, ) -> Result<(), Error> { let public_key = args.public_key; - let vp_code = args.vp_code; - // Validate the VP code - validate_untrusted_code_err(&vp_code, args.tx.force)?; - let vp_code_path = String::from_utf8(args.vp_code_path).unwrap(); + let vp_code_hash = - query_wasm_code_hash(client, vp_code_path).await.unwrap(); + query_wasm_code_hash(client, args.vp_code_path.to_str().unwrap()) + .await + .unwrap(); + + let tx_code_hash = + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); let mut tx = Tx::new(TxType::Raw); tx.header.chain_id = args.tx.chain_id.clone().unwrap(); @@ -1359,7 +1395,7 @@ pub async fn submit_init_account< }; let data = data.try_to_vec().map_err(Error::EncodeTxFailure)?; tx.set_data(Data::new(data)); - tx.set_code(Code::new(args.tx_code_path)); + tx.set_code(Code::from_hash(tx_code_hash)); // TODO Move unwrap to an either let initialized_accounts = process_tx::( @@ -1430,13 +1466,15 @@ pub async fn submit_update_vp< } }?; - let vp_code_path = String::from_utf8(args.vp_code_path).unwrap(); let vp_code_hash = - query_wasm_code_hash(client, vp_code_path).await.unwrap(); + query_wasm_code_hash(client, args.vp_code_path.to_str().unwrap()) + .await + .unwrap(); - let tx_code_path = String::from_utf8(args.tx_code_path).unwrap(); let tx_code_hash = - query_wasm_code_hash(client, tx_code_path).await.unwrap(); + query_wasm_code_hash(client, args.tx_code_path.to_str().unwrap()) + .await + .unwrap(); let mut tx = Tx::new(TxType::Raw); tx.header.chain_id = args.tx.chain_id.clone().unwrap(); @@ -1680,6 +1718,7 @@ async fn check_balance_too_low_err( } } +#[allow(dead_code)] fn validate_untrusted_code_err( vp_code: &Vec, force: bool,