diff --git a/.changelog/unreleased/improvements/2209-cli-public-keys.md b/.changelog/unreleased/improvements/2209-cli-public-keys.md new file mode 100644 index 0000000000..33486a7c1d --- /dev/null +++ b/.changelog/unreleased/improvements/2209-cli-public-keys.md @@ -0,0 +1,2 @@ +- Increase hardware wallet support in the CLI + ([\#2209](https://github.com/anoma/namada/pull/2209)) \ No newline at end of file diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index eb25939946..3c2a5fa66b 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -2985,7 +2985,7 @@ pub mod args { arg_opt("gas-spending-key"); pub const FEE_AMOUNT_OPT: ArgOpt = arg_opt("gas-price"); - pub const FEE_PAYER_OPT: ArgOpt = arg_opt("gas-payer"); + pub const FEE_PAYER_OPT: ArgOpt = arg_opt("gas-payer"); pub const FORCE: ArgFlag = flag("force"); pub const GAS_LIMIT: ArgDefault = arg_default("gas-limit", DefaultFn(|| GasLimit::from(25_000))); @@ -3070,9 +3070,8 @@ pub mod args { arg("self-bond-amount"); pub const SENDER: Arg = arg("sender"); pub const SIGNER: ArgOpt = arg_opt("signer"); - pub const SIGNING_KEY_OPT: ArgOpt = SIGNING_KEY.opt(); - pub const SIGNING_KEY: Arg = arg("signing-key"); - pub const SIGNING_KEYS: ArgMulti = arg_multi("signing-keys"); + pub const SIGNING_KEYS: ArgMulti = + arg_multi("signing-keys"); pub const SIGNATURES: ArgMulti = arg_multi("signatures"); pub const SOURCE: Arg = arg("source"); pub const SOURCE_OPT: ArgOpt = SOURCE.opt(); @@ -3101,17 +3100,15 @@ pub mod args { arg_opt("account-key"); pub const VALIDATOR_ACCOUNT_KEYS: ArgMulti = arg_multi("account-keys"); - pub const VALIDATOR_CONSENSUS_KEY: ArgOpt = + pub const VALIDATOR_CONSENSUS_KEY: ArgOpt = arg_opt("consensus-key"); pub const VALIDATOR_CODE_PATH: ArgOpt = arg_opt("validator-code-path"); - pub const VALIDATOR_ETH_COLD_KEY: ArgOpt = + pub const VALIDATOR_ETH_COLD_KEY: ArgOpt = arg_opt("eth-cold-key"); - pub const VALIDATOR_ETH_HOT_KEY: ArgOpt = + pub const VALIDATOR_ETH_HOT_KEY: ArgOpt = arg_opt("eth-hot-key"); pub const VALUE: ArgOpt = arg_opt("value"); - pub const VERIFICATION_KEY: ArgOpt = - arg_opt("verification-key"); pub const VIEWING_KEY: Arg = arg("key"); pub const WALLET_ALIAS_FORCE: ArgFlag = flag("wallet-alias-force"); pub const WASM_CHECKSUMS_PATH: Arg = arg("wasm-checksums-path"); @@ -4077,13 +4074,9 @@ pub mod args { tx, scheme: self.scheme, address: chain_ctx.get(&self.address), - consensus_key: self - .consensus_key - .map(|x| chain_ctx.get_cached(&x)), - eth_cold_key: self - .eth_cold_key - .map(|x| chain_ctx.get_cached(&x)), - eth_hot_key: self.eth_hot_key.map(|x| chain_ctx.get_cached(&x)), + consensus_key: self.consensus_key.map(|x| chain_ctx.get(&x)), + eth_cold_key: self.eth_cold_key.map(|x| chain_ctx.get(&x)), + eth_hot_key: self.eth_hot_key.map(|x| chain_ctx.get(&x)), protocol_key: self.protocol_key.map(|x| chain_ctx.get(&x)), commission_rate: self.commission_rate, max_commission_rate_change: self.max_commission_rate_change, @@ -4202,13 +4195,9 @@ pub mod args { .map(|x| chain_ctx.get(x)) .collect(), threshold: self.threshold, - consensus_key: self - .consensus_key - .map(|x| chain_ctx.get_cached(&x)), - eth_cold_key: self - .eth_cold_key - .map(|x| chain_ctx.get_cached(&x)), - eth_hot_key: self.eth_hot_key.map(|x| chain_ctx.get_cached(&x)), + consensus_key: self.consensus_key.map(|x| chain_ctx.get(&x)), + eth_cold_key: self.eth_cold_key.map(|x| chain_ctx.get(&x)), + eth_hot_key: self.eth_hot_key.map(|x| chain_ctx.get(&x)), protocol_key: self.protocol_key.map(|x| chain_ctx.get(&x)), commission_rate: self.commission_rate, max_commission_rate_change: self.max_commission_rate_change, @@ -5336,9 +5325,7 @@ pub mod args { ConsensusKeyChange:: { tx, validator: chain_ctx.get(&self.validator), - consensus_key: self - .consensus_key - .map(|x| chain_ctx.get_cached(&x)), + consensus_key: self.consensus_key.map(|x| chain_ctx.get(&x)), tx_code_path: self.tx_code_path.to_path_buf(), } } @@ -5865,16 +5852,13 @@ pub mod args { signing_keys: self .signing_keys .iter() - .map(|key| ctx.get_cached(key)) + .map(|key| ctx.get(key)) .collect(), signatures: self .signatures .iter() .map(|path| std::fs::read(path).unwrap()) .collect(), - verification_key: self - .verification_key - .map(|public_key| ctx.get(&public_key)), disposable_signing_key: self.disposable_signing_key, tx_reveal_code_path: self.tx_reveal_code_path, password: self.password, @@ -5882,9 +5866,7 @@ pub mod args { chain_id: self .chain_id .or_else(|| Some(ctx.config.ledger.chain_id.clone())), - wrapper_fee_payer: self - .wrapper_fee_payer - .map(|x| ctx.get_cached(&x)), + wrapper_fee_payer: self.wrapper_fee_payer.map(|x| ctx.get(&x)), use_device: self.use_device, } } @@ -5968,10 +5950,7 @@ pub mod args { public key, public key hash or alias from your \ wallet.", ) - .conflicts_with_all([ - SIGNATURES.name, - VERIFICATION_KEY.name, - ]), + .conflicts_with_all([SIGNATURES.name]), ) .arg( SIGNATURES @@ -5981,25 +5960,12 @@ pub mod args { to be attached to a transaction. Requires to provide \ a gas payer.", ) - .conflicts_with_all([ - SIGNING_KEYS.name, - VERIFICATION_KEY.name, - ]) + .conflicts_with_all([SIGNING_KEYS.name]) .requires(FEE_PAYER_OPT.name), ) .arg(OUTPUT_FOLDER_PATH.def().help( "The output folder path where the artifact will be stored.", )) - .arg( - VERIFICATION_KEY - .def() - .help( - "Sign the transaction with the key for the given \ - public key, public key hash or alias from your \ - wallet.", - ) - .conflicts_with_all([SIGNING_KEYS.name, SIGNATURES.name]), - ) .arg(CHAIN_ID_OPT.def().help("The chain ID.")) .arg( FEE_PAYER_OPT @@ -6036,7 +6002,6 @@ pub mod args { let disposable_signing_key = DISPOSABLE_SIGNING_KEY.parse(matches); let signing_keys = SIGNING_KEYS.parse(matches); let signatures = SIGNATURES.parse(matches); - let verification_key = VERIFICATION_KEY.parse(matches); let tx_reveal_code_path = PathBuf::from(TX_REVEAL_PK); let chain_id = CHAIN_ID_OPT.parse(matches); let password = None; @@ -6060,7 +6025,6 @@ pub mod args { disposable_signing_key, signing_keys, signatures, - verification_key, tx_reveal_code_path, password, chain_id, diff --git a/apps/src/lib/cli/wallet.rs b/apps/src/lib/cli/wallet.rs index 4d22365f80..c0dcecd751 100644 --- a/apps/src/lib/cli/wallet.rs +++ b/apps/src/lib/cli/wallet.rs @@ -135,7 +135,7 @@ fn address_key_find( Ok(spending_key) => { display_line!(io, "Spending key: {}", spending_key) } - Err(FindKeyError::KeyNotFound) => {} + Err(FindKeyError::KeyNotFound(_)) => {} Err(err) => edisplay_line!(io, "{}", err), } } diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index a4a30c1c7d..583a7ee937 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -134,9 +134,12 @@ pub async fn sign( response_pubkey, pubkey, ))); } + // Remove unnecessary detail for Ledger signing + let mut compressed_tx = tx.clone(); + compressed_tx.wallet_filter(); // Get the Ledger to sign using our obtained derivation path let response = app - .sign(&path, &tx.serialize_to_vec()) + .sign(&path, &compressed_tx.serialize_to_vec()) .await .map_err(|err| error::Error::Other(err.to_string()))?; // Sign the raw header if that is requested @@ -383,8 +386,8 @@ pub async fn submit_change_consensus_key( let mut wallet = namada.wallet_mut().await; let consensus_key = consensus_key .map(|key| match key { - common::SecretKey::Ed25519(_) => key, - common::SecretKey::Secp256k1(_) => { + common::PublicKey::Ed25519(_) => key, + common::PublicKey::Secp256k1(_) => { edisplay_line!( namada.io(), "Consensus key can only be ed25519" @@ -406,6 +409,7 @@ pub async fn submit_change_consensus_key( ) .expect("Key generation should not fail.") .1 + .ref_to() }); // To avoid wallet deadlocks in following operations drop(wallet); @@ -413,7 +417,7 @@ pub async fn submit_change_consensus_key( // Check that the new consensus key is unique let consensus_keys = rpc::query_consensus_keys(namada.client()).await; - let new_ck = consensus_key.ref_to(); + let new_ck = consensus_key; if consensus_keys.contains(&new_ck) { edisplay_line!(namada.io(), "Consensus key can only be ed25519"); safe_exit(1) @@ -601,8 +605,8 @@ pub async fn submit_become_validator( let mut wallet = namada.wallet_mut().await; let consensus_key = consensus_key .map(|key| match key { - common::SecretKey::Ed25519(_) => key, - common::SecretKey::Secp256k1(_) => { + common::PublicKey::Ed25519(_) => key, + common::PublicKey::Secp256k1(_) => { edisplay_line!( namada.io(), "Consensus key can only be ed25519" @@ -625,12 +629,13 @@ pub async fn submit_become_validator( ) .expect("Key generation should not fail.") .1 + .ref_to() }); let eth_cold_pk = eth_cold_key .map(|key| match key { - common::SecretKey::Secp256k1(_) => key.ref_to(), - common::SecretKey::Ed25519(_) => { + common::PublicKey::Secp256k1(_) => key, + common::PublicKey::Ed25519(_) => { edisplay_line!( namada.io(), "Eth cold key can only be secp256k1" @@ -658,8 +663,8 @@ pub async fn submit_become_validator( let eth_hot_pk = eth_hot_key .map(|key| match key { - common::SecretKey::Secp256k1(_) => key.ref_to(), - common::SecretKey::Ed25519(_) => { + common::PublicKey::Secp256k1(_) => key, + common::PublicKey::Ed25519(_) => { edisplay_line!( namada.io(), "Eth hot key can only be secp256k1" @@ -727,7 +732,7 @@ pub async fn submit_become_validator( let mut tx = Tx::new(chain_id, tx_args.expiration); let data = BecomeValidator { address: address.clone(), - consensus_key: consensus_key.ref_to(), + consensus_key: consensus_key.clone(), eth_cold_key: key::secp256k1::PublicKey::try_from_pk(ð_cold_pk) .unwrap(), eth_hot_key: key::secp256k1::PublicKey::try_from_pk(ð_hot_pk) @@ -753,7 +758,7 @@ pub async fn submit_become_validator( }); let mut all_pks: Vec<_> = account.public_keys_map.pk_to_idx.into_keys().collect(); - all_pks.push(consensus_key.to_public()); + all_pks.push(consensus_key.clone()); all_pks.push(eth_cold_pk); all_pks.push(eth_hot_pk); all_pks.push(data.protocol_key.clone()); @@ -789,21 +794,21 @@ pub async fn submit_become_validator( if !tx_args.dry_run { // add validator address and keys to the wallet - namada - .wallet_mut() - .await - .add_validator_data(address.clone(), validator_keys); - namada - .wallet_mut() - .await + let mut wallet = namada.wallet_mut().await; + wallet.add_validator_data(address.clone(), validator_keys); + wallet .save() .unwrap_or_else(|err| edisplay_line!(namada.io(), "{}", err)); let tendermint_home = config.ledger.cometbft_dir(); tendermint_node::write_validator_key( &tendermint_home, - &consensus_key, + &wallet + .find_key_by_pk(&consensus_key, None) + .expect("unable to find consensus key pair in the wallet"), ); + // To avoid wallet deadlocks in following operations + drop(wallet); tendermint_node::write_validator_state(tendermint_home); // Write Namada config stuff or figure out how to do the above @@ -1039,8 +1044,14 @@ where ) .await?; + let mut wallet = namada.wallet_mut().await; let signed_offline_proposal = proposal.sign( - args.tx.signing_keys, + args.tx + .signing_keys + .iter() + .map(|pk| wallet.find_key_by_pk(pk, None)) + .collect::>() + .expect("secret keys corresponding to public keys not found"), &signing_data.account_public_keys_map.unwrap(), ); let output_file_path = signed_offline_proposal @@ -1186,8 +1197,14 @@ where delegations, ); + let mut wallet = namada.wallet_mut().await; let offline_signed_vote = offline_vote.sign( - args.tx.signing_keys, + args.tx + .signing_keys + .iter() + .map(|pk| wallet.find_key_by_pk(pk, None)) + .collect::>() + .expect("secret keys corresponding to public keys not found"), &signing_data.account_public_keys_map.unwrap(), ); let output_file_path = offline_signed_vote diff --git a/apps/src/lib/config/genesis/transactions.rs b/apps/src/lib/config/genesis/transactions.rs index b617b5a3bf..432335d263 100644 --- a/apps/src/lib/config/genesis/transactions.rs +++ b/apps/src/lib/config/genesis/transactions.rs @@ -345,7 +345,7 @@ pub fn sign_delegation_bond_tx( }; let source_key = match found_key { Ok(key) => key, - Err(FindKeyError::KeyNotFound) => { + Err(FindKeyError::KeyNotFound(_)) => { // If it's not in the wallet, it must be an established account // so we need to look-up its public key first let pk = established_accounts diff --git a/apps/src/lib/wallet/mod.rs b/apps/src/lib/wallet/mod.rs index 140a85f69d..6c1034c994 100644 --- a/apps/src/lib/wallet/mod.rs +++ b/apps/src/lib/wallet/mod.rs @@ -223,12 +223,13 @@ where { maybe_pk .map(|pk| { + let pkh = PublicKeyHash::from(&pk); wallet // TODO: optionally encrypt validator keys - .find_key_by_pkh(&PublicKeyHash::from(&pk), None) + .find_key_by_pkh(&pkh, None) .ok() .or_else(|| wallet.get_validator_data().map(extract_key)) - .ok_or(FindKeyError::KeyNotFound) + .ok_or_else(|| FindKeyError::KeyNotFound(pkh.to_string())) }) .transpose() } diff --git a/core/src/proto/types.rs b/core/src/proto/types.rs index 97c16f1b1d..ba90b4936f 100644 --- a/core/src/proto/types.rs +++ b/core/src/proto/types.rs @@ -507,7 +507,7 @@ impl Signature { // vector instead of a map assert!( secret_keys.keys().cloned().eq(0..(secret_keys.len() as u8)), - "secret keys must be enumerateed when signer address is absent" + "secret keys must be enumerated when signer address is absent" ); Signer::PubKeys(secret_keys.values().map(RefTo::ref_to).collect()) }; @@ -1573,9 +1573,15 @@ impl Tx { let hashes = vec![self.raw_header_hash()]; self.protocol_filter(); + let secret_keys = if signer.is_some() { + account_public_keys_map.index_secret_keys(keypairs) + } else { + (0..).zip(keypairs.into_iter()).collect() + }; + self.add_section(Section::Signature(Signature::new( hashes, - account_public_keys_map.index_secret_keys(keypairs), + secret_keys, signer, ))); self diff --git a/sdk/src/args.rs b/sdk/src/args.rs index a03ea49bfa..395c789f81 100644 --- a/sdk/src/args.rs +++ b/sdk/src/args.rs @@ -733,11 +733,11 @@ pub struct TxBecomeValidator { /// Signature scheme pub scheme: SchemeType, /// Consensus key - pub consensus_key: Option, + pub consensus_key: Option, /// Ethereum cold key - pub eth_cold_key: Option, + pub eth_cold_key: Option, /// Ethereum hot key - pub eth_hot_key: Option, + pub eth_hot_key: Option, /// Protocol key pub protocol_key: Option, /// Commission rate @@ -770,11 +770,11 @@ pub struct TxInitValidator { /// The account multisignature threshold pub threshold: Option, /// Consensus key - pub consensus_key: Option, + pub consensus_key: Option, /// Ethereum cold key - pub eth_cold_key: Option, + pub eth_cold_key: Option, /// Ethereum hot key - pub eth_hot_key: Option, + pub eth_hot_key: Option, /// Protocol key pub protocol_key: Option, /// Commission rate @@ -1399,7 +1399,7 @@ pub struct ConsensusKeyChange { /// Validator address (should be self) pub validator: C::Address, /// New consensus key - pub consensus_key: Option, + pub consensus_key: Option, /// Path to the TX WASM code file pub tx_code_path: PathBuf, } @@ -1865,7 +1865,7 @@ pub struct Tx { /// The amount being payed (for gas unit) to include the transaction pub fee_amount: Option, /// The fee payer signing key - pub wrapper_fee_payer: Option, + pub wrapper_fee_payer: Option, /// The token in which the fee is being paid pub fee_token: C::Address, /// The optional spending key for fee unshielding @@ -1880,13 +1880,11 @@ pub struct Tx { /// The chain id for which the transaction is intended pub chain_id: Option, /// Sign the tx with the key for the given alias from your wallet - pub signing_keys: Vec, + pub signing_keys: Vec, /// List of signatures to attach to the transaction pub signatures: Vec, /// Path to the TX WASM code file to reveal PK pub tx_reveal_code_path: PathBuf, - /// Sign the tx with the public key for the given alias from your wallet - pub verification_key: Option, /// Password to decrypt key pub password: Option>, /// Use device to sign the transaction @@ -1966,7 +1964,7 @@ pub trait TxBuilder: Sized { }) } /// The fee payer signing key - fn wrapper_fee_payer(self, wrapper_fee_payer: C::Keypair) -> Self { + fn wrapper_fee_payer(self, wrapper_fee_payer: C::PublicKey) -> Self { self.tx(|x| Tx { wrapper_fee_payer: Some(wrapper_fee_payer), ..x @@ -2010,7 +2008,7 @@ pub trait TxBuilder: Sized { }) } /// Sign the tx with the key for the given alias from your wallet - fn signing_keys(self, signing_keys: Vec) -> Self { + fn signing_keys(self, signing_keys: Vec) -> Self { self.tx(|x| Tx { signing_keys, ..x }) } /// List of signatures to attach to the transaction @@ -2024,13 +2022,6 @@ pub trait TxBuilder: Sized { ..x }) } - /// Sign the tx with the public key for the given alias from your wallet - fn verification_key(self, verification_key: C::PublicKey) -> Self { - self.tx(|x| Tx { - verification_key: Some(verification_key), - ..x - }) - } /// Password to decrypt key fn password(self, password: Zeroizing) -> Self { self.tx(|x| Tx { diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 4afc62e64a..8d667b7b31 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -138,7 +138,6 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { signing_keys: vec![], signatures: vec![], tx_reveal_code_path: PathBuf::from(TX_REVEAL_PK), - verification_key: None, password: None, use_device: false, } @@ -645,7 +644,6 @@ where signing_keys: vec![], signatures: vec![], tx_reveal_code_path: PathBuf::from(TX_REVEAL_PK), - verification_key: None, password: None, use_device: false, }, diff --git a/sdk/src/signing.rs b/sdk/src/signing.rs index e42193e461..16bab7e02f 100644 --- a/sdk/src/signing.rs +++ b/sdk/src/signing.rs @@ -134,21 +134,6 @@ pub fn find_key_by_pk( // We already know the secret key corresponding to the MASP sentinal key Ok(masp_tx_key()) } else { - // Try to get the signer from the signing-keys argument - for signing_key in &args.signing_keys { - if signing_key.ref_to() == *public_key { - return Ok(signing_key.clone()); - } - } - // Try to get the signer from the wrapper-fee-payer argument - match &args.wrapper_fee_payer { - Some(wrapper_fee_payer) - if &wrapper_fee_payer.ref_to() == public_key => - { - return Ok(wrapper_fee_payer.clone()); - } - _ => {} - } // Otherwise we need to search the wallet for the secret key wallet .find_key_by_pk(public_key, args.password.clone()) @@ -172,11 +157,7 @@ pub async fn tx_signers( default: Option
, ) -> Result, Error> { let signer = if !&args.signing_keys.is_empty() { - let public_keys = - args.signing_keys.iter().map(|key| key.ref_to()).collect(); - return Ok(public_keys); - } else if let Some(verification_key) = &args.verification_key { - return Ok(vec![verification_key.clone()]); + return Ok(args.signing_keys.clone()); } else { // Otherwise use the signer determined by the caller default @@ -367,7 +348,7 @@ pub async fn aux_signing_data( .to_public() } else { match &args.wrapper_fee_payer { - Some(keypair) => keypair.to_public(), + Some(keypair) => keypair.clone(), None => public_keys.get(0).ok_or(TxError::InvalidFeePayer)?.clone(), } }; @@ -412,7 +393,7 @@ pub async fn init_validator_signing_data( .to_public() } else { match &args.wrapper_fee_payer { - Some(keypair) => keypair.to_public(), + Some(keypair) => keypair.clone(), None => public_keys.get(0).ok_or(TxError::InvalidFeePayer)?.clone(), } }; diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index 9bf980aae5..d9c2e2b31d 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -927,11 +927,17 @@ pub async fn build_unjail_validator( Err(Error::Query( QueryError::NoSuchKey(_) | QueryError::General(_), )) => { - return Err(Error::from(TxError::Other(format!( + edisplay_line!( + context.io(), "The given validator address {} is currently frozen and not \ yet eligible to be unjailed.", &validator - )))); + ); + if !tx_args.force { + return Err(Error::from( + TxError::ValidatorFrozenFromUnjailing(validator.clone()), + )); + } } Err(err) => return Err(err), } diff --git a/sdk/src/wallet/mod.rs b/sdk/src/wallet/mod.rs index 28b25c1076..3fd5579a35 100644 --- a/sdk/src/wallet/mod.rs +++ b/sdk/src/wallet/mod.rs @@ -254,8 +254,8 @@ fn gen_spending_key( #[derive(Error, Debug)] pub enum FindKeyError { /// Could not find a given key in the wallet - #[error("No matching key found")] - KeyNotFound, + #[error("No key matching {0} found")] + KeyNotFound(String), /// Could not decrypt a given key in the wallet #[error("{0}")] KeyDecryptionError(keys::DecryptionError), @@ -403,9 +403,9 @@ impl Wallet { &mut self, alias: impl AsRef, ) -> Result<&ExtendedViewingKey, FindKeyError> { - self.store - .find_viewing_key(alias.as_ref()) - .ok_or(FindKeyError::KeyNotFound) + self.store.find_viewing_key(alias.as_ref()).ok_or_else(|| { + FindKeyError::KeyNotFound(alias.as_ref().to_string()) + }) } /// Find the payment address with the given alias in the wallet and return @@ -688,7 +688,9 @@ impl Wallet { let stored_key = self .store .find_secret_key(alias_pkh_or_pk.as_ref()) - .ok_or(FindKeyError::KeyNotFound)?; + .ok_or_else(|| { + FindKeyError::KeyNotFound(alias_pkh_or_pk.as_ref().to_string()) + })?; Self::decrypt_stored_key::<_>( &mut self.decrypted_key_cache, stored_key, @@ -705,7 +707,9 @@ impl Wallet { self.store .find_public_key(alias_or_pkh.as_ref()) .cloned() - .ok_or(FindKeyError::KeyNotFound) + .ok_or_else(|| { + FindKeyError::KeyNotFound(alias_or_pkh.as_ref().to_string()) + }) } /// Find the spending key with the given alias in the wallet and return it. @@ -726,7 +730,9 @@ impl Wallet { let stored_spendkey = self .store .find_spending_key(alias.as_ref()) - .ok_or(FindKeyError::KeyNotFound)?; + .ok_or_else(|| { + FindKeyError::KeyNotFound(alias.as_ref().to_string()) + })?; Self::decrypt_stored_key::<_>( &mut self.decrypted_spendkey_cache, stored_spendkey, @@ -756,7 +762,7 @@ impl Wallet { ) -> Result { self.store .find_path_by_pkh(pkh) - .ok_or(FindKeyError::KeyNotFound) + .ok_or_else(|| FindKeyError::KeyNotFound(pkh.to_string())) } /// Find the public key by a public key hash. @@ -770,7 +776,7 @@ impl Wallet { self.store .find_public_key_by_pkh(pkh) .cloned() - .ok_or(FindKeyError::KeyNotFound) + .ok_or_else(|| FindKeyError::KeyNotFound(pkh.to_string())) } /// Find the stored key by a public key hash. @@ -795,7 +801,7 @@ impl Wallet { let stored_key = self .store .find_key_by_pkh(pkh) - .ok_or(FindKeyError::KeyNotFound)?; + .ok_or_else(|| FindKeyError::KeyNotFound(pkh.to_string()))?; Self::decrypt_stored_key( &mut self.decrypted_key_cache, stored_key, @@ -830,7 +836,7 @@ impl Wallet { decrypted_key_cache .get(&alias) .cloned() - .ok_or(FindKeyError::KeyNotFound) + .ok_or_else(|| FindKeyError::KeyNotFound(alias.to_string())) } StoredKeypair::Raw(raw) => Ok(raw.clone()), } diff --git a/sdk/src/wallet/store.rs b/sdk/src/wallet/store.rs index 980aa6ae70..4211af3ccc 100644 --- a/sdk/src/wallet/store.rs +++ b/sdk/src/wallet/store.rs @@ -631,15 +631,17 @@ impl Store { let account_pk = other.account_key.ref_to(); let consensus_pk = other.consensus_key.ref_to(); let tendermint_node_pk = other.tendermint_node_key.ref_to(); - let addresses = [ - (account_key_alias.clone(), (&account_pk).into()), - (consensus_key_alias.clone(), (&consensus_pk).into()), + let public_keys = [ + (account_key_alias.clone(), account_pk.clone()), + (consensus_key_alias.clone(), consensus_pk.clone()), ( tendermint_node_key_alias.clone(), - (&tendermint_node_pk).into(), + tendermint_node_pk.clone(), ), ]; - self.addresses.extend(addresses.into_iter()); + self.public_keys.extend(public_keys.clone().into_iter()); + self.addresses + .extend(public_keys.into_iter().map(|(k, v)| (k, (&v).into()))); let pkhs = [ ((&account_pk).into(), account_key_alias),