mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Merge branch 'main' of github.com:mir-protocol/plonky2 into bls-fp2
This commit is contained in:
commit
a5c6b14e34
@ -141,8 +141,6 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
|
||||
{
|
||||
let local_values = vars.local_values.borrow();
|
||||
let next_values = vars.next_values.borrow();
|
||||
// TODO: Some failing constraints temporarily disabled by using this dummy consumer.
|
||||
let mut dummy_yield_constr = ConstraintConsumer::new(vec![], P::ZEROS, P::ZEROS, P::ZEROS);
|
||||
bootstrap_kernel::eval_bootstrap_kernel(vars, yield_constr);
|
||||
contextops::eval_packed(local_values, next_values, yield_constr);
|
||||
control_flow::eval_packed_generic(local_values, next_values, yield_constr);
|
||||
@ -156,8 +154,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
|
||||
pc::eval_packed(local_values, yield_constr);
|
||||
shift::eval_packed(local_values, yield_constr);
|
||||
simple_logic::eval_packed(local_values, yield_constr);
|
||||
stack::eval_packed(local_values, &mut dummy_yield_constr);
|
||||
stack_bounds::eval_packed(local_values, &mut dummy_yield_constr);
|
||||
stack::eval_packed(local_values, yield_constr);
|
||||
stack_bounds::eval_packed(local_values, yield_constr);
|
||||
syscalls::eval_packed(local_values, next_values, yield_constr);
|
||||
}
|
||||
|
||||
@ -169,10 +167,6 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
|
||||
) {
|
||||
let local_values = vars.local_values.borrow();
|
||||
let next_values = vars.next_values.borrow();
|
||||
// TODO: Some failing constraints temporarily disabled by using this dummy consumer.
|
||||
let zero = builder.zero_extension();
|
||||
let mut dummy_yield_constr =
|
||||
RecursiveConstraintConsumer::new(zero, vec![], zero, zero, zero);
|
||||
bootstrap_kernel::eval_bootstrap_kernel_circuit(builder, vars, yield_constr);
|
||||
contextops::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
||||
control_flow::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
||||
@ -186,8 +180,8 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for CpuStark<F, D
|
||||
pc::eval_ext_circuit(builder, local_values, yield_constr);
|
||||
shift::eval_ext_circuit(builder, local_values, yield_constr);
|
||||
simple_logic::eval_ext_circuit(builder, local_values, yield_constr);
|
||||
stack::eval_ext_circuit(builder, local_values, &mut dummy_yield_constr);
|
||||
stack_bounds::eval_ext_circuit(builder, local_values, &mut dummy_yield_constr);
|
||||
stack::eval_ext_circuit(builder, local_values, yield_constr);
|
||||
stack_bounds::eval_ext_circuit(builder, local_values, yield_constr);
|
||||
syscalls::eval_ext_circuit(builder, local_values, next_values, yield_constr);
|
||||
}
|
||||
|
||||
|
||||
@ -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"),
|
||||
|
||||
@ -2,7 +2,15 @@
|
||||
|
||||
// Creates a new sub context and executes the code of the given account.
|
||||
global sys_call:
|
||||
// Check that the value is zero if the context is static.
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
DUP4 ISZERO %not_bit
|
||||
// stack: value≠0, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%mload_context_metadata(@CTX_METADATA_STATIC)
|
||||
// stack: is_static, value≠0, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
MUL // Cheaper than AND
|
||||
%jumpi(fault_exception)
|
||||
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
@ -21,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)
|
||||
@ -43,25 +56,44 @@ global sys_call:
|
||||
// given account. In particular the storage remains the same.
|
||||
global sys_callcode:
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
DUP1 %insert_accessed_addresses
|
||||
|
||||
%call_charge_gas
|
||||
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(args_size, args_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(ret_size, ret_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
|
||||
// stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, 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
|
||||
|
||||
%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
|
||||
DUP5 DUP5 %address %transfer_eth %jumpi(panic) // TODO: Fix this panic.
|
||||
%set_new_ctx_parent_pc(after_call_instruction)
|
||||
DUP4 %set_new_ctx_code
|
||||
|
||||
// stack: new_ctx, kexit_info, gas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%stack (new_ctx, kexit_info, gas, 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
|
||||
%stack (new_ctx, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
-> (new_ctx, kexit_info, ret_offset, ret_size)
|
||||
%enter_new_ctx
|
||||
|
||||
@ -72,24 +104,46 @@ global sys_callcode:
|
||||
// CALL if the value sent is not 0.
|
||||
global sys_staticcall:
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
DUP1 %insert_accessed_addresses
|
||||
|
||||
// Add a value of 0 to the stack. Slightly inefficient but that way we can reuse %call_charge_gas.
|
||||
%stack (cold_access, address, gas, kexit_info) -> (cold_access, address, gas, kexit_info, 0)
|
||||
%call_charge_gas
|
||||
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(args_size, args_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(ret_size, ret_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
|
||||
// stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// 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)
|
||||
DUP4 %set_new_ctx_code
|
||||
|
||||
%stack (new_ctx, kexit_info, gas, address, 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)
|
||||
%enter_new_ctx
|
||||
|
||||
@ -98,23 +152,45 @@ global sys_staticcall:
|
||||
// value remain the same.
|
||||
global sys_delegatecall:
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// TODO: Charge gas.
|
||||
SWAP2
|
||||
// stack: address, gas, kexit_info, args_offset, args_size, ret_offset, ret_size
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses POP // TODO: Use return value in gas calculation.
|
||||
SWAP2
|
||||
// stack: kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
DUP1 %insert_accessed_addresses
|
||||
|
||||
// Add a value of 0 to the stack. Slightly inefficient but that way we can reuse %call_charge_gas.
|
||||
%stack (cold_access, address, gas, kexit_info) -> (cold_access, address, gas, kexit_info, 0)
|
||||
%call_charge_gas
|
||||
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(args_size, args_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
%stack (kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size) ->
|
||||
(ret_size, ret_offset, kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size)
|
||||
%checked_mem_expansion
|
||||
|
||||
// stack: kexit_info, callgas, address, value, args_offset, args_size, ret_offset, ret_size
|
||||
%create_context
|
||||
// stack: new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size
|
||||
// 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)
|
||||
DUP4 %set_new_ctx_code
|
||||
|
||||
%stack (new_ctx, kexit_info, gas, address, args_offset, args_size, ret_offset, ret_size)
|
||||
%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
|
||||
|
||||
@ -210,9 +286,7 @@ global after_call_instruction:
|
||||
%stack (address, new_ctx) -> (address, new_ctx, @SEGMENT_CODE, %%after, new_ctx)
|
||||
%jump(load_code)
|
||||
%%after:
|
||||
%stack (code_size, new_ctx)
|
||||
-> (new_ctx, @SEGMENT_CONTEXT_METADATA, @CTX_METADATA_CODE_SIZE, code_size, new_ctx)
|
||||
MSTORE_GENERAL
|
||||
%set_new_ctx_code_size
|
||||
// stack: new_ctx
|
||||
%endmacro
|
||||
|
||||
@ -246,12 +320,16 @@ global after_call_instruction:
|
||||
|
||||
%macro copy_returndata_to_mem
|
||||
// stack: kexit_info, new_ctx, success, ret_offset, ret_size
|
||||
SWAP4
|
||||
%returndatasize
|
||||
// stack: returndata_size, ret_size, new_ctx, success, ret_offset, kexit_info
|
||||
%min
|
||||
GET_CONTEXT
|
||||
%stack (ctx, kexit_info, new_ctx, success, ret_offset, ret_size) ->
|
||||
%stack (ctx, n, new_ctx, success, ret_offset, kexit_info) ->
|
||||
(
|
||||
ctx, @SEGMENT_MAIN_MEMORY, ret_offset, // DST
|
||||
ctx, @SEGMENT_RETURNDATA, 0, // SRC
|
||||
ret_size, %%after, // count, retdest
|
||||
n, %%after, // count, retdest
|
||||
kexit_info, success
|
||||
)
|
||||
%jump(memcpy)
|
||||
@ -262,13 +340,13 @@ global after_call_instruction:
|
||||
// Doesn't include memory expansion costs.
|
||||
%macro call_charge_gas
|
||||
// Compute C_aaccess
|
||||
// stack: cold_access, address, gas, kexit_info, value, args_offset, args_size, ret_offset, ret_size
|
||||
// stack: cold_access, address, gas, kexit_info, value
|
||||
%mul_const(@GAS_COLDACCOUNTACCESS_MINUS_WARMACCESS)
|
||||
%add_const(@GAS_WARMACCESS)
|
||||
|
||||
// Compute C_xfer
|
||||
// stack: Caaccess, address, gas, kexit_info, value
|
||||
DUP5 ISZERO PUSH 1 SUB
|
||||
DUP5 ISZERO %not_bit
|
||||
// stack: value≠0, Caaccess, address, gas, kexit_info, value
|
||||
DUP1
|
||||
%mul_const(@GAS_CALLVALUE)
|
||||
@ -293,7 +371,7 @@ global after_call_instruction:
|
||||
// stack: leftover_gas<Cextra, leftover_gas, Cextra, address, gas, kexit_info, value
|
||||
DUP5 DUP2 MUL
|
||||
// stack: (leftover_gas<Cextra)*gas, leftover_gas<Cextra, leftover_gas, Cextra, address, gas, kexit_info, value
|
||||
SWAP1 PUSH 1 SUB
|
||||
SWAP1 %not_bit
|
||||
// stack: leftover_gas>=Cextra, (leftover_gas<Cextra)*gas, leftover_gas, Cextra, address, gas, kexit_info, value
|
||||
DUP4 DUP4 SUB
|
||||
// stack: leftover_gas - Cextra, leftover_gas>=Cextra, (leftover_gas<Cextra)*gas, leftover_gas, Cextra, address, gas, kexit_info, value
|
||||
@ -312,7 +390,7 @@ global after_call_instruction:
|
||||
// Compute C_callgas
|
||||
%stack (kexit_info, Cgascap, address, gas, value) ->
|
||||
(Cgascap, address, gas, kexit_info, value)
|
||||
DUP5 ISZERO PUSH 1 SUB
|
||||
DUP5 ISZERO %not_bit
|
||||
// stack: value!=0, Cgascap, address, gas, kexit_info, value
|
||||
%mul_const(@GAS_CALLSTIPEND) ADD
|
||||
%stack (C_callgas, address, gas, kexit_info, value) ->
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// Pre stack: kexit_info, value, code_offset, code_len
|
||||
// Post stack: address
|
||||
global sys_create:
|
||||
%check_static
|
||||
// stack: kexit_info, value, code_offset, code_len
|
||||
// TODO: Charge gas.
|
||||
%stack (kexit_info, value, code_offset, code_len)
|
||||
@ -25,6 +26,7 @@ sys_create_got_address:
|
||||
// Pre stack: kexit_info, value, code_offset, code_len, salt
|
||||
// Post stack: address
|
||||
global sys_create2:
|
||||
%check_static
|
||||
// stack: kexit_info, value, code_offset, code_len, salt
|
||||
// TODO: Charge gas.
|
||||
SWAP4
|
||||
|
||||
3
evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm
Normal file
3
evm/src/cpu/kernel/asm/core/precompiles/blake2_f.asm
Normal file
@ -0,0 +1,3 @@
|
||||
global precompile_blake2_f:
|
||||
// TODO
|
||||
PANIC
|
||||
48
evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm
Normal file
48
evm/src/cpu/kernel/asm/core/precompiles/bn_add.asm
Normal 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)
|
||||
44
evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm
Normal file
44
evm/src/cpu/kernel/asm/core/precompiles/bn_mul.asm
Normal 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)
|
||||
45
evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm
Normal file
45
evm/src/cpu/kernel/asm/core/precompiles/ecrec.asm
Normal 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)
|
||||
3
evm/src/cpu/kernel/asm/core/precompiles/expmod.asm
Normal file
3
evm/src/cpu/kernel/asm/core/precompiles/expmod.asm
Normal file
@ -0,0 +1,3 @@
|
||||
global precompile_expmod:
|
||||
// TODO
|
||||
PANIC
|
||||
38
evm/src/cpu/kernel/asm/core/precompiles/id.asm
Normal file
38
evm/src/cpu/kernel/asm/core/precompiles/id.asm
Normal 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)
|
||||
135
evm/src/cpu/kernel/asm/core/precompiles/main.asm
Normal file
135
evm/src/cpu/kernel/asm/core/precompiles/main.asm
Normal 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
|
||||
38
evm/src/cpu/kernel/asm/core/precompiles/rip160.asm
Normal file
38
evm/src/cpu/kernel/asm/core/precompiles/rip160.asm
Normal 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)
|
||||
41
evm/src/cpu/kernel/asm/core/precompiles/sha256.asm
Normal file
41
evm/src/cpu/kernel/asm/core/precompiles/sha256.asm
Normal 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)
|
||||
3
evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm
Normal file
3
evm/src/cpu/kernel/asm/core/precompiles/snarkv.asm
Normal file
@ -0,0 +1,3 @@
|
||||
global precompile_snarkv:
|
||||
// TODO
|
||||
PANIC
|
||||
@ -6,22 +6,18 @@ global sys_blockhash:
|
||||
global sys_prevrandao:
|
||||
// TODO: What semantics will this have for Edge?
|
||||
PANIC
|
||||
global sys_chainid:
|
||||
// TODO: Return the block's chain ID instead of the txn's, even though they should match.
|
||||
// stack: kexit_info
|
||||
%charge_gas_const(@GAS_BASE)
|
||||
// stack: kexit_info
|
||||
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
|
||||
// stack: chain_id, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
global sys_log0:
|
||||
%check_static
|
||||
PANIC
|
||||
global sys_log1:
|
||||
%check_static
|
||||
PANIC
|
||||
global sys_log2:
|
||||
%check_static
|
||||
PANIC
|
||||
global sys_log3:
|
||||
%check_static
|
||||
PANIC
|
||||
global sys_log4:
|
||||
%check_static
|
||||
PANIC
|
||||
|
||||
@ -45,6 +45,7 @@ sys_return_finish:
|
||||
%jump(terminate_common)
|
||||
|
||||
global sys_selfdestruct:
|
||||
%check_static
|
||||
// stack: kexit_info, recipient
|
||||
SWAP1 %u256_to_addr
|
||||
%address DUP1 %balance
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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]
|
||||
|
||||
@ -200,6 +200,19 @@ global sys_gaslimit:
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
|
||||
%macro blockchainid
|
||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_CHAIN_ID)
|
||||
%endmacro
|
||||
|
||||
global sys_chainid:
|
||||
// stack: kexit_info
|
||||
%charge_gas_const(@GAS_BASE)
|
||||
// stack: kexit_info
|
||||
%blockchainid
|
||||
// stack: chain_id, kexit_info
|
||||
SWAP1
|
||||
EXIT_KERNEL
|
||||
|
||||
%macro basefee
|
||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_BASE_FEE)
|
||||
%endmacro
|
||||
@ -283,3 +296,10 @@ global sys_basefee:
|
||||
%jumpi(fault_exception)
|
||||
// stack: (empty)
|
||||
%endmacro
|
||||
|
||||
// Convenience macro for checking if the current context is static.
|
||||
// Called before state-changing opcodes.
|
||||
%macro check_static
|
||||
%mload_context_metadata(@CTX_METADATA_STATIC)
|
||||
%jumpi(fault_exception)
|
||||
%endmacro
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// Post stack: (empty)
|
||||
|
||||
global sys_sstore:
|
||||
%check_static
|
||||
%stack (kexit_info, slot, value) -> (slot, kexit_info, slot, value)
|
||||
%address %insert_accessed_storage_keys POP // TODO: Use return value in gas calculation.
|
||||
// TODO: Assuming a cold zero -> nonzero write for now.
|
||||
|
||||
@ -360,8 +360,6 @@
|
||||
|
||||
%macro not_bit
|
||||
// stack: b
|
||||
PUSH 1
|
||||
// stack: 1, b
|
||||
SUB
|
||||
// stack: 1 - b
|
||||
ISZERO
|
||||
// stack: not b
|
||||
%endmacro
|
||||
|
||||
@ -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),
|
||||
];
|
||||
|
||||
@ -29,7 +29,7 @@ const BASIC_BINARY_OP: Option<StackBehavior> = Some(StackBehavior {
|
||||
disable_other_channels: true,
|
||||
});
|
||||
const BASIC_TERNARY_OP: Option<StackBehavior> = Some(StackBehavior {
|
||||
num_pops: 2,
|
||||
num_pops: 3,
|
||||
pushes: true,
|
||||
disable_other_channels: true,
|
||||
});
|
||||
@ -60,8 +60,16 @@ const STACK_BEHAVIORS: OpsColumnsView<Option<StackBehavior>> = OpsColumnsView {
|
||||
xor: BASIC_BINARY_OP,
|
||||
not: BASIC_UNARY_OP,
|
||||
byte: BASIC_BINARY_OP,
|
||||
shl: BASIC_BINARY_OP,
|
||||
shr: BASIC_BINARY_OP,
|
||||
shl: Some(StackBehavior {
|
||||
num_pops: 2,
|
||||
pushes: true,
|
||||
disable_other_channels: false,
|
||||
}),
|
||||
shr: Some(StackBehavior {
|
||||
num_pops: 2,
|
||||
pushes: true,
|
||||
disable_other_channels: false,
|
||||
}),
|
||||
keccak_general: None, // TODO
|
||||
prover_input: None, // TODO
|
||||
pop: None, // TODO
|
||||
|
||||
@ -26,13 +26,13 @@ pub const MAX_USER_STACK_SIZE: usize = 1024;
|
||||
// Other operations that have a minimum stack size (e.g. `MULMOD`, which has three inputs) read
|
||||
// all their inputs from memory. On underflow, the cross-table lookup fails, as -1, ..., -17 are
|
||||
// invalid memory addresses.
|
||||
const DECREMENTING_FLAGS: [usize; 1] = [COL_MAP.op.pop];
|
||||
pub(crate) const DECREMENTING_FLAGS: [usize; 1] = [COL_MAP.op.pop];
|
||||
|
||||
// Operations that increase the stack length by 1, but excluding:
|
||||
// - privileged (kernel-only) operations (superfluous; doesn't affect correctness),
|
||||
// - operations that from userspace to the kernel (required for correctness).
|
||||
// TODO: This list is incomplete.
|
||||
const INCREMENTING_FLAGS: [usize; 2] = [COL_MAP.op.pc, COL_MAP.op.dup];
|
||||
pub(crate) const INCREMENTING_FLAGS: [usize; 2] = [COL_MAP.op.pc, COL_MAP.op.dup];
|
||||
|
||||
/// Calculates `lv.stack_len_bounds_aux`. Note that this must be run after decode.
|
||||
pub fn generate<F: Field>(lv: &mut CpuColumnsView<F>) {
|
||||
|
||||
@ -17,10 +17,6 @@ pub(crate) struct KeccakSpongeColumnsView<T: Copy> {
|
||||
/// not a padding byte; 0 otherwise.
|
||||
pub is_full_input_block: T,
|
||||
|
||||
/// 1 if this row represents the final block of a sponge, in which case some or all of the bytes
|
||||
/// in the block will be padding bytes; 0 otherwise.
|
||||
pub is_final_block: T,
|
||||
|
||||
// The base address at which we will read the input block.
|
||||
pub context: T,
|
||||
pub segment: T,
|
||||
|
||||
@ -128,7 +128,7 @@ pub(crate) fn ctl_looking_logic<F: Field>(i: usize) -> Vec<Column<F>> {
|
||||
pub(crate) fn ctl_looked_filter<F: Field>() -> Column<F> {
|
||||
// The CPU table is only interested in our final-block rows, since those contain the final
|
||||
// sponge output.
|
||||
Column::single(KECCAK_SPONGE_COL_MAP.is_final_block)
|
||||
Column::sum(KECCAK_SPONGE_COL_MAP.is_final_input_len)
|
||||
}
|
||||
|
||||
/// CTL filter for reading the `i`th byte of input from memory.
|
||||
@ -143,12 +143,12 @@ pub(crate) fn ctl_looking_memory_filter<F: Field>(i: usize) -> Column<F> {
|
||||
/// CTL filter for looking at XORs in the logic table.
|
||||
pub(crate) fn ctl_looking_logic_filter<F: Field>() -> Column<F> {
|
||||
let cols = KECCAK_SPONGE_COL_MAP;
|
||||
Column::sum([cols.is_full_input_block, cols.is_final_block])
|
||||
Column::sum(once(&cols.is_full_input_block).chain(&cols.is_final_input_len))
|
||||
}
|
||||
|
||||
pub(crate) fn ctl_looking_keccak_filter<F: Field>() -> Column<F> {
|
||||
let cols = KECCAK_SPONGE_COL_MAP;
|
||||
Column::sum([cols.is_full_input_block, cols.is_final_block])
|
||||
Column::sum(once(&cols.is_full_input_block).chain(&cols.is_final_input_len))
|
||||
}
|
||||
|
||||
/// Information about a Keccak sponge operation needed for witness generation.
|
||||
@ -269,10 +269,7 @@ impl<F: RichField + Extendable<D>, const D: usize> KeccakSpongeStark<F, D> {
|
||||
) -> KeccakSpongeColumnsView<F> {
|
||||
assert_eq!(already_absorbed_bytes + final_inputs.len(), op.input.len());
|
||||
|
||||
let mut row = KeccakSpongeColumnsView {
|
||||
is_final_block: F::ONE,
|
||||
..Default::default()
|
||||
};
|
||||
let mut row = KeccakSpongeColumnsView::default();
|
||||
|
||||
for (block_byte, input_byte) in row.block_bytes.iter_mut().zip(final_inputs) {
|
||||
*block_byte = F::from_canonical_u8(*input_byte);
|
||||
@ -372,7 +369,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
let is_full_input_block = local_values.is_full_input_block;
|
||||
yield_constr.constraint(is_full_input_block * (is_full_input_block - P::ONES));
|
||||
|
||||
let is_final_block = local_values.is_final_block;
|
||||
let is_final_block: P = local_values.is_final_input_len.iter().copied().sum();
|
||||
yield_constr.constraint(is_final_block * (is_final_block - P::ONES));
|
||||
|
||||
for &is_final_len in local_values.is_final_input_len.iter() {
|
||||
@ -382,13 +379,6 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
// Ensure that full-input block and final block flags are not set to 1 at the same time.
|
||||
yield_constr.constraint(is_final_block * is_full_input_block);
|
||||
|
||||
// Sum of is_final_input_len should equal is_final_block (which will be 0 or 1).
|
||||
let is_final_input_len_sum: P = local_values.is_final_input_len.iter().copied().sum();
|
||||
yield_constr.constraint(is_final_input_len_sum - is_final_block);
|
||||
|
||||
// If this is a full-input block, is_final_input_len should contain all 0s.
|
||||
yield_constr.constraint(is_full_input_block * is_final_input_len_sum);
|
||||
|
||||
// If this is the first row, the original sponge state should be 0 and already_absorbed_bytes = 0.
|
||||
let already_absorbed_bytes = local_values.already_absorbed_bytes;
|
||||
yield_constr.constraint_first_row(already_absorbed_bytes);
|
||||
@ -447,8 +437,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
|
||||
// A dummy row is always followed by another dummy row, so the prover can't put dummy rows "in between" to avoid the above checks.
|
||||
let is_dummy = P::ONES - is_full_input_block - is_final_block;
|
||||
let next_is_final_block: P = next_values.is_final_input_len.iter().copied().sum();
|
||||
yield_constr.constraint_transition(
|
||||
is_dummy * (next_values.is_full_input_block + next_values.is_final_block),
|
||||
is_dummy * (next_values.is_full_input_block + next_is_final_block),
|
||||
);
|
||||
|
||||
// If this is a final block, is_final_input_len implies `len - already_absorbed == i`.
|
||||
@ -479,7 +470,7 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
);
|
||||
yield_constr.constraint(builder, constraint);
|
||||
|
||||
let is_final_block = local_values.is_final_block;
|
||||
let is_final_block = builder.add_many_extension(local_values.is_final_input_len);
|
||||
let constraint = builder.mul_sub_extension(is_final_block, is_final_block, is_final_block);
|
||||
yield_constr.constraint(builder, constraint);
|
||||
|
||||
@ -492,21 +483,6 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
let constraint = builder.mul_extension(is_final_block, is_full_input_block);
|
||||
yield_constr.constraint(builder, constraint);
|
||||
|
||||
// Sum of is_final_input_len should equal is_final_block (which will be 0 or 1).
|
||||
let mut is_final_input_len_sum = builder.add_extension(
|
||||
local_values.is_final_input_len[0],
|
||||
local_values.is_final_input_len[1],
|
||||
);
|
||||
for &input_len in local_values.is_final_input_len.iter().skip(2) {
|
||||
is_final_input_len_sum = builder.add_extension(is_final_input_len_sum, input_len);
|
||||
}
|
||||
let constraint = builder.sub_extension(is_final_input_len_sum, is_final_block);
|
||||
yield_constr.constraint(builder, constraint);
|
||||
|
||||
// If this is a full-input block, is_final_input_len should contain all 0s.
|
||||
let constraint = builder.mul_extension(is_full_input_block, is_final_input_len_sum);
|
||||
yield_constr.constraint(builder, constraint);
|
||||
|
||||
// If this is the first row, the original sponge state should be 0 and already_absorbed_bytes = 0.
|
||||
let already_absorbed_bytes = local_values.already_absorbed_bytes;
|
||||
yield_constr.constraint_first_row(builder, already_absorbed_bytes);
|
||||
@ -580,9 +556,9 @@ impl<F: RichField + Extendable<D>, const D: usize> Stark<F, D> for KeccakSpongeS
|
||||
let tmp = builder.sub_extension(one, is_final_block);
|
||||
builder.sub_extension(tmp, is_full_input_block)
|
||||
};
|
||||
let next_is_final_block = builder.add_many_extension(next_values.is_final_input_len);
|
||||
let constraint = {
|
||||
let tmp =
|
||||
builder.add_extension(next_values.is_final_block, next_values.is_full_input_block);
|
||||
let tmp = builder.add_extension(next_is_final_block, next_values.is_full_input_block);
|
||||
builder.mul_extension(is_dummy, tmp)
|
||||
};
|
||||
yield_constr.constraint_transition(builder, constraint);
|
||||
|
||||
@ -4,6 +4,7 @@ use plonky2::field::types::Field;
|
||||
|
||||
use crate::cpu::columns::CpuColumnsView;
|
||||
use crate::cpu::kernel::aggregator::KERNEL;
|
||||
use crate::cpu::stack_bounds::{DECREMENTING_FLAGS, INCREMENTING_FLAGS, MAX_USER_STACK_SIZE};
|
||||
use crate::generation::state::GenerationState;
|
||||
use crate::memory::segments::Segment;
|
||||
use crate::witness::errors::ProgramError;
|
||||
@ -258,6 +259,24 @@ fn try_perform_instruction<F: Field>(state: &mut GenerationState<F>) -> Result<(
|
||||
|
||||
fill_op_flag(op, &mut row);
|
||||
|
||||
let check_underflow: F = DECREMENTING_FLAGS.map(|i| row[i]).into_iter().sum();
|
||||
let check_overflow: F = INCREMENTING_FLAGS.map(|i| row[i]).into_iter().sum();
|
||||
let no_check = F::ONE - (check_underflow + check_overflow);
|
||||
|
||||
let disallowed_len = check_overflow * F::from_canonical_usize(MAX_USER_STACK_SIZE) - no_check;
|
||||
let diff = row.stack_len - disallowed_len;
|
||||
|
||||
let user_mode = F::ONE - row.is_kernel_mode;
|
||||
let rhs = user_mode + check_underflow;
|
||||
|
||||
row.stack_len_bounds_aux = match diff.try_inverse() {
|
||||
Some(diff_inv) => diff_inv * rhs, // `rhs` may be a value other than 1 or 0
|
||||
None => {
|
||||
assert_eq!(rhs, F::ZERO);
|
||||
F::ZERO
|
||||
}
|
||||
};
|
||||
|
||||
perform_op(state, op, row)
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user