Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reuse txn rlp #547

Merged
merged 3 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 32 additions & 66 deletions evm_arithmetization/src/cpu/kernel/asm/transactions/type_0.asm
Original file line number Diff line number Diff line change
Expand Up @@ -18,131 +18,97 @@ global process_type_0_txn:
%stack (rlp_addr, len) -> (rlp_addr)

// stack: rlp_addr, retdest
// Keep track of the nonce position.
DUP1
// stack: rlp_addr, nonce_addr, retdest
hratoanina marked this conversation as resolved.
Show resolved Hide resolved
%decode_and_store_nonce
%decode_and_store_gas_price_legacy
%decode_and_store_gas_limit
%decode_and_store_to
%decode_and_store_value
%decode_and_store_data
// stack: rlp_addr, retdest
// stack: rlp_addr, nonce_addr, retdest
DUP1

// Parse the "v" field.
// stack: rlp_addr, retdest
// stack: rlp_addr, after_data_addr, nonce_addr, retdest
%decode_rlp_scalar
// stack: rlp_addr, v, retdest
// stack: rlp_addr, v, after_data_addr, nonce_addr, retdest
SWAP1
// stack: v, rlp_addr, retdest
// stack: v, rlp_addr, after_data_addr, nonce_addr, retdest
DUP1
%gt_const(28)
// stack: v > 28, v, rlp_addr, retdest
// stack: v > 28, v, rlp_addr, after_data_addr, nonce_addr, retdest
%jumpi(process_v_new_style)

// We have an old style v, so y_parity = v - 27.
// No chain ID is present, so we can leave TXN_FIELD_CHAIN_ID_PRESENT and
// TXN_FIELD_CHAIN_ID with their default values of zero.
// stack: v, rlp_addr, retdest
// stack: v, rlp_addr, after_data_addr, nonce_addr, retdest
%sub_const(27)
%stack (y_parity, rlp_addr) -> (y_parity, rlp_addr)
%mstore_txn_field(@TXN_FIELD_Y_PARITY)

// stack: rlp_addr, retdest
// stack: rlp_addr, after_data_addr, nonce_addr, retdest
%jump(decode_r_and_s)

process_v_new_style:
// stack: v, rlp_addr, retdest
// stack: v, rlp_addr, after_data_addr, nonce_addr, retdest
// We have a new style v, so chain_id_present = 1,
// chain_id = (v - 35) / 2, and y_parity = (v - 35) % 2.
%stack (v, rlp_addr) -> (1, v, rlp_addr)
%mstore_txn_field(@TXN_FIELD_CHAIN_ID_PRESENT)

// stack: v, rlp_addr, retdest
// stack: v, rlp_addr, after_data_addr, nonce_addr, retdest
%sub_const(35)
DUP1
// stack: v - 35, v - 35, rlp_addr, retdest
// stack: v - 35, v - 35, rlp_addr, after_data_addr, nonce_addr, retdest
%div2
// stack: chain_id, v - 35, rlp_addr, retdest
// stack: chain_id, v - 35, rlp_addr, after_data_addr, nonce_addr, retdest
%mstore_txn_field(@TXN_FIELD_CHAIN_ID)

// stack: v - 35, rlp_addr, retdest
// stack: v - 35, rlp_addr, after_data_addr, nonce_addr, retdest
%mod_const(2)
// stack: y_parity, rlp_addr, retdest
// stack: y_parity, rlp_addr, after_data_addr, nonce_addr, retdest
%mstore_txn_field(@TXN_FIELD_Y_PARITY)

decode_r_and_s:
// stack: rlp_addr, retdest
// stack: rlp_addr, after_data_addr, nonce_addr, retdest
%decode_and_store_r
%decode_and_store_s
// stack: rlp_addr, retdest
// stack: rlp_addr, after_data_addr, nonce_addr, retdest
POP
// stack: retdest
// stack: after_data_addr, nonce_addr, retdest

type_0_compute_signed_data:
// If a chain_id is present in v, the signed data is
// keccak256(rlp([nonce, gas_price, gas_limit, to, value, data, chain_id, 0, 0]))
// otherwise, it is
// keccak256(rlp([nonce, gas_price, gas_limit, to, value, data]))
// We know that [nonce, gas_price, gas_limit, to, value, data] is already encoded
// at `nonce_addr`.

%alloc_rlp_block
// stack: rlp_addr_start, retdest
%mload_txn_field(@TXN_FIELD_NONCE)
// stack: nonce, rlp_addr_start, retdest
DUP2
// stack: rlp_addr, nonce, rlp_addr_start, retdest
%encode_rlp_scalar
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_TO)
%mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to)
// stack: to, rlp_addr, rlp_addr_start, retdest
SWAP1 %encode_rlp_160
%jump(after_to)
zero_to:
// stack: to, rlp_addr, rlp_addr_start, retdest
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

after_to:
%mload_txn_field(@TXN_FIELD_VALUE)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

// Encode txn data.
%mload_txn_field(@TXN_FIELD_DATA_LEN)
PUSH @SEGMENT_TXN_DATA
// stack: ADDR, len, rlp_addr, rlp_addr_start, retdest
PUSH after_serializing_txn_data
// stack: after_serializing_txn_data, ADDR, len, rlp_addr, rlp_addr_start, retdest
SWAP3
// stack: rlp_addr, ADDR, len, after_serializing_txn_data, rlp_addr_start, retdest
%jump(encode_rlp_string)

after_serializing_txn_data:
// stack: rlp_addr, rlp_addr_start, retdest
// If there is a `chain_id`, we append it at the end. This will overwrite `v`, `r` and `s`
// but the transaction has already been inserted in the MPT so it's not an issue.
// stack: after_data_addr, nonce_addr, retdest
%mload_txn_field(@TXN_FIELD_CHAIN_ID_PRESENT)
ISZERO %jumpi(finish_rlp_list)
// stack: rlp_addr, rlp_addr_start, retdest

// stack: after_data_addr, nonce_addr, retdest
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest
// stack: rlp_signed_end_addr, nonce_addr, retdest

PUSH 0
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest
// stack: rlp_signed_end_addr, rlp_addr_start, retdest

PUSH 0
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest
// stack: rlp_signed_end_addr, rlp_addr_start, retdest

finish_rlp_list:
// stack: rlp_signed_end_addr, rlp_addr_start, retdest
// We will overwrite the original transaction RLP prefix. This is fine since we don't need the
// original encoding anymore.
%prepend_rlp_list_prefix
// stack: ADDR, rlp_len, retdest
KECCAK_GENERAL
Expand Down
77 changes: 13 additions & 64 deletions evm_arithmetization/src/cpu/kernel/asm/transactions/type_1.asm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ global process_type_1_txn:
%stack (rlp_addr, len) -> (rlp_addr)

%store_chain_id_present_true
// stack: rlp_addr, retdest
// Keep track of the chain id position.
DUP1
// stack: rlp_addr, chain_id_addr, retdest
%decode_and_store_chain_id
%decode_and_store_nonce
%decode_and_store_gas_price_legacy
Expand All @@ -24,80 +28,25 @@ global process_type_1_txn:
%decode_and_store_value
%decode_and_store_data
%decode_and_store_access_list
// stack: rlp_addr, chain_id_addr, retdest
DUP1
// stack: rlp_addr, after_access_list_addr, chain_id_addr, retdest
%decode_and_store_y_parity
%decode_and_store_r
%decode_and_store_s

// stack: rlp_addr, retdest
// stack: rlp_addr, after_access_list_addr, chain_id_addr, retdest
POP
// stack: retdest
// stack: after_access_list_addr, chain_id_addr, retdest

// From EIP-2930:
// The signatureYParity, signatureR, signatureS elements of this transaction represent a secp256k1 signature
// over keccak256(0x01 || rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList])).
// We know that [chainId, nonce, gasPrice, gasLimit, to, value, data, accessList] is already encoded
// at `chain_id_addr`; we just need to overwrite the existing RLP prefix. This is fine since we don't
// need the original encoding anymore.
type_1_compute_signed_data:
%alloc_rlp_block
// stack: rlp_addr_start, retdest
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
// stack: chain_id, rlp_addr_start, retdest
DUP2
// stack: rlp_addr, chain_id, rlp_addr_start, retdest
%encode_rlp_scalar
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_NONCE)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

%mload_txn_field(@TXN_FIELD_TO)
%mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to)
// stack: to, rlp_addr, rlp_addr_start, retdest
SWAP1 %encode_rlp_160
%jump(after_to)
zero_to:
// stack: to, rlp_addr, rlp_addr_start, retdest
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

after_to:
%mload_txn_field(@TXN_FIELD_VALUE)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_addr_start, retdest

// Encode txn data.
%mload_txn_field(@TXN_FIELD_DATA_LEN)
PUSH @SEGMENT_TXN_DATA // ctx == virt == 0
// stack: ADDR, len, rlp_addr, rlp_addr_start, retdest
PUSH after_serializing_txn_data
// stack: after_serializing_txn_data, ADDR, len, rlp_addr, rlp_addr_start, retdest
SWAP3
// stack: rlp_addr, ADDR, len, after_serializing_txn_data, rlp_addr_start, retdest
%jump(encode_rlp_string)

after_serializing_txn_data:
// Instead of manually encoding the access list, we just copy the raw RLP from the transaction.
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START)
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN)
%stack (al_len, al_start, rlp_addr, rlp_addr_start, retdest) ->
(
rlp_addr,
al_start,
al_len,
after_serializing_access_list,
rlp_addr, rlp_addr_start, retdest)
%jump(memcpy_bytes)
after_serializing_access_list:
// stack: rlp_addr, rlp_addr_start, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN) ADD
// stack: rlp_addr, rlp_addr_start, retdest
// stack: after_access_list_addr, chain_id_addr, retdest
%prepend_rlp_list_prefix
// stack: prefix_start_rlp_addr, rlp_len, retdest

Expand Down
83 changes: 14 additions & 69 deletions evm_arithmetization/src/cpu/kernel/asm/transactions/type_2.asm
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ global process_type_2_txn:

// stack: rlp_addr, retdest
%store_chain_id_present_true
// stack: rlp_addr, retdest
// Keep track of the chain id position.
DUP1
// stack: rlp_addr, chain_id_addr, retdest
%decode_and_store_chain_id
%decode_and_store_nonce
%decode_and_store_max_priority_fee
Expand All @@ -27,84 +31,25 @@ global process_type_2_txn:
%decode_and_store_value
%decode_and_store_data
%decode_and_store_access_list
// stack: rlp_addr, chain_id_addr, retdest
DUP1
// stack: rlp_addr, after_access_list_addr, chain_id_addr, retdest
%decode_and_store_y_parity
%decode_and_store_r
%decode_and_store_s

// stack: rlp_addr, retdest
// stack: rlp_addr, after_access_list_addr, chain_id_addr, retdest
POP
// stack: retdest
// stack: after_access_list_addr, chain_id_addr, retdest

// From EIP-1559:
// The signature_y_parity, signature_r, signature_s elements of this transaction represent a secp256k1 signature over
// keccak256(0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list]))
// keccak256(0x02 || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list])).
// We know that [chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, destination, amount, data, access_list] is already encoded
// at `chain_id_addr`; we just need to overwrite the existing RLP prefix. This is fine since we don't
// need the original encoding anymore.
type_2_compute_signed_data:
%alloc_rlp_block
// stack: rlp_addr_start, retdest
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
// stack: chain_id, rlp_start, retdest
DUP2
// stack: rlp_addr, chain_id, rlp_start, retdest
%encode_rlp_scalar
// stack: rlp_addr, rlp_start, retdest

%mload_txn_field(@TXN_FIELD_NONCE)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

%mload_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

%mload_txn_field(@TXN_FIELD_TO)
%mload_global_metadata(@GLOBAL_METADATA_CONTRACT_CREATION) %jumpi(zero_to)
// stack: to, rlp_addr, rlp_start, retdest
SWAP1 %encode_rlp_160
%jump(after_to)
zero_to:
// stack: to, rlp_addr, rlp_start, retdest
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

after_to:
%mload_txn_field(@TXN_FIELD_VALUE)
%encode_rlp_scalar_swapped_inputs
// stack: rlp_addr, rlp_start, retdest

// Encode txn data.
%mload_txn_field(@TXN_FIELD_DATA_LEN)
PUSH @SEGMENT_TXN_DATA // ctx == virt == 0
// stack: ADDR, len, rlp_addr, rlp_start, retdest
PUSH after_serializing_txn_data
// stack: after_serializing_txn_data, ADDR, len, rlp_addr, rlp_start, retdest
SWAP3
// stack: rlp_addr, ADDR, len, after_serializing_txn_data, rlp_start, retdest
%jump(encode_rlp_string)

after_serializing_txn_data:
// Instead of manually encoding the access list, we just copy the raw RLP from the transaction.
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START)
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN)
%stack (al_len, al_start, rlp_addr, rlp_start, retdest) ->
(
rlp_addr,
al_start,
al_len,
after_serializing_access_list,
rlp_addr, rlp_start, retdest)
%jump(memcpy_bytes)
after_serializing_access_list:
// stack: rlp_addr, rlp_start, retdest
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN) ADD
// stack: rlp_addr, rlp_start, retdest
// stack: after_access_list_addr, chain_id_addr, retdest
%prepend_rlp_list_prefix
// stack: prefix_start_pos, rlp_len, retdest

Expand Down
Loading
Loading