Skip to content

Commit

Permalink
Upgrade eth-account
Browse files Browse the repository at this point in the history
  • Loading branch information
B3nac committed Jun 3, 2023
1 parent 2d8cd0c commit 04f4cec
Show file tree
Hide file tree
Showing 15 changed files with 759 additions and 656 deletions.
78 changes: 45 additions & 33 deletions eth_account/_utils/legacy_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@

def serializable_unsigned_transaction_from_dict(transaction_dict):
transaction_dict = set_transaction_type_if_needed(transaction_dict)
if 'type' in transaction_dict:
if "type" in transaction_dict:
# We delegate to TypedTransaction, which will carry out validation & formatting.
return TypedTransaction.from_dict(transaction_dict)

Expand All @@ -49,7 +49,7 @@ def serializable_unsigned_transaction_from_dict(transaction_dict):
chain_id_to_v,
apply_formatters_to_dict(LEGACY_TRANSACTION_FORMATTERS),
)
if 'v' in filled_transaction:
if "v" in filled_transaction:
serializer = Transaction
else:
serializer = UnsignedTransaction
Expand All @@ -58,36 +58,40 @@ def serializable_unsigned_transaction_from_dict(transaction_dict):

def encode_transaction(unsigned_transaction, vrs):
(v, r, s) = vrs
chain_naive_transaction = dissoc(unsigned_transaction.as_dict(), 'v', 'r', 's')
chain_naive_transaction = dissoc(unsigned_transaction.as_dict(), "v", "r", "s")
if isinstance(unsigned_transaction, TypedTransaction):
# Typed transaction have their own encoding format, so we must delegate the encoding.
chain_naive_transaction['v'] = v
chain_naive_transaction['r'] = r
chain_naive_transaction['s'] = s
# Typed transaction have their own encoding format,
# so we must delegate the encoding.
chain_naive_transaction["v"] = v
chain_naive_transaction["r"] = r
chain_naive_transaction["s"] = s
signed_typed_transaction = TypedTransaction.from_dict(chain_naive_transaction)
return signed_typed_transaction.encode()
signed_transaction = Transaction(v=v, r=r, s=s, **chain_naive_transaction)
return rlp.encode(signed_transaction)


TRANSACTION_DEFAULTS = {
'to': b'',
'value': 0,
'data': b'',
'chainId': None,
"to": b"",
"value": 0,
"data": b"",
"chainId": None,
}

ALLOWED_TRANSACTION_KEYS = {
'nonce',
'gasPrice',
'gas',
'to',
'value',
'data',
'chainId', # set chainId to None if you want a transaction that can be replayed across networks
"nonce",
"gasPrice",
"gas",
"to",
"value",
"data",
# set chainId to None if you want a transaction that can be replayed across networks
"chainId",
}

REQUIRED_TRANSACTION_KEYS = ALLOWED_TRANSACTION_KEYS.difference(TRANSACTION_DEFAULTS.keys())
REQUIRED_TRANSACTION_KEYS = ALLOWED_TRANSACTION_KEYS.difference(
TRANSACTION_DEFAULTS.keys()
)


def assert_valid_fields(transaction_dict):
Expand All @@ -99,19 +103,27 @@ def assert_valid_fields(transaction_dict):
# check if any extra keys were specified
superfluous_keys = set(transaction_dict.keys()).difference(ALLOWED_TRANSACTION_KEYS)
if superfluous_keys:
raise TypeError("Transaction must not include unrecognized fields: %r" % superfluous_keys)
raise TypeError(
"Transaction must not include unrecognized fields: %r" % superfluous_keys
)

# check for valid types in each field
valid_fields: Dict[str, bool]
valid_fields = apply_formatters_to_dict(LEGACY_TRANSACTION_VALID_VALUES, transaction_dict)
valid_fields = apply_formatters_to_dict(
LEGACY_TRANSACTION_VALID_VALUES, transaction_dict
)
if not all(valid_fields.values()):
invalid = {key: transaction_dict[key] for key, valid in valid_fields.items() if not valid}
invalid = {
key: transaction_dict[key]
for key, valid in valid_fields.items()
if not valid
}
raise TypeError("Transaction had invalid fields: %r" % invalid)


def chain_id_to_v(transaction_dict):
# See EIP 155
chain_id = transaction_dict.pop('chainId')
chain_id = transaction_dict.pop("chainId")
if chain_id is None:
return transaction_dict
else:
Expand All @@ -124,20 +136,20 @@ def fill_transaction_defaults(transaction):


UNSIGNED_TRANSACTION_FIELDS = (
('nonce', big_endian_int),
('gasPrice', big_endian_int),
('gas', big_endian_int),
('to', Binary.fixed_length(20, allow_empty=True)),
('value', big_endian_int),
('data', binary),
("nonce", big_endian_int),
("gasPrice", big_endian_int),
("gas", big_endian_int),
("to", Binary.fixed_length(20, allow_empty=True)),
("value", big_endian_int),
("data", binary),
)


class Transaction(HashableRLP):
fields = UNSIGNED_TRANSACTION_FIELDS + (
('v', big_endian_int),
('r', big_endian_int),
('s', big_endian_int),
("v", big_endian_int),
("r", big_endian_int),
("s", big_endian_int),
)


Expand All @@ -154,4 +166,4 @@ def strip_signature(txn):


def vrs_from(transaction):
return (getattr(transaction, part) for part in 'vrs')
return (getattr(transaction, part) for part in "vrs")
13 changes: 7 additions & 6 deletions eth_account/_utils/signing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
V_OFFSET = 27

# signature versions
PERSONAL_SIGN_VERSION = b'E' # Hex value 0x45
INTENDED_VALIDATOR_SIGN_VERSION = b'\x00' # Hex value 0x00
STRUCTURED_DATA_SIGN_VERSION = b'\x01' # Hex value 0x01
PERSONAL_SIGN_VERSION = b"E" # Hex value 0x45
INTENDED_VALIDATOR_SIGN_VERSION = b"\x00" # Hex value 0x00
STRUCTURED_DATA_SIGN_VERSION = b"\x01" # Hex value 0x01


def sign_transaction_dict(eth_key, transaction_dict):
Expand All @@ -42,8 +42,9 @@ def sign_transaction_dict(eth_key, transaction_dict):
(v, r, s) = sign_transaction_hash(eth_key, transaction_hash, chain_id)
elif isinstance(unsigned_transaction, TypedTransaction):
# Each transaction type dictates its payload, and consequently,
# all the funky logic around the `v` signature field is both obsolete && incorrect.
# We want to obtain the raw `v` and delegate to the transaction type itself.
# all the funky logic around the `v` signature field is both obsolete &&
# incorrect. We want to obtain the raw `v` and delegate
# to the transaction type itself.
(v, r, s) = eth_key.sign_msg_hash(transaction_hash).vrs
else:
# Cannot happen, but better for code to be defensive + self-documenting.
Expand Down Expand Up @@ -128,7 +129,7 @@ def sign_transaction_hash(account, transaction_hash, chain_id):


def _pad_to_eth_word(bytes_val):
return bytes_val.rjust(32, b'\0')
return bytes_val.rjust(32, b"\0")


def to_bytes32(val):
Expand Down
Loading

0 comments on commit 04f4cec

Please sign in to comment.