Fix EIP-155 V reconstruction for ecrecover in client

This commit is contained in:
Alexandre Paillier
2024-03-12 17:22:00 +01:00
parent d5e48aea80
commit 1783900cb1

View File

@@ -24,15 +24,31 @@ def recover_transaction(tx_params, vrs: tuple) -> bytes:
prefix = raw_tx[:1]
raw_tx = raw_tx[len(prefix):]
else:
# v is returned on one byte only so it might have overflowed
# in that case, we will reconstruct it to its full value
if "chainId" in tx_params:
# v is returned on one byte only so it might have overflowed
# in that case, we will reconstruct it to its full value
trunc_chain_id = tx_params["chainId"]
while trunc_chain_id.bit_length() > 32:
trunc_chain_id >>= 8
trunc_target = trunc_chain_id * 2 + 35
parity = int.from_bytes(vrs[0], "big") - (trunc_target & 0xff)
vrs = (parity + tx_params["chainId"] * 2 + 35, vrs[1], vrs[2])
trunc_v = int.from_bytes(vrs[0], "big")
if (trunc_target & 0xff) == trunc_v:
parity = 0
elif ((trunc_target + 1) & 0xff) == trunc_v:
parity = 1
else:
# should have matched with a previous if
assert False
# https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
full_v = parity + tx_params["chainId"] * 2 + 35
# 9 bytes would be big enough even for the biggest chain ID
vrs = (int(full_v).to_bytes(9, "big"), vrs[1], vrs[2])
else:
# Pre EIP-155 TX
assert False
decoded = rlp.decode(raw_tx)
reencoded = rlp.encode(decoded[:-3] + list(vrs))
addr = Account.recover_transaction(prefix + reencoded)