From 2d177f8bd3548739818524255892589b9d424a17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 25 Aug 2022 10:30:32 +0200 Subject: [PATCH 1/3] shared: Add pre/post to VpEnv and use them to provide default impls --- shared/src/ledger/native_vp.rs | 191 +++++++++++---------------- shared/src/ledger/storage_api/mod.rs | 12 +- shared/src/ledger/vp_env.rs | 142 ++++++++++++-------- vp_prelude/src/lib.rs | 122 ++++++----------- 4 files changed, 210 insertions(+), 257 deletions(-) diff --git a/shared/src/ledger/native_vp.rs b/shared/src/ledger/native_vp.rs index 41fbc1cda3..f17b339086 100644 --- a/shared/src/ledger/native_vp.rs +++ b/shared/src/ledger/native_vp.rs @@ -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> @@ -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, @@ -162,16 +165,38 @@ where &self, key: &crate::types::storage::Key, ) -> Result>, 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 { - 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)>, storage_api::Error> { + vp_env::iter_pre_next::(&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, @@ -179,13 +204,6 @@ where self.ctx.iter_prefix(prefix).into_storage_result() } - fn iter_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.ctx.iter_pre_next(iter).into_storage_result() - } - fn get_chain_id(&self) -> Result { self.ctx.get_chain_id().into_storage_result() } @@ -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, @@ -216,16 +234,43 @@ where &self, key: &crate::types::storage::Key, ) -> Result>, 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 { - 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)>, storage_api::Error> { + vp_env::iter_post_next::( + &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, @@ -233,13 +278,6 @@ where self.ctx.iter_prefix(prefix).into_storage_result() } - fn iter_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, storage_api::Error> { - self.ctx.iter_post_next(iter).into_storage_result() - } - fn get_chain_id(&self) -> Result { self.ctx.get_chain_id().into_storage_result() } @@ -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 = >::PrefixIter; - fn read_pre( - &self, - key: &Key, - ) -> Result, 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>, Self::Error> { - vp_env::read_pre( - &mut *self.gas_meter.borrow_mut(), - self.storage, - self.write_log, - key, - ) - } - - fn read_post( - &self, - key: &Key, - ) -> Result, 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>, 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( @@ -339,44 +337,27 @@ where ) } - fn has_key_pre(&self, key: &Key) -> Result { - vp_env::has_key_pre( - &mut *self.gas_meter.borrow_mut(), - self.storage, - key, - ) - } - - fn has_key_post(&self, key: &Key) -> Result { - vp_env::has_key_post( - &mut *self.gas_meter.borrow_mut(), - self.storage, - self.write_log, - key, - ) - } - - fn get_chain_id(&self) -> Result { + fn get_chain_id(&'view self) -> Result { vp_env::get_chain_id(&mut *self.gas_meter.borrow_mut(), self.storage) } - fn get_block_height(&self) -> Result { + fn get_block_height(&'view self) -> Result { vp_env::get_block_height( &mut *self.gas_meter.borrow_mut(), self.storage, ) } - fn get_block_hash(&self) -> Result { + fn get_block_hash(&'view self) -> Result { vp_env::get_block_hash(&mut *self.gas_meter.borrow_mut(), self.storage) } - fn get_block_epoch(&self) -> Result { + fn get_block_epoch(&'view self) -> Result { vp_env::get_block_epoch(&mut *self.gas_meter.borrow_mut(), self.storage) } fn iter_prefix( - &self, + &'view self, prefix: &Key, ) -> Result { vp_env::iter_prefix( @@ -386,24 +367,6 @@ where ) } - fn iter_pre_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error> { - vp_env::iter_pre_next::(&mut *self.gas_meter.borrow_mut(), iter) - } - - fn iter_post_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error> { - vp_env::iter_post_next::( - &mut *self.gas_meter.borrow_mut(), - self.write_log, - iter, - ) - } - fn eval( &self, vp_code: Vec, diff --git a/shared/src/ledger/storage_api/mod.rs b/shared/src/ledger/storage_api/mod.rs index 873c14ef9b..94be4d8568 100644 --- a/shared/src/ledger/storage_api/mod.rs +++ b/shared/src/ledger/storage_api/mod.rs @@ -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; + /// Storage prefix iterator for. It will try to read from the storage. + fn iter_next( + &self, + iter: &mut Self::PrefixIter, + ) -> Result)>>; + /// Storage prefix iterator. It will try to get an iterator from the /// storage. /// @@ -64,12 +70,6 @@ pub trait StorageRead<'iter> { prefix: &storage::Key, ) -> Result; - /// Storage prefix iterator for. It will try to read from the storage. - fn iter_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>>; - /// Getting the chain ID. fn get_chain_id(&self) -> Result; diff --git a/shared/src/ledger/vp_env.rs b/shared/src/ledger/vp_env.rs index 95e7c48782..e1f72d8505 100644 --- a/shared/src/ledger/vp_env.rs +++ b/shared/src/ledger/vp_env.rs @@ -7,7 +7,7 @@ use borsh::BorshDeserialize; use thiserror::Error; use super::gas::MIN_STORAGE_GAS; -use super::storage_api; +use super::storage_api::{self, StorageRead}; use crate::ledger::gas; use crate::ledger::gas::VpGasMeter; use crate::ledger::storage::write_log::WriteLog; @@ -18,40 +18,24 @@ use crate::types::key::common; use crate::types::storage::{BlockHash, BlockHeight, Epoch, Key}; /// Validity predicate's environment is available for native VPs and WASM VPs -pub trait VpEnv { +pub trait VpEnv<'view> { /// Storage read prefix iterator type PrefixIter; /// Host functions possible errors, extensible with custom user errors. - type Error; + type Error: From; - /// Storage read prior state Borsh encoded value (before tx execution). It - /// will try to read from the storage and decode it if found. - fn read_pre( - &self, - key: &Key, - ) -> Result, Self::Error>; + /// Type to read storage state before the transaction execution + type Pre: StorageRead<'view, PrefixIter = Self::PrefixIter>; - /// Storage read prior state raw bytes (before tx execution). It - /// will try to read from the storage. - fn read_bytes_pre(&self, key: &Key) - -> Result>, Self::Error>; + /// Type to read storage state after the transaction execution + type Post: StorageRead<'view, PrefixIter = Self::PrefixIter>; - /// Storage read posterior state Borsh encoded value (after tx execution). - /// It will try to read from the write log first and if no entry found - /// then from the storage and then decode it if found. - fn read_post( - &self, - key: &Key, - ) -> Result, Self::Error>; + /// Read storage state before the transaction execution + fn pre(&'view self) -> Self::Pre; - /// Storage read posterior state raw bytes (after tx execution). It will try - /// to read from the write log first and if no entry found then from the - /// storage. - fn read_bytes_post( - &self, - key: &Key, - ) -> Result>, Self::Error>; + /// Read storage state after the transaction execution + fn post(&'view self) -> Self::Post; /// Storage read temporary state Borsh encoded value (after tx execution). /// It will try to read from only the write log and then decode it if @@ -68,51 +52,28 @@ pub trait VpEnv { key: &Key, ) -> Result>, Self::Error>; - /// Storage `has_key` in prior state (before tx execution). It will try to - /// read from the storage. - fn has_key_pre(&self, key: &Key) -> Result; - - /// Storage `has_key` in posterior state (after tx execution). It will try - /// to check the write log first and if no entry found then the storage. - fn has_key_post(&self, key: &Key) -> Result; - /// Getting the chain ID. - fn get_chain_id(&self) -> Result; + fn get_chain_id(&'view 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(&self) -> Result; + fn get_block_height(&'view 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(&self) -> Result; + fn get_block_hash(&'view 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(&self) -> Result; + fn get_block_epoch(&'view self) -> Result; /// Storage prefix iterator. It will try to get an iterator from the /// storage. fn iter_prefix( - &self, + &'view self, prefix: &Key, ) -> Result; - /// Storage prefix iterator for prior state (before tx execution). It will - /// try to read from the storage. - fn iter_pre_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error>; - - /// 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( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error>; - /// Evaluate a validity predicate with given data. The address, changed /// storage keys and verifiers will have the same values as the input to /// caller's validity predicate. @@ -136,6 +97,77 @@ pub trait VpEnv { /// Get a tx hash fn get_tx_code_hash(&self) -> Result; + + // ---- Methods below have default implementation via `pre/post` ---- + + /// Storage read prior state Borsh encoded value (before tx execution). It + /// will try to read from the storage and decode it if found. + fn read_pre( + &'view self, + key: &Key, + ) -> Result, Self::Error> { + self.pre().read(key).map_err(Into::into) + } + + /// Storage read prior state raw bytes (before tx execution). It + /// will try to read from the storage. + fn read_bytes_pre( + &'view self, + key: &Key, + ) -> Result>, Self::Error> { + self.pre().read_bytes(key).map_err(Into::into) + } + + /// Storage read posterior state Borsh encoded value (after tx execution). + /// It will try to read from the write log first and if no entry found + /// then from the storage and then decode it if found. + fn read_post( + &'view self, + key: &Key, + ) -> Result, Self::Error> { + self.post().read(key).map_err(Into::into) + } + + /// Storage read posterior state raw bytes (after tx execution). It will try + /// to read from the write log first and if no entry found then from the + /// storage. + fn read_bytes_post( + &'view self, + key: &Key, + ) -> Result>, Self::Error> { + self.post().read_bytes(key).map_err(Into::into) + } + + /// Storage `has_key` in prior state (before tx execution). It will try to + /// read from the storage. + fn has_key_pre(&'view self, key: &Key) -> Result { + self.pre().has_key(key).map_err(Into::into) + } + + /// Storage `has_key` in posterior state (after tx execution). It will try + /// to check the write log first and if no entry found then the storage. + fn has_key_post(&'view self, key: &Key) -> Result { + self.post().has_key(key).map_err(Into::into) + } + + /// 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)>, Self::Error> { + self.pre().iter_next(iter).map_err(Into::into) + } + + /// 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)>, Self::Error> { + self.post().iter_next(iter).map_err(Into::into) + } } /// These runtime errors will abort VP execution immediately diff --git a/vp_prelude/src/lib.rs b/vp_prelude/src/lib.rs index 056d9cb1d5..d1d3845a48 100644 --- a/vp_prelude/src/lib.rs +++ b/vp_prelude/src/lib.rs @@ -150,36 +150,18 @@ pub fn reject() -> VpResult { #[derive(Debug)] pub struct KeyValIterator(pub u64, pub PhantomData); -impl VpEnv for Ctx { +impl<'view> VpEnv<'view> for Ctx { type Error = Error; + type Post = CtxPostStorageRead<'view>; + type Pre = CtxPreStorageRead<'view>; type PrefixIter = KeyValIterator<(String, Vec)>; - fn read_pre( - &self, - key: &storage::Key, - ) -> Result, Self::Error> { - self.pre().read(key).into_env_result() - } - - fn read_bytes_pre( - &self, - key: &storage::Key, - ) -> Result>, Self::Error> { - self.pre().read_bytes(key).into_env_result() - } - - fn read_post( - &self, - key: &storage::Key, - ) -> Result, Self::Error> { - self.post().read(key).into_env_result() + fn pre(&'view self) -> Self::Pre { + CtxPreStorageRead { _ctx: self } } - fn read_bytes_post( - &self, - key: &storage::Key, - ) -> Result>, Self::Error> { - self.post().read_bytes(key).into_env_result() + fn post(&'view self) -> Self::Post { + CtxPostStorageRead { _ctx: self } } fn read_temp( @@ -203,29 +185,24 @@ impl VpEnv for Ctx { Ok(read_from_buffer(read_result, anoma_vp_result_buffer)) } - fn has_key_pre(&self, key: &storage::Key) -> Result { - self.pre().has_key(key).into_env_result() - } - - fn has_key_post(&self, key: &storage::Key) -> Result { - self.post().has_key(key).into_env_result() - } - - fn get_chain_id(&self) -> Result { + fn get_chain_id(&'view self) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl - self.pre().get_chain_id().into_env_result() + get_chain_id().into_env_result() } - fn get_block_height(&self) -> Result { - self.pre().get_block_height().into_env_result() + fn get_block_height(&'view self) -> Result { + // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl + get_block_height().into_env_result() } - fn get_block_hash(&self) -> Result { - self.pre().get_block_hash().into_env_result() + fn get_block_hash(&'view self) -> Result { + // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl + get_block_hash().into_env_result() } - fn get_block_epoch(&self) -> Result { - self.pre().get_block_epoch().into_env_result() + fn get_block_epoch(&'view self) -> Result { + // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl + get_block_epoch().into_env_result() } fn iter_prefix( @@ -233,21 +210,7 @@ impl VpEnv for Ctx { prefix: &storage::Key, ) -> Result { // Both `CtxPreStorageRead` and `CtxPostStorageRead` have the same impl - self.pre().iter_prefix(prefix).into_env_result() - } - - fn iter_pre_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error> { - self.pre().iter_next(iter).into_env_result() - } - - fn iter_post_next( - &self, - iter: &mut Self::PrefixIter, - ) -> Result)>, Self::Error> { - self.post().iter_next(iter).into_env_result() + iter_prefix(prefix).into_env_result() } fn eval( @@ -315,14 +278,6 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { Ok(HostEnvResult::is_success(found)) } - fn iter_prefix( - &self, - prefix: &storage::Key, - ) -> Result { - // Note that this is the same as `CtxPostStorageRead` - iter_prefix(prefix) - } - fn iter_next( &self, iter: &mut Self::PrefixIter, @@ -334,27 +289,29 @@ impl StorageRead<'_> for CtxPreStorageRead<'_> { )) } + // ---- Methods below share the same implementation in `pre/post` ---- + + fn iter_prefix( + &self, + prefix: &storage::Key, + ) -> Result { + iter_prefix(prefix) + } + fn get_chain_id(&self) -> Result { get_chain_id() } fn get_block_height(&self) -> Result { - Ok(BlockHeight(unsafe { anoma_vp_get_block_height() })) + get_block_height() } fn get_block_hash(&self) -> Result { - let result = Vec::with_capacity(BLOCK_HASH_LENGTH); - unsafe { - anoma_vp_get_block_hash(result.as_ptr() as _); - } - let slice = unsafe { - slice::from_raw_parts(result.as_ptr(), BLOCK_HASH_LENGTH) - }; - Ok(BlockHash::try_from(slice).expect("Cannot convert the hash")) + get_block_hash() } fn get_block_epoch(&self) -> Result { - Ok(Epoch(unsafe { anoma_vp_get_block_epoch() })) + get_block_epoch() } } @@ -378,14 +335,6 @@ impl StorageRead<'_> for CtxPostStorageRead<'_> { Ok(HostEnvResult::is_success(found)) } - fn iter_prefix( - &self, - prefix: &storage::Key, - ) -> Result { - // Note that this is the same as `CtxPreStorageRead` - iter_prefix(prefix) - } - fn iter_next( &self, iter: &mut Self::PrefixIter, @@ -397,6 +346,15 @@ impl StorageRead<'_> for CtxPostStorageRead<'_> { )) } + // ---- Methods below share the same implementation in `pre/post` ---- + + fn iter_prefix( + &self, + prefix: &storage::Key, + ) -> Result { + iter_prefix(prefix) + } + fn get_chain_id(&self) -> Result { get_chain_id() } From c86185c640fdb91ff16f558d861fe7fed313e8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 25 Aug 2022 13:03:44 +0200 Subject: [PATCH 2/3] changelog: add #380 --- .../improvements/380-vp-env-pre-post-via-storage-api.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .changelog/unreleased/improvements/380-vp-env-pre-post-via-storage-api.md diff --git a/.changelog/unreleased/improvements/380-vp-env-pre-post-via-storage-api.md b/.changelog/unreleased/improvements/380-vp-env-pre-post-via-storage-api.md new file mode 100644 index 0000000000..655cdf256a --- /dev/null +++ b/.changelog/unreleased/improvements/380-vp-env-pre-post-via-storage-api.md @@ -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)) \ No newline at end of file From b811466de29d4c819b89d1a16f882a9082f5a100 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Zemanovi=C4=8D?= Date: Thu, 25 Aug 2022 14:38:03 +0200 Subject: [PATCH 3/3] update wasm checksums --- wasm/checksums.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 2478056cb0..1c5fec452f 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -12,8 +12,8 @@ "tx_update_vp.wasm": "tx_update_vp.a304b3c70361cde5fda458ba5637d6825eb002198e73990a1c74351113b83d43.wasm", "tx_vote_proposal.wasm": "tx_vote_proposal.8f306e1d1bcc9ca7f47a39108554fc847d4ac6df7a8d87a6effdffeae6adc4c4.wasm", "tx_withdraw.wasm": "tx_withdraw.c288861e842f0b1ac6fbb95b14b33c8819ac587bbd5b483f2cdd0ea184206c65.wasm", - "vp_nft.wasm": "vp_nft.557883861270a0a5e42802ce4bfbbc28f9f0dfa3b76520ffdd319b69a4f2f34c.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.1fb8c53e7c164d141661743f3cdfaf30d30e6e16abd2f8814c0d8829a2e36e8a.wasm", - "vp_token.wasm": "vp_token.b130ca28e8029f5ad7a33bf3d4fbb9a3b08a29484feba34b988e902c4ce9c966.wasm", - "vp_user.wasm": "vp_user.2c45ba3e0b442210d4dd953679c774cc15f8773c5c25bda7f2ad60eaaff2d0a9.wasm" + "vp_nft.wasm": "vp_nft.379f0a9fdbc9611ba9afc8b03ea17eb1e7c63992be3c2ecd5dd506a0ec3809f3.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.9d28df0e4eea55c98ac05638cfc6211aaf8e1a4b9489f7057634c66d39835c36.wasm", + "vp_token.wasm": "vp_token.6506aea021bb6de9186e96fa0d9ea2ad35bcb66777d6ecf890a66cfe36a74f23.wasm", + "vp_user.wasm": "vp_user.77a0d0d406e300b2d5b9bc1c13bc50f233b6923d369db939ac82c8e10b64543c.wasm" } \ No newline at end of file