diff --git a/contracts/cw3-fixed-multisig/src/contract.rs b/contracts/cw3-fixed-multisig/src/contract.rs index f15102592..759803952 100644 --- a/contracts/cw3-fixed-multisig/src/contract.rs +++ b/contracts/cw3-fixed-multisig/src/contract.rs @@ -13,7 +13,7 @@ use cw3::{ ProposalListResponse, ProposalResponse, Status, ThresholdResponse, Vote, VoteInfo, VoteListResponse, VoteResponse, VoterDetail, VoterListResponse, VoterResponse, }; -use cw_storage_plus::{AddrRef, Bound}; +use cw_storage_plus::Bound; use crate::error::ContractError; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; @@ -56,7 +56,7 @@ pub fn instantiate( // add all voters for voter in msg.voters.iter() { let key = deps.api.addr_validate(&voter.addr)?; - VOTERS.save(deps.storage, AddrRef::new(&key), &voter.weight)?; + VOTERS.save(deps.storage, &key, &voter.weight)?; } Ok(Response::default()) } @@ -92,9 +92,8 @@ pub fn execute_propose( latest: Option, ) -> Result, ContractError> { // only members of the multisig can create a proposal - let sender = AddrRef::new(&info.sender); let vote_power = VOTERS - .may_load(deps.storage, sender)? + .may_load(deps.storage, &info.sender)? .ok_or(ContractError::Unauthorized {})?; let cfg = CONFIG.load(deps.storage)?; @@ -126,14 +125,14 @@ pub fn execute_propose( required_weight: cfg.required_weight, }; let id = next_id(deps.storage)?; - PROPOSALS.save(deps.storage, id.into(), &prop)?; + PROPOSALS.save(deps.storage, &id.into(), &prop)?; // add the first yes vote from voter let ballot = Ballot { weight: vote_power, vote: Vote::Yes, }; - BALLOTS.save(deps.storage, (id.into(), sender), &ballot)?; + BALLOTS.save(deps.storage, &(id.into(), info.sender.clone()), &ballot)?; Ok(Response { submessages: vec![], @@ -156,13 +155,12 @@ pub fn execute_vote( vote: Vote, ) -> Result, ContractError> { // only members of the multisig can vote - let sender = AddrRef::new(&info.sender); let vote_power = VOTERS - .may_load(deps.storage, sender)? + .may_load(deps.storage, &info.sender)? .ok_or(ContractError::Unauthorized {})?; // ensure proposal exists and can be voted on - let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?; + let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?; if prop.status != Status::Open { return Err(ContractError::NotOpen {}); } @@ -173,7 +171,7 @@ pub fn execute_vote( // cast vote if no vote previously cast BALLOTS.update( deps.storage, - (proposal_id.into(), sender), + &(proposal_id.into(), info.sender.clone()), |bal| match bal { Some(_) => Err(ContractError::AlreadyVoted {}), None => Ok(Ballot { @@ -190,7 +188,7 @@ pub fn execute_vote( if prop.yes_weight >= prop.required_weight { prop.status = Status::Passed; } - PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?; + PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?; } Ok(Response { @@ -214,7 +212,7 @@ pub fn execute_execute( ) -> Result { // anyone can trigger this if the vote passed - let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?; + let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?; // we allow execution even after the proposal "expiration" as long as all vote come in before // that point. If it was approved on time, it can be executed any time. if prop.status != Status::Passed { @@ -223,7 +221,7 @@ pub fn execute_execute( // set it to executed prop.status = Status::Executed; - PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?; + PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?; // dispatch all proposed messages Ok(Response { @@ -246,7 +244,7 @@ pub fn execute_close( ) -> Result, ContractError> { // anyone can trigger this if the vote passed - let mut prop = PROPOSALS.load(deps.storage, proposal_id.into())?; + let mut prop = PROPOSALS.load(deps.storage, &proposal_id.into())?; if [Status::Executed, Status::Rejected, Status::Passed] .iter() .any(|x| *x == prop.status) @@ -259,7 +257,7 @@ pub fn execute_close( // set it to failed prop.status = Status::Rejected; - PROPOSALS.save(deps.storage, proposal_id.into(), &prop)?; + PROPOSALS.save(deps.storage, &proposal_id.into(), &prop)?; Ok(Response { submessages: vec![], @@ -307,7 +305,7 @@ fn query_threshold(deps: Deps) -> StdResult { } fn query_proposal(deps: Deps, env: Env, id: u64) -> StdResult { - let prop = PROPOSALS.load(deps.storage, id.into())?; + let prop = PROPOSALS.load(deps.storage, &id.into())?; let status = prop.current_status(&env.block); let cfg = CONFIG.load(deps.storage)?; @@ -395,12 +393,10 @@ fn map_proposal( } fn query_vote(deps: Deps, proposal_id: u64, voter: String) -> StdResult { - let ballot = BALLOTS.may_load( - deps.storage, - (proposal_id.into(), AddrRef::unchecked(&voter)), - )?; + let voter = deps.api.addr_validate(&voter)?; + let ballot = BALLOTS.may_load(deps.storage, &(proposal_id.into(), voter.clone()))?; let vote = ballot.map(|b| VoteInfo { - voter, + voter: voter.into(), vote: b.vote, weight: b.weight, }); @@ -434,7 +430,8 @@ fn list_votes( } fn query_voter(deps: Deps, voter: String) -> StdResult { - let weight = VOTERS.may_load(deps.storage, AddrRef::unchecked(&voter))?; + let voter = deps.api.addr_validate(&voter)?; + let weight = VOTERS.may_load(deps.storage, &voter)?; Ok(VoterResponse { weight }) } diff --git a/contracts/cw3-fixed-multisig/src/state.rs b/contracts/cw3-fixed-multisig/src/state.rs index 3f6dd3c82..c3f667f92 100644 --- a/contracts/cw3-fixed-multisig/src/state.rs +++ b/contracts/cw3-fixed-multisig/src/state.rs @@ -2,11 +2,11 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::convert::TryInto; -use cosmwasm_std::{BlockInfo, CosmosMsg, Empty, StdError, StdResult, Storage}; +use cosmwasm_std::{Addr, BlockInfo, CosmosMsg, Empty, StdError, StdResult, Storage}; use cw0::{Duration, Expiration}; use cw3::{Status, Vote}; -use cw_storage_plus::{AddrRef, Item, Map, U64Key}; +use cw_storage_plus::{Item, Map, U64Key}; #[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] pub struct Config { @@ -57,9 +57,9 @@ pub const CONFIG: Item = Item::new("config"); pub const PROPOSAL_COUNT: Item = Item::new("proposal_count"); // multiple-item maps -pub const VOTERS: Map = Map::new("voters"); +pub const VOTERS: Map = Map::new("voters"); pub const PROPOSALS: Map = Map::new("proposals"); -pub const BALLOTS: Map<(U64Key, AddrRef), Ballot> = Map::new("ballots"); +pub const BALLOTS: Map<(U64Key, Addr), Ballot> = Map::new("ballots"); pub fn next_id(store: &mut dyn Storage) -> StdResult { let id: u64 = PROPOSAL_COUNT.may_load(store)?.unwrap_or_default() + 1; diff --git a/packages/storage-plus/src/indexed_map.rs b/packages/storage-plus/src/indexed_map.rs index a7744164a..1735e84df 100644 --- a/packages/storage-plus/src/indexed_map.rs +++ b/packages/storage-plus/src/indexed_map.rs @@ -54,13 +54,13 @@ where /// save will serialize the model and store, returns an error on serialization issues. /// this must load the old value to update the indexes properly /// if you loaded the old value earlier in the same function, use replace to avoid needless db reads - pub fn save(&self, store: &mut dyn Storage, key: K, data: &T) -> StdResult<()> { - let old_data = self.may_load(store, key.clone())?; + pub fn save(&self, store: &mut dyn Storage, key: &K, data: &T) -> StdResult<()> { + let old_data = self.may_load(store, key)?; self.replace(store, key, Some(data), old_data.as_ref()) } - pub fn remove(&self, store: &mut dyn Storage, key: K) -> StdResult<()> { - let old_data = self.may_load(store, key.clone())?; + pub fn remove(&self, store: &mut dyn Storage, key: &K) -> StdResult<()> { + let old_data = self.may_load(store, key)?; self.replace(store, key, None, old_data.as_ref()) } @@ -70,7 +70,7 @@ where pub fn replace( &self, store: &mut dyn Storage, - key: K, + key: &K, data: Option<&T>, old_data: Option<&T>, ) -> StdResult<()> { @@ -96,12 +96,12 @@ where /// in the database. This is shorthand for some common sequences, which may be useful. /// /// If the data exists, `action(Some(value))` is called. Otherwise `action(None)` is called. - pub fn update(&self, store: &mut dyn Storage, key: K, action: A) -> Result + pub fn update(&self, store: &mut dyn Storage, key: &K, action: A) -> Result where A: FnOnce(Option) -> Result, E: From, { - let input = self.may_load(store, key.clone())?; + let input = self.may_load(store, key)?; let old_val = input.clone(); let output = action(input)?; self.replace(store, key, Some(&output), old_val.as_ref())?; @@ -112,13 +112,13 @@ where // thus can be used from while iterating over indexes /// load will return an error if no data is set at the given key, or on parse error - pub fn load(&self, store: &dyn Storage, key: K) -> StdResult { + pub fn load(&self, store: &dyn Storage, key: &K) -> StdResult { self.primary.load(store, key) } /// may_load will parse the data stored at the key if present, returns Ok(None) if no data there. /// returns an error on issues parsing - pub fn may_load(&self, store: &dyn Storage, key: K) -> StdResult> { + pub fn may_load(&self, store: &dyn Storage, key: &K) -> StdResult> { self.primary.may_load(store, key) } @@ -232,7 +232,7 @@ mod test { age: 42, }; let pk: &[u8] = b"1"; - map.save(store, pk, &data).unwrap(); + map.save(store, &pk, &data).unwrap(); pks.push(pk); datas.push(data); @@ -243,7 +243,7 @@ mod test { age: 23, }; let pk: &[u8] = b"2"; - map.save(store, pk, &data).unwrap(); + map.save(store, &pk, &data).unwrap(); pks.push(pk); datas.push(data); @@ -254,7 +254,7 @@ mod test { age: 32, }; let pk: &[u8] = b"3"; - map.save(store, pk, &data).unwrap(); + map.save(store, &pk, &data).unwrap(); pks.push(pk); datas.push(data); @@ -264,7 +264,7 @@ mod test { age: 12, }; let pk: &[u8] = b"4"; - map.save(store, pk, &data).unwrap(); + map.save(store, &pk, &data).unwrap(); pks.push(pk); datas.push(data); @@ -282,7 +282,7 @@ mod test { let data = &datas[0]; // load it properly - let loaded = map.load(&store, pk).unwrap(); + let loaded = map.load(&store, &pk).unwrap(); assert_eq!(*data, loaded); let count = map @@ -342,13 +342,13 @@ mod test { // match on proper age let proper = U32Key::new(42); - let aged = map.idx.age.item(&store, proper).unwrap().unwrap(); + let aged = map.idx.age.item(&store, &proper).unwrap().unwrap(); assert_eq!(pk.to_vec(), aged.0); assert_eq!(*data, aged.1); // no match on wrong age let too_old = U32Key::new(43); - let aged = map.idx.age.item(&store, too_old).unwrap(); + let aged = map.idx.age.item(&store, &too_old).unwrap(); assert_eq!(None, aged); } @@ -364,7 +364,7 @@ mod test { age: 42, }; let pk: &[u8] = b"5627"; - map.save(&mut store, pk, &data1).unwrap(); + map.save(&mut store, &pk, &data1).unwrap(); let data2 = Data { name: "Juan".to_string(), @@ -372,7 +372,7 @@ mod test { age: 13, }; let pk: &[u8] = b"5628"; - map.save(&mut store, pk, &data2).unwrap(); + map.save(&mut store, &pk, &data2).unwrap(); let data3 = Data { name: "Maria".to_string(), @@ -380,7 +380,7 @@ mod test { age: 24, }; let pk: &[u8] = b"5629"; - map.save(&mut store, pk, &data3).unwrap(); + map.save(&mut store, &pk, &data3).unwrap(); let data4 = Data { name: "Maria Luisa".to_string(), @@ -388,7 +388,7 @@ mod test { age: 12, }; let pk: &[u8] = b"5630"; - map.save(&mut store, pk, &data4).unwrap(); + map.save(&mut store, &pk, &data4).unwrap(); let marias: Vec<_> = map .idx @@ -428,7 +428,7 @@ mod test { age: 42, }; let pk1: &[u8] = b"5627"; - map.save(&mut store, pk1, &data1).unwrap(); + map.save(&mut store, &pk1, &data1).unwrap(); let data2 = Data { name: "Juan".to_string(), @@ -436,7 +436,7 @@ mod test { age: 13, }; let pk2: &[u8] = b"5628"; - map.save(&mut store, pk2, &data2).unwrap(); + map.save(&mut store, &pk2, &data2).unwrap(); let data3 = Data { name: "Maria".to_string(), @@ -444,7 +444,7 @@ mod test { age: 24, }; let pk3: &[u8] = b"5629"; - map.save(&mut store, pk3, &data3).unwrap(); + map.save(&mut store, &pk3, &data3).unwrap(); let data4 = Data { name: "Maria Luisa".to_string(), @@ -452,7 +452,7 @@ mod test { age: 43, }; let pk4: &[u8] = b"5630"; - map.save(&mut store, pk4, &data4).unwrap(); + map.save(&mut store, &pk4, &data4).unwrap(); let marias: Vec<_> = map .idx @@ -490,28 +490,28 @@ mod test { let pk5: &[u8] = b"4"; // enforce this returns some error - map.save(&mut store, pk5, &data5).unwrap_err(); + map.save(&mut store, &pk5, &data5).unwrap_err(); // query by unique key // match on proper age let age42 = U32Key::new(42); - let (k, v) = map.idx.age.item(&store, age42.clone()).unwrap().unwrap(); + let (k, v) = map.idx.age.item(&store, &age42).unwrap().unwrap(); assert_eq!(k.as_slice(), pks[0]); assert_eq!(v.name, datas[0].name); assert_eq!(v.age, datas[0].age); // match on other age let age23 = U32Key::new(23); - let (k, v) = map.idx.age.item(&store, age23).unwrap().unwrap(); + let (k, v) = map.idx.age.item(&store, &age23).unwrap().unwrap(); assert_eq!(k.as_slice(), pks[1]); assert_eq!(v.name, datas[1].name); assert_eq!(v.age, datas[1].age); // if we delete the first one, we can add the blocked one - map.remove(&mut store, pks[0]).unwrap(); - map.save(&mut store, pk5, &data5).unwrap(); + map.remove(&mut store, &pks[0]).unwrap(); + map.save(&mut store, &pk5, &data5).unwrap(); // now 42 is the new owner - let (k, v) = map.idx.age.item(&store, age42).unwrap().unwrap(); + let (k, v) = map.idx.age.item(&store, &age42).unwrap().unwrap(); assert_eq!(k.as_slice(), pk5); assert_eq!(v.name, data5.name); assert_eq!(v.age, data5.age); @@ -533,7 +533,7 @@ mod test { }; let pk5: &[u8] = b"5"; // enforce this returns some error - map.save(&mut store, pk5, &data5).unwrap_err(); + map.save(&mut store, &pk5, &data5).unwrap_err(); } #[test] @@ -567,10 +567,10 @@ mod test { assert_eq!(name_count(&map, &store, "Mary"), 0); // remove maria 2 - map.remove(&mut store, pks[1]).unwrap(); + map.remove(&mut store, &pks[1]).unwrap(); // change john to mary - map.update(&mut store, pks[2], |d| -> StdResult<_> { + map.update(&mut store, &pks[2], |d| -> StdResult<_> { let mut x = d.unwrap(); assert_eq!(&x.name, "John"); x.name = "Mary".to_string(); diff --git a/packages/storage-plus/src/indexes.rs b/packages/storage-plus/src/indexes.rs index 219bc3ad9..eb6679e44 100644 --- a/packages/storage-plus/src/indexes.rs +++ b/packages/storage-plus/src/indexes.rs @@ -105,12 +105,12 @@ where { fn save(&self, store: &mut dyn Storage, pk: &[u8], data: &T) -> StdResult<()> { let idx = (self.index)(data, pk.to_vec()); - self.idx_map.save(store, idx, &(pk.len() as u32)) + self.idx_map.save(store, &idx, &(pk.len() as u32)) } fn remove(&self, store: &mut dyn Storage, pk: &[u8], old_data: &T) -> StdResult<()> { let idx = (self.index)(old_data, pk.to_vec()); - self.idx_map.remove(store, idx); + self.idx_map.remove(store, &idx); Ok(()) } } @@ -240,7 +240,7 @@ where let idx = (self.index)(data); // error if this is already set self.idx_map - .update(store, idx, |existing| -> StdResult<_> { + .update(store, &idx, |existing| -> StdResult<_> { match existing { Some(_) => Err(StdError::generic_err("Violates unique constraint on index")), None => Ok(UniqueRef:: { @@ -254,7 +254,7 @@ where fn remove(&self, store: &mut dyn Storage, _pk: &[u8], old_data: &T) -> StdResult<()> { let idx = (self.index)(old_data); - self.idx_map.remove(store, idx); + self.idx_map.remove(store, &idx); Ok(()) } } @@ -283,7 +283,7 @@ where } /// returns all items that match this secondary index, always by pk Ascending - pub fn item(&self, store: &dyn Storage, idx: K) -> StdResult>> { + pub fn item(&self, store: &dyn Storage, idx: &K) -> StdResult>> { let data = self .idx_map .may_load(store, idx)? diff --git a/packages/storage-plus/src/keys.rs b/packages/storage-plus/src/keys.rs index 655be7509..6044ba0bb 100644 --- a/packages/storage-plus/src/keys.rs +++ b/packages/storage-plus/src/keys.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; use std::str::from_utf8; +use cosmwasm_std::Addr; + use crate::addr::AddrRef; use crate::helpers::{decode_length, namespaces_with_key}; use crate::Endian; @@ -20,7 +22,7 @@ pub trait PrimaryKey<'a>: Clone { } /// extracts a single or composite key from a joined key, - /// only lives as long as the original bytes + /// and returns it as an owned object. fn parse_key(serialized: &'a [u8]) -> Self; } @@ -38,6 +40,34 @@ impl<'a> PrimaryKey<'a> for &'a [u8] { } } +impl<'a> PrimaryKey<'a> for Vec { + type Prefix = (); + type SubPrefix = (); + + fn key(&self) -> Vec<&[u8]> { + // this is simple, we don't add more prefixes + vec![self] + } + + fn parse_key(serialized: &'a [u8]) -> Self { + serialized.to_owned() + } +} + +impl<'a> PrimaryKey<'a> for Addr { + type Prefix = (); + type SubPrefix = (); + + fn key(&self) -> Vec<&[u8]> { + // this is simple, we don't add more prefixes + vec![self.as_ref().as_bytes()] + } + + fn parse_key(serialized: &'a [u8]) -> Self { + Addr::unchecked(from_utf8(serialized).unwrap()) + } +} + // Provide a string version of this to raw encode strings impl<'a> PrimaryKey<'a> for &'a str { type Prefix = (); diff --git a/packages/storage-plus/src/map.rs b/packages/storage-plus/src/map.rs index 43e85c1fd..6f8a64183 100644 --- a/packages/storage-plus/src/map.rs +++ b/packages/storage-plus/src/map.rs @@ -33,7 +33,7 @@ where T: Serialize + DeserializeOwned, K: PrimaryKey<'a>, { - pub fn key(&self, k: K) -> Path { + pub fn key(&self, k: &K) -> Path { Path::new(self.namespace, &k.key()) } @@ -47,22 +47,22 @@ where Prefix::new(self.namespace, &p.prefix()) } - pub fn save(&self, store: &mut dyn Storage, k: K, data: &T) -> StdResult<()> { + pub fn save(&self, store: &mut dyn Storage, k: &K, data: &T) -> StdResult<()> { self.key(k).save(store, data) } - pub fn remove(&self, store: &mut dyn Storage, k: K) { + pub fn remove(&self, store: &mut dyn Storage, k: &K) { self.key(k).remove(store) } /// load will return an error if no data is set at the given key, or on parse error - pub fn load(&self, store: &dyn Storage, k: K) -> StdResult { + pub fn load(&self, store: &dyn Storage, k: &K) -> StdResult { self.key(k).load(store) } /// may_load will parse the data stored at the key if present, returns Ok(None) if no data there. /// returns an error on issues parsing - pub fn may_load(&self, store: &dyn Storage, k: K) -> StdResult> { + pub fn may_load(&self, store: &dyn Storage, k: &K) -> StdResult> { self.key(k).may_load(store) } @@ -70,7 +70,7 @@ where /// in the database. This is shorthand for some common sequences, which may be useful. /// /// If the data exists, `action(Some(value))` is called. Otherwise `action(None)` is called. - pub fn update(&self, store: &mut dyn Storage, k: K, action: A) -> Result + pub fn update(&self, store: &mut dyn Storage, k: &K, action: A) -> Result where A: FnOnce(Option) -> Result, E: From, @@ -133,22 +133,23 @@ mod test { pub age: i32, } - const PEOPLE: Map<&[u8], Data> = Map::new("people"); + const PEOPLE: Map, Data> = Map::new("people"); - const ALLOWANCE: Map<(&[u8], &[u8]), u64> = Map::new("allow"); + const ALLOWANCE: Map<(&[u8], Vec), u64> = Map::new("allow"); const TRIPLE: Map<(&[u8], U8Key, &str), u64> = Map::new("triple"); #[test] fn create_path() { - let path = PEOPLE.key(b"john"); + let john_key = b"john".to_vec(); + let path = PEOPLE.key(&john_key); let key = path.deref(); // this should be prefixed(people) || john - assert_eq!("people".len() + "john".len() + 2, key.len()); + assert_eq!("people".len() + john_key.len() + 2, key.len()); assert_eq!(b"people".to_vec().as_slice(), &key[2..8]); assert_eq!(b"john".to_vec().as_slice(), &key[8..]); - let path = ALLOWANCE.key((b"john", b"maria")); + let path = ALLOWANCE.key(&(b"john", b"maria".to_vec())); let key = path.deref(); // this should be prefixed(allow) || prefixed(john) || maria assert_eq!( @@ -159,7 +160,7 @@ mod test { assert_eq!(b"john".to_vec().as_slice(), &key[9..13]); assert_eq!(b"maria".to_vec().as_slice(), &key[13..]); - let path = TRIPLE.key((b"john", 8u8.into(), "pedro")); + let path = TRIPLE.key(&(b"john", 8u8.into(), "pedro")); let key = path.deref(); // this should be prefixed(allow) || prefixed(john) || maria assert_eq!( @@ -177,7 +178,9 @@ mod test { let mut store = MockStorage::new(); // save and load on one key - let john = PEOPLE.key(b"john"); + let john_key = b"john".to_vec(); + let jack_key = b"jack".to_vec(); + let john = PEOPLE.key(&john_key); let data = Data { name: "John".to_string(), age: 32, @@ -187,10 +190,10 @@ mod test { assert_eq!(data, john.load(&store).unwrap()); // nothing on another key - assert_eq!(None, PEOPLE.may_load(&store, b"jack").unwrap()); + assert_eq!(None, PEOPLE.may_load(&store, &jack_key).unwrap()); // same named path gets the data - assert_eq!(data, PEOPLE.load(&store, b"john").unwrap()); + assert_eq!(data, PEOPLE.load(&store, &john_key).unwrap()); // removing leaves us empty john.remove(&mut store); @@ -202,17 +205,21 @@ mod test { let mut store = MockStorage::new(); // save and load on a composite key - let allow = ALLOWANCE.key((b"owner", b"spender")); + let allow = ALLOWANCE.key(&(b"owner", b"spender".to_vec())); assert_eq!(None, allow.may_load(&store).unwrap()); allow.save(&mut store, &1234).unwrap(); assert_eq!(1234, allow.load(&store).unwrap()); // not under other key - let different = ALLOWANCE.may_load(&store, (b"owners", b"pender")).unwrap(); + let different = ALLOWANCE + .may_load(&store, &(b"owners", b"pender".to_vec())) + .unwrap(); assert_eq!(None, different); // matches under a proper copy - let same = ALLOWANCE.load(&store, (b"owner", b"spender")).unwrap(); + let same = ALLOWANCE + .load(&store, &(b"owner", b"spender".to_vec())) + .unwrap(); assert_eq!(1234, same); } @@ -221,20 +228,20 @@ mod test { let mut store = MockStorage::new(); // save and load on a triple composite key - let triple = TRIPLE.key((b"owner", 10u8.into(), "recipient")); + let triple = TRIPLE.key(&(b"owner", 10u8.into(), "recipient")); assert_eq!(None, triple.may_load(&store).unwrap()); triple.save(&mut store, &1234).unwrap(); assert_eq!(1234, triple.load(&store).unwrap()); // not under other key let different = TRIPLE - .may_load(&store, (b"owners", 10u8.into(), "ecipient")) + .may_load(&store, &(b"owners", 10u8.into(), "ecipient")) .unwrap(); assert_eq!(None, different); // matches under a proper copy let same = TRIPLE - .load(&store, (b"owner", 10u8.into(), "recipient")) + .load(&store, &(b"owner", 10u8.into(), "recipient")) .unwrap(); assert_eq!(1234, same); } @@ -245,17 +252,19 @@ mod test { let mut store = MockStorage::new(); // save and load on two keys + let john_key = b"john".to_vec(); + let jim_key = b"jack".to_vec(); let data = Data { name: "John".to_string(), age: 32, }; - PEOPLE.save(&mut store, b"john", &data).unwrap(); + PEOPLE.save(&mut store, &john_key, &data).unwrap(); let data2 = Data { name: "Jim".to_string(), age: 44, }; - PEOPLE.save(&mut store, b"jim", &data2).unwrap(); + PEOPLE.save(&mut store, &jim_key, &data2).unwrap(); // let's try to iterate! let all: StdResult> = PEOPLE.range(&store, None, None, Order::Ascending).collect(); @@ -264,8 +273,8 @@ mod test { assert_eq!( all, vec![ - (b"jim".to_vec(), data2.clone()), - (b"john".to_vec(), data.clone()) + (jim_key.clone(), data2.clone()), + (john_key.clone(), data.clone()) ] ); @@ -282,7 +291,7 @@ mod test { assert_eq!(2, all.len()); assert_eq!( all, - vec![(b"jim".to_vec(), data2), (b"john".to_vec(), data.clone())] + vec![(jim_key, data2), (john_key.clone(), data.clone())] ); // let's try to iterate over a more restrictive range @@ -296,7 +305,7 @@ mod test { .collect(); let all = all.unwrap(); assert_eq!(1, all.len()); - assert_eq!(all, vec![(b"john".to_vec(), data)]); + assert_eq!(all, vec![(john_key, data)]); } #[test] @@ -306,13 +315,13 @@ mod test { // save and load on three keys, one under different owner ALLOWANCE - .save(&mut store, (b"owner", b"spender"), &1000) + .save(&mut store, &(b"owner", b"spender".to_vec()), &1000) .unwrap(); ALLOWANCE - .save(&mut store, (b"owner", b"spender2"), &3000) + .save(&mut store, &(b"owner", b"spender2".to_vec()), &3000) .unwrap(); ALLOWANCE - .save(&mut store, (b"owner2", b"spender"), &5000) + .save(&mut store, &(b"owner2", b"spender".to_vec()), &5000) .unwrap(); // let's try to iterate! @@ -335,16 +344,16 @@ mod test { // save and load on three keys, one under different owner TRIPLE - .save(&mut store, (b"owner", 9u8.into(), "recipient"), &1000) + .save(&mut store, &(b"owner", 9u8.into(), "recipient"), &1000) .unwrap(); TRIPLE - .save(&mut store, (b"owner", 9u8.into(), "recipient2"), &3000) + .save(&mut store, &(b"owner", 9u8.into(), "recipient2"), &3000) .unwrap(); TRIPLE - .save(&mut store, (b"owner", 10u8.into(), "recipient3"), &3000) + .save(&mut store, &(b"owner", 10u8.into(), "recipient3"), &3000) .unwrap(); TRIPLE - .save(&mut store, (b"owner2", 9u8.into(), "recipient"), &5000) + .save(&mut store, &(b"owner2", 9u8.into(), "recipient"), &5000) .unwrap(); // let's try to iterate! @@ -396,11 +405,11 @@ mod test { let add_ten = |a: Option| -> StdResult<_> { Ok(a.unwrap_or_default() + 10) }; // save and load on three keys, one under different owner - let key: (&[u8], &[u8]) = (b"owner", b"spender"); - ALLOWANCE.update(&mut store, key, add_ten).unwrap(); - let twenty = ALLOWANCE.update(&mut store, key, add_ten).unwrap(); + let key: (&[u8], Vec) = (b"owner", b"spender".to_vec()); + ALLOWANCE.update(&mut store, &key, add_ten).unwrap(); + let twenty = ALLOWANCE.update(&mut store, &key, add_ten).unwrap(); assert_eq!(20, twenty); - let loaded = ALLOWANCE.load(&store, key).unwrap(); + let loaded = ALLOWANCE.load(&store, &key).unwrap(); assert_eq!(20, loaded); } @@ -412,15 +421,18 @@ mod test { age: 32, }; + let john_key = b"john".to_vec(); + let jack_key = b"jack".to_vec(); + // load and save with extra key argument - let empty = PEOPLE.may_load(&store, b"john")?; + let empty = PEOPLE.may_load(&store, &john_key)?; assert_eq!(None, empty); - PEOPLE.save(&mut store, b"john", &data)?; - let loaded = PEOPLE.load(&store, b"john")?; + PEOPLE.save(&mut store, &john_key, &data)?; + let loaded = PEOPLE.load(&store, &john_key)?; assert_eq!(data, loaded); // nothing on another key - let missing = PEOPLE.may_load(&store, b"jack")?; + let missing = PEOPLE.may_load(&store, &jack_key)?; assert_eq!(None, missing); // update function for new or existing keys @@ -437,21 +449,21 @@ mod test { } }; - let old_john = PEOPLE.update(&mut store, b"john", birthday)?; + let old_john = PEOPLE.update(&mut store, &john_key, birthday)?; assert_eq!(33, old_john.age); assert_eq!("John", old_john.name.as_str()); - let new_jack = PEOPLE.update(&mut store, b"jack", birthday)?; + let new_jack = PEOPLE.update(&mut store, &jack_key, birthday)?; assert_eq!(0, new_jack.age); assert_eq!("Newborn", new_jack.name.as_str()); // update also changes the store - assert_eq!(old_john, PEOPLE.load(&store, b"john")?); - assert_eq!(new_jack, PEOPLE.load(&store, b"jack")?); + assert_eq!(old_john, PEOPLE.load(&store, &john_key)?); + assert_eq!(new_jack, PEOPLE.load(&store, &jack_key)?); // removing leaves us empty - PEOPLE.remove(&mut store, b"john"); - let empty = PEOPLE.may_load(&store, b"john")?; + PEOPLE.remove(&mut store, &john_key); + let empty = PEOPLE.may_load(&store, &john_key)?; assert_eq!(None, empty); Ok(()) @@ -462,21 +474,25 @@ mod test { let mut store = MockStorage::new(); // save and load on a composite key - let empty = ALLOWANCE.may_load(&store, (b"owner", b"spender"))?; + let empty = ALLOWANCE.may_load(&store, &(b"owner", b"spender".to_vec()))?; assert_eq!(None, empty); - ALLOWANCE.save(&mut store, (b"owner", b"spender"), &777)?; - let loaded = ALLOWANCE.load(&store, (b"owner", b"spender"))?; + ALLOWANCE.save(&mut store, &(b"owner", b"spender".to_vec()), &777)?; + let loaded = ALLOWANCE.load(&store, &(b"owner", b"spender".to_vec()))?; assert_eq!(777, loaded); // doesn't appear under other key (even if a concat would be the same) - let different = ALLOWANCE.may_load(&store, (b"owners", b"pender")).unwrap(); + let different = ALLOWANCE + .may_load(&store, &(b"owners", b"pender".to_vec())) + .unwrap(); assert_eq!(None, different); // simple update - ALLOWANCE.update(&mut store, (b"owner", b"spender"), |v| -> StdResult { - Ok(v.unwrap_or_default() + 222) - })?; - let loaded = ALLOWANCE.load(&store, (b"owner", b"spender"))?; + ALLOWANCE.update( + &mut store, + &(b"owner", b"spender".to_vec()), + |v| -> StdResult { Ok(v.unwrap_or_default() + 222) }, + )?; + let loaded = ALLOWANCE.load(&store, &(b"owner", b"spender".to_vec()))?; assert_eq!(999, loaded); Ok(()) @@ -491,7 +507,8 @@ mod test { }; // create a Path one time to use below - let john = PEOPLE.key(b"john"); + let john_key = b"john".to_vec(); + let john = PEOPLE.key(&john_key); // Use this just like an Item above let empty = john.may_load(&store)?; @@ -504,7 +521,7 @@ mod test { assert_eq!(None, empty); // same for composite keys, just use both parts in key() - let allow = ALLOWANCE.key((b"owner", b"spender")); + let allow = ALLOWANCE.key(&(b"owner", b"spender".to_vec())); allow.save(&mut store, &1234)?; let loaded = allow.load(&store)?; assert_eq!(1234, loaded); @@ -523,22 +540,24 @@ mod test { let mut store = MockStorage::new(); // save and load on two keys + let john_key = b"john".to_vec(); + let jim_key = b"jim".to_vec(); let data = Data { name: "John".to_string(), age: 32, }; - PEOPLE.save(&mut store, b"john", &data)?; + PEOPLE.save(&mut store, &john_key, &data)?; let data2 = Data { name: "Jim".to_string(), age: 44, }; - PEOPLE.save(&mut store, b"jim", &data2)?; + PEOPLE.save(&mut store, &jim_key, &data2)?; // iterate over them all let all: StdResult> = PEOPLE.range(&store, None, None, Order::Ascending).collect(); assert_eq!( all?, - vec![(b"jim".to_vec(), data2), (b"john".to_vec(), data.clone())] + vec![(jim_key, data2), (john_key.clone(), data.clone())] ); // or just show what is after jim @@ -550,12 +569,12 @@ mod test { Order::Ascending, ) .collect(); - assert_eq!(all?, vec![(b"john".to_vec(), data)]); + assert_eq!(all?, vec![(john_key, data)]); // save and load on three keys, one under different owner - ALLOWANCE.save(&mut store, (b"owner", b"spender"), &1000)?; - ALLOWANCE.save(&mut store, (b"owner", b"spender2"), &3000)?; - ALLOWANCE.save(&mut store, (b"owner2", b"spender"), &5000)?; + ALLOWANCE.save(&mut store, &(b"owner", b"spender".to_vec()), &1000)?; + ALLOWANCE.save(&mut store, &(b"owner", b"spender2".to_vec()), &3000)?; + ALLOWANCE.save(&mut store, &(b"owner2", b"spender".to_vec()), &5000)?; // get all under one key let all: StdResult> = ALLOWANCE diff --git a/packages/storage-plus/src/snapshot.rs b/packages/storage-plus/src/snapshot.rs index d8d0b4f37..0a8dc441f 100644 --- a/packages/storage-plus/src/snapshot.rs +++ b/packages/storage-plus/src/snapshot.rs @@ -59,7 +59,7 @@ impl<'a, K, T> SnapshotMap<'a, K, T> { pub fn add_checkpoint(&self, store: &mut dyn Storage, height: u64) -> StdResult<()> { self.checkpoints - .update::<_, StdError>(store, height.into(), |count| { + .update::<_, StdError>(store, &height.into(), |count| { Ok(count.unwrap_or_default() + 1) })?; Ok(()) @@ -68,13 +68,13 @@ impl<'a, K, T> SnapshotMap<'a, K, T> { pub fn remove_checkpoint(&self, store: &mut dyn Storage, height: u64) -> StdResult<()> { let count = self .checkpoints - .may_load(store, height.into())? + .may_load(store, &height.into())? .unwrap_or_default(); if count <= 1 { - self.checkpoints.remove(store, height.into()); + self.checkpoints.remove(store, &height.into()); Ok(()) } else { - self.checkpoints.save(store, height.into(), &(count - 1)) + self.checkpoints.save(store, &height.into(), &(count - 1)) } } } @@ -84,7 +84,7 @@ where T: Serialize + DeserializeOwned + Clone, K: PrimaryKey<'a> + Prefixer<'a>, { - pub fn key(&self, k: K) -> Path { + pub fn key(&self, k: &K) -> Path { self.primary.key(k) } @@ -128,44 +128,47 @@ where } /// load old value and store changelog - fn write_change(&self, store: &mut dyn Storage, k: K, height: u64) -> StdResult<()> { + fn write_change(&self, store: &mut dyn Storage, k: &K, height: u64) -> StdResult<()> { // if there is already data in the changelog for this key and block, do not write more if self .changelog - .may_load(store, (k.clone(), U64Key::from(height)))? + .may_load(store, &(k.clone(), U64Key::from(height)))? .is_some() { return Ok(()); } // otherwise, store the previous value - let old = self.primary.may_load(store, k.clone())?; - self.changelog - .save(store, (k, U64Key::from(height)), &ChangeSet { old }) + let old = self.primary.may_load(store, k)?; + self.changelog.save( + store, + &(k.clone(), U64Key::from(height)), + &ChangeSet { old }, + ) } - pub fn save(&self, store: &mut dyn Storage, k: K, data: &T, height: u64) -> StdResult<()> { + pub fn save(&self, store: &mut dyn Storage, k: &K, data: &T, height: u64) -> StdResult<()> { if self.should_checkpoint(store, &k)? { - self.write_change(store, k.clone(), height)?; + self.write_change(store, k, height)?; } self.primary.save(store, k, data) } - pub fn remove(&self, store: &mut dyn Storage, k: K, height: u64) -> StdResult<()> { + pub fn remove(&self, store: &mut dyn Storage, k: &K, height: u64) -> StdResult<()> { if self.should_checkpoint(store, &k)? { - self.write_change(store, k.clone(), height)?; + self.write_change(store, k, height)?; } self.primary.remove(store, k); Ok(()) } /// load will return an error if no data is set at the given key, or on parse error - pub fn load(&self, store: &dyn Storage, k: K) -> StdResult { + pub fn load(&self, store: &dyn Storage, k: &K) -> StdResult { self.primary.load(store, k) } /// may_load will parse the data stored at the key if present, returns Ok(None) if no data there. /// returns an error on issues parsing - pub fn may_load(&self, store: &dyn Storage, k: K) -> StdResult> { + pub fn may_load(&self, store: &dyn Storage, k: &K) -> StdResult> { self.primary.may_load(store, k) } @@ -177,7 +180,7 @@ where pub fn may_load_at_height( &self, store: &dyn Storage, - k: K, + k: &K, height: u64, ) -> StdResult> { self.assert_checkpointed(store, height)?; @@ -205,7 +208,7 @@ where let has = match self.strategy { Strategy::EveryBlock => true, Strategy::Never => false, - Strategy::Selected => self.checkpoints.may_load(store, height.into())?.is_some(), + Strategy::Selected => self.checkpoints.may_load(store, &height.into())?.is_some(), }; match has { true => Ok(()), @@ -222,7 +225,7 @@ where pub fn update( &self, store: &mut dyn Storage, - k: K, + k: &K, height: u64, action: A, ) -> Result @@ -230,7 +233,7 @@ where A: FnOnce(Option) -> Result, E: From, { - let input = self.may_load(store, k.clone())?; + let input = self.may_load(store, k)?; let output = action(input)?; self.save(store, k, &output, height)?; Ok(output) @@ -297,24 +300,24 @@ mod tests { // Values at beginning of 3 -> A = 5, B = 7 // Values at beginning of 5 -> A = 8, C = 13 fn init_data(map: &TestMap, storage: &mut dyn Storage) { - map.save(storage, b"A", &5, 1).unwrap(); - map.save(storage, b"B", &7, 2).unwrap(); + map.save(storage, &b"A".as_ref(), &5, 1).unwrap(); + map.save(storage, &b"B".as_ref(), &7, 2).unwrap(); // checkpoint 3 map.add_checkpoint(storage, 3).unwrap(); // also use update to set - to ensure this works - map.save(storage, b"C", &1, 3).unwrap(); - map.update(storage, b"A", 3, |_| -> StdResult { Ok(8) }) + map.save(storage, &b"C".as_ref(), &1, 3).unwrap(); + map.update(storage, &b"A".as_ref(), 3, |_| -> StdResult { Ok(8) }) .unwrap(); - map.remove(storage, b"B", 4).unwrap(); - map.save(storage, b"C", &13, 4).unwrap(); + map.remove(storage, &b"B".as_ref(), 4).unwrap(); + map.save(storage, &b"C".as_ref(), &13, 4).unwrap(); // checkpoint 5 map.add_checkpoint(storage, 5).unwrap(); - map.remove(storage, b"A", 5).unwrap(); - map.update(storage, b"D", 5, |_| -> StdResult { Ok(22) }) + map.remove(storage, &b"A".as_ref(), 5).unwrap(); + map.update(storage, &b"D".as_ref(), 5, |_| -> StdResult { Ok(22) }) .unwrap(); // and delete it later (unknown if all data present) map.remove_checkpoint(storage, 5).unwrap(); @@ -338,8 +341,8 @@ mod tests { ]; fn assert_final_values(map: &TestMap, storage: &dyn Storage) { - for (k, v) in FINAL_VALUES.iter().cloned() { - assert_eq!(v, map.may_load(storage, k).unwrap()); + for (k, v) in FINAL_VALUES.iter() { + assert_eq!(*v, map.may_load(storage, k).unwrap()); } } @@ -349,14 +352,16 @@ mod tests { height: u64, values: &[(&[u8], Option)], ) { - for (k, v) in values.iter().cloned() { - assert_eq!(v, map.may_load_at_height(storage, k, height).unwrap()); + for (k, v) in values.iter() { + assert_eq!(*v, map.may_load_at_height(storage, k, height).unwrap()); } } fn assert_missing_checkpoint(map: &TestMap, storage: &dyn Storage, height: u64) { for k in &[b"A", b"B", b"C", b"D"] { - assert!(map.may_load_at_height(storage, *k, height).is_err()); + assert!(map + .may_load_at_height(storage, &k.as_ref(), height) + .is_err()); } } @@ -401,57 +406,82 @@ mod tests { let mut storage = MockStorage::new(); println!("SETUP"); - EVERY.save(&mut storage, b"A", &5, 1).unwrap(); - EVERY.save(&mut storage, b"B", &7, 2).unwrap(); - EVERY.save(&mut storage, b"C", &2, 2).unwrap(); + EVERY.save(&mut storage, &b"A".as_ref(), &5, 1).unwrap(); + EVERY.save(&mut storage, &b"B".as_ref(), &7, 2).unwrap(); + EVERY.save(&mut storage, &b"C".as_ref(), &2, 2).unwrap(); // update and save - A query at 3 => 5, at 4 => 12 EVERY - .update(&mut storage, b"A", 3, |_| -> StdResult { Ok(9) }) + .update(&mut storage, &b"A".as_ref(), 3, |_| -> StdResult { + Ok(9) + }) .unwrap(); - EVERY.save(&mut storage, b"A", &12, 3).unwrap(); + EVERY.save(&mut storage, &b"A".as_ref(), &12, 3).unwrap(); assert_eq!( Some(5), - EVERY.may_load_at_height(&storage, b"A", 2).unwrap() + EVERY + .may_load_at_height(&storage, &b"A".as_ref(), 2) + .unwrap() ); assert_eq!( Some(5), - EVERY.may_load_at_height(&storage, b"A", 3).unwrap() + EVERY + .may_load_at_height(&storage, &b"A".as_ref(), 3) + .unwrap() ); assert_eq!( Some(12), - EVERY.may_load_at_height(&storage, b"A", 4).unwrap() + EVERY + .may_load_at_height(&storage, &b"A".as_ref(), 4) + .unwrap() ); // save and remove - B query at 4 => 7, at 5 => None - EVERY.save(&mut storage, b"B", &17, 4).unwrap(); - EVERY.remove(&mut storage, b"B", 4).unwrap(); + EVERY.save(&mut storage, &b"B".as_ref(), &17, 4).unwrap(); + EVERY.remove(&mut storage, &b"B".as_ref(), 4).unwrap(); assert_eq!( Some(7), - EVERY.may_load_at_height(&storage, b"B", 3).unwrap() + EVERY + .may_load_at_height(&storage, &b"B".as_ref(), 3) + .unwrap() ); assert_eq!( Some(7), - EVERY.may_load_at_height(&storage, b"B", 4).unwrap() + EVERY + .may_load_at_height(&storage, &b"B".as_ref(), 4) + .unwrap() + ); + assert_eq!( + None, + EVERY + .may_load_at_height(&storage, &b"B".as_ref(), 5) + .unwrap() ); - assert_eq!(None, EVERY.may_load_at_height(&storage, b"B", 5).unwrap()); // remove and update - C query at 5 => 2, at 6 => 16 - EVERY.remove(&mut storage, b"C", 5).unwrap(); + EVERY.remove(&mut storage, &b"C".as_ref(), 5).unwrap(); EVERY - .update(&mut storage, b"C", 5, |_| -> StdResult { Ok(16) }) + .update(&mut storage, &b"C".as_ref(), 5, |_| -> StdResult { + Ok(16) + }) .unwrap(); assert_eq!( Some(2), - EVERY.may_load_at_height(&storage, b"C", 4).unwrap() + EVERY + .may_load_at_height(&storage, &b"C".as_ref(), 4) + .unwrap() ); assert_eq!( Some(2), - EVERY.may_load_at_height(&storage, b"C", 5).unwrap() + EVERY + .may_load_at_height(&storage, &b"C".as_ref(), 5) + .unwrap() ); assert_eq!( Some(16), - EVERY.may_load_at_height(&storage, b"C", 6).unwrap() + EVERY + .may_load_at_height(&storage, &b"C".as_ref(), 6) + .unwrap() ); } }