contracts: Make Origin information available (#13708)

* contracts: allow root calls

* contracts: update ContractOrigin

* contracts: test allow root calls

* contracts: rustfmt

* contracts: test root caller traps

* contracts: add Caller enum

* contracts: improve some comments

* contracts: improve some comments

* contracts: format code with +nightly

* contracts: fix failing tests

* contracts: improve charte instantiate call when root origin

* contract: refactor common, call and instantiate inputs

* contracts: fix some failing test

* contracts: trap caller when there is no account id

* Update frame/contracts/src/lib.rs

Co-authored-by: PG Herveou <pgherveou@gmail.com>

* Update frame/contracts/src/exec.rs

Co-authored-by: PG Herveou <pgherveou@gmail.com>

* contracts: make `into_deposit` return zero when the origin is root

* contracts: cargo fmt

* contracts: charging and terminating tests refactored

* contracts: improved errors

* contracts: refactor & merge ContractOrigin cand Caller enums

* Update frame/contracts/src/lib.rs

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* contracts: apply suggested pr changes

* contracts: rename Caller to Origin

* contracts: refactor run fn

* contracts: cr improvements

* contracts: allow root to use delegate call

* contracts: add caller_is_root weight

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* contracts: add caller_is_root benchmarking

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* contracts: add caller_is_root benchmarking

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* contracts: add some minor improvements

* contracts: make caller_is_root runtime fn unstable

* contracts: fix failing wasm test

* contracts: update benchmarking for origin_is_root

* contracts: improve seal_caller_is_root benchmarking

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* contracts: add small pr improvements

* contracts: fix broken tests after master merge

* contracts: acknowledge the default storage deposit limit

* ".git/.scripts/commands/bench/bench.sh" pallet dev pallet_contracts

* contracts: move origin to CommonInput

* contracts: add some extra tests

* contracts: move ensure origin logic inside invokable::run_guarded

* contracts: add minor improvements

* contracts: fix caller_is_root benchmarking

* contracts: improve function description

* Update frame/contracts/src/lib.rs

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* Update frame/contracts/src/lib.rs

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* Update frame/contracts/src/wasm/runtime.rs

Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>

* contracts: improve function description

---------

Co-authored-by: parity-processbot <>
Co-authored-by: PG Herveou <pgherveou@gmail.com>
Co-authored-by: Sasha Gryaznov <hi@agryaznov.com>
This commit is contained in:
juangirini
2023-05-02 18:45:14 +02:00
committed by GitHub
parent 0e28645153
commit 5db4119f93
10 changed files with 1835 additions and 1234 deletions
+57 -3
View File
@@ -370,7 +370,7 @@ mod tests {
gas::GasMeter,
storage::WriteOutcome,
tests::{RuntimeCall, Test, ALICE, BOB},
BalanceOf, CodeHash, Error, Pallet as Contracts,
BalanceOf, CodeHash, Error, Origin, Pallet as Contracts,
};
use assert_matches::assert_matches;
use frame_support::{
@@ -436,6 +436,7 @@ mod tests {
ecdsa_recover: RefCell<Vec<([u8; 65], [u8; 32])>>,
sr25519_verify: RefCell<Vec<([u8; 64], Vec<u8>, [u8; 32])>>,
code_hashes: Vec<CodeHash<Test>>,
caller: Origin<Test>,
}
/// The call is mocked and just returns this hardcoded value.
@@ -459,6 +460,7 @@ mod tests {
gas_meter: GasMeter::new(Weight::from_parts(10_000_000_000, 10 * 1024 * 1024)),
debug_buffer: Default::default(),
ecdsa_recover: Default::default(),
caller: Default::default(),
sr25519_verify: Default::default(),
}
}
@@ -545,8 +547,8 @@ mod tests {
}
Ok(result)
}
fn caller(&self) -> &AccountIdOf<Self::T> {
&ALICE
fn caller(&self) -> Origin<Self::T> {
self.caller.clone()
}
fn is_contract(&self, _address: &AccountIdOf<Self::T>) -> bool {
true
@@ -561,6 +563,9 @@ mod tests {
fn caller_is_origin(&self) -> bool {
false
}
fn caller_is_root(&self) -> bool {
&self.caller == &Origin::Root
}
fn address(&self) -> &AccountIdOf<Self::T> {
&BOB
}
@@ -1499,6 +1504,16 @@ mod tests {
assert_ok!(execute(CODE_CALLER, vec![], MockExt::default()));
}
#[test]
fn caller_traps_when_no_account_id() {
let mut ext = MockExt::default();
ext.caller = Origin::Root;
assert_eq!(
execute(CODE_CALLER, vec![], ext),
Err(ExecError { error: DispatchError::RootNotAllowed, origin: ErrorOrigin::Caller })
);
}
/// calls `seal_address` and compares the result with the constant (BOB's address part).
const CODE_ADDRESS: &str = r#"
(module
@@ -2977,6 +2992,45 @@ mod tests {
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 0u32.encode() },);
}
#[test]
fn caller_is_root_works() {
const CODE_CALLER_IS_ROOT: &str = r#"
;; This runs `caller_is_root` check on zero account address
(module
(import "seal0" "caller_is_root" (func $caller_is_root (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 4) here the return code of the `caller_is_root` will be stored
;; we initialize it with non-zero value to be sure that it's being overwritten below
(data (i32.const 0) "\10\10\10\10")
(func (export "deploy"))
(func (export "call")
(i32.store
(i32.const 0)
(call $caller_is_root)
)
;; exit with success and take `caller_is_root` return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
)
)
"#;
// The default `caller` is ALICE. Therefore not root.
let output = execute(CODE_CALLER_IS_ROOT, vec![], MockExt::default()).unwrap();
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 0u32.encode() },);
// The caller is forced to be root instead of using the default ALICE.
let output = execute(
CODE_CALLER_IS_ROOT,
vec![],
MockExt { caller: Origin::Root, ..MockExt::default() },
)
.unwrap();
assert_eq!(output, ExecReturnValue { flags: ReturnFlags::empty(), data: 1u32.encode() },);
}
#[test]
fn set_code_hash() {
const CODE: &str = r#"