From f261c23aecca141c2aa3572f00ae80cd25c880cc Mon Sep 17 00:00:00 2001 From: Jeeyong Um Date: Mon, 14 Oct 2024 14:09:26 +0900 Subject: [PATCH] refactor: Use EncodeLike args for Multimap traits (#77) --- frame/babel/src/cosmos/address.rs | 2 +- frame/babel/src/extensions/unify_account.rs | 4 +- frame/babel/src/lib.rs | 2 +- frame/multimap/src/traits.rs | 84 +++++++++++++-------- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/frame/babel/src/cosmos/address.rs b/frame/babel/src/cosmos/address.rs index 615f0a6a..11581911 100644 --- a/frame/babel/src/cosmos/address.rs +++ b/frame/babel/src/cosmos/address.rs @@ -45,7 +45,7 @@ where T: pallet_cosmwasm::Config + unify_account::Config, { fn convert(account: AccountIdOf) -> String { - let addresses = T::AddressMap::get(account.clone()); + let addresses = T::AddressMap::get(&account); let address: Option<&CosmosAddress> = addresses.iter().find_map(|address| match address { VarAddress::Cosmos(address) => Some(address), _ => None, diff --git a/frame/babel/src/extensions/unify_account.rs b/frame/babel/src/extensions/unify_account.rs index 732f177c..b0b275c4 100644 --- a/frame/babel/src/extensions/unify_account.rs +++ b/frame/babel/src/extensions/unify_account.rs @@ -63,7 +63,7 @@ impl UnifyAccount { let address = EthereumAddress::from(public); let interim = address.clone().into_account_truncating(); T::DrainBalance::drain_balance(&interim, who)?; - T::AddressMap::try_insert(who.clone(), VarAddress::Ethereum(address)) + T::AddressMap::try_insert(who, VarAddress::Ethereum(address)) .map_err(|_| "account unification failed: ethereum")?; } #[cfg(feature = "cosmos")] @@ -71,7 +71,7 @@ impl UnifyAccount { let address = CosmosAddress::from(public); let interim = address.clone().into_account_truncating(); T::DrainBalance::drain_balance(&interim, who)?; - T::AddressMap::try_insert(who.clone(), VarAddress::Cosmos(address)) + T::AddressMap::try_insert(who, VarAddress::Cosmos(address)) .map_err(|_| "account unification failed: cosmos")?; } } diff --git a/frame/babel/src/lib.rs b/frame/babel/src/lib.rs index 16c28049..5c51c6ae 100644 --- a/frame/babel/src/lib.rs +++ b/frame/babel/src/lib.rs @@ -126,7 +126,7 @@ pub mod pallet { transaction: Vec, ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - let address = T::AddressMap::get(who.clone()) + let address = T::AddressMap::get(&who) .iter() .find_map(|address| match address { VarAddress::Ethereum(address) => Some(address.clone()), diff --git a/frame/multimap/src/traits.rs b/frame/multimap/src/traits.rs index 89ac9be2..88719dfa 100644 --- a/frame/multimap/src/traits.rs +++ b/frame/multimap/src/traits.rs @@ -19,31 +19,44 @@ use crate::*; use alloc::collections::BTreeSet; use frame_support::ensure; +use parity_scale_codec::{Codec, EncodeLike, FullCodec}; + +fn transmute, R: Codec>(value: T) -> R { + value.using_encoded(|encoded| R::decode(&mut &encoded[..]).expect("Decoding failed")) +} /// Unique multimap whose values are unique across all keys. -pub trait UniqueMultimap { +pub trait UniqueMultimap { type Error; /// Tries to insert a value into the multimap. - fn try_insert(key: K, value: V) -> Result; + fn try_insert, ValArg: EncodeLike>( + key: KeyArg, + value: ValArg, + ) -> Result; /// Gets all values for a key. - fn get(key: K) -> BTreeSet; + fn get>(key: KeyArg) -> BTreeSet; /// Finds the key for a value. - fn find_key(value: V) -> Option; + fn find_key>(value: ValArg) -> Option; /// Removes a value from the multimap. - fn remove(key: K, value: V) -> bool; + fn remove, ValArg: EncodeLike>(key: KeyArg, value: ValArg) -> bool; /// Removes all values for a key. - fn remove_all(key: K) -> bool; + fn remove_all>(key: KeyArg) -> bool; } impl, I: 'static> UniqueMultimap for Pallet { type Error = Error; - fn try_insert(key: T::Key, value: T::Value) -> Result> { + fn try_insert, V: EncodeLike>( + key: K, + value: V, + ) -> Result> { + let key = transmute(key); + let value = transmute(value); Map::::try_mutate(&key, |values| { ensure!( Index::::get(&value).filter(|k| *k != key).is_none(), @@ -53,57 +66,66 @@ impl, I: 'static> UniqueMultimap for Pallet .try_insert(value.clone()) .inspect(|ok| { if *ok { - Index::::insert(&value, &key); + Index::::insert(value, key.clone()); } }) .map_err(|_| Error::::CapacityOverflow) }) } - fn get(key: T::Key) -> BTreeSet { - Map::::get(&key).into() + fn get>(key: K) -> BTreeSet { + Map::::get(key).into() } - fn find_key(value: T::Value) -> Option { - Index::::get(&value) + fn find_key>(value: V) -> Option { + Index::::get(value) } - fn remove(key: T::Key, value: T::Value) -> bool { - Map::::try_mutate(&key, |values| -> Result { - Ok(values.remove(&value).then(|| Index::::remove(&value)).is_some()) + fn remove, V: EncodeLike>(key: K, value: V) -> bool { + let value = transmute(value); + Map::::try_mutate(key, |values| -> Result { + Ok(values.remove(&value).then(|| Index::::remove(value)).is_some()) }) .unwrap_or(false) } - fn remove_all(key: T::Key) -> bool { - Map::::take(&key).into_iter().fold(false, |_, value| { - Index::::remove(&value); + fn remove_all>(key: K) -> bool { + Map::::take(key).into_iter().fold(false, |_, value| { + Index::::remove(value); true }) } } /// Unique map whose the value is unique across all keys. -pub trait UniqueMap { +pub trait UniqueMap { type Error; /// Tries to insert a value into the map. - fn try_insert(key: K, value: V) -> Result; + fn try_insert, ValArg: EncodeLike>( + key: KeyArg, + value: ValArg, + ) -> Result; /// Gets the value for a key. - fn get(key: K) -> Option; + fn get>(key: KeyArg) -> Option; /// Finds the key for a value. - fn find_key(value: V) -> Option; + fn find_key>(value: ValArg) -> Option; /// Removes a value from the map. - fn remove(key: K); + fn remove>(key: KeyArg); } impl, I: 'static> UniqueMap for Pallet { type Error = Error; - fn try_insert(key: T::Key, value: T::Value) -> Result> { + fn try_insert, V: EncodeLike>( + key: K, + value: V, + ) -> Result> { + let key = transmute(key); + let value = transmute(value); Map::::try_mutate(&key, |values| { ensure!( Index::::get(&value).filter(|k| *k != key).is_none(), @@ -113,21 +135,21 @@ impl, I: 'static> UniqueMap for Pallet { *values = BTreeSet::from([value.clone()]) .try_into() .map_err(|_| Error::::CapacityOverflow)?; - Index::::insert(&value, &key); + Index::::insert(value, key.clone()); Ok(true) }) } - fn get(key: T::Key) -> Option { - Map::::get(&key).first().cloned() + fn get>(key: K) -> Option { + Map::::get(key).first().cloned() } - fn find_key(value: T::Value) -> Option { - Index::::get(&value) + fn find_key>(value: V) -> Option { + Index::::get(value) } - fn remove(key: T::Key) { - Map::::remove(&key); + fn remove>(key: K) { + Map::::remove(key); } }