最近有个小任务,调用eth.sendSignedTransaction()发送已签名交易,同时要尽可能的处理这个调用的错误情况,这方面的文档资料也不多,边测边做记录!
错误测试
初始数据如下,以下的记录都是针对此数据进行修改测试:
var rawTx = {
nonce: '0x100',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
from: '54b865714068f5f03574ace39a1f3279c4e83e2c',
to: '0x469f07278600b1cb031448fd25f187f24a89ecb6',
value: '0x10000',
data: '0x'
}
错误一:nonce too low
当nonce设为"0x00"时,调用sendSignedTransaction()直接返回出错。
解决方法:
把nonce调大点,先用'0x100'试试,不出这个错误 了,出现错误二。
错误二:intrinsic gas too low
手续费太低,这个值是web3js官网上例子的数值,看看这个转帐需要多少gas
web3.eth.estimateGas(rawTx)
.then(console.log);
结果显示21000gas,好像是标准值,但gasLimit是0x2710=10000,比21000要小,在它后面加个0为0x27100,这个错误解决了!
执行打出交易hash值:
0x28a6a3499ec0849653ccc4a6bc95db7cc91e930e106be15485c5eb04e81b3e24
错误三:sendSignedTransaction成功返回hash,但交易无法完成
在geth控制台查看,可以看到有一笔在队列中的交易,但一直无法完成:
> txpool.status
{
pending: 0,
queued: 1
}
而且js超时后会报以下错误:
Unhandled rejection Error: Transaction was not mined within 50 blocks, please make sure your transaction was properly send. Be aware that it might still be mined!
那现在的nonce应该是多少呢?有一个api getTransactionCount可以查询:
web3.eth.getTransactionCount("0x54b865714068f5f03574ace39a1f3279c4e83e2c")
.then(console.log);
执行结果为:62
这个地址是from的地址,改一个地址看一看,是不是这样?
web3.eth.getTransactionCount("0x469f07278600b1cb031448fd25f187f24a89ecb6")
.then(console.log);
这下执行结果变为7了,确实如此!
把nonce改为'0x3f',也就是63,执行,查看交易池状态:
> txpool.status
{
pending: 0,
queued: 2
}
还是一直有2条交易在队列不执行,web3js超时返回同样的错误!
好像我被误导了,通过getTransactionCount取到的值就应该设为当前交易的nonce值,在web3py找到一个示例:
>>> tx = Transaction(
nonce=web3.eth.getTransactionCount(web3.eth.coinbase),
gasprice=web3.eth.gasPrice,
startgas=100000,
to='0xd3cda913deb6f67967b99d67acdfa1712c293601',
value=12345,
data=b'',
)
> eth.getTransactionCount("0x54b865714068f5f03574ace39a1f3279c4e83e2c")
62
把nonce改为'0x3e',也就是getTransactionCount返回的62,再次执行!
查看交易状态:
> txpool.status
{
pending: 2,
queued: 1
}
这次是有两笔在pending状态,过一会再查状态,如下:
> txpool.status
{
pending: 0,
queued: 1
}
也就是说刚才的两笔交易,nonce值为62、63的刚才在pending然后挖矿后已经完成,而还有一笔nonce为0x100的还在队列里!
有说队列中的交易在退出geth客户端时会被清除,试了下退出geth客户端重进队列中交易还在,这里指的是queued队列
错误四:known transaction: ...
重复发送交易时,会出现此错误。
错误五:交易覆盖
这个可能不能算错误,像钱包也会有交易可能gas不够时,提示增加手续费让交易更快完成,但这个得知道自己在做什么
队列中有一笔交易,nonce为'0x100',新生成一笔交易,其它交易数据都一样,只是gasPrice或gas更大时,发送交易能成功,队列中交易可能已经被手续费更高的交易替换
错误六:replacement transaction underpriced
队列中有一笔交易,nonce为'0x100',新生成一笔交易,其它交易数据都一样,只是gasPrice或gas更小,发送交易时直接提示此错误
或者修改其它数据,如value,但nonce一样,也会出现此错误
交易已记录,但执行失败
不知道怎么模拟这种情况,例如Out of gas
结论
从以上错误看出基本都是nonce的设值问题,看看nonce的几种情况:
- 太小时交易会直接失败,不能小于getTransactionCount取得的值
- 太大时交易会进队列,直到中间的交易都完成,这个交易才会完成(有这种特殊需求吗?交易先放进队列,也许有!)
- nonce等于getTransactionCount返回值时,交易能最快完成
nonce如何设置
好像挺简单,就是用getTransactionCount返回的值!
如果冷钱包不连网处理,就得自己维护nonce计数,情况会比较复杂,建议是直接取到应该用的nonce值,再去冷钱包签名。
参考
https://stackoverflow.com/questions/35159241/sendrawtransaction-results-in-queued-txs
https://blog.csdn.net/wo541075754/article/details/78081478
感谢您阅读 @chaimyu 的帖子,期待您能留言交流!
@chaimyu, 伦家就觉得你技术贴写得不错嘛~~~
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
@chaimyu, 看到你的帖子,真是我的幸运啊!太棒了!
BTW,嘿嘿,让 @cn-cutie.pie 可可妹子抢了首发咧...
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
我最近也在学习这个
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
一起学习啊,有些细节的地方资料还少
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
你的文章不错,收入也不错,教教我
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
给社区做点东西,让大家认识你..
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit