Skip to content

Commit 9a3e7ef

Browse files
authored
seal: Rework contracts API (#6573)
* Transition getter functions to not use scratch buffer * Remove scratch buffer from ext_get_storage * Remove scratch buffer from ext_call * Remove scratch buffer from ext_instantiate * Add ext_input and remove scratch buffer * Rework error handling (changes RPC exposed data) * ext_return passes a flags field instead of a return code * Flags is only for seal and not for the caller * flags: u32 replaced status_code: u8 in RPC exposed type * API functions use a unified error type (ReturnCode) * ext_transfer now traps on error to be consistent with call and instantiate * Remove the no longer used `Dispatched` event * Updated inline documentation * Prevent skipping of copying the output for getter API * Return gas_consumed from the RPC contracts call interface * Updated COMPLEXTITY.md * Rename ext_gas_price to ext_weight_to_fee * Align comments with spaces * Removed no longer used `ExecError` * Remove possible panic in `from_typed_value` * Use a struct as associated data for SpecialTrap::Return * Fix nits in COMPLEXITY.md * Renamed SpecialTrap to TrapReason * Fix test * Finish renaming special_trap -> trap_reason * Remove no longer used get_runtime_storage * fixup! Remove no longer used get_runtime_storage * Removed tabs for comment aligment
1 parent 762d5fb commit 9a3e7ef

23 files changed

+1092
-1237
lines changed

COMPLEXITY.md

Lines changed: 100 additions & 128 deletions
Large diffs are not rendered by default.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ sp-sandbox = { version = "0.8.0-rc4", default-features = false, path = "../../pr
2525
frame-support = { version = "2.0.0-rc4", default-features = false, path = "../support" }
2626
frame-system = { version = "2.0.0-rc4", default-features = false, path = "../system" }
2727
pallet-contracts-primitives = { version = "2.0.0-rc4", default-features = false, path = "common" }
28+
bitflags = "1.0"
2829

2930
[dev-dependencies]
3031
wabt = "0.9.2"

fixtures/caller_contract.wat

Lines changed: 81 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
(module
2-
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
3-
(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
4-
(import "env" "ext_balance" (func $ext_balance))
5-
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
6-
(import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32) (result i32)))
2+
(import "env" "ext_input" (func $ext_input (param i32 i32)))
3+
(import "env" "ext_balance" (func $ext_balance (param i32 i32)))
4+
(import "env" "ext_call" (func $ext_call (param i32 i32 i64 i32 i32 i32 i32 i32 i32) (result i32)))
5+
(import "env" "ext_instantiate" (func $ext_instantiate (param i32 i32 i64 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)))
76
(import "env" "ext_println" (func $ext_println (param i32 i32)))
87
(import "env" "memory" (memory 1 1))
98

@@ -17,14 +16,16 @@
1716
)
1817

1918
(func $current_balance (param $sp i32) (result i64)
20-
(call $ext_balance)
21-
(call $assert
22-
(i32.eq (call $ext_scratch_size) (i32.const 8))
19+
(i32.store
20+
(i32.sub (get_local $sp) (i32.const 16))
21+
(i32.const 8)
2322
)
24-
(call $ext_scratch_read
23+
(call $ext_balance
2524
(i32.sub (get_local $sp) (i32.const 8))
26-
(i32.const 0)
27-
(i32.const 8)
25+
(i32.sub (get_local $sp) (i32.const 16))
26+
)
27+
(call $assert
28+
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 16))) (i32.const 8))
2829
)
2930
(i64.load (i32.sub (get_local $sp) (i32.const 8)))
3031
)
@@ -36,21 +37,20 @@
3637
(local $exit_code i32)
3738
(local $balance i64)
3839

40+
;; Length of the buffer
41+
(i32.store (i32.const 20) (i32.const 32))
42+
43+
;; Copy input to this contracts memory
44+
(call $ext_input (i32.const 24) (i32.const 20))
45+
3946
;; Input data is the code hash of the contract to be deployed.
4047
(call $assert
4148
(i32.eq
42-
(call $ext_scratch_size)
49+
(i32.load (i32.const 20))
4350
(i32.const 32)
4451
)
4552
)
4653

47-
;; Copy code hash from scratch buffer into this contract's memory.
48-
(call $ext_scratch_read
49-
(i32.const 24) ;; The pointer where to store the scratch buffer contents,
50-
(i32.const 0) ;; Offset from the start of the scratch buffer.
51-
(i32.const 32) ;; Count of bytes to copy.
52-
)
53-
5454
;; Read current balance into local variable.
5555
(set_local $sp (i32.const 1024))
5656
(set_local $balance
@@ -67,17 +67,16 @@
6767
(i32.const 8) ;; Length of the buffer with value to transfer.
6868
(i32.const 9) ;; Pointer to input data buffer address
6969
(i32.const 7) ;; Length of input data buffer
70+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
71+
(i32.const 0) ;; Length is ignored in this case
72+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
73+
(i32.const 0) ;; Length is ignored in this case
7074
)
7175
)
7276

7377
;; Check non-zero exit status.
7478
(call $assert
75-
(i32.eq (get_local $exit_code) (i32.const 0x11))
76-
)
77-
78-
;; Check that scratch buffer is empty since contract instantiation failed.
79-
(call $assert
80-
(i32.eq (call $ext_scratch_size) (i32.const 0))
79+
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
8180
)
8281

8382
;; Check that balance has not changed.
@@ -95,24 +94,29 @@
9594
(i32.const 8) ;; Length of the buffer with value to transfer.
9695
(i32.const 8) ;; Pointer to input data buffer address
9796
(i32.const 8) ;; Length of input data buffer
97+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy address
98+
(i32.const 0) ;; Length is ignored in this case
99+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
100+
(i32.const 0) ;; Length is ignored in this case
98101
)
99102
)
100103

101104
;; Check for special trap exit status.
102105
(call $assert
103-
(i32.eq (get_local $exit_code) (i32.const 0x0100))
104-
)
105-
106-
;; Check that scratch buffer is empty since contract instantiation failed.
107-
(call $assert
108-
(i32.eq (call $ext_scratch_size) (i32.const 0))
106+
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
109107
)
110108

111109
;; Check that balance has not changed.
112110
(call $assert
113111
(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
114112
)
115113

114+
;; Length of the output buffer
115+
(i32.store
116+
(i32.sub (get_local $sp) (i32.const 4))
117+
(i32.const 8)
118+
)
119+
116120
;; Deploy the contract successfully.
117121
(set_local $exit_code
118122
(call $ext_instantiate
@@ -123,24 +127,22 @@
123127
(i32.const 8) ;; Length of the buffer with value to transfer.
124128
(i32.const 8) ;; Pointer to input data buffer address
125129
(i32.const 8) ;; Length of input data buffer
130+
(i32.const 16) ;; Pointer to the address output buffer
131+
(i32.sub (get_local $sp) (i32.const 4)) ;; Pointer to the address buffer length
132+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
133+
(i32.const 0) ;; Length is ignored in this case
134+
126135
)
127136
)
128137

129138
;; Check for success exit status.
130139
(call $assert
131-
(i32.eq (get_local $exit_code) (i32.const 0x00))
140+
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
132141
)
133142

134-
;; Check that scratch buffer contains the address of the new contract.
143+
;; Check that address has the expected length
135144
(call $assert
136-
(i32.eq (call $ext_scratch_size) (i32.const 8))
137-
)
138-
139-
;; Copy contract address from scratch buffer into this contract's memory.
140-
(call $ext_scratch_read
141-
(i32.const 16) ;; The pointer where to store the scratch buffer contents,
142-
(i32.const 0) ;; Offset from the start of the scratch buffer.
143-
(i32.const 8) ;; Count of bytes to copy.
145+
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 4))) (i32.const 8))
144146
)
145147

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

156+
;; Zero out destination buffer of output
157+
(i32.store
158+
(i32.sub (get_local $sp) (i32.const 4))
159+
(i32.const 0)
160+
)
161+
162+
;; Length of the output buffer
163+
(i32.store
164+
(i32.sub (get_local $sp) (i32.const 8))
165+
(i32.const 4)
166+
)
167+
154168
;; Call the new contract and expect it to return failing exit code.
155169
(set_local $exit_code
156170
(call $ext_call
@@ -161,26 +175,19 @@
161175
(i32.const 8) ;; Length of the buffer with value to transfer.
162176
(i32.const 9) ;; Pointer to input data buffer address
163177
(i32.const 7) ;; Length of input data buffer
178+
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
179+
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
164180
)
165181
)
166182

167183
;; Check non-zero exit status.
168184
(call $assert
169-
(i32.eq (get_local $exit_code) (i32.const 0x11))
185+
(i32.eq (get_local $exit_code) (i32.const 2)) ;; ReturnCode::CalleeReverted
170186
)
171187

172-
;; Check that scratch buffer contains the expected return data.
188+
;; Check that output buffer contains the expected return data.
173189
(call $assert
174-
(i32.eq (call $ext_scratch_size) (i32.const 3))
175-
)
176-
(i32.store
177-
(i32.sub (get_local $sp) (i32.const 4))
178-
(i32.const 0)
179-
)
180-
(call $ext_scratch_read
181-
(i32.sub (get_local $sp) (i32.const 4))
182-
(i32.const 0)
183-
(i32.const 3)
190+
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 3))
184191
)
185192
(call $assert
186193
(i32.eq
@@ -204,24 +211,33 @@
204211
(i32.const 8) ;; Length of the buffer with value to transfer.
205212
(i32.const 8) ;; Pointer to input data buffer address
206213
(i32.const 8) ;; Length of input data buffer
214+
(i32.const 4294967295) ;; u32 max sentinel value: do not copy output
215+
(i32.const 0) ;; Length is ignored in this cas
207216
)
208217
)
209218

210219
;; Check for special trap exit status.
211220
(call $assert
212-
(i32.eq (get_local $exit_code) (i32.const 0x0100))
213-
)
214-
215-
;; Check that scratch buffer is empty since call trapped.
216-
(call $assert
217-
(i32.eq (call $ext_scratch_size) (i32.const 0))
221+
(i32.eq (get_local $exit_code) (i32.const 1)) ;; ReturnCode::CalleeTrapped
218222
)
219223

220224
;; Check that balance has not changed.
221225
(call $assert
222226
(i64.eq (get_local $balance) (call $current_balance (get_local $sp)))
223227
)
224228

229+
;; Zero out destination buffer of output
230+
(i32.store
231+
(i32.sub (get_local $sp) (i32.const 4))
232+
(i32.const 0)
233+
)
234+
235+
;; Length of the output buffer
236+
(i32.store
237+
(i32.sub (get_local $sp) (i32.const 8))
238+
(i32.const 4)
239+
)
240+
225241
;; Call the contract successfully.
226242
(set_local $exit_code
227243
(call $ext_call
@@ -232,26 +248,19 @@
232248
(i32.const 8) ;; Length of the buffer with value to transfer.
233249
(i32.const 8) ;; Pointer to input data buffer address
234250
(i32.const 8) ;; Length of input data buffer
251+
(i32.sub (get_local $sp) (i32.const 4)) ;; Ptr to output buffer
252+
(i32.sub (get_local $sp) (i32.const 8)) ;; Ptr to output buffer len
235253
)
236254
)
237255

238256
;; Check for success exit status.
239257
(call $assert
240-
(i32.eq (get_local $exit_code) (i32.const 0x00))
258+
(i32.eq (get_local $exit_code) (i32.const 0)) ;; ReturnCode::Success
241259
)
242260

243-
;; Check that scratch buffer contains the expected return data.
261+
;; Check that the output buffer contains the expected return data.
244262
(call $assert
245-
(i32.eq (call $ext_scratch_size) (i32.const 4))
246-
)
247-
(i32.store
248-
(i32.sub (get_local $sp) (i32.const 4))
249-
(i32.const 0)
250-
)
251-
(call $ext_scratch_read
252-
(i32.sub (get_local $sp) (i32.const 4))
253-
(i32.const 0)
254-
(i32.const 4)
263+
(i32.eq (i32.load (i32.sub (get_local $sp) (i32.const 8))) (i32.const 4))
255264
)
256265
(call $assert
257266
(i32.eq
@@ -271,5 +280,5 @@
271280

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

fixtures/check_default_rent_allowance.wat

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
(module
2-
(import "env" "ext_rent_allowance" (func $ext_rent_allowance))
3-
(import "env" "ext_scratch_size" (func $ext_scratch_size (result i32)))
4-
(import "env" "ext_scratch_read" (func $ext_scratch_read (param i32 i32 i32)))
2+
(import "env" "ext_rent_allowance" (func $ext_rent_allowance (param i32 i32)))
53
(import "env" "memory" (memory 1 1))
64

5+
;; [0, 8) reserved for $ext_rent_allowance output
6+
7+
;; [8, 16) length of the buffer
8+
(data (i32.const 8) "\08")
9+
10+
;; [16, inf) zero initialized
11+
712
(func $assert (param i32)
813
(block $ok
914
(br_if $ok
@@ -16,30 +21,21 @@
1621
(func (export "call"))
1722

1823
(func (export "deploy")
19-
;; fill the scratch buffer with the rent allowance.
20-
(call $ext_rent_allowance)
24+
;; fill the buffer with the rent allowance.
25+
(call $ext_rent_allowance (i32.const 0) (i32.const 8))
2126

22-
;; assert $ext_scratch_size == 8
27+
;; assert len == 8
2328
(call $assert
2429
(i32.eq
25-
(call $ext_scratch_size)
30+
(i32.load (i32.const 8))
2631
(i32.const 8)
2732
)
2833
)
2934

30-
;; copy contents of the scratch buffer into the contract's memory.
31-
(call $ext_scratch_read
32-
(i32.const 8) ;; Pointer in memory to the place where to copy.
33-
(i32.const 0) ;; Offset from the start of the scratch buffer.
34-
(i32.const 8) ;; Count of bytes to copy.
35-
)
36-
3735
;; assert that contents of the buffer is equal to <BalanceOf<T>>::max_value().
3836
(call $assert
3937
(i64.eq
40-
(i64.load
41-
(i32.const 8)
42-
)
38+
(i64.load (i32.const 0))
4339
(i64.const 0xFFFFFFFFFFFFFFFF)
4440
)
4541
)

0 commit comments

Comments
 (0)