以太坊nonce

       以太坊系列(ETH&ETC)在发送交易有三个对应的RPC接口,分别是ethsendTransaction、ethsendRawTransaction和personal_sendTransaction。这三个接口发送(或构造发送内容时)都须要一个参数nonce。官方文档对此参数的解释是:整数类型,容许使用相同随机数覆盖本身发送的处于pending状态的交易。仅从官网的解释,咱们没法获取到更多的有效的信息。但在真实生成中咱们会发现若是传错nonce字段值,经过RPC接口调用发送的交易很大可能将不会被确认。若是经过console命令来操做通常不会出现此问题,由于节点已经帮咱们处理了。api

问题追踪安全

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

缘由解析排序

       为了防止交易重播,ETH(ETC)节点要求每笔交易必须有一个nonce数值。每个帐户从同一个节点发起交易时,这个nonce值从0开始计数,发送一笔nonce对应加1。当前面的nonce处理完成以后才会处理后面的nonce。注意这里的前提条件是相同的地址在相同的节点发送交易。接口

       如下是nonce使用的几条规则:队列

● 当nonce过小(小于以前已经有交易使用的nonce值),交易会被直接拒绝。                              文档

● 当nonce太大,交易会一直处于队列之中,这也就是致使咱们上面描述的问题的缘由;get

● 当发送一个比较大的nonce值,而后补齐开始nonce到那个值之间的nonce,那么交易依旧能够被执行。it

 ● 当交易处于queue中时中止geth客户端,那么交易queue中的交易会被清除掉。io

获取nonce值

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

nonce使用陷阱

热点帐户:

       所谓的热点帐户就是频繁被使用的帐户,在以太坊中好比交易所的统一出币帐户,在短期内频繁发起交易的帐户,都可被称做热点帐户。

replacement transaction underpriced异常:

       若是系统中的热点帐户或普通帐户发起交易时出现error: replacement transaction underpriced异常,那么就须要考虑nonce使用是否正确。

引发此异常缘由主要是当一个帐户发起一笔交易,假设使用nonce为1,交易已经发送至节点中,但因为手续费不高或网络拥堵或nonce值太高,此交易处于queued中迟迟未被打包。

同时此地址再发起一笔交易,若是经过eth_getTransactionCount获取的nonce值与上一个nonce值相同,用一样的nonce值再发出交易时,若是手续费高于原来的交易,那么第一笔交易将会被覆盖,若是手续费低于原来的交易就会发生上面的异常。

一般发生此异常意味着: 
- 你的Ethereum客户端中已经有一币处于pending状态的交易。 
- 新的一笔交易拥有pending状态交易相同的nonce值。 
- 新的交易的gas price过小,没法覆盖pending状态的交易。

一般状况下,覆盖掉一笔处于pending状态的交易gas price须要高于原交易的110%。

解决方案:

        针对此问题在不一样的使用场景下有不一样的解决方案。

依赖钱包:

        若是该热点帐户的私钥信息等都存放在Ethereum客户端中,那么在发送交易的时候不传递nonce值,Ethereum客户端会帮你处理好此nonce值的排序。

固然,此方案有两个弊端。第一个是安全性没法保障(未进行冷热帐户分离),第二,在热点帐户下若是想覆盖掉一笔交易,须要先查询一下该交易的信息,从中获取nonce值。

自行管理nonce:

       自行管理nonce适用于冷热帐户模式,也就是适用sendRawTransaction发送已经签名好的交易时,此时nonce值已经存在于交易中,而且已经被签名。

这种模式下,须要在业务系统中维护nonce的自增序列,适用一个nonce以后,在业务系统中对nonce进行加一处理。

此种方案也有限制条件。第一,因为nonce统一进行维护,那么这个地址必须是内部地址,并且发起交易必须经过统一维护的nonce做为出口,不然在其余地方发起交易,原有维护的nonce将会出现混乱。第二,一旦已经发出的交易发生异常,异常交易的nonce未被使用,那么异常交易的nonce须要从新被使用以后它后面的nonce才会生效。

总结:

       nonce的使用有不少坑须要踩,你们在具体实践过程当中一旦发现问题须要及时查找缘由,防止大面积的问题发生,致使整个系统的帐务或资金的错乱。

相关文章
相关标签/搜索