diff --git a/Cargo.lock b/Cargo.lock index 3e13da1ec3..3fca809348 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4401,7 +4401,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=e6451ecf64d519409f9b1a67aa1d8322a9fe0717#e6451ecf64d519409f9b1a67aa1d8322a9fe0717" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "arbitrary", "borsh", @@ -4415,7 +4415,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=e6451ecf64d519409f9b1a67aa1d8322a9fe0717#e6451ecf64d519409f9b1a67aa1d8322a9fe0717" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "aes", "arbitrary", @@ -4448,7 +4448,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=e6451ecf64d519409f9b1a67aa1d8322a9fe0717#e6451ecf64d519409f9b1a67aa1d8322a9fe0717" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "bellman", "blake2b_simd", diff --git a/Cargo.toml b/Cargo.toml index 230d1d75eb..3c315683ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -138,8 +138,8 @@ libc = "0.2.97" libloading = "0.7.2" linkme = "0.3.24" # branch = "tomas/arbitrary" -masp_primitives = { git = "https://github.com/anoma/masp", rev = "e6451ecf64d519409f9b1a67aa1d8322a9fe0717" } -masp_proofs = { git = "https://github.com/anoma/masp", rev = "e6451ecf64d519409f9b1a67aa1d8322a9fe0717", default-features = false, features = ["local-prover"] } +masp_primitives = { git = "https://github.com/anoma/masp", rev = "f2b0cae3e495e4f7d482e587432ec4e5f2793528" } +masp_proofs = { git = "https://github.com/anoma/masp", rev = "f2b0cae3e495e4f7d482e587432ec4e5f2793528", default-features = false, features = ["local-prover"] } num256 = "0.3.5" num_cpus = "1.13.0" num-derive = "0.4" diff --git a/crates/apps_lib/src/cli/context.rs b/crates/apps_lib/src/cli/context.rs index 633a37c587..0ec0f03582 100644 --- a/crates/apps_lib/src/cli/context.rs +++ b/crates/apps_lib/src/cli/context.rs @@ -6,6 +6,11 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; use color_eyre::eyre::Result; +use masp_primitives::zip32::sapling::PseudoExtendedKey; +use masp_primitives::zip32::{ + ExtendedFullViewingKey as MaspExtendedViewingKey, + ExtendedSpendingKey as MaspExtendedSpendingKey, +}; use namada_sdk::address::{Address, InternalAddress}; use namada_sdk::chain::ChainId; use namada_sdk::ethereum_events::EthAddress; @@ -16,7 +21,6 @@ use namada_sdk::masp::fs::FsShieldedUtils; use namada_sdk::masp::{ShieldedContext, *}; use namada_sdk::wallet::{DatedSpendingKey, DatedViewingKey, Wallet}; use namada_sdk::{Namada, NamadaImpl}; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; use super::args; use crate::cli::utils; @@ -44,7 +48,7 @@ pub type WalletAddrOrNativeToken = FromContext; /// A raw extended spending key (bech32m encoding) or an alias of an extended /// spending key in the wallet -pub type WalletSpendingKey = FromContext; +pub type WalletSpendingKey = FromContext; /// A raw dated extended spending key (bech32m encoding) or an alias of an /// extended spending key in the wallet @@ -585,33 +589,45 @@ impl ArgFromMutContext for ExtendedSpendingKey { } } -impl ArgFromMutContext for PseudoExtendedSpendingKey { +impl ArgFromMutContext for PseudoExtendedKey { fn arg_from_mut_ctx( ctx: &mut ChainContext, raw: impl AsRef, ) -> Result { let raw = raw.as_ref(); // Either the string is a raw extended spending key - ExtendedSpendingKey::from_str(raw).map( - |x| PseudoExtendedSpendingKey::from_spending_key(x.into()) - ).or_else(|_parse_err| { - ExtendedViewingKey::from_str(raw).map( - |x| PseudoExtendedSpendingKey::from_viewing_key(x.into()) - ) - }).or_else(|_parse_err| { - // Or it is a stored alias of one - ctx.wallet - .find_spending_key(raw, None) - .map(|k| PseudoExtendedSpendingKey::from_spending_key(k.key.into())) - .map_err(|_find_err| format!("Unknown spending key {}", raw)) - }).or_else(|_parse_err| { - // Or it is a stored alias of one - ctx.wallet - .find_viewing_key(raw) - .copied() - .map(|k| PseudoExtendedSpendingKey::from_viewing_key(k.key.into())) - .map_err(|_find_err| format!("Unknown viewing key {}", raw)) - }) + ExtendedSpendingKey::from_str(raw) + .map(|x| PseudoExtendedKey::from(MaspExtendedSpendingKey::from(x))) + .or_else(|_parse_err| { + ExtendedViewingKey::from_str(raw).map(|x| { + PseudoExtendedKey::from(MaspExtendedViewingKey::from(x)) + }) + }) + .or_else(|_parse_err| { + // Or it is a stored alias of one + ctx.wallet + .find_spending_key(raw, None) + .map(|k| { + PseudoExtendedKey::from(MaspExtendedSpendingKey::from( + k.key, + )) + }) + .map_err(|_find_err| { + format!("Unknown spending key {}", raw) + }) + }) + .or_else(|_parse_err| { + // Or it is a stored alias of one + ctx.wallet + .find_viewing_key(raw) + .copied() + .map(|k| { + PseudoExtendedKey::from(MaspExtendedViewingKey::from( + k.key, + )) + }) + .map_err(|_find_err| format!("Unknown viewing key {}", raw)) + }) } } @@ -693,12 +709,18 @@ impl ArgFromMutContext for TransferSource { Address::arg_from_ctx(ctx, raw) .map(Self::Address) .or_else(|_| { - ExtendedSpendingKey::arg_from_mut_ctx(ctx, raw) - .map(|x| Self::ExtendedSpendingKey(PseudoExtendedSpendingKey::from_spending_key(x.into()))) + ExtendedSpendingKey::arg_from_mut_ctx(ctx, raw).map(|x| { + Self::ExtendedSpendingKey(PseudoExtendedKey::from( + MaspExtendedSpendingKey::from(x), + )) + }) }) .or_else(|_| { - ExtendedViewingKey::arg_from_mut_ctx(ctx, raw) - .map(|x| Self::ExtendedSpendingKey(PseudoExtendedSpendingKey::from_viewing_key(x.into()))) + ExtendedViewingKey::arg_from_mut_ctx(ctx, raw).map(|x| { + Self::ExtendedSpendingKey(PseudoExtendedKey::from( + MaspExtendedViewingKey::from(x), + )) + }) }) } } diff --git a/crates/apps_lib/src/cli/wallet.rs b/crates/apps_lib/src/cli/wallet.rs index c83912b7d3..62ef8a957c 100644 --- a/crates/apps_lib/src/cli/wallet.rs +++ b/crates/apps_lib/src/cli/wallet.rs @@ -270,7 +270,10 @@ async fn shielded_key_derive( cli::safe_exit(1) }; let xfvk = ExtendedFullViewingKey::try_from_slice(&response_key.xfvk) - .expect("unable to decode extended full viewing key from the hardware wallet"); + .expect( + "unable to decode extended full viewing key from the hardware \ + wallet", + ); wallet .insert_viewing_key( @@ -416,7 +419,13 @@ fn shielded_key_address_add( let (alias, typ) = match masp_value { MaspValue::FullViewingKey(viewing_key) => { let alias = wallet - .insert_viewing_key(alias, viewing_key, birthday, alias_force, None) + .insert_viewing_key( + alias, + viewing_key, + birthday, + alias_force, + None, + ) .unwrap_or_else(|| { edisplay_line!(io, "Viewing key not added"); cli::safe_exit(1); diff --git a/crates/apps_lib/src/client/tx.rs b/crates/apps_lib/src/client/tx.rs index 74e8a0d4ed..618fdd2cf6 100644 --- a/crates/apps_lib/src/client/tx.rs +++ b/crates/apps_lib/src/client/tx.rs @@ -3,16 +3,25 @@ use std::io::Write; use borsh::BorshDeserialize; use borsh_ext::BorshSerializeExt; -use ledger_namada_rs::{BIP44Path, NamadaApp, KeyResponse, NamadaKeys}; +use ledger_namada_rs::{BIP44Path, KeyResponse, NamadaApp, NamadaKeys}; +use masp_primitives::sapling::redjubjub::PrivateKey; +use masp_primitives::sapling::{redjubjub, ProofGenerationKey}; +use masp_primitives::transaction::components::sapling::builder::{ + BuildParams, ConvertBuildParams, OutputBuildParams, RngBuildParams, + SpendBuildParams, StoredBuildParams, +}; +use masp_primitives::transaction::components::sapling::fees::InputView; +use masp_primitives::zip32::{ExtendedFullViewingKey, ExtendedKey}; use namada_sdk::address::{Address, ImplicitAddress}; use namada_sdk::args::TxBecomeValidator; -use namada_sdk::collections::HashSet; +use namada_sdk::collections::{HashMap, HashSet}; use namada_sdk::governance::cli::onchain::{ DefaultProposal, PgfFundingProposal, PgfStewardProposal, }; use namada_sdk::ibc::convert_masp_tx_to_ibc_memo; use namada_sdk::io::Io; use namada_sdk::key::*; +use namada_sdk::masp::ExtendedViewingKey; use namada_sdk::rpc::{InnerTxResult, TxBroadcastData, TxResponse}; use namada_sdk::state::EPOCH_SWITCH_BLOCKS_DELAY; use namada_sdk::tx::data::compute_inner_tx_hash; @@ -22,24 +31,13 @@ use namada_sdk::wallet::{Wallet, WalletIo}; use namada_sdk::{display_line, edisplay_line, error, signing, tx, Namada}; use rand::rngs::OsRng; use tokio::sync::RwLock; -use namada_sdk::masp::ExtendedViewingKey; -use masp_primitives::zip32::ExtendedFullViewingKey; -use masp_primitives::sapling::ProofGenerationKey; -use namada_sdk::collections::HashMap; -use masp_primitives::sapling::redjubjub; -use masp_primitives::transaction::components::sapling::fees::InputView; -use crate::masp_primitives::transaction::components::sapling; - -use masp_primitives::transaction::components::sapling::builder::{ - BuildParams, ConvertBuildParams, OutputBuildParams, RngBuildParams, - SpendBuildParams, StoredBuildParams, -}; use super::rpc; use crate::cli::{args, safe_exit}; use crate::client::tx::signing::{default_sign, SigningTxData}; use crate::client::tx::tx::ProcessTxResponse; use crate::config::TendermintMode; +use crate::masp_primitives::transaction::components::sapling; use crate::tendermint_node; use crate::tendermint_rpc::endpoint::broadcast::tx_sync::Response; use crate::wallet::{ @@ -801,7 +799,9 @@ struct MapSaplingSigAuth( HashMap::AuthSig>, ); -impl sapling::MapAuth for MapSaplingSigAuth { +impl sapling::MapAuth + for MapSaplingSigAuth +{ fn map_proof( &self, p: ::Proof, @@ -838,73 +838,96 @@ pub async fn submit_shielded_transfer( // Augment the pseudo spending key with a proof authorization key for data in &mut args.data { // Only attempt an augmentation if proof authorization is not there - if data.source.partial_spending_key().is_none() { + if data.source.to_spending_key().is_none() { // First find the derivation path corresponding to this viewing // key let viewing_key = ExtendedViewingKey::from(data.source.to_viewing_key()); let path = wallet .find_path_by_viewing_key(&viewing_key) - .map_err(|err| error::Error::Other(format!( - "Unable to find derivation path from the wallet for \ - viewing key {}. Error: {}", - viewing_key, - err, - )))?; - let path = BIP44Path { path: path.to_string() }; + .map_err(|err| { + error::Error::Other(format!( + "Unable to find derivation path from the wallet \ + for viewing key {}. Error: {}", + viewing_key, err, + )) + })?; + let path = BIP44Path { + path: path.to_string(), + }; // Then confirm that the viewing key at this path in the // hardware wallet matches the viewing key in this pseudo // spending key let response = app .retrieve_keys(&path, NamadaKeys::ViewKey, true) .await - .map_err(|err| error::Error::Other(format!( - "Unable to obtain viewing key from the hardware wallet \ - at path {}. Error: {}", - path.path, - err, - )))?; + .map_err(|err| { + error::Error::Other(format!( + "Unable to obtain viewing key from the hardware \ + wallet at path {}. Error: {}", + path.path, err, + )) + })?; let KeyResponse::ViewKey(response_key) = response else { return Err(error::Error::Other( "Unexpected response from Ledger".to_string(), - )) + )); }; - let xfvk = ExtendedFullViewingKey::try_from_slice(&response_key.xfvk) - .expect("unable to decode extended full viewing key from the hardware wallet"); + let xfvk = + ExtendedFullViewingKey::try_from_slice(&response_key.xfvk) + .expect( + "unable to decode extended full viewing key from \ + the hardware wallet", + ); if ExtendedFullViewingKey::from(viewing_key) != xfvk { return Err(error::Error::Other(format!( "Unexpected viewing key response from Ledger: {}", ExtendedViewingKey::from(xfvk), - ))) + ))); } // Then obtain the proof authorization key at this path in the // hardware wallet let response = app .retrieve_keys(&path, NamadaKeys::ProofGenerationKey, false) .await - .map_err(|err| error::Error::Other(format!( - "Unable to obtain proof generation key from the \ - hardware wallet for viewing key {}. Error: {}", - viewing_key, - err, - )))?; + .map_err(|err| { + error::Error::Other(format!( + "Unable to obtain proof generation key from the \ + hardware wallet for viewing key {}. Error: {}", + viewing_key, err, + )) + })?; let KeyResponse::ProofGenKey(response_key) = response else { return Err(error::Error::Other( "Unexpected response from Ledger".to_string(), - )) + )); }; let pgk = ProofGenerationKey::try_from_slice( &[response_key.ak, response_key.nsk].concat(), - ).map_err(|err| error::Error::Other(format!( - "Unexpected proof generation key in response from the \ - hardware wallet: {}.", - err, - )))?; - // Finally augment the pseudo spending key - data.source.augment(pgk).map_err(|_| error::Error::Other(format!( - "Proof generation key in response from the hardware wallet \ - does not correspond to stored viewing key.", - )))?; + ) + .map_err(|err| { + error::Error::Other(format!( + "Unexpected proof generation key in response from the \ + hardware wallet: {}.", + err, + )) + })?; + // Augment the pseudo spending key + data.source.augment_proof_generation_key(pgk).map_err( + |_| { + error::Error::Other( + "Proof generation key in response from the \ + hardware wallet does not correspond to stored \ + viewing key." + .to_string(), + ) + }, + )?; + // Finally, augment an incorrect spend authorization key just to + // make sure that the Transaction is built. + data.source.augment_spend_authorizing_key_unchecked( + PrivateKey(jubjub::Fr::default()), + ); shielded_hw_keys.insert(path.path, viewing_key); } } @@ -938,7 +961,6 @@ pub async fn submit_shielded_transfer( .map_err(|err| error::Error::Other(err.to_string()))?; bparams.convert_params.push(ConvertBuildParams { rcv: jubjub::Fr::from_bytes(&convert_randomness.rcv).unwrap(), - ..ConvertBuildParams::default() }); } for _ in 0..output_len { @@ -956,20 +978,23 @@ pub async fn submit_shielded_transfer( } else { Box::new(RngBuildParams::new(OsRng)) }; - let (mut tx, signing_data) = args.clone().build(namada, &mut bparams).await?; + let (mut tx, signing_data) = + args.clone().build(namada, &mut bparams).await?; if args.tx.dump_tx { tx::dump_tx(namada.io(), &args.tx, tx); } else { // Get the MASP section that is the target of our signing if let Some(shielded_hash) = signing_data.shielded_hash { - let mut masp_tx = tx.get_masp_section(&shielded_hash) + let mut masp_tx = tx + .get_masp_section(&shielded_hash) .expect("Expected to find the indicated MASP Transaction") .clone(); - let masp_builder = tx.get_masp_builder(&shielded_hash) + let masp_builder = tx + .get_masp_builder(&shielded_hash) .expect("Expected to find the indicated MASP Builder"); - + // Reverse the spend metadata to enable looking up construction // material let sapling_inputs = masp_builder.builder.sapling_inputs(); @@ -987,9 +1012,10 @@ pub async fn submit_shielded_transfer( let app = NamadaApp::new(transport); for (path, vk) in shielded_hw_keys { // Sign the MASP Transaction using the current viewing key - let path = BIP44Path { path: path.to_string() }; - let response = app - .sign_masp(&path, &tx.serialize_to_vec()) + let path = BIP44Path { + path: path.to_string(), + }; + app.sign_masp(&path, &tx.serialize_to_vec()) .await .map_err(|err| error::Error::Other(err.to_string()))?; // Now prepare a new list of authorizations based on hardware @@ -1004,12 +1030,17 @@ pub async fn submit_shielded_transfer( .map_err(|err| error::Error::Other(err.to_string()))?; let signature = redjubjub::Signature::try_from_slice( &[response.rbar, response.sbar].concat(), - ).map_err(|err| error::Error::Other(format!( - "Unexpected spend authorization key in response from the \ - hardware wallet: {}.", - err, - )))?; - if *sapling_inputs[*builder_pos].key() == ExtendedFullViewingKey::from(vk) { + ) + .map_err(|err| { + error::Error::Other(format!( + "Unexpected spend authorization key in response \ + from the hardware wallet: {}.", + err, + )) + })?; + if *sapling_inputs[*builder_pos].key() + == ExtendedFullViewingKey::from(vk) + { // If this descriptor was produced by the current // viewing key (which comes from the hardware wallet), // then use the authorization from the hardware wallet @@ -1027,6 +1058,8 @@ pub async fn submit_shielded_transfer( err, )))?; } + tx.remove_masp_section(&shielded_hash); + tx.add_section(Section::MaspTx(masp_tx)); } sign(namada, &mut tx, &args.tx, signing_data).await?; namada.submit(tx, &args.tx).await?; diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 536d337f23..6d9bdc21df 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -10,6 +10,7 @@ use masp_primitives::sapling::Node; use masp_primitives::transaction::sighash::{signature_hash, SignableInput}; use masp_primitives::transaction::txid::TxIdDigester; use masp_primitives::transaction::TransactionData; +use masp_primitives::zip32::ExtendedSpendingKey; use masp_proofs::group::GroupEncoding; use masp_proofs::sapling::BatchValidator; use namada_apps_lib::address::{self, Address, InternalAddress}; @@ -403,7 +404,9 @@ fn prepare_ibc_tx_and_ctx(bench_name: &str) -> (BenchShieldedCtx, BatchedTx) { shielded_ctx.shell.write().commit_block(); shielded_ctx.generate_shielded_action( Amount::native_whole(10), - TransferSource::ExtendedSpendingKey(albert_spending_key.key), + TransferSource::ExtendedSpendingKey( + ExtendedSpendingKey::from(albert_spending_key.key).into(), + ), defaults::bertha_address().to_string(), ) } @@ -595,12 +598,16 @@ fn setup_storage_for_masp_verification( ), "unshielding" => shielded_ctx.generate_masp_tx( amount, - TransferSource::ExtendedSpendingKey(albert_spending_key.key), + TransferSource::ExtendedSpendingKey( + ExtendedSpendingKey::from(albert_spending_key.key).into(), + ), TransferTarget::Address(defaults::albert_address()), ), "shielded" => shielded_ctx.generate_masp_tx( amount, - TransferSource::ExtendedSpendingKey(albert_spending_key.key), + TransferSource::ExtendedSpendingKey( + ExtendedSpendingKey::from(albert_spending_key.key).into(), + ), TransferTarget::PaymentAddress(bertha_payment_addr), ), _ => panic!("Unexpected bench test"), diff --git a/crates/core/src/masp.rs b/crates/core/src/masp.rs index e8aa961d06..349874e72c 100644 --- a/crates/core/src/masp.rs +++ b/crates/core/src/masp.rs @@ -10,8 +10,9 @@ use borsh_ext::BorshSerializeExt; use masp_primitives::asset_type::AssetType; use masp_primitives::sapling::ViewingKey; use masp_primitives::transaction::TransparentAddress; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; pub use masp_primitives::transaction::TxId as TxIdInner; +use masp_primitives::zip32::sapling::PseudoExtendedKey; +use masp_primitives::zip32::ExtendedKey; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; @@ -68,7 +69,7 @@ pub struct MaspTxId( serialize_with = "serialize_txid", deserialize_with = "deserialize_txid" )] - TxIdInner, + pub TxIdInner, ); impl From for MaspTxId { @@ -513,12 +514,13 @@ impl<'de> serde::Deserialize<'de> for ExtendedSpendingKey { } /// Represents a source of funds for a transfer +#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, Hash, Eq, PartialEq)] pub enum TransferSource { /// A transfer coming from a transparent address Address(Address), /// A transfer coming from a shielded address - ExtendedSpendingKey(PseudoExtendedSpendingKey), + ExtendedSpendingKey(PseudoExtendedKey), } impl TransferSource { @@ -533,7 +535,7 @@ impl TransferSource { } /// Get the contained ExtendedSpendingKey contained, if any - pub fn spending_key(&self) -> Option { + pub fn spending_key(&self) -> Option { match self { Self::ExtendedSpendingKey(x) => Some(*x), _ => None, @@ -561,7 +563,9 @@ impl Display for TransferSource { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Address(x) => x.fmt(f), - Self::ExtendedSpendingKey(x) => ExtendedViewingKey::from(x.to_viewing_key()).fmt(f), + Self::ExtendedSpendingKey(x) => { + ExtendedViewingKey::from(x.to_viewing_key()).fmt(f) + } } } } diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index 9dc6da077f..a970dca0de 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -14,6 +14,7 @@ use std::sync::{Arc, Once, RwLock, RwLockReadGuard, RwLockWriteGuard}; use borsh::{BorshDeserialize, BorshSerialize}; use borsh_ext::BorshSerializeExt; +use masp_primitives::transaction::components::sapling::builder::RngBuildParams; use masp_primitives::transaction::Transaction; use masp_primitives::zip32::ExtendedFullViewingKey; use masp_proofs::prover::LocalTxProver; @@ -1211,6 +1212,7 @@ impl BenchShieldedCtx { vec![masp_transfer_data], None, true, + &mut RngBuildParams::new(OsRng), ), ) .unwrap() diff --git a/crates/sdk/src/args.rs b/crates/sdk/src/args.rs index 91c76d7201..8cc7f081e5 100644 --- a/crates/sdk/src/args.rs +++ b/crates/sdk/src/args.rs @@ -6,8 +6,7 @@ use std::str::FromStr; use std::time::Duration as StdDuration; use masp_primitives::transaction::components::sapling::builder::BuildParams; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; - +use masp_primitives::zip32::sapling::PseudoExtendedKey; use namada_core::address::Address; use namada_core::chain::{BlockHeight, ChainId, Epoch}; use namada_core::collections::HashMap; @@ -121,7 +120,7 @@ impl NamadaTypes for SdkTypes { type MaspIndexerAddress = String; type PaymentAddress = namada_core::masp::PaymentAddress; type PublicKey = namada_core::key::common::PublicKey; - type SpendingKey = PseudoExtendedSpendingKey; + type SpendingKey = PseudoExtendedKey; type TendermintAddress = tendermint_rpc::Url; type TransferSource = namada_core::masp::TransferSource; type TransferTarget = namada_core::masp::TransferTarget; diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs index ccab6ea824..05407a1c1b 100644 --- a/crates/sdk/src/lib.rs +++ b/crates/sdk/src/lib.rs @@ -51,10 +51,10 @@ pub use std::marker::Sync as MaybeSync; use std::path::PathBuf; use std::str::FromStr; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; use args::{DeviceTransport, InputAmount, SdkTypes}; use io::Io; use masp::{ShieldedContext, ShieldedUtils}; +use masp_primitives::zip32::sapling::PseudoExtendedKey; use namada_core::address::Address; use namada_core::collections::HashSet; pub use namada_core::control_flow; @@ -62,7 +62,7 @@ use namada_core::dec::Dec; use namada_core::ethereum_events::EthAddress; use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada_core::key::*; -use namada_core::masp::{ExtendedSpendingKey, PaymentAddress, TransferSource}; +use namada_core::masp::{PaymentAddress, TransferSource}; use namada_tx::data::wrapper::GasLimit; use namada_tx::Tx; use rpc::{denominate_amount, format_denominated_amount, query_native_token}; @@ -190,7 +190,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { fn new_shielded_transfer( &self, data: Vec, - gas_spending_keys: Vec, + gas_spending_keys: Vec, disposable_signing_key: bool, ) -> args::TxShieldedTransfer { args::TxShieldedTransfer { @@ -221,9 +221,9 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { /// arguments fn new_unshielding_transfer( &self, - source: PseudoExtendedSpendingKey, + source: PseudoExtendedKey, data: Vec, - gas_spending_keys: Vec, + gas_spending_keys: Vec, disposable_signing_key: bool, ) -> args::TxUnshieldingTransfer { args::TxUnshieldingTransfer { diff --git a/crates/sdk/src/masp.rs b/crates/sdk/src/masp.rs index 927c430671..f1b18c6438 100644 --- a/crates/sdk/src/masp.rs +++ b/crates/sdk/src/masp.rs @@ -27,16 +27,17 @@ use masp_primitives::sapling::{ }; use masp_primitives::transaction::builder::{self, *}; use masp_primitives::transaction::components::sapling::builder::{ - BuildParams, RngBuildParams, SaplingMetadata, + BuildParams, SaplingMetadata, }; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; use masp_primitives::transaction::components::{ I128Sum, TxOut, U64Sum, ValueSum, }; use masp_primitives::transaction::fees::fixed::FeeRule; use masp_primitives::transaction::Transaction; +use masp_primitives::zip32::sapling::PseudoExtendedKey; use masp_primitives::zip32::{ - ExtendedFullViewingKey, ExtendedSpendingKey as MaspExtendedSpendingKey, + ExtendedFullViewingKey, ExtendedKey, + ExtendedSpendingKey as MaspExtendedSpendingKey, }; use masp_proofs::prover::LocalTxProver; use namada_core::address::Address; @@ -111,7 +112,7 @@ pub struct ShieldedTransfer { #[allow(missing_docs)] #[derive(Debug)] pub struct MaspFeeData { - pub sources: Vec, + pub sources: Vec, pub target: Address, pub token: Address, pub amount: token::DenominatedAmount, @@ -160,7 +161,7 @@ struct MaspTxReorderedData { // Data about the unspent amounts for any given shielded source coming from the // spent notes in their posses that have been added to the builder. Can be used // to either pay fees or to return a change -type Changes = HashMap; +type Changes = HashMap; /// Shielded pool data for a token #[allow(missing_docs)] @@ -198,20 +199,20 @@ struct WalletMap; impl masp_primitives::transaction::components::sapling::builder::MapBuilder< P1, - MaspExtendedSpendingKey, + PseudoExtendedKey, (), ExtendedFullViewingKey, > for WalletMap { fn map_params(&self, _s: P1) {} - fn map_key(&self, s: MaspExtendedSpendingKey) -> ExtendedFullViewingKey { - (&s).into() + fn map_key(&self, s: PseudoExtendedKey) -> ExtendedFullViewingKey { + s.to_viewing_key() } } impl - MapBuilder + MapBuilder for WalletMap { fn map_notifier(&self, _s: N1) {} @@ -942,7 +943,7 @@ impl ShieldedContext { &mut self, context: &impl Namada, spent_notes: &mut SpentNotesTracker, - sk: PseudoExtendedSpendingKey, + sk: PseudoExtendedKey, is_native_token: bool, target: I128Sum, target_epoch: MaspEpoch, @@ -1227,7 +1228,7 @@ impl ShieldedContext { u32::MAX - 20 } }; - let mut builder = Builder::::new( + let mut builder = Builder::::new( NETWORK, // NOTE: this is going to add 20 more blocks to the actual // expiration but there's no other exposed function that we could @@ -1437,7 +1438,7 @@ impl ShieldedContext { #[allow(clippy::too_many_arguments)] async fn add_inputs( context: &impl Namada, - builder: &mut Builder, + builder: &mut Builder, source: &TransferSource, token: &Address, amount: &token::DenominatedAmount, @@ -1496,16 +1497,7 @@ impl ShieldedContext { // Commit the notes found to our transaction for (diversifier, note, merkle_path) in unspent_notes { builder - .add_sapling_spend( - sk.partial_spending_key().ok_or_else(|| { - Error::Other(format!( - "Unable to get proof authorization" - )) - })?, - diversifier, - note, - merkle_path, - ) + .add_sapling_spend(sk, diversifier, note, merkle_path) .map_err(|e| TransferErr::Build { error: builder::Error::SaplingBuild(e), data: None, @@ -1570,7 +1562,7 @@ impl ShieldedContext { #[allow(clippy::too_many_arguments)] async fn add_outputs( context: &impl Namada, - builder: &mut Builder, + builder: &mut Builder, source: TransferSource, target: &TransferTarget, token: Address, @@ -1618,9 +1610,8 @@ impl ShieldedContext { let contr = std::cmp::min(*rem_amount as u128, val) as u64; // If we are sending to a shielded address, we need the outgoing // viewing key in the following computations. - let ovk_opt = source - .spending_key() - .map(|x| x.to_viewing_key().fvk.ovk); + let ovk_opt = + source.spending_key().map(|x| x.to_viewing_key().fvk.ovk); // Make transaction output tied to the current token, // denomination, and epoch. if let Some(pa) = payment_address { @@ -1711,9 +1702,9 @@ impl ShieldedContext { #[allow(clippy::too_many_arguments)] async fn add_fees( context: &impl Namada, - builder: &mut Builder, + builder: &mut Builder, source_data: &HashMap, - sources: Vec, + sources: Vec, target: &Address, token: &Address, amount: &token::DenominatedAmount, @@ -1949,21 +1940,17 @@ impl ShieldedContext { // `add_fees` cause we might have some change coming from there too #[allow(clippy::result_large_err)] fn add_changes( - builder: &mut Builder, + builder: &mut Builder, changes: Changes, ) -> Result<(), TransferErr> { for (sp, changes) in changes.into_iter() { for (asset_type, amt) in changes.components() { if let Ordering::Greater = amt.cmp(&0) { - let sk = sp.partial_spending_key().ok_or_else(|| { - Error::Other(format!( - "Unable to get proof authorization" - )) - })?; + let sk = sp.to_viewing_key(); // Send the change in this asset type back to the sender builder .add_sapling_output( - Some(sk.expsk.ovk), + Some(sk.fvk.ovk), sk.default_address().1, *asset_type, *amt as u64, @@ -2319,7 +2306,9 @@ pub mod testing { use masp_primitives::sapling::prover::TxProver; use masp_primitives::sapling::redjubjub::{PublicKey, Signature}; use masp_primitives::sapling::{ProofGenerationKey, Rseed}; - use masp_primitives::transaction::components::sapling::builder::StoredBuildParams; + use masp_primitives::transaction::components::sapling::builder::{ + RngBuildParams, StoredBuildParams, + }; use masp_primitives::transaction::components::{ OutputDescription, GROTH_PROOF_SIZE, }; @@ -2662,7 +2651,7 @@ pub mod testing { mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), prover_rng in arb_rng().prop_map(TestCsprng), - ) -> (MaspExtendedSpendingKey, Diversifier, Note, Node) { + ) -> (PseudoExtendedKey, Diversifier, Note, Node) { let mut spending_key_seed = [0; 32]; rng.fill_bytes(&mut spending_key_seed); let spending_key = MaspExtendedSpendingKey::master(spending_key_seed.as_ref()); @@ -2673,7 +2662,7 @@ pub mod testing { .to_payment_address(div) .expect("a PaymentAddress"); - let mut builder = Builder::::new( + let mut builder = Builder::::new( NETWORK, // NOTE: this is going to add 20 more blocks to the actual // expiration but there's no other exposed function that we could @@ -2707,7 +2696,7 @@ pub mod testing { assert_eq!(payment_addr, pa); // Make a path to out new note let node = Node::new(shielded_output.cmu.to_repr()); - (spending_key, div, note, node) + (PseudoExtendedKey::from(spending_key), div, note, node) } } @@ -2757,7 +2746,7 @@ pub mod testing { ).unwrap(), *value, )).collect::>() - ) -> Vec<(MaspExtendedSpendingKey, Diversifier, Note, Node)> { + ) -> Vec<(PseudoExtendedKey, Diversifier, Note, Node)> { spend_description } } @@ -2833,7 +2822,7 @@ pub mod testing { assets in Just(assets), ) -> ( Transfer, - Builder::, + Builder::, HashMap, ) { // Enable assets to be more easily decoded diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 343e30163b..41885466fb 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -10,16 +10,18 @@ use borsh::BorshSerialize; use borsh_ext::BorshSerializeExt; use masp_primitives::asset_type::AssetType; use masp_primitives::transaction::builder::Builder; +use masp_primitives::transaction::components::sapling::builder::{ + BuildParams, RngBuildParams, +}; use masp_primitives::transaction::components::sapling::fees::{ ConvertView, InputView as SaplingInputView, OutputView as SaplingOutputView, }; use masp_primitives::transaction::components::transparent::fees::{ InputView as TransparentInputView, OutputView as TransparentOutputView, }; -use masp_primitives::zip32::sapling::PseudoExtendedSpendingKey; -use masp_primitives::transaction::components::sapling::builder::{BuildParams, RngBuildParams}; use masp_primitives::transaction::components::I128Sum; use masp_primitives::transaction::{builder, Transaction as MaspTransaction}; +use masp_primitives::zip32::sapling::PseudoExtendedKey; use namada_account::{InitAccount, UpdateAccount}; use namada_core::address::{Address, IBC, MASP}; use namada_core::arith::checked; @@ -38,9 +40,7 @@ use namada_core::ibc::core::client::types::Height as IbcHeight; use namada_core::ibc::core::host::types::identifiers::{ChannelId, PortId}; use namada_core::ibc::primitives::Timestamp as IbcTimestamp; use namada_core::key::{self, *}; -use namada_core::masp::{ - AssetData, ExtendedSpendingKey, MaspEpoch, TransferSource, TransferTarget, -}; +use namada_core::masp::{AssetData, MaspEpoch, TransferSource, TransferTarget}; use namada_core::storage; use namada_core::time::DateTimeUtc; use namada_governance::cli::onchain::{ @@ -3131,7 +3131,7 @@ async fn get_masp_fee_payment_amount( args: &args::Tx, fee_amount: DenominatedAmount, fee_payer: &common::PublicKey, - gas_spending_keys: Vec, + gas_spending_keys: Vec, ) -> Result> { let fee_payer_address = Address::from(fee_payer); let balance_key = balance_key(&args.fee_token, &fee_payer_address); diff --git a/crates/sdk/src/wallet/mod.rs b/crates/sdk/src/wallet/mod.rs index 03f0a40ee4..ca6581865c 100644 --- a/crates/sdk/src/wallet/mod.rs +++ b/crates/sdk/src/wallet/mod.rs @@ -594,13 +594,12 @@ impl Wallet { seed.as_bytes(), zip32_seed_path, ) - .try_to_sk::() - .expect("Expected Ed25519 key") - .0 - .to_bytes(); + .try_to_sk::() + .expect("Expected Ed25519 key") + .0 + .to_bytes(); // Now ZIP32 derive the extended spending key from the new seed - let spend_key = - derive_hd_spending_key(&seed, derivation_path.clone()); + let spend_key = derive_hd_spending_key(&seed, derivation_path.clone()); self.insert_spending_key( alias, diff --git a/crates/sdk/src/wallet/store.rs b/crates/sdk/src/wallet/store.rs index 80a3f7331a..178cf7eaba 100644 --- a/crates/sdk/src/wallet/store.rs +++ b/crates/sdk/src/wallet/store.rs @@ -201,7 +201,7 @@ impl Store { ) -> Option { for (alias, vk) in &self.view_keys { if *viewing_key == vk.key { - return self.derivation_paths.get(&alias).cloned() + return self.derivation_paths.get(alias).cloned(); } } None diff --git a/crates/shielded_token/src/validation.rs b/crates/shielded_token/src/validation.rs index 1567791acd..039da17823 100644 --- a/crates/shielded_token/src/validation.rs +++ b/crates/shielded_token/src/validation.rs @@ -16,6 +16,7 @@ use masp_primitives::transaction::txid::TxIdDigester; use masp_primitives::transaction::{ Authorization, Authorized, Transaction, TransactionData, Unauthorized, }; +use masp_primitives::zip32::ExtendedSpendingKey; use masp_proofs::bellman::groth16::VerifyingKey; use masp_proofs::sapling::BatchValidator; use rand_core::OsRng; @@ -55,7 +56,8 @@ pub struct PartialAuthorized; impl Authorization for PartialAuthorized { type SaplingAuth = ::SaplingAuth; - type TransparentAuth = ::TransparentAuth; + type TransparentAuth = + as Authorization>::TransparentAuth; } /// MASP verifying keys diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index 2bc0fda9b0..bd26af4d44 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -1293,6 +1293,18 @@ impl Tx { None } + /// Remove the transaction section with the given hash + pub fn remove_masp_section(&mut self, hash: &MaspTxId) { + self.sections.retain(|section| { + if let Section::MaspTx(masp) = section { + if MaspTxId::from(masp.txid()) == *hash { + return false; + } + } + true + }); + } + /// Get the MASP builder section with the given hash pub fn get_masp_builder(&self, hash: &MaspTxId) -> Option<&MaspBuilder> { for section in &self.sections { diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 933cc91bdb..a15c6cd844 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -3356,7 +3356,7 @@ dependencies = [ [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "borsh", "chacha20", @@ -3369,7 +3369,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "aes", "bip0039", @@ -3401,7 +3401,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "bellman", "blake2b_simd", diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 553b114fc2..50c45e35d7 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -1785,7 +1785,7 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "masp_note_encryption" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "borsh", "chacha20", @@ -1798,7 +1798,7 @@ dependencies = [ [[package]] name = "masp_primitives" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "aes", "bip0039", @@ -1829,7 +1829,7 @@ dependencies = [ [[package]] name = "masp_proofs" version = "1.0.0" -source = "git+https://github.com/anoma/masp?rev=9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3#9bc6dec4d4b3f5a0344aa94b739a122c3e0989f3" +source = "git+https://github.com/anoma/masp?rev=f2b0cae3e495e4f7d482e587432ec4e5f2793528#f2b0cae3e495e4f7d482e587432ec4e5f2793528" dependencies = [ "bellman", "blake2b_simd",