Skip to content

Commit

Permalink
Merge remote-tracking branch 'namada/tomas/add-temp-wl-storage' (#1051)…
Browse files Browse the repository at this point in the history
… into main

evil: add some 'static lifetimes

* namada/tomas/add-temp-wl-storage:
  changelog: add #1051
  core: added `TempWlStorage` for ABCI++ prepare/process proposal
  • Loading branch information
juped committed Apr 13, 2023
2 parents 616408a + 2bb8ead commit c278068
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 30 deletions.
3 changes: 3 additions & 0 deletions .changelog/unreleased/improvements/1051-temp-wl-storage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Added a TempWlStorage for storage_api::StorageRead/Write
in ABCI++ prepare/process proposal handler.
([#1051](https://github.com/anoma/namada/pull/1051))
4 changes: 2 additions & 2 deletions apps/src/lib/node/ledger/shell/block_space_alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ pub struct BlockSpaceAllocator<State> {
impl<D, H, M> From<&WlStorage<D, H>>
for BlockSpaceAllocator<states::BuildingEncryptedTxBatch<M>>
where
D: storage::DB + for<'iter> storage::DBIter<'iter>,
H: storage::StorageHasher,
D: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + storage::StorageHasher,
{
#[inline]
fn from(storage: &WlStorage<D, H>) -> Self {
Expand Down
4 changes: 2 additions & 2 deletions apps/src/lib/node/ledger/shell/process_proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ pub struct ValidationMeta {

impl<D, H> From<&WlStorage<D, H>> for ValidationMeta
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
D: 'static + DB + for<'iter> DBIter<'iter>,
H: 'static + StorageHasher,
{
fn from(storage: &WlStorage<D, H>) -> Self {
let max_proposal_bytes =
Expand Down
4 changes: 2 additions & 2 deletions core/src/ledger/storage/masp_conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ pub fn update_allowed_conversions<D, H>(
wl_storage: &mut super::WlStorage<D, H>,
) -> crate::ledger::storage_api::Result<()>
where
D: super::DB + for<'iter> super::DBIter<'iter>,
H: super::StorageHasher,
D: 'static + super::DB + for<'iter> super::DBIter<'iter>,
H: 'static + super::StorageHasher,
{
use masp_primitives::ff::PrimeField;
use masp_primitives::transaction::components::Amount as MaspAmount;
Expand Down
2 changes: 1 addition & 1 deletion core/src/ledger/storage/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use merkle_tree::{
use thiserror::Error;
pub use traits::{Sha256Hasher, StorageHasher};
pub use wl_storage::{
iter_prefix_post, iter_prefix_pre, PrefixIter, WlStorage,
iter_prefix_post, iter_prefix_pre, PrefixIter, TempWlStorage, WlStorage,
};

#[cfg(feature = "wasm-runtime")]
Expand Down
140 changes: 121 additions & 19 deletions core/src/ledger/storage/wl_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,101 @@ where
pub storage: Storage<D, H>,
}

/// Temporary storage that can be used for changes that will never be committed
/// to the DB. This is useful for the shell `PrepareProposal` and
/// `ProcessProposal` handlers that should not change state, but need to apply
/// storage changes for replay protection to validate the proposal.
#[derive(Debug)]
pub struct TempWlStorage<'a, D, H>
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
{
/// Write log
pub write_log: WriteLog,
/// Storage provides access to DB
pub storage: &'a Storage<D, H>,
}

impl<'a, D, H> TempWlStorage<'a, D, H>
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
{
/// Create a temp storage that can mutated in memory, but never committed to
/// DB.
pub fn new(storage: &'a Storage<D, H>) -> Self {
Self {
write_log: WriteLog::default(),
storage,
}
}
}

/// Common trait for [`WlStorage`] and [`TempWlStorage`], used to implement
/// storage_api traits.
trait WriteLogAndStorage {
// DB type
type D: DB + for<'iter> DBIter<'iter>;
// DB hasher type
type H: StorageHasher;

/// Borrow `WriteLog`
fn write_log(&self) -> &WriteLog;

/// Borrow mutable `WriteLog`
fn write_log_mut(&mut self) -> &mut WriteLog;

/// Borrow `Storage`
fn storage(&self) -> &Storage<Self::D, Self::H>;
}

impl<D, H> WriteLogAndStorage for WlStorage<D, H>
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
{
type D = D;
type H = H;

fn write_log(&self) -> &WriteLog {
&self.write_log
}

fn write_log_mut(&mut self) -> &mut WriteLog {
&mut self.write_log
}

fn storage(&self) -> &Storage<D, H> {
&self.storage
}
}

impl<D, H> WriteLogAndStorage for TempWlStorage<'_, D, H>
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
{
type D = D;
type H = H;

fn write_log(&self) -> &WriteLog {
&self.write_log
}

fn write_log_mut(&mut self) -> &mut WriteLog {
&mut self.write_log
}

fn storage(&self) -> &Storage<D, H> {
self.storage
}
}

impl<D, H> WlStorage<D, H>
where
D: 'static + DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
H: 'static + StorageHasher,
{
/// Combine storage with write-log
pub fn new(write_log: WriteLog, storage: Storage<D, H>) -> Self {
Expand Down Expand Up @@ -255,10 +346,11 @@ where
}
}

impl<D, H> StorageRead for WlStorage<D, H>
impl<T, D, H> StorageRead for T
where
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
T: WriteLogAndStorage<D = D, H = H>,
D: 'static + DB + for<'iter> DBIter<'iter>,
H: 'static + StorageHasher,
{
type PrefixIter<'iter> = PrefixIter<'iter, D> where Self: 'iter;

Expand All @@ -267,7 +359,7 @@ where
key: &storage::Key,
) -> storage_api::Result<Option<Vec<u8>>> {
// try to read from the write log first
let (log_val, _gas) = self.write_log.read(key);
let (log_val, _gas) = self.write_log().read(key);
match log_val {
Some(&write_log::StorageModification::Write { ref value }) => {
Ok(Some(value.clone()))
Expand All @@ -282,14 +374,17 @@ where
}
None => {
// when not found in write log, try to read from the storage
self.storage.db.read_subspace_val(key).into_storage_result()
self.storage()
.db
.read_subspace_val(key)
.into_storage_result()
}
}
}

fn has_key(&self, key: &storage::Key) -> storage_api::Result<bool> {
// try to read from the write log first
let (log_val, _gas) = self.write_log.read(key);
let (log_val, _gas) = self.write_log().read(key);
match log_val {
Some(&write_log::StorageModification::Write { .. })
| Some(&write_log::StorageModification::InitAccount { .. })
Expand All @@ -300,7 +395,7 @@ where
}
None => {
// when not found in write log, try to check the storage
self.storage.block.tree.has_key(key).into_storage_result()
self.storage().block.tree.has_key(key).into_storage_result()
}
}
}
Expand All @@ -310,7 +405,7 @@ where
prefix: &storage::Key,
) -> storage_api::Result<Self::PrefixIter<'iter>> {
let (iter, _gas) =
iter_prefix_post(&self.write_log, &self.storage, prefix);
iter_prefix_post(self.write_log(), self.storage(), prefix);
Ok(iter)
}

Expand All @@ -322,40 +417,41 @@ where
}

fn get_chain_id(&self) -> std::result::Result<String, storage_api::Error> {
Ok(self.storage.chain_id.to_string())
Ok(self.storage().chain_id.to_string())
}

fn get_block_height(
&self,
) -> std::result::Result<storage::BlockHeight, storage_api::Error> {
Ok(self.storage.block.height)
Ok(self.storage().block.height)
}

fn get_block_hash(
&self,
) -> std::result::Result<storage::BlockHash, storage_api::Error> {
Ok(self.storage.block.hash.clone())
Ok(self.storage().block.hash.clone())
}

fn get_block_epoch(
&self,
) -> std::result::Result<storage::Epoch, storage_api::Error> {
Ok(self.storage.block.epoch)
Ok(self.storage().block.epoch)
}

fn get_tx_index(
&self,
) -> std::result::Result<storage::TxIndex, storage_api::Error> {
Ok(self.storage.tx_index)
Ok(self.storage().tx_index)
}

fn get_native_token(&self) -> storage_api::Result<Address> {
Ok(self.storage.native_token.clone())
Ok(self.storage().native_token.clone())
}
}

impl<D, H> StorageWrite for WlStorage<D, H>
impl<T, D, H> StorageWrite for T
where
T: WriteLogAndStorage<D = D, H = H>,
D: DB + for<'iter> DBIter<'iter>,
H: StorageHasher,
{
Expand All @@ -364,13 +460,19 @@ where
key: &storage::Key,
val: impl AsRef<[u8]>,
) -> storage_api::Result<()> {
self.write_log
let _ = self
.write_log_mut()
.protocol_write(key, val.as_ref().to_vec())
.into_storage_result()
.into_storage_result();
Ok(())
}

fn delete(&mut self, key: &storage::Key) -> storage_api::Result<()> {
self.write_log.protocol_delete(key).into_storage_result()
let _ = self
.write_log_mut()
.protocol_delete(key)
.into_storage_result();
Ok(())
}
}

Expand Down
8 changes: 4 additions & 4 deletions proof_of_stake/src/pos_queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ impl<'db, DB> Copy for PosQueriesHook<'db, DB> {}

impl<'db, D, H> PosQueriesHook<'db, WlStorage<D, H>>
where
D: storage::DB + for<'iter> storage::DBIter<'iter>,
H: storage::StorageHasher,
D: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + storage::StorageHasher,
{
/// Return a handle to the inner [`WlStorage`].
#[inline]
Expand Down Expand Up @@ -285,8 +285,8 @@ where

impl<'db, D, H> ConsensusValidators<'db, D, H>
where
D: storage::DB + for<'iter> storage::DBIter<'iter>,
H: storage::StorageHasher,
D: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + storage::StorageHasher,
{
/// Iterate over the set of consensus validators in Namada, at some given
/// epoch.
Expand Down

0 comments on commit c278068

Please sign in to comment.