Skip to content

Commit

Permalink
refactor: Streamline Cosmos-to-Polkadot type conversion and vice versa (
Browse files Browse the repository at this point in the history
#127)

* refactor: Streamline Cosmos-to-Polkadot type conversion and vice versa

* refactor: Define constants for Cosmos user and contract address lengths

* refactor: Replace length check with ensure macro for Cosmos address validation
  • Loading branch information
code0xff authored Jan 23, 2025
1 parent e03d9af commit 76f2190
Show file tree
Hide file tree
Showing 12 changed files with 106 additions and 100 deletions.
42 changes: 22 additions & 20 deletions frame/babel/src/cosmos/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ use bech32::{Bech32, Hrp};
use core::marker::PhantomData;
use np_babel::cosmos::{traits::ChainInfo, Address as CosmosAddress};
use np_multimap::traits::UniqueMultimap;
use pallet_cosmos_types::address::acc_address_from_bech32;
use pallet_cosmos_types::address::{
acc_address_from_bech32, AUTH_ADDRESS_LEN, CONTRACT_ADDRESS_LEN,
};
use pallet_cosmwasm::types::AccountIdOf;
use sp_core::{H160, H256};
use sp_runtime::traits::{AccountIdConversion, Convert};
use sp_runtime::traits::{AccountIdConversion, Convert, MaybeConvert, TryConvert};

pub struct AddressMapping<T>(PhantomData<T>);
impl<T> pallet_cosmos::AddressMapping<T::AccountId> for AddressMapping<T>
Expand All @@ -46,41 +48,41 @@ where
{
fn convert(account: AccountIdOf<T>) -> String {
let addresses = T::AddressMap::get(&account);
let address: Option<&CosmosAddress> = addresses.iter().find_map(|address| match address {
VarAddress::Cosmos(address) => Some(address),
_ => None,
});
let address_raw = match address {
Some(address) => address.as_ref(),
None => account.as_ref(),
};
let address_raw = addresses
.iter()
.find_map(|address| match address {
VarAddress::Cosmos(addr) => Some(addr.as_ref()),
_ => None,
})
.unwrap_or_else(|| account.as_ref());

let hrp = Hrp::parse(T::ChainInfo::bech32_prefix()).unwrap();
bech32::encode::<Bech32>(hrp, address_raw).unwrap()
}
}

impl<T> Convert<String, Result<AccountIdOf<T>, ()>> for AccountToAddr<T>
impl<T> TryConvert<String, AccountIdOf<T>> for AccountToAddr<T>
where
T: pallet_cosmwasm::Config + unify_account::Config<AccountId = AccountIdOf<T>>,
{
fn convert(address: String) -> Result<AccountIdOf<T>, ()> {
let (_hrp, address_raw) = acc_address_from_bech32(&address).map_err(|_| ())?;
Self::convert(address_raw)
fn try_convert(address: String) -> Result<AccountIdOf<T>, String> {
let (_hrp, data) = acc_address_from_bech32(&address).map_err(|_| address.clone())?;
Self::maybe_convert(data).ok_or(address)
}
}

impl<T> Convert<Vec<u8>, Result<AccountIdOf<T>, ()>> for AccountToAddr<T>
impl<T> MaybeConvert<Vec<u8>, AccountIdOf<T>> for AccountToAddr<T>
where
T: pallet_cosmwasm::Config + unify_account::Config<AccountId = AccountIdOf<T>>,
{
fn convert(address: Vec<u8>) -> Result<AccountIdOf<T>, ()> {
fn maybe_convert(address: Vec<u8>) -> Option<AccountIdOf<T>> {
match address.len() {
20 => {
AUTH_ADDRESS_LEN => {
let address = CosmosAddress::from(H160::from_slice(&address));
T::AddressMap::find_key(VarAddress::Cosmos(address)).ok_or(())
T::AddressMap::find_key(VarAddress::Cosmos(address))
},
32 => Ok(H256::from_slice(&address).into()),
_ => Err(()),
CONTRACT_ADDRESS_LEN => Some(H256::from_slice(&address).into()),
_ => None,
}
}
}
9 changes: 4 additions & 5 deletions frame/babel/src/cosmos/precompile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ use cosmwasm_vm::{
use cosmwasm_vm_wasmi::OwnedWasmiVM;
use frame_support::{
dispatch::{GetDispatchInfo, PostDispatchInfo},
PalletId,
ensure, PalletId,
};
use pallet_cosmos::AddressMapping;
use pallet_cosmos_types::address::acc_address_from_bech32;
use pallet_cosmos_types::address::{acc_address_from_bech32, AUTH_ADDRESS_LEN};
use pallet_cosmwasm::{
pallet_hook::PalletHook,
runtimes::vm::{CosmwasmVM, CosmwasmVMError},
Expand Down Expand Up @@ -95,9 +95,8 @@ where
let sender = vm.0.data().cosmwasm_message_info.sender.clone().into_string();
let (_hrp, address_raw) = acc_address_from_bech32(&sender)
.map_err(|_| CosmwasmVMError::AccountConvert)?;
if address_raw.len() != 20 {
return Err(CosmwasmVMError::AccountConvert);
}
ensure!(address_raw.len() == AUTH_ADDRESS_LEN, CosmwasmVMError::AccountConvert);

let origin = T::AddressMapping::into_account_id(H160::from_slice(&address_raw));

call.dispatch(Some(origin).into())
Expand Down
8 changes: 4 additions & 4 deletions frame/babel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ pub mod pallet {
types::{AssetIdOf, DenomOf},
AddressMapping as _,
};
use pallet_cosmos_types::address::acc_address_from_bech32;
use pallet_cosmos_types::address::{acc_address_from_bech32, AUTH_ADDRESS_LEN};
use pallet_cosmos_x_auth_signing::sign_verifiable_tx::traits::SigVerifiableTx;
use pallet_evm::{AddressMapping as _, FrameSystemAccountProvider};
use solana_sdk::transaction::VersionedTransaction;
Expand Down Expand Up @@ -196,14 +196,14 @@ pub mod pallet {
use cosmos_sdk_proto::traits::Message;
use cosmos_sdk_proto::cosmos::tx::v1beta1::Tx;
use pallet_cosmos::weights::WeightInfo;
use sp_runtime::traits::Convert;
use sp_runtime::traits::ConvertBack;
Tx::decode(&mut &tx_bytes[..])
.ok()
.and_then(|tx| tx.auth_info)
.and_then(|auth_info| auth_info.fee)
.map_or(<T as pallet_cosmos::Config>::WeightInfo::base_weight(), |fee| {
<T as pallet_cosmos::Config>::WeightToGas::convert(fee.gas_limit)
<T as pallet_cosmos::Config>::WeightToGas::convert_back(fee.gas_limit)
})
})]
pub fn cosmos_transact(
Expand All @@ -228,7 +228,7 @@ pub mod pallet {
let (_hrp, address_raw) =
acc_address_from_bech32(signer).map_err(|_| Error::<T>::InvalidTransaction)?;
ensure!(
address_raw.len() == 20 && address.to_vec() == address_raw,
address_raw.len() == AUTH_ADDRESS_LEN && address.to_vec() == address_raw,
Error::<T>::InvalidTransaction
);

Expand Down
24 changes: 12 additions & 12 deletions frame/babel/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ use pallet_solana::Pubkey;
use solana_sdk::hash::Hash;
use sp_core::{ConstU128, Pair, H256};
use sp_runtime::{
traits::{Convert, ConvertBack, IdentityLookup, TryConvert},
traits::{Convert, ConvertBack, IdentityLookup, TryConvert, TryConvertBack},
BoundedVec, BuildStorage,
};

Expand Down Expand Up @@ -192,17 +192,6 @@ impl context::traits::MinGasPrices for MinGasPrices {
}

pub struct AssetToDenom;
impl TryConvert<String, AssetId> for AssetToDenom {
fn try_convert(denom: String) -> Result<AssetId, String> {
if denom == NativeDenom::get() {
Ok(NativeAssetId::get())
} else {
let denom_raw: BoundedVec<u8, MaxDenomLimit> =
denom.as_bytes().to_vec().try_into().map_err(|_| denom.clone())?;
<Test as frame_babel::Config>::AssetMap::find_key(denom_raw).ok_or(denom.clone())
}
}
}
impl TryConvert<AssetId, String> for AssetToDenom {
fn try_convert(asset_id: AssetId) -> Result<String, AssetId> {
if asset_id == NativeAssetId::get() {
Expand All @@ -213,6 +202,17 @@ impl TryConvert<AssetId, String> for AssetToDenom {
}
}
}
impl TryConvertBack<AssetId, String> for AssetToDenom {
fn try_convert_back(denom: String) -> Result<AssetId, String> {
if denom == NativeDenom::get() {
Ok(NativeAssetId::get())
} else {
let denom_raw: BoundedVec<u8, MaxDenomLimit> =
denom.as_bytes().to_vec().try_into().map_err(|_| denom.clone())?;
<Test as frame_babel::Config>::AssetMap::find_key(denom_raw).ok_or(denom.clone())
}
}
}

pub struct MsgFilter;
impl Contains<Any> for MsgFilter {
Expand Down
24 changes: 12 additions & 12 deletions frame/cosmos/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use frame_support::{
use frame_system::{pallet_prelude::*, CheckWeight};
use nostd::prelude::*;
use pallet_cosmos_types::{
address::acc_address_from_bech32,
address::{acc_address_from_bech32, AUTH_ADDRESS_LEN},
context::traits::Context,
errors::{CosmosError, RootError},
events::traits::EventManager,
Expand All @@ -46,7 +46,7 @@ use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::H160;
use sp_runtime::{
traits::{Convert, DispatchInfoOf, Dispatchable},
traits::{Convert, ConvertBack, DispatchInfoOf, Dispatchable},
transaction_validity::ValidTransactionBuilder,
RuntimeDebug, SaturatedConversion,
};
Expand Down Expand Up @@ -85,7 +85,7 @@ where
T::SigVerifiableTx::fee_payer(&tx).map_err(|_| InvalidTransaction::Call)?;
let (_hrp, address_raw) = acc_address_from_bech32(&fee_payer)
.map_err(|_| InvalidTransaction::BadSigner)?;
ensure!(address_raw.len() == 20, InvalidTransaction::BadSigner);
ensure!(address_raw.len() == AUTH_ADDRESS_LEN, InvalidTransaction::BadSigner);

Ok(H160::from_slice(&address_raw))
};
Expand Down Expand Up @@ -152,7 +152,7 @@ pub mod pallet {
handler::PostDecorator,
};
use pallet_cosmos_x_auth_signing::sign_mode_handler::traits::SignModeHandler;
use sp_runtime::traits::{Convert, TryConvert};
use sp_runtime::traits::TryConvertBack;

#[pallet::pallet]
pub struct Pallet<T>(PhantomData<T>);
Expand Down Expand Up @@ -207,14 +207,14 @@ pub mod pallet {
type WeightInfo: WeightInfo;

/// Converter between Weight and Gas.
type WeightToGas: Convert<Weight, Gas> + Convert<Gas, Weight>;
type WeightToGas: ConvertBack<Weight, Gas>;

#[pallet::no_default]
type MinGasPrices: MinGasPrices;

/// Converter between AssetId and Denom.
#[pallet::no_default]
type AssetToDenom: TryConvert<Self::AssetId, String> + TryConvert<String, Self::AssetId>;
type AssetToDenom: TryConvertBack<Self::AssetId, String>;

/// Context for executing transactions.
type Context: Context;
Expand Down Expand Up @@ -271,8 +271,8 @@ pub mod pallet {
weight.ref_time()
}
}
impl Convert<Gas, Weight> for WeightToGas {
fn convert(gas: Gas) -> Weight {
impl ConvertBack<Weight, Gas> for WeightToGas {
fn convert_back(gas: Gas) -> Weight {
Weight::from_parts(gas, 0)
}
}
Expand Down Expand Up @@ -324,7 +324,7 @@ pub mod pallet {
.and_then(|tx| tx.auth_info)
.and_then(|auth_info| auth_info.fee)
.map_or(T::WeightInfo::base_weight(), |fee| {
T::WeightToGas::convert(fee.gas_limit)
T::WeightToGas::convert_back(fee.gas_limit)
})
})]
pub fn transact(origin: OriginFor<T>, tx_bytes: Vec<u8>) -> DispatchResultWithPostInfo {
Expand Down Expand Up @@ -381,12 +381,12 @@ impl<T: Config> Pallet<T> {
let mut ctx = T::Context::new(gas_limit);
Self::run_tx(&mut ctx, &tx).map_err(|e| {
Error::<T>::CosmosError(e)
.with_weight(T::WeightToGas::convert(ctx.gas_meter().consumed_gas()))
.with_weight(T::WeightToGas::convert_back(ctx.gas_meter().consumed_gas()))
})?;

T::PostHandler::post_handle(&mut ctx, &tx, false).map_err(|e| {
Error::<T>::CosmosError(e)
.with_weight(T::WeightToGas::convert(ctx.gas_meter().consumed_gas()))
.with_weight(T::WeightToGas::convert_back(ctx.gas_meter().consumed_gas()))
})?;

Self::deposit_event(Event::Executed {
Expand All @@ -396,7 +396,7 @@ impl<T: Config> Pallet<T> {
});

Ok(PostDispatchInfo {
actual_weight: Some(T::WeightToGas::convert(ctx.gas_meter().consumed_gas())),
actual_weight: Some(T::WeightToGas::convert_back(ctx.gas_meter().consumed_gas())),
pays_fee: Pays::Yes,
})
}
Expand Down
6 changes: 5 additions & 1 deletion frame/cosmos/types/src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use bech32::DecodeError;
use nostd::{
string::{String, ToString},
vec::Vec,
};

#[derive(Clone, PartialEq, Eq, Debug)]
pub enum Error {
DecodeError(bech32::DecodeError),
DecodeError(DecodeError),
}

pub const AUTH_ADDRESS_LEN: usize = 20;
pub const CONTRACT_ADDRESS_LEN: usize = 32;

pub fn acc_address_from_bech32(address: &str) -> Result<(String, Vec<u8>), Error> {
bech32::decode(address)
.map(|(hrp, data)| (hrp.to_string(), data))
Expand Down
8 changes: 4 additions & 4 deletions frame/cosmos/x/auth/src/fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use frame_support::{
use nostd::vec;
use pallet_cosmos::AddressMapping;
use pallet_cosmos_types::{
address::acc_address_from_bech32,
address::{acc_address_from_bech32, AUTH_ADDRESS_LEN},
coin::traits::Coins,
context::traits::MinGasPrices,
errors::{CosmosError, RootError},
Expand All @@ -41,7 +41,7 @@ use pallet_cosmos_types::{
use pallet_cosmos_x_auth_signing::sign_verifiable_tx::traits::SigVerifiableTx;
use sp_core::{Get, H160};
use sp_runtime::{
traits::{TryConvert, Zero},
traits::{TryConvertBack, Zero},
SaturatedConversion,
};

Expand Down Expand Up @@ -88,7 +88,7 @@ where

let (_hrp, address_raw) =
acc_address_from_bech32(&fee_payer).map_err(|_| RootError::InvalidAddress)?;
ensure!(address_raw.len() == 20, RootError::InvalidAddress);
ensure!(address_raw.len() == AUTH_ADDRESS_LEN, RootError::InvalidAddress);
let deduct_fees_from = T::AddressMapping::into_account_id(H160::from_slice(&address_raw));

if !fee.amount.is_empty() {
Expand Down Expand Up @@ -126,7 +126,7 @@ where

// TODO: Resolve imbalance
} else {
let asset_id = T::AssetToDenom::try_convert(amt.denom.clone())
let asset_id = T::AssetToDenom::try_convert_back(amt.denom.clone())
.map_err(|_| RootError::InsufficientFunds)?;
let _imbalance = T::Assets::withdraw(
asset_id,
Expand Down
8 changes: 4 additions & 4 deletions frame/cosmos/x/auth/src/sigverify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use nostd::vec::Vec;
use np_cosmos::traits::ChainInfo;
use pallet_cosmos::AddressMapping;
use pallet_cosmos_types::{
address::acc_address_from_bech32,
address::{acc_address_from_bech32, AUTH_ADDRESS_LEN},
any_match,
errors::{CosmosError, RootError},
handler::AnteDecorator,
Expand Down Expand Up @@ -63,7 +63,7 @@ where

let (_hrp, signer_addr_raw) =
acc_address_from_bech32(signer).map_err(|_| RootError::InvalidAddress)?;
ensure!(signer_addr_raw.len() == 20, RootError::InvalidAddress);
ensure!(signer_addr_raw.len() == AUTH_ADDRESS_LEN, RootError::InvalidAddress);
let who = T::AddressMapping::into_account_id(H160::from_slice(&signer_addr_raw));

let sequence = frame_system::Pallet::<T>::account_nonce(&who).saturated_into();
Expand Down Expand Up @@ -115,7 +115,7 @@ where

let (_hrp, signer_addr_raw) =
acc_address_from_bech32(&signer_data.address).map_err(|_| RootError::InvalidAddress)?;
ensure!(signer_addr_raw.len() == 20, RootError::InvalidAddress);
ensure!(signer_addr_raw.len() == AUTH_ADDRESS_LEN, RootError::InvalidAddress);

ensure!(H160::from_slice(&signer_addr_raw) == address, RootError::Unauthorized);

Expand Down Expand Up @@ -204,7 +204,7 @@ where
for signer in signers.iter() {
let (_hrp, address_raw) =
acc_address_from_bech32(signer).map_err(|_| RootError::InvalidAddress)?;
ensure!(address_raw.len() == 20, RootError::InvalidAddress);
ensure!(address_raw.len() == AUTH_ADDRESS_LEN, RootError::InvalidAddress);

let account = T::AddressMapping::into_account_id(H160::from_slice(&address_raw));
frame_system::pallet::Pallet::<T>::inc_account_nonce(account);
Expand Down
Loading

0 comments on commit 76f2190

Please sign in to comment.