diff --git a/crates/apps_lib/src/client/masp.rs b/crates/apps_lib/src/client/masp.rs index 46aff6695d6..f5bc676ecd9 100644 --- a/crates/apps_lib/src/client/masp.rs +++ b/crates/apps_lib/src/client/masp.rs @@ -40,7 +40,7 @@ pub async fn syncing< let logger = CliProgressTracker::new(io); let sync = async move { shielded - .fetch::<_, _, _, LedgerMaspClient>( + .fetch::<_, _, _, LedgerMaspClient<'_, C>>( client, &logger, RetryStrategy::Forever, diff --git a/crates/benches/native_vps.rs b/crates/benches/native_vps.rs index 0ad8a637b5c..68eea32b253 100644 --- a/crates/benches/native_vps.rs +++ b/crates/benches/native_vps.rs @@ -1191,7 +1191,7 @@ fn parameters(c: &mut Criterion) { let mut tx = Tx::from_type(namada::tx::data::TxType::Raw); tx.set_data(namada::tx::Data::new(borsh::to_vec(&0).unwrap())); let verifiers_from_tx = BTreeSet::default(); - let cmt = tx.first_commitments().unwrap().clone(); + let cmt = *tx.first_commitments().unwrap(); let batched_tx = tx.batch_tx(cmt); (verifiers_from_tx, batched_tx) } @@ -1265,7 +1265,7 @@ fn pos(c: &mut Criterion) { let mut tx = Tx::from_type(namada::tx::data::TxType::Raw); tx.set_data(namada::tx::Data::new(borsh::to_vec(&0).unwrap())); let verifiers_from_tx = BTreeSet::default(); - let cmt = tx.first_commitments().unwrap().clone(); + let cmt = *tx.first_commitments().unwrap(); let batched_tx = tx.batch_tx(cmt); (verifiers_from_tx, batched_tx) } diff --git a/crates/node/src/bench_utils.rs b/crates/node/src/bench_utils.rs index da0828ecc7e..4c46f1f16a8 100644 --- a/crates/node/src/bench_utils.rs +++ b/crates/node/src/bench_utils.rs @@ -89,9 +89,8 @@ use namada_apps_lib::cli; use namada_apps_lib::cli::context::FromContext; use namada_apps_lib::cli::Context; use namada_apps_lib::wallet::{defaults, CliWalletUtils}; -use namada_sdk::masp::{ - self, ContextSyncStatus, ShieldedContext, ShieldedTransfer, ShieldedUtils, -}; +use namada_sdk::masp::types::{ContextSyncStatus, ShieldedTransfer}; +use namada_sdk::masp::{self, ShieldedContext, ShieldedUtils}; pub use namada_sdk::tx::{ TX_BECOME_VALIDATOR_WASM, TX_BOND_WASM, TX_BRIDGE_POOL_WASM, TX_CHANGE_COMMISSION_WASM as TX_CHANGE_VALIDATOR_COMMISSION_WASM, @@ -335,7 +334,7 @@ impl BenchShell { ))); } - let cmt = tx.first_commitments().unwrap().clone(); + let cmt = *tx.first_commitments().unwrap(); tx.batch_tx(cmt) } @@ -356,7 +355,7 @@ impl BenchShell { tx.set_data(Data::new(data)); // NOTE: the Ibc VP doesn't actually check the signature - let cmt = tx.first_commitments().unwrap().clone(); + let cmt = *tx.first_commitments().unwrap(); tx.batch_tx(cmt) } @@ -639,7 +638,7 @@ pub fn generate_foreign_key_tx(signer: &SecretKey) -> BatchedTx { None, ))); - let cmt = tx.first_commitments().unwrap().clone(); + let cmt = *tx.first_commitments().unwrap(); tx.batch_tx(cmt) } diff --git a/crates/sdk/src/masp/mod.rs b/crates/sdk/src/masp/mod.rs index e7acefcfd3a..03be8aaf6ec 100644 --- a/crates/sdk/src/masp/mod.rs +++ b/crates/sdk/src/masp/mod.rs @@ -14,9 +14,9 @@ use std::path::PathBuf; use borsh::{BorshDeserialize, BorshSerialize}; use lazy_static::lazy_static; #[cfg(feature = "mainnet")] -use masp_primitives::consensus::MainNetwork; +use masp_primitives::consensus::MainNetwork as Network; #[cfg(not(feature = "mainnet"))] -use masp_primitives::consensus::TestNetwork; +use masp_primitives::consensus::TestNetwork as Network; use masp_primitives::group::GroupEncoding; use masp_primitives::sapling::redjubjub::PublicKey; use masp_primitives::transaction::components::transparent::builder::TransparentBuilder; @@ -57,10 +57,7 @@ pub const ENV_VAR_MASP_PARAMS_DIR: &str = "NAMADA_MASP_PARAMS_DIR"; pub const ENV_VAR_MASP_TEST_SEED: &str = "NAMADA_MASP_TEST_SEED"; /// The network to use for MASP -#[cfg(feature = "mainnet")] -const NETWORK: MainNetwork = MainNetwork; -#[cfg(not(feature = "mainnet"))] -const NETWORK: TestNetwork = TestNetwork; +const NETWORK: Network = Network; // TODO these could be exported from masp_proof crate /// Spend circuit name @@ -451,7 +448,6 @@ pub mod testing { use super::*; use crate::address::testing::arb_address; use crate::masp::types::{ShieldedTransfer, WalletMap}; - use crate::masp::utils::find_valid_diversifier; use crate::masp_primitives::consensus::BranchId; use crate::masp_primitives::constants::VALUE_COMMITMENT_RANDOMNESS_GENERATOR; use crate::masp_primitives::merkle_tree::FrozenCommitmentTree; @@ -568,8 +564,13 @@ pub mod testing { sighash_value, binding_sig, |bvk, msg, binding_sig| { + // Compute the signature's message for bvk/binding_sig + let mut data_to_be_signed = [0u8; 64]; + data_to_be_signed[0..32].copy_from_slice(&bvk.0.to_bytes()); + data_to_be_signed[32..64].copy_from_slice(msg); + bvk.verify_with_zip216( - &msg, + &data_to_be_signed, &binding_sig, VALUE_COMMITMENT_RANDOMNESS_GENERATOR, self.zip216_enabled, @@ -579,8 +580,8 @@ pub mod testing { } } - // This function computes `value` in the exponent of the value commitment - // base + /// This function computes `value` in the exponent of the value commitment + /// base fn masp_compute_value_balance( asset_type: AssetType, value: i128, @@ -610,8 +611,8 @@ pub mod testing { Some(value_balance.into()) } - // A context object for creating the Sapling components of a Zcash - // transaction. + /// A context object for creating the Sapling components of a Zcash + /// transaction. pub struct SaplingProvingContext { bsk: jubjub::Fr, // (sum of the Spend value commitments) - (sum of the Output value @@ -619,9 +620,9 @@ pub mod testing { cv_sum: jubjub::ExtendedPoint, } - // An implementation of TxProver that does everything except generating - // valid zero-knowledge proofs. Uses the supplied source of randomness to - // carry out its operations. + /// An implementation of TxProver that does everything except generating + /// valid zero-knowledge proofs. Uses the supplied source of randomness to + /// carry out its operations. pub struct MockTxProver(pub Mutex); impl TxProver for MockTxProver { @@ -828,7 +829,7 @@ pub mod testing { } #[derive(Debug, Clone)] - // Adapts a CSPRNG from a PRNG for proptesting + /// Adapts a CSPRNG from a PRNG for proptesting pub struct TestCsprng(R); impl CryptoRng for TestCsprng {} @@ -855,14 +856,14 @@ pub mod testing { } prop_compose! { - // Expose a random number generator + /// Expose a random number generator pub fn arb_rng()(rng in Just(()).prop_perturb(|(), rng| rng)) -> TestRng { rng } } prop_compose! { - // Generate an arbitrary output description with the given value + /// Generate an arbitrary output description with the given value pub fn arb_output_description( asset_type: AssetType, value: u64, @@ -884,13 +885,13 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary spend description with the given value + /// Generate an arbitrary spend description with the given value pub fn arb_spend_description( asset_type: AssetType, value: u64, )( address in arb_transparent_address(), - expiration_height in arb_height(BranchId::MASP, &TestNetwork), + expiration_height in arb_height(BranchId::MASP, &Network), mut rng in arb_rng().prop_map(TestCsprng), bparams_rng in arb_rng().prop_map(TestCsprng), prover_rng in arb_rng().prop_map(TestCsprng), @@ -905,7 +906,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 @@ -944,7 +945,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary MASP denomination + /// Generate an arbitrary MASP denomination pub fn arb_masp_digit_pos()(denom in 0..4u8) -> MaspDigitPos { MaspDigitPos::from(denom) } @@ -956,8 +957,8 @@ pub mod testing { const MAX_SPLITS: usize = 3; prop_compose! { - // Arbitrarily partition the given vector of integers into sets and sum - // them + /// Arbitrarily partition the given vector of integers into sets and sum + /// them pub fn arb_partition(values: Vec)(buckets in ((!values.is_empty()) as usize)..=values.len())( values in Just(values.clone()), assigns in collection::vec(0..buckets, values.len()), @@ -972,8 +973,8 @@ pub mod testing { } prop_compose! { - // Generate arbitrary spend descriptions with the given asset type - // partitioning the given values + /// Generate arbitrary spend descriptions with the given asset type + /// partitioning the given values pub fn arb_spend_descriptions( asset: AssetData, values: Vec, @@ -995,8 +996,8 @@ pub mod testing { } prop_compose! { - // Generate arbitrary output descriptions with the given asset type - // partitioning the given values + /// Generate arbitrary output descriptions with the given asset type + /// partitioning the given values pub fn arb_output_descriptions( asset: AssetData, values: Vec, @@ -1018,8 +1019,8 @@ pub mod testing { } prop_compose! { - // Generate arbitrary spend descriptions with the given asset type - // partitioning the given values + /// Generate arbitrary spend descriptions with the given asset type + /// partitioning the given values pub fn arb_txouts( asset: AssetData, values: Vec, @@ -1043,7 +1044,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary shielded MASP transaction builder + /// Generate an arbitrary shielded MASP transaction builder pub fn arb_shielded_builder(asset_range: impl Into)( assets in collection::hash_map( arb_pre_asset_type(), @@ -1051,7 +1052,7 @@ pub mod testing { asset_range, ), )( - expiration_height in arb_height(BranchId::MASP, &TestNetwork), + expiration_height in arb_height(BranchId::MASP, &Network), spend_descriptions in assets .iter() .map(|(asset, values)| arb_spend_descriptions(asset.clone(), values.clone())) @@ -1062,15 +1063,15 @@ pub mod testing { .collect::>(), assets in Just(assets), ) -> ( - Builder::, + Builder::, HashMap, ) { - 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 // use from the masp crate to specify the expiration better - expiration_height.unwrap() + expiration_height.unwrap(), ); let mut leaves = Vec::new(); // First construct a Merkle tree containing all notes to be used @@ -1090,7 +1091,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary pre-asset type + /// Generate an arbitrary pre-asset type pub fn arb_pre_asset_type()( token in arb_address(), denom in arb_denomination(), @@ -1107,7 +1108,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary shielding MASP transaction builder + /// Generate an arbitrary shielding MASP transaction builder pub fn arb_shielding_builder( source: TransparentAddress, asset_range: impl Into, @@ -1118,7 +1119,7 @@ pub mod testing { asset_range, ), )( - expiration_height in arb_height(BranchId::MASP, &TestNetwork), + expiration_height in arb_height(BranchId::MASP, &Network), txins in assets .iter() .map(|(asset, values)| arb_txouts(asset.clone(), values.clone(), source)) @@ -1129,10 +1130,10 @@ pub mod testing { .collect::>(), assets in Just(assets), ) -> ( - Builder::, + Builder::, HashMap, ) { - 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 @@ -1150,7 +1151,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary deshielding MASP transaction builder + /// Generate an arbitrary deshielding MASP transaction builder pub fn arb_deshielding_builder( target: TransparentAddress, asset_range: impl Into, @@ -1161,7 +1162,7 @@ pub mod testing { asset_range, ), )( - expiration_height in arb_height(BranchId::MASP, &TestNetwork), + expiration_height in arb_height(BranchId::MASP, &Network), spend_descriptions in assets .iter() .map(|(asset, values)| arb_spend_descriptions(asset.clone(), values.clone())) @@ -1172,10 +1173,10 @@ pub mod testing { .collect::>(), assets in Just(assets), ) -> ( - Builder::, + Builder::, HashMap, ) { - 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 @@ -1200,7 +1201,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary MASP shielded transfer + /// Generate an arbitrary MASP shielded transfer pub fn arb_shielded_transfer( asset_range: impl Into, )(asset_range in Just(asset_range.into()))( @@ -1226,7 +1227,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary MASP shielded transfer + /// Generate an arbitrary MASP shielded transfer pub fn arb_shielding_transfer( source: TransparentAddress, asset_range: impl Into, @@ -1256,7 +1257,7 @@ pub mod testing { } prop_compose! { - // Generate an arbitrary MASP shielded transfer + /// Generate an arbitrary MASP shielded transfer pub fn arb_deshielding_transfer( target: TransparentAddress, asset_range: impl Into, @@ -1324,12 +1325,19 @@ pub mod fs { && convert_path.exists() && output_path.exists()) { - println!("MASP parameters not present, downloading..."); + #[allow(clippy::print_stdout)] + { + println!("MASP parameters not present, downloading..."); + } masp_proofs::download_masp_parameters(None) .expect("MASP parameters not present or downloadable"); - println!( - "MASP parameter download complete, resuming execution..." - ); + #[allow(clippy::print_stdout)] + { + println!( + "MASP parameter download complete, resuming \ + execution..." + ); + } } // Finally initialize a shielded context with the supplied directory diff --git a/crates/sdk/src/masp/shielded_ctx.rs b/crates/sdk/src/masp/shielded_ctx.rs index ecd50609616..16c22dcf993 100644 --- a/crates/sdk/src/masp/shielded_ctx.rs +++ b/crates/sdk/src/masp/shielded_ctx.rs @@ -1,3 +1,5 @@ +//! The main implementation of the shielded context. This acts +//! as wallet and client for the MASP use std::cmp::Ordering; use std::collections::{btree_map, BTreeMap, BTreeSet}; use std::convert::TryInto; @@ -18,6 +20,7 @@ use masp_primitives::sapling::{ Diversifier, Node, Note, Nullifier, ViewingKey, }; use masp_primitives::transaction::builder::Builder; +use masp_primitives::transaction::components::sapling::builder::RngBuildParams; use masp_primitives::transaction::components::{ I128Sum, OutputDescription, TxOut, U64Sum, ValueSum, }; @@ -25,17 +28,16 @@ use masp_primitives::transaction::fees::fixed::FeeRule; use masp_primitives::transaction::{ builder, Authorization, Authorized, Transaction, TransparentAddress, }; -use masp_primitives::transaction::components::sapling::builder::RngBuildParams; use masp_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; use namada_core::address::Address; use namada_core::collections::{HashMap, HashSet}; use namada_core::masp::{ - encode_asset_type, AssetData, - TransferSource, TransferTarget, + encode_asset_type, AssetData, TransferSource, TransferTarget, }; -use namada_core::storage::{BlockHeight, Epoch, IndexedTx, TxIndex}; +use namada_core::storage::{BlockHeight, Epoch}; use namada_core::time::{DateTimeUtc, DurationSecs}; use namada_token::{self as token, Denomination, MaspDigitPos}; +use namada_tx::{IndexedTx, TxCommitments}; use rand_core::OsRng; use rayon::prelude::*; use ripemd::Digest as RipemdDigest; @@ -49,15 +51,13 @@ use crate::masp::types::{ Unscanned, WalletMap, }; use crate::masp::utils::{ - cloned_pair, fetch_channel, is_amount_required, - to_viewing_key, FetchQueueSender, - MaspClient, ProgressTracker, RetryStrategy, ShieldedUtils, TaskManager, + cloned_pair, fetch_channel, is_amount_required, to_viewing_key, + FetchQueueSender, MaspClient, ProgressTracker, RetryStrategy, + ShieldedUtils, TaskManager, }; use crate::masp::NETWORK; use crate::queries::Client; -use crate::rpc::{ - query_block, query_conversion, query_denom, -}; +use crate::rpc::{query_block, query_conversion, query_denom}; use crate::{display_line, edisplay_line, rpc, MaybeSend, MaybeSync, Namada}; /// Represents the current state of the shielded pool from the perspective of @@ -291,9 +291,7 @@ impl ShieldedContext { /// * nullify notes that have been spent /// * update balances of each viewing key pub(super) fn nullify_spent_notes(&mut self) -> Result<(), Error> { - for ((_, _vk), decrypted_data) in - self.decrypted_note_cache.drain() - { + for ((_, _vk), decrypted_data) in self.decrypted_note_cache.drain() { let DecryptedData { tx: shielded, delta: mut transaction_delta, @@ -537,11 +535,9 @@ impl ShieldedContext { let required = value / threshold; // Forget about the trace amount left over because we cannot // realize its value - let trace = I128Sum::from_pair(asset_type, value % threshold) - .expect("the trace should be a valid i128"); + let trace = I128Sum::from_pair(asset_type, value % threshold); let normed_trace = - I128Sum::from_pair(normed_asset_type, value % threshold) - .expect("the trace should be a valid i128"); + I128Sum::from_pair(normed_asset_type, value % threshold); // Record how much more of the given conversion has been used *usage += required; // Apply the conversions to input and move the trace amount to output @@ -721,13 +717,7 @@ impl ShieldedContext { // The amount contributed by this note before conversion let pre_contr = - I128Sum::from_pair(note.asset_type, note.value as i128) - .map_err(|()| { - Error::Other( - "received note has invalid value or asset type" - .to_string(), - ) - })?; + I128Sum::from_pair(note.asset_type, note.value as i128); let (contr, normed_contr, proposed_convs) = self .compute_exchanged_amount( context.client(), @@ -808,12 +798,10 @@ impl ShieldedContext { res += ValueSum::from_pair( pre_asset_type.token, decoded_change, - ) - .expect("expected this to fit"); + ); } None => { - undecoded += ValueSum::from_pair(*asset_type, *val) - .expect("expected this to fit"); + undecoded += ValueSum::from_pair(*asset_type, *val); } _ => {} } @@ -843,11 +831,9 @@ impl ShieldedContext { res += MaspAmount::from_pair( (decoded.epoch, decoded.token), decoded_change, - ) - .expect("unable to construct decoded amount"); + ); } else { - undecoded += ValueSum::from_pair(*asset_type, *val) - .expect("expected this to fit"); + undecoded += ValueSum::from_pair(*asset_type, *val); } } (res, undecoded) @@ -866,8 +852,7 @@ impl ShieldedContext { if let Some(decoded) = self.decode_asset_type(client, *asset_type).await { - res += ValueSum::from_pair((*asset_type, decoded), *val) - .expect("unable to construct decoded amount"); + res += ValueSum::from_pair((*asset_type, decoded), *val); } } res @@ -918,17 +903,19 @@ impl ShieldedContext { #[allow(unused_mut)] let mut rng = StdRng::from_rng(OsRng).unwrap(); #[cfg(feature = "testing")] - let mut rng = if let Ok(seed) = std::env::var(super::ENV_VAR_MASP_TEST_SEED) - .map_err(|e| Error::Other(e.to_string())) - .and_then(|seed| { - let exp_str = format!( - "Env var {} must be a u64.", - super::ENV_VAR_MASP_TEST_SEED - ); - let parsed_seed: u64 = std::str::FromStr::from_str(&seed) - .map_err(|_| Error::Other(exp_str))?; - Ok(parsed_seed) - }) { + let mut rng = if let Ok(seed) = + std::env::var(super::ENV_VAR_MASP_TEST_SEED) + .map_err(|e| Error::Other(e.to_string())) + .and_then(|seed| { + let exp_str = format!( + "Env var {} must be a u64.", + super::ENV_VAR_MASP_TEST_SEED + ); + let parsed_seed: u64 = + std::str::FromStr::from_str(&seed) + .map_err(|_| Error::Other(exp_str))?; + Ok(parsed_seed) + }) { tracing::warn!( "UNSAFE: Using a seed from {} env var to build proofs.", super::ENV_VAR_MASP_TEST_SEED, @@ -1084,9 +1071,7 @@ impl ShieldedContext { // Annotate the asset type in the value balance with its decoding in // order to facilitate cross-epoch computations - let value_balance = builder.value_balance().map_err(|e| { - Error::Other(format!("unable to complete value balance: {}", e)) - })?; + let value_balance = builder.value_balance(); let value_balance = context .shielded_mut() .await @@ -1176,8 +1161,7 @@ impl ShieldedContext { // Convert the shortfall into a I128Sum let mut shortfall = I128Sum::zero(); for (asset_type, val) in asset_types.iter().zip(rem_amount) { - shortfall += I128Sum::from_pair(*asset_type, val.into()) - .expect("unable to construct value sum"); + shortfall += I128Sum::from_pair(*asset_type, val.into()); } // Return an insufficient funds error return Result::Err(TransferErr::from( @@ -1189,16 +1173,7 @@ impl ShieldedContext { if let Some(sk) = spending_key { // Represents the amount of inputs we are short by let mut additional = I128Sum::zero(); - for (asset_type, amt) in builder - .value_balance() - .map_err(|e| { - Error::Other(format!( - "unable to complete value balance: {}", - e - )) - })? - .components() - { + for (asset_type, amt) in builder.value_balance().components() { match amt.cmp(&0) { Ordering::Greater => { // Send the change in this asset type back to the sender @@ -1242,21 +1217,18 @@ impl ShieldedContext { let prover = context.shielded().await.utils.local_tx_prover(); #[cfg(feature = "testing")] let prover = super::testing::MockTxProver(std::sync::Mutex::new(OsRng)); - let (masp_tx, metadata) = - builder.build( - &prover, - &FeeRule::non_standard(U64Sum::zero()), - &mut rng, - &mut RngBuildParams::new(OsRng), - )?; + let (masp_tx, metadata) = builder.build( + &prover, + &FeeRule::non_standard(U64Sum::zero()), + &mut rng, + &mut RngBuildParams::new(OsRng), + )?; if update_ctx { // Cache the generated transfer let mut shielded_ctx = context.shielded_mut().await; shielded_ctx - .pre_cache_transaction( - context, &masp_tx, - ) + .pre_cache_transaction(context, &masp_tx) .await?; } @@ -1287,18 +1259,17 @@ impl ShieldedContext { let last_witnessed_tx = self.tx_note_map.keys().max(); // This data will be discarded at the next fetch so we don't need to // populate it accurately - let indexed_tx = last_witnessed_tx.map_or_else( - || IndexedTx { - height: BlockHeight::first(), - index: TxIndex(0), - is_wrapper: false, - }, - |indexed| IndexedTx { - height: indexed.height, - index: TxIndex(indexed.index.0 + 1), - is_wrapper: false, - }, - ); + let indexed_tx = + last_witnessed_tx.map_or_else(IndexedTx::default, |indexed| { + IndexedTx { + height: indexed.height, + index: indexed + .index + .checked_add(1) + .expect("Tx index shouldn't overflow"), + inner_tx: TxCommitments::default(), + } + }); self.sync_status = ContextSyncStatus::Speculative; let mut scanned_data = ScannedData::default(); for vk in vks { @@ -1592,6 +1563,7 @@ mod shielded_ctx_tests { use masp_primitives::zip32::ExtendedFullViewingKey; use namada_core::masp::ExtendedViewingKey; + use namada_core::storage::TxIndex; use tempfile::tempdir; use super::*; @@ -1718,7 +1690,7 @@ mod shielded_ctx_tests { // we first test that with no retries, a fetching failure // stops process let result = shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1747,7 +1719,7 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -1757,7 +1729,7 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(2), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -1765,7 +1737,7 @@ mod shielded_ctx_tests { // This should complete successfully shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(2), @@ -1788,12 +1760,12 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }, IndexedTx { height: 1.into(), index: TxIndex(2), - is_wrapper: false, + inner_tx: Default::default(), }, ]); @@ -1803,7 +1775,7 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(2), - is_wrapper: false, + inner_tx: Default::default(), } ); assert_eq!(shielded_ctx.note_map.len(), 2); @@ -1829,7 +1801,7 @@ mod shielded_ctx_tests { // first fetch no blocks masp_tx_sender.send(None).expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1849,14 +1821,14 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: Default::default(), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) .expect("Test failed"); masp_tx_sender.send(None).expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1873,7 +1845,7 @@ mod shielded_ctx_tests { // fetch no blocks masp_tx_sender.send(None).expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1892,7 +1864,7 @@ mod shielded_ctx_tests { let (client, masp_tx_sender) = test_client(3.into()); masp_tx_sender.send(None).expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1912,7 +1884,7 @@ mod shielded_ctx_tests { IndexedTx { height: 2.into(), index: Default::default(), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -1922,7 +1894,7 @@ mod shielded_ctx_tests { IndexedTx { height: 3.into(), index: Default::default(), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -1931,7 +1903,7 @@ mod shielded_ctx_tests { // all expected blocks masp_tx_sender.send(None).expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -1970,7 +1942,7 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -1980,14 +1952,14 @@ mod shielded_ctx_tests { IndexedTx { height: 1.into(), index: TxIndex(2), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) .expect("Test failed"); shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(2), @@ -2012,7 +1984,7 @@ mod shielded_ctx_tests { let expected = vec![IndexedTx { height: 1.into(), index: TxIndex(2), - is_wrapper: false, + inner_tx: Default::default(), }]; assert_eq!(keys, expected); } @@ -2041,7 +2013,7 @@ mod shielded_ctx_tests { IndexedTx { height: h.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -2051,7 +2023,7 @@ mod shielded_ctx_tests { // we expect this to fail. let result = shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), @@ -2080,7 +2052,7 @@ mod shielded_ctx_tests { shielded_ctx.tx_note_map.remove(&IndexedTx { height: 18.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }); shielded_ctx.save().await.expect("Test failed"); @@ -2091,7 +2063,7 @@ mod shielded_ctx_tests { IndexedTx { height: h.into(), index: TxIndex(1), - is_wrapper: false, + inner_tx: Default::default(), }, masp_tx.clone(), ))) @@ -2101,7 +2073,7 @@ mod shielded_ctx_tests { // we expect this to fail. shielded_ctx - .fetch::<_, _, _, TestingMaspClient>( + .fetch::<_, _, _, TestingMaspClient<'_>>( &client, &progress, RetryStrategy::Times(1), diff --git a/crates/sdk/src/masp/test_utils.rs b/crates/sdk/src/masp/test_utils.rs index b677e5cb2bd..1658bb6ac63 100644 --- a/crates/sdk/src/masp/test_utils.rs +++ b/crates/sdk/src/masp/test_utils.rs @@ -4,8 +4,9 @@ use std::sync::{Arc, Mutex}; use masp_primitives::merkle_tree::CommitmentTree; use masp_primitives::sapling::Node; -use namada_core::storage::{BlockHeight, IndexedTx}; +use namada_core::storage::BlockHeight; use namada_state::LastBlock; +use namada_tx::IndexedTx; use tendermint_rpc::SimpleRequest; use crate::error::Error; @@ -110,7 +111,7 @@ impl<'a> MaspClient<'a, TestingClient> for TestingMaspClient<'a> { Self { client } } - async fn witness_map_updates( + async fn fetch_witness_map_updates( &self, _: &ShieldedContext, _: &IO, diff --git a/crates/sdk/src/masp/types.rs b/crates/sdk/src/masp/types.rs index 749ac84b9cb..89ee5bda32c 100644 --- a/crates/sdk/src/masp/types.rs +++ b/crates/sdk/src/masp/types.rs @@ -1,3 +1,4 @@ +//! The public types for using the MASP tooling use std::collections::{BTreeMap, BTreeSet}; use std::io::{Read, Write}; use std::sync::{Arc, Mutex}; @@ -23,12 +24,13 @@ use namada_core::address::Address; use namada_core::borsh::{BorshDeserialize, BorshSerialize}; use namada_core::collections::HashMap; use namada_core::dec::Dec; -use namada_core::storage::{BlockHeight, Epoch, IndexedTx}; +use namada_core::storage::{BlockHeight, Epoch}; use namada_core::uint::Uint; use namada_macros::BorshDeserializer; #[cfg(feature = "migrations")] use namada_migrations::*; use namada_token as token; +use namada_tx::{IndexedTx, TxCommitments}; use thiserror::Error; use crate::error::Error; @@ -87,6 +89,7 @@ pub struct ShieldedTransfer { } /// Shielded pool data for a token +#[allow(missing_docs)] #[derive(Debug, BorshSerialize, BorshDeserialize, BorshDeserializer)] pub struct MaspTokenRewardData { pub name: String, @@ -98,13 +101,8 @@ pub struct MaspTokenRewardData { } /// The MASP transaction(s) found in a Namada tx. -/// These transactions can appear in the fee payment -/// and / or the main payload. #[derive(Debug, Clone)] -pub(super) struct ExtractedMaspTx { - pub(crate) fee_unshielding: Option, - pub(crate) inner_tx: Option, -} +pub(crate) struct ExtractedMaspTxs(pub Vec<(TxCommitments, Transaction)>); /// MASP verifying keys pub struct PVKs { @@ -218,7 +216,9 @@ impl ScannedData { /// re-scanned as part of nullifying spent notes (which /// is not parallelizable). pub struct DecryptedData { + /// The actual transaction pub tx: Transaction, + /// balance changes from the tx pub delta: TransactionDelta, } diff --git a/crates/sdk/src/masp/utils.rs b/crates/sdk/src/masp/utils.rs index a65737562ba..ff8f0847c8a 100644 --- a/crates/sdk/src/masp/utils.rs +++ b/crates/sdk/src/masp/utils.rs @@ -1,3 +1,4 @@ +//! Helper functions use std::collections::BTreeMap; use std::env; use std::marker::PhantomData; @@ -14,13 +15,13 @@ use masp_primitives::transaction::Transaction; use masp_primitives::zip32::{ExtendedFullViewingKey, ExtendedSpendingKey}; use masp_proofs::prover::LocalTxProver; use namada_core::collections::HashMap; -use namada_core::storage::{BlockHeight, IndexedTx, TxIndex}; +use namada_core::storage::{BlockHeight, TxIndex}; use namada_core::token::Transfer; use namada_events::extend::{ - ReadFromEventAttributes, ValidMaspTx as ValidMaspTxAttr, + MaspTxBlockIndex as MaspTxBlockIndexAttr, ReadFromEventAttributes, }; use namada_ibc::IbcMessage; -use namada_tx::Tx; +use namada_tx::{IndexedTx, Tx}; use rand_core::{CryptoRng, RngCore}; use tokio::sync::mpsc::{Receiver, Sender}; @@ -28,7 +29,7 @@ use crate::error::{Error, QueryError}; use crate::io::Io; use crate::masp::shielded_ctx::ShieldedContext; use crate::masp::types::{ - ContextSyncStatus, ExtractedMaspTx, IndexedNoteEntry, PVKs, ScannedData, + ContextSyncStatus, ExtractedMaspTxs, IndexedNoteEntry, PVKs, ScannedData, TransactionDelta, Unscanned, }; use crate::masp::{ENV_VAR_MASP_PARAMS_DIR, VERIFIYING_KEYS}; @@ -48,7 +49,10 @@ pub(super) fn load_pvks() -> &'static PVKs { /// use the default. pub fn get_params_dir() -> PathBuf { if let Ok(params_dir) = env::var(ENV_VAR_MASP_PARAMS_DIR) { - println!("Using {} as masp parameter folder.", params_dir); + #[allow(clippy::print_stdout)] + { + println!("Using {} as masp parameter folder.", params_dir); + } PathBuf::from(params_dir) } else { masp_proofs::default_params_folder().unwrap() @@ -121,7 +125,6 @@ pub(super) fn cloned_pair((a, b): (&T, &U)) -> (T, U) { (a.clone(), b.clone()) } - /// Retrieves all the indexes and tx events at the specified height which refer /// to a valid MASP transaction. If an index is given, it filters only the /// transactions with an index equal or greater to the provided one. @@ -141,10 +144,11 @@ pub(super) async fn get_indexed_masp_events_at_height( events .into_iter() .filter_map(|event| { - let tx_index = ValidMaspTxAttr::read_from_event_attributes( - &event.attributes, - ) - .ok()?; + let tx_index = + MaspTxBlockIndexAttr::read_from_event_attributes( + &event.attributes, + ) + .ok()?; if tx_index >= first_idx_to_query { Some(tx_index) @@ -159,75 +163,57 @@ pub(super) async fn get_indexed_masp_events_at_height( /// Extract the relevant shielded portions of a [`Tx`], if any. pub(super) async fn extract_masp_tx( tx: &Tx, - check_header: bool, -) -> Result { - let tx_header = tx.header(); +) -> Result { // NOTE: simply looking for masp sections attached to the tx // is not safe. We don't validate the sections attached to a // transaction se we could end up with transactions carrying // an unnecessary masp section. We must instead look for the // required masp sections in the signed commitments (hashes) - // of the transactions' headers/data sections - let wrapper_header = tx_header - .wrapper() - .expect("All transactions must have a wrapper"); - let maybe_fee_unshield = if let (Some(hash), true) = - (wrapper_header.unshield_section_hash, check_header) - { - let masp_transaction = tx - .get_section(&hash) - .ok_or_else(|| { - Error::Other("Missing expected masp section".to_string()) - })? - .masp_tx() - .ok_or_else(|| { - Error::Other("Missing masp transaction".to_string()) - })?; - - Some(masp_transaction) - } else { - None - }; + // of the transactions' data sections + let mut txs = vec![]; // Expect transaction - let tx_data = tx - .data() - .ok_or_else(|| Error::Other("Missing data section".to_string()))?; - let maybe_masp_tx = match Transfer::try_from_slice(&tx_data) { - Ok(transfer) => Some(transfer), - Err(_) => { - // This should be a MASP over IBC transaction, it - // could be a ShieldedTransfer or an Envelope - // message, need to try both - extract_payload_from_shielded_action(&tx_data).await.ok() + for cmt in tx.commitments() { + let tx_data = tx + .data(cmt) + .ok_or_else(|| Error::Other("Missing data section".to_string()))?; + let maybe_masp_tx = match Transfer::try_from_slice(&tx_data) { + Ok(transfer) => Some(transfer), + Err(_) => { + // This should be a MASP over IBC transaction, it + // could be a ShieldedTransfer or an Envelope + // message, need to try both + extract_payload_from_shielded_action(&tx_data).await.ok() + } } - } - .map(|transfer| { - if let Some(hash) = transfer.shielded { - let masp_tx = tx - .get_section(&hash) - .ok_or_else(|| { - Error::Other( - "Missing masp section in transaction".to_string(), - ) - })? - .masp_tx() - .ok_or_else(|| { - Error::Other("Missing masp transaction".to_string()) - })?; - - Ok::<_, Error>(Some(masp_tx)) - } else { - Ok(None) + .map(|transfer| { + if let Some(hash) = transfer.shielded { + let masp_tx = tx + .get_section(&hash) + .ok_or_else(|| { + Error::Other( + "Missing masp section in transaction".to_string(), + ) + })? + .masp_tx() + .ok_or_else(|| { + Error::Other("Missing masp transaction".to_string()) + })?; + + Ok::<_, Error>(Some(masp_tx)) + } else { + Ok(None) + } + }) + .transpose()? + .flatten(); + + if let Some(transaction) = maybe_masp_tx { + txs.push((cmt.to_owned(), transaction)); } - }) - .transpose()? - .flatten(); + } - Ok(ExtractedMaspTx { - fee_unshielding: maybe_fee_unshield, - inner_tx: maybe_masp_tx, - }) + Ok(ExtractedMaspTxs(txs)) } /// Extract the changed keys and Transaction hash from a MASP over ibc message @@ -271,6 +257,7 @@ pub(super) async fn extract_payload_from_shielded_action( /// The updates to the commitment tree and witness maps /// fetched at the beginning of shielded-sync. +#[allow(missing_docs)] pub struct CommitmentTreeUpdates { pub commitment_tree: CommitmentTree, pub witness_map: HashMap>, @@ -281,12 +268,14 @@ pub struct CommitmentTreeUpdates { /// of how shielded-sync fetches the necessary data /// from a remote server. pub trait MaspClient<'a, C: Client> { + /// Create a new [`MaspClient`] given an rpc client. fn new(client: &'a C) -> Self where Self: 'a; + /// Fetch data relevant to the commitment tree #[allow(async_fn_in_trait)] - async fn witness_map_updates( + async fn fetch_witness_map_updates( &self, ctx: &ShieldedContext, io: &IO, @@ -294,6 +283,7 @@ pub trait MaspClient<'a, C: Client> { last_query_height: BlockHeight, ) -> Result; + /// Apply updates to the commitment tree #[allow(async_fn_in_trait)] async fn update_commitment_tree( &self, @@ -307,7 +297,12 @@ pub trait MaspClient<'a, C: Client> { witness_map, mut note_map_delta, } = self - .witness_map_updates(ctx, io, last_witnessed_tx, last_query_height) + .fetch_witness_map_updates( + ctx, + io, + last_witnessed_tx, + last_query_height, + ) .await?; ctx.tree = commitment_tree; ctx.witness_map = witness_map; @@ -315,6 +310,7 @@ pub trait MaspClient<'a, C: Client> { Ok(()) } + /// Fetches shielded transfers #[allow(async_fn_in_trait)] async fn fetch_shielded_transfer( &self, @@ -343,7 +339,7 @@ where Self { client } } - async fn witness_map_updates( + async fn fetch_witness_map_updates( &self, ctx: &ShieldedContext, io: &IO, @@ -368,7 +364,7 @@ where note_map_delta: Default::default(), }; let mut note_pos = updates.commitment_tree.size(); - for (indexed_tx, ref shielded) in tx_receiver { + for (indexed_tx, ref shielded) in tx_receiver { updates.note_map_delta.insert(indexed_tx, note_pos); for so in shielded .sapling_bundle() @@ -453,30 +449,16 @@ where for idx in txs_results { let tx = Tx::try_from(block[idx.0 as usize].as_ref()) .map_err(|e| Error::Other(e.to_string()))?; - let ExtractedMaspTx { - fee_unshielding, - inner_tx, - } = extract_masp_tx(&tx, true).await?; - // Collect the current transaction(s) - if let Some(masp_transaction) = fee_unshielding { + let extracted_masp_txs = extract_masp_tx(&tx).await?; + for (inner_tx, transaction) in extracted_masp_txs.0 { tx_sender.send(( IndexedTx { height: height.into(), index: idx, - is_wrapper: true, + inner_tx, }, - masp_transaction, - )); - } - if let Some(masp_transaction) = inner_tx { - tx_sender.send(( - IndexedTx { - height: height.into(), - index: idx, - is_wrapper: false, - }, - masp_transaction, - )); + transaction, + )) } } fetch_iter.next(); @@ -708,7 +690,9 @@ impl TaskScheduler { /// loop, this dictates the strategy for /// how many attempts should be made. pub enum RetryStrategy { + /// Always retry Forever, + /// Limit number of retries to a fixed number Times(u64), } @@ -732,14 +716,19 @@ impl Iterator for RetryStrategy { /// An enum to indicate how to log sync progress depending on /// whether sync is currently fetch or scanning blocks. +#[allow(missing_docs)] #[derive(Debug, Copy, Clone)] pub enum ProgressType { Fetch, Scan, } +/// A peekable iterator interface pub trait PeekableIter { + /// Peek at next element fn peek(&mut self) -> Option<&I>; + + /// get next element fn next(&mut self) -> Option; } @@ -765,12 +754,15 @@ where /// Additionally, it has access to IO in case the struct implementing /// this trait wishes to log this progress. pub trait ProgressTracker { + /// Get an IO handle fn io(&self) -> &IO; + /// Return an iterator to fetched shielded transfers fn fetch(&self, items: I) -> impl PeekableIter where I: Iterator; + /// Return an interator over MASP transactions to be scanned fn scan( &self, items: I, @@ -778,6 +770,7 @@ pub trait ProgressTracker { where I: Iterator + Send; + /// The number of blocks that need to be fetched fn left_to_fetch(&self) -> usize; } @@ -789,6 +782,7 @@ pub struct DefaultTracker<'io, IO: Io> { } impl<'io, IO: Io> DefaultTracker<'io, IO> { + /// New [`DefaultTracker`] pub fn new(io: &'io IO) -> Self { Self { io, diff --git a/crates/sdk/src/tx.rs b/crates/sdk/src/tx.rs index 0c69c87c553..16d7539a2e1 100644 --- a/crates/sdk/src/tx.rs +++ b/crates/sdk/src/tx.rs @@ -2806,7 +2806,7 @@ pub fn build_batch( } let cmt = tx.first_commitments().unwrap().to_owned(); - if !batched_tx.add_inner_tx(tx, cmt.clone()) { + if !batched_tx.add_inner_tx(tx, cmt) { return Err(Error::Other(format!( "The transaction batch already contains inner tx: {}", cmt.get_hash() diff --git a/crates/tx/src/types.rs b/crates/tx/src/types.rs index c1fe7e99ab0..7f2d348fcb8 100644 --- a/crates/tx/src/types.rs +++ b/crates/tx/src/types.rs @@ -892,6 +892,7 @@ impl Section { /// An inner transaction of the batch, represented by its commitments to the /// [`Code`], [`Data`] and [`Memo`] sections #[derive( + Copy, Clone, Debug, Default, @@ -1734,6 +1735,7 @@ impl<'tx> Tx { /// index inside that block and the commitment inside the tx bundle (if inner /// tx) #[derive( + Copy, Debug, Clone, BorshSerialize, diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 2a00208e8aa..be5f2057f22 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -270,7 +270,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower", "tower-layer", "tower-service", @@ -1942,6 +1942,18 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2039,6 +2051,7 @@ checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" dependencies = [ "futures-channel", "futures-task", + "tokio", ] [[package]] @@ -3926,7 +3939,9 @@ dependencies = [ "ethers", "eyre", "fd-lock", + "flume", "futures", + "futures-locks", "itertools 0.12.1", "jubjub", "lazy_static", @@ -3959,6 +3974,7 @@ dependencies = [ "prost", "rand 0.8.5", "rand_core 0.6.4", + "rayon", "regex", "ripemd", "serde", @@ -3966,6 +3982,7 @@ dependencies = [ "sha2 0.9.9", "slip10_ed25519", "smooth-operator", + "sync_wrapper 1.0.1", "tendermint-config", "tendermint-rpc", "thiserror", @@ -4226,6 +4243,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.11", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -5842,6 +5868,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -5970,6 +5999,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "system-configuration" version = "0.5.1" diff --git a/wasm_for_tests/Cargo.lock b/wasm_for_tests/Cargo.lock index 59aa30e7306..b936fa34c55 100644 --- a/wasm_for_tests/Cargo.lock +++ b/wasm_for_tests/Cargo.lock @@ -270,7 +270,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower", "tower-layer", "tower-service", @@ -1942,6 +1942,18 @@ dependencies = [ "paste", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2039,6 +2051,7 @@ checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" dependencies = [ "futures-channel", "futures-task", + "tokio", ] [[package]] @@ -3881,7 +3894,9 @@ dependencies = [ "ethers", "eyre", "fd-lock", + "flume", "futures", + "futures-locks", "itertools 0.12.1", "jubjub", "lazy_static", @@ -3912,6 +3927,7 @@ dependencies = [ "prost", "rand 0.8.5", "rand_core 0.6.4", + "rayon", "regex", "ripemd", "serde", @@ -3919,6 +3935,7 @@ dependencies = [ "sha2 0.9.9", "slip10_ed25519", "smooth-operator", + "sync_wrapper 1.0.1", "tendermint-config", "tendermint-rpc", "thiserror", @@ -4171,6 +4188,15 @@ dependencies = [ "thiserror", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.11", +] + [[package]] name = "nonempty" version = "0.7.0" @@ -5779,6 +5805,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -5907,6 +5936,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "system-configuration" version = "0.5.1"