Skip to content

Commit dd5990d

Browse files
souradeep-dasSamWilsn
authored andcommitted
add changes for all forks
1 parent 2d2e8d9 commit dd5990d

File tree

23 files changed

+471
-85
lines changed

23 files changed

+471
-85
lines changed

src/ethereum/arrow_glacier/exceptions.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from typing import Final
66

7+
from ethereum_types.numeric import Uint
8+
79
from ethereum.exceptions import InvalidTransaction
810

911

@@ -22,3 +24,35 @@ class TransactionTypeError(InvalidTransaction):
2224
def __init__(self, transaction_type: int):
2325
super().__init__(f"unknown transaction type `{transaction_type}`")
2426
self.transaction_type = transaction_type
27+
28+
29+
class InsufficientMaxFeePerGasError(InvalidTransaction):
30+
"""
31+
The maximum fee per gas is insufficient for the transaction.
32+
"""
33+
34+
transaction_max_fee_per_gas: Final[Uint]
35+
"""
36+
The maximum fee per gas specified in the transaction.
37+
"""
38+
39+
block_base_fee_per_gas: Final[Uint]
40+
"""
41+
The base fee per gas of the block in which the transaction is included.
42+
"""
43+
44+
def __init__(
45+
self, transaction_max_fee_per_gas: Uint, block_base_fee_per_gas: Uint
46+
):
47+
super().__init__(
48+
f"Insufficient max fee per gas "
49+
f"({transaction_max_fee_per_gas} < {block_base_fee_per_gas})"
50+
)
51+
self.transaction_max_fee_per_gas = transaction_max_fee_per_gas
52+
self.block_base_fee_per_gas = block_base_fee_per_gas
53+
54+
55+
class PriorityFeeGreaterThanMaxFeeError(InvalidTransaction):
56+
"""
57+
The priority fee is greater than the maximum fee per gas.
58+
"""

src/ethereum/arrow_glacier/fork.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@
3333
from . import vm
3434
from .blocks import Block, Header, Log, Receipt, encode_receipt
3535
from .bloom import logs_bloom
36+
from .exceptions import (
37+
InsufficientMaxFeePerGasError,
38+
PriorityFeeGreaterThanMaxFeeError,
39+
)
3640
from .fork_types import Address
3741
from .state import (
3842
State,
@@ -454,9 +458,13 @@ def check_transaction(
454458

455459
if isinstance(tx, FeeMarketTransaction):
456460
if tx.max_fee_per_gas < tx.max_priority_fee_per_gas:
457-
raise InvalidBlock
461+
raise PriorityFeeGreaterThanMaxFeeError(
462+
"priority fee greater than max fee"
463+
)
458464
if tx.max_fee_per_gas < block_env.base_fee_per_gas:
459-
raise InvalidBlock
465+
raise InsufficientMaxFeePerGasError(
466+
tx.max_fee_per_gas, block_env.base_fee_per_gas
467+
)
460468

461469
priority_fee_per_gas = min(
462470
tx.max_priority_fee_per_gas,

src/ethereum/berlin/fork.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,11 @@
2222
from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
2323
from ethereum.exceptions import (
2424
EthereumException,
25+
GasUsedExceedsLimitError,
26+
InsufficientBalanceError,
2527
InvalidBlock,
2628
InvalidSenderError,
29+
NonceMismatchError,
2730
)
2831

2932
from . import vm
@@ -368,16 +371,18 @@ def check_transaction(
368371
"""
369372
gas_available = block_env.block_gas_limit - block_output.block_gas_used
370373
if tx.gas > gas_available:
371-
raise InvalidBlock
374+
raise GasUsedExceedsLimitError("gas used exceeds limit")
372375
sender_address = recover_sender(block_env.chain_id, tx)
373376
sender_account = get_account(block_env.state, sender_address)
374377

375378
max_gas_fee = tx.gas * tx.gas_price
376379

377-
if sender_account.nonce != tx.nonce:
378-
raise InvalidBlock
380+
if sender_account.nonce > Uint(tx.nonce):
381+
raise NonceMismatchError("nonce too low")
382+
elif sender_account.nonce < Uint(tx.nonce):
383+
raise NonceMismatchError("nonce too high")
379384
if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
380-
raise InvalidBlock
385+
raise InsufficientBalanceError("insufficient sender balance")
381386
if sender_account.code:
382387
raise InvalidSenderError("not EOA")
383388

src/ethereum/byzantium/fork.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
2222
from ethereum.exceptions import (
2323
EthereumException,
24+
GasUsedExceedsLimitError,
25+
InsufficientBalanceError,
2426
InvalidBlock,
2527
InvalidSenderError,
28+
NonceMismatchError,
2629
)
2730

2831
from . import vm
@@ -363,16 +366,18 @@ def check_transaction(
363366
"""
364367
gas_available = block_env.block_gas_limit - block_output.block_gas_used
365368
if tx.gas > gas_available:
366-
raise InvalidBlock
369+
raise GasUsedExceedsLimitError("gas used exceeds limit")
367370
sender_address = recover_sender(block_env.chain_id, tx)
368371
sender_account = get_account(block_env.state, sender_address)
369372

370373
max_gas_fee = tx.gas * tx.gas_price
371374

372-
if sender_account.nonce != tx.nonce:
373-
raise InvalidBlock
375+
if sender_account.nonce > Uint(tx.nonce):
376+
raise NonceMismatchError("nonce too low")
377+
elif sender_account.nonce < Uint(tx.nonce):
378+
raise NonceMismatchError("nonce too high")
374379
if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
375-
raise InvalidBlock
380+
raise InsufficientBalanceError("insufficient sender balance")
376381
if sender_account.code:
377382
raise InvalidSenderError("not EOA")
378383

src/ethereum/cancun/exceptions.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from typing import Final
66

7+
from ethereum_types.numeric import Uint
8+
79
from ethereum.exceptions import InvalidTransaction
810

911

@@ -24,7 +26,75 @@ def __init__(self, transaction_type: int):
2426
self.transaction_type = transaction_type
2527

2628

29+
class TransactionTypeContractCreationError(InvalidTransaction):
30+
"""
31+
Transaction type is not allowed for contract creation.
32+
"""
33+
34+
transaction_type: Final[int]
35+
"""
36+
The type byte of the transaction that caused the error.
37+
"""
38+
39+
def __init__(self, transaction_type: int):
40+
super().__init__(
41+
f"transaction type `{transaction_type}` not allowed for "
42+
"contract creation"
43+
)
44+
self.transaction_type = transaction_type
45+
46+
47+
class BlobGasLimitExceededError(InvalidTransaction):
48+
"""
49+
The blob gas limit for the transaction exceeds the maximum allowed.
50+
"""
51+
52+
2753
class InsufficientMaxFeePerBlobGasError(InvalidTransaction):
2854
"""
2955
The maximum fee per blob gas is insufficient for the transaction.
3056
"""
57+
58+
59+
class InsufficientMaxFeePerGasError(InvalidTransaction):
60+
"""
61+
The maximum fee per gas is insufficient for the transaction.
62+
"""
63+
64+
transaction_max_fee_per_gas: Final[Uint]
65+
"""
66+
The maximum fee per gas specified in the transaction.
67+
"""
68+
69+
block_base_fee_per_gas: Final[Uint]
70+
"""
71+
The base fee per gas of the block in which the transaction is included.
72+
"""
73+
74+
def __init__(
75+
self, transaction_max_fee_per_gas: Uint, block_base_fee_per_gas: Uint
76+
):
77+
super().__init__(
78+
f"Insufficient max fee per gas "
79+
f"({transaction_max_fee_per_gas} < {block_base_fee_per_gas})"
80+
)
81+
self.transaction_max_fee_per_gas = transaction_max_fee_per_gas
82+
self.block_base_fee_per_gas = block_base_fee_per_gas
83+
84+
85+
class InvalidBlobVersionedHashError(InvalidTransaction):
86+
"""
87+
The versioned hash of the blob is invalid.
88+
"""
89+
90+
91+
class NoBlobDataError(InvalidTransaction):
92+
"""
93+
The transaction does not contain any blob data.
94+
"""
95+
96+
97+
class PriorityFeeGreaterThanMaxFeeError(InvalidTransaction):
98+
"""
99+
The priority fee is greater than the maximum fee per gas.
100+
"""

src/ethereum/cancun/fork.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,25 @@
2222
from ethereum.crypto.hash import Hash32, keccak256
2323
from ethereum.exceptions import (
2424
EthereumException,
25+
GasUsedExceedsLimitError,
26+
InsufficientBalanceError,
2527
InvalidBlock,
2628
InvalidSenderError,
29+
NonceMismatchError,
2730
)
2831

2932
from . import vm
3033
from .blocks import Block, Header, Log, Receipt, Withdrawal, encode_receipt
3134
from .bloom import logs_bloom
32-
from .exceptions import InsufficientMaxFeePerBlobGasError
35+
from .exceptions import (
36+
BlobGasLimitExceededError,
37+
InsufficientMaxFeePerBlobGasError,
38+
InsufficientMaxFeePerGasError,
39+
InvalidBlobVersionedHashError,
40+
NoBlobDataError,
41+
PriorityFeeGreaterThanMaxFeeError,
42+
TransactionTypeContractCreationError,
43+
)
3344
from .fork_types import Account, Address, VersionedHash
3445
from .state import (
3546
State,
@@ -383,20 +394,24 @@ def check_transaction(
383394
blob_gas_available = MAX_BLOB_GAS_PER_BLOCK - block_output.blob_gas_used
384395

385396
if tx.gas > gas_available:
386-
raise InvalidBlock
397+
raise GasUsedExceedsLimitError("gas used exceeds limit")
387398

388399
tx_blob_gas_used = calculate_total_blob_gas(tx)
389400
if tx_blob_gas_used > blob_gas_available:
390-
raise InvalidBlock
401+
raise BlobGasLimitExceededError("blob gas limit exceeded")
391402

392403
sender_address = recover_sender(block_env.chain_id, tx)
393404
sender_account = get_account(block_env.state, sender_address)
394405

395406
if isinstance(tx, (FeeMarketTransaction, BlobTransaction)):
396407
if tx.max_fee_per_gas < tx.max_priority_fee_per_gas:
397-
raise InvalidBlock
408+
raise PriorityFeeGreaterThanMaxFeeError(
409+
"priority fee greater than max fee"
410+
)
398411
if tx.max_fee_per_gas < block_env.base_fee_per_gas:
399-
raise InvalidBlock
412+
raise InsufficientMaxFeePerGasError(
413+
tx.max_fee_per_gas, block_env.base_fee_per_gas
414+
)
400415

401416
priority_fee_per_gas = min(
402417
tx.max_priority_fee_per_gas,
@@ -412,12 +427,14 @@ def check_transaction(
412427

413428
if isinstance(tx, BlobTransaction):
414429
if not isinstance(tx.to, Address):
415-
raise InvalidBlock
430+
raise TransactionTypeContractCreationError(tx[0])
416431
if len(tx.blob_versioned_hashes) == 0:
417-
raise InvalidBlock
432+
raise NoBlobDataError("no blob data in transaction")
418433
for blob_versioned_hash in tx.blob_versioned_hashes:
419434
if blob_versioned_hash[0:1] != VERSIONED_HASH_VERSION_KZG:
420-
raise InvalidBlock
435+
raise InvalidBlobVersionedHashError(
436+
"invalid blob versioned hash"
437+
)
421438

422439
blob_gas_price = calculate_blob_gas_price(block_env.excess_blob_gas)
423440
if Uint(tx.max_fee_per_blob_gas) < blob_gas_price:
@@ -431,10 +448,12 @@ def check_transaction(
431448
blob_versioned_hashes = tx.blob_versioned_hashes
432449
else:
433450
blob_versioned_hashes = ()
434-
if sender_account.nonce != tx.nonce:
435-
raise InvalidBlock
451+
if sender_account.nonce > Uint(tx.nonce):
452+
raise NonceMismatchError("nonce too low")
453+
elif sender_account.nonce < Uint(tx.nonce):
454+
raise NonceMismatchError("nonce too high")
436455
if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
437-
raise InvalidBlock
456+
raise InsufficientBalanceError("insufficient sender balance")
438457
if sender_account.code:
439458
raise InvalidSenderError("not EOA")
440459

src/ethereum/constantinople/fork.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
2222
from ethereum.exceptions import (
2323
EthereumException,
24+
GasUsedExceedsLimitError,
25+
InsufficientBalanceError,
2426
InvalidBlock,
2527
InvalidSenderError,
28+
NonceMismatchError,
2629
)
2730

2831
from . import vm
@@ -363,16 +366,18 @@ def check_transaction(
363366
"""
364367
gas_available = block_env.block_gas_limit - block_output.block_gas_used
365368
if tx.gas > gas_available:
366-
raise InvalidBlock
369+
raise GasUsedExceedsLimitError("gas used exceeds limit")
367370
sender_address = recover_sender(block_env.chain_id, tx)
368371
sender_account = get_account(block_env.state, sender_address)
369372

370373
max_gas_fee = tx.gas * tx.gas_price
371374

372-
if sender_account.nonce != tx.nonce:
373-
raise InvalidBlock
375+
if sender_account.nonce > Uint(tx.nonce):
376+
raise NonceMismatchError("nonce too low")
377+
elif sender_account.nonce < Uint(tx.nonce):
378+
raise NonceMismatchError("nonce too high")
374379
if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
375-
raise InvalidBlock
380+
raise InsufficientBalanceError("insufficient sender balance")
376381
if sender_account.code:
377382
raise InvalidSenderError("not EOA")
378383

src/ethereum/dao_fork/fork.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@
2222

2323
from ethereum.crypto.hash import Hash32, keccak256
2424
from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
25-
from ethereum.exceptions import InvalidBlock, InvalidSenderError
25+
from ethereum.exceptions import (
26+
GasUsedExceedsLimitError,
27+
InsufficientBalanceError,
28+
InvalidBlock,
29+
InvalidSenderError,
30+
NonceMismatchError,
31+
)
2632

2733
from . import FORK_CRITERIA, vm
2834
from .blocks import Block, Header, Log, Receipt
@@ -372,16 +378,18 @@ def check_transaction(
372378
"""
373379
gas_available = block_env.block_gas_limit - block_output.block_gas_used
374380
if tx.gas > gas_available:
375-
raise InvalidBlock
381+
raise GasUsedExceedsLimitError("gas used exceeds limit")
376382
sender_address = recover_sender(tx)
377383
sender_account = get_account(block_env.state, sender_address)
378384

379385
max_gas_fee = tx.gas * tx.gas_price
380386

381-
if sender_account.nonce != tx.nonce:
382-
raise InvalidBlock
387+
if sender_account.nonce > Uint(tx.nonce):
388+
raise NonceMismatchError("nonce too low")
389+
elif sender_account.nonce < Uint(tx.nonce):
390+
raise NonceMismatchError("nonce too high")
383391
if Uint(sender_account.balance) < max_gas_fee + Uint(tx.value):
384-
raise InvalidBlock
392+
raise InsufficientBalanceError("insufficient sender balance")
385393
if sender_account.code:
386394
raise InvalidSenderError("not EOA")
387395

0 commit comments

Comments
 (0)