mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-02-18 12:53:08 +00:00
Support for type-1 transactions (#1051)
* Type 1 txn * Remove magic constants * Remove useless stack element * Read correct original value for sk * EIP-3651 * Fix encoding when TO is 0 * Minor
This commit is contained in:
parent
15dec6faf9
commit
9b0092ab1d
@ -87,7 +87,7 @@ remove_accessed_addresses_found:
|
||||
%stack (addr, key, value) -> (addr, key, value, %%after)
|
||||
%jump(insert_accessed_storage_keys)
|
||||
%%after:
|
||||
// stack: cold_access
|
||||
// stack: cold_access, original_value
|
||||
%endmacro
|
||||
|
||||
/// Inserts the storage key and value into the access list if it is not already present.
|
||||
|
||||
@ -23,7 +23,7 @@ global sys_call:
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses
|
||||
%checkpoint // Checkpoint
|
||||
DUP1 %insert_touched_addresses
|
||||
DUP2 %insert_touched_addresses
|
||||
|
||||
%call_charge_gas(1, 1)
|
||||
|
||||
@ -123,7 +123,7 @@ global sys_staticcall:
|
||||
%u256_to_addr // Truncate to 160 bits
|
||||
DUP1 %insert_accessed_addresses
|
||||
%checkpoint // Checkpoint
|
||||
DUP1 %insert_touched_addresses
|
||||
DUP2 %insert_touched_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)
|
||||
|
||||
@ -65,12 +65,11 @@ count_zeros_finish:
|
||||
PUSH @GAS_TRANSACTION
|
||||
// stack: gas_txn, gas_creation, gas_txndata, retdest
|
||||
|
||||
// TODO: Add num_access_list_addresses * GAS_ACCESSLISTADDRESS
|
||||
// TODO: Add num_access_list_slots * GAS_ACCESSLISTSTORAGE
|
||||
|
||||
ADD
|
||||
ADD
|
||||
// stack: total_gas, retdest
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||
ADD
|
||||
|
||||
SWAP1
|
||||
JUMP
|
||||
|
||||
@ -77,6 +77,11 @@ global increment_sender_nonce:
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||
%increment_nonce
|
||||
|
||||
// EIP-3651
|
||||
global warm_coinbase:
|
||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_BENEFICIARY)
|
||||
%insert_accessed_addresses_no_return
|
||||
|
||||
global process_based_on_type:
|
||||
%is_contract_creation
|
||||
%jumpi(process_contract_creation_txn)
|
||||
|
||||
@ -105,10 +105,15 @@
|
||||
|
||||
%macro decode_and_store_access_list
|
||||
// stack: pos
|
||||
DUP1 %mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START)
|
||||
%decode_rlp_list_len
|
||||
%stack (pos, len) -> (len, pos)
|
||||
%jumpi(todo_access_lists_not_supported_yet)
|
||||
%stack (pos, len) -> (len, len, pos, %%after)
|
||||
%jumpi(decode_and_store_access_list)
|
||||
// stack: len, pos, %%after
|
||||
POP SWAP1 POP
|
||||
// stack: pos
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START) DUP2 SUB %mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN)
|
||||
%%after:
|
||||
%endmacro
|
||||
|
||||
%macro decode_and_store_y_parity
|
||||
@ -135,5 +140,96 @@
|
||||
// stack: pos
|
||||
%endmacro
|
||||
|
||||
global todo_access_lists_not_supported_yet:
|
||||
PANIC
|
||||
|
||||
// The access list is of the form `[[{20 bytes}, [{32 bytes}...]]...]`.
|
||||
global decode_and_store_access_list:
|
||||
// stack: len, pos
|
||||
DUP2 ADD
|
||||
// stack: end_pos, pos
|
||||
// Store the RLP length.
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START) DUP2 SUB %mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN)
|
||||
SWAP1
|
||||
decode_and_store_access_list_loop:
|
||||
// stack: pos, end_pos
|
||||
DUP2 DUP2 EQ %jumpi(decode_and_store_access_list_finish)
|
||||
// stack: pos, end_pos
|
||||
%decode_rlp_list_len // Should be a list `[{20 bytes}, [{32 bytes}...]]`
|
||||
// stack: pos, internal_len, end_pos
|
||||
SWAP1 POP // We don't need the length of this list.
|
||||
// stack: pos, end_pos
|
||||
%decode_rlp_scalar // Address // TODO: Should panic when address is not 20 bytes?
|
||||
// stack: pos, addr, end_pos
|
||||
SWAP1
|
||||
// stack: addr, pos, end_pos
|
||||
DUP1 %insert_accessed_addresses_no_return
|
||||
// stack: addr, pos, end_pos
|
||||
%add_address_cost
|
||||
// stack: addr, pos, end_pos
|
||||
SWAP1
|
||||
// stack: pos, addr, end_pos
|
||||
%decode_rlp_list_len // Should be a list of storage keys `[{32 bytes}...]`
|
||||
// stack: pos, sk_len, addr, end_pos
|
||||
SWAP1 DUP2 ADD
|
||||
// stack: sk_end_pos, pos, addr, end_pos
|
||||
SWAP1
|
||||
// stack: pos, sk_end_pos, addr, end_pos
|
||||
sk_loop:
|
||||
DUP2 DUP2 EQ %jumpi(end_sk)
|
||||
// stack: pos, sk_end_pos, addr, end_pos
|
||||
%decode_rlp_scalar // Storage key // TODO: Should panic when key is not 32 bytes?
|
||||
%stack (pos, key, sk_end_pos, addr, end_pos) ->
|
||||
(addr, key, sk_loop_contd, pos, sk_end_pos, addr, end_pos)
|
||||
%jump(insert_accessed_storage_keys_with_original_value)
|
||||
sk_loop_contd:
|
||||
// stack: pos, sk_end_pos, addr, end_pos
|
||||
%add_storage_key_cost
|
||||
%jump(sk_loop)
|
||||
end_sk:
|
||||
%stack (pos, sk_end_pos, addr, end_pos) -> (pos, end_pos)
|
||||
%jump(decode_and_store_access_list_loop)
|
||||
decode_and_store_access_list_finish:
|
||||
%stack (pos, end_pos, retdest) -> (retdest, pos)
|
||||
JUMP
|
||||
|
||||
%macro add_address_cost
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||
%add_const(@GAS_ACCESSLISTADDRESS)
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||
%endmacro
|
||||
|
||||
%macro add_storage_key_cost
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||
%add_const(@GAS_ACCESSLISTSTORAGE)
|
||||
%mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||
%endmacro
|
||||
|
||||
insert_accessed_storage_keys_with_original_value:
|
||||
%stack (addr, key, retdest) -> (key, addr, after_read, addr, key, retdest)
|
||||
%jump(sload_with_addr)
|
||||
after_read:
|
||||
%stack (value, addr, key, retdest) -> ( addr, key, value, retdest)
|
||||
%insert_accessed_storage_keys
|
||||
%pop2
|
||||
JUMP
|
||||
|
||||
|
||||
sload_with_addr:
|
||||
%stack (slot, addr) -> (slot, addr, after_storage_read)
|
||||
%slot_to_storage_key
|
||||
// stack: storage_key, addr, after_storage_read
|
||||
PUSH 64 // storage_key has 64 nibbles
|
||||
%stack (n64, storage_key, addr, after_storage_read) -> (addr, n64, storage_key, after_storage_read)
|
||||
%mpt_read_state_trie
|
||||
// stack: account_ptr, 64, storage_key, after_storage_read
|
||||
DUP1 ISZERO %jumpi(ret_zero) // TODO: Fix this. This should never happen.
|
||||
// stack: account_ptr, 64, storage_key, after_storage_read
|
||||
%add_const(2)
|
||||
// stack: storage_root_ptr_ptr
|
||||
%mload_trie_data
|
||||
// stack: storage_root_ptr, 64, storage_key, after_storage_read
|
||||
%jump(mpt_read)
|
||||
|
||||
ret_zero:
|
||||
// stack: account_ptr, 64, storage_key, after_storage_read, retdest
|
||||
%pop4
|
||||
PUSH 0 SWAP1 JUMP
|
||||
|
||||
@ -102,9 +102,16 @@ type_0_compute_signed_data:
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_TO)
|
||||
DUP1 %jumpi(nonzero_to)
|
||||
// stack: to, rlp_pos, rlp_start, retdest
|
||||
SWAP1 %encode_rlp_scalar
|
||||
%jump(after_to)
|
||||
nonzero_to:
|
||||
// stack: to, rlp_pos, rlp_start, retdest
|
||||
SWAP1 %encode_rlp_160
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
after_to:
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
@ -31,6 +31,109 @@ global process_type_1_txn:
|
||||
POP
|
||||
// stack: retdest
|
||||
|
||||
// TODO: Check signature.
|
||||
// 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])).
|
||||
type_1_compute_signed_data:
|
||||
%alloc_rlp_block
|
||||
// stack: rlp_start, retdest
|
||||
%mload_txn_field(@TXN_FIELD_CHAIN_ID)
|
||||
// stack: chain_id, rlp_start, retdest
|
||||
DUP2
|
||||
// stack: rlp_pos, chain_id, rlp_start, retdest
|
||||
%encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_NONCE)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_TO)
|
||||
DUP1 %jumpi(nonzero_to)
|
||||
// stack: to, rlp_pos, rlp_start, retdest
|
||||
SWAP1 %encode_rlp_scalar
|
||||
%jump(after_to)
|
||||
nonzero_to:
|
||||
// stack: to, rlp_pos, rlp_start, retdest
|
||||
SWAP1 %encode_rlp_160
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
after_to:
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
SWAP1 %encode_rlp_scalar
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
|
||||
// Encode txn data.
|
||||
%mload_txn_field(@TXN_FIELD_DATA_LEN)
|
||||
PUSH 0 // ADDR.virt
|
||||
PUSH @SEGMENT_TXN_DATA
|
||||
PUSH 0 // ADDR.context
|
||||
// stack: ADDR: 3, len, rlp_pos, rlp_start, retdest
|
||||
PUSH after_serializing_txn_data
|
||||
// stack: after_serializing_txn_data, ADDR: 3, len, rlp_pos, rlp_start, retdest
|
||||
SWAP5
|
||||
// stack: rlp_pos, ADDR: 3, 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_pos, rlp_start, retdest) ->
|
||||
(
|
||||
0, @SEGMENT_RLP_RAW, rlp_pos,
|
||||
0, @SEGMENT_RLP_RAW, al_start,
|
||||
al_len,
|
||||
after_serializing_access_list,
|
||||
rlp_pos, rlp_start, retdest)
|
||||
%jump(memcpy)
|
||||
after_serializing_access_list:
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN) ADD
|
||||
// stack: rlp_pos, rlp_start, retdest
|
||||
%prepend_rlp_list_prefix
|
||||
// stack: prefix_start_pos, rlp_len, retdest
|
||||
|
||||
// Store a `1` in front of the RLP
|
||||
%decrement
|
||||
%stack (pos) -> (0, @SEGMENT_RLP_RAW, pos, 1, pos)
|
||||
MSTORE_GENERAL
|
||||
// stack: pos, rlp_len, retdest
|
||||
|
||||
// Hash the RLP + the leading `1`
|
||||
SWAP1 %increment SWAP1
|
||||
PUSH @SEGMENT_RLP_RAW
|
||||
PUSH 0 // context
|
||||
// stack: ADDR: 3, len, retdest
|
||||
KECCAK_GENERAL
|
||||
// stack: hash, retdest
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_S)
|
||||
%mload_txn_field(@TXN_FIELD_R)
|
||||
%mload_txn_field(@TXN_FIELD_Y_PARITY) %add_const(27) // ecrecover interprets v as y_parity + 27
|
||||
|
||||
PUSH store_origin
|
||||
// stack: store_origin, v, r, s, hash, retdest
|
||||
SWAP4
|
||||
// stack: hash, v, r, s, store_origin, retdest
|
||||
%jump(ecrecover)
|
||||
|
||||
store_origin:
|
||||
// stack: address, retdest
|
||||
// If ecrecover returned u256::MAX, that indicates failure.
|
||||
DUP1
|
||||
%eq_const(0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
|
||||
%jumpi(panic)
|
||||
|
||||
// stack: address, retdest
|
||||
%mstore_txn_field(@TXN_FIELD_ORIGIN)
|
||||
// stack: retdest
|
||||
%jump(process_normalized_txn)
|
||||
|
||||
@ -59,10 +59,16 @@ pub(crate) enum GlobalMetadata {
|
||||
/// Current checkpoint.
|
||||
CurrentCheckpoint = 28,
|
||||
TouchedAddressesLen = 29,
|
||||
// Gas cost for the access list in type-1 txns. See EIP-2930.
|
||||
AccessListDataCost = 30,
|
||||
// Start of the access list in the RLP for type-1 txns.
|
||||
AccessListRlpStart = 31,
|
||||
// Length of the access list in the RLP for type-1 txns.
|
||||
AccessListRlpLen = 32,
|
||||
}
|
||||
|
||||
impl GlobalMetadata {
|
||||
pub(crate) const COUNT: usize = 29;
|
||||
pub(crate) const COUNT: usize = 32;
|
||||
|
||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||
[
|
||||
@ -95,6 +101,9 @@ impl GlobalMetadata {
|
||||
Self::JournalDataLen,
|
||||
Self::CurrentCheckpoint,
|
||||
Self::TouchedAddressesLen,
|
||||
Self::AccessListDataCost,
|
||||
Self::AccessListRlpStart,
|
||||
Self::AccessListRlpLen,
|
||||
]
|
||||
}
|
||||
|
||||
@ -130,6 +139,9 @@ impl GlobalMetadata {
|
||||
Self::JournalDataLen => "GLOBAL_METADATA_JOURNAL_DATA_LEN",
|
||||
Self::CurrentCheckpoint => "GLOBAL_METADATA_CURRENT_CHECKPOINT",
|
||||
Self::TouchedAddressesLen => "GLOBAL_METADATA_TOUCHED_ADDRESSES_LEN",
|
||||
Self::AccessListDataCost => "GLOBAL_METADATA_ACCESS_LIST_DATA_COST",
|
||||
Self::AccessListRlpStart => "GLOBAL_METADATA_ACCESS_LIST_RLP_START",
|
||||
Self::AccessListRlpLen => "GLOBAL_METADATA_ACCESS_LIST_RLP_LEN",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user