以太坊实战之《如何正确处理nonce》

本文详细解析了以太坊系列(ETH&ETC)在发送交易时所需参数nonce的作用及使用规则,并提供了获取可靠nonce值的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题概述

以太坊系列(ETH&ETC)在发送交易有三个对应的RPC接口,分别是eth_sendTransaction、eth_sendRawTransaction和personal_sendTransaction。这三个接口发送(或构造发送内容时)都需要一个参数nonce。官方文档对此参数的解释是:整数类型,允许使用相同随机数覆盖自己发送的处于pending状态的交易。

官网解释

仅从官网的解释,我们无法获取到更多的有效的信息。但在真实生成中我们会发现如果传错nonce字段值,通过RPC接口调用发送的交易很大可能将不会被确认。如果通过console命令来操作一般不会出现此问题,因为节点已经帮我们处理了。

问题追踪

如果继续追踪问题,会发现nonce传递错误的交易可以通过eth_getTransaction查询得到相关信息,但是它的blocknumber始终未null,也就说这边交易始终未被确认。如果是在dev模式下,应该是很快就会被确认的。更进一步,通过txpool.content命令,会发现那笔交易一直处于queued队列中,而未被消费。

原因解析

为了防止交易重播,ETH(ETC)节点要求每笔交易必须有一个nonce数值。每一个账户从同一个节点发起交易时,这个nonce值从0开始计数,发送一笔nonce对应加1。当前面的nonce处理完成之后才会处理后面的nonce。注意这里的前提条件是相同的地址在相同的节点发送交易。
以下是nonce使用的几条规则:
● 当nonce太小(小于之前已经有交易使用的nonce值),交易会被直接拒绝。
● 当nonce太大,交易会一直处于队列之中,这也就是导致我们上面描述的问题的原因;
● 当发送一个比较大的nonce值,然后补齐开始nonce到那个值之间的nonce,那么交易依旧可以被执行。
● 当交易处于queue中时停止geth客户端,那么交易queue中的交易会被清除掉。

获取nonce值

经过上面的解释追踪,我们已经了解到了nonce的基本使用规则。那么,在实际应该用中我们如何保障nonce值的可靠性呢?这里有两个思路,第一个思路就是由业务系统维护nonce值的递增。如果交易发送就出现问题,那么该地址下一笔交易继续使用这个nonce进行发送交易。第二个思路就是使用现有的api查询当前地址已经发送交易的nonce值,然后对其加1,再发送交易。对应的API接口为:eth_getTransactionCount,此方法由两个参数,第一个参数为需要查询nonce的地址,第二个参数为block的状态:latest、earliest和pending。一般情况使用pending就可以查询获得最新已使用的nonce。其他状态大家可以自行验证。

小密圈(知识星球)

个人小密圈已经创建。最近正在致力于区块链各类数字货币节点使用相关工作,在小密圈中会持续分享实践中遇到的各种常见的问题及解决方案、疑难杂症和各种坑。同时会回答大家一些常见的技术问题。刚刚创建,优惠加入中。希望大家多多支持。
这里写图片描述

Python以太坊交易是指使用Python编程语言进行以太坊区块链上的交易操作。以太坊是一种基于区块链技术的智能合约平台,它允许开发者构建和部署去中心化应用程序(DApps)。 在Python中,可以使用以太坊的官方库web3.py来进行以太坊交易的编程操作。web3.py提供了一系列的API,可以与以太坊节点进行通信,并执行各种操作,包括创建账户、发送交易、查询余额等。 以下是一个简单的Python代码示例,展示了如何使用web3.py库发送以太坊交易: ```python from web3 import Web3 # 连接到以太坊节点 w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/your_infura_project_id')) # 设置发送方账户私钥和接收方地址 private_key = 'your_private_key' receiver_address = '0x1234567890abcdef1234567890abcdef12345678' # 构建交易参数 transaction = { 'to': receiver_address, 'value': w3.toWei(1, 'ether'), 'gas': 21000, 'gasPrice': w3.toWei('50', 'gwei'), 'nonce': w3.eth.getTransactionCount(w3.eth.accounts), } # 签名交易 signed_transaction = w3.eth.account.signTransaction(transaction, private_key) # 发送交易 transaction_hash = w3.eth.sendRawTransaction(signed_transaction.rawTransaction) # 等待交易确认 transaction_receipt = w3.eth.waitForTransactionReceipt(transaction_hash) # 打印交易结果 print('交易成功,交易哈希:', transaction_receipt.transactionHash.hex()) ``` 上述代码中,首先使用`Web3`类连接到以太坊节点。然后设置发送方账户的私钥和接收方地址。接下来,构建交易参数,包括接收方地址、转账金额、燃气限制、燃气价格和交易序号。然后使用发送方账户的私钥对交易进行签名,并发送签名后的交易到以太坊网络。最后,等待交易被确认,并打印交易结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序新视界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值