diff --git a/evm/src/cpu/kernel/asm/core/create.asm b/evm/src/cpu/kernel/asm/core/create.asm index dfdb6b76..e2552ff5 100644 --- a/evm/src/cpu/kernel/asm/core/create.asm +++ b/evm/src/cpu/kernel/asm/core/create.asm @@ -1,9 +1,17 @@ +// The CREATE syscall. +// +// Pre stack: value, CODE_ADDR, code_len, retdest +// Post stack: address +global sys_create: + %address + %jump(create) + // Create a new contract account with the traditional address scheme, i.e. // address = KEC(RLP(sender, nonce))[12:] // This can be used both for the CREATE instruction and for contract-creation // transactions. // -// Pre stack: CODE_ADDR, code_len, retdest +// Pre stack: sender, endowment, CODE_ADDR, code_len, retdest // Post stack: address // Note: CODE_ADDR refers to a (context, segment, offset) tuple. global create: @@ -21,18 +29,11 @@ global create: // Pre stack: sender, endowment, salt, CODE_ADDR, code_len, retdest // Post stack: address // Note: CODE_ADDR refers to a (context, segment, offset) tuple. -global create2: +global sys_create2: // stack: sender, endowment, salt, CODE_ADDR, code_len, retdest // Call get_create2_address and have it return to create_inner. - %stack (sender, endowment, salt) -> (salt, sender, endowment) - // stack: salt, sender, endowment, CODE_ADDR, code_len, retdest - DUP7 DUP7 DUP7 DUP7 // CODE_ADDR and code_len - // stack: CODE_ADDR, code_len, salt, sender, endowment, CODE_ADDR, code_len, retdest - PUSH create_inner - // stack: create_inner, CODE_ADDR, code_len, salt, sender, endowment, CODE_ADDR, code_len, retdest - SWAP5 // create_inner <-> salt - // stack: salt, CODE_ADDR, code_len, create_inner, sender, endowment, CODE_ADDR, code_len, retdest - DUP7 // sender + %stack (sender, endowment, salt, CODE_ADDR: 3, code_len) + -> (sender, salt, CODE_ADDR, code_len, create_inner, sender, endowment, CODE_ADDR, code_len) // stack: sender, salt, CODE_ADDR, code_len, create_inner, sender, endowment, CODE_ADDR, code_len, retdest %jump(get_create2_address) diff --git a/evm/src/cpu/kernel/asm/core/process_txn.asm b/evm/src/cpu/kernel/asm/core/process_txn.asm index 8671fb1c..6adc0831 100644 --- a/evm/src/cpu/kernel/asm/core/process_txn.asm +++ b/evm/src/cpu/kernel/asm/core/process_txn.asm @@ -40,6 +40,7 @@ global buy_gas: // stack: sender_addr, gas_cost, retdest %deduct_eth // stack: deduct_eth_status, retdest +global txn_failure_insufficient_balance: %jumpi(panic) // stack: retdest @@ -54,17 +55,26 @@ global process_based_on_type: global process_contract_creation_txn: // stack: retdest - // Push the code address & length onto the stack, then call `create`. + 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, retdest + // stack: code_len, process_contract_creation_txn_after_create, retdest PUSH 0 - // stack: code_offset, code_len, retdest + // stack: code_offset, code_len, process_contract_creation_txn_after_create, retdest PUSH @SEGMENT_TXN_DATA - // stack: code_segment, code_offset, code_len, retdest + // stack: code_segment, code_offset, code_len, process_contract_creation_txn_after_create, retdest PUSH 0 // context - // stack: CODE_ADDR, code_len, retdest + // stack: CODE_ADDR, code_len, process_contract_creation_txn_after_create, retdest + %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) +global process_contract_creation_txn_after_create: + // stack: new_address, retdest + POP + JUMP + global process_message_txn: // stack: retdest %mload_txn_field(@TXN_FIELD_VALUE) @@ -162,5 +172,5 @@ global process_message_txn_code_loaded: global process_message_txn_after_call: // stack: success, retdest // TODO: Return leftover gas? Or handled by termination instructions? - POP // Pop success for now. Will go into the reciept when we support that. + POP // Pop success for now. Will go into the receipt when we support that. JUMP diff --git a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm index dfaa8bac..d7f5b912 100644 --- a/evm/src/cpu/kernel/asm/core/syscall_stubs.asm +++ b/evm/src/cpu/kernel/asm/core/syscall_stubs.asm @@ -2,49 +2,86 @@ // Each label should be removed from this file once it is implemented. global sys_sdiv: + PANIC global sys_smod: + PANIC global sys_signextend: + PANIC global sys_slt: + PANIC global sys_sgt: + PANIC global sys_sar: + PANIC global sys_address: + PANIC global sys_balance: + PANIC global sys_origin: + PANIC global sys_caller: + PANIC global sys_callvalue: + PANIC global sys_calldataload: + PANIC global sys_calldatasize: + PANIC global sys_calldatacopy: + PANIC global sys_codesize: + PANIC global sys_codecopy: + PANIC global sys_gasprice: + PANIC global sys_extcodesize: + PANIC global sys_extcodecopy: + PANIC global sys_returndatasize: + PANIC global sys_returndatacopy: + PANIC global sys_extcodehash: + PANIC global sys_blockhash: + PANIC global sys_coinbase: + PANIC global sys_timestamp: + PANIC global sys_number: + PANIC global sys_prevrandao: + PANIC global sys_gaslimit: + PANIC global sys_chainid: + PANIC global sys_selfbalance: + PANIC global sys_basefee: -global sys_sload: -global sys_sstore: + PANIC global sys_msize: + PANIC global sys_gas: + PANIC global sys_log0: + PANIC global sys_log1: + PANIC global sys_log2: + PANIC global sys_log3: + PANIC global sys_log4: -global sys_create: + PANIC global sys_call: + PANIC global sys_callcode: + PANIC global sys_delegatecall: -global sys_create2: + PANIC global sys_staticcall: PANIC diff --git a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm index 39253b9f..15f33cee 100644 --- a/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm +++ b/evm/src/cpu/kernel/asm/mpt/hash/hash_trie_specific.asm @@ -88,11 +88,15 @@ encode_account_after_hash_storage_trie: SWAP1 JUMP -encode_txn: +global encode_txn: PANIC // TODO -encode_receipt: +global encode_receipt: PANIC // TODO -encode_storage_value: - PANIC // TODO: RLP encode as variable-len scalar? +global encode_storage_value: + // stack: rlp_pos, value_ptr, retdest + %encode_rlp_scalar + // stack: rlp_pos', retdest + SWAP1 + JUMP diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm index d8801cda..e93b333f 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_read.asm @@ -1,30 +1,32 @@ // Read a word from the current account's storage trie. // -// Pre stack: slot, retdest +// Pre stack: kexit_info, slot // Post stack: value -global storage_read: - // stack: slot, retdest +global sys_sload: + // stack: kexit_info, slot + SWAP1 + // stack: slot, kexit_info %stack (slot) -> (slot, after_storage_read) %slot_to_storage_key - // stack: storage_key, after_storage_read, retdest + // stack: storage_key, after_storage_read, kexit_info PUSH 64 // storage_key has 64 nibbles %current_storage_trie - // stack: storage_root_ptr, 64, storage_key, after_storage_read, retdest + // stack: storage_root_ptr, 64, storage_key, after_storage_read, kexit_info %jump(mpt_read) after_storage_read: - // stack: value_ptr, retdest + // stack: value_ptr, kexit_info DUP1 %jumpi(storage_key_exists) // Storage key not found. Return default value_ptr = 0, // which derefs to 0 since @SEGMENT_TRIE_DATA[0] = 0. - %stack (value_ptr, retdest) -> (retdest, 0) - JUMP + %stack (value_ptr, kexit_info) -> (kexit_info, 0) + EXIT_KERNEL storage_key_exists: - // stack: value_ptr, retdest + // stack: value_ptr, kexit_info %mload_trie_data - // stack: value, retdest + // stack: value, kexit_info SWAP1 - JUMP + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm index 7695b0c2..a56117a7 100644 --- a/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm +++ b/evm/src/cpu/kernel/asm/mpt/storage/storage_write.asm @@ -1,44 +1,50 @@ // Write a word to the current account's storage trie. // -// Pre stack: slot, value, retdest +// Pre stack: kexit_info, slot, value // Post stack: (empty) -global storage_write: +global sys_sstore: + %stack (kexit_info, slot, value) -> (slot, value, kexit_info) // TODO: If value = 0, delete the key instead of inserting 0. - // stack: slot, value, retdest + // stack: slot, value, kexit_info // First we write the value to MPT data, and get a pointer to it. %get_trie_data_size - // stack: value_ptr, slot, value, retdest + // stack: value_ptr, slot, value, kexit_info SWAP2 - // stack: value, slot, value_ptr, retdest + // stack: value, slot, value_ptr, kexit_info %append_to_trie_data - // stack: slot, value_ptr, retdest + // stack: slot, value_ptr, kexit_info // Next, call mpt_insert on the current account's storage root. %stack (slot, value_ptr) -> (slot, value_ptr, after_storage_insert) %slot_to_storage_key - // stack: storage_key, value_ptr, after_storage_write, retdest + // stack: storage_key, value_ptr, after_storage_insert, kexit_info PUSH 64 // storage_key has 64 nibbles %current_storage_trie - // stack: storage_root_ptr, 64, storage_key, value_ptr, after_storage_insert, retdest + // stack: storage_root_ptr, 64, storage_key, value_ptr, after_storage_insert, kexit_info %jump(mpt_insert) after_storage_insert: - // stack: new_storage_root_ptr, retdest + // stack: new_storage_root_ptr, kexit_info %current_account_data - // stack: old_account_ptr, new_storage_root_ptr, retdest + // stack: old_account_ptr, new_storage_root_ptr, kexit_info %make_account_copy - // stack: new_account_ptr, new_storage_root_ptr, retdest + // stack: new_account_ptr, new_storage_root_ptr, kexit_info // Update the copied account with our new storage root pointer. %stack (new_account_ptr, new_storage_root_ptr) -> (new_account_ptr, new_storage_root_ptr, new_account_ptr) %add_const(2) - // stack: new_account_storage_root_ptr_ptr, new_storage_root_ptr, new_account_ptr, retdest + // stack: new_account_storage_root_ptr_ptr, new_storage_root_ptr, new_account_ptr, kexit_info %mstore_trie_data - // stack: new_account_ptr, retdest + // stack: new_account_ptr, kexit_info // Save this updated account to the state trie. + %stack (new_account_ptr) -> (new_account_ptr, after_state_insert) %address %addr_to_state_key - // stack: state_key, new_account_ptr, retdest + // stack: state_key, new_account_ptr, after_state_insert, kexit_info %jump(mpt_insert_state_trie) + +after_state_insert: + // stack: kexit_info + EXIT_KERNEL diff --git a/evm/src/cpu/kernel/asm/rlp/encode_rlp_string.asm b/evm/src/cpu/kernel/asm/rlp/encode_rlp_string.asm index a19507d8..e094b8c3 100644 --- a/evm/src/cpu/kernel/asm/rlp/encode_rlp_string.asm +++ b/evm/src/cpu/kernel/asm/rlp/encode_rlp_string.asm @@ -44,6 +44,8 @@ global encode_rlp_string_small_single_byte: %mstore_rlp // stack: pos, retdest %increment + SWAP1 + // stack: retdest, pos' JUMP global encode_rlp_string_large: diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 04a6f027..588454fd 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -73,7 +73,10 @@ impl GenerationState { // Return length of code. // stack: codehash, ... let codehash = stack_peek(self, 0).expect("Empty stack"); - self.inputs.contract_code[&H256::from_uint(&codehash)] + self.inputs + .contract_code + .get(&H256::from_uint(&codehash)) + .unwrap_or_else(|| panic!("No code found with hash {codehash}")) .len() .into() } @@ -82,7 +85,11 @@ impl GenerationState { // stack: i, code_length, codehash, ... let i = stack_peek(self, 0).expect("Unexpected stack").as_usize(); let codehash = stack_peek(self, 2).expect("Unexpected stack"); - self.inputs.contract_code[&H256::from_uint(&codehash)][i].into() + self.inputs + .contract_code + .get(&H256::from_uint(&codehash)) + .unwrap_or_else(|| panic!("No code found with hash {codehash}"))[i] + .into() } _ => panic!("Invalid prover input function."), }