构建已签名EIP-1559交易载荷:与web3py结果不符问题排查
问题原因与修复方案
你手动构造EIP-1559交易原始数据时,核心错误在于RLP编码时传入了hex字符串而非原始数值/字节数据——RLP会把字符串本身当作编码对象,而非对应数值的字节形式,导致最终结果和web3py生成的不一致。
修复后的代码
from web3 import Web3 import rlp from eth_utils import to_bytes w3 = Web3(Web3.HTTPProvider(NODE_URL)) tx = { 'from': PUBLIC_KEY, 'nonce': w3.eth.get_transaction_count(PUBLIC_KEY), 'to': '0x0000000000000000000000000000000000000000', 'value': Web3.toWei(0.01, 'ether'), 'chainId': 5, 'gas': 50000, 'maxFeePerGas': Web3.toWei(500, 'gwei'), 'maxPriorityFeePerGas': Web3.toWei(200, 'gwei'), 'data': '0x0' } signed_tx = w3.eth.account.sign_transaction(tx, PRIVATE_KEY) print(signed_tx) # 正确的RLP编码字段:使用原始整数或字节,而非hex字符串 encoded = rlp.encode([ tx['chainId'], # 直接传入整数chainId tx['nonce'], # 传入整数nonce tx['maxPriorityFeePerGas'], # 传入整数优先级手续费 tx['maxFeePerGas'], # 传入整数最大手续费 tx['gas'], # 传入整数gas限制 bytes.fromhex(tx['to'][2:]) if tx['to'] else b'', # 地址转字节(去掉0x前缀) tx['value'], # 传入整数转账金额 bytes.fromhex(tx['data'][2:]) if tx['data'] else b'', # 数据转字节 [], # 空的accessList signed_tx['v'], # 直接使用整数v值 to_bytes(hexstr=signed_tx['r']), # r转字节对象 to_bytes(hexstr=signed_tx['s']) # s转字节对象 ]) # 拼接交易类型前缀0x02 manual_raw_tx = f'0x02{encoded.hex()}' print(manual_raw_tx) # 验证是否和web3py的结果一致 print(f"是否匹配: {manual_raw_tx == signed_tx.rawTransaction.hex()}")
关键修复点说明
- 字段类型匹配要求:RLP编码EIP-1559交易时,chainId、nonce、gas、各类手续费、value必须传入原始整数,不能用hex字符串;地址、data需转换为字节对象(去掉0x前缀后通过
bytes.fromhex()转换)。 - 签名字段正确处理:signed_tx返回的r、s是十六进制字符串,要通过
to_bytes(hexstr=...)转为字节对象后再参与RLP编码;v值直接使用整数即可。 - 交易类型前缀保留:EIP-1559交易类型标识0x02需要拼接在RLP编码结果的十六进制字符串前,这部分你之前的逻辑是正确的。
内容的提问来源于stack exchange,提问作者user22244332
相关产品推荐
相关产品推荐

