Skip to content

Commit

Permalink
handle test edge cases
Browse files Browse the repository at this point in the history
This commit handles a couple of edge cases

1. There are some error messages in the test fixtures that could raise RLPDecodingError or InvalidBlock depending on the context. For example TR_TypeNotSupported. If we try to include a typed transaction in Istanbul, it causes an RLPDecodingError. However, if we include a type 2 transaction in Berlin, it won't raise a RLPDecodingError since type1 and type2 are indistinguishable while decoding the rlp. In this case, it raises an InvalidBlock Exception. Therefore we stop making a distinction between these cases in the context of testing.

2. The test HighGasPrice raises a ValueError. We just raise a InvalidBlock from it.
  • Loading branch information
gurukamath authored and SamWilsn committed Jun 27, 2023
1 parent f210ac4 commit a6c94f3
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 61 deletions.
12 changes: 8 additions & 4 deletions src/ethereum/arrow_glacier/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ def check_transaction(

if isinstance(tx, FeeMarketTransaction):
ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)

priority_fee_per_gas = min(
tx.max_priority_fee_per_gas,
Expand Down Expand Up @@ -762,10 +763,13 @@ def process_transaction(
sender = env.origin
sender_account = get_account(env.state, sender)

if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
try:
if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e

ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/berlin/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/byzantium/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/constantinople/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/dao_fork/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/frontier/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
12 changes: 8 additions & 4 deletions src/ethereum/gray_glacier/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ def check_transaction(

if isinstance(tx, FeeMarketTransaction):
ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)

priority_fee_per_gas = min(
tx.max_priority_fee_per_gas,
Expand Down Expand Up @@ -762,10 +763,13 @@ def process_transaction(
sender = env.origin
sender_account = get_account(env.state, sender)

if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
try:
if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e

ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/homestead/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/istanbul/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
12 changes: 8 additions & 4 deletions src/ethereum/london/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ def check_transaction(

if isinstance(tx, FeeMarketTransaction):
ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)

priority_fee_per_gas = min(
tx.max_priority_fee_per_gas,
Expand Down Expand Up @@ -770,10 +771,13 @@ def process_transaction(
sender = env.origin
sender_account = get_account(env.state, sender)

if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
try:
if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e

ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/muir_glacier/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
12 changes: 8 additions & 4 deletions src/ethereum/paris/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ def check_transaction(

if isinstance(tx, FeeMarketTransaction):
ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)

priority_fee_per_gas = min(
tx.max_priority_fee_per_gas,
Expand Down Expand Up @@ -550,10 +551,13 @@ def process_transaction(
sender = env.origin
sender_account = get_account(env.state, sender)

if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
try:
if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e

ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
Expand Down
12 changes: 8 additions & 4 deletions src/ethereum/shanghai/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,7 @@ def check_transaction(

if isinstance(tx, FeeMarketTransaction):
ensure(tx.max_fee_per_gas >= tx.max_priority_fee_per_gas, InvalidBlock)
ensure(tx.max_fee_per_gas >= base_fee_per_gas, InvalidBlock)

priority_fee_per_gas = min(
tx.max_priority_fee_per_gas,
Expand Down Expand Up @@ -571,10 +572,13 @@ def process_transaction(
sender = env.origin
sender_account = get_account(env.state, sender)

if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
try:
if isinstance(tx, FeeMarketTransaction):
gas_fee = tx.gas * tx.max_fee_per_gas
else:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e

ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/spurious_dragon/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
5 changes: 4 additions & 1 deletion src/ethereum/tangerine_whistle/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,10 @@ def process_transaction(

sender = env.origin
sender_account = get_account(env.state, sender)
gas_fee = tx.gas * tx.gas_price
try:
gas_fee = tx.gas * tx.gas_price
except ValueError as e:
raise InvalidBlock from e
ensure(sender_account.nonce == tx.nonce, InvalidBlock)
ensure(sender_account.balance >= gas_fee + tx.value, InvalidBlock)
ensure(sender_account.code == bytearray(), InvalidBlock)
Expand Down
49 changes: 18 additions & 31 deletions tests/helpers/load_state_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,10 @@

from ethereum import rlp
from ethereum.base_types import U64
from ethereum.exceptions import InvalidBlock, RLPDecodingError
from ethereum.exceptions import InvalidBlock
from ethereum.utils.hexadecimal import hex_to_bytes
from ethereum_spec_tools.evm_tools.fixture_loader import Load

RLP_DECODING_EXCEPTIONS = (
"RLP_VALUESIZE_MORE_AVAILABLEINPUTLENGTH",
"RLP_ExpectedAsList",
"INPUT_UNMARSHAL_SIZE_ERROR",
"RLP_BODY_UNMARSHAL_ERROR",
"INPUT_UNMARSHAL_ERROR",
)


class NoTestsFound(Exception):
"""
Expand Down Expand Up @@ -70,36 +62,21 @@ def run_blockchain_st_test(test_case: Dict, load: Load) -> None:
chain_id=U64(json_data["genesisBlockHeader"].get("chainId", 1)),
)

mock_pow = json_data["sealEngine"] == "NoProof" and not load.proof_of_stake

for json_block in json_data["blocks"]:
block_exception = None
for key, value in json_block.items():
if key.startswith("expectException"):
block_exception = value
break

if block_exception in RLP_DECODING_EXCEPTIONS:
with pytest.raises(RLPDecodingError):
load.json_to_block(json_block)
return
else:
(
block,
block_header_hash,
block_rlp,
) = load.json_to_block(json_block)

assert rlp.rlp_hash(block.header) == block_header_hash
assert rlp.encode(cast(rlp.RLP, block)) == block_rlp

mock_pow = (
json_data["sealEngine"] == "NoProof" and not load.proof_of_stake
)
if block_exception is None:
add_block_to_chain(chain, block, load, mock_pow)
else:
if block_exception:
with pytest.raises(InvalidBlock):
add_block_to_chain(chain, block, load, mock_pow)
add_block_to_chain(chain, json_block, load, mock_pow)
return
else:
add_block_to_chain(chain, json_block, load, mock_pow)

last_block_hash = hex_to_bytes(json_data["lastblockhash"])
assert rlp.rlp_hash(chain.blocks[-1].header) == last_block_hash
Expand All @@ -111,8 +88,18 @@ def run_blockchain_st_test(test_case: Dict, load: Load) -> None:


def add_block_to_chain(
chain: Any, block: Any, load: Load, mock_pow: bool
chain: Any, json_block: Any, load: Load, mock_pow: bool
) -> None:

(
block,
block_header_hash,
block_rlp,
) = load.json_to_block(json_block)

assert rlp.rlp_hash(block.header) == block_header_hash
assert rlp.encode(cast(rlp.RLP, block)) == block_rlp

if not mock_pow:
load.state_transition(chain, block)
else:
Expand Down

0 comments on commit a6c94f3

Please sign in to comment.