From 1e73bc5a1437e8c100472d99fbac81f8fdd6d413 Mon Sep 17 00:00:00 2001 From: Alejandro Martinez Andres <11448715+al3mart@users.noreply.github.com> Date: Mon, 4 Mar 2024 17:56:33 +0100 Subject: [PATCH] feat: query_state & pop_api_primitives (#14) * demo_contract:query_runtime * pop-api-ext:query * read relay_block# & state * unused import * ci: add build workflow * chore: improve zombienet config * ci: grant write permission to actions * feat: initialize pop-api directory * feat: add codec indexes, and wrap NFT interface * feat: add example contract utilizing pop-api crate -- not working * feat: minting NFT from contract through runtime works * feat: generic state reads * chore: fmt * RuntimeStateKeys * clean keys * fmt * cumulus_parachain_system is accessible --------- Co-authored-by: Frank Bell Co-authored-by: Peter White --- Cargo.lock | 12 +- Cargo.toml | 2 + .../balance-transfer/Cargo.toml | 1 - .../pop-api-examples/balance-transfer/lib.rs | 9 +- .../read-runtime-state/.gitignore | 9 + .../read-runtime-state/Cargo.toml | 33 +++ .../read-runtime-state/lib.rs | 224 ++++++++++++++++++ pop-api/Cargo.toml | 5 +- pop-api/primitives/Cargo.toml | 28 +++ pop-api/primitives/src/lib.rs | 1 + pop-api/primitives/src/storage_keys.rs | 11 + pop-api/src/lib.rs | 1 + runtime/Cargo.toml | 3 + runtime/src/extensions/ext_impl/dispatch.rs | 64 +++++ runtime/src/extensions/ext_impl/mod.rs | 2 + runtime/src/extensions/ext_impl/read_state.rs | 33 +++ runtime/src/extensions/mod.rs | 1 + runtime/src/extensions/pop_api_extension.rs | 56 +---- 18 files changed, 442 insertions(+), 53 deletions(-) create mode 100755 contracts/pop-api-examples/read-runtime-state/.gitignore create mode 100755 contracts/pop-api-examples/read-runtime-state/Cargo.toml create mode 100755 contracts/pop-api-examples/read-runtime-state/lib.rs create mode 100644 pop-api/primitives/Cargo.toml create mode 100644 pop-api/primitives/src/lib.rs create mode 100644 pop-api/primitives/src/storage_keys.rs create mode 100644 runtime/src/extensions/ext_impl/dispatch.rs create mode 100644 runtime/src/extensions/ext_impl/mod.rs create mode 100644 runtime/src/extensions/ext_impl/read_state.rs diff --git a/Cargo.lock b/Cargo.lock index 26c55acf..75af935a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9034,7 +9034,16 @@ name = "pop-api" version = "0.0.0" dependencies = [ "ink", - "ink_env", + "parity-scale-codec", + "pop-api-primitives", + "scale-info", + "sp-runtime 24.0.0", +] + +[[package]] +name = "pop-api-primitives" +version = "0.0.0" +dependencies = [ "parity-scale-codec", "scale-info", "sp-runtime 24.0.0", @@ -9143,6 +9152,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "polkadot-runtime-common", + "pop-api-primitives", "scale-info", "smallvec", "sp-api", diff --git a/Cargo.toml b/Cargo.toml index 22df83b4..9fe934cd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,9 @@ substrate-wasm-builder = { git = "https://github.com/paritytech/polkadot-sdk", b substrate-build-script-utils = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1" } # Local + pop-runtime = { path = "./runtime" } +pop-api-primitives = { path = "./pop-api/primitives"} # Substrate sc-basic-authorship = { git = "https://github.com/paritytech/polkadot-sdk", branch = "release-polkadot-v1.7.1" } diff --git a/contracts/pop-api-examples/balance-transfer/Cargo.toml b/contracts/pop-api-examples/balance-transfer/Cargo.toml index 88ab4506..cee76dd5 100755 --- a/contracts/pop-api-examples/balance-transfer/Cargo.toml +++ b/contracts/pop-api-examples/balance-transfer/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" [dependencies] ink = { version = "4.3.0", default-features = false } - scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } diff --git a/contracts/pop-api-examples/balance-transfer/lib.rs b/contracts/pop-api-examples/balance-transfer/lib.rs index 53dc73a2..0ed81f21 100755 --- a/contracts/pop-api-examples/balance-transfer/lib.rs +++ b/contracts/pop-api-examples/balance-transfer/lib.rs @@ -1,6 +1,5 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] - use ink::{ env::Environment, prelude::vec::Vec, @@ -8,6 +7,8 @@ use ink::{ use ink::primitives::AccountId; use sp_runtime::MultiAddress; +use scale::{Encode, Decode}; +use scale_info::TypeInfo; /// A part of the runtime dispatchable API. /// @@ -19,7 +20,7 @@ use sp_runtime::MultiAddress; /// You can investigate the full `RuntimeCall` definition by either expanding /// `construct_runtime!` macro application or by using secondary tools for reading chain /// metadata, like `subxt`. -#[derive(scale::Encode)] +#[derive(Encode, Decode, TypeInfo)] enum RuntimeCall { /// This index can be found by investigating runtime configuration. You can check the /// pallet order inside `construct_runtime!` block and read the position of your @@ -80,6 +81,10 @@ pub trait PopApi { /// operations. #[ink(extension = 0xfecb)] fn dispatch(call: RuntimeCall) -> Result>; + + #[ink(extension = 0xfeca)] + fn read_state(key: SafeKeys) -> Result>; + } impl ink::env::chain_extension::FromStatusCode for PopApiError { diff --git a/contracts/pop-api-examples/read-runtime-state/.gitignore b/contracts/pop-api-examples/read-runtime-state/.gitignore new file mode 100755 index 00000000..8de8f877 --- /dev/null +++ b/contracts/pop-api-examples/read-runtime-state/.gitignore @@ -0,0 +1,9 @@ +# Ignore build artifacts from the local tests sub-crate. +/target/ + +# Ignore backup files creates by cargo fmt. +**/*.rs.bk + +# Remove Cargo.lock when creating an executable, leave it for libraries +# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock +Cargo.lock diff --git a/contracts/pop-api-examples/read-runtime-state/Cargo.toml b/contracts/pop-api-examples/read-runtime-state/Cargo.toml new file mode 100755 index 00000000..b53f8415 --- /dev/null +++ b/contracts/pop-api-examples/read-runtime-state/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "pop_api_extension_demo" +version = "0.1.0" +authors = ["[your_name] <[your_email]>"] +edition = "2021" + +[dependencies] +ink = { version = "4.3.0", default-features = false } +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +pop-api = { path = "../../../pop-api", default-features = false } + +sp-io = { version = "23.0.0", default-features = false, features = ["disable_panic_handler", "disable_oom", "disable_allocator"] } +sp-runtime = { version = "24.0.0", default-features = false } + +[dev-dependencies] +ink_e2e = "4.3.0" + +[lib] +path = "lib.rs" + +[features] +default = ["std"] +std = [ + "ink/std", + "scale/std", + "scale-info/std", + "sp-runtime/std", + "sp-io/std", +] +ink-as-dependency = [] +e2e-tests = [] diff --git a/contracts/pop-api-examples/read-runtime-state/lib.rs b/contracts/pop-api-examples/read-runtime-state/lib.rs new file mode 100755 index 00000000..391ff857 --- /dev/null +++ b/contracts/pop-api-examples/read-runtime-state/lib.rs @@ -0,0 +1,224 @@ +#![cfg_attr(not(feature = "std"), no_std, no_main)] + +use ink::{ + env::Environment, + prelude::vec::Vec, +}; + +use ink::primitives::AccountId; +use sp_runtime::MultiAddress; +use pop_api::storage_keys::RuntimeStateKeys::ParachainSystemKeys; + + +#[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum PopApiError { + TotalSupplyFailed, +} + +pub type Result = core::result::Result; + +use scale; +impl From for PopApiError { + fn from(_: scale::Error) -> Self { + panic!("encountered unexpected invalid SCALE encoding") + } +} + +/// This is an example of how an ink! contract may call the Substrate +/// runtime function `RandomnessCollectiveFlip::random_seed`. See the +/// file `runtime/chain-extension-example.rs` for that implementation. +/// +/// Here we define the operations to interact with the Substrate runtime. +#[ink::chain_extension] +pub trait PopApi { + type ErrorCode = PopApiError; + + /// Note: this gives the operation a corresponding `func_id` (1101 in this case), + /// and the chain-side chain extension will get the `func_id` to do further + /// operations. + + #[ink(extension = 0xfeca)] + fn read_relay_block_number(key: LastRelayChainBlockNumber) -> Result; + +} + +impl ink::env::chain_extension::FromStatusCode for PopApiError { + fn from_status_code(status_code: u32) -> core::result::Result<(), Self> { + match status_code { + 0 => Ok(()), + 1 => Err(Self::TotalSupplyFailed), + _ => panic!("encountered unknown status code"), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum CustomEnvironment {} + +impl Environment for CustomEnvironment { + const MAX_EVENT_TOPICS: usize = + ::MAX_EVENT_TOPICS; + + type AccountId = ::AccountId; + type Balance = ::Balance; + type Hash = ::Hash; + type BlockNumber = ::BlockNumber; + type Timestamp = ::Timestamp; + + type ChainExtension = PopApi; +} + +#[ink::contract(env = crate::CustomEnvironment)] +mod pop_api_extension_demo { + use crate::{ + BalancesCall, + RuntimeCall, + }; + + use super::PopApiError; + + use ink::env::Error as EnvError; + + #[ink(event)] + pub struct RelayBlockNumberRead { + value: BlockNumber + } + + /// A trivial contract with a single message, that uses `call-runtime` API for + /// performing native token transfer. + #[ink(storage)] + #[derive(Default)] + pub struct PopApiExtensionDemo; + + impl From for PopApiError { + fn from(e: EnvError) -> Self { + match e { + EnvError::CallRuntimeFailed => PopApiError::TotalSupplyFailed, + _ => panic!("Unexpected error from `pallet-contracts`."), + } + } + } + + impl PopApiExtensionDemo { + #[ink(constructor, payable)] + pub fn new() -> Self { + ink::env::debug_println!("PopApiExtensionDemo::new"); + Default::default() + } + + #[ink(message)] + pub fn read_relay_block_number( + &self + ) { + let state = self.env().extension().read_state(LastRelayChainBlockNumber); + ink::env::debug_println!("{:?}", state); + ink::env().emit_event( + RelayBlockNumberRead {value: state} + ); + } + } + + #[cfg(all(test, feature = "e2e-tests"))] + mod e2e_tests { + use super::*; + use ink_e2e::{ + ChainBackend, + ContractsBackend, + }; + + use ink::{ + env::{ + test::default_accounts, + DefaultEnvironment, + }, + primitives::AccountId, + }; + + type E2EResult = Result>; + + /// The base number of indivisible units for balances on the + /// `substrate-contracts-node`. + const UNIT: Balance = 1_000_000_000_000; + + /// The contract will be given 1000 tokens during instantiation. + const CONTRACT_BALANCE: Balance = 1_000 * UNIT; + + /// The receiver will get enough funds to have the required existential deposit. + /// + /// If your chain has this threshold higher, increase the transfer value. + const TRANSFER_VALUE: Balance = 1 / 10 * UNIT; + + /// An amount that is below the existential deposit, so that a transfer to an + /// empty account fails. + /// + /// Must not be zero, because such an operation would be a successful no-op. + const INSUFFICIENT_TRANSFER_VALUE: Balance = 1; + + /// Positive case scenario: + /// - the call is valid + /// - the call execution succeeds + #[ink_e2e::test] + async fn transfer_with_call_runtime_works( + mut client: Client, + ) -> E2EResult<()> { + // given + let mut constructor = RuntimeCallerRef::new(); + let contract = client + .instantiate("call-runtime", &ink_e2e::alice(), &mut constructor) + .value(CONTRACT_BALANCE) + .submit() + .await + .expect("instantiate failed"); + let mut call_builder = contract.call_builder::(); + + let accounts = default_accounts::(); + + let receiver: AccountId = accounts.bob; + + let sender_balance_before = client + .free_balance(accounts.alice) + .await + .expect("Failed to get account balance"); + let receiver_balance_before = client + .free_balance(receiver) + .await + .expect("Failed to get account balance"); + + // when + let transfer_message = + call_builder.transfer_through_runtime(receiver, TRANSFER_VALUE); + + let call_res = client + .call(&ink_e2e::alice(), &transfer_message) + .submit() + .await + .expect("call failed"); + + assert!(call_res.return_value().is_ok()); + + // then + let sender_balance_after = client + .free_balance(accounts.alice) + .await + .expect("Failed to get account balance"); + let receiver_balance_after = client + .free_balance(receiver) + .await + .expect("Failed to get account balance"); + + assert_eq!( + contract_balance_before, + contract_balance_after + TRANSFER_VALUE + ); + assert_eq!( + receiver_balance_before, + receiver_balance_after - TRANSFER_VALUE + ); + + Ok(()) + } + + } +} \ No newline at end of file diff --git a/pop-api/Cargo.toml b/pop-api/Cargo.toml index ee581ba6..b2ffb628 100644 --- a/pop-api/Cargo.toml +++ b/pop-api/Cargo.toml @@ -6,9 +6,12 @@ version = "0.0.0" edition = "2021" [dependencies] + +pop-api-primitives = { path = "./primitives" } + ink = { version = "4.3.0", default-features = false } -ink_env = { version = "4.3.0", default-features = false } sp-runtime = { version = "24.0.0", default-features = false } + scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } diff --git a/pop-api/primitives/Cargo.toml b/pop-api/primitives/Cargo.toml new file mode 100644 index 00000000..0fa865b0 --- /dev/null +++ b/pop-api/primitives/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "pop-api-primitives" +description = "Reserved crate for pop-api-primitives." +license = "GPL-3.0-only" +version = "0.0.0" +edition = "2021" + +[dependencies] +sp-runtime = { version = "24.0.0", default-features = false } + +scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } +scale-info = { version = "2.6", default-features = false, features = ["derive"], optional = true } + +[lib] +name = "pop_api_primitives" +path = "src/lib.rs" +crate-type = [ + "rlib", +] + + +[features] +default = ["std"] +std = [ + "sp-runtime/std", + "scale/std", + "scale-info/std", +] diff --git a/pop-api/primitives/src/lib.rs b/pop-api/primitives/src/lib.rs new file mode 100644 index 00000000..d37a392a --- /dev/null +++ b/pop-api/primitives/src/lib.rs @@ -0,0 +1 @@ +pub mod storage_keys; diff --git a/pop-api/primitives/src/storage_keys.rs b/pop-api/primitives/src/storage_keys.rs new file mode 100644 index 00000000..a67f3a18 --- /dev/null +++ b/pop-api/primitives/src/storage_keys.rs @@ -0,0 +1,11 @@ +use scale::{Decode, Encode}; + +#[derive(Encode, Decode, Debug)] +pub enum RuntimeStateKeys { + ParachainSystem(ParachainSystemKeys), +} + +#[derive(Encode, Decode, Debug)] +pub enum ParachainSystemKeys { + LastRelayChainBlockNumber, +} diff --git a/pop-api/src/lib.rs b/pop-api/src/lib.rs index 0f9f7f70..6eae52a6 100644 --- a/pop-api/src/lib.rs +++ b/pop-api/src/lib.rs @@ -1,5 +1,6 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] +use pop_api_primitives::storage_keys; pub mod v0; use ink::{env::Environment, prelude::vec::Vec, ChainExtensionInstance}; diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index a47ddbca..603c8c96 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -21,6 +21,9 @@ log = { workspace = true } scale-info = { workspace = true } smallvec = { workspace = true } +# Local +pop-api-primitives = { workspace = true } + # Substrate frame-benchmarking = { workspace = true } diff --git a/runtime/src/extensions/ext_impl/dispatch.rs b/runtime/src/extensions/ext_impl/dispatch.rs new file mode 100644 index 00000000..df804bc7 --- /dev/null +++ b/runtime/src/extensions/ext_impl/dispatch.rs @@ -0,0 +1,64 @@ +use frame_support::{ + dispatch::{GetDispatchInfo, PostDispatchInfo, RawOrigin}, + pallet_prelude::*, +}; +use log; +use pallet_contracts::chain_extension::{Environment, Ext, InitState, SysConfig}; +use sp_core::crypto::UncheckedFrom; +use sp_runtime::{traits::Dispatchable, DispatchError}; + +const LOG_TARGET: &str = "popapi::extension::dispatch"; + +pub(crate) fn dispatch(env: Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + frame_system::Config, + ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, + ::RuntimeCall: Parameter + + Dispatchable::RuntimeOrigin, PostInfo = PostDispatchInfo> + + GetDispatchInfo + + From>, + E: Ext, +{ + let mut env = env.buf_in_buf_out(); + + // charge max weight before reading contract memory + // TODO: causing "1010: block limits exhausted" error + // let weight_limit = env.ext().gas_meter().gas_left(); + // let charged_weight = env.charge_weight(weight_limit)?; + + // TODO: debug_message weight is a good approximation of the additional overhead of going + // from contract layer to substrate layer. + + // input length + let len = env.in_len(); + let call: ::RuntimeCall = env.read_as_unbounded(len)?; + + // conservative weight estimate for deserializing the input. The actual weight is less and should utilize a custom benchmark + let base_weight: Weight = T::DbWeight::get().reads(len.into()); + + // weight for dispatching the call + let dispatch_weight = call.get_dispatch_info().weight; + + // charge weight for the cost of the deserialization and the dispatch + let _ = env.charge_weight(base_weight.saturating_add(dispatch_weight))?; + + log::debug!(target:LOG_TARGET, " dispatch inputted RuntimeCall: {:?}", call); + + let sender = env.ext().caller(); + let origin: T::RuntimeOrigin = RawOrigin::Signed(sender.account_id()?.clone()).into(); + + // TODO: uncomment once charged_weight is fixed + // let actual_weight = call.get_dispatch_info().weight; + // env.adjust_weight(charged_weight, actual_weight); + let result = call.dispatch(origin); + match result { + Ok(info) => { + log::debug!(target:LOG_TARGET, "dispatch success, actual weight: {:?}", info.actual_weight); + } + Err(err) => { + log::debug!(target:LOG_TARGET, "dispatch failed: error: {:?}", err.error); + return Err(err.error); + } + } + Ok(()) +} diff --git a/runtime/src/extensions/ext_impl/mod.rs b/runtime/src/extensions/ext_impl/mod.rs new file mode 100644 index 00000000..2389a49b --- /dev/null +++ b/runtime/src/extensions/ext_impl/mod.rs @@ -0,0 +1,2 @@ +pub mod dispatch; +pub mod read_state; diff --git a/runtime/src/extensions/ext_impl/read_state.rs b/runtime/src/extensions/ext_impl/read_state.rs new file mode 100644 index 00000000..1281810f --- /dev/null +++ b/runtime/src/extensions/ext_impl/read_state.rs @@ -0,0 +1,33 @@ +use codec::Decode; +use cumulus_primitives_core::relay_chain::BlockNumber; +use frame_support::pallet_prelude::*; +use log; +use pallet_contracts::chain_extension::{Environment, Ext, InitState}; +use pop_api_primitives::storage_keys::ParachainSystemKeys; + +const LOG_TARGET: &str = "popapi::extension::read_state"; + +pub(crate) fn read_state(env: Environment) -> Result<(), DispatchError> +where + T: pallet_contracts::Config + frame_system::Config, + E: Ext, +{ + let mut env = env.buf_in_buf_out(); + // TODO: Substitue len u32 with pop_api::src::impls::pop_network::StringLimit. + // Move StringLimit to pop_api_primitives first. + let len: u32 = env.in_len(); + let key: ParachainSystemKeys = env.read_as_unbounded(len)?; + + match key { + ParachainSystemKeys::LastRelayChainBlockNumber => { + let relay_block_num: BlockNumber = crate::ParachainSystem::last_relay_block_number(); + log::debug!( + target:LOG_TARGET, + "Last Relay Chain Block Number is: {:?}.", relay_block_num + ); + //Ok(relay_block_num) + Ok(()) + } + _ => Err(DispatchError::Other("Unable to read provided key.")), + } +} diff --git a/runtime/src/extensions/mod.rs b/runtime/src/extensions/mod.rs index ad18a5a0..3f110092 100644 --- a/runtime/src/extensions/mod.rs +++ b/runtime/src/extensions/mod.rs @@ -1 +1,2 @@ +mod ext_impl; pub mod pop_api_extension; diff --git a/runtime/src/extensions/pop_api_extension.rs b/runtime/src/extensions/pop_api_extension.rs index c3f1bf21..4c15c07c 100644 --- a/runtime/src/extensions/pop_api_extension.rs +++ b/runtime/src/extensions/pop_api_extension.rs @@ -1,18 +1,18 @@ use frame_support::{ - dispatch::{GetDispatchInfo, PostDispatchInfo, RawOrigin}, + dispatch::{GetDispatchInfo, PostDispatchInfo}, pallet_prelude::*, }; - use log; - use pallet_contracts::chain_extension::{ ChainExtension, Environment, Ext, InitState, RetVal, SysConfig, }; - use sp_core::crypto::UncheckedFrom; use sp_runtime::{traits::Dispatchable, DispatchError}; +use crate::extensions::ext_impl::{dispatch::dispatch, read_state::read_state}; + const LOG_TARGET: &str = "popapi::extension"; + #[derive(Default)] pub struct PopApiExtension; @@ -30,6 +30,7 @@ fn convert_err(err_msg: &'static str) -> impl FnOnce(DispatchError) -> DispatchE #[derive(Debug)] enum FuncId { CallRuntime, + QueryState, } impl TryFrom for FuncId { @@ -38,6 +39,7 @@ impl TryFrom for FuncId { fn try_from(func_id: u16) -> Result { let id = match func_id { 0xfecb => Self::CallRuntime, + 0xfeca => Self::QueryState, _ => { log::error!("Called an unregistered `func_id`: {:}", func_id); return Err(DispatchError::Other("Unimplemented func_id")); @@ -48,52 +50,9 @@ impl TryFrom for FuncId { } } -fn dispatch(env: Environment) -> Result<(), DispatchError> -where - T: pallet_contracts::Config + frame_system::Config, - ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, - ::RuntimeCall: Parameter - + Dispatchable::RuntimeOrigin, PostInfo = PostDispatchInfo> - + GetDispatchInfo - + From>, - E: Ext, -{ - let mut env = env.buf_in_buf_out(); - - // input length - let len = env.in_len(); - let call: ::RuntimeCall = env.read_as_unbounded(len)?; - - // conservative weight estimate for deserializing the input. The actual weight is less and should utilize a custom benchmark - let base_weight: Weight = T::DbWeight::get().reads(len.into()); - - // weight for dispatching the call - let dispatch_weight = call.get_dispatch_info().weight; - - // charge weight for the cost of the deserialization and the dispatch - let _ = env.charge_weight(base_weight.saturating_add(dispatch_weight))?; - - log::debug!(target:LOG_TARGET, " dispatch inputted RuntimeCall: {:?}", call); - - let sender = env.ext().caller(); - let origin: T::RuntimeOrigin = RawOrigin::Signed(sender.account_id()?.clone()).into(); - - let result = call.dispatch(origin); - match result { - Ok(info) => { - log::debug!(target:LOG_TARGET, "dispatch success, actual weight: {:?}", info.actual_weight); - } - Err(err) => { - log::debug!(target:LOG_TARGET, "dispatch failed: error: {:?}", err.error); - return Err(err.error); - } - } - Ok(()) -} - impl ChainExtension for PopApiExtension where - T: pallet_contracts::Config, + T: pallet_contracts::Config + cumulus_pallet_parachain_system::Config, ::AccountId: UncheckedFrom<::Hash> + AsRef<[u8]>, ::RuntimeCall: Parameter + Dispatchable::RuntimeOrigin, PostInfo = PostDispatchInfo> @@ -109,6 +68,7 @@ where let func_id = FuncId::try_from(env.func_id())?; match func_id { FuncId::CallRuntime => dispatch::(env)?, + FuncId::QueryState => read_state::(env)?, } Ok(RetVal::Converging(0))