mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-30 23:37:56 +00:00
contracts: Allow contracts to dispatch calls into the runtime (#9276)
* contracts: Allow contracts to dispatch calls into the runtime * Fix RPC tests * Fix typo * Replace () by AllowAllFilter and DenyAllFilter * Add rust doc * Fixup for `()` removal * Fix lowest gas calculation * Rename AllowAllFilter and DenyAllFilter * Updated changelog
This commit is contained in:
committed by
GitHub
parent
2f31602896
commit
e01ac8cea0
Generated
+1
@@ -4871,6 +4871,7 @@ dependencies = [
|
|||||||
"pallet-contracts-proc-macro",
|
"pallet-contracts-proc-macro",
|
||||||
"pallet-randomness-collective-flip",
|
"pallet-randomness-collective-flip",
|
||||||
"pallet-timestamp",
|
"pallet-timestamp",
|
||||||
|
"pallet-utility",
|
||||||
"parity-scale-codec",
|
"parity-scale-codec",
|
||||||
"paste 1.0.4",
|
"paste 1.0.4",
|
||||||
"pretty_assertions 0.7.2",
|
"pretty_assertions 0.7.2",
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl system::Config for Test {
|
impl system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ parameter_types! {
|
|||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
/// The basic call filter to use in dispatchable.
|
/// The basic call filter to use in dispatchable.
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
/// Block & extrinsics weights: base values and limits.
|
/// Block & extrinsics weights: base values and limits.
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
/// The maximum length of a block (in bytes).
|
/// The maximum length of a block (in bytes).
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ use frame_support::{
|
|||||||
},
|
},
|
||||||
traits::{
|
traits::{
|
||||||
Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, LockIdentifier,
|
Currency, Imbalance, KeyOwnerProofSystem, OnUnbalanced, LockIdentifier,
|
||||||
U128CurrencyToVote,
|
U128CurrencyToVote, AllowAll, DenyAll,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use frame_system::{
|
use frame_system::{
|
||||||
@@ -193,7 +193,7 @@ parameter_types! {
|
|||||||
const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
|
const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = AllowAll;
|
||||||
type BlockWeights = RuntimeBlockWeights;
|
type BlockWeights = RuntimeBlockWeights;
|
||||||
type BlockLength = RuntimeBlockLength;
|
type BlockLength = RuntimeBlockLength;
|
||||||
type DbWeight = RocksDbWeight;
|
type DbWeight = RocksDbWeight;
|
||||||
@@ -839,6 +839,14 @@ impl pallet_contracts::Config for Runtime {
|
|||||||
type Randomness = RandomnessCollectiveFlip;
|
type Randomness = RandomnessCollectiveFlip;
|
||||||
type Currency = Balances;
|
type Currency = Balances;
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
|
type Call = Call;
|
||||||
|
/// The safest default is to allow no calls at all.
|
||||||
|
///
|
||||||
|
/// Runtimes should whitelist dispatchables that are allowed to be called from contracts
|
||||||
|
/// and make sure they are stable. Dispatchables exposed to contracts are not allowed to
|
||||||
|
/// change because that would break already deployed contracts. The `Call` structure itself
|
||||||
|
/// is not allowed to change the indices of existing pallets, too.
|
||||||
|
type CallFilter = DenyAll;
|
||||||
type RentPayment = ();
|
type RentPayment = ();
|
||||||
type SignedClaimHandicap = SignedClaimHandicap;
|
type SignedClaimHandicap = SignedClaimHandicap;
|
||||||
type TombstoneDeposit = TombstoneDeposit;
|
type TombstoneDeposit = TombstoneDeposit;
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ And update the overall definition for weights on frame and a few related types a
|
|||||||
+const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
|
+const_assert!(NORMAL_DISPATCH_RATIO.deconstruct() >= AVERAGE_ON_INITIALIZE_RATIO.deconstruct());
|
||||||
+
|
+
|
||||||
+impl frame_system::Config for Runtime {
|
+impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
+ type BlockWeights = RuntimeBlockWeights;
|
+ type BlockWeights = RuntimeBlockWeights;
|
||||||
+ type BlockLength = RuntimeBlockLength;
|
+ type BlockLength = RuntimeBlockLength;
|
||||||
+ type DbWeight = RocksDbWeight;
|
+ type DbWeight = RocksDbWeight;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ parameter_types! {
|
|||||||
pub const BlockHashCount: u64 = 250;
|
pub const BlockHashCount: u64 = 250;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ parameter_types! {
|
|||||||
pub static ExistentialDeposit: u64 = 0;
|
pub static ExistentialDeposit: u64 = 0;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ parameter_types! {
|
|||||||
pub static ExistentialDeposit: u64 = 0;
|
pub static ExistentialDeposit: u64 = 0;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ parameter_types! {
|
|||||||
pub static ExistentialDeposit: u64 = 0;
|
pub static ExistentialDeposit: u64 = 0;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ frame_support::construct_runtime!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -986,7 +986,7 @@ mod tests {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ In other words: Upgrading this pallet will not break pre-existing contracts.
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Allow contracts to dispatch calls into the runtime (**unstable**)
|
||||||
|
[#9276](https://github.com/paritytech/substrate/pull/9276)
|
||||||
|
|
||||||
- New **unstable** version of `seal_call` that offers more features.
|
- New **unstable** version of `seal_call` that offers more features.
|
||||||
[#8909](https://github.com/paritytech/substrate/pull/8909)
|
[#8909](https://github.com/paritytech/substrate/pull/8909)
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ wat = "1"
|
|||||||
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
|
pallet-balances = { version = "4.0.0-dev", path = "../balances" }
|
||||||
pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" }
|
pallet-timestamp = { version = "4.0.0-dev", path = "../timestamp" }
|
||||||
pallet-randomness-collective-flip = { version = "4.0.0-dev", path = "../randomness-collective-flip" }
|
pallet-randomness-collective-flip = { version = "4.0.0-dev", path = "../randomness-collective-flip" }
|
||||||
|
pallet-utility = { version = "4.0.0-dev", path = "../utility" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std"]
|
default = ["std"]
|
||||||
|
|||||||
@@ -37,6 +37,15 @@ use serde::{Serialize, Deserialize};
|
|||||||
pub struct ContractResult<T> {
|
pub struct ContractResult<T> {
|
||||||
/// How much gas was consumed during execution.
|
/// How much gas was consumed during execution.
|
||||||
pub gas_consumed: u64,
|
pub gas_consumed: u64,
|
||||||
|
/// How much gas is required as gas limit in order to execute this call.
|
||||||
|
///
|
||||||
|
/// This value should be used to determine the gas limit for on-chain execution.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// This can only different from [`Self::gas_consumed`] when weight pre charging
|
||||||
|
/// is used. Currently, only `seal_call_runtime` makes use of pre charging.
|
||||||
|
pub gas_required: u64,
|
||||||
/// An optional debug message. This message is only filled when explicitly requested
|
/// An optional debug message. This message is only filled when explicitly requested
|
||||||
/// by the code that calls into the contract. Otherwise it is empty.
|
/// by the code that calls into the contract. Otherwise it is empty.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
;; This passes its input to `seal_call_runtime` and returns the return value to its caller.
|
||||||
|
(module
|
||||||
|
(import "__unstable__" "seal_call_runtime" (func $seal_call_runtime (param i32 i32) (result i32)))
|
||||||
|
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||||
|
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||||
|
(import "env" "memory" (memory 1 1))
|
||||||
|
|
||||||
|
;; 0x1000 = 4k in little endian
|
||||||
|
;; size of input buffer
|
||||||
|
(data (i32.const 0) "\00\10")
|
||||||
|
|
||||||
|
(func (export "call")
|
||||||
|
;; Receive the encoded call
|
||||||
|
(call $seal_input
|
||||||
|
(i32.const 4) ;; Pointer to the input buffer
|
||||||
|
(i32.const 0) ;; Size of the length buffer
|
||||||
|
)
|
||||||
|
;; Just use the call passed as input and store result to memory
|
||||||
|
(i32.store (i32.const 0)
|
||||||
|
(call $seal_call_runtime
|
||||||
|
(i32.const 4) ;; Pointer where the call is stored
|
||||||
|
(i32.load (i32.const 0)) ;; Size of the call
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(call $seal_return
|
||||||
|
(i32.const 0) ;; flags
|
||||||
|
(i32.const 0) ;; returned value
|
||||||
|
(i32.const 4) ;; length of returned value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func (export "deploy"))
|
||||||
|
)
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
;; This expects [account_id, gas_limit] as input and calls the account_id with the supplied gas_limit.
|
||||||
|
;; It returns the result of the call as output data.
|
||||||
|
(module
|
||||||
|
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||||
|
(import "seal0" "seal_call" (func $seal_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
|
||||||
|
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||||
|
(import "env" "memory" (memory 1 1))
|
||||||
|
|
||||||
|
;; 0x1000 = 4k in little endian
|
||||||
|
;; size of input buffer
|
||||||
|
(data (i32.const 0) "\00\10")
|
||||||
|
|
||||||
|
(func (export "deploy"))
|
||||||
|
|
||||||
|
(func (export "call")
|
||||||
|
;; Receive the encoded call + gas_limit
|
||||||
|
(call $seal_input
|
||||||
|
(i32.const 4) ;; Pointer to the input buffer
|
||||||
|
(i32.const 0) ;; Size of the length buffer
|
||||||
|
)
|
||||||
|
(i32.store
|
||||||
|
(i32.const 0)
|
||||||
|
(call $seal_call
|
||||||
|
(i32.const 4) ;; Pointer to "callee" address.
|
||||||
|
(i32.const 32) ;; Length of "callee" address.
|
||||||
|
(i64.load (i32.const 36)) ;; How much gas to devote for the execution.
|
||||||
|
(i32.const 0) ;; Pointer to the buffer with value to transfer
|
||||||
|
(i32.const 0) ;; Length of the buffer with value to transfer.
|
||||||
|
(i32.const 0) ;; Pointer to input data buffer address
|
||||||
|
(i32.const 0) ;; Length of input data buffer
|
||||||
|
(i32.const 0xffffffff) ;; u32 max sentinel value: do not copy output
|
||||||
|
(i32.const 0) ;; Ptr to output buffer len
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -385,7 +385,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
test(r#"{
|
test(r#"{
|
||||||
"gasConsumed": 5000,
|
"gasConsumed": 5000,
|
||||||
"debugMessage": "0x68656c704f6b",
|
"gasRequired": 8000,
|
||||||
|
"debugMessage": "HelloWorld",
|
||||||
"result": {
|
"result": {
|
||||||
"Ok": {
|
"Ok": {
|
||||||
"flags": 5,
|
"flags": 5,
|
||||||
@@ -395,7 +396,8 @@ mod tests {
|
|||||||
}"#);
|
}"#);
|
||||||
test(r#"{
|
test(r#"{
|
||||||
"gasConsumed": 3400,
|
"gasConsumed": 3400,
|
||||||
"debugMessage": "0x68656c70457272",
|
"gasRequired": 5200,
|
||||||
|
"debugMessage": "HelloWorld",
|
||||||
"result": {
|
"result": {
|
||||||
"Err": "BadOrigin"
|
"Err": "BadOrigin"
|
||||||
}
|
}
|
||||||
@@ -411,7 +413,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
test(r#"{
|
test(r#"{
|
||||||
"gasConsumed": 5000,
|
"gasConsumed": 5000,
|
||||||
"debugMessage": "0x68656c704f6b",
|
"gasRequired": 8000,
|
||||||
|
"debugMessage": "HelloWorld",
|
||||||
"result": {
|
"result": {
|
||||||
"Ok": {
|
"Ok": {
|
||||||
"result": {
|
"result": {
|
||||||
@@ -425,7 +428,8 @@ mod tests {
|
|||||||
}"#);
|
}"#);
|
||||||
test(r#"{
|
test(r#"{
|
||||||
"gasConsumed": 3400,
|
"gasConsumed": 3400,
|
||||||
"debugMessage": "0x68656c70457272",
|
"gasRequired": 5200,
|
||||||
|
"debugMessage": "HelloWorld",
|
||||||
"result": {
|
"result": {
|
||||||
"Err": "BadOrigin"
|
"Err": "BadOrigin"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
wasm::{Runtime, RuntimeCosts},
|
wasm::{Runtime, RuntimeCosts},
|
||||||
|
gas::ChargedAmount,
|
||||||
};
|
};
|
||||||
use codec::{Decode, MaxEncodedLen};
|
use codec::{Decode, MaxEncodedLen};
|
||||||
use frame_support::weights::Weight;
|
use frame_support::weights::Weight;
|
||||||
@@ -167,11 +168,22 @@ where
|
|||||||
/// `weight`. It returns `Err` otherwise. In this case the chain extension should
|
/// `weight`. It returns `Err` otherwise. In this case the chain extension should
|
||||||
/// abort the execution and pass through the error.
|
/// abort the execution and pass through the error.
|
||||||
///
|
///
|
||||||
|
/// The returned value can be used to with [`Self::adjust_weight`]. Other than that
|
||||||
|
/// it has no purpose.
|
||||||
|
///
|
||||||
/// # Note
|
/// # Note
|
||||||
///
|
///
|
||||||
/// Weight is synonymous with gas in substrate.
|
/// Weight is synonymous with gas in substrate.
|
||||||
pub fn charge_weight(&mut self, amount: Weight) -> Result<()> {
|
pub fn charge_weight(&mut self, amount: Weight) -> Result<ChargedAmount> {
|
||||||
self.inner.runtime.charge_gas(RuntimeCosts::ChainExtension(amount)).map(|_| ())
|
self.inner.runtime.charge_gas(RuntimeCosts::ChainExtension(amount))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adjust a previously charged amount down to its actual amount.
|
||||||
|
///
|
||||||
|
/// This is when a maximum a priori amount was charged and then should be partially
|
||||||
|
/// refunded to match the actual amount.
|
||||||
|
pub fn adjust_weight(&mut self, charged: ChargedAmount, actual_weight: Weight) {
|
||||||
|
self.inner.runtime.adjust_gas(charged, RuntimeCosts::ChainExtension(actual_weight))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grants access to the execution environment of the current contract call.
|
/// Grants access to the execution environment of the current contract call.
|
||||||
|
|||||||
@@ -28,12 +28,13 @@ use sp_std::{
|
|||||||
};
|
};
|
||||||
use sp_runtime::{Perbill, traits::{Convert, Saturating}};
|
use sp_runtime::{Perbill, traits::{Convert, Saturating}};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
dispatch::{DispatchResult, DispatchError},
|
dispatch::{DispatchResult, DispatchError, DispatchResultWithPostInfo, Dispatchable},
|
||||||
storage::{with_transaction, TransactionOutcome},
|
storage::{with_transaction, TransactionOutcome},
|
||||||
traits::{ExistenceRequirement, Currency, Time, Randomness, Get},
|
traits::{ExistenceRequirement, Currency, Time, Randomness, Get, OriginTrait, Filter},
|
||||||
weights::Weight,
|
weights::Weight,
|
||||||
ensure, DefaultNoBound,
|
ensure, DefaultNoBound,
|
||||||
};
|
};
|
||||||
|
use frame_system::RawOrigin;
|
||||||
use pallet_contracts_primitives::{ExecReturnValue};
|
use pallet_contracts_primitives::{ExecReturnValue};
|
||||||
use smallvec::{SmallVec, Array};
|
use smallvec::{SmallVec, Array};
|
||||||
|
|
||||||
@@ -300,6 +301,9 @@ pub trait Ext: sealing::Sealed {
|
|||||||
///
|
///
|
||||||
/// Returns `true` if debug message recording is enabled. Otherwise `false` is returned.
|
/// Returns `true` if debug message recording is enabled. Otherwise `false` is returned.
|
||||||
fn append_debug_buffer(&mut self, msg: &str) -> bool;
|
fn append_debug_buffer(&mut self, msg: &str) -> bool;
|
||||||
|
|
||||||
|
/// Call some dispatchable and return the result.
|
||||||
|
fn call_runtime(&self, call: <Self::T as Config>::Call) -> DispatchResultWithPostInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Describes the different functions that can be exported by an [`Executable`].
|
/// Describes the different functions that can be exported by an [`Executable`].
|
||||||
@@ -1291,6 +1295,12 @@ where
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call_runtime(&self, call: <Self::T as Config>::Call) -> DispatchResultWithPostInfo {
|
||||||
|
let mut origin: T::Origin = RawOrigin::Signed(self.address().clone()).into();
|
||||||
|
origin.add_filter(T::CallFilter::filter);
|
||||||
|
call.dispatch(origin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deposit_event<T: Config>(
|
fn deposit_event<T: Config>(
|
||||||
@@ -1326,10 +1336,10 @@ mod sealing {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
gas::GasMeter, tests::{ExtBuilder, Test, Event as MetaEvent},
|
gas::GasMeter,
|
||||||
storage::Storage,
|
storage::Storage,
|
||||||
tests::{
|
tests::{
|
||||||
ALICE, BOB, CHARLIE,
|
ALICE, BOB, CHARLIE, Call, TestFilter, ExtBuilder, Test, Event as MetaEvent,
|
||||||
test_utils::{place_contract, set_balance, get_balance},
|
test_utils::{place_contract, set_balance, get_balance},
|
||||||
},
|
},
|
||||||
exec::ExportedFunction::*,
|
exec::ExportedFunction::*,
|
||||||
@@ -1337,12 +1347,15 @@ mod tests {
|
|||||||
};
|
};
|
||||||
use codec::{Encode, Decode};
|
use codec::{Encode, Decode};
|
||||||
use sp_core::Bytes;
|
use sp_core::Bytes;
|
||||||
use sp_runtime::DispatchError;
|
use sp_runtime::{DispatchError, traits::{BadOrigin, Hash}};
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
use pretty_assertions::{assert_eq, assert_ne};
|
use pretty_assertions::{assert_eq, assert_ne};
|
||||||
use pallet_contracts_primitives::ReturnFlags;
|
use pallet_contracts_primitives::ReturnFlags;
|
||||||
use frame_support::{assert_ok, assert_err};
|
use frame_support::{assert_ok, assert_err};
|
||||||
|
use frame_system::{EventRecord, Phase};
|
||||||
|
|
||||||
|
type System = frame_system::Pallet<Test>;
|
||||||
|
|
||||||
type MockStack<'a> = Stack<'a, Test, MockExecutable>;
|
type MockStack<'a> = Stack<'a, Test, MockExecutable>;
|
||||||
|
|
||||||
@@ -1353,7 +1366,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn events() -> Vec<Event<Test>> {
|
fn events() -> Vec<Event<Test>> {
|
||||||
<frame_system::Pallet<Test>>::events()
|
System::events()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|meta| match meta.event {
|
.filter_map(|meta| match meta.event {
|
||||||
MetaEvent::Contracts(contract_event) => Some(contract_event),
|
MetaEvent::Contracts(contract_event) => Some(contract_event),
|
||||||
@@ -2503,4 +2516,114 @@ mod tests {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn call_runtime_works() {
|
||||||
|
let code_hash = MockLoader::insert(Call, |ctx, _| {
|
||||||
|
let call = Call::System(frame_system::Call::remark_with_event(b"Hello World".to_vec()));
|
||||||
|
ctx.ext.call_runtime(call).unwrap();
|
||||||
|
exec_success()
|
||||||
|
});
|
||||||
|
|
||||||
|
ExtBuilder::default().build().execute_with(|| {
|
||||||
|
let subsistence = Contracts::<Test>::subsistence_threshold();
|
||||||
|
let schedule = <Test as Config>::Schedule::get();
|
||||||
|
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
|
||||||
|
set_balance(&ALICE, subsistence * 10);
|
||||||
|
place_contract(&BOB, code_hash);
|
||||||
|
System::reset_events();
|
||||||
|
MockStack::run_call(
|
||||||
|
ALICE,
|
||||||
|
BOB,
|
||||||
|
&mut gas_meter,
|
||||||
|
&schedule,
|
||||||
|
0,
|
||||||
|
vec![],
|
||||||
|
None,
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello World");
|
||||||
|
assert_eq!(System::events(), vec![
|
||||||
|
EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: MetaEvent::System(frame_system::Event::Remarked(BOB, remark_hash)),
|
||||||
|
topics: vec![],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn call_runtime_filter() {
|
||||||
|
let code_hash = MockLoader::insert(Call, |ctx, _| {
|
||||||
|
use frame_system::Call as SysCall;
|
||||||
|
use pallet_balances::Call as BalanceCall;
|
||||||
|
use pallet_utility::Call as UtilCall;
|
||||||
|
|
||||||
|
// remark should still be allowed
|
||||||
|
let allowed_call = Call::System(SysCall::remark_with_event(b"Hello".to_vec()));
|
||||||
|
|
||||||
|
// transfers are disallowed by the `TestFiler` (see below)
|
||||||
|
let forbidden_call = Call::Balances(BalanceCall::transfer(CHARLIE, 22));
|
||||||
|
|
||||||
|
// simple cases: direct call
|
||||||
|
assert_err!(
|
||||||
|
ctx.ext.call_runtime(forbidden_call.clone()),
|
||||||
|
BadOrigin,
|
||||||
|
);
|
||||||
|
|
||||||
|
// as part of a patch: return is OK (but it interrupted the batch)
|
||||||
|
assert_ok!(
|
||||||
|
ctx.ext.call_runtime(Call::Utility(UtilCall::batch(vec![
|
||||||
|
allowed_call.clone(), forbidden_call, allowed_call
|
||||||
|
]))),
|
||||||
|
);
|
||||||
|
|
||||||
|
// the transfer wasn't performed
|
||||||
|
assert_eq!(get_balance(&CHARLIE), 0);
|
||||||
|
|
||||||
|
exec_success()
|
||||||
|
});
|
||||||
|
|
||||||
|
TestFilter::set_filter(|call| {
|
||||||
|
match call {
|
||||||
|
Call::Balances(pallet_balances::Call::transfer(_, _)) => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ExtBuilder::default().build().execute_with(|| {
|
||||||
|
let subsistence = Contracts::<Test>::subsistence_threshold();
|
||||||
|
let schedule = <Test as Config>::Schedule::get();
|
||||||
|
let mut gas_meter = GasMeter::<Test>::new(GAS_LIMIT);
|
||||||
|
set_balance(&ALICE, subsistence * 10);
|
||||||
|
place_contract(&BOB, code_hash);
|
||||||
|
System::reset_events();
|
||||||
|
MockStack::run_call(
|
||||||
|
ALICE,
|
||||||
|
BOB,
|
||||||
|
&mut gas_meter,
|
||||||
|
&schedule,
|
||||||
|
0,
|
||||||
|
vec![],
|
||||||
|
None,
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
let remark_hash = <Test as frame_system::Config>::Hashing::hash(b"Hello");
|
||||||
|
assert_eq!(System::events(), vec![
|
||||||
|
EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: MetaEvent::System(frame_system::Event::Remarked(BOB, remark_hash)),
|
||||||
|
topics: vec![],
|
||||||
|
},
|
||||||
|
EventRecord {
|
||||||
|
phase: Phase::Initialization,
|
||||||
|
event: MetaEvent::Utility(
|
||||||
|
pallet_utility::Event::BatchInterrupted(1, BadOrigin.into()),
|
||||||
|
),
|
||||||
|
topics: vec![],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ pub struct GasMeter<T: Config> {
|
|||||||
gas_limit: Weight,
|
gas_limit: Weight,
|
||||||
/// Amount of gas left from initial gas limit. Can reach zero.
|
/// Amount of gas left from initial gas limit. Can reach zero.
|
||||||
gas_left: Weight,
|
gas_left: Weight,
|
||||||
|
/// Due to `adjust_gas` and `nested` the `gas_left` can temporarily dip below its final value.
|
||||||
|
gas_left_lowest: Weight,
|
||||||
_phantom: PhantomData<T>,
|
_phantom: PhantomData<T>,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
tokens: Vec<ErasedToken>,
|
tokens: Vec<ErasedToken>,
|
||||||
@@ -92,6 +94,7 @@ where
|
|||||||
GasMeter {
|
GasMeter {
|
||||||
gas_limit,
|
gas_limit,
|
||||||
gas_left: gas_limit,
|
gas_left: gas_limit,
|
||||||
|
gas_left_lowest: gas_limit,
|
||||||
_phantom: PhantomData,
|
_phantom: PhantomData,
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
tokens: Vec::new(),
|
tokens: Vec::new(),
|
||||||
@@ -122,6 +125,19 @@ where
|
|||||||
|
|
||||||
/// Absorb the remaining gas of a nested meter after we are done using it.
|
/// Absorb the remaining gas of a nested meter after we are done using it.
|
||||||
pub fn absorb_nested(&mut self, nested: Self) {
|
pub fn absorb_nested(&mut self, nested: Self) {
|
||||||
|
if self.gas_left == 0 {
|
||||||
|
// All of the remaining gas was inherited by the nested gas meter. When absorbing
|
||||||
|
// we can therefore safely inherit the lowest gas that the nested gas meter experienced
|
||||||
|
// as long as it is lower than the lowest gas that was experienced by the parent.
|
||||||
|
// We cannot call `self.gas_left_lowest()` here because in the state that this
|
||||||
|
// code is run the parent gas meter has `0` gas left.
|
||||||
|
self.gas_left_lowest = nested.gas_left_lowest().min(self.gas_left_lowest);
|
||||||
|
} else {
|
||||||
|
// The nested gas meter was created with a fixed amount that did not consume all of the
|
||||||
|
// parents (self) gas. The lowest gas that self will experience is when the nested
|
||||||
|
// gas was pre charged with the fixed amount.
|
||||||
|
self.gas_left_lowest = self.gas_left_lowest();
|
||||||
|
}
|
||||||
self.gas_left += nested.gas_left;
|
self.gas_left += nested.gas_left;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,12 +179,21 @@ where
|
|||||||
/// This is when a maximum a priori amount was charged and then should be partially
|
/// This is when a maximum a priori amount was charged and then should be partially
|
||||||
/// refunded to match the actual amount.
|
/// refunded to match the actual amount.
|
||||||
pub fn adjust_gas<Tok: Token<T>>(&mut self, charged_amount: ChargedAmount, token: Tok) {
|
pub fn adjust_gas<Tok: Token<T>>(&mut self, charged_amount: ChargedAmount, token: Tok) {
|
||||||
|
self.gas_left_lowest = self.gas_left_lowest();
|
||||||
let adjustment = charged_amount.0.saturating_sub(token.weight());
|
let adjustment = charged_amount.0.saturating_sub(token.weight());
|
||||||
self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit);
|
self.gas_left = self.gas_left.saturating_add(adjustment).min(self.gas_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns how much gas was used.
|
/// Returns the amount of gas that is required to run the same call.
|
||||||
pub fn gas_spent(&self) -> Weight {
|
///
|
||||||
|
/// This can be different from `gas_spent` because due to `adjust_gas` the amount of
|
||||||
|
/// spent gas can temporarily drop and be refunded later.
|
||||||
|
pub fn gas_required(&self) -> Weight {
|
||||||
|
self.gas_limit - self.gas_left_lowest()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns how much gas was spent
|
||||||
|
pub fn gas_consumed(&self) -> Weight {
|
||||||
self.gas_limit - self.gas_left
|
self.gas_limit - self.gas_left
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,14 +204,15 @@ where
|
|||||||
|
|
||||||
/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
|
/// Turn this GasMeter into a DispatchResult that contains the actually used gas.
|
||||||
pub fn into_dispatch_result<R, E>(
|
pub fn into_dispatch_result<R, E>(
|
||||||
self, result: Result<R, E>,
|
self,
|
||||||
|
result: Result<R, E>,
|
||||||
base_weight: Weight,
|
base_weight: Weight,
|
||||||
) -> DispatchResultWithPostInfo
|
) -> DispatchResultWithPostInfo
|
||||||
where
|
where
|
||||||
E: Into<ExecError>,
|
E: Into<ExecError>,
|
||||||
{
|
{
|
||||||
let post_info = PostDispatchInfo {
|
let post_info = PostDispatchInfo {
|
||||||
actual_weight: Some(self.gas_spent().saturating_add(base_weight)),
|
actual_weight: Some(self.gas_consumed().saturating_add(base_weight)),
|
||||||
pays_fee: Default::default(),
|
pays_fee: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -195,6 +221,10 @@ where
|
|||||||
.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e.into().error })
|
.map_err(|e| DispatchErrorWithPostInfo { post_info, error: e.into().error })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gas_left_lowest(&self) -> Weight {
|
||||||
|
self.gas_left_lowest.min(self.gas_left)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub fn tokens(&self) -> &[ErasedToken] {
|
pub fn tokens(&self) -> &[ErasedToken] {
|
||||||
&self.tokens
|
&self.tokens
|
||||||
|
|||||||
@@ -118,8 +118,9 @@ use sp_runtime::{
|
|||||||
Perbill,
|
Perbill,
|
||||||
};
|
};
|
||||||
use frame_support::{
|
use frame_support::{
|
||||||
traits::{OnUnbalanced, Currency, Get, Time, Randomness},
|
traits::{OnUnbalanced, Currency, Get, Time, Randomness, Filter},
|
||||||
weights::{Weight, PostDispatchInfo, WithPostDispatchInfo},
|
weights::{Weight, PostDispatchInfo, WithPostDispatchInfo, GetDispatchInfo},
|
||||||
|
dispatch::Dispatchable,
|
||||||
};
|
};
|
||||||
use frame_system::Pallet as System;
|
use frame_system::Pallet as System;
|
||||||
use pallet_contracts_primitives::{
|
use pallet_contracts_primitives::{
|
||||||
@@ -154,6 +155,41 @@ pub mod pallet {
|
|||||||
/// The overarching event type.
|
/// The overarching event type.
|
||||||
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
|
||||||
|
|
||||||
|
/// The overarching call type.
|
||||||
|
type Call:
|
||||||
|
Dispatchable<Origin=Self::Origin, PostInfo=PostDispatchInfo> +
|
||||||
|
GetDispatchInfo +
|
||||||
|
codec::Decode +
|
||||||
|
IsType<<Self as frame_system::Config>::Call>;
|
||||||
|
|
||||||
|
/// Filter that is applied to calls dispatched by contracts.
|
||||||
|
///
|
||||||
|
/// Use this filter to control which dispatchables are callable by contracts.
|
||||||
|
/// This is applied in **addition** to [`frame_system::Config::BaseCallFilter`].
|
||||||
|
/// It is recommended to treat this as a whitelist.
|
||||||
|
///
|
||||||
|
/// # Subsistence Threshold
|
||||||
|
///
|
||||||
|
/// The runtime **must** make sure that any allowed dispatchable makes sure that the
|
||||||
|
/// `total_balance` of the contract stays above [`Pallet::subsistence_threshold()`].
|
||||||
|
/// Otherwise contracts can clutter the storage with their tombstones without
|
||||||
|
/// deposting the correct amount of balance.
|
||||||
|
///
|
||||||
|
/// # Stability
|
||||||
|
///
|
||||||
|
/// The runtime **must** make sure that all dispatchables that are callable by
|
||||||
|
/// contracts remain stable. In addition [`Self::Call`] itself must remain stable.
|
||||||
|
/// This means that no existing variants are allowed to switch their positions.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
///
|
||||||
|
/// Note that dispatchables that are called via contracts do not spawn their
|
||||||
|
/// own wasm instance for each call (as opposed to when called via a transaction).
|
||||||
|
/// Therefore please make sure to be restrictive about which dispatchables are allowed
|
||||||
|
/// in order to not introduce a new DoS vector like memory allocation patterns that can
|
||||||
|
/// be exploited to drive the runtime into a panic.
|
||||||
|
type CallFilter: Filter<<Self as frame_system::Config>::Call>;
|
||||||
|
|
||||||
/// Handler for rent payments.
|
/// Handler for rent payments.
|
||||||
type RentPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
type RentPayment: OnUnbalanced<NegativeImbalanceOf<Self>>;
|
||||||
|
|
||||||
@@ -658,7 +694,8 @@ where
|
|||||||
);
|
);
|
||||||
ContractExecResult {
|
ContractExecResult {
|
||||||
result: result.map_err(|r| r.error),
|
result: result.map_err(|r| r.error),
|
||||||
gas_consumed: gas_meter.gas_spent(),
|
gas_consumed: gas_meter.gas_consumed(),
|
||||||
|
gas_required: gas_meter.gas_required(),
|
||||||
debug_message: debug_message.unwrap_or_default(),
|
debug_message: debug_message.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -699,7 +736,8 @@ where
|
|||||||
Ok(executable) => executable,
|
Ok(executable) => executable,
|
||||||
Err(error) => return ContractInstantiateResult {
|
Err(error) => return ContractInstantiateResult {
|
||||||
result: Err(error.into()),
|
result: Err(error.into()),
|
||||||
gas_consumed: gas_meter.gas_spent(),
|
gas_consumed: gas_meter.gas_consumed(),
|
||||||
|
gas_required: gas_meter.gas_required(),
|
||||||
debug_message: Vec::new(),
|
debug_message: Vec::new(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -727,7 +765,8 @@ where
|
|||||||
});
|
});
|
||||||
ContractInstantiateResult {
|
ContractInstantiateResult {
|
||||||
result: result.map_err(|e| e.error),
|
result: result.map_err(|e| e.error),
|
||||||
gas_consumed: gas_meter.gas_spent(),
|
gas_consumed: gas_meter.gas_consumed(),
|
||||||
|
gas_required: gas_meter.gas_required(),
|
||||||
debug_message: debug_message.unwrap_or_default(),
|
debug_message: debug_message.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,13 +40,14 @@ use sp_io::hashing::blake2_256;
|
|||||||
use frame_support::{
|
use frame_support::{
|
||||||
assert_ok, assert_err, assert_err_ignore_postinfo,
|
assert_ok, assert_err, assert_err_ignore_postinfo,
|
||||||
parameter_types, assert_storage_noop,
|
parameter_types, assert_storage_noop,
|
||||||
traits::{Currency, ReservableCurrency, OnInitialize},
|
traits::{Currency, ReservableCurrency, OnInitialize, Filter},
|
||||||
weights::{Weight, PostDispatchInfo, DispatchClass, constants::WEIGHT_PER_SECOND},
|
weights::{Weight, PostDispatchInfo, DispatchClass, constants::WEIGHT_PER_SECOND},
|
||||||
dispatch::DispatchErrorWithPostInfo,
|
dispatch::DispatchErrorWithPostInfo,
|
||||||
storage::child,
|
storage::child,
|
||||||
};
|
};
|
||||||
use frame_system::{self as system, EventRecord, Phase};
|
use frame_system::{self as system, EventRecord, Phase};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
use crate as pallet_contracts;
|
use crate as pallet_contracts;
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ frame_support::construct_runtime!(
|
|||||||
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
|
||||||
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
|
Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent},
|
||||||
Randomness: pallet_randomness_collective_flip::{Pallet, Storage},
|
Randomness: pallet_randomness_collective_flip::{Pallet, Storage},
|
||||||
|
Utility: pallet_utility::{Pallet, Call, Storage, Event},
|
||||||
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
|
Contracts: pallet_contracts::{Pallet, Call, Storage, Event<T>},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -125,7 +127,7 @@ pub mod test_utils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static TEST_EXTENSION: sp_std::cell::RefCell<TestExtension> = Default::default();
|
static TEST_EXTENSION: RefCell<TestExtension> = Default::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestExtension {
|
pub struct TestExtension {
|
||||||
@@ -211,7 +213,7 @@ parameter_types! {
|
|||||||
pub static ExistentialDeposit: u64 = 0;
|
pub static ExistentialDeposit: u64 = 0;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
@@ -256,6 +258,11 @@ impl pallet_timestamp::Config for Test {
|
|||||||
type MinimumPeriod = MinimumPeriod;
|
type MinimumPeriod = MinimumPeriod;
|
||||||
type WeightInfo = ();
|
type WeightInfo = ();
|
||||||
}
|
}
|
||||||
|
impl pallet_utility::Config for Test {
|
||||||
|
type Event = Event;
|
||||||
|
type Call = Call;
|
||||||
|
type WeightInfo = ();
|
||||||
|
}
|
||||||
parameter_types! {
|
parameter_types! {
|
||||||
pub const SignedClaimHandicap: u64 = 2;
|
pub const SignedClaimHandicap: u64 = 2;
|
||||||
pub const TombstoneDeposit: u64 = 16;
|
pub const TombstoneDeposit: u64 = 16;
|
||||||
@@ -269,9 +276,6 @@ parameter_types! {
|
|||||||
pub const DeletionWeightLimit: Weight = 500_000_000_000;
|
pub const DeletionWeightLimit: Weight = 500_000_000_000;
|
||||||
pub const MaxCodeSize: u32 = 2 * 1024;
|
pub const MaxCodeSize: u32 = 2 * 1024;
|
||||||
pub MySchedule: Schedule<Test> = <Schedule<Test>>::default();
|
pub MySchedule: Schedule<Test> = <Schedule<Test>>::default();
|
||||||
}
|
|
||||||
|
|
||||||
parameter_types! {
|
|
||||||
pub const TransactionByteFee: u64 = 0;
|
pub const TransactionByteFee: u64 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,11 +285,32 @@ impl Convert<Weight, BalanceOf<Self>> for Test {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A filter whose filter function can be swapped at runtime.
|
||||||
|
pub struct TestFilter;
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static CALL_FILTER: RefCell<fn(&Call) -> bool> = RefCell::new(|_| true);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestFilter {
|
||||||
|
pub fn set_filter(filter: fn(&Call) -> bool) {
|
||||||
|
CALL_FILTER.with(|fltr| *fltr.borrow_mut() = filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Filter<Call> for TestFilter {
|
||||||
|
fn filter(call: &Call) -> bool {
|
||||||
|
CALL_FILTER.with(|fltr| fltr.borrow()(call))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Config for Test {
|
impl Config for Test {
|
||||||
type Time = Timestamp;
|
type Time = Timestamp;
|
||||||
type Randomness = Randomness;
|
type Randomness = Randomness;
|
||||||
type Currency = Balances;
|
type Currency = Balances;
|
||||||
type Event = Event;
|
type Event = Event;
|
||||||
|
type Call = Call;
|
||||||
|
type CallFilter = TestFilter;
|
||||||
type RentPayment = ();
|
type RentPayment = ();
|
||||||
type SignedClaimHandicap = SignedClaimHandicap;
|
type SignedClaimHandicap = SignedClaimHandicap;
|
||||||
type TombstoneDeposit = TombstoneDeposit;
|
type TombstoneDeposit = TombstoneDeposit;
|
||||||
@@ -2944,8 +2969,8 @@ fn debug_message_invalid_utf8() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn gas_estimation_correct() {
|
fn gas_estimation_nested_call_fixed_limit() {
|
||||||
let (caller_code, caller_hash) = compile_module::<Test>("call_return_code").unwrap();
|
let (caller_code, caller_hash) = compile_module::<Test>("call_with_limit").unwrap();
|
||||||
let (callee_code, callee_hash) = compile_module::<Test>("dummy").unwrap();
|
let (callee_code, callee_hash) = compile_module::<Test>("dummy").unwrap();
|
||||||
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
|
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
|
||||||
let subsistence = Pallet::<Test>::subsistence_threshold();
|
let subsistence = Pallet::<Test>::subsistence_threshold();
|
||||||
@@ -2976,24 +3001,93 @@ fn gas_estimation_correct() {
|
|||||||
);
|
);
|
||||||
let addr_callee = Contracts::contract_address(&ALICE, &callee_hash, &[1]);
|
let addr_callee = Contracts::contract_address(&ALICE, &callee_hash, &[1]);
|
||||||
|
|
||||||
|
let input: Vec<u8> = AsRef::<[u8]>::as_ref(&addr_callee)
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain((GAS_LIMIT / 5).to_le_bytes())
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Call in order to determine the gas that is required for this call
|
// Call in order to determine the gas that is required for this call
|
||||||
let result = Contracts::bare_call(
|
let result = Contracts::bare_call(
|
||||||
ALICE,
|
ALICE,
|
||||||
addr_caller.clone(),
|
addr_caller.clone(),
|
||||||
0,
|
0,
|
||||||
GAS_LIMIT,
|
GAS_LIMIT,
|
||||||
AsRef::<[u8]>::as_ref(&addr_callee).to_vec(),
|
input.clone(),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
assert_ok!(result.result);
|
assert_ok!(&result.result);
|
||||||
|
|
||||||
|
assert!(result.gas_required > result.gas_consumed);
|
||||||
|
|
||||||
// Make the same call using the estimated gas. Should succeed.
|
// Make the same call using the estimated gas. Should succeed.
|
||||||
assert_ok!(Contracts::bare_call(
|
assert_ok!(Contracts::bare_call(
|
||||||
ALICE,
|
ALICE,
|
||||||
addr_caller,
|
addr_caller,
|
||||||
0,
|
0,
|
||||||
result.gas_consumed,
|
result.gas_required,
|
||||||
AsRef::<[u8]>::as_ref(&addr_callee).to_vec(),
|
input,
|
||||||
|
false,
|
||||||
|
).result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
fn gas_estimation_call_runtime() {
|
||||||
|
let (caller_code, caller_hash) = compile_module::<Test>("call_runtime").unwrap();
|
||||||
|
let (callee_code, callee_hash) = compile_module::<Test>("dummy").unwrap();
|
||||||
|
ExtBuilder::default().existential_deposit(50).build().execute_with(|| {
|
||||||
|
let subsistence = Pallet::<Test>::subsistence_threshold();
|
||||||
|
let _ = Balances::deposit_creating(&ALICE, 1000 * subsistence);
|
||||||
|
let _ = Balances::deposit_creating(&CHARLIE, 1000 * subsistence);
|
||||||
|
|
||||||
|
assert_ok!(
|
||||||
|
Contracts::instantiate_with_code(
|
||||||
|
Origin::signed(ALICE),
|
||||||
|
subsistence * 100,
|
||||||
|
GAS_LIMIT,
|
||||||
|
caller_code,
|
||||||
|
vec![],
|
||||||
|
vec![0],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let addr_caller = Contracts::contract_address(&ALICE, &caller_hash, &[0]);
|
||||||
|
|
||||||
|
assert_ok!(
|
||||||
|
Contracts::instantiate_with_code(
|
||||||
|
Origin::signed(ALICE),
|
||||||
|
subsistence * 100,
|
||||||
|
GAS_LIMIT,
|
||||||
|
callee_code,
|
||||||
|
vec![],
|
||||||
|
vec![1],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
let addr_callee = Contracts::contract_address(&ALICE, &callee_hash, &[1]);
|
||||||
|
|
||||||
|
// Call something trivial with a huge gas limit so that we can observe the effects
|
||||||
|
// of pre-charging. This should create a difference between consumed and required.
|
||||||
|
let call = Call::Contracts(crate::Call::call(addr_callee, 0, GAS_LIMIT / 3, vec![]));
|
||||||
|
let result = Contracts::bare_call(
|
||||||
|
ALICE,
|
||||||
|
addr_caller.clone(),
|
||||||
|
0,
|
||||||
|
GAS_LIMIT,
|
||||||
|
call.encode(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
assert_ok!(&result.result);
|
||||||
|
|
||||||
|
assert!(result.gas_required > result.gas_consumed);
|
||||||
|
|
||||||
|
// Make the same call using the required gas. Should succeed.
|
||||||
|
assert_ok!(Contracts::bare_call(
|
||||||
|
ALICE,
|
||||||
|
addr_caller,
|
||||||
|
0,
|
||||||
|
result.gas_required,
|
||||||
|
call.encode(),
|
||||||
false,
|
false,
|
||||||
).result);
|
).result);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -254,18 +254,22 @@ mod tests {
|
|||||||
rent::RentStatus,
|
rent::RentStatus,
|
||||||
tests::{Test, Call, ALICE, BOB},
|
tests::{Test, Call, ALICE, BOB},
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::{
|
||||||
|
borrow::BorrowMut,
|
||||||
|
cell::RefCell,
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
use sp_core::{Bytes, H256};
|
use sp_core::{Bytes, H256};
|
||||||
use hex_literal::hex;
|
use hex_literal::hex;
|
||||||
use sp_runtime::DispatchError;
|
use sp_runtime::DispatchError;
|
||||||
use frame_support::{assert_ok, dispatch::DispatchResult, weights::Weight};
|
use frame_support::{
|
||||||
|
assert_ok,
|
||||||
|
dispatch::{DispatchResult, DispatchResultWithPostInfo},
|
||||||
|
weights::Weight,
|
||||||
|
};
|
||||||
use assert_matches::assert_matches;
|
use assert_matches::assert_matches;
|
||||||
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
|
use pallet_contracts_primitives::{ExecReturnValue, ReturnFlags};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use sp_std::borrow::BorrowMut;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
|
||||||
struct DispatchEntry(Call);
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
struct RestoreEntry {
|
struct RestoreEntry {
|
||||||
@@ -313,6 +317,7 @@ mod tests {
|
|||||||
restores: Vec<RestoreEntry>,
|
restores: Vec<RestoreEntry>,
|
||||||
// (topics, data)
|
// (topics, data)
|
||||||
events: Vec<(Vec<H256>, Vec<u8>)>,
|
events: Vec<(Vec<H256>, Vec<u8>)>,
|
||||||
|
runtime_calls: RefCell<Vec<Call>>,
|
||||||
schedule: Schedule<Test>,
|
schedule: Schedule<Test>,
|
||||||
rent_params: RentParams<Test>,
|
rent_params: RentParams<Test>,
|
||||||
gas_meter: GasMeter<Test>,
|
gas_meter: GasMeter<Test>,
|
||||||
@@ -335,6 +340,7 @@ mod tests {
|
|||||||
transfers: Default::default(),
|
transfers: Default::default(),
|
||||||
restores: Default::default(),
|
restores: Default::default(),
|
||||||
events: Default::default(),
|
events: Default::default(),
|
||||||
|
runtime_calls: Default::default(),
|
||||||
schedule: Default::default(),
|
schedule: Default::default(),
|
||||||
rent_params: Default::default(),
|
rent_params: Default::default(),
|
||||||
gas_meter: GasMeter::new(10_000_000_000),
|
gas_meter: GasMeter::new(10_000_000_000),
|
||||||
@@ -481,6 +487,10 @@ mod tests {
|
|||||||
self.debug_buffer.extend(msg.as_bytes());
|
self.debug_buffer.extend(msg.as_bytes());
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
fn call_runtime(&self, call: <Self::T as Config>::Call) -> DispatchResultWithPostInfo {
|
||||||
|
self.runtime_calls.borrow_mut().push(call);
|
||||||
|
Ok(Default::default())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute<E: BorrowMut<MockExt>>(
|
fn execute<E: BorrowMut<MockExt>>(
|
||||||
@@ -2160,4 +2170,81 @@ mod tests {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
const CODE_CALL_RUNTIME: &str = r#"
|
||||||
|
(module
|
||||||
|
(import "__unstable__" "seal_call_runtime" (func $seal_call_runtime (param i32 i32) (result i32)))
|
||||||
|
(import "seal0" "seal_input" (func $seal_input (param i32 i32)))
|
||||||
|
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
|
||||||
|
(import "env" "memory" (memory 1 1))
|
||||||
|
|
||||||
|
;; 0x1000 = 4k in little endian
|
||||||
|
;; size of input buffer
|
||||||
|
(data (i32.const 0) "\00\10")
|
||||||
|
|
||||||
|
(func (export "call")
|
||||||
|
;; Receive the encoded call
|
||||||
|
(call $seal_input
|
||||||
|
(i32.const 4) ;; Pointer to the input buffer
|
||||||
|
(i32.const 0) ;; Size of the length buffer
|
||||||
|
)
|
||||||
|
;; Just use the call passed as input and store result to memory
|
||||||
|
(i32.store (i32.const 0)
|
||||||
|
(call $seal_call_runtime
|
||||||
|
(i32.const 4) ;; Pointer where the call is stored
|
||||||
|
(i32.load (i32.const 0)) ;; Size of the call
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(call $seal_return
|
||||||
|
(i32.const 0) ;; flags
|
||||||
|
(i32.const 0) ;; returned value
|
||||||
|
(i32.const 4) ;; length of returned value
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(func (export "deploy"))
|
||||||
|
)
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
fn call_runtime_works() {
|
||||||
|
use std::convert::TryInto;
|
||||||
|
let call = Call::System(frame_system::Call::remark(b"Hello World".to_vec()));
|
||||||
|
let mut ext = MockExt::default();
|
||||||
|
let result = execute(
|
||||||
|
CODE_CALL_RUNTIME,
|
||||||
|
call.encode(),
|
||||||
|
&mut ext,
|
||||||
|
).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
*ext.runtime_calls.borrow(),
|
||||||
|
vec![call],
|
||||||
|
);
|
||||||
|
// 0 = ReturnCode::Success
|
||||||
|
assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
fn call_runtime_panics_on_invalid_call() {
|
||||||
|
let mut ext = MockExt::default();
|
||||||
|
let result = execute(
|
||||||
|
CODE_CALL_RUNTIME,
|
||||||
|
vec![0x42],
|
||||||
|
&mut ext,
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
result,
|
||||||
|
Err(ExecError {
|
||||||
|
error: Error::<Test>::DecodingFailed.into(),
|
||||||
|
origin: ErrorOrigin::Caller,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
*ext.runtime_calls.borrow(),
|
||||||
|
vec![],
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,9 @@ pub enum ReturnCode {
|
|||||||
/// recording was disabled.
|
/// recording was disabled.
|
||||||
#[cfg(feature = "unstable-interface")]
|
#[cfg(feature = "unstable-interface")]
|
||||||
LoggingDisabled = 9,
|
LoggingDisabled = 9,
|
||||||
|
/// The call dispatched by `seal_call_runtime` was executed but returned an error.
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
CallRuntimeReturnedError = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConvertibleToWasm for ReturnCode {
|
impl ConvertibleToWasm for ReturnCode {
|
||||||
@@ -213,6 +216,12 @@ pub enum RuntimeCosts {
|
|||||||
HashBlake128(u32),
|
HashBlake128(u32),
|
||||||
/// Weight charged by a chain extension through `seal_call_chain_extension`.
|
/// Weight charged by a chain extension through `seal_call_chain_extension`.
|
||||||
ChainExtension(u64),
|
ChainExtension(u64),
|
||||||
|
/// Weight charged for copying data from the sandbox.
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
CopyIn(u32),
|
||||||
|
/// Weight charged for calling into the runtime.
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
CallRuntime(Weight),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RuntimeCosts {
|
impl RuntimeCosts {
|
||||||
@@ -273,6 +282,10 @@ impl RuntimeCosts {
|
|||||||
HashBlake128(len) => s.hash_blake2_128
|
HashBlake128(len) => s.hash_blake2_128
|
||||||
.saturating_add(s.hash_blake2_128_per_byte.saturating_mul(len.into())),
|
.saturating_add(s.hash_blake2_128_per_byte.saturating_mul(len.into())),
|
||||||
ChainExtension(amount) => amount,
|
ChainExtension(amount) => amount,
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
CopyIn(len) => s.return_per_byte.saturating_mul(len.into()),
|
||||||
|
#[cfg(feature = "unstable-interface")]
|
||||||
|
CallRuntime(weight) => weight,
|
||||||
};
|
};
|
||||||
RuntimeToken {
|
RuntimeToken {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -457,6 +470,15 @@ where
|
|||||||
self.ext.gas_meter().charge(token)
|
self.ext.gas_meter().charge(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adjust a previously charged amount down to its actual amount.
|
||||||
|
///
|
||||||
|
/// This is when a maximum a priori amount was charged and then should be partially
|
||||||
|
/// refunded to match the actual amount.
|
||||||
|
pub fn adjust_gas(&mut self, charged: ChargedAmount, actual_costs: RuntimeCosts) {
|
||||||
|
let token = actual_costs.token(&self.ext.schedule().host_fn_weights);
|
||||||
|
self.ext.gas_meter().adjust_gas(charged, token);
|
||||||
|
}
|
||||||
|
|
||||||
/// Read designated chunk from the sandbox memory.
|
/// Read designated chunk from the sandbox memory.
|
||||||
///
|
///
|
||||||
/// Returns `Err` if one of the following conditions occurs:
|
/// Returns `Err` if one of the following conditions occurs:
|
||||||
@@ -797,7 +819,6 @@ where
|
|||||||
// data passed to the supervisor will lead to a trap. This is not documented explicitly
|
// data passed to the supervisor will lead to a trap. This is not documented explicitly
|
||||||
// for every function.
|
// for every function.
|
||||||
define_env!(Env, <E: Ext>,
|
define_env!(Env, <E: Ext>,
|
||||||
|
|
||||||
// Account for used gas. Traps if gas used is greater than gas limit.
|
// Account for used gas. Traps if gas used is greater than gas limit.
|
||||||
//
|
//
|
||||||
// NOTE: This is a implementation defined call and is NOT a part of the public API.
|
// NOTE: This is a implementation defined call and is NOT a part of the public API.
|
||||||
@@ -1808,4 +1829,58 @@ define_env!(Env, <E: Ext>,
|
|||||||
out_ptr, out_len_ptr, &rent_status, false, already_charged
|
out_ptr, out_len_ptr, &rent_status, false, already_charged
|
||||||
)?)
|
)?)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Call some dispatchable of the runtime.
|
||||||
|
//
|
||||||
|
// This function decodes the passed in data as the overarching `Call` type of the
|
||||||
|
// runtime and dispatches it. The weight as specified in the runtime is charged
|
||||||
|
// from the gas meter. Any weight refunds made by the dispatchable are considered.
|
||||||
|
//
|
||||||
|
// The filter specified by `Config::CallFilter` is attached to the origin of
|
||||||
|
// the dispatched call.
|
||||||
|
//
|
||||||
|
// # Parameters
|
||||||
|
//
|
||||||
|
// - `input_ptr`: the pointer into the linear memory where the input data is placed.
|
||||||
|
// - `input_len`: the length of the input data in bytes.
|
||||||
|
//
|
||||||
|
// # Return Value
|
||||||
|
//
|
||||||
|
// Returns `ReturnCode::Success` when the dispatchable was succesfully executed and
|
||||||
|
// returned `Ok`. When the dispatchable was exeuted but returned an error
|
||||||
|
// `ReturnCode::CallRuntimeReturnedError` is returned. The full error is not
|
||||||
|
// provided because it is not guaranteed to be stable.
|
||||||
|
//
|
||||||
|
// # Comparison with `ChainExtension`
|
||||||
|
//
|
||||||
|
// Just as a chain extension this API allows the runtime to extend the functionality
|
||||||
|
// of contracts. While making use of this function is generelly easier it cannot be
|
||||||
|
// used in call cases. Consider writing a chain extension if you need to do perform
|
||||||
|
// one of the following tasks:
|
||||||
|
//
|
||||||
|
// - Return data.
|
||||||
|
// - Provide functionality **exclusively** to contracts.
|
||||||
|
// - Provide custom weights.
|
||||||
|
// - Avoid the need to keep the `Call` data structure stable.
|
||||||
|
//
|
||||||
|
// # Unstable
|
||||||
|
//
|
||||||
|
// This function is unstable and subject to change (or removal) in the future. Do not
|
||||||
|
// deploy a contract using it to a production chain.
|
||||||
|
[__unstable__] seal_call_runtime(ctx, call_ptr: u32, call_len: u32) -> ReturnCode => {
|
||||||
|
use frame_support::{dispatch::GetDispatchInfo, weights::extract_actual_weight};
|
||||||
|
ctx.charge_gas(RuntimeCosts::CopyIn(call_len))?;
|
||||||
|
let call: <E::T as Config>::Call = ctx.read_sandbox_memory_as_unbounded(
|
||||||
|
call_ptr, call_len
|
||||||
|
)?;
|
||||||
|
let dispatch_info = call.get_dispatch_info();
|
||||||
|
let charged = ctx.charge_gas(RuntimeCosts::CallRuntime(dispatch_info.weight))?;
|
||||||
|
let result = ctx.ext.call_runtime(call);
|
||||||
|
let actual_weight = extract_actual_weight(&result, &dispatch_info);
|
||||||
|
ctx.adjust_gas(charged, RuntimeCosts::CallRuntime(actual_weight));
|
||||||
|
match result {
|
||||||
|
Ok(_) => Ok(ReturnCode::Success),
|
||||||
|
Err(_) => Ok(ReturnCode::CallRuntimeReturnedError),
|
||||||
|
}
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ pub fn witness() -> SolutionOrSnapshotSize {
|
|||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type SS58Prefix = ();
|
type SS58Prefix = ();
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u64;
|
type BlockNumber = u64;
|
||||||
|
|||||||
@@ -1123,7 +1123,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
type PalletInfo = PalletInfo;
|
type PalletInfo = PalletInfo;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -694,7 +694,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -491,7 +491,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ parameter_types! {
|
|||||||
pub const BlockHashCount: u64 = 250;
|
pub const BlockHashCount: u64 = 250;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Call = Call;
|
type Call = Call;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ mod tests {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameter_types! {
|
|||||||
pub const BlockHashCount: u64 = 250;
|
pub const BlockHashCount: u64 = 250;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND);
|
frame_system::limits::BlockWeights::simple_max(2 * WEIGHT_PER_SECOND);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = RocksDbWeight;
|
type DbWeight = RocksDbWeight;
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = BlockLength;
|
type BlockLength = BlockLength;
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ ord_parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ frame_support::construct_runtime!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ ord_parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ frame_support::construct_runtime!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = RocksDbWeight;
|
type DbWeight = RocksDbWeight;
|
||||||
|
|||||||
@@ -2684,7 +2684,7 @@ mod tests {
|
|||||||
type Origin = OuterOrigin;
|
type Origin = OuterOrigin;
|
||||||
type AccountId = u32;
|
type AccountId = u32;
|
||||||
type Call = ();
|
type Call = ();
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockNumber = u32;
|
type BlockNumber = u32;
|
||||||
type PalletInfo = Self;
|
type PalletInfo = Self;
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ pub use validation::{
|
|||||||
mod filter;
|
mod filter;
|
||||||
pub use filter::{
|
pub use filter::{
|
||||||
Filter, FilterStack, FilterStackGuard, ClearFilterGuard, InstanceFilter, IntegrityTest,
|
Filter, FilterStack, FilterStackGuard, ClearFilterGuard, InstanceFilter, IntegrityTest,
|
||||||
|
AllowAll, DenyAll,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod misc;
|
mod misc;
|
||||||
|
|||||||
@@ -25,10 +25,20 @@ pub trait Filter<T> {
|
|||||||
fn filter(_: &T) -> bool;
|
fn filter(_: &T) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Filter<T> for () {
|
/// A [`Filter`] that allows any value.
|
||||||
|
pub enum AllowAll {}
|
||||||
|
|
||||||
|
/// A [`Filter`] that denies any value.
|
||||||
|
pub enum DenyAll {}
|
||||||
|
|
||||||
|
impl<T> Filter<T> for AllowAll {
|
||||||
fn filter(_: &T) -> bool { true }
|
fn filter(_: &T) -> bool { true }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Filter<T> for DenyAll {
|
||||||
|
fn filter(_: &T) -> bool { false }
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait to add a constraint onto the filter.
|
/// Trait to add a constraint onto the filter.
|
||||||
pub trait FilterStack<T>: Filter<T> {
|
pub trait FilterStack<T>: Filter<T> {
|
||||||
/// The type used to archive the stack.
|
/// The type used to archive the stack.
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ pub type BlockNumber = u64;
|
|||||||
pub type Index = u64;
|
pub type Index = u64;
|
||||||
|
|
||||||
impl system::Config for Runtime {
|
impl system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Hash = H256;
|
type Hash = H256;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = BlockNumber;
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ pub type BlockNumber = u64;
|
|||||||
pub type Index = u64;
|
pub type Index = u64;
|
||||||
|
|
||||||
impl system::Config for Runtime {
|
impl system::Config for Runtime {
|
||||||
type BaseCallFilter= ();
|
type BaseCallFilter= frame_support::traits::AllowAll;
|
||||||
type Hash = H256;
|
type Hash = H256;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = BlockNumber;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ pub type Block = generic::Block<Header, UncheckedExtrinsic>;
|
|||||||
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<u32, Call, Signature, ()>;
|
||||||
|
|
||||||
impl system::Config for Runtime {
|
impl system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Hash = H256;
|
type Hash = H256;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = BlockNumber;
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ frame_support::parameter_types!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u32;
|
type BlockNumber = u32;
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ frame_support::parameter_types!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u32;
|
type BlockNumber = u32;
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ impl frame_system::Config for Runtime {
|
|||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u32;
|
type BlockNumber = u32;
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ frame_support::parameter_types!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u32;
|
type BlockNumber = u32;
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ frame_support::parameter_types!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = BlockNumber;
|
type BlockNumber = BlockNumber;
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
type Index = u64;
|
type Index = u64;
|
||||||
type BlockNumber = u64;
|
type BlockNumber = u64;
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ frame_support::parameter_types! {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
impl system::Config for Runtime {
|
impl system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = BlockLength;
|
type BlockLength = BlockLength;
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ frame_support::construct_runtime!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ impl OnKilledAccount<u64> for RecordKilled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Config for Test {
|
impl Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = RuntimeBlockWeights;
|
type BlockWeights = RuntimeBlockWeights;
|
||||||
type BlockLength = RuntimeBlockLength;
|
type BlockLength = RuntimeBlockLength;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ mod tests {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ parameter_types! {
|
|||||||
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
pub const AvailableBlockRatio: Perbill = Perbill::one();
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -715,7 +715,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = BlockWeights;
|
type BlockWeights = BlockWeights;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ parameter_types! {
|
|||||||
frame_system::limits::BlockWeights::simple_max(1024);
|
frame_system::limits::BlockWeights::simple_max(1024);
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type DbWeight = ();
|
type DbWeight = ();
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ parameter_types! {
|
|||||||
pub const BlockHashCount: u64 = 250;
|
pub const BlockHashCount: u64 = 250;
|
||||||
}
|
}
|
||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = ();
|
type BlockWeights = ();
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ parameter_types! {
|
|||||||
impl frame_system::Config for Test {
|
impl frame_system::Config for Test {
|
||||||
type AccountData = pallet_balances::AccountData<u64>;
|
type AccountData = pallet_balances::AccountData<u64>;
|
||||||
type AccountId = u64;
|
type AccountId = u64;
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockHashCount = BlockHashCount;
|
type BlockHashCount = BlockHashCount;
|
||||||
type BlockLength = ();
|
type BlockLength = ();
|
||||||
type BlockNumber = u64;
|
type BlockNumber = u64;
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ parameter_types! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl frame_system::Config for Runtime {
|
impl frame_system::Config for Runtime {
|
||||||
type BaseCallFilter = ();
|
type BaseCallFilter = frame_support::traits::AllowAll;
|
||||||
type BlockWeights = RuntimeBlockWeights;
|
type BlockWeights = RuntimeBlockWeights;
|
||||||
type BlockLength = RuntimeBlockLength;
|
type BlockLength = RuntimeBlockLength;
|
||||||
type Origin = Origin;
|
type Origin = Origin;
|
||||||
|
|||||||
Reference in New Issue
Block a user