Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/testing/src/execution_testing/forks/base_fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,15 @@ def __init_subclass__(
if base_fork_class != BaseFork:
base_fork_class._children.add(cls)
cls._enabled_eips |= base_fork_class._enabled_eips
# A fork inheriting from more than one fork enables the union of
# their EIPs; the first base alone leads the lineage above.
for base_class in cls.__bases__:
if (
issubclass(base_class, BaseFork)
and not base_class.is_eip()
and base_class is not BaseFork
):
cls._enabled_eips |= base_class._enabled_eips
eip_bases = [
base_class
for base_class in cls.__bases__
Expand Down
16 changes: 15 additions & 1 deletion src/ethereum/forks/monad_eight/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@

from typing import TYPE_CHECKING, Final

from ethereum_types.numeric import Uint
from ethereum_types.numeric import U64, Uint

from ethereum.exceptions import InvalidTransaction

if TYPE_CHECKING:
from .transactions import Transaction


class WrongChainIdError(InvalidTransaction):
"""
Chain identifier from a transaction does not match the executing chain. See
[EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""

def __init__(self, expected: U64, actual: U64):
super().__init__(f"expected chain_id `{expected}` but got `{actual}`")
self.expected = expected
self.actual = actual


class TransactionTypeError(InvalidTransaction):
"""
Unknown [EIP-2718] transaction type byte.
Expand Down
11 changes: 10 additions & 1 deletion src/ethereum/forks/monad_eight/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
NoBlobDataError,
PriorityFeeGreaterThanMaxFeeError,
TransactionTypeContractCreationError,
WrongChainIdError,
)
from .fork_types import Authorization, VersionedHash
from .requests import (
Expand Down Expand Up @@ -72,6 +73,7 @@
LegacyTransaction,
SetCodeTransaction,
Transaction,
chain_id,
decode_transaction,
encode_transaction,
get_transaction_hash,
Expand Down Expand Up @@ -467,7 +469,14 @@ def check_transaction(
if tx_blob_gas_used > blob_gas_available:
raise BlobGasLimitExceededError("blob gas limit exceeded")

sender_address = recover_sender(block_env.chain_id, tx)
tx_chain_id = chain_id(tx)
if tx_chain_id is not None and tx_chain_id != block_env.chain_id:
raise WrongChainIdError(
expected=block_env.chain_id,
actual=tx_chain_id,
)

sender_address = recover_sender(tx)
sender_account = get_account(tx_state, sender_address)

if isinstance(
Expand Down
36 changes: 27 additions & 9 deletions src/ethereum/forks/monad_eight/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,25 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
)


def recover_sender(chain_id: U64, tx: Transaction) -> Address:
def chain_id(tx: Transaction) -> None | U64:
"""
Extract the chain identifier from a transaction. See [EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""
if isinstance(tx, LegacyTransaction):
if tx.v == 27 or tx.v == 28:
return None

if tx.v < U256(35):
raise InvalidSignatureError("bad v")

return U64((tx.v - U256(35)) >> U256(1))
Comment thread
pdobacz marked this conversation as resolved.
else:
return tx.chain_id


def recover_sender(tx: Transaction) -> Address:
"""
Extracts the sender address from a transaction.

Expand All @@ -635,9 +653,9 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
signing hash of the transaction. The sender's public key can be obtained
with these two values and therefore the sender address can be retrieved.

This function takes chain_id and a transaction as parameters and returns
the address of the sender of the transaction. It raises an
`InvalidSignatureError` if the signature values (r, s, v) are invalid.
This function takes a transaction as a parameter and returns the address
of the sender of the transaction. It raises an `InvalidSignatureError` if
the signature values (r, s, v) are invalid.
"""
r, s = tx.r, tx.s
if U256(0) >= r or r >= SECP256K1N:
Expand All @@ -652,14 +670,14 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
r, s, v - U256(27), signing_hash_pre155(tx)
)
else:
chain_id_x2 = U256(chain_id) * U256(2)
if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
raise InvalidSignatureError("bad v")
assert v >= U256(35), "call chain_id before recover_sender"
tx_chain_id = U64((v - U256(35)) >> U256(1))
v = (v - U256(35)) & U256(1)
public_key = secp256k1_recover(
r,
s,
v - U256(35) - chain_id_x2,
signing_hash_155(tx, chain_id),
v,
signing_hash_155(tx, tx_chain_id),
)
elif isinstance(tx, AccessListTransaction):
if tx.y_parity not in (U256(0), U256(1)):
Expand Down
16 changes: 15 additions & 1 deletion src/ethereum/forks/monad_next/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@

from typing import TYPE_CHECKING, Final

from ethereum_types.numeric import Uint
from ethereum_types.numeric import U64, Uint

from ethereum.exceptions import InvalidTransaction

if TYPE_CHECKING:
from .transactions import Transaction


class WrongChainIdError(InvalidTransaction):
"""
Chain identifier from a transaction does not match the executing chain. See
[EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""

def __init__(self, expected: U64, actual: U64):
super().__init__(f"expected chain_id `{expected}` but got `{actual}`")
self.expected = expected
self.actual = actual


class TransactionTypeError(InvalidTransaction):
"""
Unknown [EIP-2718] transaction type byte.
Expand Down
11 changes: 10 additions & 1 deletion src/ethereum/forks/monad_next/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
NoBlobDataError,
PriorityFeeGreaterThanMaxFeeError,
TransactionTypeContractCreationError,
WrongChainIdError,
)
from .fork_types import Authorization, VersionedHash
from .requests import (
Expand Down Expand Up @@ -76,6 +77,7 @@
LegacyTransaction,
SetCodeTransaction,
Transaction,
chain_id,
decode_transaction,
encode_transaction,
get_transaction_hash,
Expand Down Expand Up @@ -482,7 +484,14 @@ def check_transaction(
if tx_blob_gas_used > blob_gas_available:
raise BlobGasLimitExceededError("blob gas limit exceeded")

sender_address = recover_sender(block_env.chain_id, tx)
tx_chain_id = chain_id(tx)
if tx_chain_id is not None and tx_chain_id != block_env.chain_id:
raise WrongChainIdError(
expected=block_env.chain_id,
actual=tx_chain_id,
)

sender_address = recover_sender(tx)
sender_account = get_account(tx_state, sender_address)

if isinstance(
Expand Down
36 changes: 27 additions & 9 deletions src/ethereum/forks/monad_next/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,25 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
)


def recover_sender(chain_id: U64, tx: Transaction) -> Address:
def chain_id(tx: Transaction) -> None | U64:
"""
Extract the chain identifier from a transaction. See [EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""
if isinstance(tx, LegacyTransaction):
if tx.v == 27 or tx.v == 28:
return None

if tx.v < U256(35):
raise InvalidSignatureError("bad v")

return U64((tx.v - U256(35)) >> U256(1))
else:
return tx.chain_id


def recover_sender(tx: Transaction) -> Address:
"""
Extracts the sender address from a transaction.

Expand All @@ -635,9 +653,9 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
signing hash of the transaction. The sender's public key can be obtained
with these two values and therefore the sender address can be retrieved.

This function takes chain_id and a transaction as parameters and returns
the address of the sender of the transaction. It raises an
`InvalidSignatureError` if the signature values (r, s, v) are invalid.
This function takes a transaction as a parameter and returns the address
of the sender of the transaction. It raises an `InvalidSignatureError` if
the signature values (r, s, v) are invalid.
"""
r, s = tx.r, tx.s
if U256(0) >= r or r >= SECP256K1N:
Expand All @@ -652,14 +670,14 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
r, s, v - U256(27), signing_hash_pre155(tx)
)
else:
chain_id_x2 = U256(chain_id) * U256(2)
if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
raise InvalidSignatureError("bad v")
assert v >= U256(35), "call chain_id before recover_sender"
tx_chain_id = U64((v - U256(35)) >> U256(1))
v = (v - U256(35)) & U256(1)
public_key = secp256k1_recover(
r,
s,
v - U256(35) - chain_id_x2,
signing_hash_155(tx, chain_id),
v,
signing_hash_155(tx, tx_chain_id),
)
elif isinstance(tx, AccessListTransaction):
if tx.y_parity not in (U256(0), U256(1)):
Expand Down
16 changes: 15 additions & 1 deletion src/ethereum/forks/monad_nine/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@

from typing import TYPE_CHECKING, Final

from ethereum_types.numeric import Uint
from ethereum_types.numeric import U64, Uint

from ethereum.exceptions import InvalidTransaction

if TYPE_CHECKING:
from .transactions import Transaction


class WrongChainIdError(InvalidTransaction):
"""
Chain identifier from a transaction does not match the executing chain. See
[EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""

def __init__(self, expected: U64, actual: U64):
super().__init__(f"expected chain_id `{expected}` but got `{actual}`")
self.expected = expected
self.actual = actual


class TransactionTypeError(InvalidTransaction):
"""
Unknown [EIP-2718] transaction type byte.
Expand Down
11 changes: 10 additions & 1 deletion src/ethereum/forks/monad_nine/fork.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
NoBlobDataError,
PriorityFeeGreaterThanMaxFeeError,
TransactionTypeContractCreationError,
WrongChainIdError,
)
from .fork_types import Authorization, VersionedHash
from .requests import (
Expand Down Expand Up @@ -73,6 +74,7 @@
LegacyTransaction,
SetCodeTransaction,
Transaction,
chain_id,
decode_transaction,
encode_transaction,
get_transaction_hash,
Expand Down Expand Up @@ -479,7 +481,14 @@ def check_transaction(
if tx_blob_gas_used > blob_gas_available:
raise BlobGasLimitExceededError("blob gas limit exceeded")

sender_address = recover_sender(block_env.chain_id, tx)
tx_chain_id = chain_id(tx)
if tx_chain_id is not None and tx_chain_id != block_env.chain_id:
raise WrongChainIdError(
expected=block_env.chain_id,
actual=tx_chain_id,
)

sender_address = recover_sender(tx)
sender_account = get_account(tx_state, sender_address)

if isinstance(
Expand Down
36 changes: 27 additions & 9 deletions src/ethereum/forks/monad_nine/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,25 @@ def calculate_intrinsic_cost(tx: Transaction) -> Tuple[Uint, Uint]:
)


def recover_sender(chain_id: U64, tx: Transaction) -> Address:
def chain_id(tx: Transaction) -> None | U64:
"""
Extract the chain identifier from a transaction. See [EIP-155].

[EIP-155]: https://eips.ethereum.org/EIPS/eip-155
"""
if isinstance(tx, LegacyTransaction):
if tx.v == 27 or tx.v == 28:
return None

if tx.v < U256(35):
raise InvalidSignatureError("bad v")

return U64((tx.v - U256(35)) >> U256(1))
else:
return tx.chain_id


def recover_sender(tx: Transaction) -> Address:
"""
Extracts the sender address from a transaction.

Expand All @@ -635,9 +653,9 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
signing hash of the transaction. The sender's public key can be obtained
with these two values and therefore the sender address can be retrieved.

This function takes chain_id and a transaction as parameters and returns
the address of the sender of the transaction. It raises an
`InvalidSignatureError` if the signature values (r, s, v) are invalid.
This function takes a transaction as a parameter and returns the address
of the sender of the transaction. It raises an `InvalidSignatureError` if
the signature values (r, s, v) are invalid.
"""
r, s = tx.r, tx.s
if U256(0) >= r or r >= SECP256K1N:
Expand All @@ -652,14 +670,14 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address:
r, s, v - U256(27), signing_hash_pre155(tx)
)
else:
chain_id_x2 = U256(chain_id) * U256(2)
if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
raise InvalidSignatureError("bad v")
assert v >= U256(35), "call chain_id before recover_sender"
tx_chain_id = U64((v - U256(35)) >> U256(1))
v = (v - U256(35)) & U256(1)
public_key = secp256k1_recover(
r,
s,
v - U256(35) - chain_id_x2,
signing_hash_155(tx, chain_id),
v,
signing_hash_155(tx, tx_chain_id),
)
elif isinstance(tx, AccessListTransaction):
if tx.y_parity not in (U256(0), U256(1)):
Expand Down
Loading