Precompiles interface (#983)

* Start

* Some sha256 test passing

* precompiles folder

* Files reorg

* Progress

* Minor

* Start of sha2 interface

* All call opcodes

* ecrec

* rip160

* Fix copy_returndata_to_mem

* id

* bn_add

* bn_mul

* TODOs for snarkv and blake2

* Comments

* Use charge_gas_const when possible

* Minor

* Minor

* Minor

* PR feedback
This commit is contained in:
wborgeaud 2023-04-14 12:20:28 +02:00 committed by GitHub
parent b896f9b2da
commit b721236eb3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 477 additions and 27 deletions

View File

@ -40,6 +40,16 @@ pub(crate) fn combined_kernel() -> Kernel {
include_str!("asm/core/util.asm"),
include_str!("asm/core/access_lists.asm"),
include_str!("asm/core/selfdestruct_list.asm"),
include_str!("asm/core/precompiles/main.asm"),
include_str!("asm/core/precompiles/ecrec.asm"),
include_str!("asm/core/precompiles/sha256.asm"),
include_str!("asm/core/precompiles/rip160.asm"),
include_str!("asm/core/precompiles/id.asm"),
include_str!("asm/core/precompiles/expmod.asm"),
include_str!("asm/core/precompiles/bn_add.asm"),
include_str!("asm/core/precompiles/bn_mul.asm"),
include_str!("asm/core/precompiles/snarkv.asm"),
include_str!("asm/core/precompiles/blake2_f.asm"),
include_str!("asm/curve/bls381/util.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/constants.asm"),
include_str!("asm/curve/bn254/curve_arithmetic/curve_add.asm"),

View File

@ -29,19 +29,24 @@ global sys_call:
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
// TODO: Consider call depth
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
DUP5 DUP5 %address %transfer_eth %jumpi(panic) // TODO: Fix this panic.
DUP3 %set_new_ctx_gas_limit
%set_new_ctx_parent_pc(after_call_instruction)
DUP9 DUP9 DUP4 DUP4 DUP8 // Duplicate address, new_ctx, kexit_info, ret_offset, and ret_size.
// stack: address, new_ctx, kexit_info, ret_offset, ret_size, ...
%handle_precompiles
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
// Each line in the block below does not change the stack.
DUP4 %set_new_ctx_addr
%address %set_new_ctx_caller
DUP5 %set_new_ctx_value
DUP5 DUP5 %address %transfer_eth %jumpi(panic) // TODO: Fix this panic.
%set_new_ctx_parent_pc(after_call_instruction)
DUP3 %set_new_ctx_gas_limit
DUP4 %set_new_ctx_code
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
-> (new_ctx, kexit_info, ret_offset, ret_size)
@ -69,17 +74,23 @@ global sys_callcode:
%create_context
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
DUP3 %set_new_ctx_gas_limit
%set_new_ctx_parent_pc(after_call_instruction)
DUP9 DUP9 DUP4 DUP4 DUP8 // Duplicate address, new_ctx, kexit_info, ret_offset, and ret_size.
// stack: address, new_ctx, kexit_info, ret_offset, ret_size, ...
%handle_precompiles
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
// Each line in the block below does not change the stack.
%address %set_new_ctx_addr
%address %set_new_ctx_caller
DUP5 %set_new_ctx_value
%set_new_ctx_parent_pc(after_call_instruction)
DUP3 %set_new_ctx_gas_limit
DUP4 %set_new_ctx_code
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
@ -113,18 +124,24 @@ global sys_staticcall:
%create_context
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
DUP3 %set_new_ctx_gas_limit
%set_new_ctx_parent_pc(after_call_instruction)
DUP9 DUP9 DUP4 DUP4 DUP8 // Duplicate address, new_ctx, kexit_info, ret_offset, and ret_size.
// stack: address, new_ctx, kexit_info, ret_offset, ret_size, ...
%handle_precompiles
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
// Each line in the block below does not change the stack.
%set_static_true
DUP4 %set_new_ctx_addr
%address %set_new_ctx_caller
PUSH 0 %set_new_ctx_value
%set_new_ctx_parent_pc(after_call_instruction)
DUP3 %set_new_ctx_gas_limit
DUP4 %set_new_ctx_code
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
-> (new_ctx, kexit_info, ret_offset, ret_size)
@ -155,18 +172,24 @@ global sys_delegatecall:
%create_context
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
DUP3 %set_new_ctx_gas_limit
%set_new_ctx_parent_pc(after_call_instruction)
DUP9 DUP9 DUP4 DUP4 DUP8 // Duplicate address, new_ctx, kexit_info, ret_offset, and ret_size.
// stack: address, new_ctx, kexit_info, ret_offset, ret_size, ...
%handle_precompiles
// stack: new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
// Each line in the block below does not change the stack.
%address %set_new_ctx_addr
%caller %set_new_ctx_caller
%callvalue %set_new_ctx_value
%set_new_ctx_parent_pc(after_call_instruction)
DUP3 %set_new_ctx_gas_limit
DUP4 %set_new_ctx_code
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
(new_ctx, args_offset, args_size, new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
%copy_mem_to_calldata
%stack (new_ctx, kexit_info, callgas, address, args_offset, args_size, ret_offset, ret_size)
-> (new_ctx, kexit_info, ret_offset, ret_size)
%enter_new_ctx

View File

@ -0,0 +1,3 @@
global precompile_blake2_f:
// TODO
PANIC

View File

@ -0,0 +1,48 @@
global precompile_bn_add:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%charge_gas_const(@BN_ADD_GAS)
// Load x0, y0, x1, y1 from the call data using `mload_packing`.
GET_CONTEXT
%stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 96, 32, bn_add_contd, kexit_info)
%jump(mload_packing)
bn_add_contd:
GET_CONTEXT
%stack (ctx, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, bn_add_contd2, y1, kexit_info)
%jump(mload_packing)
bn_add_contd2:
GET_CONTEXT
%stack (ctx, x1, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, bn_add_contd3, x1, y1, kexit_info)
%jump(mload_packing)
bn_add_contd3:
GET_CONTEXT
%stack (ctx, y0, x1, y1, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, bn_add_contd4, y0, x1, y1, kexit_info)
%jump(mload_packing)
bn_add_contd4:
%stack (x0, y0, x1, y1, kexit_info) -> (x0, y0, x1, y1, bn_add_contd5, kexit_info)
%jump(bn_add)
bn_add_contd5:
// stack: x, y, kexit_info
DUP2 %eq_const(@U256_MAX) // bn_add returns (U256_MAX, U256_MAX) on bad input.
DUP2 %eq_const(@U256_MAX) // bn_add returns (U256_MAX, U256_MAX) on bad input.
MUL // Cheaper than AND
%jumpi(fault_exception)
// stack: x, y, kexit_info
// Store the result (x, y) to the parent's return data using `mstore_unpacking`.
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 64)
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, x, y) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, x, 32, bn_add_contd6, parent_ctx, y)
%jump(mstore_unpacking)
bn_add_contd6:
POP
%stack (parent_ctx, y) -> (parent_ctx, @SEGMENT_RETURNDATA, 32, y, 32, pop_and_return_success)
%jump(mstore_unpacking)

View File

@ -0,0 +1,44 @@
global precompile_bn_mul:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%charge_gas_const(@BN_MUL_GAS)
// Load x, y, n from the call data using `mload_packing`.
GET_CONTEXT
%stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, bn_mul_contd, kexit_info)
%jump(mload_packing)
bn_mul_contd:
GET_CONTEXT
%stack (ctx, n, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, bn_mul_contd2, n, kexit_info)
%jump(mload_packing)
bn_mul_contd2:
GET_CONTEXT
%stack (ctx, y, n, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, bn_mul_contd3, y, n, kexit_info)
%jump(mload_packing)
bn_mul_contd3:
%stack (x, y, n, kexit_info) -> (x, y, n, bn_mul_contd4, kexit_info)
%jump(bn_mul)
bn_mul_contd4:
// stack: Px, Py, kexit_info
DUP2 %eq_const(@U256_MAX) // bn_mul returns (U256_MAX, U256_MAX) on bad input.
DUP2 %eq_const(@U256_MAX) // bn_mul returns (U256_MAX, U256_MAX) on bad input.
MUL // Cheaper than AND
%jumpi(fault_exception)
// stack: Px, Py, kexit_info
// Store the result (Px, Py) to the parent's return data using `mstore_unpacking`.
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 64)
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, Px, Py) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, Px, 32, bn_mul_contd6, parent_ctx, Py)
%jump(mstore_unpacking)
bn_mul_contd6:
POP
%stack (parent_ctx, Py) -> (parent_ctx, @SEGMENT_RETURNDATA, 32, Py, 32, pop_and_return_success)
%jump(mstore_unpacking)

View File

@ -0,0 +1,45 @@
global precompile_ecrec:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%charge_gas_const(@ECREC_GAS)
// Load hash, v, r, s from the call data using `mload_packing`.
GET_CONTEXT
%stack (ctx, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 96, 32, ecrec_contd, kexit_info)
%jump(mload_packing)
ecrec_contd:
GET_CONTEXT
%stack (ctx, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 64, 32, ecrec_contd2, s, kexit_info)
%jump(mload_packing)
ecrec_contd2:
GET_CONTEXT
%stack (ctx, r, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 32, 32, ecrec_contd3, r, s, kexit_info)
%jump(mload_packing)
ecrec_contd3:
GET_CONTEXT
%stack (ctx, v, r, s, kexit_info) -> (ctx, @SEGMENT_CALLDATA, 0, 32, ecrec_contd4, v, r, s, kexit_info)
%jump(mload_packing)
ecrec_contd4:
%stack (hash, v, r, s, kexit_info) -> (hash, v, r, s, ecrec_contd5, kexit_info)
%jump(ecrecover)
ecrec_contd5:
// stack: address, kexit_info
DUP1 %eq_const(@U256_MAX) %jumpi(ecrec_bad_input) // ecrecover returns U256_MAX on bad input.
// Store the result address to the parent's return data using `mstore_unpacking`.
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32)
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, address) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, address, 32, pop_and_return_success)
%jump(mstore_unpacking)
// On bad input, return empty return data but still return success.
ecrec_bad_input:
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 0)
%jump(pop_and_return_success)

View File

@ -0,0 +1,3 @@
global precompile_expmod:
// TODO
PANIC

View File

@ -0,0 +1,38 @@
global precompile_id:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%calldatasize
%num_bytes_to_num_words
// stack: data_words_len, kexit_info
%mul_const(@ID_DYNAMIC_GAS)
PUSH @ID_STATIC_GAS
ADD
// stack: gas, kexit_info
%charge_gas
// Simply copy the call data to the parent's return data.
%calldatasize
DUP1 %mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE)
GET_CONTEXT
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, ctx, size) ->
(
parent_ctx, @SEGMENT_RETURNDATA, 0, // DST
ctx, @SEGMENT_CALLDATA, 0, // SRC
size, id_contd // count, retdest
)
%jump(memcpy)
id_contd:
// stack: kexit_info
%leftover_gas
// stack: leftover_gas
PUSH 1 // success
%jump(terminate_common)

View File

@ -0,0 +1,135 @@
%macro handle_precompiles
// stack: address, new_ctx, kexit_info, ret_offset, ret_size
PUSH %%after
SWAP1
// stack: address, %%after, new_ctx, kexit_info, ret_offset, ret_size
%jump(handle_precompiles)
%%after:
// stack: new_ctx, kexit_info, ret_offset, ret_size
%pop4
%endmacro
global handle_precompiles:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
DUP1 %eq_const(@ECREC) %jumpi(precompile_ecrec)
DUP1 %eq_const(@SHA256) %jumpi(precompile_sha256)
DUP1 %eq_const(@RIP160) %jumpi(precompile_rip160)
DUP1 %eq_const(@ID) %jumpi(precompile_id)
DUP1 %eq_const(@EXPMOD) %jumpi(precompile_expmod)
DUP1 %eq_const(@BN_ADD) %jumpi(precompile_bn_add)
DUP1 %eq_const(@BN_MUL) %jumpi(precompile_bn_mul)
DUP1 %eq_const(@SNARKV) %jumpi(precompile_snarkv)
%eq_const(@BLAKE2_F) %jumpi(precompile_blake2_f)
// stack: retdest
JUMP
global pop_and_return_success:
// stack: _unused, kexit_info
POP
%leftover_gas
// stack: leftover_gas
PUSH 1 // success
%jump(terminate_common)
%macro zero_out_kernel_general
PUSH 0 PUSH 0 %mstore_kernel_general
PUSH 0 PUSH 1 %mstore_kernel_general
PUSH 0 PUSH 2 %mstore_kernel_general
PUSH 0 PUSH 3 %mstore_kernel_general
PUSH 0 PUSH 4 %mstore_kernel_general
PUSH 0 PUSH 5 %mstore_kernel_general
PUSH 0 PUSH 6 %mstore_kernel_general
PUSH 0 PUSH 7 %mstore_kernel_general
PUSH 0 PUSH 8 %mstore_kernel_general
PUSH 0 PUSH 9 %mstore_kernel_general
PUSH 0 PUSH 10 %mstore_kernel_general
PUSH 0 PUSH 11 %mstore_kernel_general
PUSH 0 PUSH 12 %mstore_kernel_general
PUSH 0 PUSH 13 %mstore_kernel_general
PUSH 0 PUSH 14 %mstore_kernel_general
PUSH 0 PUSH 15 %mstore_kernel_general
PUSH 0 PUSH 16 %mstore_kernel_general
PUSH 0 PUSH 17 %mstore_kernel_general
PUSH 0 PUSH 18 %mstore_kernel_general
PUSH 0 PUSH 19 %mstore_kernel_general
PUSH 0 PUSH 20 %mstore_kernel_general
PUSH 0 PUSH 21 %mstore_kernel_general
PUSH 0 PUSH 22 %mstore_kernel_general
PUSH 0 PUSH 23 %mstore_kernel_general
PUSH 0 PUSH 24 %mstore_kernel_general
PUSH 0 PUSH 25 %mstore_kernel_general
PUSH 0 PUSH 26 %mstore_kernel_general
PUSH 0 PUSH 27 %mstore_kernel_general
PUSH 0 PUSH 28 %mstore_kernel_general
PUSH 0 PUSH 29 %mstore_kernel_general
PUSH 0 PUSH 30 %mstore_kernel_general
PUSH 0 PUSH 31 %mstore_kernel_general
PUSH 0 PUSH 32 %mstore_kernel_general
PUSH 0 PUSH 33 %mstore_kernel_general
PUSH 0 PUSH 34 %mstore_kernel_general
PUSH 0 PUSH 35 %mstore_kernel_general
PUSH 0 PUSH 36 %mstore_kernel_general
PUSH 0 PUSH 37 %mstore_kernel_general
PUSH 0 PUSH 38 %mstore_kernel_general
PUSH 0 PUSH 39 %mstore_kernel_general
PUSH 0 PUSH 40 %mstore_kernel_general
PUSH 0 PUSH 41 %mstore_kernel_general
PUSH 0 PUSH 42 %mstore_kernel_general
PUSH 0 PUSH 43 %mstore_kernel_general
PUSH 0 PUSH 44 %mstore_kernel_general
PUSH 0 PUSH 45 %mstore_kernel_general
PUSH 0 PUSH 46 %mstore_kernel_general
PUSH 0 PUSH 47 %mstore_kernel_general
PUSH 0 PUSH 48 %mstore_kernel_general
PUSH 0 PUSH 49 %mstore_kernel_general
PUSH 0 PUSH 50 %mstore_kernel_general
PUSH 0 PUSH 51 %mstore_kernel_general
PUSH 0 PUSH 52 %mstore_kernel_general
PUSH 0 PUSH 53 %mstore_kernel_general
PUSH 0 PUSH 54 %mstore_kernel_general
PUSH 0 PUSH 55 %mstore_kernel_general
PUSH 0 PUSH 56 %mstore_kernel_general
PUSH 0 PUSH 57 %mstore_kernel_general
PUSH 0 PUSH 58 %mstore_kernel_general
PUSH 0 PUSH 59 %mstore_kernel_general
PUSH 0 PUSH 60 %mstore_kernel_general
PUSH 0 PUSH 61 %mstore_kernel_general
PUSH 0 PUSH 62 %mstore_kernel_general
PUSH 0 PUSH 63 %mstore_kernel_general
PUSH 0 PUSH 64 %mstore_kernel_general
PUSH 0 PUSH 65 %mstore_kernel_general
PUSH 0 PUSH 66 %mstore_kernel_general
PUSH 0 PUSH 67 %mstore_kernel_general
PUSH 0 PUSH 68 %mstore_kernel_general
PUSH 0 PUSH 69 %mstore_kernel_general
PUSH 0 PUSH 70 %mstore_kernel_general
PUSH 0 PUSH 71 %mstore_kernel_general
PUSH 0 PUSH 72 %mstore_kernel_general
PUSH 0 PUSH 73 %mstore_kernel_general
PUSH 0 PUSH 74 %mstore_kernel_general
PUSH 0 PUSH 75 %mstore_kernel_general
PUSH 0 PUSH 76 %mstore_kernel_general
PUSH 0 PUSH 77 %mstore_kernel_general
PUSH 0 PUSH 78 %mstore_kernel_general
PUSH 0 PUSH 79 %mstore_kernel_general
PUSH 0 PUSH 80 %mstore_kernel_general
PUSH 0 PUSH 81 %mstore_kernel_general
PUSH 0 PUSH 82 %mstore_kernel_general
PUSH 0 PUSH 83 %mstore_kernel_general
PUSH 0 PUSH 84 %mstore_kernel_general
PUSH 0 PUSH 85 %mstore_kernel_general
PUSH 0 PUSH 86 %mstore_kernel_general
PUSH 0 PUSH 87 %mstore_kernel_general
PUSH 0 PUSH 88 %mstore_kernel_general
PUSH 0 PUSH 89 %mstore_kernel_general
PUSH 0 PUSH 90 %mstore_kernel_general
PUSH 0 PUSH 91 %mstore_kernel_general
PUSH 0 PUSH 92 %mstore_kernel_general
PUSH 0 PUSH 93 %mstore_kernel_general
PUSH 0 PUSH 94 %mstore_kernel_general
PUSH 0 PUSH 95 %mstore_kernel_general
PUSH 0 PUSH 96 %mstore_kernel_general
PUSH 0 PUSH 97 %mstore_kernel_general
PUSH 0 PUSH 98 %mstore_kernel_general
PUSH 0 PUSH 99 %mstore_kernel_general
%endmacro

View File

@ -0,0 +1,38 @@
global precompile_rip160:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%calldatasize
%num_bytes_to_num_words
// stack: data_words_len, kexit_info
%mul_const(@RIP160_DYNAMIC_GAS)
PUSH @RIP160_STATIC_GAS
ADD
// stack: gas, kexit_info
%charge_gas
// Copy the call data to the kernel general segment (ripemd expects it there) and call ripemd.
%calldatasize
GET_CONTEXT
%stack (ctx, size) ->
(
0, @SEGMENT_KERNEL_GENERAL, 200, // DST
ctx, @SEGMENT_CALLDATA, 0, // SRC
size, ripemd, // count, retdest
200, size, rip160_contd // ripemd input: virt, num_bytes, retdest
)
%jump(memcpy)
rip160_contd:
// stack: hash, kexit_info
// Store the result hash to the parent's return data using `mstore_unpacking`.
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32)
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, hash) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, hash, 32, pop_and_return_success)
%jump(mstore_unpacking)

View File

@ -0,0 +1,41 @@
global precompile_sha256:
// stack: address, retdest, new_ctx, kexit_info, ret_offset, ret_size
%pop2
// stack: new_ctx, kexit_info, ret_offset, ret_size
DUP1
SET_CONTEXT
// stack: (empty)
PUSH 0x100000000 // = 2^32 (is_kernel = true)
// stack: kexit_info
%calldatasize
%num_bytes_to_num_words
// stack: data_words_len, kexit_info
%mul_const(@SHA256_DYNAMIC_GAS)
PUSH @SHA256_STATIC_GAS
ADD
// stack: gas, kexit_info
%charge_gas
// TODO: fix this
%zero_out_kernel_general
// Copy the call data to the kernel general segment (sha2 expects it there) and call sha2.
%calldatasize
GET_CONTEXT
%stack (ctx, size) ->
(
0, @SEGMENT_KERNEL_GENERAL, 1, // DST
ctx, @SEGMENT_CALLDATA, 0, // SRC
size, sha2, // count, retdest
0, size, sha256_contd // sha2 input: virt, num_bytes, retdest
)
%jump(memcpy)
sha256_contd:
// stack: hash, kexit_info
// Store the result hash to the parent's return data using `mstore_unpacking`.
%mstore_parent_context_metadata(@CTX_METADATA_RETURNDATA_SIZE, 32)
%mload_context_metadata(@CTX_METADATA_PARENT_CONTEXT)
%stack (parent_ctx, hash) -> (parent_ctx, @SEGMENT_RETURNDATA, 0, hash, 32, pop_and_return_success)
%jump(mstore_unpacking)

View File

@ -0,0 +1,3 @@
global precompile_snarkv:
// TODO
PANIC

View File

@ -1,6 +1,7 @@
// BN254 elliptic curve addition.
// Uses the standard affine addition formula.
global bn_add:
// stack: x0, y0, x1, y1, retdest
// Check if points are valid BN254 points.
DUP2
// stack: y0, x0, y0, x1, y1, retdest
@ -257,7 +258,7 @@ global bn_double:
// Return (u256::MAX, u256::MAX) which is used to indicate the input was invalid.
%macro bn_invalid_input
// stack: retdest
PUSH 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
PUSH @U256_MAX
// stack: u256::MAX, retdest
DUP1
// stack: u256::MAX, u256::MAX, retdest

View File

@ -108,9 +108,7 @@ pubkey_to_addr:
// stack: PKx, PKy, retdest
%keccak256_u256_pair
// stack: hash, retdest
PUSH 0xffffffffffffffffffffffffffffffffffffffff
// stack: 2^160-1, hash, retdest
AND
%u256_to_addr
// stack: address, retdest
SWAP1
// stack: retdest, address

View File

@ -6,7 +6,7 @@ global sha2:
// stack: virt, num_bytes, virt, retdest
%mstore_kernel_general
// stack: virt, retdest
// Precodition: input is in memory, starting at virt of kernel general segment, of the form
// num_bytes, x[0], x[1], ..., x[num_bytes - 1]

View File

@ -36,6 +36,10 @@ pub fn evm_constants() -> HashMap<String, U256> {
c.insert(name.into(), U256::from(value));
}
for (name, value) in PRECOMPILES_GAS {
c.insert(name.into(), U256::from(value));
}
for segment in Segment::all() {
c.insert(segment.var_name().into(), (segment as u32).into());
}
@ -207,3 +211,19 @@ const PRECOMPILES: [(&str, u16); 9] = [
("SNARKV", 8),
("BLAKE2_F", 9),
];
const PRECOMPILES_GAS: [(&str, u16); 13] = [
("ECREC_GAS", 3_000),
("SHA256_STATIC_GAS", 60),
("SHA256_DYNAMIC_GAS", 12),
("RIP160_STATIC_GAS", 600),
("RIP160_DYNAMIC_GAS", 120),
("ID_STATIC_GAS", 15),
("ID_DYNAMIC_GAS", 3),
("EXPMOD_MIN_GAS", 200),
("BN_ADD_GAS", 150),
("BN_MUL_GAS", 6_000),
("SNARKV_STATIC_GAS", 45_000),
("SNARKV_DYNAMIC_GAS", 34_000),
("BLAKE2_F_DYNAMIC_GAS", 1),
];