diff --git a/console/program/src/state_path/configuration/mod.rs b/console/program/src/state_path/configuration/mod.rs index 17d4795f66..e8ae37eaa5 100644 --- a/console/program/src/state_path/configuration/mod.rs +++ b/console/program/src/state_path/configuration/mod.rs @@ -57,15 +57,16 @@ pub type TransactionsTree = BHPMerkleTree; /// The Merkle path for a transaction in a block. pub type TransactionsPath = MerklePath; -/// The Merkle tree for the execution. -pub type ExecutionTree = BHPMerkleTree; -/// The Merkle tree for the deployment. -pub type DeploymentTree = BHPMerkleTree; /// The Merkle tree for the transaction. pub type TransactionTree = BHPMerkleTree; /// The Merkle path for a function or transition in the transaction. pub type TransactionPath = MerklePath; +/// The Merkle tree for the execution. +pub type ExecutionTree = BHPMerkleTree; +/// The Merkle tree for the deployment. +pub type DeploymentTree = BHPMerkleTree; + /// The Merkle tree for the transition. pub type TransitionTree = BHPMerkleTree; /// The Merkle path for an input or output ID in the transition. diff --git a/ledger/block/src/transaction/bytes.rs b/ledger/block/src/transaction/bytes.rs index ee4b8c127e..ce70b91c79 100644 --- a/ledger/block/src/transaction/bytes.rs +++ b/ledger/block/src/transaction/bytes.rs @@ -96,7 +96,8 @@ impl ToBytes for Transaction { 1u8.write_le(&mut writer)?; // Write the transaction. - // We don't write the deployment or execution id, which are recomputed when creating the transaction. + // Note: We purposefully do not write out the deployment or execution ID, + // and instead recompute it when reconstructing the transaction, to ensure there was no malleability. match self { Self::Deploy(id, _, owner, deployment, fee) => { // Write the variant. diff --git a/ledger/block/src/transaction/deployment/mod.rs b/ledger/block/src/transaction/deployment/mod.rs index da7f80b949..73eac400b5 100644 --- a/ledger/block/src/transaction/deployment/mod.rs +++ b/ledger/block/src/transaction/deployment/mod.rs @@ -121,15 +121,10 @@ impl Deployment { } /// Returns the number of program functions in the deployment. - pub fn len(&self) -> usize { + pub fn num_functions(&self) -> usize { self.program.functions().len() } - /// Returns `true` if the deployment is empty. - pub fn is_empty(&self) -> bool { - self.program.functions().is_empty() - } - /// Returns the edition. pub const fn edition(&self) -> u16 { self.edition diff --git a/ledger/block/src/transaction/merkle.rs b/ledger/block/src/transaction/merkle.rs index 78883e0663..a6ceab5cdc 100644 --- a/ledger/block/src/transaction/merkle.rs +++ b/ledger/block/src/transaction/merkle.rs @@ -93,17 +93,11 @@ impl Transaction { match self { // Compute the deployment tree. Transaction::Deploy(_, _, _, deployment, fee) => { - let deployment_tree = Self::deployment_tree(deployment)?; - Self::transaction_tree(deployment_tree, deployment.len(), fee) + Self::transaction_tree(Self::deployment_tree(deployment)?, Some(fee)) } // Compute the execution tree. Transaction::Execute(_, _, execution, fee) => { - let execution_tree = Self::execution_tree(execution)?; - if let Some(fee) = fee { - Ok(Transaction::transaction_tree(execution_tree, execution.len(), fee)?) - } else { - Ok(execution_tree) - } + Self::transaction_tree(Self::execution_tree(execution)?, fee.as_ref()) } // Compute the fee tree. Transaction::Fee(_, fee) => Self::fee_tree(fee), @@ -112,6 +106,37 @@ impl Transaction { } impl Transaction { + /// Returns the Merkle tree for the given transaction tree, fee index, and fee. + pub fn transaction_tree( + mut deployment_or_execution_tree: TransactionTree, + fee: Option<&Fee>, + ) -> Result> { + // Retrieve the fee index, defined as the last index in the transaction tree. + let fee_index = deployment_or_execution_tree.number_of_leaves(); + // Ensure the fee index is within the Merkle tree size. + ensure!( + fee_index <= N::MAX_FUNCTIONS, + "The fee index ('{fee_index}') in the transaction tree must be less than {}", + N::MAX_FUNCTIONS + ); + // Ensure the fee index is within the Merkle tree size. + ensure!( + fee_index < Self::MAX_TRANSITIONS, + "The fee index ('{fee_index}') in the transaction tree must be less than {}", + Self::MAX_TRANSITIONS + ); + + // If a fee is provided, append the fee leaf to the transaction tree. + if let Some(fee) = fee { + // Construct the transaction leaf. + let leaf = TransactionLeaf::new_fee(u16::try_from(fee_index)?, **fee.transition_id()).to_bits_le(); + // Append the fee leaf to the transaction tree. + deployment_or_execution_tree.append(&[leaf])?; + } + // Return the transaction tree. + Ok(deployment_or_execution_tree) + } + /// Returns the Merkle tree for the given deployment. pub fn deployment_tree(deployment: &Deployment) -> Result> { // Use the V1 or V2 deployment tree based on whether or not the program checksum exists. @@ -137,29 +162,12 @@ impl Transaction { // Ensure the number of leaves is within the Merkle tree size. Self::check_execution_size(num_transitions)?; // Prepare the leaves. - let leaves = transitions - .enumerate() - .map(|(index, transition)| { - // Construct the transaction leaf. - Ok::<_, Error>(TransactionLeaf::new_execution(u16::try_from(index)?, **transition.id()).to_bits_le()) - }) - .collect::, _>>()?; + let leaves = transitions.enumerate().map(|(index, transition)| { + // Construct the transaction leaf. + Ok::<_, Error>(TransactionLeaf::new_execution(u16::try_from(index)?, **transition.id()).to_bits_le()) + }); // Compute the execution tree. - N::merkle_tree_bhp::(&leaves) - } - - /// Returns the Merkle tree for the given 1. transaction or deployment tree and 2. fee. - pub fn transaction_tree( - mut deployment_or_execution_tree: TransactionTree, - fee_index: usize, - fee: &Fee, - ) -> Result> { - // Construct the transaction leaf. - let leaf = TransactionLeaf::new_fee(u16::try_from(fee_index)?, **fee.transition_id()).to_bits_le(); - // Compute the updated transaction tree. - deployment_or_execution_tree.append(&[leaf])?; - - Ok(deployment_or_execution_tree) + N::merkle_tree_bhp::(&leaves.collect::, _>>()?) } /// Returns the Merkle tree for the given fee. @@ -178,20 +186,28 @@ impl Transaction { let functions = program.functions(); // Retrieve the verifying keys. let verifying_keys = deployment.verifying_keys(); + // Retrieve the number of functions. + let num_functions = functions.len(); // Ensure the number of functions and verifying keys match. ensure!( - functions.len() == verifying_keys.len(), - "Number of functions ('{}') and verifying keys ('{}') do not match", - functions.len(), + num_functions == verifying_keys.len(), + "Number of functions ('{num_functions}') and verifying keys ('{}') do not match", verifying_keys.len() ); + // Ensure there are functions. + ensure!(num_functions > 0, "Deployment must contain at least one function"); + // Ensure the number of functions is within the allowed range. + ensure!( + num_functions <= N::MAX_FUNCTIONS, + "Deployment must contain at most {} functions, found {num_functions}", + N::MAX_FUNCTIONS, + ); // Ensure the number of functions is within the allowed range. ensure!( - functions.len() < Self::MAX_TRANSITIONS, // Note: Observe we hold back 1 for the fee. - "Deployment must contain less than {} functions, found {}", + num_functions < Self::MAX_TRANSITIONS, // Note: Observe we hold back 1 for the fee. + "Deployment must contain less than {} functions, found {num_functions}", Self::MAX_TRANSITIONS, - functions.len() ); Ok(()) } @@ -218,22 +234,16 @@ impl Transaction { // Prepare the header for the hash. let header = deployment.program().id().to_bits_le(); // Prepare the leaves. - let leaves = deployment - .program() - .functions() - .values() - .enumerate() - .map(|(index, function)| { - // Construct the transaction leaf. - Ok(TransactionLeaf::new_deployment( - u16::try_from(index)?, - N::hash_bhp1024(&to_bits_le![header, function.to_bytes_le()?])?, - ) - .to_bits_le()) - }) - .collect::>>()?; + let leaves = deployment.program().functions().values().enumerate().map(|(index, function)| { + // Construct the transaction leaf. + Ok(TransactionLeaf::new_deployment( + u16::try_from(index)?, + N::hash_bhp1024(&to_bits_le![header, function.to_bytes_le()?])?, + ) + .to_bits_le()) + }); // Compute the deployment tree. - N::merkle_tree_bhp::(&leaves) + N::merkle_tree_bhp::(&leaves.collect::>>()?) } /// Returns the V2 deployment tree. @@ -246,21 +256,36 @@ impl Transaction { Some(program_checksum) => program_checksum.to_bits_le(), }; // Prepare the leaves. - let leaves = deployment - .program() - .functions() - .values() - .enumerate() - .map(|(index, function)| { - // Construct the transaction leaf. - Ok(TransactionLeaf::new_deployment( - u16::try_from(index)?, - N::hash_bhp1024(&to_bits_le![header, function.to_bytes_le()?])?, - ) - .to_bits_le()) - }) - .collect::>>()?; + let leaves = deployment.program().functions().values().enumerate().map(|(index, function)| { + // Construct the transaction leaf. + Ok(TransactionLeaf::new_deployment( + u16::try_from(index)?, + N::hash_bhp1024(&to_bits_le![header, function.to_bytes_le()?])?, + ) + .to_bits_le()) + }); // Compute the deployment tree. - N::merkle_tree_bhp::(&leaves) + N::merkle_tree_bhp::(&leaves.collect::>>()?) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + type CurrentNetwork = console::network::MainnetV0; + + #[test] + fn test_transaction_depth_is_correct() { + // We ensure 2^TRANSACTION_DEPTH == MAX_FUNCTIONS + 1. + // The "1 extra" is for the fee transition. + assert_eq!( + 2u32.checked_pow(TRANSACTION_DEPTH as u32).unwrap() as usize, + Transaction::::MAX_TRANSITIONS + ); + assert_eq!( + CurrentNetwork::MAX_FUNCTIONS.checked_add(1).unwrap(), + Transaction::::MAX_TRANSITIONS + ); } } diff --git a/ledger/block/src/transaction/mod.rs b/ledger/block/src/transaction/mod.rs index c83908434a..55231d55e8 100644 --- a/ledger/block/src/transaction/mod.rs +++ b/ledger/block/src/transaction/mod.rs @@ -67,7 +67,7 @@ impl Transaction { // Compute the deployment ID. let deployment_id = *deployment_tree.root(); // Compute the transaction ID - let transaction_id = *Self::transaction_tree(deployment_tree, deployment.len(), &fee)?.root(); + let transaction_id = *Self::transaction_tree(deployment_tree, Some(&fee))?.root(); // Ensure the owner signed the correct transaction ID. ensure!(owner.verify(deployment_id), "Attempted to create a deployment transaction with an invalid owner"); // Construct the deployment transaction. @@ -82,14 +82,8 @@ impl Transaction { let execution_tree = Self::execution_tree(&execution)?; // Compute the execution ID. let execution_id = *execution_tree.root(); - // Compute the transaction ID - let transaction_id = match &fee { - Some(fee) => { - // Compute the root of the transaction tree. - *Self::transaction_tree(execution_tree, execution.len(), fee)?.root() - } - None => execution_id, - }; + // Compute the transaction ID. + let transaction_id = *Self::transaction_tree(execution_tree, fee.as_ref())?.root(); // Construct the execution transaction. Ok(Self::Execute(transaction_id.into(), execution_id, Box::new(execution), fee)) } diff --git a/ledger/block/src/transaction/serialize.rs b/ledger/block/src/transaction/serialize.rs index 0aafc2264a..f62f61c250 100644 --- a/ledger/block/src/transaction/serialize.rs +++ b/ledger/block/src/transaction/serialize.rs @@ -18,8 +18,9 @@ use super::*; impl Serialize for Transaction { /// Serializes the transaction to a JSON-string or buffer. fn serialize(&self, serializer: S) -> Result { + // Note: We purposefully do not write out the deployment or execution ID, + // and instead recompute it when reconstructing the transaction, to ensure there was no malleability. match serializer.is_human_readable() { - // We don't write the deployment or execution id, which are recomputed when creating the Transaction. true => match self { Self::Deploy(id, _, owner, deployment, fee) => { let mut transaction = serializer.serialize_struct("Transaction", 5)?; diff --git a/ledger/block/src/transactions/rejected/mod.rs b/ledger/block/src/transactions/rejected/mod.rs index 8453ec49a7..4491937457 100644 --- a/ledger/block/src/transactions/rejected/mod.rs +++ b/ledger/block/src/transactions/rejected/mod.rs @@ -85,15 +85,13 @@ impl Rejected { /// When a transaction is rejected, its fee transition is used to construct the confirmed transaction ID, /// changing the original transaction ID. pub fn to_unconfirmed_id(&self, fee: &Option>) -> Result> { - let (tree, fee_index) = match self { - Self::Deployment(_, deployment) => (Transaction::deployment_tree(deployment)?, deployment.len()), - Self::Execution(execution) => (Transaction::execution_tree(execution)?, execution.len()), + // Compute the deployment or execution tree. + let tree = match self { + Self::Deployment(_, deployment) => Transaction::deployment_tree(deployment)?, + Self::Execution(execution) => Transaction::execution_tree(execution)?, }; - if let Some(fee) = fee { - Ok(*Transaction::transaction_tree(tree, fee_index, fee)?.root()) - } else { - Ok(*tree.root()) - } + // Construct the transaction tree and return the unconfirmed transaction ID. + Ok(*Transaction::transaction_tree(tree, fee.as_ref())?.root()) } } diff --git a/ledger/store/src/helpers/memory/internal/map.rs b/ledger/store/src/helpers/memory/internal/map.rs index 10a2edbb7e..47c69abdf6 100644 --- a/ledger/store/src/helpers/memory/internal/map.rs +++ b/ledger/store/src/helpers/memory/internal/map.rs @@ -33,7 +33,7 @@ use std::{ #[derive(Clone)] pub struct MemoryMap< K: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > { // The reason for using BTreeMap with binary keys is for the order of items to be the same as // the one in the RocksDB-backed DataMap; if not for that, it could be any map @@ -46,7 +46,7 @@ pub struct MemoryMap< impl< K: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > Default for MemoryMap { fn default() -> Self { @@ -61,7 +61,7 @@ impl< impl< K: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > FromIterator<(K, V)> for MemoryMap { /// Initializes a new `MemoryMap` from the given iterator. @@ -82,7 +82,7 @@ impl< impl< 'a, K: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: 'a + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > Map<'a, K, V> for MemoryMap { /// @@ -253,7 +253,7 @@ impl< impl< 'a, K: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: 'a + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > MapRead<'a, K, V> for MemoryMap { type Iterator = core::iter::Map, V>, fn((Vec, V)) -> (Cow<'a, K>, Cow<'a, V>)>; @@ -371,7 +371,7 @@ impl< impl< K: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > Deref for MemoryMap { type Target = Arc, V>>>; diff --git a/ledger/store/src/helpers/memory/internal/nested_map.rs b/ledger/store/src/helpers/memory/internal/nested_map.rs index b0319957e1..4279934549 100644 --- a/ledger/store/src/helpers/memory/internal/nested_map.rs +++ b/ledger/store/src/helpers/memory/internal/nested_map.rs @@ -33,7 +33,7 @@ use std::{ pub struct NestedMemoryMap< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > { // The reason for using BTreeMap with binary keys is for the order of items to be the same as // the one in the RocksDB-backed DataMap; if not for that, it could be any map @@ -48,7 +48,7 @@ pub struct NestedMemoryMap< impl< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > Default for NestedMemoryMap { fn default() -> Self { @@ -65,7 +65,7 @@ impl< impl< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > FromIterator<(M, K, V)> for NestedMemoryMap { /// Initializes a new `NestedMemoryMap` from the given iterator. @@ -94,7 +94,7 @@ impl< 'a, M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: 'a + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > NestedMap<'a, M, K, V> for NestedMemoryMap { /// @@ -239,7 +239,7 @@ impl< 'a, M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: 'a + Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, > NestedMapRead<'a, M, K, V> for NestedMemoryMap { // type Iterator = core::iter::FlatMap< @@ -507,7 +507,7 @@ impl< fn insert< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, >( map: &mut BTreeMap, BTreeSet>>, map_inner: &mut BTreeMap, V>, @@ -531,7 +531,7 @@ fn insert< /// Removes the given map-key pair. fn remove_map< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, >( map: &mut BTreeMap, BTreeSet>>, map_inner: &mut BTreeMap, V>, @@ -557,7 +557,7 @@ fn remove_map< fn remove_key< M: Copy + Clone + PartialEq + Eq + Hash + Serialize + for<'de> Deserialize<'de> + Send + Sync, K: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, - V: Clone + PartialEq + Eq + Serialize + for<'de> Deserialize<'de> + Send + Sync, + V: Clone + Serialize + for<'de> Deserialize<'de> + Send + Sync, >( map: &mut BTreeMap, BTreeSet>>, map_inner: &mut BTreeMap, V>, diff --git a/ledger/store/src/helpers/rocksdb/internal/map.rs b/ledger/store/src/helpers/rocksdb/internal/map.rs index 44536a3daa..aac51b63dd 100644 --- a/ledger/store/src/helpers/rocksdb/internal/map.rs +++ b/ledger/store/src/helpers/rocksdb/internal/map.rs @@ -51,7 +51,7 @@ pub struct InnerDataMap Map<'a, K, V> for DataMap { /// @@ -258,7 +258,7 @@ impl< impl< 'a, K: 'a + Copy + Clone + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync, + V: 'a + Clone + Serialize + DeserializeOwned + Send + Sync, > MapRead<'a, K, V> for DataMap { type Iterator = Iter<'a, K, V>; @@ -404,17 +404,14 @@ impl< pub struct Iter< 'a, K: 'a + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, - V: 'a + PartialEq + Eq + Serialize + DeserializeOwned, + V: 'a + Serialize + DeserializeOwned, > { db_iter: rocksdb::DBRawIterator<'a>, _phantom: PhantomData<(K, V)>, } -impl< - 'a, - K: 'a + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, - V: 'a + PartialEq + Eq + Serialize + DeserializeOwned, -> Iter<'a, K, V> +impl<'a, K: 'a + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, V: 'a + Serialize + DeserializeOwned> + Iter<'a, K, V> { pub(super) fn new(db_iter: rocksdb::DBIterator<'a>) -> Self { Self { db_iter: db_iter.into(), _phantom: PhantomData } @@ -424,7 +421,7 @@ impl< impl< 'a, K: 'a + Clone + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, - V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned, + V: 'a + Clone + Serialize + DeserializeOwned, > Iterator for Iter<'a, K, V> { type Item = (Cow<'a, K>, Cow<'a, V>); @@ -488,18 +485,18 @@ impl<'a, K: 'a + Clone + Debug + PartialEq + Eq + Hash + Serialize + Deserialize } /// An iterator over the values of a prefix. -pub struct Values<'a, V: 'a + PartialEq + Eq + Serialize + DeserializeOwned> { +pub struct Values<'a, V: 'a + Serialize + DeserializeOwned> { db_iter: rocksdb::DBRawIterator<'a>, _phantom: PhantomData, } -impl<'a, V: 'a + PartialEq + Eq + Serialize + DeserializeOwned> Values<'a, V> { +impl<'a, V: 'a + Serialize + DeserializeOwned> Values<'a, V> { pub(crate) fn new(db_iter: rocksdb::DBIterator<'a>) -> Self { Self { db_iter: db_iter.into(), _phantom: PhantomData } } } -impl<'a, V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned> Iterator for Values<'a, V> { +impl<'a, V: 'a + Clone + Serialize + DeserializeOwned> Iterator for Values<'a, V> { type Item = Cow<'a, V>; fn next(&mut self) -> Option { diff --git a/ledger/store/src/helpers/rocksdb/internal/nested_map.rs b/ledger/store/src/helpers/rocksdb/internal/nested_map.rs index 1d10698291..1dc9e3f1bf 100644 --- a/ledger/store/src/helpers/rocksdb/internal/nested_map.rs +++ b/ledger/store/src/helpers/rocksdb/internal/nested_map.rs @@ -105,7 +105,7 @@ impl< 'a, M: 'a + Copy + Clone + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned + Send + Sync, K: 'a + Clone + Debug + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync, + V: 'a + Clone + Serialize + DeserializeOwned + Send + Sync, > NestedMap<'a, M, K, V> for NestedDataMap { /// @@ -346,7 +346,7 @@ impl< 'a, M: 'a + Copy + Clone + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned + Send + Sync, K: 'a + Clone + Debug + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned + Send + Sync, + V: 'a + Clone + Serialize + DeserializeOwned + Send + Sync, > NestedMapRead<'a, M, K, V> for NestedDataMap { type Iterator = NestedIter<'a, M, K, V>; @@ -597,7 +597,7 @@ pub struct NestedIter< 'a, M: 'a + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, K: 'a + Debug + PartialEq + Eq + Serialize + DeserializeOwned, - V: 'a + PartialEq + Eq + Serialize + DeserializeOwned, + V: 'a + Serialize + DeserializeOwned, > { db_iter: rocksdb::DBRawIterator<'a>, _phantom: PhantomData<(M, K, V)>, @@ -607,7 +607,7 @@ impl< 'a, M: 'a + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, K: 'a + Debug + PartialEq + Eq + Serialize + DeserializeOwned, - V: 'a + PartialEq + Eq + Serialize + DeserializeOwned, + V: 'a + Serialize + DeserializeOwned, > NestedIter<'a, M, K, V> { pub(super) fn new(db_iter: rocksdb::DBIterator<'a>) -> Self { @@ -619,7 +619,7 @@ impl< 'a, M: 'a + Clone + Debug + PartialEq + Eq + Hash + Serialize + DeserializeOwned, K: 'a + Clone + Debug + PartialEq + Eq + Serialize + DeserializeOwned, - V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned, + V: 'a + Clone + Serialize + DeserializeOwned, > Iterator for NestedIter<'a, M, K, V> { type Item = (Cow<'a, M>, Cow<'a, K>, Cow<'a, V>); @@ -724,18 +724,18 @@ impl< } /// An iterator over the values of a prefix. -pub struct NestedValues<'a, V: 'a + PartialEq + Eq + Serialize + DeserializeOwned> { +pub struct NestedValues<'a, V: 'a + Serialize + DeserializeOwned> { db_iter: rocksdb::DBRawIterator<'a>, _phantom: PhantomData, } -impl<'a, V: 'a + PartialEq + Eq + Serialize + DeserializeOwned> NestedValues<'a, V> { +impl<'a, V: 'a + Serialize + DeserializeOwned> NestedValues<'a, V> { pub(crate) fn new(db_iter: rocksdb::DBIterator<'a>) -> Self { Self { db_iter: db_iter.into(), _phantom: PhantomData } } } -impl<'a, V: 'a + Clone + PartialEq + Eq + Serialize + DeserializeOwned> Iterator for NestedValues<'a, V> { +impl<'a, V: 'a + Clone + Serialize + DeserializeOwned> Iterator for NestedValues<'a, V> { type Item = Cow<'a, V>; fn next(&mut self) -> Option { diff --git a/ledger/store/src/helpers/traits/map.rs b/ledger/store/src/helpers/traits/map.rs index fefa522ef6..ad435ac007 100644 --- a/ledger/store/src/helpers/traits/map.rs +++ b/ledger/store/src/helpers/traits/map.rs @@ -22,7 +22,7 @@ use std::borrow::Cow; pub trait Map< 'a, K: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Send + Sync, + V: 'a + Clone + Serialize + Deserialize<'a> + Send + Sync, >: Clone + MapRead<'a, K, V> + Send + Sync { /// @@ -93,7 +93,7 @@ pub trait Map< pub trait MapRead< 'a, K: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Sync, + V: 'a + Clone + Serialize + Deserialize<'a> + Sync, > { type PendingIterator: Iterator, Option>)>; diff --git a/ledger/store/src/helpers/traits/nested_map.rs b/ledger/store/src/helpers/traits/nested_map.rs index c3b5729723..eaba238d96 100644 --- a/ledger/store/src/helpers/traits/nested_map.rs +++ b/ledger/store/src/helpers/traits/nested_map.rs @@ -23,7 +23,7 @@ pub trait NestedMap< 'a, M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Send + Sync, K: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Send + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Send + Sync, + V: 'a + Clone + Serialize + Deserialize<'a> + Send + Sync, >: Clone + NestedMapRead<'a, M, K, V> + Send + Sync { /// @@ -87,7 +87,7 @@ pub trait NestedMapRead< 'a, M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Sync, K: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Sync, - V: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Sync, + V: 'a + Clone + Serialize + Deserialize<'a> + Sync, > { type PendingIterator: Iterator, Option>, Option>)>;