diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 3b18e309..10d0a686 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -55,15 +55,9 @@ global extcodesize: // stack: extcodesize(address), retdest SWAP1 JUMP -%macro codecopy - // stack: dest_offset, offset, size - %address - %extcodecopy -%endmacro - %macro extcodecopy // stack: address, dest_offset, offset, size - %stack (dest_offset, offset, size) -> (dest_offset, offset, size, %%after) + %stack (address, dest_offset, offset, size) -> (address, dest_offset, offset, size, %%after) %jump(extcodecopy) %%after: %endmacro @@ -145,6 +139,7 @@ global load_code: JUMP load_code_ctd: // stack: codehash, ctx, segment, retdest + DUP1 ISZERO %jumpi(load_code_non_existent_account) PROVER_INPUT(account_code::length) // stack: code_size, codehash, ctx, segment, retdest PUSH 0 @@ -177,3 +172,7 @@ load_code_check: // stack: shouldbecodehash, codehash, retdest, code_size %assert_eq JUMP + +load_code_non_existent_account: + %stack (codehash, ctx, segment, retdest) -> (retdest, 0) + JUMP diff --git a/evm/src/cpu/kernel/asm/balance.asm b/evm/src/cpu/kernel/asm/balance.asm index 6ce88cc4..1c6429d2 100644 --- a/evm/src/cpu/kernel/asm/balance.asm +++ b/evm/src/cpu/kernel/asm/balance.asm @@ -1,3 +1,20 @@ +global sys_balance: + // stack: kexit_info, address + // TODO: assuming a cold account access for now. + %charge_gas_const(@GAS_COLDACCOUNTACCESS) + SWAP1 + // stack: address, kexit_info + %balance + // stack: balance, kexit_info + SWAP1 + EXIT_KERNEL + +%macro balance + %stack (address) -> (address, %%after) + %jump(balance) +%%after: +%endmacro + global balance: // stack: address, retdest %mpt_read_state_trie @@ -13,11 +30,17 @@ retzero: %stack (account_ptr, retdest) -> (retdest, 0) JUMP +global sys_selfbalance: + // stack: kexit_info + %charge_gas_const(@GAS_LOW) + %selfbalance + // stack: balance, kexit_info + SWAP1 + EXIT_KERNEL -global selfbalance: - // stack: retdest +%macro selfbalance + PUSH %%after %address - PUSH balance - // stack: balance, address, retdest - JUMP - + %jump(balance) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index cc37f832..d7e6eed2 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -1,3 +1,7 @@ +// TODO: This file needs to be cleaned up. +// `create` is no longer being used for contract-creation txns, +// so it can be inlined. Also need to set metadata on new ctx. + // The CREATE syscall. // // Pre stack: kexit_info, value, code_offset, code_len @@ -24,8 +28,8 @@ sys_create_finish: // Note: CODE_ADDR refers to a (context, segment, offset) tuple. global create: // stack: sender, endowment, CODE_ADDR, code_len, retdest - // TODO: Charge gas. - DUP1 %get_nonce + DUP1 %nonce + // stack: nonce, sender, endowment, CODE_ADDR, code_len, retdest // Call get_create_address and have it return to create_inner. %stack (nonce, sender) @@ -67,12 +71,14 @@ sys_create2_finish: // Pre stack: address, sender, endowment, CODE_ADDR, code_len, retdest // Post stack: address // Note: CODE_ADDR refers to a (context, segment, offset) tuple. -create_inner: +global create_inner: // stack: address, sender, endowment, CODE_ADDR, code_len, retdest %stack (address, sender, endowment) -> (sender, address, endowment, sender, address) - // TODO: Need to handle insufficient balance failure. + %transfer_eth + // stack: transfer_eth_status, sender, address, CODE_ADDR, code_len, retdest + %jumpi(fault_exception) // stack: sender, address, CODE_ADDR, code_len, retdest %increment_nonce diff --git a/evm/src/cpu/kernel/asm/core/create_addresses.asm b/evm/src/cpu/kernel/asm/core/create_addresses.asm index 67fd65a6..7dd4e889 100644 --- a/evm/src/cpu/kernel/asm/core/create_addresses.asm +++ b/evm/src/cpu/kernel/asm/core/create_addresses.asm @@ -5,14 +5,33 @@ // Post stack: address global get_create_address: // stack: sender, nonce, retdest - // TODO: Replace with actual implementation. - %pop2 - PUSH 123 + %alloc_rlp_block + // stack: rlp_start, sender, nonce, retdest + %stack (rlp_start, sender, nonce) -> (rlp_start, sender, nonce, rlp_start) + // stack: rlp_start, sender, nonce, rlp_start, retdest + %encode_rlp_160 // TODO: or encode_rlp_scalar? + // stack: rlp_pos, nonce, rlp_start, retdest + %encode_rlp_scalar + // stack: rlp_pos, rlp_start, retdest + %prepend_rlp_list_prefix + // stack: rlp_prefix_start, rlp_len, retdest + PUSH @SEGMENT_RLP_RAW + PUSH 0 // context + // stack: RLP_ADDR: 3, rlp_len, retdest + KECCAK_GENERAL + %mod_const(0x10000000000000000000000000000000000000000) // 2^160 // stack: address, retdest %observe_new_address SWAP1 JUMP +// Convenience macro to call get_create_address and return where we left off. +%macro get_create_address + %stack (sender, nonce) -> (sender, nonce, %%after) + %jump(get_create_address) +%%after: +%endmacro + // Computes the address for a contract based on the CREATE2 rule, i.e. // address = KEC(0xff || sender || salt || code_hash)[12:] // diff --git a/evm/src/cpu/kernel/asm/core/nonce.asm b/evm/src/cpu/kernel/asm/core/nonce.asm index 042d81f3..973a032d 100644 --- a/evm/src/cpu/kernel/asm/core/nonce.asm +++ b/evm/src/cpu/kernel/asm/core/nonce.asm @@ -1,17 +1,21 @@ -// Increment the nonce of the given account. +// Get the nonce of the given account. // Pre stack: address, retdest // Post stack: (empty) - -global get_nonce: +global nonce: // stack: address, retdest - // TODO: Replace with actual implementation. - POP - JUMP + %mpt_read_state_trie + // stack: account_ptr, retdest + // The nonce is the first account field, so we deref the account pointer itself. + // Note: We don't need to handle account_ptr=0, as trie_data[0] = 0, + // so the deref will give 0 (the default nonce) as desired. + %mload_trie_data + // stack: nonce, retdest + SWAP1 JUMP -// Convenience macro to call get_nonce and return where we left off. -%macro get_nonce +// Convenience macro to call nonce and return where we left off. +%macro nonce %stack (address) -> (address, %%after) - %jump(get_nonce) + %jump(nonce) %%after: %endmacro @@ -20,7 +24,7 @@ global increment_nonce: // stack: address, retdest %mpt_read_state_trie // stack: account_ptr, retdest - DUP1 ISZERO %jumpi(panic) + DUP1 ISZERO %jumpi(increment_nonce_no_such_account) // stack: nonce_ptr, retdest DUP1 %mload_trie_data // stack: nonce, nonce_ptr, retdest @@ -30,6 +34,8 @@ global increment_nonce: %mstore_trie_data // stack: retdest JUMP +global increment_nonce_no_such_account: + PANIC // Convenience macro to call increment_nonce and return where we left off. %macro increment_nonce diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index 9629d647..acce98f9 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -50,23 +50,76 @@ global process_based_on_type: global process_contract_creation_txn: // stack: retdest - PUSH process_contract_creation_txn_after_create - // stack: process_contract_creation_txn_after_create, retdest - %mload_txn_field(@TXN_FIELD_DATA_LEN) - // stack: code_len, process_contract_creation_txn_after_create, retdest - PUSH 0 - // stack: code_offset, code_len, process_contract_creation_txn_after_create, retdest - PUSH @SEGMENT_TXN_DATA - // stack: code_segment, code_offset, code_len, process_contract_creation_txn_after_create, retdest - PUSH 0 // context - // stack: CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest + + %mload_txn_field(@TXN_FIELD_ORIGIN) + // stack: origin, retdest + DUP1 %nonce + // stack: origin_nonce, origin, retdest + SWAP1 + // stack: origin, origin_nonce, retdest + %get_create_address + // stack: address, retdest + + // Deduct value from caller. %mload_txn_field(@TXN_FIELD_VALUE) %mload_txn_field(@TXN_FIELD_ORIGIN) - // stack: sender, endowment, CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest - %jump(create) + %deduct_eth + // stack: deduct_eth_status, address, retdest + %jumpi(panic) + // stack: address, retdest -global process_contract_creation_txn_after_create: - // stack: new_address, retdest + // Write the new account's data to MPT data, and get a pointer to it. + %get_trie_data_size + // stack: account_ptr, address, retdest + PUSH 1 %append_to_trie_data // nonce = 1 + // stack: account_ptr, address, retdest + DUP2 %balance %mload_txn_field(@TXN_FIELD_VALUE) ADD %append_to_trie_data // balance = old_balance + txn_value + // stack: account_ptr, address, retdest + PUSH 0 %append_to_trie_data // storage_root = nil + // stack: account_ptr, address, retdest + PUSH @EMPTY_STRING_HASH %append_to_trie_data // code_hash = keccak('') + // stack: account_ptr, address, retdest + DUP2 + // stack: address, account_ptr, address, retdest + %mpt_insert_state_trie + // stack: address, retdest + + %create_context + // stack: new_ctx, address, retdest + + // Copy the code from txdata to the new context's code segment. + PUSH process_contract_creation_txn_after_code_loaded + %mload_txn_field(@TXN_FIELD_DATA_LEN) + PUSH 0 // SRC.offset + PUSH @SEGMENT_TXN_DATA // SRC.segment + PUSH 0 // SRC.context + PUSH 0 // DST.offset + PUSH @SEGMENT_CODE // DST.segment + DUP7 // DST.context = new_ctx + %jump(memcpy) + +process_contract_creation_txn_after_code_loaded: + // stack: new_ctx, address, retdest + + // Each line in the block below does not change the stack. + DUP2 %set_new_ctx_addr + %mload_txn_field(@TXN_FIELD_ORIGIN) %set_new_ctx_caller + %mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value + %set_new_ctx_parent_ctx + %set_new_ctx_parent_pc(process_contract_creation_txn_after_constructor) + %non_intrinisic_gas %set_new_ctx_gas_limit + // stack: new_ctx, address, retdest + + %enter_new_ctx + // (Old context) stack: new_ctx, address, retdest + +global process_contract_creation_txn_after_constructor: + // stack: success, leftover_gas, new_ctx, address, retdest + POP // TODO: Success will go into the receipt when we support that. + // stack: leftover_gas, new_ctx, address, retdest + %pay_coinbase_and_refund_sender + // stack: new_ctx, address, retdest + POP POP JUMP @@ -105,9 +158,8 @@ global process_message_txn_insufficient_balance: global process_message_txn_return: // stack: retdest - %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) - %mload_txn_field(@TXN_FIELD_GAS_LIMIT) - SUB + // Since no code was executed, the leftover gas is the non-intrinsic gas. + %non_intrinisic_gas // stack: leftover_gas, retdest %pay_coinbase_and_refund_sender // stack: retdest @@ -124,18 +176,13 @@ global process_message_txn_code_loaded: %mload_txn_field(@TXN_FIELD_VALUE) %set_new_ctx_value %set_new_ctx_parent_ctx %set_new_ctx_parent_pc(process_message_txn_after_call) - // stack: new_ctx, retdest - - // The gas provided to the callee is gas_limit - intrinsic_gas. - %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) - %mload_txn_field(@TXN_FIELD_GAS_LIMIT) - SUB - %set_new_ctx_gas_limit + %non_intrinisic_gas %set_new_ctx_gas_limit // stack: new_ctx, retdest // TODO: Copy TXN_DATA to CALLDATA %enter_new_ctx + // (Old context) stack: new_ctx, retdest global process_message_txn_after_call: // stack: success, leftover_gas, new_ctx, retdest @@ -206,3 +253,11 @@ global process_message_txn_after_call: %mstore_txn_field(@TXN_FIELD_COMPUTED_PRIORITY_FEE_PER_GAS) // stack: (empty) %endmacro + +%macro non_intrinisic_gas + // stack: (empty) + %mload_txn_field(@TXN_FIELD_INTRINSIC_GAS) + %mload_txn_field(@TXN_FIELD_GAS_LIMIT) + SUB + // stack: gas_limit - intrinsic_gas +%endmacro diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index 26281eea..f94bcad4 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -13,34 +13,11 @@ global sys_sgt: PANIC global sys_sar: PANIC -global sys_balance: - PANIC -global sys_origin: - PANIC -global sys_calldatasize: - PANIC -global sys_calldatacopy: - PANIC -global sys_codecopy: - PANIC -global sys_returndatasize: - PANIC -global sys_returndatacopy: - PANIC global sys_blockhash: PANIC -global sys_coinbase: - PANIC -global sys_timestamp: - PANIC -global sys_number: - PANIC global sys_prevrandao: // TODO: What semantics will this have for Edge? PANIC -global sys_gaslimit: - // TODO: Return the block's gas limit. - PANIC global sys_chainid: // TODO: Return the block's chain ID instead of the txn's, even though they should match. // stack: kexit_info @@ -50,10 +27,6 @@ global sys_chainid: // stack: chain_id, kexit_info SWAP1 EXIT_KERNEL -global sys_selfbalance: - PANIC -global sys_basefee: - PANIC global sys_log0: PANIC global sys_log1: diff --git a/evm/src/cpu/kernel/asm/core/terminate.asm b/evm/src/cpu/kernel/asm/core/terminate.asm index 4a3fbf02..26fb113c 100644 --- a/evm/src/cpu/kernel/asm/core/terminate.asm +++ b/evm/src/cpu/kernel/asm/core/terminate.asm @@ -97,6 +97,15 @@ global terminate_common: %shr_const(192) // stack: gas_used %mload_context_metadata(@CTX_METADATA_GAS_LIMIT) + // stack: gas_limit, gas_used + SWAP1 + // stack: gas_used, gas_limit + DUP2 DUP2 LT + // stack: gas_used < gas_limit, gas_used, gas_limit + SWAP2 + // stack: gas_limit, gas_used, gas_used < gas_limit SUB - // stack: leftover_gas + // stack: gas_limit - gas_used, gas_used < gas_limit + MUL + // stack: leftover_gas = (gas_limit - gas_used) * (gas_used < gas_limit) %endmacro diff --git a/evm/src/cpu/kernel/asm/memory/metadata.asm b/evm/src/cpu/kernel/asm/memory/metadata.asm index 89b39707..d891c0d1 100644 --- a/evm/src/cpu/kernel/asm/memory/metadata.asm +++ b/evm/src/cpu/kernel/asm/memory/metadata.asm @@ -104,6 +104,97 @@ global sys_msize: SWAP1 EXIT_KERNEL +%macro calldatasize + %mload_context_metadata(@CTX_METADATA_CALLDATA_SIZE) +%endmacro + +global sys_calldatasize: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %calldatasize + // stack: calldatasize, kexit_info + SWAP1 + EXIT_KERNEL + +%macro returndatasize + %mload_context_metadata(@CTX_METADATA_RETURNDATA_SIZE) +%endmacro + +global sys_returndatasize: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %returndatasize + // stack: returndatasize, kexit_info + SWAP1 + EXIT_KERNEL + +%macro coinbase + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_BENEFICIARY) +%endmacro + +global sys_coinbase: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %coinbase + // stack: coinbase, kexit_info + SWAP1 + EXIT_KERNEL + +%macro timestamp + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_TIMESTAMP) +%endmacro + +global sys_timestamp: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %timestamp + // stack: timestamp, kexit_info + SWAP1 + EXIT_KERNEL + +%macro blocknumber + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_NUMBER) +%endmacro + +global sys_number: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %blocknumber + // stack: blocknumber, kexit_info + SWAP1 + EXIT_KERNEL + +%macro blockgaslimit + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_GAS_LIMIT) +%endmacro + +global sys_gaslimit: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %blockgaslimit + // stack: blockgaslimit, kexit_info + SWAP1 + EXIT_KERNEL + +%macro basefee + %mload_global_metadata(@GLOBAL_METADATA_BLOCK_BASE_FEE) +%endmacro + +global sys_basefee: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %basefee + // stack: basefee, kexit_info + SWAP1 + EXIT_KERNEL + %macro update_mem_words // stack: num_words, kexit_info %mem_words diff --git a/evm/src/cpu/kernel/asm/memory/syscalls.asm b/evm/src/cpu/kernel/asm/memory/syscalls.asm index 3045be6d..11f8054b 100644 --- a/evm/src/cpu/kernel/asm/memory/syscalls.asm +++ b/evm/src/cpu/kernel/asm/memory/syscalls.asm @@ -118,3 +118,32 @@ sys_calldataload_after_mload_packing: SWAP1 EXIT_KERNEL PANIC + +// Macro for {CALLDATA,CODE,RETURNDATA}COPY (W_copy in Yellow Paper). +%macro wcopy(segment) + // stack: kexit_info, dest_offset, offset, size + DUP4 %num_bytes_to_num_words %mul_const(@GAS_COPY) %add_const(@GAS_VERYLOW) %charge_gas + + %stack (kexit_info, dest_offset, offset, size) -> (dest_offset, size, dest_offset, offset, size, kexit_info) + ADD // TODO: check for overflow, see discussion here https://github.com/mir-protocol/plonky2/pull/930/files/a4ea0965d79561c345e2f77836c07949c7e0bc69#r1143630253 + // stack: expanded_num_bytes, dest_offset, offset, size, kexit_info + DUP1 %ensure_reasonable_offset + %update_mem_bytes + + GET_CONTEXT + %stack (context, dest_offset, offset, size, kexit_info) -> + (context, @SEGMENT_MAIN_MEMORY, dest_offset, context, $segment, offset, size, %%after, kexit_info) + %jump(memcpy) +%%after: + // stack: kexit_info + EXIT_KERNEL +%endmacro + +global sys_calldatacopy: + %wcopy(@SEGMENT_CALLDATA) + +global sys_codecopy: + %wcopy(@SEGMENT_CODE) + +global sys_returndatacopy: + %wcopy(@SEGMENT_RETURNDATA) diff --git a/evm/src/cpu/kernel/asm/memory/txn_fields.asm b/evm/src/cpu/kernel/asm/memory/txn_fields.asm index d15b7264..e4e6b875 100644 --- a/evm/src/cpu/kernel/asm/memory/txn_fields.asm +++ b/evm/src/cpu/kernel/asm/memory/txn_fields.asm @@ -15,3 +15,16 @@ %mstore_kernel(@SEGMENT_NORMALIZED_TXN) // stack: (empty) %endmacro + +%macro origin + %mload_txn_field(@TXN_FIELD_ORIGIN) +%endmacro + +global sys_origin: + // stack: kexit_info + %charge_gas_const(@GAS_BASE) + // stack: kexit_info + %origin + // stack: origin, kexit_info + SWAP1 + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm index 225f3cc0..60df845e 100644 --- a/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/insert/insert_trie_specific.asm @@ -15,3 +15,9 @@ mpt_insert_state_trie_save: // stack: updated_node_ptr, retdest %mstore_global_metadata(@GLOBAL_METADATA_STATE_TRIE_ROOT) JUMP + +%macro mpt_insert_state_trie + %stack (key, value_ptr) -> (key, value_ptr, %%after) + %jump(mpt_insert_state_trie) +%%after: +%endmacro diff --git a/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm index b93b36e4..80c6dbbe 100644 --- a/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/load/load_trie_specific.asm @@ -37,4 +37,7 @@ global mpt_load_receipt_trie_value: global mpt_load_storage_trie_value: // stack: retdest - PANIC // TODO + PROVER_INPUT(mpt) + %append_to_trie_data + // stack: retdest + JUMP diff --git a/evm/src/cpu/kernel/asm/transactions/type_0.asm b/evm/src/cpu/kernel/asm/transactions/type_0.asm index d00b10d4..45c57361 100644 --- a/evm/src/cpu/kernel/asm/transactions/type_0.asm +++ b/evm/src/cpu/kernel/asm/transactions/type_0.asm @@ -102,7 +102,7 @@ type_0_compute_signed_data: // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_TO) - SWAP1 %encode_rlp_160 + SWAP1 %encode_rlp_scalar // stack: rlp_pos, rlp_start, retdest %mload_txn_field(@TXN_FIELD_VALUE) diff --git a/evm/src/cpu/kernel/tests/core/create_addresses.rs b/evm/src/cpu/kernel/tests/core/create_addresses.rs index 047ddc00..03d780d8 100644 --- a/evm/src/cpu/kernel/tests/core/create_addresses.rs +++ b/evm/src/cpu/kernel/tests/core/create_addresses.rs @@ -1,4 +1,6 @@ use anyhow::Result; +use ethereum_types::U256; +use hex_literal::hex; use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::interpreter::Interpreter; @@ -7,11 +9,11 @@ use crate::cpu::kernel::interpreter::Interpreter; fn test_get_create_address() -> Result<()> { let get_create_address = KERNEL.global_labels["get_create_address"]; - // TODO: Replace with real data once we have a real implementation. + // This is copied from OpenEthereum's `test_contract_address`. let retaddr = 0xdeadbeefu32.into(); - let nonce = 5.into(); - let sender = 0.into(); - let expected_addr = 123.into(); + let nonce = 88.into(); + let sender = U256::from_big_endian(&hex!("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6")); + let expected_addr = U256::from_big_endian(&hex!("3f09c73a5ed19289fb9bdc72f1742566df146f56")); let initial_stack = vec![retaddr, nonce, sender]; let mut interpreter = Interpreter::new_with_kernel(get_create_address, initial_stack); diff --git a/evm/src/generation/state.rs b/evm/src/generation/state.rs index 82be7324..49c11611 100644 --- a/evm/src/generation/state.rs +++ b/evm/src/generation/state.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use ethereum_types::{Address, H160, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H160, H256, U256}; use keccak_hash::keccak; use plonky2::field::types::Field; @@ -79,10 +79,10 @@ impl GenerationState { pub fn jump_to(&mut self, dst: usize) { self.registers.program_counter = dst; if dst == KERNEL.global_labels["observe_new_address"] { - let address = stack_peek(self, 0).expect("Empty stack"); - let mut address_bytes = [0; 20]; - address.to_big_endian(&mut address_bytes); - self.observe_address(H160(address_bytes)); + let tip_u256 = stack_peek(self, 0).expect("Empty stack"); + let tip_h256 = H256::from_uint(&tip_u256); + let tip_h160 = H160::from(tip_h256); + self.observe_address(tip_h160); } } diff --git a/evm/src/witness/errors.rs b/evm/src/witness/errors.rs index 53263675..e28e7d0f 100644 --- a/evm/src/witness/errors.rs +++ b/evm/src/witness/errors.rs @@ -1,3 +1,5 @@ +use ethereum_types::U256; + #[allow(dead_code)] #[derive(Debug)] pub enum ProgramError { @@ -8,4 +10,13 @@ pub enum ProgramError { InvalidJumpiDestination, StackOverflow, KernelPanic, + MemoryError(MemoryError), +} + +#[allow(clippy::enum_variant_names)] +#[derive(Debug)] +pub enum MemoryError { + ContextTooLarge { context: U256 }, + SegmentTooLarge { segment: U256 }, + VirtTooLarge { virt: U256 }, } diff --git a/evm/src/witness/memory.rs b/evm/src/witness/memory.rs index a2885796..127aac33 100644 --- a/evm/src/witness/memory.rs +++ b/evm/src/witness/memory.rs @@ -12,6 +12,9 @@ use MemoryChannel::{Code, GeneralPurpose}; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::memory::segments::Segment; +use crate::witness::errors::MemoryError::{ContextTooLarge, SegmentTooLarge, VirtTooLarge}; +use crate::witness::errors::ProgramError; +use crate::witness::errors::ProgramError::MemoryError; impl MemoryChannel { pub fn index(&self) -> usize { @@ -41,19 +44,25 @@ impl MemoryAddress { } } - pub(crate) fn new_u256s(context: U256, segment: U256, virt: U256) -> Self { - assert!(context.bits() <= 32, "context too large: {}", context); - assert!( - segment < Segment::COUNT.into(), - "segment too large: {}", - segment - ); - assert!(virt.bits() <= 32, "virt too large: {}", virt); - Self { + pub(crate) fn new_u256s( + context: U256, + segment: U256, + virt: U256, + ) -> Result { + if context.bits() > 32 { + return Err(MemoryError(ContextTooLarge { context })); + } + if segment >= Segment::COUNT.into() { + return Err(MemoryError(SegmentTooLarge { segment })); + } + if virt.bits() > 32 { + return Err(MemoryError(VirtTooLarge { virt })); + } + Ok(Self { context: context.as_usize(), segment: segment.as_usize(), virt: virt.as_usize(), - } + }) } pub(crate) fn increment(&mut self) { diff --git a/evm/src/witness/operation.rs b/evm/src/witness/operation.rs index 6d42eb48..43576ff4 100644 --- a/evm/src/witness/operation.rs +++ b/evm/src/witness/operation.rs @@ -111,7 +111,7 @@ pub(crate) fn generate_keccak_general( stack_pop_with_log_and_fill::<4, _>(state, &mut row)?; let len = len.as_usize(); - let base_address = MemoryAddress::new_u256s(context, segment, base_virt); + let base_address = MemoryAddress::new_u256s(context, segment, base_virt)?; let input = (0..len) .map(|i| { let address = MemoryAddress { @@ -608,7 +608,7 @@ pub(crate) fn generate_mload_general( let (val, log_read) = mem_read_gp_with_log_and_fill( 3, - MemoryAddress::new_u256s(context, segment, virt), + MemoryAddress::new_u256s(context, segment, virt)?, state, &mut row, ); diff --git a/evm/src/witness/transition.rs b/evm/src/witness/transition.rs index d48561db..be6aba94 100644 --- a/evm/src/witness/transition.rs +++ b/evm/src/witness/transition.rs @@ -108,6 +108,7 @@ fn decode(registers: RegistersState, opcode: u8) -> Result Ok(Operation::Jumpi), (0x58, _) => Ok(Operation::Pc), (0x59, _) => Ok(Operation::Syscall(opcode)), + (0x5a, _) => Ok(Operation::Syscall(opcode)), (0x5b, _) => Ok(Operation::Jumpdest), (0x60..=0x7f, _) => Ok(Operation::Push(opcode & 0x1f)), (0x80..=0x8f, _) => Ok(Operation::Dup(opcode & 0xf)),