# web3py第四课:处理nonce常见的坑 — Mirror **Published by:** [ourens.eth](https://paragraph.com/@ourens/) **Published on:** 2022-01-02 **URL:** https://paragraph.com/@ourens/web3py-nonce-mirror ## Content 前面几节课讲了很多内容,但是没有说nonce的几个坑,今天我就来好好说说。 关于nonce的使用建议可以参考下面群友发的内容:然后我们就说说nonce。nonce的坑如果跑过前面几课的代码,你会发现跑我的例子都能成功。当你写一个批量交易的脚本就会出问题,尤其是同一个地址发送多次请求时会遇到各种各样的问题,大部分原因就是nonce产生的问题。 我们都知道获取nonce的方法就是:`web3.eth.getTransactionCount(address)` 这句方法就是取你的地址下一个nonce的值是多少,但是这个方法取出来的值会有几个坑。 坑1:当你的上一次交易还没有打包完,你取到的nonce跟上一次的值是一样。 坑2:上一次交易已经成功打包了,得到的nonce值居然还跟上一次的一样。 坑3:上一次交易已经成功打包了,得到的nonce值居然还小于上一次的值。 这些坑产生的具体原因不在这里讨论了,其实我也没有去深入去查,但是有一些解决办法跟大家分享一下。解决方案我在我的代码中,都把发送交易的方法封装了,因为都是通用的代码。在里面我加上了一步,就是如果交易成功被矿工打包上链了,再返回。 这就相当于作了一种同步方式,因为这种同步的方式比较方便查错,虽然效率低了,但是开发过程比较顺畅。 首先是查询交易状态的代码:web3.eth.getTransactionReceipt(tx_hash)['status'] 这句话可以根据tx来查询状态,1:完成 0:失败 其他:等待 我们判定这个返回值为1,再继续,可以用循环这种比较笨的方法改一下: def send_transaction(func, params): tx = func.buildTransaction(params) signed_tx = self.web3.eth.account.sign_transaction(tx, private_key=wallet_key) tx_hash = self.web3.eth.sendRawTransaction(signed_tx.rawTransaction) while True: status = get_transaction_status(tx_hash) if status == 1: break elif status == 0: print('失败') exit() time.sleep(1) return tx_hash 经过这样的改造,你的send_transaction方法就变成同步了,只有矿工打包之后才会返回tx。 然后我们再处理nonce,在构造params之前,你可以这样处理一下:global old_nonce nonce = self.web3.eth.getTransactionCount(self.wallet_address) num = 0 while True: if num > 20: break if nonce <= old_nonce and nonce != 0: nonce = self.web3.eth.getTransactionCount(self.wallet_address) print(f'发现nonce[{old_nonce}]重复,已重新获取。[{nonce}]') time.sleep(1) else: break num = num + 1 params = { ... } old_nonce = nonce 我在这里存了上一次的nonce为old_nonce,每次会判断一下是否大于小于上一次的值,如果不对继续取。注意,我这里加了num为20,是只去重试20次,20次都取不到就是别的问题了。 一般如果你把发送交易方法改成了同步,后面遇到nonce这个问题就会少很多。最后上面这几个方法都比较民科,如果有更科学的方式欢迎跟我讨论~ 上面的这些方法我也经过了一些时间的验证,解决问题肯定是可以的! 这周我多发了一篇文章哦,如果下周我鸽了也很正常~ ## Publication Information - [ourens.eth](https://paragraph.com/@ourens/): Publication homepage - [All Posts](https://paragraph.com/@ourens/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@ourens): Subscribe to updates