Skip to content

Commit

Permalink
Improve on Mapping::contains + Migrate examples to new API (#1242)
Browse files Browse the repository at this point in the history
* Rename `Mapping::contains` to `Mapping::size`

* Add `Mapping::contains`

* Update examples for new `Mapping::contains` API

* Fix typo

* Implement `contains_storage` in off-chain testing `engine`

* Apply suggestions from code review

Co-authored-by: Alexander Gryaznov <hi@agryaznov.com>

Co-authored-by: Alexander Gryaznov <hi@agryaznov.com>
  • Loading branch information
cmichi and agryaznov committed May 18, 2022
1 parent 961c7ef commit 3f6befa
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 29 deletions.
11 changes: 11 additions & 0 deletions crates/engine/src/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ impl Engine {
}
}

/// Returns the size of the value stored in the contract storage at the key if any.
pub fn contains_storage(&mut self, key: &[u8; 32]) -> Option<u32> {
let callee = self.get_callee();
let account_id = AccountId::from_bytes(&callee[..]);

self.debug_info.inc_reads(account_id);
self.database
.get_from_contract_storage(&callee, key)
.map(|val| val.len() as u32)
}

/// Removes the storage entries at the given key.
pub fn clear_storage(&mut self, key: &[u8; 32]) {
let callee = self.get_callee();
Expand Down
6 changes: 2 additions & 4 deletions crates/env/src/engine/off_chain/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,10 +206,8 @@ impl EnvBackend for EnvInstance {
Ok(Some(decoded))
}

fn contract_storage_contains(&mut self, _key: &Key) -> Option<u32> {
unimplemented!(
"the off-chain env does not implement `seal_contains_storage`, yet"
)
fn contract_storage_contains(&mut self, key: &Key) -> Option<u32> {
self.engine.contains_storage(key.as_ref())
}

fn clear_contract_storage(&mut self, key: &Key) {
Expand Down
13 changes: 12 additions & 1 deletion crates/storage/src/lazy/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,24 @@ where
///
/// Returns `None` if no `value` exists at the given `key`.
#[inline]
pub fn contains<Q>(&self, key: Q) -> Option<u32>
pub fn size<Q>(&self, key: Q) -> Option<u32>
where
Q: scale::EncodeLike<K>,
{
ink_env::contract_storage_contains(&self.storage_key(&key))
}

/// Checks if a value is stored at the given `key` in the contract storage.
///
/// Returns `None` if no `value` exists at the given `key`.
#[inline]
pub fn contains<Q>(&self, key: Q) -> bool
where
Q: scale::EncodeLike<K>,
{
ink_env::contract_storage_contains(&self.storage_key(&key)).is_some()
}

/// Clears the value at `key` from storage.
pub fn remove<Q>(&self, key: Q)
where
Expand Down
2 changes: 1 addition & 1 deletion examples/dns/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ mod dns {
#[ink(message)]
pub fn register(&mut self, name: Hash) -> Result<()> {
let caller = self.env().caller();
if self.name_to_owner.get(&name).is_some() {
if self.name_to_owner.contains(&name) {
return Err(Error::NameAlreadyExists)
}

Expand Down
2 changes: 1 addition & 1 deletion examples/erc1155/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ mod erc1155 {

#[ink(message)]
fn is_approved_for_all(&self, owner: AccountId, operator: AccountId) -> bool {
self.approvals.get((&owner, &operator)).is_some()
self.approvals.contains((&owner, &operator))
}
}

Expand Down
10 changes: 5 additions & 5 deletions examples/erc721/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ mod erc721 {
..
} = self;

if token_owner.get(&id).is_none() {
if !token_owner.contains(&id) {
return Err(Error::TokenNotFound)
}

Expand All @@ -305,7 +305,7 @@ mod erc721 {
..
} = self;

if token_owner.get(&id).is_some() {
if token_owner.contains(&id) {
return Err(Error::TokenExists)
}

Expand Down Expand Up @@ -360,7 +360,7 @@ mod erc721 {
return Err(Error::NotAllowed)
};

if self.token_approvals.get(&id).is_some() {
if self.token_approvals.contains(&id) {
return Err(Error::CannotInsert)
} else {
self.token_approvals.insert(&id, to);
Expand All @@ -387,7 +387,7 @@ mod erc721 {

/// Gets an operator on other Account's behalf.
fn approved_for_all(&self, owner: AccountId, operator: AccountId) -> bool {
self.operator_approvals.get((&owner, &operator)).is_some()
self.operator_approvals.contains((&owner, &operator))
}

/// Returns true if the `AccountId` `from` is the owner of token `id`
Expand All @@ -405,7 +405,7 @@ mod erc721 {

/// Returns true if token `id` exists or false if it does not.
fn exists(&self, id: TokenId) -> bool {
self.token_owner.get(&id).is_some()
self.token_owner.contains(&id)
}
}

Expand Down
34 changes: 17 additions & 17 deletions examples/multisig/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ mod multisig {
pub fn revoke_confirmation(&mut self, trans_id: TransactionId) {
self.ensure_caller_is_owner();
let caller = self.env().caller();
if self.confirmations.get(&(trans_id, caller)).is_some() {
if self.confirmations.contains(&(trans_id, caller)) {
self.confirmations.remove(&(trans_id, caller));
let mut confirmation_count = self
.confirmation_count
Expand Down Expand Up @@ -601,7 +601,7 @@ mod multisig {
) -> ConfirmationStatus {
let mut count = self.confirmation_count.get(&transaction).unwrap_or(0);
let key = (transaction, confirmer);
let new_confirmation = self.confirmations.get(&key).is_none();
let new_confirmation = !self.confirmations.contains(&key);
if new_confirmation {
count += 1;
self.confirmations.insert(&key, &());
Expand Down Expand Up @@ -659,7 +659,7 @@ mod multisig {
fn clean_owner_confirmations(&mut self, owner: &AccountId) {
for trans_id in &self.transaction_list.transactions {
let key = (*trans_id, *owner);
if self.confirmations.get(&key).is_some() {
if self.confirmations.contains(&key) {
self.confirmations.remove(&key);
let mut count = self.confirmation_count.get(&trans_id).unwrap_or(0);
count -= 1;
Expand Down Expand Up @@ -696,12 +696,12 @@ mod multisig {

/// Panic if `owner` is not an owner,
fn ensure_owner(&self, owner: &AccountId) {
assert!(self.is_owner.get(owner).is_some());
assert!(self.is_owner.contains(owner));
}

/// Panic if `owner` is an owner.
fn ensure_no_owner(&self, owner: &AccountId) {
assert!(self.is_owner.get(owner).is_none());
assert!(!self.is_owner.contains(owner));
}
}

Expand Down Expand Up @@ -794,12 +794,12 @@ mod multisig {
assert_eq!(contract.owners.len(), 3);
assert_eq!(contract.requirement, 2);
assert!(contract.owners.iter().eq(owners.iter()));
assert!(contract.is_owner.get(&accounts.alice).is_some());
assert!(contract.is_owner.get(&accounts.bob).is_some());
assert!(contract.is_owner.get(&accounts.eve).is_some());
assert!(contract.is_owner.get(&accounts.charlie).is_none());
assert!(contract.is_owner.get(&accounts.django).is_none());
assert!(contract.is_owner.get(&accounts.frank).is_none());
assert!(contract.is_owner.contains(&accounts.alice));
assert!(contract.is_owner.contains(&accounts.bob));
assert!(contract.is_owner.contains(&accounts.eve));
assert!(!contract.is_owner.contains(&accounts.charlie));
assert!(!contract.is_owner.contains(&accounts.django));
assert!(!contract.is_owner.contains(&accounts.frank));
assert_eq!(contract.transaction_list.transactions.len(), 0);
}

Expand Down Expand Up @@ -831,7 +831,7 @@ mod multisig {
let owners = contract.owners.len();
contract.add_owner(accounts.frank);
assert_eq!(contract.owners.len(), owners + 1);
assert!(contract.is_owner.get(&accounts.frank).is_some());
assert!(contract.is_owner.contains(&accounts.frank));
assert_eq!(test::recorded_events().count(), 1);
}

Expand Down Expand Up @@ -861,7 +861,7 @@ mod multisig {
let owners = contract.owners.len();
contract.remove_owner(accounts.alice);
assert_eq!(contract.owners.len(), owners - 1);
assert!(contract.is_owner.get(&accounts.alice).is_none());
assert!(!contract.is_owner.contains(&accounts.alice));
assert_eq!(test::recorded_events().count(), 1);
}

Expand Down Expand Up @@ -891,8 +891,8 @@ mod multisig {
let owners = contract.owners.len();
contract.replace_owner(accounts.alice, accounts.django);
assert_eq!(contract.owners.len(), owners);
assert!(contract.is_owner.get(&accounts.alice).is_none());
assert!(contract.is_owner.get(&accounts.django).is_some());
assert!(!contract.is_owner.contains(&accounts.alice));
assert!(contract.is_owner.contains(&accounts.django));
assert_eq!(test::recorded_events().count(), 2);
}

Expand Down Expand Up @@ -1053,7 +1053,7 @@ mod multisig {
set_caller(accounts.alice);
contract.revoke_confirmation(0);
assert_eq!(test::recorded_events().count(), 3);
assert!(contract.confirmations.get(&(0, accounts.alice)).is_none());
assert!(!contract.confirmations.contains(&(0, accounts.alice)));
assert_eq!(contract.confirmation_count.get(&0).unwrap(), 0);
}

Expand All @@ -1064,7 +1064,7 @@ mod multisig {
set_caller(accounts.bob);
contract.revoke_confirmation(0);
assert_eq!(test::recorded_events().count(), 2);
assert!(contract.confirmations.get(&(0, accounts.alice)).is_some());
assert!(contract.confirmations.contains(&(0, accounts.alice)));
assert_eq!(contract.confirmation_count.get(&0).unwrap(), 1);
}

Expand Down

0 comments on commit 3f6befa

Please sign in to comment.