Skip to content

Commit

Permalink
Merge branch 'tomas/vp-env-pre-post-via-storage-api' (#380)
Browse files Browse the repository at this point in the history
* tomas/vp-env-pre-post-via-storage-api:
  update wasm checksums
  changelog: add #380
  shared: Add pre/post to VpEnv and use them to provide default impls
  • Loading branch information
tzemanovic committed Sep 23, 2022
2 parents 1a054a9 + b811466 commit 5325a5f
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 261 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Added `pre/post` methods into `trait VpEnv` that return objects implementing
`trait StorageRead` for re-use of library code written on top of `StorageRead`
inside validity predicates. ([#380](https://github.com/anoma/namada/pull/380))
191 changes: 77 additions & 114 deletions shared/src/ledger/native_vp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,25 @@ where
/// Read access to the prior storage (state before tx execution) via
/// [`trait@StorageRead`].
#[derive(Debug)]
pub struct CtxPreStorageRead<'b, 'a: 'b, DB, H, CA>
pub struct CtxPreStorageRead<'view, 'a: 'view, DB, H, CA>
where
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
ctx: &'b Ctx<'a, DB, H, CA>,
ctx: &'view Ctx<'a, DB, H, CA>,
}

/// Read access to the posterior storage (state after tx execution) via
/// [`trait@StorageRead`].
#[derive(Debug)]
pub struct CtxPostStorageRead<'f, 'a: 'f, DB, H, CA>
pub struct CtxPostStorageRead<'view, 'a: 'view, DB, H, CA>
where
DB: storage::DB + for<'iter> storage::DBIter<'iter>,
H: StorageHasher,
CA: WasmCacheAccess,
{
ctx: &'f Ctx<'a, DB, H, CA>,
ctx: &'view Ctx<'a, DB, H, CA>,
}

impl<'a, DB, H, CA> Ctx<'a, DB, H, CA>
Expand Down Expand Up @@ -139,18 +139,21 @@ where

/// Read access to the prior storage (state before tx execution)
/// via [`trait@StorageRead`].
pub fn pre<'b>(&'b self) -> CtxPreStorageRead<'b, 'a, DB, H, CA> {
pub fn pre<'view>(&'view self) -> CtxPreStorageRead<'view, 'a, DB, H, CA> {
CtxPreStorageRead { ctx: self }
}

/// Read access to the posterior storage (state after tx execution)
/// via [`trait@StorageRead`].
pub fn post<'b>(&'b self) -> CtxPostStorageRead<'b, 'a, DB, H, CA> {
pub fn post<'view>(
&'view self,
) -> CtxPostStorageRead<'view, 'a, DB, H, CA> {
CtxPostStorageRead { ctx: self }
}
}

impl<'f, 'a, DB, H, CA> StorageRead<'f> for CtxPreStorageRead<'f, 'a, DB, H, CA>
impl<'view, 'a, DB, H, CA> StorageRead<'view>
for CtxPreStorageRead<'view, 'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + StorageHasher,
Expand All @@ -162,30 +165,45 @@ where
&self,
key: &crate::types::storage::Key,
) -> Result<Option<Vec<u8>>, storage_api::Error> {
self.ctx.read_bytes_pre(key).into_storage_result()
vp_env::read_pre(
&mut *self.ctx.gas_meter.borrow_mut(),
self.ctx.storage,
self.ctx.write_log,
key,
)
.into_storage_result()
}

fn has_key(
&self,
key: &crate::types::storage::Key,
) -> Result<bool, storage_api::Error> {
self.ctx.has_key_pre(key).into_storage_result()
vp_env::has_key_pre(
&mut *self.ctx.gas_meter.borrow_mut(),
self.ctx.storage,
key,
)
.into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
vp_env::iter_pre_next::<DB>(&mut *self.ctx.gas_meter.borrow_mut(), iter)
.into_storage_result()
}

// ---- Methods below are implemented in `self.ctx`, because they are
// the same in `pre/post` ----

fn iter_prefix(
&self,
prefix: &crate::types::storage::Key,
) -> Result<Self::PrefixIter, storage_api::Error> {
self.ctx.iter_prefix(prefix).into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
self.ctx.iter_pre_next(iter).into_storage_result()
}

fn get_chain_id(&self) -> Result<String, storage_api::Error> {
self.ctx.get_chain_id().into_storage_result()
}
Expand All @@ -203,8 +221,8 @@ where
}
}

impl<'f, 'a, DB, H, CA> StorageRead<'f>
for CtxPostStorageRead<'f, 'a, DB, H, CA>
impl<'view, 'a, DB, H, CA> StorageRead<'view>
for CtxPostStorageRead<'view, 'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + StorageHasher,
Expand All @@ -216,30 +234,50 @@ where
&self,
key: &crate::types::storage::Key,
) -> Result<Option<Vec<u8>>, storage_api::Error> {
self.ctx.read_bytes_post(key).into_storage_result()
vp_env::read_post(
&mut *self.ctx.gas_meter.borrow_mut(),
self.ctx.storage,
self.ctx.write_log,
key,
)
.into_storage_result()
}

fn has_key(
&self,
key: &crate::types::storage::Key,
) -> Result<bool, storage_api::Error> {
self.ctx.has_key_post(key).into_storage_result()
vp_env::has_key_post(
&mut *self.ctx.gas_meter.borrow_mut(),
self.ctx.storage,
self.ctx.write_log,
key,
)
.into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
vp_env::iter_post_next::<DB>(
&mut *self.ctx.gas_meter.borrow_mut(),
self.ctx.write_log,
iter,
)
.into_storage_result()
}

// ---- Methods below are implemented in `self.ctx`, because they are
// the same in `pre/post` ----

fn iter_prefix(
&self,
prefix: &crate::types::storage::Key,
) -> Result<Self::PrefixIter, storage_api::Error> {
self.ctx.iter_prefix(prefix).into_storage_result()
}

fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, storage_api::Error> {
self.ctx.iter_post_next(iter).into_storage_result()
}

fn get_chain_id(&self) -> Result<String, storage_api::Error> {
self.ctx.get_chain_id().into_storage_result()
}
Expand All @@ -257,63 +295,23 @@ where
}
}

impl<'a, DB, H, CA> VpEnv for Ctx<'a, DB, H, CA>
impl<'view, 'a: 'view, DB, H, CA> VpEnv<'view> for Ctx<'a, DB, H, CA>
where
DB: 'static + storage::DB + for<'iter> storage::DBIter<'iter>,
H: 'static + StorageHasher,
CA: 'static + WasmCacheAccess,
{
type Error = Error;
type Post = CtxPostStorageRead<'view, 'a, DB, H, CA>;
type Pre = CtxPreStorageRead<'view, 'a, DB, H, CA>;
type PrefixIter = <DB as storage::DBIter<'a>>::PrefixIter;

fn read_pre<T: borsh::BorshDeserialize>(
&self,
key: &Key,
) -> Result<Option<T>, Self::Error> {
vp_env::read_pre(
&mut *self.gas_meter.borrow_mut(),
self.storage,
self.write_log,
key,
)
.map(|data| data.and_then(|t| T::try_from_slice(&t[..]).ok()))
}

fn read_bytes_pre(
&self,
key: &Key,
) -> Result<Option<Vec<u8>>, Self::Error> {
vp_env::read_pre(
&mut *self.gas_meter.borrow_mut(),
self.storage,
self.write_log,
key,
)
}

fn read_post<T: borsh::BorshDeserialize>(
&self,
key: &Key,
) -> Result<Option<T>, Self::Error> {
vp_env::read_post(
&mut *self.gas_meter.borrow_mut(),
self.storage,
self.write_log,
key,
)
.map(|data| data.and_then(|t| T::try_from_slice(&t[..]).ok()))
fn pre(&'view self) -> Self::Pre {
CtxPreStorageRead { ctx: self }
}

fn read_bytes_post(
&self,
key: &Key,
) -> Result<Option<Vec<u8>>, Self::Error> {
vp_env::read_post(
&mut *self.gas_meter.borrow_mut(),
self.storage,
self.write_log,
key,
)
fn post(&'view self) -> Self::Post {
CtxPostStorageRead { ctx: self }
}

fn read_temp<T: borsh::BorshDeserialize>(
Expand All @@ -339,44 +337,27 @@ where
)
}

fn has_key_pre(&self, key: &Key) -> Result<bool, Self::Error> {
vp_env::has_key_pre(
&mut *self.gas_meter.borrow_mut(),
self.storage,
key,
)
}

fn has_key_post(&self, key: &Key) -> Result<bool, Self::Error> {
vp_env::has_key_post(
&mut *self.gas_meter.borrow_mut(),
self.storage,
self.write_log,
key,
)
}

fn get_chain_id(&self) -> Result<String, Self::Error> {
fn get_chain_id(&'view self) -> Result<String, Self::Error> {
vp_env::get_chain_id(&mut *self.gas_meter.borrow_mut(), self.storage)
}

fn get_block_height(&self) -> Result<BlockHeight, Self::Error> {
fn get_block_height(&'view self) -> Result<BlockHeight, Self::Error> {
vp_env::get_block_height(
&mut *self.gas_meter.borrow_mut(),
self.storage,
)
}

fn get_block_hash(&self) -> Result<BlockHash, Self::Error> {
fn get_block_hash(&'view self) -> Result<BlockHash, Self::Error> {
vp_env::get_block_hash(&mut *self.gas_meter.borrow_mut(), self.storage)
}

fn get_block_epoch(&self) -> Result<Epoch, Self::Error> {
fn get_block_epoch(&'view self) -> Result<Epoch, Self::Error> {
vp_env::get_block_epoch(&mut *self.gas_meter.borrow_mut(), self.storage)
}

fn iter_prefix(
&self,
&'view self,
prefix: &Key,
) -> Result<Self::PrefixIter, Self::Error> {
vp_env::iter_prefix(
Expand All @@ -386,24 +367,6 @@ where
)
}

fn iter_pre_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, Self::Error> {
vp_env::iter_pre_next::<DB>(&mut *self.gas_meter.borrow_mut(), iter)
}

fn iter_post_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>, Self::Error> {
vp_env::iter_post_next::<DB>(
&mut *self.gas_meter.borrow_mut(),
self.write_log,
iter,
)
}

fn eval(
&self,
vp_code: Vec<u8>,
Expand Down
12 changes: 6 additions & 6 deletions shared/src/ledger/storage_api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ pub trait StorageRead<'iter> {
/// Storage `has_key` in. It will try to read from the storage.
fn has_key(&self, key: &storage::Key) -> Result<bool>;

/// Storage prefix iterator for. It will try to read from the storage.
fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>>;

/// Storage prefix iterator. It will try to get an iterator from the
/// storage.
///
Expand All @@ -64,12 +70,6 @@ pub trait StorageRead<'iter> {
prefix: &storage::Key,
) -> Result<Self::PrefixIter>;

/// Storage prefix iterator for. It will try to read from the storage.
fn iter_next(
&self,
iter: &mut Self::PrefixIter,
) -> Result<Option<(String, Vec<u8>)>>;

/// Getting the chain ID.
fn get_chain_id(&self) -> Result<String>;

Expand Down
Loading

0 comments on commit 5325a5f

Please sign in to comment.