From 93a9e450facb07a75f806091d78ec620213a9a97 Mon Sep 17 00:00:00 2001 From: Franfran <51274081+iFrostizz@users.noreply.github.com> Date: Fri, 5 Jul 2024 19:37:23 +0200 Subject: [PATCH] Make `store` take a list of (key, value) to "store many" (#1097) * add `store_single` and adapt `store` to take a list of tuples * merge import * rename to `store_by_key` and make it a store of a one length array Co-authored-by: Richard Pringle Signed-off-by: Franfran <51274081+iFrostizz@users.noreply.github.com> --------- Signed-off-by: Franfran <51274081+iFrostizz@users.noreply.github.com> Co-authored-by: Richard Pringle --- .../automated-market-maker/src/lib.rs | 37 ++++++---------- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/examples/token/src/lib.rs | 18 ++++---- x/programs/rust/wasmlanche-sdk/src/state.rs | 43 +++++++++++-------- .../test/programs/state_access/src/lib.rs | 2 +- 5 files changed, 50 insertions(+), 52 deletions(-) diff --git a/x/programs/rust/examples/automated-market-maker/src/lib.rs b/x/programs/rust/examples/automated-market-maker/src/lib.rs index d418311a59..0fe1cee600 100644 --- a/x/programs/rust/examples/automated-market-maker/src/lib.rs +++ b/x/programs/rust/examples/automated-market-maker/src/lib.rs @@ -31,15 +31,11 @@ pub fn add_liquidity(context: Context, amount_x: u64, amount_y: u64) program .state() - .store(StateKeys::ReserveX, &(reserve_x + amount_x)) - .unwrap(); - program - .state() - .store(StateKeys::ReserveY, &(reserve_y + amount_y)) - .unwrap(); - program - .state() - .store(StateKeys::TotalySupply, &(total_supply + minted)) + .store([ + (StateKeys::ReserveX, &(reserve_x + amount_x)), + (StateKeys::ReserveY, &(reserve_y + amount_y)), + (StateKeys::TotalySupply, &(total_supply + minted)), + ]) .unwrap(); minted @@ -57,15 +53,11 @@ pub fn remove_liquidity(context: Context, shares: u64) -> (u64, u64) program .state() - .store(StateKeys::ReserveX, &(reserve_x - amount_x)) - .unwrap(); - program - .state() - .store(StateKeys::ReserveY, &(reserve_y - amount_y)) - .unwrap(); - program - .state() - .store(StateKeys::TotalySupply, &(total_supply - shares)) + .store([ + (StateKeys::ReserveX, &(reserve_x - amount_x)), + (StateKeys::ReserveY, &(reserve_y - amount_y)), + (StateKeys::TotalySupply, &(total_supply - shares)), + ]) .unwrap(); (amount_x, amount_y) @@ -95,11 +87,10 @@ pub fn swap(context: Context, amount_in: u64, x_to_y: bool) -> u64 { program .state() - .store(StateKeys::ReserveX, &reserve_x) - .unwrap(); - program - .state() - .store(StateKeys::ReserveY, &reserve_y) + .store([ + (StateKeys::ReserveX, &reserve_x), + (StateKeys::ReserveY, &reserve_y), + ]) .unwrap(); out diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index a7568350da..0e180cd75d 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -22,7 +22,7 @@ pub fn inc(context: Context, to: Address, amount: Count) -> bool { context .program() .state() - .store(StateKeys::Counter(to), &counter) + .store_by_key(StateKeys::Counter(to), &counter) .expect("failed to store counter"); true diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 77e4472415..20a34634ac 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -26,19 +26,19 @@ pub fn init(context: Context) { // set total supply program .state() - .store(StateKeys::TotalSupply, &INITIAL_SUPPLY) + .store_by_key(StateKeys::TotalSupply, &INITIAL_SUPPLY) .expect("failed to store total supply"); // set token name program .state() - .store(StateKeys::Name, b"WasmCoin") + .store_by_key(StateKeys::Name, b"WasmCoin") .expect("failed to store coin name"); // set token symbol program .state() - .store(StateKeys::Symbol, b"WACK") + .store_by_key(StateKeys::Symbol, b"WACK") .expect("failed to store symbol"); } @@ -76,7 +76,7 @@ fn mint_to_internal( program .state() - .store(StateKeys::Balance(recipient), &(balance + amount)) + .store_by_key(StateKeys::Balance(recipient), &(balance + amount)) .expect("failed to store balance"); context @@ -123,12 +123,10 @@ pub fn transfer( // update balances program .state() - .store(StateKeys::Balance(sender), &(sender_balance - amount)) - .expect("failed to store balance"); - - program - .state() - .store(StateKeys::Balance(recipient), &(recipient_balance + amount)) + .store([ + (StateKeys::Balance(sender), &(sender_balance - amount)), + (StateKeys::Balance(recipient), &(recipient_balance + amount)), + ]) .expect("failed to store balance"); true diff --git a/x/programs/rust/wasmlanche-sdk/src/state.rs b/x/programs/rust/wasmlanche-sdk/src/state.rs index cac90c41f7..ead11c773c 100644 --- a/x/programs/rust/wasmlanche-sdk/src/state.rs +++ b/x/programs/rust/wasmlanche-sdk/src/state.rs @@ -1,5 +1,5 @@ use crate::{memory::HostPtr, state::Error as StateError}; -use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize}; +use borsh::{from_slice, BorshDeserialize, BorshSerialize}; use std::{cell::RefCell, collections::HashMap, hash::Hash}; #[derive(Clone, thiserror::Error, Debug)] @@ -38,29 +38,38 @@ impl<'a, K: Key> State<'a, K> { Self { cache } } - /// Store a key and value to the host storage. If the key already exists, - /// the value will be overwritten. + /// Store a list of tuple of key and value to the host storage. /// # Errors /// Returns an [`Error`] if the key or value cannot be /// serialized or if the host fails to handle the operation. - pub fn store(self, key: K, value: &V) -> Result<(), Error> - where - V: BorshSerialize, - { - let serialized = to_vec(&value) - .map_err(|_| StateError::Deserialization) - .and_then(|bytes| { - if bytes.is_empty() { - Err(StateError::InvalidByteLength(0)) - } else { - Ok(bytes) - } - })?; - self.cache.borrow_mut().insert(key, Some(serialized)); + pub fn store<'b, V: BorshSerialize + 'b, Pairs: IntoIterator>( + self, + pairs: Pairs, + ) -> Result<(), Error> { + let cache = &mut self.cache.borrow_mut(); + + pairs + .into_iter() + .map(|(k, v)| borsh::to_vec(&v).map(|bytes| (k, Some(bytes)))) + .try_for_each(|result| { + result.map(|(k, v)| { + cache.insert(k, v); + }) + }) + .map_err(|_| StateError::Serialization)?; Ok(()) } + /// Store a key and value to the host storage. If the key already exists, + /// the value will be overwritten. + /// # Errors + /// Returns an [`Error`] if the key or value cannot be + /// serialized or if the host fails to handle the operation. + pub fn store_by_key(self, key: K, value: &V) -> Result<(), Error> { + self.store([(key, value)]) + } + /// Get a value from the host's storage. /// /// Note: The pointer passed to the host are only valid for the duration of this diff --git a/x/programs/test/programs/state_access/src/lib.rs b/x/programs/test/programs/state_access/src/lib.rs index c9f8ef717e..c68a5b5fe2 100644 --- a/x/programs/test/programs/state_access/src/lib.rs +++ b/x/programs/test/programs/state_access/src/lib.rs @@ -12,7 +12,7 @@ pub fn put(context: Context, value: i64) { context .program() .state() - .store(StateKeys::State, &value) + .store_by_key(StateKeys::State, &value) .expect("failed to store state"); }