mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-02 22:03:07 +00:00
Support for type-2 transactions (#1052)
* Type-2 txns * Minor * Minor * Fix add11_yml block metadata * Fix simple_transfer test * Minor
This commit is contained in:
parent
9b0092ab1d
commit
6e3036017e
@ -18,22 +18,27 @@ global process_normalized_txn:
|
||||
// Assert gas_limit >= intrinsic_gas.
|
||||
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
%assert_ge
|
||||
%assert_ge(invalid_txn)
|
||||
|
||||
// Assert block gas limit >= txn gas limit.
|
||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_GAS_LIMIT)
|
||||
%assert_ge(invalid_txn)
|
||||
|
||||
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||
// stack: sender, retdest
|
||||
|
||||
// Check that txn nonce matches account nonce.
|
||||
DUP1 %nonce
|
||||
DUP1 %eq_const(@MAX_NONCE) %assert_zero // EIP-2681
|
||||
DUP1 %eq_const(@MAX_NONCE) %assert_zero(invalid_txn) // EIP-2681
|
||||
// stack: sender_nonce, sender, retdest
|
||||
%mload_txn_field(@TXN_FIELD_NONCE)
|
||||
// stack: tx_nonce, sender_nonce, sender, retdest
|
||||
%assert_eq
|
||||
%assert_eq(invalid_txn)
|
||||
// stack: sender, retdest
|
||||
|
||||
// Assert sender has no code.
|
||||
DUP1 %ext_code_empty %assert_nonzero
|
||||
DUP1 %ext_code_empty %assert_nonzero(invalid_txn)
|
||||
// stack: sender, retdest
|
||||
|
||||
// Assert sender balance >= gas_limit * gas_price + value.
|
||||
@ -44,7 +49,7 @@ global process_normalized_txn:
|
||||
MUL
|
||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||
ADD
|
||||
%assert_le
|
||||
%assert_le(invalid_txn)
|
||||
// stack: retdest
|
||||
|
||||
// Assert chain ID matches block metadata
|
||||
@ -58,7 +63,7 @@ global process_normalized_txn:
|
||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_CHAIN_ID)
|
||||
MUL
|
||||
// stack: filtered_block_chain_id, filtered_tx_chain_id, retdest
|
||||
%assert_eq
|
||||
%assert_eq(invalid_txn)
|
||||
// stack: retdest
|
||||
|
||||
global buy_gas:
|
||||
@ -348,8 +353,9 @@ process_message_txn_fail:
|
||||
%mload_txn_field(@TXN_FIELD_MAX_PRIORITY_FEE_PER_GAS)
|
||||
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||
// stack: max_fee, max_priority_fee, base_fee
|
||||
DUP3 DUP2 %assert_ge // Assert max_fee >= base_fee
|
||||
DUP3 DUP2 %assert_ge(invalid_txn) // Assert max_fee >= base_fee
|
||||
// stack: max_fee, max_priority_fee, base_fee
|
||||
DUP2 DUP2 %assert_ge(invalid_txn) // Assert max_fee >= max_priority_fee
|
||||
%stack (max_fee, max_priority_fee, base_fee) -> (max_fee, base_fee, max_priority_fee, base_fee)
|
||||
SUB
|
||||
// stack: max_fee - base_fee, max_priority_fee, base_fee
|
||||
@ -399,3 +405,7 @@ contract_creation_fault_4:
|
||||
%delete_all_touched_addresses
|
||||
%delete_all_selfdestructed_addresses
|
||||
JUMP
|
||||
|
||||
|
||||
invalid_txn:
|
||||
%jump(txn_loop)
|
||||
|
||||
@ -34,6 +34,113 @@ global process_type_2_txn:
|
||||
POP
|
||||
// stack: retdest
|
||||
|
||||
// TODO: Check signature.
|
||||
// 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]))
|
||||
type_2_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_PRIORITY_FEE_PER_GAS)
|
||||
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 `2` in front of the RLP
|
||||
%decrement
|
||||
%stack (pos) -> (0, @SEGMENT_RLP_RAW, pos, 2, pos)
|
||||
MSTORE_GENERAL
|
||||
// stack: pos, rlp_len, retdest
|
||||
|
||||
// Hash the RLP + the leading `2`
|
||||
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)
|
||||
|
||||
@ -8,17 +8,31 @@ global panic:
|
||||
%jumpi(panic)
|
||||
%endmacro
|
||||
|
||||
%macro assert_zero(ret)
|
||||
%jumpi($ret)
|
||||
%endmacro
|
||||
|
||||
// Consumes the top element and asserts that it is nonzero.
|
||||
%macro assert_nonzero
|
||||
ISZERO
|
||||
%jumpi(panic)
|
||||
%endmacro
|
||||
|
||||
%macro assert_nonzero(ret)
|
||||
ISZERO
|
||||
%jumpi($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_eq
|
||||
EQ
|
||||
%assert_nonzero
|
||||
%endmacro
|
||||
|
||||
%macro assert_eq(ret)
|
||||
EQ
|
||||
%assert_nonzero($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_lt
|
||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||
// fact that (x < y) == !(x >= y).
|
||||
@ -26,6 +40,11 @@ global panic:
|
||||
%assert_zero
|
||||
%endmacro
|
||||
|
||||
%macro assert_lt(ret)
|
||||
GE
|
||||
%assert_zero($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_le
|
||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||
// fact that (x <= y) == !(x > y).
|
||||
@ -33,6 +52,11 @@ global panic:
|
||||
%assert_zero
|
||||
%endmacro
|
||||
|
||||
%macro assert_le(ret)
|
||||
GT
|
||||
%assert_zero($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_gt
|
||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||
// fact that (x > y) == !(x <= y).
|
||||
@ -40,6 +64,11 @@ global panic:
|
||||
%assert_zero
|
||||
%endmacro
|
||||
|
||||
%macro assert_gt(ret)
|
||||
LE
|
||||
%assert_zero($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_ge
|
||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||
// fact that (x >= y) == !(x < y).
|
||||
@ -47,6 +76,11 @@ global panic:
|
||||
%assert_zero
|
||||
%endmacro
|
||||
|
||||
%macro assert_ge(ret)
|
||||
LT
|
||||
%assert_zero($ret)
|
||||
%endmacro
|
||||
|
||||
%macro assert_eq_const(c)
|
||||
%eq_const($c)
|
||||
%assert_nonzero
|
||||
|
||||
@ -81,8 +81,12 @@ fn add11_yml() -> anyhow::Result<()> {
|
||||
|
||||
let block_metadata = BlockMetadata {
|
||||
block_beneficiary: Address::from(beneficiary),
|
||||
block_timestamp: 0x03e8.into(),
|
||||
block_number: 1.into(),
|
||||
block_difficulty: 0x020000.into(),
|
||||
block_gaslimit: 0xff112233445566u64.into(),
|
||||
block_chain_id: 1.into(),
|
||||
block_base_fee: 0xa.into(),
|
||||
..BlockMetadata::default()
|
||||
};
|
||||
|
||||
let mut contract_code = HashMap::new();
|
||||
|
||||
@ -37,15 +37,12 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
||||
let sender = hex!("2c7536e3605d9c16a7a3d7b1898e529396a65c23");
|
||||
let to = hex!("a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0");
|
||||
|
||||
let beneficiary_state_key = keccak(beneficiary);
|
||||
let sender_state_key = keccak(sender);
|
||||
let to_state_key = keccak(to);
|
||||
|
||||
let beneficiary_nibbles = Nibbles::from_bytes_be(beneficiary_state_key.as_bytes()).unwrap();
|
||||
let sender_nibbles = Nibbles::from_bytes_be(sender_state_key.as_bytes()).unwrap();
|
||||
let to_nibbles = Nibbles::from_bytes_be(to_state_key.as_bytes()).unwrap();
|
||||
|
||||
let beneficiary_account_before = AccountRlp::default();
|
||||
let sender_account_before = AccountRlp {
|
||||
nonce: 5.into(),
|
||||
balance: eth_to_wei(100_000.into()),
|
||||
@ -72,7 +69,12 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
||||
|
||||
let block_metadata = BlockMetadata {
|
||||
block_beneficiary: Address::from(beneficiary),
|
||||
..BlockMetadata::default()
|
||||
block_timestamp: 0x03e8.into(),
|
||||
block_number: 1.into(),
|
||||
block_difficulty: 0x020000.into(),
|
||||
block_gaslimit: 0xff112233445566u64.into(),
|
||||
block_chain_id: 1.into(),
|
||||
block_base_fee: 0xa.into(),
|
||||
};
|
||||
|
||||
let mut contract_code = HashMap::new();
|
||||
@ -94,10 +96,6 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
||||
let txdata_gas = 2 * 16;
|
||||
let gas_used = 21_000 + txdata_gas;
|
||||
|
||||
let beneficiary_account_after = AccountRlp {
|
||||
balance: beneficiary_account_before.balance + gas_used * 10,
|
||||
..beneficiary_account_before
|
||||
};
|
||||
let sender_account_after = AccountRlp {
|
||||
balance: sender_account_before.balance - value - gas_used * 10,
|
||||
nonce: sender_account_before.nonce + 1,
|
||||
@ -109,11 +107,6 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
||||
};
|
||||
|
||||
let mut children = core::array::from_fn(|_| Node::Empty.into());
|
||||
children[beneficiary_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
||||
nibbles: beneficiary_nibbles.truncate_n_nibbles_front(1),
|
||||
value: rlp::encode(&beneficiary_account_after).to_vec(),
|
||||
}
|
||||
.into();
|
||||
children[sender_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
||||
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
||||
value: rlp::encode(&sender_account_after).to_vec(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user