From 97b87b3e7346cebfca454afcb14d2fe3a7baeb38 Mon Sep 17 00:00:00 2001 From: PierreOssun Date: Fri, 21 Apr 2023 16:34:16 +0200 Subject: [PATCH 1/2] Added Scheduler CE --- Cargo.toml | 5 + chain-extensions/pallet-scheduler/Cargo.toml | 50 ++ chain-extensions/pallet-scheduler/src/lib.rs | 169 +++++ chain-extensions/pallet-scheduler/src/mock.rs | 242 +++++++ .../pallet-scheduler/src/tests.rs | 196 ++++++ .../pallet-scheduler/src/weights.rs | 37 ++ .../test-contract/scheduler_example.json | 620 ++++++++++++++++++ .../test-contract/scheduler_example.wasm | Bin 0 -> 18012 bytes chain-extensions/types/scheduler/Cargo.toml | 27 + chain-extensions/types/scheduler/src/lib.rs | 95 +++ 10 files changed, 1441 insertions(+) create mode 100644 chain-extensions/pallet-scheduler/Cargo.toml create mode 100644 chain-extensions/pallet-scheduler/src/lib.rs create mode 100644 chain-extensions/pallet-scheduler/src/mock.rs create mode 100644 chain-extensions/pallet-scheduler/src/tests.rs create mode 100644 chain-extensions/pallet-scheduler/src/weights.rs create mode 100644 chain-extensions/pallet-scheduler/test-contract/scheduler_example.json create mode 100644 chain-extensions/pallet-scheduler/test-contract/scheduler_example.wasm create mode 100644 chain-extensions/types/scheduler/Cargo.toml create mode 100644 chain-extensions/types/scheduler/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 3eb8697f..4728cee5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "chain-extensions/dapps-staking", "chain-extensions/pallet-assets", "chain-extensions/xvm", + "chain-extensions/pallet-scheduler", "chain-extensions/types/*", "frame/block-reward", "frame/collator-selection", @@ -97,6 +98,7 @@ sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0 frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } sp-keyring = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } # (native) sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39" } @@ -120,6 +122,8 @@ pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = pallet-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } pallet-assets = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } +pallet-preimage = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.39", default-features = false } # Polkadot # (wasm) @@ -154,6 +158,7 @@ pallet-xc-asset-config = { path = "./frame/xc-asset-config", default-features = dapps-staking-chain-extension-types = { path = "./chain-extensions/types/dapps-staking", default-features = false } xvm-chain-extension-types = { path = "./chain-extensions/types/xvm", default-features = false } assets-chain-extension-types = { path = "./chain-extensions/types/assets", default-features = false } +scheduler-chain-extension-types = { path = "./chain-extensions/types/scheduler", default-features = false } pallet-evm-precompile-assets-erc20 = { path = "./precompiles/assets-erc20", default-features = false } precompile-utils = { path = "./precompiles/utils", default-features = false } diff --git a/chain-extensions/pallet-scheduler/Cargo.toml b/chain-extensions/pallet-scheduler/Cargo.toml new file mode 100644 index 00000000..13fe3666 --- /dev/null +++ b/chain-extensions/pallet-scheduler/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "pallet-chain-extension-scheduler" +version = "0.1.0" +license = "Apache-2.0" +description = "Scheduler chain extension for WASM contracts" +authors.workspace = true +edition.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } +num-traits = { workspace = true } +pallet-contracts = { workspace = true } +pallet-contracts-primitives = { workspace = true } +pallet-scheduler = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } +scheduler-chain-extension-types = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } + +[dev-dependencies] +env_logger = "0.9" +pallet-balances = { workspace = true } +pallet-preimage = { workspace = true } +pallet-timestamp = { workspace = true } +sp-io = { workspace = true } +sp-keystore = { workspace = true } + +[features] +default = ["std"] +std = [ + "parity-scale-codec/std", + "frame-support/std", + "frame-system/std", + "num-traits/std", + "pallet-contracts/std", + "pallet-contracts-primitives/std", + "scale-info/std", + "sp-std/std", + "sp-core/std", + "sp-runtime/std", + "pallet-scheduler/std", + "scheduler-chain-extension-types/std", + "pallet-balances/std", +] diff --git a/chain-extensions/pallet-scheduler/src/lib.rs b/chain-extensions/pallet-scheduler/src/lib.rs new file mode 100644 index 00000000..8dc57b91 --- /dev/null +++ b/chain-extensions/pallet-scheduler/src/lib.rs @@ -0,0 +1,169 @@ +// 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_attr(not(feature = "std"), no_std)] + +#[cfg(test)] +mod mock; +#[cfg(test)] +pub mod tests; +pub mod weights; + +use frame_support::dispatch::Weight; +use frame_support::traits::{schedule, Currency}; +use frame_system::RawOrigin; +use pallet_contracts::{ + chain_extension::{ChainExtension, Environment, Ext, InitState, RetVal, SysConfig}, + Call as PalletContractCall, +}; +use pallet_scheduler::WeightInfo; +use parity_scale_codec::{Encode, HasCompact}; +use scale_info::TypeInfo; +use scheduler_chain_extension_types::*; +use sp_core::Get; +use sp_runtime::traits::StaticLookup; +use sp_runtime::DispatchError; +use sp_std::boxed::Box; +use sp_std::fmt::Debug; +use sp_std::marker::PhantomData; + +enum SchedulerFunc { + Schedule, + Cancel, +} + +impl TryFrom for SchedulerFunc { + type Error = DispatchError; + + fn try_from(value: u16) -> Result { + match value { + 1 => Ok(SchedulerFunc::Schedule), + 2 => Ok(SchedulerFunc::Cancel), + _ => Err(DispatchError::Other( + "PalletSchedulerExtension: Unimplemented func_id", + )), + } + } +} + +type BalanceOf = <::Currency as Currency< + ::AccountId, +>>::Balance; + +/// Pallet Scheduler chain extension. +pub struct SchedulerExtension(PhantomData<(T, W)>); + +impl Default for SchedulerExtension { + fn default() -> Self { + SchedulerExtension(PhantomData) + } +} + +impl ChainExtension for SchedulerExtension +where + T: pallet_scheduler::Config + pallet_contracts::Config, + <::Lookup as StaticLookup>::Source: From<::AccountId>, + ::AccountId: From<[u8; 32]>, + <<::Currency as Currency<::AccountId>>::Balance as HasCompact>::Type: Clone + Encode + TypeInfo + Debug + Eq, + ::RuntimeCall: From> + Encode, + ::RuntimeCall: From>, + W: weights::WeightInfo, +{ + fn call(&mut self, env: Environment) -> Result + where + E: Ext, + { + let func_id = env.func_id().try_into()?; + let mut env = env.buf_in_buf_out(); + + match func_id { + SchedulerFunc::Schedule => { + let (origin, when, maybe_periodic, priority, call_input): ( + Origin, + T::BlockNumber, + Option>, + schedule::Priority, + ContractCallInput>, + ) = env.read_as_unbounded(env.in_len())?; + + let read_weigth = ::read_as_unbounded(env.in_len()); + env.charge_weight(read_weigth)?; + + let base_weight = ::WeightInfo::schedule( + T::MaxScheduledPerBlock::get(), + ); + env.charge_weight(base_weight)?; + + let raw_origin = select_origin!(&origin, env.ext().address().clone()); + + let call: ::RuntimeCall = + PalletContractCall::::call { + dest: call_input.dest.into(), + value: call_input.value, + gas_limit: Weight::from_parts(call_input.gas_limit.0, call_input.gas_limit.1), + data: call_input.data.into(), + storage_deposit_limit: None, + }.into(); + + let call_result = pallet_scheduler::Pallet::::schedule( + raw_origin.into(), + when, + maybe_periodic, + priority, + Box::new(call), + ); + return match call_result { + Err(e) => { + sp_std::if_std! {println!("Schedule:{:?}", e)}; + let mapped_error = Outcome::from(e); + Ok(RetVal::Converging(mapped_error as u32)) + } + Ok(_) => Ok(RetVal::Converging(Outcome::Success as u32)), + }; + }, + SchedulerFunc::Cancel => { + let (origin, when, index): ( + Origin, + T::BlockNumber, + u32, + ) = env.read_as()?; + + let base_weight = ::WeightInfo::cancel( + T::MaxScheduledPerBlock::get(), + ); + env.charge_weight(base_weight)?; + + let raw_origin = select_origin!(&origin, env.ext().address().clone()); + + let call_result = pallet_scheduler::Pallet::::cancel( + raw_origin.into(), + when, + index, + ); + return match call_result { + Err(e) => { + sp_std::if_std! {println!("Cancel:{:?}", e)}; + let mapped_error = Outcome::from(e); + Ok(RetVal::Converging(mapped_error as u32)) + } + Ok(_) => Ok(RetVal::Converging(Outcome::Success as u32)), + }; + } + } + } +} diff --git a/chain-extensions/pallet-scheduler/src/mock.rs b/chain-extensions/pallet-scheduler/src/mock.rs new file mode 100644 index 00000000..49f43f66 --- /dev/null +++ b/chain-extensions/pallet-scheduler/src/mock.rs @@ -0,0 +1,242 @@ +// 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 crate::weights::SubstrateWeight; +use crate::BalanceOf; +use crate::{weights, SchedulerExtension}; +use frame_support::traits::Randomness; +use frame_support::{ + ord_parameter_types, parameter_types, sp_io, + traits::{ConstU32, ConstU64, EqualPrivilegeOnly, Nothing, OnFinalize, OnInitialize}, + weights::Weight, +}; +use frame_system::{EnsureRoot, EnsureSigned}; +use pallet_contracts::chain_extension::RegisteredChainExtension; +use pallet_contracts::{DefaultAddressGenerator, Frame}; +use sp_core::crypto::AccountId32; +use sp_keystore::{testing::KeyStore, KeystoreExt}; +use sp_runtime::testing::H256; +use sp_runtime::traits::{BlakeTwo256, Convert, IdentityLookup, Zero}; +use sp_runtime::{generic, Perbill}; +use std::sync::Arc; + +pub type BlockNumber = u32; +pub type Balance = u128; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::simple_max( + Weight::from_ref_time(2_000_000_000_000).set_proof_size(u64::MAX), + ); +} +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = BlockWeights; + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u32; + type BlockNumber = BlockNumber; + type Hash = H256; + type RuntimeCall = RuntimeCall; + type Hashing = BlakeTwo256; + type AccountId = AccountId32; + type Lookup = IdentityLookup; + type Header = generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + 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_preimage::Config for Test { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); + type Currency = (); + type ManagerOrigin = EnsureRoot; + type BaseDeposit = (); + type ByteDeposit = (); +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + BlockWeights::get().max_block; +} + +ord_parameter_types! { + pub const One: u64 = 1; +} + +impl pallet_scheduler::Config for Test { + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureSigned; + type MaxScheduledPerBlock = ConstU32<10>; + type WeightInfo = (); + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type Preimages = Preimage; +} + +parameter_types! { + pub const DeletionWeightLimit: Weight = Weight::from_ref_time(500_000_000_000); + pub static UnstableInterface: bool = true; + pub Schedule: pallet_contracts::Schedule = Default::default(); + pub static DepositPerByte: BalanceOf = 1; + pub const DepositPerItem: BalanceOf = 1; +} + +pub struct DummyDeprecatedRandomness; +impl Randomness for DummyDeprecatedRandomness { + fn random(_: &[u8]) -> (H256, BlockNumber) { + (Default::default(), Zero::zero()) + } +} + +impl pallet_contracts::Config for Test { + type Time = Timestamp; + type Randomness = DummyDeprecatedRandomness; + type Currency = Balances; + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type CallFilter = Nothing; + type CallStack = [Frame; 5]; + type WeightPrice = Self; + type WeightInfo = (); + type ChainExtension = SchedulerExtension>; + type DeletionQueueDepth = ConstU32<128>; + type DeletionWeightLimit = DeletionWeightLimit; + type Schedule = Schedule; + type DepositPerByte = DepositPerByte; + type DepositPerItem = DepositPerItem; + type AddressGenerator = DefaultAddressGenerator; + type MaxCodeLen = ConstU32<{ 123 * 1024 }>; + type MaxStorageKeyLen = ConstU32<128>; + type UnsafeUnstableInterface = UnstableInterface; + type MaxDebugBufferLen = ConstU32<{ 2 * 1024 * 1024 }>; +} + +impl RegisteredChainExtension for SchedulerExtension { + const ID: u16 = 03; +} + +parameter_types! { + pub static ExistentialDeposit: u64 = 1; +} + +impl pallet_balances::Config for Test { + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); +} + +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<1>; + type WeightInfo = (); +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, + Contracts: pallet_contracts::{Pallet, Call, Storage, Event}, + Scheduler: pallet_scheduler::{Pallet, Call, Storage, Event}, + Preimage: pallet_preimage::{Pallet, Call, Storage, Event}, + } +); + +pub const ALICE: AccountId32 = AccountId32::new([1u8; 32]); +pub const GAS_LIMIT: Weight = Weight::from_ref_time(100_000_000_000).set_proof_size(700000u64); + +impl Convert> for Test { + fn convert(w: Weight) -> BalanceOf { + w.ref_time().into() + } +} + +pub struct ExtBuilder { + existential_deposit: u64, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + existential_deposit: ExistentialDeposit::get(), + } + } +} + +impl ExtBuilder { + pub fn existential_deposit(mut self, existential_deposit: u64) -> Self { + self.existential_deposit = existential_deposit; + self + } + pub fn set_associated_consts(&self) { + EXISTENTIAL_DEPOSIT.with(|v| *v.borrow_mut() = self.existential_deposit); + } + pub fn build(self) -> sp_io::TestExternalities { + use env_logger::{Builder, Env}; + let env = Env::new().default_filter_or("runtime=debug"); + let _ = Builder::from_env(env).is_test(true).try_init(); + self.set_associated_consts(); + let mut t = frame_system::GenesisConfig::default() + .build_storage::() + .unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![] } + .assimilate_storage(&mut t) + .unwrap(); + let mut ext = sp_io::TestExternalities::new(t); + ext.register_extension(KeystoreExt(Arc::new(KeyStore::new()))); + ext.execute_with(|| System::set_block_number(1)); + ext + } +} + +pub fn run_to_block(n: u32) { + while System::block_number() < n { + Scheduler::on_finalize(System::block_number()); + System::set_block_number(System::block_number() + 1); + Scheduler::on_initialize(System::block_number()); + } +} diff --git a/chain-extensions/pallet-scheduler/src/tests.rs b/chain-extensions/pallet-scheduler/src/tests.rs new file mode 100644 index 00000000..1e9a54fe --- /dev/null +++ b/chain-extensions/pallet-scheduler/src/tests.rs @@ -0,0 +1,196 @@ +// 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 crate::mock::{Test, *}; +use frame_support::assert_ok; +use frame_support::traits::Currency; +use pallet_contracts::Determinism; +use pallet_contracts_primitives::{Code, ExecReturnValue}; +use pallet_scheduler::Agenda; +use parity_scale_codec::Encode; +use sp_runtime::{AccountId32, DispatchError}; +use std::fs; + +// Those tests use the contract scheduler_example avilable here: +// https://github.com/swanky-dapps/chain-extension-contracts/blob/feature/scheduler/examples/scheduler/lib.rs +// It stores a u32 value in storage (default value: 0): +// #[ink(storage)] +// #[derive(Default)] +// pub struct Scheduler { +// value: u32, +// } +// +// and `schedule()` will schedule a call to `increase_value()` that will increment value by 10 +// #[ink(message)] +// pub fn increase_value(&mut self) { +// self.value += 10; +// } + +#[test] +fn schedule_call_works() { + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let addr = instantiate(); + + // Schedule a call to `increase_value()` that will increment value by 10 + // params + // when: BlockNumber = 5 + // maybe_periodic: None + let result = schedule(addr.clone(), 5, None); + assert_ok!(result); + + // Assert that the scheduled call is part of Scheduler Agenda + assert!(Agenda::::get(5).len() == 1); + + // Run tu block 5 add assert value has been incremented + run_to_block(5); + let result = get_value(addr); + assert_eq!(result.data[1], 10); + }); +} + +#[test] +fn schedule_periodic_call() { + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let addr = instantiate(); + + // Schedule a call to `increase_value()` that will increment value by 10 + // params + // when: BlockNumber = 5 + // maybe_periodic: every 2 blocks, 3 times + let result = schedule(addr.clone(), 5, Some((2, 3))); + assert_ok!(result); + + // Assert that the scheduled call is part of Scheduler Agenda + assert!(Agenda::::get(5).len() == 1); + + // Run tu block 5 add assert value has been incremented + run_to_block(5); + let result = get_value(addr.clone()); + assert_eq!(result.data[1], 10); + + // Run tu block 7 add assert value has been incremented + run_to_block(7); + let result = get_value(addr.clone()); + assert_eq!(result.data[1], 20); + + // Run tu block 7 add assert value has been incremented + run_to_block(9); + let result = get_value(addr.clone()); + assert_eq!(result.data[1], 30); + }); +} + +#[test] +fn cancel_call() { + ExtBuilder::default() + .existential_deposit(50) + .build() + .execute_with(|| { + let addr = instantiate(); + + // Schedule a call to `increase_value()` that will increment value by 10 + // params + // when: BlockNumber = 5 + // maybe_periodic: None + let result = schedule(addr.clone(), 5, None); + assert_ok!(result); + + // Assert that the scheduled call is part of Scheduler Agenda + assert!(Agenda::::get(5).len() == 1); + + // Cancel the call + // params + // when: BlockNumber = 5 + // index: 0 + let result = cancel(addr.clone(), 5, 0); + assert_ok!(result); + + // Run tu block 5 add assert value has not been incremented + run_to_block(5); + let result = get_value(addr.clone()); + assert_eq!(result.data[1], 0); + }); +} + +fn instantiate() -> AccountId32 { + let code = + fs::read("./test-contract/scheduler_example.wasm").expect("could not read .wasm file"); + let min_balance = ::Currency::minimum_balance(); + let _ = Balances::deposit_creating(&ALICE, 1000 * min_balance); + let instance_selector: Vec = [0x9b, 0xae, 0x9d, 0x5e].to_vec(); + Contracts::bare_instantiate( + ALICE, + 0, + GAS_LIMIT, + None, + Code::Upload(code), + instance_selector, + vec![], + false, + ) + .result + .unwrap() + .account_id +} + +fn schedule( + addr: AccountId32, + when: u32, + maybe_periodic: Option<(u32, u32)>, +) -> Result { + let mut data = Vec::new(); + data.append(&mut [0x9d, 0xb8, 0x31, 0x96].to_vec()); + data.append(&mut when.encode()); + data.append(&mut maybe_periodic.encode()); + + do_bare_call(addr, data) +} + +fn cancel(addr: AccountId32, when: u32, index: u32) -> Result { + let mut data = Vec::new(); + data.append(&mut [0x97, 0x96, 0xe9, 0xa7].to_vec()); + data.append(&mut when.encode()); + data.append(&mut index.encode()); + + do_bare_call(addr, data) +} + +fn get_value(addr: AccountId32) -> ExecReturnValue { + let selector = [0xca, 0x6f, 0x21, 0x70].to_vec(); + do_bare_call(addr, selector).unwrap() +} + +fn do_bare_call(addr: AccountId32, input: Vec) -> Result { + Contracts::bare_call( + ALICE, + addr.into(), + 0, + GAS_LIMIT, + None, + input, + false, + Determinism::Deterministic, + ) + .result +} diff --git a/chain-extensions/pallet-scheduler/src/weights.rs b/chain-extensions/pallet-scheduler/src/weights.rs new file mode 100644 index 00000000..cd46fd40 --- /dev/null +++ b/chain-extensions/pallet-scheduler/src/weights.rs @@ -0,0 +1,37 @@ +// 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_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet-scheduler chain-extension. +pub trait WeightInfo { + fn read_as_unbounded(n: u32) -> Weight; +} + +/// Weights for pallet-scheduler chain-extension +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + fn read_as_unbounded(n: u32) -> Weight { + Weight::from_ref_time(1_000).saturating_mul(n.into()) + } +} \ No newline at end of file diff --git a/chain-extensions/pallet-scheduler/test-contract/scheduler_example.json b/chain-extensions/pallet-scheduler/test-contract/scheduler_example.json new file mode 100644 index 00000000..399a2f66 --- /dev/null +++ b/chain-extensions/pallet-scheduler/test-contract/scheduler_example.json @@ -0,0 +1,620 @@ +{ + "source": { + "hash": "0x6ce7d36cc6cb4d0908b5aa096df9d2f8896ad976df2c1872019859f78a99bc26", + "language": "ink! 4.2.0", + "compiler": "rustc 1.69.0-nightly", + "build_info": { + "build_mode": "Debug", + "cargo_contract_version": "2.1.0", + "rust_toolchain": "nightly-x86_64-unknown-linux-gnu", + "wasm_opt_settings": { + "keep_debug_symbols": false, + "optimization_passes": "Z" + } + } + }, + "contract": { + "name": "scheduler_example", + "version": "0.1.0", + "authors": [ + "Stake Technologies " + ] + }, + "spec": { + "constructors": [ + { + "args": [], + "default": false, + "docs": [], + "label": "new", + "payable": false, + "returnType": { + "displayName": [ + "ink_primitives", + "ConstructorResult" + ], + "type": 1 + }, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "environment": { + "accountId": { + "displayName": [ + "AccountId" + ], + "type": 10 + }, + "balance": { + "displayName": [ + "Balance" + ], + "type": 13 + }, + "blockNumber": { + "displayName": [ + "BlockNumber" + ], + "type": 0 + }, + "chainExtension": { + "displayName": [ + "ChainExtension" + ], + "type": 16 + }, + "hash": { + "displayName": [ + "Hash" + ], + "type": 14 + }, + "maxEventTopics": 4, + "timestamp": { + "displayName": [ + "Timestamp" + ], + "type": 15 + } + }, + "events": [], + "lang_error": { + "displayName": [ + "ink", + "LangError" + ], + "type": 3 + }, + "messages": [ + { + "args": [ + { + "label": "when", + "type": { + "displayName": [ + "BlockNumber" + ], + "type": 0 + } + }, + { + "label": "maybe_periodic", + "type": { + "displayName": [ + "Option" + ], + "type": 4 + } + } + ], + "default": false, + "docs": [], + "label": "schedule", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 6 + }, + "selector": "0x9db83196" + }, + { + "args": [ + { + "label": "when", + "type": { + "displayName": [ + "BlockNumber" + ], + "type": 0 + } + }, + { + "label": "index", + "type": { + "displayName": [ + "u32" + ], + "type": 0 + } + } + ], + "default": false, + "docs": [], + "label": "cancel", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 6 + }, + "selector": "0x9796e9a7" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "increase_value", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 1 + }, + "selector": "0xf8af079d" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "get_value", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 9 + }, + "selector": "0xca6f2170" + }, + { + "args": [], + "default": false, + "docs": [], + "label": "get_block_number", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "ink", + "MessageResult" + ], + "type": 9 + }, + "selector": "0xf37053d6" + } + ] + }, + "storage": { + "root": { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "leaf": { + "key": "0x00000000", + "ty": 0 + } + }, + "name": "value" + } + ], + "name": "Scheduler" + } + }, + "root_key": "0x00000000" + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 1, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 2, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 3, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "CouldNotReadInput" + } + ] + } + }, + "path": [ + "ink_primitives", + "LangError" + ] + } + }, + { + "id": 4, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "None" + }, + { + "fields": [ + { + "type": 5 + } + ], + "index": 1, + "name": "Some" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 5 + } + ], + "path": [ + "Option" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "tuple": [ + 0, + 0 + ] + } + } + }, + { + "id": 6, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 7 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 7 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 7, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 2 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 8 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 2 + }, + { + "name": "E", + "type": 8 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 8, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 1, + "name": "FailedToSchedule" + }, + { + "index": 2, + "name": "NotFound" + }, + { + "index": 3, + "name": "TargetBlockNumberInPast" + }, + { + "index": 4, + "name": "RescheduleNoChange" + }, + { + "index": 5, + "name": "Named" + }, + { + "index": 98, + "name": "OriginCannotBeCaller" + }, + { + "index": 99, + "name": "RuntimeError" + }, + { + "index": 7, + "name": "UnknownStatusCode" + }, + { + "index": 8, + "name": "InvalidScaleEncoding" + } + ] + } + }, + "path": [ + "scheduler_extension", + "SchedulerError" + ] + } + }, + { + "id": 9, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 0 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 3 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 0 + }, + { + "name": "E", + "type": 3 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 11, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "AccountId" + ] + } + }, + { + "id": 11, + "type": { + "def": { + "array": { + "len": 32, + "type": 12 + } + } + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 13, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 14, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 11, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "types", + "Hash" + ] + } + }, + { + "id": 15, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 16, + "type": { + "def": { + "variant": {} + }, + "path": [ + "ink_env", + "types", + "NoChainExtension" + ] + } + } + ], + "version": "4" +} \ No newline at end of file diff --git a/chain-extensions/pallet-scheduler/test-contract/scheduler_example.wasm b/chain-extensions/pallet-scheduler/test-contract/scheduler_example.wasm new file mode 100644 index 0000000000000000000000000000000000000000..7f840101c0a139fe4de22ef24bda00767467d131 GIT binary patch literal 18012 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. + +#![cfg_attr(not(feature = "std"), no_std)] +use parity_scale_codec::MaxEncodedLen; +use parity_scale_codec::{Decode, Encode}; +use scale_info::prelude::vec::Vec; +use sp_runtime::{DispatchError, ModuleError}; + +#[derive(PartialEq, Eq, Copy, Clone, Encode, Decode, Debug)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum Outcome { + /// Success + Success = 0, + /// Failed to schedule a call + FailedToSchedule = 1, + /// Cannot find the scheduled call. + NotFound = 2, + /// Given target block number is in the past. + TargetBlockNumberInPast = 3, + /// Reschedule failed because it does not change scheduled time. + RescheduleNoChange = 4, + /// Attempt to use a non-named function on a named task. + Named = 5, + /// Origin Caller is not supported + OriginCannotBeCaller = 98, + /// Unknown error + RuntimeError = 99, +} + +impl From for Outcome { + fn from(input: DispatchError) -> Self { + let error_text = match input { + DispatchError::Module(ModuleError { message, .. }) => message, + _ => Some("No module error Info"), + }; + return match error_text { + Some("FailedToSchedule") => Outcome::FailedToSchedule, + Some("NotFound") => Outcome::NotFound, + Some("TargetBlockNumberInPast") => Outcome::TargetBlockNumberInPast, + Some("RescheduleNoChange") => Outcome::RescheduleNoChange, + Some("Named") => Outcome::Named, + _ => Outcome::RuntimeError, + }; + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub struct ContractCallInput { + pub dest: AccountId, + pub data: Vec, + pub gas_limit: (u64, u64), + pub storage_deposit_limit: Option, + pub value: Balance, + pub max_weight: u64, +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq, Encode, Decode, MaxEncodedLen)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum Origin { + Caller, + Address, +} + +impl Default for Origin { + fn default() -> Self { + Self::Address + } +} + +#[macro_export] +macro_rules! select_origin { + ($origin:expr, $account:expr) => { + match $origin { + Origin::Caller => return Ok(RetVal::Converging(Outcome::OriginCannotBeCaller as u32)), + Origin::Address => RawOrigin::Signed($account), + } + }; +} From f0e6a030e562b4ca76d69aab0ff1d433994e32b0 Mon Sep 17 00:00:00 2001 From: PierreOssun Date: Mon, 24 Apr 2023 14:14:21 +0200 Subject: [PATCH 2/2] removed printlns --- chain-extensions/pallet-scheduler/src/lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/chain-extensions/pallet-scheduler/src/lib.rs b/chain-extensions/pallet-scheduler/src/lib.rs index 8dc57b91..e91a5d80 100644 --- a/chain-extensions/pallet-scheduler/src/lib.rs +++ b/chain-extensions/pallet-scheduler/src/lib.rs @@ -100,10 +100,10 @@ where schedule::Priority, ContractCallInput>, ) = env.read_as_unbounded(env.in_len())?; - - let read_weigth = ::read_as_unbounded(env.in_len()); - env.charge_weight(read_weigth)?; - + + let read_weight = ::read_as_unbounded(env.in_len()); + env.charge_weight(read_weight)?; + let base_weight = ::WeightInfo::schedule( T::MaxScheduledPerBlock::get(), ); @@ -129,7 +129,6 @@ where ); return match call_result { Err(e) => { - sp_std::if_std! {println!("Schedule:{:?}", e)}; let mapped_error = Outcome::from(e); Ok(RetVal::Converging(mapped_error as u32)) } @@ -157,7 +156,6 @@ where ); return match call_result { Err(e) => { - sp_std::if_std! {println!("Cancel:{:?}", e)}; let mapped_error = Outcome::from(e); Ok(RetVal::Converging(mapped_error as u32)) }