mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 16:23:12 +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.
|
// Assert gas_limit >= intrinsic_gas.
|
||||||
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
%mload_txn_field(@TXN_FIELD_INTRINSIC_GAS)
|
||||||
%mload_txn_field(@TXN_FIELD_GAS_LIMIT)
|
%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)
|
%mload_txn_field(@TXN_FIELD_ORIGIN)
|
||||||
// stack: sender, retdest
|
// stack: sender, retdest
|
||||||
|
|
||||||
// Check that txn nonce matches account nonce.
|
// Check that txn nonce matches account nonce.
|
||||||
DUP1 %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
|
// stack: sender_nonce, sender, retdest
|
||||||
%mload_txn_field(@TXN_FIELD_NONCE)
|
%mload_txn_field(@TXN_FIELD_NONCE)
|
||||||
// stack: tx_nonce, sender_nonce, sender, retdest
|
// stack: tx_nonce, sender_nonce, sender, retdest
|
||||||
%assert_eq
|
%assert_eq(invalid_txn)
|
||||||
// stack: sender, retdest
|
// stack: sender, retdest
|
||||||
|
|
||||||
// Assert sender has no code.
|
// Assert sender has no code.
|
||||||
DUP1 %ext_code_empty %assert_nonzero
|
DUP1 %ext_code_empty %assert_nonzero(invalid_txn)
|
||||||
// stack: sender, retdest
|
// stack: sender, retdest
|
||||||
|
|
||||||
// Assert sender balance >= gas_limit * gas_price + value.
|
// Assert sender balance >= gas_limit * gas_price + value.
|
||||||
@ -44,7 +49,7 @@ global process_normalized_txn:
|
|||||||
MUL
|
MUL
|
||||||
%mload_txn_field(@TXN_FIELD_VALUE)
|
%mload_txn_field(@TXN_FIELD_VALUE)
|
||||||
ADD
|
ADD
|
||||||
%assert_le
|
%assert_le(invalid_txn)
|
||||||
// stack: retdest
|
// stack: retdest
|
||||||
|
|
||||||
// Assert chain ID matches block metadata
|
// Assert chain ID matches block metadata
|
||||||
@ -58,7 +63,7 @@ global process_normalized_txn:
|
|||||||
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_CHAIN_ID)
|
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_CHAIN_ID)
|
||||||
MUL
|
MUL
|
||||||
// stack: filtered_block_chain_id, filtered_tx_chain_id, retdest
|
// stack: filtered_block_chain_id, filtered_tx_chain_id, retdest
|
||||||
%assert_eq
|
%assert_eq(invalid_txn)
|
||||||
// stack: retdest
|
// stack: retdest
|
||||||
|
|
||||||
global buy_gas:
|
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_PRIORITY_FEE_PER_GAS)
|
||||||
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
%mload_txn_field(@TXN_FIELD_MAX_FEE_PER_GAS)
|
||||||
// stack: max_fee, max_priority_fee, base_fee
|
// 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
|
// 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)
|
%stack (max_fee, max_priority_fee, base_fee) -> (max_fee, base_fee, max_priority_fee, base_fee)
|
||||||
SUB
|
SUB
|
||||||
// stack: max_fee - base_fee, max_priority_fee, base_fee
|
// stack: max_fee - base_fee, max_priority_fee, base_fee
|
||||||
@ -399,3 +405,7 @@ contract_creation_fault_4:
|
|||||||
%delete_all_touched_addresses
|
%delete_all_touched_addresses
|
||||||
%delete_all_selfdestructed_addresses
|
%delete_all_selfdestructed_addresses
|
||||||
JUMP
|
JUMP
|
||||||
|
|
||||||
|
|
||||||
|
invalid_txn:
|
||||||
|
%jump(txn_loop)
|
||||||
|
|||||||
@ -34,6 +34,113 @@ global process_type_2_txn:
|
|||||||
POP
|
POP
|
||||||
// stack: retdest
|
// 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)
|
%jump(process_normalized_txn)
|
||||||
|
|||||||
@ -8,17 +8,31 @@ global panic:
|
|||||||
%jumpi(panic)
|
%jumpi(panic)
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_zero(ret)
|
||||||
|
%jumpi($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
// Consumes the top element and asserts that it is nonzero.
|
// Consumes the top element and asserts that it is nonzero.
|
||||||
%macro assert_nonzero
|
%macro assert_nonzero
|
||||||
ISZERO
|
ISZERO
|
||||||
%jumpi(panic)
|
%jumpi(panic)
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_nonzero(ret)
|
||||||
|
ISZERO
|
||||||
|
%jumpi($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_eq
|
%macro assert_eq
|
||||||
EQ
|
EQ
|
||||||
%assert_nonzero
|
%assert_nonzero
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_eq(ret)
|
||||||
|
EQ
|
||||||
|
%assert_nonzero($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_lt
|
%macro assert_lt
|
||||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||||
// fact that (x < y) == !(x >= y).
|
// fact that (x < y) == !(x >= y).
|
||||||
@ -26,6 +40,11 @@ global panic:
|
|||||||
%assert_zero
|
%assert_zero
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_lt(ret)
|
||||||
|
GE
|
||||||
|
%assert_zero($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_le
|
%macro assert_le
|
||||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||||
// fact that (x <= y) == !(x > y).
|
// fact that (x <= y) == !(x > y).
|
||||||
@ -33,6 +52,11 @@ global panic:
|
|||||||
%assert_zero
|
%assert_zero
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_le(ret)
|
||||||
|
GT
|
||||||
|
%assert_zero($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_gt
|
%macro assert_gt
|
||||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||||
// fact that (x > y) == !(x <= y).
|
// fact that (x > y) == !(x <= y).
|
||||||
@ -40,6 +64,11 @@ global panic:
|
|||||||
%assert_zero
|
%assert_zero
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_gt(ret)
|
||||||
|
LE
|
||||||
|
%assert_zero($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_ge
|
%macro assert_ge
|
||||||
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
// %assert_zero is cheaper than %assert_nonzero, so we will leverage the
|
||||||
// fact that (x >= y) == !(x < y).
|
// fact that (x >= y) == !(x < y).
|
||||||
@ -47,6 +76,11 @@ global panic:
|
|||||||
%assert_zero
|
%assert_zero
|
||||||
%endmacro
|
%endmacro
|
||||||
|
|
||||||
|
%macro assert_ge(ret)
|
||||||
|
LT
|
||||||
|
%assert_zero($ret)
|
||||||
|
%endmacro
|
||||||
|
|
||||||
%macro assert_eq_const(c)
|
%macro assert_eq_const(c)
|
||||||
%eq_const($c)
|
%eq_const($c)
|
||||||
%assert_nonzero
|
%assert_nonzero
|
||||||
|
|||||||
@ -81,8 +81,12 @@ fn add11_yml() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let block_metadata = BlockMetadata {
|
let block_metadata = BlockMetadata {
|
||||||
block_beneficiary: Address::from(beneficiary),
|
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(),
|
block_base_fee: 0xa.into(),
|
||||||
..BlockMetadata::default()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut contract_code = HashMap::new();
|
let mut contract_code = HashMap::new();
|
||||||
|
|||||||
@ -37,15 +37,12 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
|||||||
let sender = hex!("2c7536e3605d9c16a7a3d7b1898e529396a65c23");
|
let sender = hex!("2c7536e3605d9c16a7a3d7b1898e529396a65c23");
|
||||||
let to = hex!("a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0");
|
let to = hex!("a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0");
|
||||||
|
|
||||||
let beneficiary_state_key = keccak(beneficiary);
|
|
||||||
let sender_state_key = keccak(sender);
|
let sender_state_key = keccak(sender);
|
||||||
let to_state_key = keccak(to);
|
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 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 to_nibbles = Nibbles::from_bytes_be(to_state_key.as_bytes()).unwrap();
|
||||||
|
|
||||||
let beneficiary_account_before = AccountRlp::default();
|
|
||||||
let sender_account_before = AccountRlp {
|
let sender_account_before = AccountRlp {
|
||||||
nonce: 5.into(),
|
nonce: 5.into(),
|
||||||
balance: eth_to_wei(100_000.into()),
|
balance: eth_to_wei(100_000.into()),
|
||||||
@ -72,7 +69,12 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
let block_metadata = BlockMetadata {
|
let block_metadata = BlockMetadata {
|
||||||
block_beneficiary: Address::from(beneficiary),
|
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();
|
let mut contract_code = HashMap::new();
|
||||||
@ -94,10 +96,6 @@ fn test_simple_transfer() -> anyhow::Result<()> {
|
|||||||
let txdata_gas = 2 * 16;
|
let txdata_gas = 2 * 16;
|
||||||
let gas_used = 21_000 + txdata_gas;
|
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 {
|
let sender_account_after = AccountRlp {
|
||||||
balance: sender_account_before.balance - value - gas_used * 10,
|
balance: sender_account_before.balance - value - gas_used * 10,
|
||||||
nonce: sender_account_before.nonce + 1,
|
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());
|
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 {
|
children[sender_nibbles.get_nibble(0) as usize] = Node::Leaf {
|
||||||
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
nibbles: sender_nibbles.truncate_n_nibbles_front(1),
|
||||||
value: rlp::encode(&sender_account_after).to_vec(),
|
value: rlp::encode(&sender_account_after).to_vec(),
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user