mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-08 00:33:06 +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)
|
%stack (addr, key, value) -> (addr, key, value, %%after)
|
||||||
%jump(insert_accessed_storage_keys)
|
%jump(insert_accessed_storage_keys)
|
||||||
%%after:
|
%%after:
|
||||||
// stack: cold_access
|
// stack: cold_access, original_value
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
/// Inserts the storage key and value into the access list if it is not already present.
|
/// 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
|
%u256_to_addr // Truncate to 160 bits
|
||||||
DUP1 %insert_accessed_addresses
|
DUP1 %insert_accessed_addresses
|
||||||
%checkpoint // Checkpoint
|
%checkpoint // Checkpoint
|
||||||
DUP1 %insert_touched_addresses
|
DUP2 %insert_touched_addresses
|
||||||
|
|
||||||
%call_charge_gas(1, 1)
|
%call_charge_gas(1, 1)
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ global sys_staticcall:
|
|||||||
%u256_to_addr // Truncate to 160 bits
|
%u256_to_addr // Truncate to 160 bits
|
||||||
DUP1 %insert_accessed_addresses
|
DUP1 %insert_accessed_addresses
|
||||||
%checkpoint // Checkpoint
|
%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.
|
// 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)
|
%stack (cold_access, address, gas, kexit_info) -> (cold_access, address, gas, kexit_info, 0)
|
||||||
|
|||||||
@ -65,12 +65,11 @@ count_zeros_finish:
|
|||||||
PUSH @GAS_TRANSACTION
|
PUSH @GAS_TRANSACTION
|
||||||
// stack: gas_txn, gas_creation, gas_txndata, retdest
|
// 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
|
||||||
ADD
|
ADD
|
||||||
// stack: total_gas, retdest
|
// stack: total_gas, retdest
|
||||||
|
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_DATA_COST)
|
||||||
|
ADD
|
||||||
|
|
||||||
SWAP1
|
SWAP1
|
||||||
JUMP
|
JUMP
|
||||||
|
|||||||
@ -77,6 +77,11 @@ global increment_sender_nonce:
|
|||||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||||
%increment_nonce
|
%increment_nonce
|
||||||
|
|
||||||
|
// EIP-3651
|
||||||
|
global warm_coinbase:
|
||||||
|
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_BENEFICIARY)
|
||||||
|
%insert_accessed_addresses_no_return
|
||||||
|
|
||||||
global process_based_on_type:
|
global process_based_on_type:
|
||||||
%is_contract_creation
|
%is_contract_creation
|
||||||
%jumpi(process_contract_creation_txn)
|
%jumpi(process_contract_creation_txn)
|
||||||
|
|||||||
@ -105,10 +105,15 @@
|
|||||||
|
|
||||||
%macro decode_and_store_access_list
|
%macro decode_and_store_access_list
|
||||||
// stack: pos
|
// stack: pos
|
||||||
|
DUP1 %mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START)
|
||||||
%decode_rlp_list_len
|
%decode_rlp_list_len
|
||||||
%stack (pos, len) -> (len, pos)
|
%stack (pos, len) -> (len, len, pos, %%after)
|
||||||
%jumpi(todo_access_lists_not_supported_yet)
|
%jumpi(decode_and_store_access_list)
|
||||||
|
// stack: len, pos, %%after
|
||||||
|
POP SWAP1 POP
|
||||||
// stack: pos
|
// stack: pos
|
||||||
|
%mload_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_START) DUP2 SUB %mstore_global_metadata(@GLOBAL_METADATA_ACCESS_LIST_RLP_LEN)
|
||||||
|
%%after:
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
%macro decode_and_store_y_parity
|
%macro decode_and_store_y_parity
|
||||||
@ -135,5 +140,96 @@
|
|||||||
// stack: pos
|
// stack: pos
|
||||||
%endmacro
|
%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
|
// stack: rlp_pos, rlp_start, retdest
|
||||||
|
|
||||||
%mload_txn_field(@TXN_FIELD_TO)
|
%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
|
SWAP1 %encode_rlp_160
|
||||||
// stack: rlp_pos, rlp_start, retdest
|
// stack: rlp_pos, rlp_start, retdest
|
||||||
|
|
||||||
|
after_to:
|
||||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||||
SWAP1 %encode_rlp_scalar
|
SWAP1 %encode_rlp_scalar
|
||||||
// stack: rlp_pos, rlp_start, retdest
|
// stack: rlp_pos, rlp_start, retdest
|
||||||
|
|||||||
@ -31,6 +31,109 @@ global process_type_1_txn:
|
|||||||
POP
|
POP
|
||||||
// stack: retdest
|
// 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)
|
%jump(process_normalized_txn)
|
||||||
|
|||||||
@ -59,10 +59,16 @@ pub(crate) enum GlobalMetadata {
|
|||||||
/// Current checkpoint.
|
/// Current checkpoint.
|
||||||
CurrentCheckpoint = 28,
|
CurrentCheckpoint = 28,
|
||||||
TouchedAddressesLen = 29,
|
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 {
|
impl GlobalMetadata {
|
||||||
pub(crate) const COUNT: usize = 29;
|
pub(crate) const COUNT: usize = 32;
|
||||||
|
|
||||||
pub(crate) fn all() -> [Self; Self::COUNT] {
|
pub(crate) fn all() -> [Self; Self::COUNT] {
|
||||||
[
|
[
|
||||||
@ -95,6 +101,9 @@ impl GlobalMetadata {
|
|||||||
Self::JournalDataLen,
|
Self::JournalDataLen,
|
||||||
Self::CurrentCheckpoint,
|
Self::CurrentCheckpoint,
|
||||||
Self::TouchedAddressesLen,
|
Self::TouchedAddressesLen,
|
||||||
|
Self::AccessListDataCost,
|
||||||
|
Self::AccessListRlpStart,
|
||||||
|
Self::AccessListRlpLen,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,6 +139,9 @@ impl GlobalMetadata {
|
|||||||
Self::JournalDataLen => "GLOBAL_METADATA_JOURNAL_DATA_LEN",
|
Self::JournalDataLen => "GLOBAL_METADATA_JOURNAL_DATA_LEN",
|
||||||
Self::CurrentCheckpoint => "GLOBAL_METADATA_CURRENT_CHECKPOINT",
|
Self::CurrentCheckpoint => "GLOBAL_METADATA_CURRENT_CHECKPOINT",
|
||||||
Self::TouchedAddressesLen => "GLOBAL_METADATA_TOUCHED_ADDRESSES_LEN",
|
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