From cd8dcbf605733938fb9da14bb1d666d2b18b3e5e Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 6 Jun 2024 11:52:15 +0100 Subject: [PATCH 01/16] enhancement: factor out a type from access lists in Cancun --- src/ethereum/cancun/transactions.py | 59 ++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/src/ethereum/cancun/transactions.py b/src/ethereum/cancun/transactions.py index d81d11ed13..a041ef0ed3 100644 --- a/src/ethereum/cancun/transactions.py +++ b/src/ethereum/cancun/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,7 +87,7 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -101,7 +108,7 @@ class BlobTransaction: to: Address value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] max_fee_per_blob_gas: U256 blob_versioned_hashes: Tuple[VersionedHash, ...] y_parity: U256 @@ -117,6 +124,28 @@ class BlobTransaction: ] +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: """ Encode a transaction. Needed because non-legacy transactions aren't RLP. @@ -124,11 +153,17 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, BlobTransaction): - return b"\x03" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x03" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -139,11 +174,17 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 3: - return rlp.decode_to(BlobTransaction, tx[1:]) + decoded_tx = rlp.decode_to(BlobTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From 9f73e2c30c6847a98e4e3bda059361ff63480611 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 11:07:56 +0100 Subject: [PATCH 02/16] enhancement: factor out a type from access lists in Paris --- src/ethereum/paris/transactions.py | 49 ++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ethereum/paris/transactions.py b/src/ethereum/paris/transactions.py index d11bc88219..62cc4ab88c 100644 --- a/src/ethereum/paris/transactions.py +++ b/src/ethereum/paris/transactions.py @@ -27,6 +27,13 @@ TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class LegacyTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,7 +87,7 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -91,6 +98,28 @@ class FeeMarketTransaction: ] +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: """ Encode a transaction. Needed because non-legacy transactions aren't RLP. @@ -98,9 +127,13 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -111,9 +144,13 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From 6020ece1ea952d9eaf0647ddfc49b32d48874d9d Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 12:07:26 +0100 Subject: [PATCH 03/16] enhancement: factor out a type from access lists in Berlin --- src/ethereum/berlin/transactions.py | 39 ++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/ethereum/berlin/transactions.py b/src/ethereum/berlin/transactions.py index 19994de100..6360cbcfb1 100644 --- a/src/ethereum/berlin/transactions.py +++ b/src/ethereum/berlin/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,12 +66,34 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + Transaction = Union[LegacyTransaction, AccessListTransaction] @@ -75,7 +104,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -87,6 +118,8 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: if isinstance(tx, Bytes): if tx[0] != 1: raise InvalidBlock - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: return tx From ce3c77ff61f41887ef875360d149664785549981 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 12:23:56 +0100 Subject: [PATCH 04/16] enhancement: factor out a type from access lists in London --- src/ethereum/cancun/transactions.py | 16 +++++----- src/ethereum/london/transactions.py | 49 +++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/ethereum/cancun/transactions.py b/src/ethereum/cancun/transactions.py index a041ef0ed3..e3f1edd844 100644 --- a/src/ethereum/cancun/transactions.py +++ b/src/ethereum/cancun/transactions.py @@ -116,14 +116,6 @@ class BlobTransaction: s: U256 -Transaction = Union[ - LegacyTransaction, - AccessListTransaction, - FeeMarketTransaction, - BlobTransaction, -] - - # Helper function to handle the RLP encoding of the Access class instances. def encode_access_list( access_list: Tuple[Access, ...] @@ -146,6 +138,14 @@ def decode_access_list( ) for encoded in encoded_access_list) +Transaction = Union[ + LegacyTransaction, + AccessListTransaction, + FeeMarketTransaction, + BlobTransaction, +] + + def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: """ Encode a transaction. Needed because non-legacy transactions aren't RLP. diff --git a/src/ethereum/london/transactions.py b/src/ethereum/london/transactions.py index d11bc88219..2cf502b768 100644 --- a/src/ethereum/london/transactions.py +++ b/src/ethereum/london/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,12 +87,34 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -98,9 +127,13 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -111,9 +144,13 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From 2303ffc523e164e90bcf3fc4a7ca84cbc72a94fa Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 14:06:32 +0100 Subject: [PATCH 05/16] enhancement: factor out a type from access lists in Shanghai --- src/ethereum/shanghai/transactions.py | 49 +++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ethereum/shanghai/transactions.py b/src/ethereum/shanghai/transactions.py index d11bc88219..2cf502b768 100644 --- a/src/ethereum/shanghai/transactions.py +++ b/src/ethereum/shanghai/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,12 +87,34 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -98,9 +127,13 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -111,9 +144,13 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From c23af041ee588d5f47bafc86127fc362e5a24d9b Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 15:21:09 +0100 Subject: [PATCH 06/16] enhancement: factor out a type from access lists in Arrow Glacier --- src/ethereum/arrow_glacier/transactions.py | 49 +++++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ethereum/arrow_glacier/transactions.py b/src/ethereum/arrow_glacier/transactions.py index d11bc88219..2cf502b768 100644 --- a/src/ethereum/arrow_glacier/transactions.py +++ b/src/ethereum/arrow_glacier/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,12 +87,34 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -98,9 +127,13 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -111,9 +144,13 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From a4c56eee822a379c64298496c8cd236105ac51de Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 27 Jun 2024 15:44:35 +0100 Subject: [PATCH 07/16] enhancement: factor out a type from access lists in Gray Glacier --- src/ethereum/gray_glacier/transactions.py | 49 ++++++++++++++++++++--- 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/src/ethereum/gray_glacier/transactions.py b/src/ethereum/gray_glacier/transactions.py index d11bc88219..2cf502b768 100644 --- a/src/ethereum/gray_glacier/transactions.py +++ b/src/ethereum/gray_glacier/transactions.py @@ -45,6 +45,13 @@ class LegacyTransaction: s: U256 +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] + + @slotted_freezable @dataclass class AccessListTransaction: @@ -59,7 +66,7 @@ class AccessListTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 @@ -80,12 +87,34 @@ class FeeMarketTransaction: to: Union[Bytes0, Address] value: U256 data: Bytes - access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] + access_list: Tuple[Access, ...] y_parity: U256 r: U256 s: U256 +# Helper function to handle the RLP encoding of the Access class instances. +def encode_access_list( + access_list: Tuple[Access, ...] +) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: + """ + Encode the Access list for RLP encoding. + """ + return tuple((access.account, access.slots) for access in access_list) + + +# Helper function to handle the RLP decoding of the Access class instances. +def decode_access_list( + encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] +) -> Tuple[Access, ...]: + """ + Decode the Access list from RLP encoding. + """ + return tuple( + Access(account=encoded[0], slots=encoded[1] + ) for encoded in encoded_access_list) + + Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -98,9 +127,13 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - return b"\x01" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x01" + rlp.encode(tx._replace( + access_list=encoded_access_list)) elif isinstance(tx, FeeMarketTransaction): - return b"\x02" + rlp.encode(tx) + encoded_access_list = encode_access_list(tx.access_list) + return b"\x02" + rlp.encode(tx._replace( + access_list=encoded_access_list)) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -111,9 +144,13 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - return rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) elif tx[0] == 2: - return rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) + decoded_access_list = decode_access_list(decoded_tx.access_list) + return decoded_tx._replace(access_list=decoded_access_list) else: raise InvalidBlock else: From 4d20eb0ec7cfc863263b1124ff10d8421acab9b8 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Wed, 7 Aug 2024 13:47:23 +0100 Subject: [PATCH 08/16] Modify Cancun's test_rlp and fork to use new Access type --- src/ethereum/cancun/fork.py | 13 +++--- src/ethereum/cancun/transactions.py | 65 ++++++----------------------- tests/cancun/test_rlp.py | 5 ++- 3 files changed, 22 insertions(+), 61 deletions(-) diff --git a/src/ethereum/cancun/fork.py b/src/ethereum/cancun/fork.py index 29ce1958e3..2ae0aea7b5 100644 --- a/src/ethereum/cancun/fork.py +++ b/src/ethereum/cancun/fork.py @@ -754,10 +754,10 @@ def process_transaction( if isinstance( tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction) ): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -849,9 +849,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: if isinstance( tx, (AccessListTransaction, FeeMarketTransaction, BlobTransaction) ): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/cancun/transactions.py b/src/ethereum/cancun/transactions.py index e3f1edd844..b3286c2315 100644 --- a/src/ethereum/cancun/transactions.py +++ b/src/ethereum/cancun/transactions.py @@ -19,12 +19,12 @@ from ..exceptions import InvalidBlock from .fork_types import Address, VersionedHash -TX_BASE_COST = 21000 -TX_DATA_COST_PER_NON_ZERO = 16 -TX_DATA_COST_PER_ZERO = 4 -TX_CREATE_COST = 32000 -TX_ACCESS_LIST_ADDRESS_COST = 2400 -TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + +@slotted_freezable +@dataclass +class Access: + account: Address + slots: Tuple[Bytes32, ...] @slotted_freezable @@ -45,13 +45,6 @@ class LegacyTransaction: s: U256 -@slotted_freezable -@dataclass -class Access: - account: Address - slots: Tuple[Bytes32, ...] - - @slotted_freezable @dataclass class AccessListTransaction: @@ -116,28 +109,6 @@ class BlobTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[ LegacyTransaction, AccessListTransaction, @@ -153,17 +124,11 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) elif isinstance(tx, BlobTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x03" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x03" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -174,17 +139,11 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) elif tx[0] == 3: - decoded_tx = rlp.decode_to(BlobTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(BlobTransaction, tx[1:]) else: raise InvalidBlock else: diff --git a/tests/cancun/test_rlp.py b/tests/cancun/test_rlp.py index 747eeb7e48..dd9f63ea3f 100644 --- a/tests/cancun/test_rlp.py +++ b/tests/cancun/test_rlp.py @@ -10,6 +10,7 @@ Transaction, decode_transaction, encode_transaction, + Access ) from ethereum.cancun.utils.hexadecimal import hex_to_address from ethereum.crypto.hash import keccak256 @@ -59,7 +60,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), @@ -74,7 +75,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), From 2b748a7a1b96b48e20bf89629272f36cf9286a92 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 10:27:39 +0100 Subject: [PATCH 09/16] Modify Paris' test_rlp and fork to use new Access type --- src/ethereum/paris/fork.py | 13 +++++----- src/ethereum/paris/transactions.py | 38 ++++-------------------------- tests/paris/test_rlp.py | 5 ++-- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/ethereum/paris/fork.py b/src/ethereum/paris/fork.py index 66e8f6c56b..98e80b43f3 100644 --- a/src/ethereum/paris/fork.py +++ b/src/ethereum/paris/fork.py @@ -594,10 +594,10 @@ def process_transaction( preaccessed_addresses = set() preaccessed_storage_keys = set() if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -717,9 +717,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: access_list_cost = 0 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/paris/transactions.py b/src/ethereum/paris/transactions.py index 62cc4ab88c..712614258b 100644 --- a/src/ethereum/paris/transactions.py +++ b/src/ethereum/paris/transactions.py @@ -98,28 +98,6 @@ class FeeMarketTransaction: ] -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: """ Encode a transaction. Needed because non-legacy transactions aren't RLP. @@ -127,13 +105,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -144,13 +118,9 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) else: raise InvalidBlock else: diff --git a/tests/paris/test_rlp.py b/tests/paris/test_rlp.py index 695f385bd4..90e173f65e 100644 --- a/tests/paris/test_rlp.py +++ b/tests/paris/test_rlp.py @@ -11,6 +11,7 @@ Transaction, decode_transaction, encode_transaction, + Access ) from ethereum.paris.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -59,7 +60,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), @@ -74,7 +75,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), From 76b516a131beb399906ca25c29796a7bfb90d856 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 14:27:12 +0100 Subject: [PATCH 10/16] Modify Berlin's test_rlp and fork to use new Access type. --- src/ethereum/berlin/fork.py | 13 +++++++------ src/ethereum/berlin/transactions.py | 30 ++--------------------------- tests/berlin/test_rlp.py | 3 ++- 3 files changed, 11 insertions(+), 35 deletions(-) diff --git a/src/ethereum/berlin/fork.py b/src/ethereum/berlin/fork.py index 720f7e4c8e..4f8e3bf5f3 100644 --- a/src/ethereum/berlin/fork.py +++ b/src/ethereum/berlin/fork.py @@ -687,10 +687,10 @@ def process_transaction( preaccessed_addresses = set() preaccessed_storage_keys = set() if isinstance(tx, AccessListTransaction): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -804,9 +804,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: access_list_cost = 0 if isinstance(tx, AccessListTransaction): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/berlin/transactions.py b/src/ethereum/berlin/transactions.py index 6360cbcfb1..715f526273 100644 --- a/src/ethereum/berlin/transactions.py +++ b/src/ethereum/berlin/transactions.py @@ -72,28 +72,6 @@ class AccessListTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[LegacyTransaction, AccessListTransaction] @@ -104,9 +82,7 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -118,8 +94,6 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: if isinstance(tx, Bytes): if tx[0] != 1: raise InvalidBlock - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) else: return tx diff --git a/tests/berlin/test_rlp.py b/tests/berlin/test_rlp.py index b1d7e4e4b7..4556c3e02b 100644 --- a/tests/berlin/test_rlp.py +++ b/tests/berlin/test_rlp.py @@ -9,6 +9,7 @@ Transaction, decode_transaction, encode_transaction, + Access ) from ethereum.berlin.utils.hexadecimal import hex_to_address from ethereum.crypto.hash import keccak256 @@ -58,7 +59,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), From 2fa9581b45998ef42fb072412836616614fa10dd Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 14:36:43 +0100 Subject: [PATCH 11/16] Modify London's test_rlp and fork to use new Access type. --- src/ethereum/london/fork.py | 13 +++++----- src/ethereum/london/transactions.py | 38 +++-------------------------- tests/london/test_rlp.py | 5 ++-- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/ethereum/london/fork.py b/src/ethereum/london/fork.py index 9aae34f0f0..31560995ee 100644 --- a/src/ethereum/london/fork.py +++ b/src/ethereum/london/fork.py @@ -808,10 +808,10 @@ def process_transaction( preaccessed_addresses = set() preaccessed_storage_keys = set() if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -931,9 +931,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: access_list_cost = 0 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/london/transactions.py b/src/ethereum/london/transactions.py index 2cf502b768..c2413c7973 100644 --- a/src/ethereum/london/transactions.py +++ b/src/ethereum/london/transactions.py @@ -93,28 +93,6 @@ class FeeMarketTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -127,13 +105,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -144,13 +118,9 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) else: raise InvalidBlock else: diff --git a/tests/london/test_rlp.py b/tests/london/test_rlp.py index 56f6a4f81c..08fba2afa6 100644 --- a/tests/london/test_rlp.py +++ b/tests/london/test_rlp.py @@ -11,6 +11,7 @@ Transaction, decode_transaction, encode_transaction, + Access ) from ethereum.london.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -59,7 +60,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), @@ -74,7 +75,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), From aacfcaab14d2d269c90f410b77caecb77824ba10 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 15:31:29 +0100 Subject: [PATCH 12/16] Modify Shanghai's test_rlp and fork to use new Access type. --- src/ethereum/shanghai/fork.py | 13 ++++----- src/ethereum/shanghai/transactions.py | 38 +++------------------------ tests/shanghai/test_rlp.py | 5 ++-- 3 files changed, 14 insertions(+), 42 deletions(-) diff --git a/src/ethereum/shanghai/fork.py b/src/ethereum/shanghai/fork.py index c713780981..b6708add82 100644 --- a/src/ethereum/shanghai/fork.py +++ b/src/ethereum/shanghai/fork.py @@ -618,10 +618,10 @@ def process_transaction( preaccessed_storage_keys = set() preaccessed_addresses.add(env.coinbase) if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -748,9 +748,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: access_list_cost = 0 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/shanghai/transactions.py b/src/ethereum/shanghai/transactions.py index 2cf502b768..c2413c7973 100644 --- a/src/ethereum/shanghai/transactions.py +++ b/src/ethereum/shanghai/transactions.py @@ -93,28 +93,6 @@ class FeeMarketTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -127,13 +105,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -144,13 +118,9 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) else: raise InvalidBlock else: diff --git a/tests/shanghai/test_rlp.py b/tests/shanghai/test_rlp.py index 2b073783c5..56db721f82 100644 --- a/tests/shanghai/test_rlp.py +++ b/tests/shanghai/test_rlp.py @@ -11,6 +11,7 @@ Transaction, decode_transaction, encode_transaction, + Access ) from ethereum.shanghai.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -59,7 +60,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), @@ -74,7 +75,7 @@ Bytes0(), U256(4), Bytes(b"bar"), - ((address1, (hash1, hash2)), (address2, tuple())), + (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), U256(27), U256(5), U256(6), From deac7c2eefa91e68fbdd77bf341ecb7e5e22d650 Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 15:43:45 +0100 Subject: [PATCH 13/16] Modify Gray Glacier's fork to use new Access type. --- src/ethereum/gray_glacier/fork.py | 13 ++++---- src/ethereum/gray_glacier/transactions.py | 38 +++-------------------- 2 files changed, 11 insertions(+), 40 deletions(-) diff --git a/src/ethereum/gray_glacier/fork.py b/src/ethereum/gray_glacier/fork.py index 4a80e96bdb..0ef5648b39 100644 --- a/src/ethereum/gray_glacier/fork.py +++ b/src/ethereum/gray_glacier/fork.py @@ -800,10 +800,10 @@ def process_transaction( preaccessed_addresses = set() preaccessed_storage_keys = set() if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for address, keys in tx.access_list: - preaccessed_addresses.add(address) - for key in keys: - preaccessed_storage_keys.add((address, key)) + for access in tx.access_list: + preaccessed_addresses.add(access.account) + for key in access.slots: + preaccessed_storage_keys.add((access.account, key)) message = prepare_message( sender, @@ -923,9 +923,10 @@ def calculate_intrinsic_cost(tx: Transaction) -> Uint: access_list_cost = 0 if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)): - for _address, keys in tx.access_list: + for access in tx.access_list: access_list_cost += TX_ACCESS_LIST_ADDRESS_COST - access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST + slots_cost = len(access.slots) * TX_ACCESS_LIST_STORAGE_KEY_COST + access_list_cost += slots_cost return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost) diff --git a/src/ethereum/gray_glacier/transactions.py b/src/ethereum/gray_glacier/transactions.py index 2cf502b768..c2413c7973 100644 --- a/src/ethereum/gray_glacier/transactions.py +++ b/src/ethereum/gray_glacier/transactions.py @@ -93,28 +93,6 @@ class FeeMarketTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -127,13 +105,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -144,13 +118,9 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) else: raise InvalidBlock else: From eb2f271f2cf694af09b890eef852297d631c869e Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Thu, 8 Aug 2024 15:50:46 +0100 Subject: [PATCH 14/16] Modify Arrow Glacier's fork to use new Access type. --- src/ethereum/arrow_glacier/transactions.py | 38 +++------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/src/ethereum/arrow_glacier/transactions.py b/src/ethereum/arrow_glacier/transactions.py index 2cf502b768..c2413c7973 100644 --- a/src/ethereum/arrow_glacier/transactions.py +++ b/src/ethereum/arrow_glacier/transactions.py @@ -93,28 +93,6 @@ class FeeMarketTransaction: s: U256 -# Helper function to handle the RLP encoding of the Access class instances. -def encode_access_list( - access_list: Tuple[Access, ...] -) -> Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...]: - """ - Encode the Access list for RLP encoding. - """ - return tuple((access.account, access.slots) for access in access_list) - - -# Helper function to handle the RLP decoding of the Access class instances. -def decode_access_list( - encoded_access_list: Tuple[Tuple[Address, Tuple[Bytes32, ...]], ...] -) -> Tuple[Access, ...]: - """ - Decode the Access list from RLP encoding. - """ - return tuple( - Access(account=encoded[0], slots=encoded[1] - ) for encoded in encoded_access_list) - - Transaction = Union[ LegacyTransaction, AccessListTransaction, FeeMarketTransaction ] @@ -127,13 +105,9 @@ def encode_transaction(tx: Transaction) -> Union[LegacyTransaction, Bytes]: if isinstance(tx, LegacyTransaction): return tx elif isinstance(tx, AccessListTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x01" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x01" + rlp.encode(tx) elif isinstance(tx, FeeMarketTransaction): - encoded_access_list = encode_access_list(tx.access_list) - return b"\x02" + rlp.encode(tx._replace( - access_list=encoded_access_list)) + return b"\x02" + rlp.encode(tx) else: raise Exception(f"Unable to encode transaction of type {type(tx)}") @@ -144,13 +118,9 @@ def decode_transaction(tx: Union[LegacyTransaction, Bytes]) -> Transaction: """ if isinstance(tx, Bytes): if tx[0] == 1: - decoded_tx = rlp.decode_to(AccessListTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(AccessListTransaction, tx[1:]) elif tx[0] == 2: - decoded_tx = rlp.decode_to(FeeMarketTransaction, tx[1:]) - decoded_access_list = decode_access_list(decoded_tx.access_list) - return decoded_tx._replace(access_list=decoded_access_list) + return rlp.decode_to(FeeMarketTransaction, tx[1:]) else: raise InvalidBlock else: From c2a769b8ed48e9dc344cb8f8fb39d1df04dcef25 Mon Sep 17 00:00:00 2001 From: Sam Wilson Date: Tue, 13 Aug 2024 11:33:29 -0400 Subject: [PATCH 15/16] black and isort --- tests/berlin/test_rlp.py | 7 +++++-- tests/cancun/test_rlp.py | 12 +++++++++--- tests/london/test_rlp.py | 12 +++++++++--- tests/paris/test_rlp.py | 12 +++++++++--- tests/shanghai/test_rlp.py | 12 +++++++++--- 5 files changed, 41 insertions(+), 14 deletions(-) diff --git a/tests/berlin/test_rlp.py b/tests/berlin/test_rlp.py index 4556c3e02b..b13513b4d8 100644 --- a/tests/berlin/test_rlp.py +++ b/tests/berlin/test_rlp.py @@ -4,12 +4,12 @@ from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes8, Uint from ethereum.berlin.blocks import Block, Header, Log, Receipt from ethereum.berlin.transactions import ( + Access, AccessListTransaction, LegacyTransaction, Transaction, decode_transaction, encode_transaction, - Access ) from ethereum.berlin.utils.hexadecimal import hex_to_address from ethereum.crypto.hash import keccak256 @@ -59,7 +59,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), diff --git a/tests/cancun/test_rlp.py b/tests/cancun/test_rlp.py index dd9f63ea3f..f4eac4e2f2 100644 --- a/tests/cancun/test_rlp.py +++ b/tests/cancun/test_rlp.py @@ -4,13 +4,13 @@ from ethereum.base_types import U64, U256, Bytes, Bytes0, Bytes8, Bytes32, Uint from ethereum.cancun.blocks import Block, Header, Log, Receipt, Withdrawal from ethereum.cancun.transactions import ( + Access, AccessListTransaction, FeeMarketTransaction, LegacyTransaction, Transaction, decode_transaction, encode_transaction, - Access ) from ethereum.cancun.utils.hexadecimal import hex_to_address from ethereum.crypto.hash import keccak256 @@ -60,7 +60,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), @@ -75,7 +78,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), diff --git a/tests/london/test_rlp.py b/tests/london/test_rlp.py index 08fba2afa6..22bfb5bc38 100644 --- a/tests/london/test_rlp.py +++ b/tests/london/test_rlp.py @@ -5,13 +5,13 @@ from ethereum.crypto.hash import keccak256 from ethereum.london.blocks import Block, Header, Log, Receipt from ethereum.london.transactions import ( + Access, AccessListTransaction, FeeMarketTransaction, LegacyTransaction, Transaction, decode_transaction, encode_transaction, - Access ) from ethereum.london.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -60,7 +60,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), @@ -75,7 +78,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), diff --git a/tests/paris/test_rlp.py b/tests/paris/test_rlp.py index 90e173f65e..ed6a97a8c1 100644 --- a/tests/paris/test_rlp.py +++ b/tests/paris/test_rlp.py @@ -5,13 +5,13 @@ from ethereum.crypto.hash import keccak256 from ethereum.paris.blocks import Block, Header, Log, Receipt from ethereum.paris.transactions import ( + Access, AccessListTransaction, FeeMarketTransaction, LegacyTransaction, Transaction, decode_transaction, encode_transaction, - Access ) from ethereum.paris.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -60,7 +60,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), @@ -75,7 +78,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), diff --git a/tests/shanghai/test_rlp.py b/tests/shanghai/test_rlp.py index 56db721f82..86ddc7a83b 100644 --- a/tests/shanghai/test_rlp.py +++ b/tests/shanghai/test_rlp.py @@ -5,13 +5,13 @@ from ethereum.crypto.hash import keccak256 from ethereum.shanghai.blocks import Block, Header, Log, Receipt, Withdrawal from ethereum.shanghai.transactions import ( + Access, AccessListTransaction, FeeMarketTransaction, LegacyTransaction, Transaction, decode_transaction, encode_transaction, - Access ) from ethereum.shanghai.utils.hexadecimal import hex_to_address from ethereum.utils.hexadecimal import hex_to_bytes256 @@ -60,7 +60,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), @@ -75,7 +78,10 @@ Bytes0(), U256(4), Bytes(b"bar"), - (Access(account=address1, slots=(hash1, hash2)), Access(account=address2, slots=tuple())), + ( + Access(account=address1, slots=(hash1, hash2)), + Access(account=address2, slots=tuple()), + ), U256(27), U256(5), U256(6), From eed30648b1e8eda1076737095a276454cd91297b Mon Sep 17 00:00:00 2001 From: Richard Gregory Date: Wed, 14 Aug 2024 21:01:29 +0100 Subject: [PATCH 16/16] Re-add deleted constants in Cancun's transaction.py --- src/ethereum/cancun/transactions.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ethereum/cancun/transactions.py b/src/ethereum/cancun/transactions.py index b3286c2315..0d21184248 100644 --- a/src/ethereum/cancun/transactions.py +++ b/src/ethereum/cancun/transactions.py @@ -19,6 +19,13 @@ from ..exceptions import InvalidBlock from .fork_types import Address, VersionedHash +TX_BASE_COST = 21000 +TX_DATA_COST_PER_NON_ZERO = 16 +TX_DATA_COST_PER_ZERO = 4 +TX_CREATE_COST = 32000 +TX_ACCESS_LIST_ADDRESS_COST = 2400 +TX_ACCESS_LIST_STORAGE_KEY_COST = 1900 + @slotted_freezable @dataclass