From 50c04b265ca331086e3370bcd15fca3a6f891cde Mon Sep 17 00:00:00 2001 From: Shaun Wang Date: Wed, 26 Jul 2023 21:17:27 +1200 Subject: [PATCH] Benchmarks and mock. --- Cargo.lock | 6 +- pallets/ethereum-checked/src/lib.rs | 2 +- pallets/xvm/Cargo.toml | 10 +- pallets/xvm/src/benchmarking.rs | 78 +++++++++++ pallets/xvm/src/lib.rs | 33 +++-- pallets/xvm/src/mock.rs | 207 ++++++++++++++++++++++++++++ precompiles/xvm/src/mock.rs | 4 +- primitives/src/xvm.rs | 4 +- runtime/local/src/lib.rs | 2 + runtime/shibuya/Cargo.toml | 1 + runtime/shibuya/src/lib.rs | 3 + 11 files changed, 326 insertions(+), 24 deletions(-) create mode 100644 pallets/xvm/src/benchmarking.rs create mode 100644 pallets/xvm/src/mock.rs diff --git a/Cargo.lock b/Cargo.lock index 41d2040ba5..dedb95240f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8045,17 +8045,21 @@ name = "pallet-xvm" version = "0.2.2" dependencies = [ "astar-primitives", + "fp-evm", "frame-benchmarking", "frame-support", "frame-system", "log", + "pallet-balances", "pallet-contracts", - "pallet-ethereum-checked", "pallet-evm", + "pallet-insecure-randomness-collective-flip", + "pallet-timestamp", "parity-scale-codec", "scale-info", "serde", "sp-core", + "sp-io", "sp-runtime", "sp-std", ] diff --git a/pallets/ethereum-checked/src/lib.rs b/pallets/ethereum-checked/src/lib.rs index 7ac4f0320b..c627f141b8 100644 --- a/pallets/ethereum-checked/src/lib.rs +++ b/pallets/ethereum-checked/src/lib.rs @@ -20,7 +20,7 @@ //! //! ## Overview //! -//! A `pallet-ethererum` like pallet that execute transactions from checked source, +//! A `pallet-ethereum like pallet that execute transactions from checked source, //! like XCM remote call, cross-VM call, etc. Only `Call` transactions are supported //! (no `Create`). //! diff --git a/pallets/xvm/Cargo.toml b/pallets/xvm/Cargo.toml index 8d5213d225..6121f5657a 100644 --- a/pallets/xvm/Cargo.toml +++ b/pallets/xvm/Cargo.toml @@ -30,9 +30,13 @@ pallet-contracts = { workspace = true } # Astar astar-primitives = { workspace = true } -pallet-ethereum-checked = { workspace = true } [dev-dependencies] +sp-io = { workspace = true } +fp-evm = { workspace = true } +pallet-timestamp = { workspace = true, features = ["std"] } +pallet-balances = { workspace = true, features = ["std"] } +pallet-insecure-randomness-collective-flip = { workspace = true, features = ["std"] } [features] default = ["std"] @@ -43,22 +47,20 @@ std = [ "frame-system/std", "pallet-contracts/std", "pallet-evm/std", + "pallet-insecure-randomness-collective-flip/std", "scale-info/std", "serde", "sp-core/std", "sp-runtime/std", "sp-std/std", "astar-primitives/std", - "pallet-ethereum-checked/std", ] runtime-benchmarks = [ "frame-benchmarking", - "pallet-ethereum-checked/runtime-benchmarks", ] try-runtime = [ "frame-support/try-runtime", "pallet-contracts/try-runtime", "pallet-evm/try-runtime", - "pallet-ethereum-checked/try-runtime", ] diff --git a/pallets/xvm/src/benchmarking.rs b/pallets/xvm/src/benchmarking.rs new file mode 100644 index 0000000000..e013422135 --- /dev/null +++ b/pallets/xvm/src/benchmarking.rs @@ -0,0 +1,78 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +use super::*; + +use frame_benchmarking::v2::*; +use parity_scale_codec::Encode; +use sp_core::H160; + +#[benchmarks] +mod benchmarks { + use super::*; + + #[benchmark] + fn evm_call_without_execution() { + let context = Context { + source_vm_id: VmId::Wasm, + weight_limit: Weight::from_parts(1_000_000, 1_000_000), + }; + let vm_id = VmId::Evm; + let source = whitelisted_caller(); + let target = H160::repeat_byte(1).encode(); + let input = vec![1, 2, 3]; + + #[block] + { + Pallet::::call_without_execution(context, vm_id, source, target, input).unwrap(); + } + } + + #[benchmark] + fn wasm_call_without_execution() { + let context = Context { + source_vm_id: VmId::Evm, + weight_limit: Weight::from_parts(1_000_000, 1_000_000), + }; + let vm_id = VmId::Wasm; + let source = whitelisted_caller(); + let target = whitelisted_caller::().encode(); + let input = vec![1, 2, 3]; + + #[block] + { + Pallet::::call_without_execution(context, vm_id, source, target, input).unwrap(); + } + } + + impl_benchmark_test_suite!( + Pallet, + crate::benchmarking::tests::new_test_ext(), + crate::mock::TestRuntime, + ); +} + +#[cfg(test)] +mod tests { + use crate::mock; + use sp_io::TestExternalities; + + pub fn new_test_ext() -> TestExternalities { + mock::ExtBuilder::default().build() + } +} diff --git a/pallets/xvm/src/lib.rs b/pallets/xvm/src/lib.rs index 789d5b4821..e5927c2647 100644 --- a/pallets/xvm/src/lib.rs +++ b/pallets/xvm/src/lib.rs @@ -42,9 +42,15 @@ use astar_primitives::{ ethereum_checked::{ AccountMapping, CheckedEthereumTransact, CheckedEthereumTx, MAX_ETHEREUM_TX_INPUT_SIZE, }, - xvm::{CallError, CallErrorWithWeight, CallInfo, Context, VmId, XvmCall, XvmCallResult}, + xvm::{CallError, CallErrorWithWeight, CallInfo, CallResult, Context, VmId, XvmCall}, }; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; + +#[cfg(test)] +mod mock; + pub use pallet::*; #[frame_support::pallet] @@ -55,12 +61,11 @@ pub mod pallet { pub struct Pallet(PhantomData); #[pallet::config] - pub trait Config: - frame_system::Config - + pallet_evm::Config - + pallet_ethereum_checked::Config - + pallet_contracts::Config - { + pub trait Config: frame_system::Config + pallet_contracts::Config { + /// Mapping from `Account` to `H160`. + type AccountMapping: AccountMapping; + /// Mapping from Ethereum gas to Substrate weight. + type GasWeightMapping: GasWeightMapping; /// `CheckedEthereumTransact` implementation. type EthereumTransact: CheckedEthereumTransact; } @@ -73,7 +78,7 @@ impl XvmCall for Pallet { source: T::AccountId, target: Vec, input: Vec, - ) -> XvmCallResult { + ) -> CallResult { Pallet::::do_call(context, vm_id, source, target, input, false) } } @@ -89,7 +94,7 @@ impl Pallet { target: Vec, input: Vec, skip_execution: bool, - ) -> XvmCallResult { + ) -> CallResult { ensure!( context.source_vm_id != vm_id, CallErrorWithWeight { @@ -98,7 +103,7 @@ impl Pallet { } ); - match context.source_vm_id { + match vm_id { VmId::Evm => Pallet::::evm_call(context, source, target, input, skip_execution), VmId::Wasm => Pallet::::wasm_call(context, source, target, input, skip_execution), } @@ -110,7 +115,7 @@ impl Pallet { target: Vec, input: Vec, skip_execution: bool, - ) -> XvmCallResult { + ) -> CallResult { log::trace!( target: "xvm::evm_call", "Calling EVM: {:?} {:?}, {:?}, {:?}", @@ -174,7 +179,7 @@ impl Pallet { target: Vec, input: Vec, skip_execution: bool, - ) -> XvmCallResult { + ) -> CallResult { log::trace!( target: "xvm::wasm_call", "Calling WASM: {:?} {:?}, {:?}, {:?}", @@ -226,13 +231,13 @@ impl Pallet { } #[cfg(feature = "runtime-benchmarks")] - pub fn xvm_call_without_execution( + pub fn call_without_execution( context: Context, vm_id: VmId, source: T::AccountId, target: Vec, input: Vec, - ) -> XvmCallResult { + ) -> CallResult { Self::do_call(context, vm_id, source, target, input, true) } } diff --git a/pallets/xvm/src/mock.rs b/pallets/xvm/src/mock.rs new file mode 100644 index 0000000000..2c06bc4d63 --- /dev/null +++ b/pallets/xvm/src/mock.rs @@ -0,0 +1,207 @@ +// This file is part of Astar. + +// Copyright (C) 2019-2023 Stake Technologies Pte.Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later + +// Astar is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Astar is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Astar. If not, see . + +#![cfg(test)] + +use super::*; +use crate as pallet_xvm; + +use fp_evm::{CallInfo as EvmCallInfo, ExitReason, ExitSucceed}; +use frame_support::{ + construct_runtime, + dispatch::{DispatchErrorWithPostInfo, PostDispatchInfo}, + parameter_types, + sp_io::TestExternalities, + traits::{ConstBool, ConstU128, ConstU64, Nothing}, + weights::Weight, +}; +use sp_core::{H160, H256}; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + AccountId32, +}; + +parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max(Weight::from_parts(1024, 0)); +} + +impl frame_system::Config for TestRuntime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type RuntimeCall = RuntimeCall; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_balances::Config for TestRuntime { + type MaxLocks = ConstU32<4>; + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU128<2>; + type AccountStore = System; + type WeightInfo = (); +} + +impl pallet_timestamp::Config for TestRuntime { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<3>; + type WeightInfo = (); +} + +impl pallet_insecure_randomness_collective_flip::Config for TestRuntime {} + +parameter_types! { + pub const DepositPerItem: Balance = 1_000; + pub const DepositPerByte: Balance = 1_000; + pub DeletionWeightLimit: Weight = Weight::from_parts(u64::MAX, u64::MAX); + pub Schedule: pallet_contracts::Schedule = Default::default(); +} + +impl pallet_contracts::Config for TestRuntime { + type Time = Timestamp; + type Randomness = RandomnessCollectiveFlip; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type CallFilter = Nothing; + type DepositPerItem = DepositPerItem; + type DepositPerByte = DepositPerByte; + type CallStack = [pallet_contracts::Frame; 5]; + type WeightPrice = (); + type WeightInfo = pallet_contracts::weights::SubstrateWeight; + type ChainExtension = (); + type DeletionQueueDepth = ConstU32<128>; + type DeletionWeightLimit = DeletionWeightLimit; + type Schedule = Schedule; + type AddressGenerator = pallet_contracts::DefaultAddressGenerator; + type MaxCodeLen = ConstU32<{ 123 * 1024 }>; + type MaxStorageKeyLen = ConstU32<128>; + type UnsafeUnstableInterface = ConstBool; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; +} + +pub struct HashedAccountMapping; +impl astar_primitives::ethereum_checked::AccountMapping for HashedAccountMapping { + fn into_h160(account_id: AccountId) -> H160 { + let data = (b"evm:", account_id); + return H160::from_slice(&data.using_encoded(sp_io::hashing::blake2_256)[0..20]); + } +} + +pub struct MockEthereumTransact; +impl CheckedEthereumTransact for MockEthereumTransact { + fn xvm_transact( + _source: H160, + _checked_tx: CheckedEthereumTx, + ) -> Result<(PostDispatchInfo, EvmCallInfo), DispatchErrorWithPostInfo> { + Ok(( + PostDispatchInfo { + actual_weight: Default::default(), + pays_fee: Default::default(), + }, + EvmCallInfo { + exit_reason: ExitReason::Succeed(ExitSucceed::Returned), + value: Default::default(), + used_gas: Default::default(), + logs: Default::default(), + }, + )) + } +} + +pub struct MockGasWeightMapping; +impl GasWeightMapping for MockGasWeightMapping { + fn gas_to_weight(gas: u64, _without_base_weight: bool) -> Weight { + Weight::from_parts(gas, 0) + } + fn weight_to_gas(weight: Weight) -> u64 { + weight.ref_time() + } +} + +impl pallet_xvm::Config for TestRuntime { + type GasWeightMapping = MockGasWeightMapping; + type AccountMapping = HashedAccountMapping; + type EthereumTransact = MockEthereumTransact; +} + +pub(crate) type AccountId = AccountId32; +pub(crate) type BlockNumber = u64; +pub(crate) type Balance = u128; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub struct TestRuntime + where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Timestamp: pallet_timestamp, + Balances: pallet_balances, + RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip, + Contracts: pallet_contracts, + Xvm: pallet_xvm, + } +); + +#[derive(Default)] +pub struct ExtBuilder; + +impl ExtBuilder { + #[allow(dead_code)] + pub fn build(self) -> TestExternalities { + let t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + + let mut ext = TestExternalities::from(t); + ext.execute_with(|| { + System::set_block_number(1); + }); + ext + } +} diff --git a/precompiles/xvm/src/mock.rs b/precompiles/xvm/src/mock.rs index 4c9fe078f7..4e591f4268 100644 --- a/precompiles/xvm/src/mock.rs +++ b/precompiles/xvm/src/mock.rs @@ -37,7 +37,7 @@ use sp_runtime::{ traits::{BlakeTwo256, IdentityLookup}, }; -use astar_primitives::xvm::{CallError::*, CallErrorWithWeight, CallInfo, XvmCallResult}; +use astar_primitives::xvm::{CallError::*, CallErrorWithWeight, CallInfo, CallResult}; pub type AccountId = TestAccount; pub type Balance = u128; @@ -237,7 +237,7 @@ impl XvmCall for MockXvmWithArgsCheck { _source: AccountId, target: Vec, input: Vec, - ) -> XvmCallResult { + ) -> CallResult { ensure!( vm_id != VmId::Evm, CallErrorWithWeight { diff --git a/primitives/src/xvm.rs b/primitives/src/xvm.rs index 168e1c1fe9..50d4d472a0 100644 --- a/primitives/src/xvm.rs +++ b/primitives/src/xvm.rs @@ -78,7 +78,7 @@ pub struct CallErrorWithWeight { } /// XVM call result. -pub type XvmCallResult = Result; +pub type CallResult = Result; /// XVM context. /// @@ -106,5 +106,5 @@ pub trait XvmCall { source: AccountId, target: Vec, input: Vec, - ) -> XvmCallResult; + ) -> CallResult; } diff --git a/runtime/local/src/lib.rs b/runtime/local/src/lib.rs index 0e4ba1ce17..99c166aee8 100644 --- a/runtime/local/src/lib.rs +++ b/runtime/local/src/lib.rs @@ -471,6 +471,8 @@ parameter_types! { } impl pallet_xvm::Config for Runtime { + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type AccountMapping = HashedAccountMapping; type EthereumTransact = EthereumChecked; } diff --git a/runtime/shibuya/Cargo.toml b/runtime/shibuya/Cargo.toml index a1cb4ab9a0..bfdcbf913d 100644 --- a/runtime/shibuya/Cargo.toml +++ b/runtime/shibuya/Cargo.toml @@ -255,6 +255,7 @@ runtime-benchmarks = [ "pallet-preimage/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-ethereum-checked/runtime-benchmarks", + "pallet-xvm/runtime-benchmarks", "polkadot-runtime/runtime-benchmarks", "orml-xtokens/runtime-benchmarks", "astar-primitives/runtime-benchmarks", diff --git a/runtime/shibuya/src/lib.rs b/runtime/shibuya/src/lib.rs index 16ae014b08..d5ae642d1a 100644 --- a/runtime/shibuya/src/lib.rs +++ b/runtime/shibuya/src/lib.rs @@ -784,6 +784,8 @@ impl pallet_ethereum_checked::Config for Runtime { } impl pallet_xvm::Config for Runtime { + type GasWeightMapping = pallet_evm::FixedGasWeightMapping; + type AccountMapping = HashedAccountMapping; type EthereumTransact = EthereumChecked; } @@ -1423,6 +1425,7 @@ mod benches { [pallet_collator_selection, CollatorSelection] [pallet_xcm, PolkadotXcm] [pallet_ethereum_checked, EthereumChecked] + [pallet_xvm, Xvm] ); }