diff --git a/src/ethereum/arrow_glacier/fork.py b/src/ethereum/arrow_glacier/fork.py index 818e48a838..b935f22960 100644 --- a/src/ethereum/arrow_glacier/fork.py +++ b/src/ethereum/arrow_glacier/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple, Union from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -417,6 +418,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) if isinstance(tx, FeeMarketTransaction): @@ -958,26 +960,29 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/berlin/fork.py b/src/ethereum/berlin/fork.py index 720f7e4c8e..51dbaa8a30 100644 --- a/src/ethereum/berlin/fork.py +++ b/src/ethereum/berlin/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple, Union from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -335,6 +336,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -839,22 +841,25 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/berlin/vm/precompiled_contracts/ecrecover.py b/src/ethereum/berlin/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/berlin/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/berlin/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/byzantium/fork.py b/src/ethereum/byzantium/fork.py index 610ec867a0..3487633ec5 100644 --- a/src/ethereum/byzantium/fork.py +++ b/src/ethereum/byzantium/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -329,6 +330,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -811,14 +813,20 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if v == 27 or v == 28: - public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) + try: + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/byzantium/vm/precompiled_contracts/ecrecover.py b/src/ethereum/byzantium/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/byzantium/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/byzantium/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/cancun/fork.py b/src/ethereum/cancun/fork.py index 7ae751cae3..86f35e5cd0 100644 --- a/src/ethereum/cancun/fork.py +++ b/src/ethereum/cancun/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Tuple, Union from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.exceptions import InvalidBlock @@ -383,8 +384,9 @@ def check_transaction( if tx.gas > gas_available: raise InvalidBlock - sender = recover_sender(chain_id, tx) - sender_account = get_account(state, sender) + sender_address = recover_sender(chain_id, tx) + + sender_account = get_account(state, sender_address) if isinstance(tx, (FeeMarketTransaction, BlobTransaction)): if tx.max_fee_per_gas < tx.max_priority_fee_per_gas: @@ -427,7 +429,7 @@ def check_transaction( if sender_account.code != bytearray(): raise InvalidBlock - return sender, effective_gas_price, blob_versioned_hashes + return sender_address, effective_gas_price, blob_versioned_hashes def make_receipt( @@ -953,30 +955,33 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) - elif isinstance(tx, BlobTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_4844(tx) - ) + elif isinstance(tx, BlobTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_4844(tx) + ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/cancun/vm/precompiled_contracts/ecrecover.py b/src/ethereum/cancun/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/cancun/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/cancun/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/constantinople/fork.py b/src/ethereum/constantinople/fork.py index dab9200777..90d4f4d920 100644 --- a/src/ethereum/constantinople/fork.py +++ b/src/ethereum/constantinople/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -329,6 +330,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -811,14 +813,20 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if v == 27 or v == 28: - public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) + try: + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/constantinople/vm/precompiled_contracts/ecrecover.py b/src/ethereum/constantinople/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/constantinople/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/constantinople/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/crypto/__init__.py b/src/ethereum/crypto/__init__.py index e676f81b3f..ac98a16b6e 100644 --- a/src/ethereum/crypto/__init__.py +++ b/src/ethereum/crypto/__init__.py @@ -1,3 +1,11 @@ """ Cryptographic primitives used in Ethereum. """ + + +class InvalidSignature(Exception): + """ + Thrown when a signature is invalid. + """ + + pass diff --git a/src/ethereum/crypto/elliptic_curve.py b/src/ethereum/crypto/elliptic_curve.py index 1b6c23b90f..d9c6f01859 100644 --- a/src/ethereum/crypto/elliptic_curve.py +++ b/src/ethereum/crypto/elliptic_curve.py @@ -8,9 +8,12 @@ import coincurve from ..base_types import U256, Bytes +from . import InvalidSignature from .finite_field import Field from .hash import Hash32 +SECP256K1B = 7 +SECP256K1P = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F SECP256K1N = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 F = TypeVar("F", bound=Field) @@ -37,6 +40,15 @@ def secp256k1_recover(r: U256, s: U256, v: U256, msg_hash: Hash32) -> Bytes: public_key : `ethereum.base_types.Bytes` Recovered public key. """ + is_square = pow( + pow(r, 3, SECP256K1P) + SECP256K1B, (SECP256K1P - 1) // 2, SECP256K1P + ) + + if is_square != 1: + raise InvalidSignature( + "r is not the x-coordinate of a point on the secp256k1 curve" + ) + r_bytes = r.to_be_bytes32() s_bytes = s.to_be_bytes32() @@ -44,9 +56,17 @@ def secp256k1_recover(r: U256, s: U256, v: U256, msg_hash: Hash32) -> Bytes: signature[32 - len(r_bytes) : 32] = r_bytes signature[64 - len(s_bytes) : 64] = s_bytes signature[64] = v - public_key = coincurve.PublicKey.from_signature_and_message( - bytes(signature), msg_hash, hasher=None - ) + + # If the recovery algorithm returns the point at infinity, + # the signature is considered invalid + # the below function will raise a ValueError. + try: + public_key = coincurve.PublicKey.from_signature_and_message( + bytes(signature), msg_hash, hasher=None + ) + except ValueError as e: + raise InvalidSignature from e + public_key = public_key.format(compressed=False)[1:] return public_key diff --git a/src/ethereum/dao_fork/fork.py b/src/ethereum/dao_fork/fork.py index a475de7d4e..6e9dc7aed5 100644 --- a/src/ethereum/dao_fork/fork.py +++ b/src/ethereum/dao_fork/fork.py @@ -18,6 +18,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -338,6 +339,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(tx) return sender_address @@ -810,7 +812,11 @@ def recover_sender(tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + try: + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.py b/src/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/frontier/fork.py b/src/ethereum/frontier/fork.py index 742bb64e01..c62c94b910 100644 --- a/src/ethereum/frontier/fork.py +++ b/src/ethereum/frontier/fork.py @@ -15,6 +15,7 @@ from dataclasses import dataclass from typing import List, Optional, Set, Tuple +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -318,6 +319,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(tx) return sender_address @@ -785,7 +787,11 @@ def recover_sender(tx: Transaction) -> Address: if 0 >= s or s >= SECP256K1N: raise InvalidBlock - public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + try: + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/frontier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/frontier/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/frontier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/frontier/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/genesis.py b/src/ethereum/genesis.py index 19d2ab8760..cf8e2592cf 100644 --- a/src/ethereum/genesis.py +++ b/src/ethereum/genesis.py @@ -263,6 +263,9 @@ def add_genesis_block( if has_field(hardfork.Header, "parent_beacon_block_root"): fields["parent_beacon_block_root"] = Hash32(b"\0" * 32) + if has_field(hardfork.Header, "requests_root"): + fields["requests_root"] = hardfork.root(hardfork.Trie(False, None)) + genesis_header = hardfork.Header(**fields) block_fields = { @@ -274,6 +277,9 @@ def add_genesis_block( if has_field(hardfork.Block, "withdrawals"): block_fields["withdrawals"] = () + if has_field(hardfork.Block, "requests"): + block_fields["requests"] = () + genesis_block = hardfork.Block(**block_fields) chain.blocks.append(genesis_block) diff --git a/src/ethereum/gray_glacier/fork.py b/src/ethereum/gray_glacier/fork.py index 4a80e96bdb..bf46487e8f 100644 --- a/src/ethereum/gray_glacier/fork.py +++ b/src/ethereum/gray_glacier/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple, Union from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -417,6 +418,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) if isinstance(tx, FeeMarketTransaction): @@ -958,26 +960,29 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/homestead/fork.py b/src/ethereum/homestead/fork.py index 46173ff765..52c10709e0 100644 --- a/src/ethereum/homestead/fork.py +++ b/src/ethereum/homestead/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -320,6 +321,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(tx) return sender_address @@ -792,7 +794,11 @@ def recover_sender(tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + try: + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/homestead/vm/precompiled_contracts/ecrecover.py b/src/ethereum/homestead/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/homestead/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/homestead/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/istanbul/fork.py b/src/ethereum/istanbul/fork.py index 945dffa498..23ae75d50a 100644 --- a/src/ethereum/istanbul/fork.py +++ b/src/ethereum/istanbul/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -329,6 +330,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -812,14 +814,20 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if v == 27 or v == 28: - public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) + try: + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/istanbul/vm/precompiled_contracts/ecrecover.py b/src/ethereum/istanbul/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/istanbul/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/istanbul/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/london/fork.py b/src/ethereum/london/fork.py index 9aae34f0f0..4330ee0a02 100644 --- a/src/ethereum/london/fork.py +++ b/src/ethereum/london/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple, Union from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -425,6 +426,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) if isinstance(tx, FeeMarketTransaction): @@ -966,26 +968,29 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/london/vm/precompiled_contracts/ecrecover.py b/src/ethereum/london/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/london/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/london/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/muir_glacier/fork.py b/src/ethereum/muir_glacier/fork.py index 751c932139..815ec68bb7 100644 --- a/src/ethereum/muir_glacier/fork.py +++ b/src/ethereum/muir_glacier/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -329,6 +330,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -812,14 +814,20 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if v == 27 or v == 28: - public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) + try: + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.py b/src/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/paris/fork.py b/src/ethereum/paris/fork.py index 66e8f6c56b..41faaf0856 100644 --- a/src/ethereum/paris/fork.py +++ b/src/ethereum/paris/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Tuple, Union from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.exceptions import InvalidBlock @@ -332,6 +333,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) if isinstance(tx, FeeMarketTransaction): @@ -752,26 +754,29 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/paris/vm/precompiled_contracts/ecrecover.py b/src/ethereum/paris/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/paris/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/paris/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/prague/fork.py b/src/ethereum/prague/fork.py index be7472bf03..d0c1d0f73b 100644 --- a/src/ethereum/prague/fork.py +++ b/src/ethereum/prague/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Tuple, Union from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.exceptions import InvalidBlock @@ -402,8 +403,9 @@ def check_transaction( if tx.gas > gas_available: raise InvalidBlock - sender = recover_sender(chain_id, tx) - sender_account = get_account(state, sender) + sender_address = recover_sender(chain_id, tx) + + sender_account = get_account(state, sender_address) if isinstance(tx, (FeeMarketTransaction, BlobTransaction)): if tx.max_fee_per_gas < tx.max_priority_fee_per_gas: @@ -446,7 +448,7 @@ def check_transaction( if sender_account.code != bytearray(): raise InvalidBlock - return sender, effective_gas_price, blob_versioned_hashes + return sender_address, effective_gas_price, blob_versioned_hashes def make_receipt( @@ -1049,30 +1051,33 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) - elif isinstance(tx, BlobTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_4844(tx) - ) + elif isinstance(tx, BlobTransaction): + public_key = secp256k1_recover( + r, s, tx.y_parity, signing_hash_4844(tx) + ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/prague/vm/precompiled_contracts/ecrecover.py b/src/ethereum/prague/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/prague/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/prague/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/shanghai/fork.py b/src/ethereum/shanghai/fork.py index c713780981..bdb9bcd4e4 100644 --- a/src/ethereum/shanghai/fork.py +++ b/src/ethereum/shanghai/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Tuple, Union from ethereum.base_types import Bytes0, Bytes32 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.exceptions import InvalidBlock @@ -337,6 +338,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) if isinstance(tx, FeeMarketTransaction): @@ -783,26 +785,29 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if isinstance(tx, LegacyTransaction): - v = tx.v - if v == 27 or v == 28: + try: + if isinstance(tx, LegacyTransaction): + v = tx.v + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + elif isinstance(tx, AccessListTransaction): public_key = secp256k1_recover( - r, s, v - 27, signing_hash_pre155(tx) + r, s, tx.y_parity, signing_hash_2930(tx) ) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock + elif isinstance(tx, FeeMarketTransaction): public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + r, s, tx.y_parity, signing_hash_1559(tx) ) - elif isinstance(tx, AccessListTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_2930(tx) - ) - elif isinstance(tx, FeeMarketTransaction): - public_key = secp256k1_recover( - r, s, tx.y_parity, signing_hash_1559(tx) - ) + except InvalidSignature as e: + raise InvalidBlock from e return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/shanghai/vm/precompiled_contracts/ecrecover.py b/src/ethereum/shanghai/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/shanghai/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/shanghai/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/spurious_dragon/fork.py b/src/ethereum/spurious_dragon/fork.py index 8dd4f63755..1bc5609d18 100644 --- a/src/ethereum/spurious_dragon/fork.py +++ b/src/ethereum/spurious_dragon/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -325,6 +326,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(chain_id, tx) return sender_address @@ -807,14 +809,20 @@ def recover_sender(chain_id: U64, tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - if v == 27 or v == 28: - public_key = secp256k1_recover(r, s, v - 27, signing_hash_pre155(tx)) - else: - if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: - raise InvalidBlock - public_key = secp256k1_recover( - r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) - ) + try: + if v == 27 or v == 28: + public_key = secp256k1_recover( + r, s, v - 27, signing_hash_pre155(tx) + ) + else: + if v != 35 + chain_id * 2 and v != 36 + chain_id * 2: + raise InvalidBlock + public_key = secp256k1_recover( + r, s, v - 35 - chain_id * 2, signing_hash_155(tx, chain_id) + ) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.py b/src/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/src/ethereum/tangerine_whistle/fork.py b/src/ethereum/tangerine_whistle/fork.py index 46173ff765..52c10709e0 100644 --- a/src/ethereum/tangerine_whistle/fork.py +++ b/src/ethereum/tangerine_whistle/fork.py @@ -16,6 +16,7 @@ from typing import List, Optional, Set, Tuple from ethereum.base_types import Bytes0 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.ethash import dataset_size, generate_cache, hashimoto_light @@ -320,6 +321,7 @@ def check_transaction( """ if tx.gas > gas_available: raise InvalidBlock + sender_address = recover_sender(tx) return sender_address @@ -792,7 +794,11 @@ def recover_sender(tx: Transaction) -> Address: if 0 >= s or s > SECP256K1N // 2: raise InvalidBlock - public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + try: + public_key = secp256k1_recover(r, s, v - 27, signing_hash(tx)) + except InvalidSignature as e: + raise InvalidBlock from e + return Address(keccak256(public_key)[12:32]) diff --git a/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.py b/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.py index 664d1c145f..a8a36bf4c3 100644 --- a/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.py +++ b/src/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.py @@ -12,6 +12,7 @@ Implementation of the ECRECOVER precompiled contract. """ from ethereum.base_types import U256 +from ethereum.crypto import InvalidSignature from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover from ethereum.crypto.hash import Hash32, keccak256 from ethereum.utils.byte import left_pad_zero_bytes @@ -52,7 +53,7 @@ def ecrecover(evm: Evm) -> None: try: public_key = secp256k1_recover(r, s, v - 27, message_hash) - except ValueError: + except InvalidSignature: # unable to extract public key return diff --git a/whitelist.txt b/whitelist.txt index 9252af0ab5..5a0eb5d9b7 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -63,6 +63,8 @@ U32 U8 secp256k1 secp256k1n +secp256k1p +secp256k1b statetest subclasses iadd