Skip to content

Commit

Permalink
types: Force required fields on different transaction types (#216)
Browse files Browse the repository at this point in the history
* types: force required fields for transaction types

* types: add tests

* types: print address on storage mismatch

* tools: fix typos in transaction exception messages

* tools: add tests for transaction __post_init__

---------

Co-authored-by: danceratopz <danceratopz@gmail.com>
  • Loading branch information
marioevz and danceratopz authored Jul 25, 2023
1 parent 99d46d9 commit 8d796b9
Show file tree
Hide file tree
Showing 5 changed files with 240 additions and 34 deletions.
1 change: 1 addition & 0 deletions .wordlist_python_pytest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ callspec
collectonly
dedent
dest
exc
fixturenames
fspath
funcargs
Expand Down
71 changes: 40 additions & 31 deletions src/ethereum_test_tools/common/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,26 +349,25 @@ class KeyValueMismatch(Exception):
was different.
"""

address: str
key: int
want: int
got: int

def __init__(self, key: int, want: int, got: int, *args):
def __init__(self, address: str, key: int, want: int, got: int, *args):
super().__init__(args)
self.address = address
self.key = key
self.want = want
self.got = got

def __str__(self):
"""Print exception string"""
return (
"incorrect value for key {0}: want {1} (dec:{2})," + " got {3} (dec:{4})"
).format(
Storage.key_value_to_string(self.key),
Storage.key_value_to_string(self.want),
self.want,
Storage.key_value_to_string(self.got),
self.got,
f"incorrect value in address {self.address} for "
+ f"key {Storage.key_value_to_string(self.key)}:"
+ f" want {Storage.key_value_to_string(self.want)} (dec:{self.want}),"
+ f" got {Storage.key_value_to_string(self.got)} (dec:{self.got})"
)

@staticmethod
Expand Down Expand Up @@ -477,7 +476,7 @@ def contains(self, other: "Storage") -> bool:
return False
return True

def must_contain(self, other: "Storage"):
def must_contain(self, address: str, other: "Storage"):
"""
Succeeds only if self contains all keys with equal value as
contained by second storage.
Expand All @@ -491,25 +490,25 @@ def must_contain(self, other: "Storage"):
if other[key] != 0:
raise Storage.MissingKey(key)
elif self.data[key] != other.data[key]:
raise Storage.KeyValueMismatch(key, self.data[key], other.data[key])
raise Storage.KeyValueMismatch(address, key, self.data[key], other.data[key])

def must_be_equal(self, other: "Storage"):
def must_be_equal(self, address: str, other: "Storage"):
"""
Succeeds only if "self" is equal to "other" storage.
"""
# Test keys contained in both storage objects
for key in self.data.keys() & other.data.keys():
if self.data[key] != other.data[key]:
raise Storage.KeyValueMismatch(key, self.data[key], other.data[key])
raise Storage.KeyValueMismatch(address, key, self.data[key], other.data[key])

# Test keys contained in either one of the storage objects
for key in self.data.keys() ^ other.data.keys():
if key in self.data:
if self.data[key] != 0:
raise Storage.KeyValueMismatch(key, self.data[key], 0)
raise Storage.KeyValueMismatch(address, key, self.data[key], 0)

elif other.data[key] != 0:
raise Storage.KeyValueMismatch(key, 0, other.data[key])
raise Storage.KeyValueMismatch(address, key, 0, other.data[key])


@dataclass(kw_only=True)
Expand Down Expand Up @@ -681,7 +680,7 @@ def check_alloc(self: "Account", address: str, alloc: dict):
self.storage if isinstance(self.storage, Storage) else Storage(self.storage)
)
actual_storage = Storage(alloc["storage"]) if "storage" in alloc else Storage({})
expected_storage.must_be_equal(actual_storage)
expected_storage.must_be_equal(address=address, other=actual_storage)

@classmethod
def with_code(cls: Type, code: BytesConvertible) -> "Account":
Expand Down Expand Up @@ -1249,17 +1248,18 @@ def __post_init__(self) -> None:
"""
Ensures the transaction has no conflicting properties.
"""
if (
self.gas_price is not None
and self.max_fee_per_gas is not None
and self.max_priority_fee_per_gas is not None
if self.gas_price is not None and (
self.max_fee_per_gas is not None
or self.max_priority_fee_per_gas is not None
or self.max_fee_per_data_gas is not None
):
raise Transaction.InvalidFeePayment()

if (
self.gas_price is None
and self.max_fee_per_gas is None
and self.max_priority_fee_per_gas is None
and self.max_fee_per_data_gas is None
):
self.gas_price = 10

Expand All @@ -1280,6 +1280,13 @@ def __post_init__(self) -> None:
else:
self.ty = 0

# Set default values for fields that are required for certain tx types
if self.ty >= 1 and self.access_list is None:
self.access_list = []

if self.ty >= 2 and self.max_priority_fee_per_gas is None:
self.max_priority_fee_per_gas = 0

def with_error(self, error: str) -> "Transaction":
"""
Create a copy of the transaction with an added error.
Expand Down Expand Up @@ -1329,6 +1336,8 @@ def payload_body(self) -> List[Any]:
raise ValueError("max_fee_per_data_gas must be set for type 3 tx")
if self.blob_versioned_hashes is None:
raise ValueError("blob_versioned_hashes must be set for type 3 tx")
if self.access_list is None:
raise ValueError("access_list must be set for type 3 tx")

if self.wrapped_blob_transaction:
if self.blobs is None:
Expand All @@ -1352,9 +1361,7 @@ def payload_body(self) -> List[Any]:
to,
Uint(self.value),
Bytes(self.data),
[a.to_list() for a in self.access_list]
if self.access_list is not None
else [],
[a.to_list() for a in self.access_list],
Uint(self.max_fee_per_data_gas),
[Hash(h) for h in self.blob_versioned_hashes],
Uint(self.v),
Expand All @@ -1375,9 +1382,7 @@ def payload_body(self) -> List[Any]:
to,
Uint(self.value),
Bytes(self.data),
[a.to_list() for a in self.access_list]
if self.access_list is not None
else [],
[a.to_list() for a in self.access_list],
Uint(self.max_fee_per_data_gas),
[Hash(h) for h in self.blob_versioned_hashes],
Uint(self.v),
Expand All @@ -1387,9 +1392,11 @@ def payload_body(self) -> List[Any]:
elif self.ty == 2:
# EIP-1559: https://eips.ethereum.org/EIPS/eip-1559
if self.max_priority_fee_per_gas is None:
raise ValueError("max_priority_fee_per_gas must be set for type 3 tx")
raise ValueError("max_priority_fee_per_gas must be set for type 2 tx")
if self.max_fee_per_gas is None:
raise ValueError("max_fee_per_gas must be set for type 3 tx")
raise ValueError("max_fee_per_gas must be set for type 2 tx")
if self.access_list is None:
raise ValueError("access_list must be set for type 2 tx")
return [
Uint(self.chain_id),
Uint(self.nonce),
Expand All @@ -1399,7 +1406,7 @@ def payload_body(self) -> List[Any]:
to,
Uint(self.value),
Bytes(self.data),
[a.to_list() for a in self.access_list] if self.access_list is not None else [],
[a.to_list() for a in self.access_list],
Uint(self.v),
Uint(self.r),
Uint(self.s),
Expand All @@ -1408,6 +1415,8 @@ def payload_body(self) -> List[Any]:
# EIP-2930: https://eips.ethereum.org/EIPS/eip-2930
if self.gas_price is None:
raise ValueError("gas_price must be set for type 1 tx")
if self.access_list is None:
raise ValueError("access_list must be set for type 1 tx")

return [
Uint(self.chain_id),
Expand All @@ -1417,7 +1426,7 @@ def payload_body(self) -> List[Any]:
to,
Uint(self.value),
Bytes(self.data),
[a.to_list() for a in self.access_list] if self.access_list is not None else [],
[a.to_list() for a in self.access_list],
Uint(self.v),
Uint(self.r),
Uint(self.s),
Expand Down Expand Up @@ -1487,9 +1496,9 @@ def signing_envelope(self) -> List[Any]:
elif self.ty == 2:
# EIP-1559: https://eips.ethereum.org/EIPS/eip-1559
if self.max_priority_fee_per_gas is None:
raise ValueError("max_priority_fee_per_gas must be set for type 3 tx")
raise ValueError("max_priority_fee_per_gas must be set for type 2 tx")
if self.max_fee_per_gas is None:
raise ValueError("max_fee_per_gas must be set for type 3 tx")
raise ValueError("max_fee_per_gas must be set for type 2 tx")
return [
Uint(self.chain_id),
Uint(self.nonce),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"gasLimit": "0x0f4240",
"maxFeePerGas": "0x03e8",
"maxPriorityFeePerGas": "0x01",
"accessList": [],
"v": "0x00",
"r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58",
"s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b",
Expand Down Expand Up @@ -75,6 +76,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0a",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050",
"s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0",
Expand All @@ -90,6 +92,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d",
"s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d",
Expand All @@ -105,6 +108,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a",
"s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a",
Expand Down Expand Up @@ -151,6 +155,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x03e8",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63",
"s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169",
Expand All @@ -166,6 +171,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e",
"s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33",
Expand All @@ -181,6 +187,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0186a0",
"maxFeePerGas": "0x0186a0",
"accessList": [],
"v": "0x01",
"r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a",
"s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c",
Expand Down Expand Up @@ -227,6 +234,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x03e8",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c",
"s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97",
Expand All @@ -242,6 +250,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15",
"s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d",
Expand All @@ -257,6 +266,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0186a0",
"maxFeePerGas": "0x0186a0",
"accessList": [],
"v": "0x01",
"r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9",
"s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x01",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x3351b6993208fc7b03fd770c8c06440cfb0d75b29aafee0a4c64c8ba20a80e58",
"s": "0x67817fdb3058e75c5d26e51a33d1e338346bc7d406e115447a4bb5f7ab01625b",
Expand Down Expand Up @@ -75,6 +76,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0a",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x6ea285a870a051df2b8c80c462b7d3517f984815e09c4748efc8548a40434050",
"s": "0x52f635268c1b9e1538ac76b37cb69c7b897595744d6de2dda9507b6624d352d0",
Expand All @@ -90,6 +92,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x218549e818b36b3823c3f11a65ab5c1e16f6886469c385503cc2f1af1f53825d",
"s": "0x58b082850f55fd61290a99add11b7af6356ac8d55fbe4d513f06bf648824a64d",
Expand All @@ -105,6 +108,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x339e9ed3f6342f2644e4cd33a775b7e62a8208a137dcf2e354c7473caa77782a",
"s": "0x74004c85b651c8ca9828aac28414997f3eff46edbba2bb606a545d95fd4c9b3a",
Expand Down Expand Up @@ -146,6 +150,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x03e8",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x720e2870881f8b0e285b7ec02c169f1165847bcb5f36ea5f33f3db6079854f63",
"s": "0x4448266b715d7d99acd1e31dcab50d7119faa620d44c69b3f64f97d636634169",
Expand All @@ -161,6 +166,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x9c8531a41f9281633470c5e12b6c72c8930409a6433f26bf7b394a703d18512e",
"s": "0x7a0c6151fde75f10a7e4efdd17a21f1f25206559bd4b8cf7880e5bc30e1cfe33",
Expand All @@ -176,6 +182,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0186a0",
"maxFeePerGas": "0x0186a0",
"accessList": [],
"v": "0x01",
"r": "0xc8b85e158b532a0e3b3b5848fad0f4d5c6807805a4ce65e8591de13a62f3ac6a",
"s": "0x3e923eb1be030c3ca69623f31ad3a357368b1ccb7ee48ac8deec5cb5dc49cb0c",
Expand Down Expand Up @@ -217,6 +224,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x03e8",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x01",
"r": "0x113c54f83e1b1e5c689ba86d288ec0ce2877f350b71821c4c7a3f7073b46602c",
"s": "0x548848e711b86ceeb657fd0a0bf44b792f6665ed18ec8a04f498471e811f8f97",
Expand All @@ -232,6 +240,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x64",
"maxFeePerGas": "0x03e8",
"accessList": [],
"v": "0x00",
"r": "0x8d7ec1116399aab6e1297b09302b291d73c5898a0338fb62a46c74b037d15a15",
"s": "0x3cacc1a12eb47c261394443d490b8436f53a99d2109dac9ca5018cf531e6b29d",
Expand All @@ -247,6 +256,7 @@
"gasLimit": "0x0f4240",
"maxPriorityFeePerGas": "0x0186a0",
"maxFeePerGas": "0x0186a0",
"accessList": [],
"v": "0x01",
"r": "0x54bd3a30ee3c2182d92f30223adb53feb0f51d76970a2628d9479536ff3edfe9",
"s": "0x6f681aa0ad9362eeeafb981394526ca6425f3a24e1c7f44c413b68dd2e56e5d0",
Expand Down
Loading

0 comments on commit 8d796b9

Please sign in to comment.