Skip to content

Commit 872bd2e

Browse files
committed
Move tx methods; add sig error (#1021)
1 parent 1adcc1b commit 872bd2e

File tree

35 files changed

+3354
-3306
lines changed

35 files changed

+3354
-3306
lines changed

src/ethereum/arrow_glacier/fork.py

Lines changed: 4 additions & 265 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
from dataclasses import dataclass
1616
from typing import List, Optional, Set, Tuple, Union
1717

18-
from ethereum_types.bytes import Bytes, Bytes0
18+
from ethereum_types.bytes import Bytes
1919
from ethereum_types.numeric import U64, U256, Uint
2020

21-
from ethereum.crypto.elliptic_curve import SECP256K1N, secp256k1_recover
2221
from ethereum.crypto.hash import Hash32, keccak256
2322
from ethereum.ethash import dataset_size, generate_cache, hashimoto_light
2423
from ethereum.exceptions import InvalidBlock, InvalidSenderError
@@ -39,18 +38,15 @@
3938
state_root,
4039
)
4140
from .transactions import (
42-
TX_ACCESS_LIST_ADDRESS_COST,
43-
TX_ACCESS_LIST_STORAGE_KEY_COST,
44-
TX_BASE_COST,
45-
TX_CREATE_COST,
46-
TX_DATA_COST_PER_NON_ZERO,
47-
TX_DATA_COST_PER_ZERO,
4841
AccessListTransaction,
4942
FeeMarketTransaction,
5043
LegacyTransaction,
5144
Transaction,
45+
calculate_intrinsic_cost,
5246
decode_transaction,
5347
encode_transaction,
48+
recover_sender,
49+
validate_transaction,
5450
)
5551
from .trie import Trie, root, trie_set
5652
from .utils.message import prepare_message
@@ -866,263 +862,6 @@ def process_transaction(
866862
return total_gas_used, output.logs, output.error
867863

868864

869-
def validate_transaction(tx: Transaction) -> bool:
870-
"""
871-
Verifies a transaction.
872-
873-
The gas in a transaction gets used to pay for the intrinsic cost of
874-
operations, therefore if there is insufficient gas then it would not
875-
be possible to execute a transaction and it will be declared invalid.
876-
877-
Additionally, the nonce of a transaction must not equal or exceed the
878-
limit defined in `EIP-2681 <https://eips.ethereum.org/EIPS/eip-2681>`_.
879-
In practice, defining the limit as ``2**64-1`` has no impact because
880-
sending ``2**64-1`` transactions is improbable. It's not strictly
881-
impossible though, ``2**64-1`` transactions is the entire capacity of the
882-
Ethereum blockchain at 2022 gas limits for a little over 22 years.
883-
884-
Parameters
885-
----------
886-
tx :
887-
Transaction to validate.
888-
889-
Returns
890-
-------
891-
verified : `bool`
892-
True if the transaction can be executed, or False otherwise.
893-
"""
894-
if calculate_intrinsic_cost(tx) > Uint(tx.gas):
895-
return False
896-
if tx.nonce >= U256(U64.MAX_VALUE):
897-
return False
898-
return True
899-
900-
901-
def calculate_intrinsic_cost(tx: Transaction) -> Uint:
902-
"""
903-
Calculates the gas that is charged before execution is started.
904-
905-
The intrinsic cost of the transaction is charged before execution has
906-
begun. Functions/operations in the EVM cost money to execute so this
907-
intrinsic cost is for the operations that need to be paid for as part of
908-
the transaction. Data transfer, for example, is part of this intrinsic
909-
cost. It costs ether to send data over the wire and that ether is
910-
accounted for in the intrinsic cost calculated in this function. This
911-
intrinsic cost must be calculated and paid for before execution in order
912-
for all operations to be implemented.
913-
914-
Parameters
915-
----------
916-
tx :
917-
Transaction to compute the intrinsic cost of.
918-
919-
Returns
920-
-------
921-
verified : `ethereum.base_types.Uint`
922-
The intrinsic cost of the transaction.
923-
"""
924-
data_cost = 0
925-
926-
for byte in tx.data:
927-
if byte == 0:
928-
data_cost += TX_DATA_COST_PER_ZERO
929-
else:
930-
data_cost += TX_DATA_COST_PER_NON_ZERO
931-
932-
if tx.to == Bytes0(b""):
933-
create_cost = TX_CREATE_COST
934-
else:
935-
create_cost = 0
936-
937-
access_list_cost = 0
938-
if isinstance(tx, (AccessListTransaction, FeeMarketTransaction)):
939-
for _address, keys in tx.access_list:
940-
access_list_cost += TX_ACCESS_LIST_ADDRESS_COST
941-
access_list_cost += len(keys) * TX_ACCESS_LIST_STORAGE_KEY_COST
942-
943-
return Uint(TX_BASE_COST + data_cost + create_cost + access_list_cost)
944-
945-
946-
def recover_sender(chain_id: U64, tx: Transaction) -> Address:
947-
"""
948-
Extracts the sender address from a transaction.
949-
950-
The v, r, and s values are the three parts that make up the signature
951-
of a transaction. In order to recover the sender of a transaction the two
952-
components needed are the signature (``v``, ``r``, and ``s``) and the
953-
signing hash of the transaction. The sender's public key can be obtained
954-
with these two values and therefore the sender address can be retrieved.
955-
956-
Parameters
957-
----------
958-
tx :
959-
Transaction of interest.
960-
chain_id :
961-
ID of the executing chain.
962-
963-
Returns
964-
-------
965-
sender : `ethereum.fork_types.Address`
966-
The address of the account that signed the transaction.
967-
"""
968-
r, s = tx.r, tx.s
969-
if U256(0) >= r or r >= SECP256K1N:
970-
raise InvalidBlock
971-
if U256(0) >= s or s > SECP256K1N // U256(2):
972-
raise InvalidBlock
973-
974-
if isinstance(tx, LegacyTransaction):
975-
v = tx.v
976-
if v == 27 or v == 28:
977-
public_key = secp256k1_recover(
978-
r, s, v - U256(27), signing_hash_pre155(tx)
979-
)
980-
else:
981-
chain_id_x2 = U256(chain_id) * U256(2)
982-
if v != U256(35) + chain_id_x2 and v != U256(36) + chain_id_x2:
983-
raise InvalidBlock
984-
public_key = secp256k1_recover(
985-
r,
986-
s,
987-
v - U256(35) - chain_id_x2,
988-
signing_hash_155(tx, chain_id),
989-
)
990-
elif isinstance(tx, AccessListTransaction):
991-
public_key = secp256k1_recover(
992-
r, s, tx.y_parity, signing_hash_2930(tx)
993-
)
994-
elif isinstance(tx, FeeMarketTransaction):
995-
public_key = secp256k1_recover(
996-
r, s, tx.y_parity, signing_hash_1559(tx)
997-
)
998-
999-
return Address(keccak256(public_key)[12:32])
1000-
1001-
1002-
def signing_hash_pre155(tx: LegacyTransaction) -> Hash32:
1003-
"""
1004-
Compute the hash of a transaction used in a legacy (pre EIP 155) signature.
1005-
1006-
Parameters
1007-
----------
1008-
tx :
1009-
Transaction of interest.
1010-
1011-
Returns
1012-
-------
1013-
hash : `ethereum.crypto.hash.Hash32`
1014-
Hash of the transaction.
1015-
"""
1016-
return keccak256(
1017-
rlp.encode(
1018-
(
1019-
tx.nonce,
1020-
tx.gas_price,
1021-
tx.gas,
1022-
tx.to,
1023-
tx.value,
1024-
tx.data,
1025-
)
1026-
)
1027-
)
1028-
1029-
1030-
def signing_hash_155(tx: LegacyTransaction, chain_id: U64) -> Hash32:
1031-
"""
1032-
Compute the hash of a transaction used in a EIP 155 signature.
1033-
1034-
Parameters
1035-
----------
1036-
tx :
1037-
Transaction of interest.
1038-
chain_id :
1039-
The id of the current chain.
1040-
1041-
Returns
1042-
-------
1043-
hash : `ethereum.crypto.hash.Hash32`
1044-
Hash of the transaction.
1045-
"""
1046-
return keccak256(
1047-
rlp.encode(
1048-
(
1049-
tx.nonce,
1050-
tx.gas_price,
1051-
tx.gas,
1052-
tx.to,
1053-
tx.value,
1054-
tx.data,
1055-
chain_id,
1056-
Uint(0),
1057-
Uint(0),
1058-
)
1059-
)
1060-
)
1061-
1062-
1063-
def signing_hash_2930(tx: AccessListTransaction) -> Hash32:
1064-
"""
1065-
Compute the hash of a transaction used in a EIP 2930 signature.
1066-
1067-
Parameters
1068-
----------
1069-
tx :
1070-
Transaction of interest.
1071-
1072-
Returns
1073-
-------
1074-
hash : `ethereum.crypto.hash.Hash32`
1075-
Hash of the transaction.
1076-
"""
1077-
return keccak256(
1078-
b"\x01"
1079-
+ rlp.encode(
1080-
(
1081-
tx.chain_id,
1082-
tx.nonce,
1083-
tx.gas_price,
1084-
tx.gas,
1085-
tx.to,
1086-
tx.value,
1087-
tx.data,
1088-
tx.access_list,
1089-
)
1090-
)
1091-
)
1092-
1093-
1094-
def signing_hash_1559(tx: FeeMarketTransaction) -> Hash32:
1095-
"""
1096-
Compute the hash of a transaction used in a EIP 1559 signature.
1097-
1098-
Parameters
1099-
----------
1100-
tx :
1101-
Transaction of interest.
1102-
1103-
Returns
1104-
-------
1105-
hash : `ethereum.crypto.hash.Hash32`
1106-
Hash of the transaction.
1107-
"""
1108-
return keccak256(
1109-
b"\x02"
1110-
+ rlp.encode(
1111-
(
1112-
tx.chain_id,
1113-
tx.nonce,
1114-
tx.max_priority_fee_per_gas,
1115-
tx.max_fee_per_gas,
1116-
tx.gas,
1117-
tx.to,
1118-
tx.value,
1119-
tx.data,
1120-
tx.access_list,
1121-
)
1122-
)
1123-
)
1124-
1125-
1126865
def compute_header_hash(header: Header) -> Hash32:
1127866
"""
1128867
Computes the hash of a block header.

0 commit comments

Comments
 (0)