Skip to content

Commit

Permalink
feat: Add solana_transact to frame-babel (#118)
Browse files Browse the repository at this point in the history
* feat: Add Solana address handling to transfer method in frame-babel

* feat: Add solana_transact to frame-babel

* feat: Switch raw transaction deserialization from serde_json to bincode

* chore: Update Cargo.toml to conditionally include solana-sdk/std

Co-authored-by: Jeeyong Um <[email protected]>

* chore: Make bincode and pallet-solana dependencies optional

* feat: Replace serde_json with bincode for params in solana-runtime-api serializer

---------

Co-authored-by: Jeeyong Um <[email protected]>
  • Loading branch information
code0xff and conr2d authored Jan 9, 2025
1 parent 26a3136 commit 11a05ae
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 12 deletions.
14 changes: 13 additions & 1 deletion frame/babel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ workspace = true

[dependencies]
bech32 = { workspace = true, optional = true }
bincode = { workspace = true, optional = true }
cosmos-sdk-proto = { workspace = true, optional = true }
cosmwasm-std = { workspace = true, default-features = false, optional = true }
cosmwasm-vm = { workspace = true, default-features = false, optional = true }
Expand Down Expand Up @@ -41,11 +42,13 @@ pallet-evm-precompile-blake2 = { workspace = true, optional = true }
pallet-evm-precompile-bn128 = { workspace = true, optional = true }
pallet-evm-precompile-modexp = { workspace = true, optional = true }
pallet-evm-precompile-simple = { workspace = true, optional = true }
pallet-solana = { workspace = true, optional = true }
parity-scale-codec = { workspace = true }
precompile-utils = { workspace = true, optional = true }
scale-info = { workspace = true }
serde = { workspace = true, optional = true }
serde-json-wasm = { workspace = true, optional = true }
solana-sdk = { workspace = true, optional = true }
sp-core = { workspace = true }
sp-io = { workspace = true }
sp-runtime = { workspace = true }
Expand All @@ -72,6 +75,7 @@ pallet-multimap = { workspace = true, default-features = true }
default = ["std", "pallet"]
std = [
"bech32?/std",
"bincode?/std",
"cosmos-sdk-proto?/std",
"cosmwasm-std?/std",
"cosmwasm-vm?/std",
Expand Down Expand Up @@ -99,11 +103,13 @@ std = [
"pallet-evm-precompile-bn128?/std",
"pallet-evm-precompile-modexp?/std",
"pallet-evm-precompile-simple?/std",
"pallet-solana?/std",
"parity-scale-codec/std",
"precompile-utils?/std",
"scale-info/std",
"serde?/std",
"serde-json-wasm?/std",
"solana-sdk?/std",
"sp-core/std",
"sp-runtime/std",
]
Expand Down Expand Up @@ -140,11 +146,17 @@ ethereum = [
"precompile-utils",
]
nostr = ["np-babel/nostr"]
solana = ["np-babel/solana"]
solana = [
"bincode",
"np-babel/solana",
"pallet-solana",
"solana-sdk",
]
pallet = [
"cosmos",
"ethereum",
"np-babel/serde",
"solana",
]
runtime-benchmarks = [
"frame-support/runtime-benchmarks",
Expand Down
31 changes: 28 additions & 3 deletions frame/babel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,12 @@ pub mod pallet {
use pallet_cosmos_types::address::acc_address_from_bech32;
use pallet_cosmos_x_auth_signing::sign_verifiable_tx::traits::SigVerifiableTx;
use pallet_evm::{AddressMapping as _, FrameSystemAccountProvider};
use solana_sdk::transaction::VersionedTransaction;
use sp_core::{ecdsa, H256};
#[cfg(feature = "nostr")]
use sp_runtime::traits::AccountIdConversion;
use sp_runtime::traits::{
AtLeast32BitUnsigned, One, Saturating, StaticLookup, UniqueSaturatedInto,
AtLeast32BitUnsigned, ConvertBack, One, Saturating, StaticLookup, UniqueSaturatedInto,
};

type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;
Expand All @@ -83,6 +84,7 @@ pub mod pallet {
+ pallet_cosmos::Config<AssetId = <Self as pallet_assets::Config>::AssetId>
+ pallet_ethereum::Config
+ pallet_evm::Config<AccountProvider = FrameSystemAccountProvider<Self>>
+ pallet_solana::Config
{
type AddressMap: UniqueMultimap<Self::AccountId, VarAddress>;
type AssetMap: UniqueMap<AssetIdOf<Self>, DenomOf<Self>>;
Expand Down Expand Up @@ -139,9 +141,12 @@ pub mod pallet {
impl<T: Config> Pallet<T>
where
OriginFor<T>: Into<Result<pallet_ethereum::RawOrigin, OriginFor<T>>>
+ Into<Result<pallet_cosmos::RawOrigin, OriginFor<T>>>,
+ Into<Result<pallet_cosmos::RawOrigin, OriginFor<T>>>
+ Into<Result<pallet_solana::RawOrigin, OriginFor<T>>>,
T::AccountId: TryInto<ecdsa::Public> + From<H256>,
T::RuntimeOrigin: From<pallet_ethereum::RawOrigin> + From<pallet_cosmos::RawOrigin>,
T::RuntimeOrigin: From<pallet_ethereum::RawOrigin>
+ From<pallet_cosmos::RawOrigin>
+ From<pallet_solana::RawOrigin>,
{
#[pallet::call_index(0)]
#[pallet::weight({
Expand Down Expand Up @@ -233,6 +238,25 @@ pub mod pallet {
pallet_cosmos::Pallet::<T>::transact(origin, tx_bytes)
}

// TODO: Need to adjust the call_index and weight
#[pallet::call_index(4)]
#[pallet::weight({ 1_000 })]
pub fn solana_transact(
origin: OriginFor<T>,
transaction: Vec<u8>,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
let pubkey = <T as pallet_solana::Config>::AccountIdConversion::convert_back(who);

let transaction: VersionedTransaction =
bincode::deserialize(&transaction).map_err(|_| Error::<T>::InvalidTransaction)?;

let origin =
T::RuntimeOrigin::from(pallet_solana::RawOrigin::SolanaTransaction(pubkey));

pallet_solana::Pallet::<T>::transact(origin, transaction)
}

#[pallet::call_index(2)]
#[pallet::weight({
use pallet_assets::weights::WeightInfo;
Expand Down Expand Up @@ -304,6 +328,7 @@ pub mod pallet {
#[cfg(feature = "nostr")]
VarAddress::Nostr(ref address) =>
T::AddressMap::find_key(&dest).unwrap_or(address.into_account_truncating()),
VarAddress::Solana(address) => H256::from(address).into(),
_ => unreachable!(),
};

Expand Down
45 changes: 42 additions & 3 deletions frame/babel/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,18 @@ use pallet_cosmos_x_wasm::msgs::{
MsgStoreCodeHandler, MsgUpdateAdminHandler,
};
use pallet_cosmwasm::instrument::CostRules;
use pallet_solana::Pubkey;
use solana_sdk::hash::Hash;
use sp_core::{ConstU128, Pair, H256};
use sp_runtime::{
traits::{IdentityLookup, TryConvert},
traits::{Convert, ConvertBack, IdentityLookup, TryConvert},
BoundedVec, BuildStorage,
};

pub type AccountId = AccountId32<MultiSigner>;
pub type Balance = u128;
pub type AssetId = u32;
pub type Hash = H256;
pub type Blockhash = H256;

#[frame_support::runtime]
mod runtime {
Expand Down Expand Up @@ -115,6 +117,9 @@ mod runtime {
#[runtime::pallet_index(41)]
pub type Cosmwasm = pallet_cosmwasm;

#[runtime::pallet_index(50)]
pub type Solana = pallet_solana;

#[runtime::pallet_index(100)]
pub type Babel = frame_babel;
}
Expand Down Expand Up @@ -265,7 +270,7 @@ impl pallet_cosmos::Config for Test {
parameter_types! {
pub const CosmwasmPalletId: PalletId = PalletId(*b"cosmwasm");
pub const MaxContractLabelSize: u32 = 64;
pub const MaxContractTrieIdSize: u32 = Hash::len_bytes() as u32;
pub const MaxContractTrieIdSize: u32 = Blockhash::len_bytes() as u32;
pub const MaxInstantiateSaltSize: u32 = 128;
pub const MaxFundsAssets: u32 = 32;
pub const CodeTableSizeLimit: u32 = 4096;
Expand Down Expand Up @@ -323,6 +328,40 @@ impl pallet_cosmwasm::Config for Test {
type NativeDenom = NativeDenom;
}

pub struct AccountIdConversion;
impl Convert<Pubkey, AccountId> for AccountIdConversion {
fn convert(pubkey: Pubkey) -> AccountId {
AccountId::new(pubkey.to_bytes())
}
}

impl ConvertBack<Pubkey, AccountId> for AccountIdConversion {
fn convert_back(account_id: AccountId) -> Pubkey {
Pubkey::from(<[u8; 32]>::from(account_id))
}
}

pub struct HashConversion;
impl Convert<Hash, Blockhash> for HashConversion {
fn convert(hash: Hash) -> Blockhash {
Blockhash::from(hash.to_bytes())
}
}
impl ConvertBack<Hash, Blockhash> for HashConversion {
fn convert_back(hash: Blockhash) -> Hash {
Hash::new_from_array(hash.0)
}
}

#[derive_impl(pallet_solana::config_preludes::TestDefaultConfig)]
impl pallet_solana::Config for Test {
type AccountIdConversion = AccountIdConversion;
type HashConversion = HashConversion;
type Balance = <Self as pallet_balances::Config>::Balance;
type Currency = Balances;
type DecimalMultiplier = ConstU128<1_000_000_000>;
}

#[derive_impl(pallet_multimap::config_preludes::TestDefaultConfig)]
impl pallet_multimap::Config<Instance1> for Test {
type Key = AccountId;
Expand Down
4 changes: 2 additions & 2 deletions frame/solana/runtime-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ repository = { workspace = true }
publish = false

[dependencies]
bincode = { workspace = true, default-features = false }
frame-support = { workspace = true, default-features = false }
nostd = { workspace = true, features = ["alloc"] }
pallet-solana = { workspace = true, default-features = false }
Expand All @@ -18,7 +19,6 @@ scale-info = { workspace = true, default-features = false, features = [
"derive",
] }
serde = { workspace = true, default-features = false }
serde_json = { workspace = true, default-features = false }
solana-compute-budget = { workspace = true, default-features = false }
solana-inline-spl = { workspace = true, default-features = false }
solana-rpc-client-api = { workspace = true, default-features = false }
Expand All @@ -28,12 +28,12 @@ sp-api = { workspace = true, default-features = false }
[features]
default = ["std"]
std = [
"bincode/std",
"frame-support/std",
"pallet-solana/std",
"parity-scale-codec/std",
"scale-info/std",
"serde/std",
"serde_json/std",
"solana-compute-budget/std",
"solana-inline-spl/std",
"solana-rpc-client-api/std",
Expand Down
4 changes: 2 additions & 2 deletions frame/solana/runtime-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ where
O: serde::Serialize + Send + Sync,
{
fn call_raw(params: Vec<u8>) -> Result<Vec<u8>, Error> {
let input: I = serde_json::from_slice(&params).map_err(|_| Error::ParseError)?;
let input: I = bincode::deserialize(&params).map_err(|_| Error::ParseError)?;
let output = Self::call(input)?;
serde_json::to_vec(&output).map_err(|_| Error::ParseError)
bincode::serialize(&output).map_err(|_| Error::ParseError)
}

fn call(input: I) -> Result<O, Error>;
Expand Down
2 changes: 1 addition & 1 deletion frame/solana/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ pub mod pallet {
#[pallet::config(with_default)]
pub trait Config: frame_system::Config + pallet_timestamp::Config {
#[pallet::no_default]
type AccountIdConversion: Convert<Pubkey, Self::AccountId>;
type AccountIdConversion: ConvertBack<Pubkey, Self::AccountId>;

#[pallet::no_default]
type HashConversion: ConvertBack<Hash, Self::Hash>;
Expand Down
6 changes: 6 additions & 0 deletions frame/solana/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ impl Convert<Pubkey, AccountId> for AccountIdConversion {
}
}

impl ConvertBack<Pubkey, AccountId> for AccountIdConversion {
fn convert_back(account_id: AccountId) -> Pubkey {
Pubkey::from(<[u8; 32]>::from(account_id))
}
}

pub struct HashConversion;
impl Convert<Hash, Blockhash> for HashConversion {
fn convert(hash: Hash) -> Blockhash {
Expand Down

0 comments on commit 11a05ae

Please sign in to comment.