From 9ba2b895b9f2eef90315173a15c2855d5b7e2d41 Mon Sep 17 00:00:00 2001 From: Linda Guiga Date: Mon, 4 Sep 2023 11:15:04 +0100 Subject: [PATCH] Implement receipts of types 1 and 2 --- .../cpu/kernel/asm/core/create_receipt.asm | 17 +++ .../asm/mpt/hash/hash_trie_specific.asm | 127 +++++++++++------- .../asm/mpt/load/load_trie_specific.asm | 13 +- 3 files changed, 106 insertions(+), 51 deletions(-) diff --git a/evm/src/cpu/kernel/asm/core/create_receipt.asm b/evm/src/cpu/kernel/asm/core/create_receipt.asm index 4dfcdc5e..32f64494 100644 --- a/evm/src/cpu/kernel/asm/core/create_receipt.asm +++ b/evm/src/cpu/kernel/asm/core/create_receipt.asm @@ -53,6 +53,18 @@ process_receipt_after_bloom: // stack: payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, retdest // Now we can write the receipt in MPT_TRIE_DATA. %get_trie_data_size + // stack: receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, retdest + // Write transaction type if necessary. RLP_RAW contains, at index 0, the current transaction type. + PUSH 0 + %mload_kernel(@SEGMENT_RLP_RAW) + DUP1 + // stack: first_txn_byte, first_txn_byte, receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, retdest + %eq_const(1) %jumpi(receipt_nonzero_type) + DUP1 %eq_const(2) %jumpi(receipt_nonzero_type) + // If we are here, we are dealing with a legacy transaction, and we do not need to write the type. + POP + +process_receipt_after_type: // stack: receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, retdest // Write payload_len. SWAP1 @@ -206,6 +218,11 @@ process_receipt_after_write: %stack (new_cum_gas, txn_nb, retdest) -> (retdest, new_cum_gas, txn_nb) JUMP +receipt_nonzero_type: + // stack: txn_type, receipt_ptr, payload_len, status, new_cum_gas, txn_nb, new_cum_gas, txn_nb, retdest + %append_to_trie_data + %jump(process_receipt_after_type) + failed_receipt: // stack: status, new_cum_gas, txn_nb // It is the receipt of a failed transaction, so set num_logs to 0. This will also lead to Bloom filter = 0. 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 596e9d49..5b40225c 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 @@ -102,138 +102,167 @@ global encode_txn: // We assume a receipt in memory is stored as: // [payload_len, status, cum_gas_used, bloom, logs_payload_len, num_logs, [logs]]. // A log is [payload_len, address, num_topics, [topics], data_len, [data]]. -// TODO: support type >0 receipts. global encode_receipt: // stack: rlp_pos, value_ptr, retdest // There is a double encoding! What we compute is: - // RLP(RLP(receipt)). + // either RLP(RLP(receipt)) for Legacy transactions or RLP(txn_type||RLP(receipt)) for transactions of type 1 or 2. // First encode the wrapper prefix. DUP2 %mload_trie_data + // stack: first_byte, rlp_pos, value_ptr, retdest + // The first byte is either the transaction type or the first byte of the RLP encoding. + DUP1 PUSH 3 GT %jumpi(encode_nonzero_receipt_type) + // If we are here, then the first byte is the payload length. %rlp_list_len // stack: rlp_receipt_len, rlp_pos, value_ptr, retdest SWAP1 %encode_rlp_multi_byte_string_prefix // stack: rlp_pos, value_ptr, retdest + +encode_receipt_after_type: + // stack: rlp_pos, payload_len_ptr, retdest // Then encode the receipt prefix. + // `payload_ptr` is either `value_ptr` or `value_ptr+1`, depending on the transaction type. DUP2 %mload_trie_data - // stack: payload_len, rlp_pos, value_ptr, retdest + // stack: payload_len, rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_list_prefix - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest // Encode status. DUP2 %increment %mload_trie_data - // stack: status, rlp_pos, value_ptr, retdest + // stack: status, rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_scalar - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest // Encode cum_gas_used. DUP2 %add_const(2) %mload_trie_data - // stack: cum_gas_used, rlp_pos, value_ptr, retdest + // stack: cum_gas_used, rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_scalar - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest // Encode bloom. PUSH 256 // Bloom length. DUP3 %add_const(3) PUSH @SEGMENT_TRIE_DATA PUSH 0 // MPT src address. DUP5 - // stack: rlp_pos, SRC, 256, rlp_pos, value_ptr, retdest + // stack: rlp_pos, SRC, 256, rlp_pos, payload_len_ptr, retdest %encode_rlp_string - // stack: rlp_pos, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, old_rlp_pos, payload_len_ptr, retdest SWAP1 POP - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest // Encode logs prefix. DUP2 %add_const(259) %mload_trie_data - // stack: logs_payload_len, rlp_pos, value_ptr, retdest + // stack: logs_payload_len, rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_list_prefix - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest DUP2 %add_const(261) - // stack: logs_ptr, rlp_pos, value_ptr, retdest + // stack: logs_ptr, rlp_pos, payload_len_ptr, retdest DUP3 %add_const(260) %mload_trie_data - // stack: num_logs, logs_ptr, rlp_pos, value_ptr, retdest + // stack: num_logs, logs_ptr, rlp_pos, payload_len_ptr, retdest PUSH 0 encode_receipt_logs_loop: - // stack: i, num_logs, current_log_ptr, rlp_pos, value_ptr, retdest + // stack: i, num_logs, current_log_ptr, rlp_pos, payload_len_ptr, retdest DUP2 DUP2 EQ - // stack: i == num_logs, i, num_logs, current_log_ptr, rlp_pos, value_ptr, retdest + // stack: i == num_logs, i, num_logs, current_log_ptr, rlp_pos, payload_len_ptr, retdest %jumpi(encode_receipt_end) - // stack: i, num_logs, current_log_ptr, rlp_pos, value_ptr, retdest + // stack: i, num_logs, current_log_ptr, rlp_pos, payload_len_ptr, retdest DUP3 DUP5 - // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest // Encode log prefix. DUP2 %mload_trie_data - // stack: payload_len, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: payload_len, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_list_prefix - // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest // Encode address. DUP2 %increment %mload_trie_data - // stack: address, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: address, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP1 %encode_rlp_160 - // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest DUP2 %add_const(2) %mload_trie_data - // stack: num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest // Encode topics prefix. DUP1 %mul_const(33) - // stack: topics_payload_len, num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: topics_payload_len, num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest DUP3 %encode_rlp_list_prefix - // stack: new_rlp_pos, num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: new_rlp_pos, num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP2 POP - // stack: num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: num_topics, rlp_pos, current_log_ptr, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP2 %add_const(3) - // stack: topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest PUSH 0 encode_receipt_topics_loop: - // stack: j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest DUP4 DUP2 EQ - // stack: j == num_topics, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: j == num_topics, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest %jumpi(encode_receipt_topics_end) - // stack: j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest DUP2 DUP2 ADD %mload_trie_data - // stack: current_topic, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: current_topic, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest DUP4 - // stack: rlp_pos, current_topic, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, current_topic, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest %encode_rlp_256 - // stack: new_rlp_pos, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: new_rlp_pos, j, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP3 POP - // stack: j, topics_ptr, new_rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: j, topics_ptr, new_rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest %increment %jump(encode_receipt_topics_loop) encode_receipt_topics_end: - // stack: num_topics, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: num_topics, topics_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest ADD - // stack: data_len_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, value_ptr, retdest + // stack: data_len_ptr, rlp_pos, num_topics, i, num_logs, current_log_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP5 POP - // stack: rlp_pos, num_topics, i, num_logs, data_len_ptr, old_rlp_pos, value_ptr, retdest + // stack: rlp_pos, num_topics, i, num_logs, data_len_ptr, old_rlp_pos, payload_len_ptr, retdest SWAP5 POP - // stack: num_topics, i, num_logs, data_len_ptr, rlp_pos, value_ptr, retdest + // stack: num_topics, i, num_logs, data_len_ptr, rlp_pos, payload_len_ptr, retdest POP - // stack: i, num_logs, data_len_ptr, rlp_pos, value_ptr, retdest + // stack: i, num_logs, data_len_ptr, rlp_pos, payload_len_ptr, retdest // Encode data prefix. DUP3 %mload_trie_data - // stack: data_len, i, num_logs, data_len_ptr, rlp_pos, value_ptr, retdest + // stack: data_len, i, num_logs, data_len_ptr, rlp_pos, payload_len_ptr, retdest DUP4 %increment DUP2 ADD - // stack: next_log_ptr, data_len, i, num_logs, data_len_ptr, rlp_pos, value_ptr, retdest + // stack: next_log_ptr, data_len, i, num_logs, data_len_ptr, rlp_pos, payload_len_ptr, retdest SWAP4 %increment - // stack: data_ptr, data_len, i, num_logs, next_log_ptr, rlp_pos, value_ptr, retdest + // stack: data_ptr, data_len, i, num_logs, next_log_ptr, rlp_pos, payload_len_ptr, retdest PUSH @SEGMENT_TRIE_DATA PUSH 0 - // stack: SRC, data_len, i, num_logs, next_log_ptr, rlp_pos, value_ptr, retdest + // stack: SRC, data_len, i, num_logs, next_log_ptr, rlp_pos, payload_len_ptr, retdest DUP8 - // stack: rlp_pos, SRC, data_len, i, num_logs, next_log_ptr, rlp_pos, value_ptr, retdest + // stack: rlp_pos, SRC, data_len, i, num_logs, next_log_ptr, rlp_pos, payload_len_ptr, retdest %encode_rlp_string - // stack: new_rlp_pos, i, num_logs, next_log_ptr, rlp_pos, value_ptr, retdest + // stack: new_rlp_pos, i, num_logs, next_log_ptr, rlp_pos, payload_len_ptr, retdest SWAP4 POP - // stack: i, num_logs, next_log_ptr, new_rlp_pos, value_ptr, retdest + // stack: i, num_logs, next_log_ptr, new_rlp_pos, payload_len_ptr, retdest %increment %jump(encode_receipt_logs_loop) encode_receipt_end: - // stack: num_logs, num_logs, current_log_ptr, rlp_pos, value_ptr, retdest + // stack: num_logs, num_logs, current_log_ptr, rlp_pos, payload_len_ptr, retdest %pop3 - // stack: rlp_pos, value_ptr, retdest + // stack: rlp_pos, payload_len_ptr, retdest SWAP1 POP // stack: rlp_pos, retdest SWAP1 JUMP +encode_nonzero_receipt_type: + // stack: txn_type, rlp_pos, value_ptr, retdest + DUP3 %increment %mload_trie_data + // stack: payload_len, txn_type, rlp_pos, value_ptr, retdest + // The transaction type is encoded in 1 byte + %increment %rlp_list_len + // stack: rlp_receipt_len, txn_type, rlp_pos, value_ptr, retdest + DUP3 %encode_rlp_multi_byte_string_prefix + // stack: rlp_pos, txn_type, old_rlp_pos, value_ptr, retdest + DUP2 DUP2 + %mstore_rlp + %increment + // stack: rlp_pos, txn_type, old_rlp_pos, value_ptr, retdest + SWAP1 POP + // stack: rlp_pos, old_rlp_pos, value_ptr, retdest + SWAP1 POP + // stack: rlp_pos, value_ptr, retdest + // We replace `value_ptr` with `paylaod_len_ptr` so we can encode the rest of the data more easily + SWAP1 %increment SWAP1 + // stack: rlp_pos, payload_len_ptr, retdest + %jump(encode_receipt_after_type) + global encode_storage_value: // stack: rlp_pos, value_ptr, retdest SWAP1 %mload_trie_data SWAP1 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 e7b79039..213469cc 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 @@ -33,9 +33,13 @@ global mpt_load_txn_trie_value: global mpt_load_receipt_trie_value: // stack: retdest + // Load first byte. It is either `payload_len` or the transaction type. + PROVER_INPUT(mpt) DUP1 %append_to_trie_data + // If the first byte is less than 3, then it is the transaction type, equal to either 1 or 2. + // In that case, we still need to load the payload length. + PUSH 3 GT %jumpi(mpt_load_payload_len) - // Load payload_len. - PROVER_INPUT(mpt) %append_to_trie_data +mpt_load_after_type: // Load status. PROVER_INPUT(mpt) %append_to_trie_data // Load cum_gas_used. @@ -117,6 +121,11 @@ mpt_load_receipt_trie_value_end: %pop2 JUMP +mpt_load_payload_len: + // stack: retdest + PROVER_INPUT(mpt) %append_to_trie_data + %jump(mpt_load_after_type) + global mpt_load_storage_trie_value: // stack: retdest PROVER_INPUT(mpt)