diff --git a/.changelog/unreleased/bugs/912-remove-prefix-iter.md b/.changelog/unreleased/bugs/912-remove-prefix-iter.md new file mode 100644 index 0000000000..20e553a8a7 --- /dev/null +++ b/.changelog/unreleased/bugs/912-remove-prefix-iter.md @@ -0,0 +1,3 @@ +- Removed 'rev_iter_prefix' from storage API as its implementation + depends on RocksDB and it doesn't work as expected. + ([#912](https://github.com/anoma/namada/pull/912)) diff --git a/.changelog/unreleased/improvements/966-gats-lifetimes-refactor.md b/.changelog/unreleased/improvements/966-gats-lifetimes-refactor.md new file mode 100644 index 0000000000..b3233a072e --- /dev/null +++ b/.changelog/unreleased/improvements/966-gats-lifetimes-refactor.md @@ -0,0 +1,2 @@ +- Hide the explicit lifetime from StorageRead trait. + ([#966](https://github.com/anoma/namada/pull/966)) \ No newline at end of file diff --git a/apps/src/lib/node/ledger/storage/mod.rs b/apps/src/lib/node/ledger/storage/mod.rs index f24cffa6a3..1bd1446c51 100644 --- a/apps/src/lib/node/ledger/storage/mod.rs +++ b/apps/src/lib/node/ledger/storage/mod.rs @@ -50,10 +50,13 @@ fn new_blake2b() -> Blake2b { #[cfg(test)] mod tests { + use borsh::BorshSerialize; + use itertools::Itertools; use namada::ledger::storage::types; - use namada::types::address; + use namada::ledger::storage_api; use namada::types::chain::ChainId; use namada::types::storage::{BlockHash, BlockHeight, Key}; + use namada::types::{address, storage}; use proptest::collection::vec; use proptest::prelude::*; use proptest::test_runner::Config; @@ -344,4 +347,45 @@ mod tests { Ok(()) } + + /// Test the prefix iterator with RocksDB. + #[test] + fn test_persistent_storage_prefix_iter() { + let db_path = + TempDir::new().expect("Unable to create a temporary DB directory"); + let mut storage = PersistentStorage::open( + db_path.path(), + ChainId::default(), + address::nam(), + None, + ); + + let prefix = storage::Key::parse("prefix").unwrap(); + let mismatched_prefix = storage::Key::parse("different").unwrap(); + // We'll write sub-key in some random order to check prefix iter's order + let sub_keys = [2_i32, 1, i32::MAX, -1, 260, -2, i32::MIN, 5, 0]; + + for i in sub_keys.iter() { + let key = prefix.push(i).unwrap(); + let value = i.try_to_vec().unwrap(); + storage.write(&key, value).unwrap(); + + let key = mismatched_prefix.push(i).unwrap(); + let value = (i / 2).try_to_vec().unwrap(); + storage.write(&key, value).unwrap(); + } + storage.commit().unwrap(); + + // Then try to iterate over their prefix + let iter = storage_api::iter_prefix(&storage, &prefix) + .unwrap() + .map(Result::unwrap); + + // The order has to be sorted by sub-key value + let expected = sub_keys + .iter() + .sorted() + .map(|i| (prefix.push(i).unwrap(), *i)); + itertools::assert_equal(iter, expected); + } } diff --git a/apps/src/lib/node/ledger/storage/rocksdb.rs b/apps/src/lib/node/ledger/storage/rocksdb.rs index 86980813fc..fa7c981697 100644 --- a/apps/src/lib/node/ledger/storage/rocksdb.rs +++ b/apps/src/lib/node/ledger/storage/rocksdb.rs @@ -891,11 +891,7 @@ impl<'iter> DBIter<'iter> for RocksDB { &'iter self, prefix: &Key, ) -> PersistentPrefixIterator<'iter> { - iter_prefix(self, prefix, Direction::Forward) - } - - fn rev_iter_prefix(&'iter self, prefix: &Key) -> Self::PrefixIter { - iter_prefix(self, prefix, Direction::Reverse) + iter_prefix(self, prefix) } fn iter_results(&'iter self) -> PersistentPrefixIterator<'iter> { @@ -922,7 +918,6 @@ impl<'iter> DBIter<'iter> for RocksDB { fn iter_prefix<'iter>( db: &'iter RocksDB, prefix: &Key, - direction: Direction, ) -> PersistentPrefixIterator<'iter> { let db_prefix = "subspace/".to_owned(); let prefix = format!("{}{}", db_prefix, prefix); @@ -937,7 +932,7 @@ fn iter_prefix<'iter>( read_opts.set_iterate_upper_bound(upper_prefix); let iter = db.0.iterator_opt( - IteratorMode::From(prefix.as_bytes(), direction), + IteratorMode::From(prefix.as_bytes(), Direction::Forward), read_opts, ); PersistentPrefixIterator(PrefixIterator::new(iter, db_prefix)) diff --git a/core/src/ledger/storage/mockdb.rs b/core/src/ledger/storage/mockdb.rs index 011d8faac8..eb8ae04543 100644 --- a/core/src/ledger/storage/mockdb.rs +++ b/core/src/ledger/storage/mockdb.rs @@ -446,42 +446,14 @@ impl<'iter> DBIter<'iter> for MockDB { let db_prefix = "subspace/".to_owned(); let prefix = format!("{}{}", db_prefix, prefix); let iter = self.0.borrow().clone().into_iter(); - MockPrefixIterator::new( - MockIterator { - prefix, - iter, - reverse_order: false, - }, - db_prefix, - ) - } - - fn rev_iter_prefix(&'iter self, prefix: &Key) -> Self::PrefixIter { - let db_prefix = "subspace/".to_owned(); - let prefix = format!("{}{}", db_prefix, prefix); - let iter = self.0.borrow().clone().into_iter(); - MockPrefixIterator::new( - MockIterator { - prefix, - iter, - reverse_order: true, - }, - db_prefix, - ) + MockPrefixIterator::new(MockIterator { prefix, iter }, db_prefix) } fn iter_results(&'iter self) -> MockPrefixIterator { let db_prefix = "results/".to_owned(); let prefix = "results".to_owned(); let iter = self.0.borrow().clone().into_iter(); - MockPrefixIterator::new( - MockIterator { - prefix, - iter, - reverse_order: false, - }, - db_prefix, - ) + MockPrefixIterator::new(MockIterator { prefix, iter }, db_prefix) } } @@ -491,8 +463,6 @@ pub struct MockIterator { prefix: String, /// The concrete iterator pub iter: btree_map::IntoIter>, - /// Is the iterator in reverse order? - reverse_order: bool, } /// A prefix iterator for the [`MockDB`]. @@ -502,23 +472,12 @@ impl Iterator for MockIterator { type Item = Result; fn next(&mut self) -> Option { - if self.reverse_order { - for (key, val) in (&mut self.iter).rev() { - if key.starts_with(&self.prefix) { - return Some(Ok(( - Box::from(key.as_bytes()), - Box::from(val.as_slice()), - ))); - } - } - } else { - for (key, val) in &mut self.iter { - if key.starts_with(&self.prefix) { - return Some(Ok(( - Box::from(key.as_bytes()), - Box::from(val.as_slice()), - ))); - } + for (key, val) in &mut self.iter { + if key.starts_with(&self.prefix) { + return Some(Ok(( + Box::from(key.as_bytes()), + Box::from(val.as_slice()), + ))); } } None diff --git a/core/src/ledger/storage/mod.rs b/core/src/ledger/storage/mod.rs index 8285e58bab..13d0db6c7e 100644 --- a/core/src/ledger/storage/mod.rs +++ b/core/src/ledger/storage/mod.rs @@ -305,10 +305,6 @@ pub trait DBIter<'iter> { /// ordered by the storage keys. fn iter_prefix(&'iter self, prefix: &Key) -> Self::PrefixIter; - /// Read account subspace key value pairs with the given prefix from the DB, - /// reverse ordered by the storage keys. - fn rev_iter_prefix(&'iter self, prefix: &Key) -> Self::PrefixIter; - /// Read results subspace key value pairs from the DB fn iter_results(&'iter self) -> Self::PrefixIter; } @@ -515,15 +511,6 @@ where (self.db.iter_prefix(prefix), prefix.len() as _) } - /// Returns a prefix iterator, reverse ordered by storage keys, and the gas - /// cost - pub fn rev_iter_prefix( - &self, - prefix: &Key, - ) -> (>::PrefixIter, u64) { - (self.db.rev_iter_prefix(prefix), prefix.len() as _) - } - /// Returns a prefix iterator and the gas cost pub fn iter_results(&self) -> (>::PrefixIter, u64) { (self.db.iter_results(), 0) @@ -1005,12 +992,15 @@ where } } -impl<'iter, D, H> StorageRead<'iter> for Storage +impl StorageRead for Storage where D: DB + for<'iter_> DBIter<'iter_>, H: StorageHasher, { - type PrefixIter = >::PrefixIter; + type PrefixIter<'iter> = >::PrefixIter +where + Self: 'iter + ; fn read_bytes( &self, @@ -1026,23 +1016,16 @@ where self.block.tree.has_key(key).into_storage_result() } - fn iter_prefix( + fn iter_prefix<'iter>( &'iter self, prefix: &crate::types::storage::Key, - ) -> std::result::Result { + ) -> std::result::Result, storage_api::Error> { Ok(self.db.iter_prefix(prefix)) } - fn rev_iter_prefix( + fn iter_next<'iter>( &'iter self, - prefix: &crate::types::storage::Key, - ) -> std::result::Result { - Ok(self.db.rev_iter_prefix(prefix)) - } - - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + iter: &mut Self::PrefixIter<'iter>, ) -> std::result::Result)>, storage_api::Error> { Ok(iter.next().map(|(key, val, _gas)| (key, val))) @@ -1119,44 +1102,6 @@ where } } -impl StorageWrite for &mut Storage -where - D: DB + for<'iter> DBIter<'iter>, - H: StorageHasher, -{ - fn write( - &mut self, - key: &crate::types::storage::Key, - val: T, - ) -> storage_api::Result<()> { - let val = val.try_to_vec().unwrap(); - self.write_bytes(key, val) - } - - fn write_bytes( - &mut self, - key: &crate::types::storage::Key, - val: impl AsRef<[u8]>, - ) -> storage_api::Result<()> { - let _ = self - .db - .write_subspace_val(self.block.height, key, val) - .into_storage_result()?; - Ok(()) - } - - fn delete( - &mut self, - key: &crate::types::storage::Key, - ) -> storage_api::Result<()> { - let _ = self - .db - .delete_subspace_val(self.block.height, key) - .into_storage_result()?; - Ok(()) - } -} - impl From for Error { fn from(error: MerkleTreeError) -> Self { Self::MerkleTreeError(error) diff --git a/core/src/ledger/storage_api/collections/lazy_map.rs b/core/src/ledger/storage_api/collections/lazy_map.rs index 34a0f7d891..81ddd7f42d 100644 --- a/core/src/ledger/storage_api/collections/lazy_map.rs +++ b/core/src/ledger/storage_api/collections/lazy_map.rs @@ -323,7 +323,7 @@ where /// Returns whether the set contains a value. pub fn contains(&self, storage: &S, key: &K) -> Result where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { storage.has_key(&self.get_data_key(key)) } @@ -363,7 +363,7 @@ where /// map. pub fn iter<'iter>( &'iter self, - storage: &'iter impl StorageRead<'iter>, + storage: &'iter impl StorageRead, ) -> Result< impl Iterator< Item = Result<( @@ -406,7 +406,7 @@ where val: V, ) -> Result> where - S: StorageWrite + for<'iter> StorageRead<'iter>, + S: StorageWrite + StorageRead, { let previous = self.get(storage, &key)?; @@ -420,7 +420,7 @@ where /// was previously in the map. pub fn remove(&self, storage: &mut S, key: &K) -> Result> where - S: StorageWrite + for<'iter> StorageRead<'iter>, + S: StorageWrite + StorageRead, { let value = self.get(storage, key)?; @@ -433,7 +433,7 @@ where /// Returns the value corresponding to the key, if any. pub fn get(&self, storage: &S, key: &K) -> Result> where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let data_key = self.get_data_key(key); Self::read_key_val(storage, &data_key) @@ -442,7 +442,7 @@ where /// Returns whether the map contains no elements. pub fn is_empty(&self, storage: &S) -> Result where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let mut iter = storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; @@ -457,7 +457,7 @@ where #[allow(clippy::len_without_is_empty)] pub fn len(&self, storage: &S) -> Result where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let iter = storage_api::iter_prefix_bytes(storage, &self.get_data_prefix())?; @@ -473,7 +473,7 @@ where /// map. pub fn iter<'iter>( &self, - storage: &'iter impl StorageRead<'iter>, + storage: &'iter impl StorageRead, ) -> Result> + 'iter> { let iter = storage_api::iter_prefix(storage, &self.get_data_prefix())?; Ok(iter.map(|key_val_res| { @@ -493,7 +493,7 @@ where storage_key: &storage::Key, ) -> Result> where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let res = storage.read(storage_key)?; Ok(res) diff --git a/core/src/ledger/storage_api/collections/lazy_vec.rs b/core/src/ledger/storage_api/collections/lazy_vec.rs index 59eaa225e5..0e0a5ab03b 100644 --- a/core/src/ledger/storage_api/collections/lazy_vec.rs +++ b/core/src/ledger/storage_api/collections/lazy_vec.rs @@ -358,7 +358,7 @@ impl LazyVec { #[allow(clippy::len_without_is_empty)] pub fn len(&self, storage: &S) -> Result where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let len = storage.read(&self.get_len_key())?; Ok(len.unwrap_or_default()) @@ -367,7 +367,7 @@ impl LazyVec { /// Returns `true` if the vector contains no elements. pub fn is_empty(&self, storage: &S) -> Result where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { Ok(self.len(storage)? == 0) } @@ -396,7 +396,7 @@ where /// Appends an element to the back of a collection. pub fn push(&self, storage: &mut S, val: T) -> Result<()> where - S: StorageWrite + for<'iter> StorageRead<'iter>, + S: StorageWrite + StorageRead, { let len = self.len(storage)?; let data_key = self.get_data_key(len); @@ -410,7 +410,7 @@ where /// Note that an empty vector is completely removed from storage. pub fn pop(&self, storage: &mut S) -> Result> where - S: StorageWrite + for<'iter> StorageRead<'iter>, + S: StorageWrite + StorageRead, { let len = self.len(storage)?; if len == 0 { @@ -435,7 +435,7 @@ where /// will fail with `UpdateError::InvalidIndex`. pub fn update(&self, storage: &mut S, index: Index, val: T) -> Result<()> where - S: StorageWrite + for<'iter> StorageRead<'iter>, + S: StorageWrite + StorageRead, { let len = self.len(storage)?; if index >= len { @@ -449,7 +449,7 @@ where /// Read an element at the index or `Ok(None)` if out of bounds. pub fn get(&self, storage: &S, index: Index) -> Result> where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { storage.read(&self.get_data_key(index)) } @@ -463,7 +463,7 @@ where /// set. pub fn iter<'iter>( &self, - storage: &'iter impl StorageRead<'iter>, + storage: &'iter impl StorageRead, ) -> Result> + 'iter> { let iter = storage_api::iter_prefix(storage, &self.get_data_prefix())?; Ok(iter.map(|key_val_res| { diff --git a/core/src/ledger/storage_api/key.rs b/core/src/ledger/storage_api/key.rs index 06b3c76bad..6e3eba64aa 100644 --- a/core/src/ledger/storage_api/key.rs +++ b/core/src/ledger/storage_api/key.rs @@ -8,7 +8,7 @@ use crate::types::key::*; /// not found. pub fn get(storage: &S, owner: &Address) -> Result> where - S: for<'iter> StorageRead<'iter>, + S: StorageRead, { let key = pk_key(owner); storage.read(&key) diff --git a/core/src/ledger/storage_api/mod.rs b/core/src/ledger/storage_api/mod.rs index 7c842a6136..c929aec03b 100644 --- a/core/src/ledger/storage_api/mod.rs +++ b/core/src/ledger/storage_api/mod.rs @@ -20,21 +20,17 @@ use crate::types::storage::{self, BlockHash, BlockHeight, Epoch, TxIndex}; /// /// ```rust,ignore /// where -/// S: for<'iter> StorageRead<'iter> +/// S: StorageRead /// ``` /// /// If you want to know why this is needed, see the to-do task below. The /// syntax for this relies on higher-rank lifetimes, see e.g. /// . -/// -/// TODO: once GATs are stabilized, we should be able to remove the `'iter` -/// lifetime param that is currently the only way to make the prefix iterator -/// typecheck in the `>::PrefixIter` associated type used in -/// `impl StorageRead for Storage` (shared/src/ledger/storage/mod.rs). -/// See -pub trait StorageRead<'iter> { +pub trait StorageRead { /// Storage read prefix iterator - type PrefixIter; + type PrefixIter<'iter> + where + Self: 'iter; /// Storage read Borsh encoded value. It will try to read from the storage /// and decode it if found. @@ -63,25 +59,15 @@ pub trait StorageRead<'iter> { /// /// For a more user-friendly iterator API, use [`fn@iter_prefix`] or /// [`fn@iter_prefix_bytes`] instead. - fn iter_prefix( - &'iter self, - prefix: &storage::Key, - ) -> Result; - - /// Storage prefix iterator in reverse order of the storage keys. It will - /// try to get an iterator from the storage. - /// - /// For a more user-friendly iterator API, use [`fn@rev_iter_prefix`] or - /// [`fn@rev_iter_prefix_bytes`] instead. - fn rev_iter_prefix( + fn iter_prefix<'iter>( &'iter self, prefix: &storage::Key, - ) -> Result; + ) -> Result>; /// Storage prefix iterator. It will try to read from the storage. - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>>; /// Getting the chain ID. @@ -131,7 +117,7 @@ pub trait StorageWrite { /// Iterate items matching the given prefix, ordered by the storage keys. pub fn iter_prefix_bytes<'a>( - storage: &'a impl StorageRead<'a>, + storage: &'a impl StorageRead, prefix: &crate::types::storage::Key, ) -> Result)>> + 'a> { let iter = storage.iter_prefix(prefix)?; @@ -160,7 +146,7 @@ pub fn iter_prefix_bytes<'a>( /// Iterate Borsh encoded items matching the given prefix, ordered by the /// storage keys. pub fn iter_prefix<'a, T>( - storage: &'a impl StorageRead<'a>, + storage: &'a impl StorageRead, prefix: &crate::types::storage::Key, ) -> Result> + 'a> where @@ -195,71 +181,3 @@ where }); Ok(iter) } - -/// Iterate items matching the given prefix, reverse ordered by the storage -/// keys. -pub fn rev_iter_prefix_bytes<'a>( - storage: &'a impl StorageRead<'a>, - prefix: &crate::types::storage::Key, -) -> Result)>> + 'a> { - let iter = storage.rev_iter_prefix(prefix)?; - let iter = itertools::unfold(iter, |iter| { - match storage.iter_next(iter) { - Ok(Some((key, val))) => { - let key = match storage::Key::parse(key).into_storage_result() { - Ok(key) => key, - Err(err) => { - // Propagate key encoding errors into Iterator's Item - return Some(Err(err)); - } - }; - Some(Ok((key, val))) - } - Ok(None) => None, - Err(err) => { - // Propagate `iter_next` errors into Iterator's Item - Some(Err(err)) - } - } - }); - Ok(iter) -} - -/// Iterate Borsh encoded items matching the given prefix, reverse ordered by -/// the storage keys. -pub fn rev_iter_prefix<'a, T>( - storage: &'a impl StorageRead<'a>, - prefix: &crate::types::storage::Key, -) -> Result> + 'a> -where - T: BorshDeserialize, -{ - let iter = storage.rev_iter_prefix(prefix)?; - let iter = itertools::unfold(iter, |iter| { - match storage.iter_next(iter) { - Ok(Some((key, val))) => { - let key = match storage::Key::parse(key).into_storage_result() { - Ok(key) => key, - Err(err) => { - // Propagate key encoding errors into Iterator's Item - return Some(Err(err)); - } - }; - let val = match T::try_from_slice(&val).into_storage_result() { - Ok(val) => val, - Err(err) => { - // Propagate val encoding errors into Iterator's Item - return Some(Err(err)); - } - }; - Some(Ok((key, val))) - } - Ok(None) => None, - Err(err) => { - // Propagate `iter_next` errors into Iterator's Item - Some(Err(err)) - } - } - }); - Ok(iter) -} diff --git a/core/src/ledger/tx_env.rs b/core/src/ledger/tx_env.rs index 7672ac6505..6ca47bb9d9 100644 --- a/core/src/ledger/tx_env.rs +++ b/core/src/ledger/tx_env.rs @@ -10,7 +10,7 @@ use crate::types::storage; use crate::types::time::Rfc3339String; /// Transaction host functions -pub trait TxEnv<'iter>: StorageRead<'iter> + StorageWrite { +pub trait TxEnv: StorageRead + StorageWrite { /// Write a temporary value to be encoded with Borsh at the given key to /// storage. fn write_temp( diff --git a/core/src/ledger/vp_env.rs b/core/src/ledger/vp_env.rs index 49bd5d515c..43bc744635 100644 --- a/core/src/ledger/vp_env.rs +++ b/core/src/ledger/vp_env.rs @@ -10,15 +10,20 @@ use crate::types::key::common; use crate::types::storage::{BlockHash, BlockHeight, Epoch, Key, TxIndex}; /// Validity predicate's environment is available for native VPs and WASM VPs -pub trait VpEnv<'view> { +pub trait VpEnv<'view> +where + Self: 'view, +{ /// Storage read prefix iterator - type PrefixIter; + type PrefixIter<'iter> + where + Self: 'iter; /// Type to read storage state before the transaction execution - type Pre: StorageRead<'view, PrefixIter = Self::PrefixIter>; + type Pre: StorageRead = Self::PrefixIter<'view>>; /// Type to read storage state after the transaction execution - type Post: StorageRead<'view, PrefixIter = Self::PrefixIter>; + type Post: StorageRead = Self::PrefixIter<'view>>; /// Read storage state before the transaction execution fn pre(&'view self) -> Self::Pre; @@ -42,40 +47,32 @@ pub trait VpEnv<'view> { ) -> Result>, storage_api::Error>; /// Getting the chain ID. - fn get_chain_id(&'view self) -> Result; + fn get_chain_id(&self) -> Result; /// Getting the block height. The height is that of the block to which the /// current transaction is being applied. - fn get_block_height(&'view self) - -> Result; + fn get_block_height(&self) -> Result; /// Getting the block hash. The height is that of the block to which the /// current transaction is being applied. - fn get_block_hash(&'view self) -> Result; + fn get_block_hash(&self) -> Result; /// Getting the block epoch. The epoch is that of the block to which the /// current transaction is being applied. - fn get_block_epoch(&'view self) -> Result; + fn get_block_epoch(&self) -> Result; /// Get the shielded transaction index. - fn get_tx_index(&'view self) -> Result; + fn get_tx_index(&self) -> Result; /// Get the address of the native token. - fn get_native_token(&'view self) -> Result; + fn get_native_token(&self) -> Result; /// Storage prefix iterator, ordered by storage keys. It will try to get an /// iterator from the storage. - fn iter_prefix( - &'view self, - prefix: &Key, - ) -> Result; - - /// Storage prefix iterator, reverse ordered by storage keys. It will try to - /// get an iterator from the storage. - fn rev_iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &Key, - ) -> Result; + ) -> Result, storage_api::Error>; /// Evaluate a validity predicate with given data. The address, changed /// storage keys and verifiers will have the same values as the input to @@ -158,23 +155,4 @@ pub trait VpEnv<'view> { ) -> Result { self.post().has_key(key) } - - /// Storage prefix iterator for prior state (before tx execution). It will - /// try to read from the storage. - fn iter_pre_next( - &'view self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.pre().iter_next(iter) - } - - /// Storage prefix iterator next for posterior state (after tx execution). - /// It will try to read from the write log first and if no entry found - /// then from the storage. - fn iter_post_next( - &'view self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.post().iter_next(iter) - } } diff --git a/shared/src/ledger/ibc/vp/channel.rs b/shared/src/ledger/ibc/vp/channel.rs index 05cbf7ad15..e85a221212 100644 --- a/shared/src/ledger/ibc/vp/channel.rs +++ b/shared/src/ledger/ibc/vp/channel.rs @@ -19,6 +19,7 @@ use namada_core::ledger::ibc::storage::{ }; use namada_core::ledger::parameters; use namada_core::ledger::storage::{self as ledger_storage, StorageHasher}; +use namada_core::ledger::storage_api::StorageRead; use namada_core::types::storage::Key; use sha2::Digest; use thiserror::Error; @@ -734,14 +735,13 @@ where let mut channels = vec![]; let prefix = Key::parse("channelEnds/ports") .expect("Creating a key for the prefix shouldn't fail"); - let mut iter = self - .ctx + let post = self.ctx.post(); + let mut iter = post .iter_prefix(&prefix) .map_err(|_| Ics04Error::implementation_specific())?; loop { - let next = self - .ctx - .iter_post_next(&mut iter) + let next = post + .iter_next(&mut iter) .map_err(|_| Ics04Error::implementation_specific())?; if let Some((key, value)) = next { let channel = ChannelEnd::decode_vec(&value) diff --git a/shared/src/ledger/ibc/vp/client.rs b/shared/src/ledger/ibc/vp/client.rs index 40807673f1..9bc5d20efb 100644 --- a/shared/src/ledger/ibc/vp/client.rs +++ b/shared/src/ledger/ibc/vp/client.rs @@ -6,6 +6,7 @@ use namada_core::ledger::ibc::actions::{ make_create_client_event, make_update_client_event, make_upgrade_client_event, }; +use namada_core::ledger::storage_api::StorageRead; use thiserror::Error; use super::super::storage::{ @@ -478,14 +479,13 @@ where height: Height, ) -> Ics02Result> { let prefix = consensus_state_prefix(client_id); - let mut iter = self - .ctx + let pre = self.ctx.pre(); + let mut iter = pre .iter_prefix(&prefix) .map_err(|_| Ics02Error::implementation_specific())?; let mut lowest_height_value = None; - while let Some((key, value)) = self - .ctx - .iter_pre_next(&mut iter) + while let Some((key, value)) = pre + .iter_next(&mut iter) .map_err(|_| Ics02Error::implementation_specific())? { let key = Key::parse(key) @@ -519,14 +519,13 @@ where height: Height, ) -> Ics02Result> { let prefix = consensus_state_prefix(client_id); - let mut iter = self - .ctx + let pre = self.ctx.pre(); + let mut iter = pre .iter_prefix(&prefix) .map_err(|_| Ics02Error::implementation_specific())?; let mut highest_height_value = None; - while let Some((key, value)) = self - .ctx - .iter_pre_next(&mut iter) + while let Some((key, value)) = pre + .iter_next(&mut iter) .map_err(|_| Ics02Error::implementation_specific())? { let key = Key::parse(key) diff --git a/shared/src/ledger/native_vp/governance/utils.rs b/shared/src/ledger/native_vp/governance/utils.rs index eb96948c49..4fd0a68217 100644 --- a/shared/src/ledger/native_vp/governance/utils.rs +++ b/shared/src/ledger/native_vp/governance/utils.rs @@ -220,7 +220,7 @@ pub fn is_proposal_accepted( tx_data: &[u8], ) -> storage_api::Result where - S: for<'iter> storage_api::StorageRead<'iter>, + S: storage_api::StorageRead, { let proposal_id = u64::try_from_slice(tx_data).ok(); match proposal_id { diff --git a/shared/src/ledger/native_vp/mod.rs b/shared/src/ledger/native_vp/mod.rs index 8943c4f8d3..0907c1cc38 100644 --- a/shared/src/ledger/native_vp/mod.rs +++ b/shared/src/ledger/native_vp/mod.rs @@ -169,14 +169,14 @@ where } } -impl<'view, 'a, DB, H, CA> StorageRead<'view> +impl<'view, 'a: 'view, DB, H, CA> StorageRead for CtxPreStorageRead<'view, 'a, DB, H, CA> where DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>, H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - type PrefixIter = >::PrefixIter; + type PrefixIter<'iter> = >::PrefixIter where Self: 'iter; fn read_bytes( &self, @@ -203,16 +203,9 @@ where .into_storage_result() } - fn rev_iter_prefix( - &self, - prefix: &crate::types::storage::Key, - ) -> storage_api::Result { - self.ctx.rev_iter_prefix(prefix).into_storage_result() - } - - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>, storage_api::Error> { vp_host_fns::iter_pre_next::( &mut self.ctx.gas_meter.borrow_mut(), @@ -224,10 +217,10 @@ where // ---- Methods below are implemented in `self.ctx`, because they are // the same in `pre/post` ---- - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &crate::types::storage::Key, - ) -> Result { + ) -> Result, storage_api::Error> { self.ctx.iter_prefix(prefix) } @@ -256,14 +249,14 @@ where } } -impl<'view, 'a, DB, H, CA> StorageRead<'view> +impl<'view, 'a: 'view, DB, H, CA> StorageRead for CtxPostStorageRead<'view, 'a, DB, H, CA> where DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>, H: 'static + StorageHasher, CA: 'static + WasmCacheAccess, { - type PrefixIter = >::PrefixIter; + type PrefixIter<'iter> = >::PrefixIter where Self:'iter; fn read_bytes( &self, @@ -291,16 +284,9 @@ where .into_storage_result() } - fn rev_iter_prefix( - &self, - prefix: &crate::types::storage::Key, - ) -> storage_api::Result { - self.ctx.rev_iter_prefix(prefix).into_storage_result() - } - - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>, storage_api::Error> { vp_host_fns::iter_post_next::( &mut self.ctx.gas_meter.borrow_mut(), @@ -313,10 +299,10 @@ where // ---- Methods below are implemented in `self.ctx`, because they are // the same in `pre/post` ---- - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &crate::types::storage::Key, - ) -> Result { + ) -> Result, storage_api::Error> { self.ctx.iter_prefix(prefix) } @@ -353,7 +339,7 @@ where { type Post = CtxPostStorageRead<'view, 'a, DB, H, CA>; type Pre = CtxPreStorageRead<'view, 'a, DB, H, CA>; - type PrefixIter = >::PrefixIter; + type PrefixIter<'iter> = >::PrefixIter where Self: 'iter; fn pre(&'view self) -> Self::Pre { CtxPreStorageRead { ctx: self } @@ -388,7 +374,7 @@ where .into_storage_result() } - fn get_chain_id(&'view self) -> Result { + fn get_chain_id(&self) -> Result { vp_host_fns::get_chain_id( &mut self.gas_meter.borrow_mut(), self.storage, @@ -396,9 +382,7 @@ where .into_storage_result() } - fn get_block_height( - &'view self, - ) -> Result { + fn get_block_height(&self) -> Result { vp_host_fns::get_block_height( &mut self.gas_meter.borrow_mut(), self.storage, @@ -406,7 +390,7 @@ where .into_storage_result() } - fn get_block_hash(&'view self) -> Result { + fn get_block_hash(&self) -> Result { vp_host_fns::get_block_hash( &mut self.gas_meter.borrow_mut(), self.storage, @@ -414,7 +398,7 @@ where .into_storage_result() } - fn get_block_epoch(&'view self) -> Result { + fn get_block_epoch(&self) -> Result { vp_host_fns::get_block_epoch( &mut self.gas_meter.borrow_mut(), self.storage, @@ -422,7 +406,7 @@ where .into_storage_result() } - fn get_tx_index(&'view self) -> Result { + fn get_tx_index(&self) -> Result { vp_host_fns::get_tx_index( &mut self.gas_meter.borrow_mut(), self.tx_index, @@ -430,7 +414,7 @@ where .into_storage_result() } - fn get_native_token(&'view self) -> Result { + fn get_native_token(&self) -> Result { vp_host_fns::get_native_token( &mut self.gas_meter.borrow_mut(), self.storage, @@ -438,10 +422,10 @@ where .into_storage_result() } - fn iter_prefix( - &'view self, + fn iter_prefix<'iter>( + &'iter self, prefix: &Key, - ) -> Result { + ) -> Result, storage_api::Error> { vp_host_fns::iter_prefix( &mut self.gas_meter.borrow_mut(), self.storage, @@ -450,18 +434,6 @@ where .into_storage_result() } - fn rev_iter_prefix( - &self, - prefix: &Key, - ) -> Result { - vp_host_fns::rev_iter_prefix( - &mut self.gas_meter.borrow_mut(), - self.storage, - prefix, - ) - .into_storage_result() - } - fn eval( &self, vp_code: Vec, @@ -539,55 +511,38 @@ where } fn read_pre( - &'view self, + &self, key: &Key, ) -> Result, storage_api::Error> { self.pre().read(key).map_err(Into::into) } fn read_bytes_pre( - &'view self, + &self, key: &Key, ) -> Result>, storage_api::Error> { self.pre().read_bytes(key).map_err(Into::into) } fn read_post( - &'view self, + &self, key: &Key, ) -> Result, storage_api::Error> { self.post().read(key).map_err(Into::into) } fn read_bytes_post( - &'view self, + &self, key: &Key, ) -> Result>, storage_api::Error> { self.post().read_bytes(key).map_err(Into::into) } - fn has_key_pre(&'view self, key: &Key) -> Result { + fn has_key_pre(&self, key: &Key) -> Result { self.pre().has_key(key).map_err(Into::into) } - fn has_key_post( - &'view self, - key: &Key, - ) -> Result { + fn has_key_post(&self, key: &Key) -> Result { self.post().has_key(key).map_err(Into::into) } - - fn iter_pre_next( - &'view self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.pre().iter_next(iter).map_err(Into::into) - } - - fn iter_post_next( - &'view self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.post().iter_next(iter).map_err(Into::into) - } } diff --git a/shared/src/ledger/pos/vp.rs b/shared/src/ledger/pos/vp.rs index e1b13648d0..2a2e87bdba 100644 --- a/shared/src/ledger/pos/vp.rs +++ b/shared/src/ledger/pos/vp.rs @@ -305,7 +305,7 @@ where } impl_pos_read_only! { - impl<'f, 'a, DB, H, CA> PosReadOnly for CtxPreStorageRead<'f, 'a, DB, H, CA> + impl<'view, 'a: 'view, DB, H, CA> PosReadOnly for CtxPreStorageRead<'view, 'a, DB, H, CA> where DB: ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter> +'static, H: StorageHasher +'static, @@ -313,7 +313,7 @@ impl_pos_read_only! { } impl_pos_read_only! { - impl<'f, 'a, DB, H, CA> PosReadOnly for CtxPostStorageRead<'f, 'a, DB, H, CA> + impl<'view, 'a: 'view, DB, H, CA> PosReadOnly for CtxPostStorageRead<'view, 'a, DB, H, CA> where DB: ledger_storage::DB + for<'iter> ledger_storage::DBIter<'iter> +'static, H: StorageHasher +'static, diff --git a/shared/src/ledger/vp_host_fns.rs b/shared/src/ledger/vp_host_fns.rs index 8fc013075a..c678744ccf 100644 --- a/shared/src/ledger/vp_host_fns.rs +++ b/shared/src/ledger/vp_host_fns.rs @@ -311,22 +311,6 @@ where Ok(iter) } -/// Storage prefix iterator, reverse ordered by storage keys. It will try to get -/// an iterator from the storage. -pub fn rev_iter_prefix<'a, DB, H>( - gas_meter: &mut VpGasMeter, - storage: &'a Storage, - prefix: &Key, -) -> EnvResult<>::PrefixIter> -where - DB: storage::DB + for<'iter> storage::DBIter<'iter>, - H: StorageHasher, -{ - let (iter, gas) = storage.rev_iter_prefix(prefix); - add_gas(gas_meter, gas)?; - Ok(iter) -} - /// Storage prefix iterator for prior state (before tx execution). It will try /// to read from the storage. pub fn iter_pre_next( diff --git a/shared/src/vm/host_env.rs b/shared/src/vm/host_env.rs index 90e6e4405f..9e61651b5e 100644 --- a/shared/src/vm/host_env.rs +++ b/shared/src/vm/host_env.rs @@ -706,38 +706,6 @@ where Ok(iterators.insert(iter).id()) } -/// Storage prefix iterator function exposed to the wasm VM Tx environment. -/// It will try to get an iterator from the storage and return the corresponding -/// ID of the iterator, reverse ordered by storage keys. -pub fn tx_rev_iter_prefix( - env: &TxVmEnv, - prefix_ptr: u64, - prefix_len: u64, -) -> TxResult -where - MEM: VmMemory, - DB: storage::DB + for<'iter> storage::DBIter<'iter>, - H: StorageHasher, - CA: WasmCacheAccess, -{ - let (prefix, gas) = env - .memory - .read_string(prefix_ptr, prefix_len as _) - .map_err(|e| TxRuntimeError::MemoryError(Box::new(e)))?; - tx_add_gas(env, gas)?; - - tracing::debug!("tx_rev_iter_prefix {}, prefix {}", prefix, prefix_ptr); - - let prefix = - Key::parse(prefix).map_err(TxRuntimeError::StorageDataError)?; - - let storage = unsafe { env.ctx.storage.get() }; - let iterators = unsafe { env.ctx.iterators.get() }; - let (iter, gas) = storage.rev_iter_prefix(&prefix); - tx_add_gas(env, gas)?; - Ok(iterators.insert(iter).id()) -} - /// Storage prefix iterator next function exposed to the wasm VM Tx environment. /// It will try to read from the write log first and if no entry found then from /// the storage. @@ -1272,38 +1240,6 @@ where Ok(iterators.insert(iter).id()) } -/// Storage prefix iterator function exposed to the wasm VM VP environment. -/// It will try to get an iterator from the storage and return the corresponding -/// ID of the iterator, reverse ordered by storage keys. -pub fn vp_rev_iter_prefix( - env: &VpVmEnv, - prefix_ptr: u64, - prefix_len: u64, -) -> vp_host_fns::EnvResult -where - MEM: VmMemory, - DB: storage::DB + for<'iter> storage::DBIter<'iter>, - H: StorageHasher, - EVAL: VpEvaluator, - CA: WasmCacheAccess, -{ - let (prefix, gas) = env - .memory - .read_string(prefix_ptr, prefix_len as _) - .map_err(|e| vp_host_fns::RuntimeError::MemoryError(Box::new(e)))?; - let gas_meter = unsafe { env.ctx.gas_meter.get() }; - vp_host_fns::add_gas(gas_meter, gas)?; - - let prefix = Key::parse(prefix) - .map_err(vp_host_fns::RuntimeError::StorageDataError)?; - tracing::debug!("vp_rev_iter_prefix {}", prefix); - - let storage = unsafe { env.ctx.storage.get() }; - let iter = vp_host_fns::rev_iter_prefix(gas_meter, storage, &prefix)?; - let iterators = unsafe { env.ctx.iterators.get() }; - Ok(iterators.insert(iter).id()) -} - /// Storage prefix iterator for prior state (before tx execution) function /// exposed to the wasm VM VP environment. It will try to read from the storage. /// diff --git a/shared/src/vm/wasm/host_env.rs b/shared/src/vm/wasm/host_env.rs index e4e173f47c..b9eeffecfc 100644 --- a/shared/src/vm/wasm/host_env.rs +++ b/shared/src/vm/wasm/host_env.rs @@ -67,7 +67,6 @@ where "namada_tx_write_temp" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_write_temp), "namada_tx_delete" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_delete), "namada_tx_iter_prefix" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_iter_prefix), - "namada_tx_rev_iter_prefix" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_rev_iter_prefix), "namada_tx_iter_next" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_iter_next), "namada_tx_insert_verifier" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_insert_verifier), "namada_tx_update_validity_predicate" => Function::new_native_with_env(wasm_store, env.clone(), host_env::tx_update_validity_predicate), @@ -110,7 +109,6 @@ where "namada_vp_has_key_pre" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_has_key_pre), "namada_vp_has_key_post" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_has_key_post), "namada_vp_iter_prefix" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_prefix), - "namada_vp_rev_iter_prefix" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_rev_iter_prefix), "namada_vp_iter_pre_next" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_pre_next), "namada_vp_iter_post_next" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_iter_post_next), "namada_vp_get_chain_id" => Function::new_native_with_env(wasm_store, env.clone(), host_env::vp_get_chain_id), diff --git a/tests/src/vm_host_env/mod.rs b/tests/src/vm_host_env/mod.rs index aa8c160339..4ab7b6eca7 100644 --- a/tests/src/vm_host_env/mod.rs +++ b/tests/src/vm_host_env/mod.rs @@ -183,19 +183,6 @@ mod tests { .sorted() .map(|i| (prefix.push(i).unwrap(), *i)); itertools::assert_equal(iter, expected); - - // Try to iterate over their prefix in reverse - let iter = namada_tx_prelude::rev_iter_prefix(tx::ctx(), &prefix) - .unwrap() - .map(Result::unwrap); - - // The order has to be reverse sorted by sub-key value - let expected = sub_keys - .iter() - .sorted() - .rev() - .map(|i| (prefix.push(i).unwrap(), *i)); - itertools::assert_equal(iter, expected); } #[test] @@ -429,19 +416,6 @@ mod tests { (prefix.push(i).unwrap(), val) }); itertools::assert_equal(iter_post, expected_post); - - // Try to iterate over their prefix in reverse - let iter_pre = namada_vp_prelude::rev_iter_prefix(&ctx_pre, &prefix) - .unwrap() - .map(|item| item.unwrap()); - - // The order in has to be reverse sorted by sub-key value - let expected_pre = sub_keys - .iter() - .sorted() - .rev() - .map(|i| (prefix.push(i).unwrap(), *i)); - itertools::assert_equal(iter_pre, expected_pre); } #[test] diff --git a/tests/src/vm_host_env/tx.rs b/tests/src/vm_host_env/tx.rs index 05542438d6..0f7040941d 100644 --- a/tests/src/vm_host_env/tx.rs +++ b/tests/src/vm_host_env/tx.rs @@ -400,7 +400,6 @@ mod native_tx_host_env { )); native_host_fn!(tx_delete(key_ptr: u64, key_len: u64)); native_host_fn!(tx_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64); - native_host_fn!(tx_rev_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64); native_host_fn!(tx_iter_next(iter_id: u64) -> i64); native_host_fn!(tx_insert_verifier(addr_ptr: u64, addr_len: u64)); native_host_fn!(tx_update_validity_predicate( diff --git a/tests/src/vm_host_env/vp.rs b/tests/src/vm_host_env/vp.rs index 50cbc7b6ef..a88176d182 100644 --- a/tests/src/vm_host_env/vp.rs +++ b/tests/src/vm_host_env/vp.rs @@ -332,7 +332,6 @@ mod native_vp_host_env { native_host_fn!(vp_has_key_pre(key_ptr: u64, key_len: u64) -> i64); native_host_fn!(vp_has_key_post(key_ptr: u64, key_len: u64) -> i64); native_host_fn!(vp_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64); - native_host_fn!(vp_rev_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64); native_host_fn!(vp_iter_pre_next(iter_id: u64) -> i64); native_host_fn!(vp_iter_post_next(iter_id: u64) -> i64); native_host_fn!(vp_get_chain_id(result_ptr: u64)); diff --git a/tx_prelude/src/lib.rs b/tx_prelude/src/lib.rs index d0d4511577..9d66dcb73e 100644 --- a/tx_prelude/src/lib.rs +++ b/tx_prelude/src/lib.rs @@ -21,9 +21,8 @@ pub use namada_core::ledger::parameters::storage as parameters_storage; pub use namada_core::ledger::slash_fund::storage as slash_fund_storage; pub use namada_core::ledger::storage::types::encode; pub use namada_core::ledger::storage_api::{ - self, iter_prefix, iter_prefix_bytes, rev_iter_prefix, - rev_iter_prefix_bytes, Error, OptionExt, ResultExt, StorageRead, - StorageWrite, + self, iter_prefix, iter_prefix_bytes, Error, OptionExt, ResultExt, + StorageRead, StorageWrite, }; pub use namada_core::ledger::tx_env::TxEnv; pub use namada_core::proto::{Signed, SignedTxData}; @@ -112,8 +111,8 @@ pub type TxResult = EnvResult<()>; #[derive(Debug)] pub struct KeyValIterator(pub u64, pub PhantomData); -impl StorageRead<'_> for Ctx { - type PrefixIter = KeyValIterator<(String, Vec)>; +impl StorageRead for Ctx { + type PrefixIter<'iter> = KeyValIterator<(String, Vec)>; fn read_bytes(&self, key: &storage::Key) -> Result>, Error> { let key = key.to_string(); @@ -179,10 +178,10 @@ impl StorageRead<'_> for Ctx { Ok(Address::decode(address_str).expect("Cannot decode native address")) } - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &storage::Key, - ) -> Result { + ) -> Result, Error> { let prefix = prefix.to_string(); let iter_id = unsafe { namada_tx_iter_prefix(prefix.as_ptr() as _, prefix.len() as _) @@ -190,20 +189,9 @@ impl StorageRead<'_> for Ctx { Ok(KeyValIterator(iter_id, PhantomData)) } - fn rev_iter_prefix( - &self, - prefix: &storage::Key, - ) -> Result { - let prefix = prefix.to_string(); - let iter_id = unsafe { - namada_tx_rev_iter_prefix(prefix.as_ptr() as _, prefix.len() as _) - }; - Ok(KeyValIterator(iter_id, PhantomData)) - } - - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>, Error> { let read_result = unsafe { namada_tx_iter_next(iter.0) }; Ok(read_key_val_bytes_from_buffer( @@ -243,7 +231,7 @@ impl StorageWrite for Ctx { } } -impl TxEnv<'_> for Ctx { +impl TxEnv for Ctx { fn get_block_time(&self) -> Result { let read_result = unsafe { namada_tx_get_block_time() }; let time_value = read_from_buffer(read_result, namada_tx_result_buffer) diff --git a/vm_env/src/lib.rs b/vm_env/src/lib.rs index 795ae912dc..e328a8748c 100644 --- a/vm_env/src/lib.rs +++ b/vm_env/src/lib.rs @@ -51,13 +51,6 @@ pub mod tx { // keys. pub fn namada_tx_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64; - // Get an ID of a data iterator with key prefix, reverse ordered by - // storage keys. - pub fn namada_tx_rev_iter_prefix( - prefix_ptr: u64, - prefix_len: u64, - ) -> u64; - // Returns the size of the value (can be 0), or -1 if there's no next // value. If a value is found, it will be placed in the read // cache, because we cannot allocate a buffer for it before we know @@ -150,13 +143,6 @@ pub mod vp { // keys. pub fn namada_vp_iter_prefix(prefix_ptr: u64, prefix_len: u64) -> u64; - // Get an ID of a data iterator with key prefix, reverse ordered by - // storage keys. - pub fn namada_vp_rev_iter_prefix( - prefix_ptr: u64, - prefix_len: u64, - ) -> u64; - // Read variable-length prior state when we don't know the size // up-front, returns the size of the value (can be 0), or -1 if // the key is not present. If a value is found, it will be placed in the diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs index 6ff90f56df..58ee37e756 100644 --- a/vp_prelude/src/lib.rs +++ b/vp_prelude/src/lib.rs @@ -20,8 +20,8 @@ pub use borsh::{BorshDeserialize, BorshSerialize}; pub use namada_core::ledger::governance::storage as gov_storage; pub use namada_core::ledger::parameters; pub use namada_core::ledger::storage_api::{ - self, iter_prefix, iter_prefix_bytes, rev_iter_prefix, - rev_iter_prefix_bytes, Error, OptionExt, ResultExt, StorageRead, + self, iter_prefix, iter_prefix_bytes, Error, OptionExt, ResultExt, + StorageRead, }; pub use namada_core::ledger::vp_env::VpEnv; pub use namada_core::proto::{Signed, SignedTxData}; @@ -190,7 +190,7 @@ pub struct KeyValIterator(pub u64, pub PhantomData); impl<'view> VpEnv<'view> for Ctx { type Post = CtxPostStorageRead<'view>; type Pre = CtxPreStorageRead<'view>; - type PrefixIter = KeyValIterator<(String, Vec)>; + type PrefixIter<'iter> = KeyValIterator<(String, Vec)>; fn pre(&'view self) -> Self::Pre { CtxPreStorageRead { _ctx: self } @@ -221,51 +221,43 @@ impl<'view> VpEnv<'view> for Ctx { Ok(read_from_buffer(read_result, namada_vp_result_buffer)) } - fn get_chain_id(&'view self) -> Result { + fn get_chain_id(&self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl get_chain_id() } - fn get_block_height(&'view self) -> Result { + fn get_block_height(&self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl get_block_height() } - fn get_block_hash(&'view self) -> Result { + fn get_block_hash(&self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl get_block_hash() } - fn get_block_epoch(&'view self) -> Result { + fn get_block_epoch(&self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl get_block_epoch() } - fn get_tx_index(&'view self) -> Result { + fn get_tx_index(&self) -> Result { get_tx_index() } - fn get_native_token(&'view self) -> Result { + fn get_native_token(&self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl get_native_token() } - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &storage::Key, - ) -> Result { + ) -> Result, Error> { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl iter_prefix_impl(prefix) } - fn rev_iter_prefix( - &self, - prefix: &storage::Key, - ) -> Result { - // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl - rev_iter_prefix_impl(prefix) - } - fn eval( &self, vp_code: Vec, @@ -317,8 +309,8 @@ impl<'view> VpEnv<'view> for Ctx { } } -impl StorageRead<'_> for CtxPreStorageRead<'_> { - type PrefixIter = KeyValIterator<(String, Vec)>; +impl StorageRead for CtxPreStorageRead<'_> { + type PrefixIter<'iter> = KeyValIterator<(String, Vec)> where Self: 'iter; fn read_bytes(&self, key: &storage::Key) -> Result>, Error> { let key = key.to_string(); @@ -334,9 +326,9 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { Ok(HostEnvResult::is_success(found)) } - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>, Error> { let read_result = unsafe { namada_vp_iter_pre_next(iter.0) }; Ok(read_key_val_bytes_from_buffer( @@ -347,20 +339,13 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { // ---- Methods below share the same implementation in `pre/post` ---- - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &storage::Key, - ) -> Result { + ) -> Result, Error> { iter_prefix_impl(prefix) } - fn rev_iter_prefix( - &self, - prefix: &storage::Key, - ) -> Result { - rev_iter_prefix_impl(prefix) - } - fn get_chain_id(&self) -> Result { get_chain_id() } @@ -386,8 +371,8 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { } } -impl StorageRead<'_> for CtxPostStorageRead<'_> { - type PrefixIter = KeyValIterator<(String, Vec)>; +impl StorageRead for CtxPostStorageRead<'_> { + type PrefixIter<'iter> = KeyValIterator<(String, Vec)> where Self:'iter; fn read_bytes(&self, key: &storage::Key) -> Result>, Error> { let key = key.to_string(); @@ -404,9 +389,9 @@ impl StorageRead<'_> for CtxPostStorageRead<'_> { Ok(HostEnvResult::is_success(found)) } - fn iter_next( - &self, - iter: &mut Self::PrefixIter, + fn iter_next<'iter>( + &'iter self, + iter: &mut Self::PrefixIter<'iter>, ) -> Result)>, Error> { let read_result = unsafe { namada_vp_iter_post_next(iter.0) }; Ok(read_key_val_bytes_from_buffer( @@ -417,20 +402,13 @@ impl StorageRead<'_> for CtxPostStorageRead<'_> { // ---- Methods below share the same implementation in `pre/post` ---- - fn iter_prefix( - &self, + fn iter_prefix<'iter>( + &'iter self, prefix: &storage::Key, - ) -> Result { + ) -> Result, Error> { iter_prefix_impl(prefix) } - fn rev_iter_prefix( - &self, - prefix: &storage::Key, - ) -> storage_api::Result { - rev_iter_prefix_impl(prefix) - } - fn get_chain_id(&self) -> Result { get_chain_id() } @@ -466,16 +444,6 @@ fn iter_prefix_impl( Ok(KeyValIterator(iter_id, PhantomData)) } -fn rev_iter_prefix_impl( - prefix: &storage::Key, -) -> Result)>, Error> { - let prefix = prefix.to_string(); - let iter_id = unsafe { - namada_vp_rev_iter_prefix(prefix.as_ptr() as _, prefix.len() as _) - }; - Ok(KeyValIterator(iter_id, PhantomData)) -} - fn get_chain_id() -> Result { let result = Vec::with_capacity(CHAIN_ID_LENGTH); unsafe { diff --git a/wasm/checksums.json b/wasm/checksums.json index 1d0b3d93c7..eb4686a990 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,20 +1,20 @@ { - "tx_bond.wasm": "tx_bond.59f751c77d75d96679ec6df7376d896e3cbf9598846ea09e2caef8114de97932.wasm", + "tx_bond.wasm": "tx_bond.14ebbb45aad0e1301df40a5c412679c05078903794b6caaa2b52e24d9bbb7594.wasm", "tx_change_validator_commission.wasm": "tx_change_validator_commission.cd861e0e82f4934be6d8382d6fff98286b4fadbc20ab826b9e817f6666021273.wasm", - "tx_ibc.wasm": "tx_ibc.f261d127df2cb05489ad2655fcc6d0d8e7378789226ee27f0251ae90adfc1b0a.wasm", - "tx_init_account.wasm": "tx_init_account.e21cfd7e96802f8e841613fb89f1571451401d002a159c5e9586855ac1374df5.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.211265350906ad7aef3aca30d6ef463d065b738707accd0acaa19992977bfabe.wasm", - "tx_init_validator.wasm": "tx_init_validator.eac9858c4f96bbefd120e3ebe0489e1700a83e8a22d778d5aa2b14ab0627f172.wasm", + "tx_ibc.wasm": "tx_ibc.dc7969c3f1a0f1bfb8e1c942e09f9c2678c2217846e607ee39ea0a7022258bdd.wasm", + "tx_init_account.wasm": "tx_init_account.87ece7f13b327f7d15c5b6e7083b510debb1c3205bafe9e36457c8585beeb49c.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.c39152be5435cf3f7588ddcde82b801e98902079a152ae3df30bac69833e3ebb.wasm", + "tx_init_validator.wasm": "tx_init_validator.56d563e4b9001790d9089ff91c6c98cde95032fb57d97122e58e8b5e363fc13f.wasm", "tx_reveal_pk.wasm": "tx_reveal_pk.47bc922a8be5571620a647ae442a1af7d03d05d29bef95f0b32cdfe00b11fee9.wasm", - "tx_transfer.wasm": "tx_transfer.5b95e6f1f6b2d4b0ec6f07ac1ec66089374ece2e4a6c5bdb32297985670a2ab0.wasm", - "tx_unbond.wasm": "tx_unbond.a33d113d04786c6638f5181b1bd65413b6b199e0c37985f444bea56430fc3f4c.wasm", + "tx_transfer.wasm": "tx_transfer.c75399e44b86e22084937b69b2f6c9b9ae112706ac9f8c472d3646fc36cfaa06.wasm", + "tx_unbond.wasm": "tx_unbond.c0a690d0ad43a94294a6405bae3327f638a657446c74dc61dbb3a4d2ce488b5e.wasm", "tx_update_vp.wasm": "tx_update_vp.ee2e9b882c4accadf4626e87d801c9ac8ea8c61ccea677e0532fc6c1ee7db6a2.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.263fd9f4cb40f283756f394d86bdea3417e9ecd0568d6582c07a5b6bd14287d6.wasm", - "tx_withdraw.wasm": "tx_withdraw.b9b8623217202de2cb2c3941f740f6acd8558eaa05406efc60ee471c212aa513.wasm", - "vp_implicit.wasm": "vp_implicit.6c221c5210973b8d39dae73378cb8291ffebb9fb99e790f89290a1b51eb6a690.wasm", - "vp_masp.wasm": "vp_masp.16516aeafa4c2c814cf3a4289b7f924d2551966f98b9ce136fbae361aba2a73c.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.e893d1f02ec8b3668a58ab69f9dd676ccb18d0cc96d3b5c9c789714552ea715e.wasm", - "vp_token.wasm": "vp_token.bfeddd3c5954174e95064f753cb743d84659f05910cbcb31a6d8b23769b59638.wasm", - "vp_user.wasm": "vp_user.40087a1e14bdafb4429427f47c5c7a0a247433d4f72927f2ec5906119192c900.wasm", - "vp_validator.wasm": "vp_validator.3f219ebb7f3f058f6681fe3d461d6296ab1d21d92ae1578ad421b272789f451e.wasm" + "tx_withdraw.wasm": "tx_withdraw.8f53ce136e07c4d1a09bebf2d3d0eba77828622a8c95d5bb3a14b6f934f0cf0d.wasm", + "vp_implicit.wasm": "vp_implicit.5b71d2ab5a9fe9bc21f116f978d1c6b8889ea835386605f7ccfc1204fff79867.wasm", + "vp_masp.wasm": "vp_masp.5620cb6e555161641337d308851c760fbab4f9d3693cfd378703aa55e285249d.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.55df1439dfc51ce9bbf592e9dd74036138f749be50e09fbcfb879d582b625b35.wasm", + "vp_token.wasm": "vp_token.dfde368a9e52cbda5aec60fa54d73ee0d36abac31fa3342098ebb29100a0f5b5.wasm", + "vp_user.wasm": "vp_user.33e5dd9f09f7d4ab61330a46edc72ca9063eeff224b9b751e3c1e8124282df2c.wasm", + "vp_validator.wasm": "vp_validator.f5ba5c2dfa46ce3b223df7ec2fd879e86a903ad382beda113c0f0f457a479553.wasm" } \ No newline at end of file diff --git a/wasm_for_tests/tx_memory_limit.wasm b/wasm_for_tests/tx_memory_limit.wasm index 9c4ea2abcc..09fcaea999 100755 Binary files a/wasm_for_tests/tx_memory_limit.wasm and b/wasm_for_tests/tx_memory_limit.wasm differ diff --git a/wasm_for_tests/tx_mint_tokens.wasm b/wasm_for_tests/tx_mint_tokens.wasm index 72e1e8f075..e3bd3e5724 100755 Binary files a/wasm_for_tests/tx_mint_tokens.wasm and b/wasm_for_tests/tx_mint_tokens.wasm differ diff --git a/wasm_for_tests/tx_no_op.wasm b/wasm_for_tests/tx_no_op.wasm index 105a68cd1b..3e0b1ef997 100755 Binary files a/wasm_for_tests/tx_no_op.wasm and b/wasm_for_tests/tx_no_op.wasm differ diff --git a/wasm_for_tests/tx_proposal_code.wasm b/wasm_for_tests/tx_proposal_code.wasm index 584ebfdcb1..2124f28120 100755 Binary files a/wasm_for_tests/tx_proposal_code.wasm and b/wasm_for_tests/tx_proposal_code.wasm differ diff --git a/wasm_for_tests/tx_read_storage_key.wasm b/wasm_for_tests/tx_read_storage_key.wasm index 8f62c8211e..d7f90d6987 100755 Binary files a/wasm_for_tests/tx_read_storage_key.wasm and b/wasm_for_tests/tx_read_storage_key.wasm differ diff --git a/wasm_for_tests/tx_write_storage_key.wasm b/wasm_for_tests/tx_write_storage_key.wasm index 2831315a06..684c3d378b 100755 Binary files a/wasm_for_tests/tx_write_storage_key.wasm and b/wasm_for_tests/tx_write_storage_key.wasm differ diff --git a/wasm_for_tests/vp_always_false.wasm b/wasm_for_tests/vp_always_false.wasm index db0729c87c..3ce1549f15 100755 Binary files a/wasm_for_tests/vp_always_false.wasm and b/wasm_for_tests/vp_always_false.wasm differ diff --git a/wasm_for_tests/vp_always_true.wasm b/wasm_for_tests/vp_always_true.wasm index e363102995..052a441836 100755 Binary files a/wasm_for_tests/vp_always_true.wasm and b/wasm_for_tests/vp_always_true.wasm differ diff --git a/wasm_for_tests/vp_eval.wasm b/wasm_for_tests/vp_eval.wasm index 8711cfca76..3bf4ac8028 100755 Binary files a/wasm_for_tests/vp_eval.wasm and b/wasm_for_tests/vp_eval.wasm differ diff --git a/wasm_for_tests/vp_memory_limit.wasm b/wasm_for_tests/vp_memory_limit.wasm index d7d10f8a36..a7e901a067 100755 Binary files a/wasm_for_tests/vp_memory_limit.wasm and b/wasm_for_tests/vp_memory_limit.wasm differ diff --git a/wasm_for_tests/vp_read_storage_key.wasm b/wasm_for_tests/vp_read_storage_key.wasm index 9bf70703e9..703a144bff 100755 Binary files a/wasm_for_tests/vp_read_storage_key.wasm and b/wasm_for_tests/vp_read_storage_key.wasm differ