contracts: is_contract(address) and caller_is_origin() are added to API (#10789)

* is_contract() and caller_is_origin() added to Ext API

* is_contract() exposed in wasm runtime.rs

* + test for is_contract()

* + seal_is_contract benchmark

* caller_is_origin() exposed to wasm/runtime.rs and covered by a test

* + seal_caller_is_origin benchmark

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

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

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

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

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

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

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* Update frame/contracts/src/exec.rs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* identation fix for benchmark macroses; test cosmetic improvement

* benchmark fix

* + is_contract() wasm test

* + caller_is_origin() wasm test

* Apply suggestions from code review

Co-authored-by: Alexander Theißen <alex.theissen@me.com>

* is_contract() to borrow param instead of taking ownership

* phrasing improved

Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>

* fixed wasm tests according to @athei feedback

* dead code warnings suppressed by unstable-interface attributes

* cargo run --quiet --profile=production  --features=runtime-benchmarks --manifest-path=bin/node/cli/Cargo.toml -- benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_contracts --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --output=./frame/contracts/src/weights.rs --template=./.maintain/frame-weight-template.hbs

Co-authored-by: Alexander Theißen <alex.theissen@me.com>
Co-authored-by: Hernando Castano <HCastano@users.noreply.github.com>
Co-authored-by: Parity Bot <admin@parity.io>
This commit is contained in:
Alexander Gryaznov
2022-02-04 20:13:00 +01:00
committed by GitHub
parent 89fa61125e
commit d5c8593566
6 changed files with 965 additions and 652 deletions
+82
View File
@@ -409,6 +409,12 @@ mod tests {
fn caller(&self) -> &AccountIdOf<Self::T> {
&ALICE
}
fn is_contract(&self, _address: &AccountIdOf<Self::T>) -> bool {
true
}
fn caller_is_origin(&self) -> bool {
false
}
fn address(&self) -> &AccountIdOf<Self::T> {
&BOB
}
@@ -2240,4 +2246,80 @@ mod tests {
let result = execute(CODE, [2u8; 32].encode(), &mut ext).unwrap();
assert_eq!(u32::from_le_bytes(result.data.0.try_into().unwrap()), 0,);
}
#[test]
#[cfg(feature = "unstable-interface")]
fn is_contract_works() {
const CODE_IS_CONTRACT: &str = r#"
;; This runs `is_contract` check on zero account address
(module
(import "__unstable__" "seal_is_contract" (func $seal_is_contract (param i32) (result i32)))
(import "seal0" "seal_return" (func $seal_return (param i32 i32 i32)))
(import "env" "memory" (memory 1 1))
;; [0, 32) zero-adress
(data (i32.const 0)
"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
"\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00"
)
;; [32, 36) here we store the return code of the `seal_is_contract`
(func (export "deploy"))
(func (export "call")
(i32.store
(i32.const 32)
(call $seal_is_contract
(i32.const 0) ;; ptr to destination address
)
)
;; exit with success and take `seal_is_contract` return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 32) (i32.const 4))
)
)
"#;
let output = execute(CODE_IS_CONTRACT, vec![], MockExt::default()).unwrap();
// The mock ext just always returns 1u32 (`true`).
assert_eq!(
output,
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(1u32.encode()) },
);
}
#[test]
#[cfg(feature = "unstable-interface")]
fn caller_is_origin_works() {
const CODE_CALLER_IS_ORIGIN: &str = r#"
;; This runs `caller_is_origin` check on zero account address
(module
(import "__unstable__" "seal_caller_is_origin" (func $seal_caller_is_origin (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 `seal_caller_is_origin` 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 $seal_caller_is_origin)
)
;; exit with success and take `seal_caller_is_origin` return code to the output buffer
(call $seal_return (i32.const 0) (i32.const 0) (i32.const 4))
)
)
"#;
let output = execute(CODE_CALLER_IS_ORIGIN, vec![], MockExt::default()).unwrap();
// The mock ext just always returns 0u32 (`false`)
assert_eq!(
output,
ExecReturnValue { flags: ReturnFlags::empty(), data: Bytes(0u32.encode()) },
);
}
}