sendSignedTransaction错误情况

in cn •  7 years ago 

最近有个小任务,调用eth.sendSignedTransaction()发送已签名交易,同时要尽可能的处理这个调用的错误情况,这方面的文档资料也不多,边测边做记录!

用web3js发送已签名交易

错误测试

初始数据如下,以下的记录都是针对此数据进行修改测试:

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 的帖子,期待您能留言交流!

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

@chaimyu, 伦家就觉得你技术贴写得不错嘛~~~ img

@chaimyu, 看到你的帖子,真是我的幸运啊!太棒了!

BTW,嘿嘿,让 @cn-cutie.pie 可可妹子抢了首发咧...

我最近也在学习这个

一起学习啊,有些细节的地方资料还少

你的文章不错,收入也不错,教教我

给社区做点东西,让大家认识你..