Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

seal: Rework contracts API #6573

Merged
25 commits merged into from
Jul 9, 2020
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8321883
Transition getter functions to not use scratch buffer
athei Jun 24, 2020
92fe839
Remove scratch buffer from ext_get_storage
athei Jun 26, 2020
e1c0e26
Remove scratch buffer from ext_call
athei Jun 29, 2020
6f94941
Remove scratch buffer from ext_instantiate
athei Jun 29, 2020
0b27908
Add ext_input and remove scratch buffer
athei Jun 29, 2020
46191f5
Remove the no longer used `Dispatched` event
athei Jul 1, 2020
fa6bf8c
Rework error handling (changes RPC exposed data)
athei Jun 30, 2020
c86c2ad
Updated inline documentation
athei Jul 2, 2020
ddf69ab
Prevent skipping of copying the output for getter API
athei Jul 3, 2020
868668c
Return gas_consumed from the RPC contracts call interface
athei Jul 3, 2020
84973b0
Updated COMPLEXTITY.md
athei Jul 3, 2020
d205f60
Rename ext_gas_price to ext_weight_to_fee
athei Jul 3, 2020
e096945
Align comments with spaces
athei Jul 7, 2020
6b0c1f0
Removed no longer used `ExecError`
athei Jul 7, 2020
8e5170c
Remove possible panic in `from_typed_value`
athei Jul 7, 2020
08edc84
Use a struct as associated data for SpecialTrap::Return
athei Jul 7, 2020
792c942
Fix nits in COMPLEXITY.md
athei Jul 7, 2020
41f1d55
Renamed SpecialTrap to TrapReason
athei Jul 7, 2020
3977032
Merge remote-tracking branch 'origin/master' into at-remove-scratch-b…
athei Jul 7, 2020
8373842
Fix test
athei Jul 7, 2020
cf72226
Merge branch 'master' into at-remove-scratch-buffer
athei Jul 9, 2020
9021d20
Finish renaming special_trap -> trap_reason
athei Jul 9, 2020
9ef80e1
Remove no longer used get_runtime_storage
athei Jul 9, 2020
fe110ed
fixup! Remove no longer used get_runtime_storage
athei Jul 9, 2020
9deebd3
Removed tabs for comment aligment
athei Jul 9, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 16 additions & 13 deletions bin/node/executor/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,32 +491,31 @@ const CODE_TRANSFER: &str = r#"
;; value_ptr: u32,
;; value_len: u32,
;; input_data_ptr: u32,
;; input_data_len: u32
;; input_data_len: u32,
;; output_ptr: u32,
;; output_len_ptr: u32
;; ) -> u32
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "ext_input" (func $ext_input (param i32 i32)))
(import "env" "memory" (memory 1 1))
(func (export "deploy")
)
(func (export "call")
(block $fail
;; load and check the input data (which is stored in the scratch buffer).
;; Load input data to contract memory
(call $ext_input
(i32.const 0)
(i32.const 52)
)

;; fail if the input size is not != 4
(br_if $fail
(i32.ne
(i32.const 4)
(call $ext_scratch_size)
(i32.load (i32.const 52))
)
)

(call $ext_scratch_read
(i32.const 0)
(i32.const 0)
(i32.const 4)
)


(br_if $fail
(i32.ne
(i32.load8_u (i32.const 0))
Expand Down Expand Up @@ -551,6 +550,8 @@ const CODE_TRANSFER: &str = r#"
(i32.const 16) ;; 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 4294967295) ;; u32 max value is the sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)

Expand All @@ -571,6 +572,8 @@ const CODE_TRANSFER: &str = r#"
"\06\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"
)
;; Length of the input buffer
(data (i32.const 52) "\04")
)
"#;

Expand Down
5 changes: 3 additions & 2 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1066,12 +1066,13 @@ impl_runtime_apis! {
gas_limit: u64,
input_data: Vec<u8>,
) -> ContractExecResult {
let exec_result =
let (exec_result, gas_consumed) =
Contracts::bare_call(origin, dest.into(), value, gas_limit, input_data);
match exec_result {
Ok(v) => ContractExecResult::Success {
status: v.status,
flags: v.flags.bits(),
data: v.data,
gas_consumed: gas_consumed,
},
Err(_) => ContractExecResult::Error,
}
Expand Down
228 changes: 100 additions & 128 deletions frame/contracts/COMPLEXITY.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frame/contracts/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ sp-sandbox = { version = "0.8.0-rc4", default-features = false, path = "../../pr
frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" }
frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" }
pallet-contracts-primitives = { version = "2.0.0-rc4", default-features = false, path = "common" }
bitflags = "1.0"

[dev-dependencies]
wabt = "0.9.2"
Expand Down
153 changes: 81 additions & 72 deletions frame/contracts/fixtures/caller_contract.wat
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
(module
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
(import "env" "ext_balance" (func $ext_balance))
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
(import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
(import "env" "ext_input" (func $ext_input (param i32 i32)))
(import "env" "ext_balance" (func $ext_balance (param i32 i32)))
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)))
(import "env" "ext_println" (func $ext_println (param i32 i32)))
(import "env" "memory" (memory 1 1))

Expand All @@ -17,14 +16,16 @@
)

(func $current_balance (param $sp i32) (result i64)
(call $ext_balance)
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 8))
(i32.store
(i32.sub (get_local $sp) (i32.const 16))
(i32.const 8)
)
(call $ext_scratch_read
(call $ext_balance
(i32.sub (get_local $sp) (i32.const 8))
(i32.const 0)
(i32.const 8)
(i32.sub (get_local $sp) (i32.const 16))
)
(call $assert
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 16))) (i32.const 8))
)
(i64.load (i32.sub (get_local $sp) (i32.const 8)))
)
Expand All @@ -36,21 +37,20 @@
(local $exit_code i32)
(local $balance i64)

;; Length of the buffer
(i32.store (i32.const 20) (i32.const 32))

;; Copy input to this contracts memory
(call $ext_input (i32.const 24) (i32.const 20))

;; Input data is the code hash of the contract to be deployed.
(call $assert
(i32.eq
(call $ext_scratch_size)
(i32.load (i32.const 20))
(i32.const 32)
)
)

;; Copy code hash from scratch buffer into this contract's memory.
(call $ext_scratch_read
(i32.const 24) ;; The pointer where to store the scratch buffer contents,
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 32) ;; Count of bytes to copy.
)

;; Read current balance into local variable.
(set_local $sp (i32.const 1024))
(set_local $balance
Expand All @@ -67,17 +67,16 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 9) ;; Pointer to input data buffer address
(i32.const 7) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)

;; Check non-zero exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x11))
)

;; Check that scratch buffer is empty since contract instantiation failed.
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 0))
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
)

;; Check that balance has not changed.
Expand All @@ -95,24 +94,29 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
(i32.const 0) ;; Length is ignored in this case
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case
)
)

;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x0100))
)

;; Check that scratch buffer is empty since contract instantiation failed.
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 0))
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)

;; Check that balance has not changed.
(call $assert
(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
)

;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 8)
)

;; Deploy the contract successfully.
(set_local $exit_code
(call $ext_instantiate
Expand All @@ -123,24 +127,22 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 16) ;; Pointer to the address output buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this case

)
)

;; Check for success exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x00))
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)

;; Check that scratch buffer contains the address of the new contract.
;; Check that address has the expected length
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 8))
)

;; Copy contract address from scratch buffer into this contract's memory.
(call $ext_scratch_read
(i32.const 16) ;; The pointer where to store the scratch buffer contents,
(i32.const 0) ;; Offset from the start of the scratch buffer.
(i32.const 8) ;; Count of bytes to copy.
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 8))
)

;; Check that balance has been deducted.
Expand All @@ -151,6 +153,18 @@
(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
)

;; Zero out destination buffer of output
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)

;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 8))
(i32.const 4)
)

;; Call the new contract and expect it to return failing exit code.
(set_local $exit_code
(call $ext_call
Expand All @@ -161,26 +175,19 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 9) ;; Pointer to input data buffer address
(i32.const 7) ;; Length of input data buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
)
)

;; Check non-zero exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x11))
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
)

;; Check that scratch buffer contains the expected return data.
;; Check that output buffer contains the expected return data.
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 3))
)
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)
(call $ext_scratch_read
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
(i32.const 3)
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3))
)
(call $assert
(i32.eq
Expand All @@ -204,24 +211,33 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
(i32.const 0) ;; Length is ignored in this cas
)
)

;; Check for special trap exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x0100))
)

;; Check that scratch buffer is empty since call trapped.
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 0))
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
)

;; Check that balance has not changed.
(call $assert
(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
)

;; Zero out destination buffer of output
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)

;; Length of the output buffer
(i32.store
(i32.sub (get_local $sp) (i32.const 8))
(i32.const 4)
)

;; Call the contract successfully.
(set_local $exit_code
(call $ext_call
Expand All @@ -232,26 +248,19 @@
(i32.const 8) ;; Length of the buffer with value to transfer.
(i32.const 8) ;; Pointer to input data buffer address
(i32.const 8) ;; Length of input data buffer
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
)
)

;; Check for success exit status.
(call $assert
(i32.eq (get_local $exit_code) (i32.const 0x00))
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
)

;; Check that scratch buffer contains the expected return data.
;; Check that the output buffer contains the expected return data.
(call $assert
(i32.eq (call $ext_scratch_size) (i32.const 4))
)
(i32.store
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
)
(call $ext_scratch_read
(i32.sub (get_local $sp) (i32.const 4))
(i32.const 0)
(i32.const 4)
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4))
)
(call $assert
(i32.eq
Expand All @@ -271,5 +280,5 @@

(data (i32.const 0) "\00\80") ;; The value to transfer on instantiation and calls.
;; Chosen to be greater than existential deposit.
(data (i32.const 8) "\00\11\22\33\44\55\66\77") ;; The input data to instantiations and calls.
(data (i32.const 8) "\00\01\22\33\44\55\66\77") ;; The input data to instantiations and calls.
)
Loading