以太坊nonce
以太坊系列(ETH&ETC)在发送交易有三个对应的RPC接口,分别是ethsendTransaction、ethsendRawTransaction和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。其他状态大家可以自行验证。
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的使用有很多坑需要踩,大家在具体实践过程中一旦发现问题需要及时查找原因,防止大面积的问题发生,导致整个系统的账务或资金的错乱。
以太坊nonce的更多相关文章
- Windows搭建以太坊的私有链环境
1.下载Geth.exe 运行文件,并安装 https://github.com/ethereum/go-ethereum/releases/ 下载后,只有一个Geth.exe的文件 2.cmd进入按 ...
- ubuntu系统搭建以太坊私有链
1.安装curl.git apt-get update apt-get install git apt-get install curl 2.安装go curl -O https://storage. ...
- 区块链入门(2):搭建以太坊私有链(private network of ethereum),以及挖矿的操作..
在做一些测试工作的时候, 为了方便控制以及更快的进入真正的测试工作,可能需要搭建一个私有的以太坊网络. 而以太坊节点之间能够互相链接需要满足1)相同的协议版本2)相同的networkid,所以搭建私有 ...
- 以太坊系列之十六: 使用golang与智能合约进行交互
以太坊系列之十六: 使用golang与智能合约进行交互 以太坊系列之十六: 使用golang与智能合约进行交互 此例子的目录结构 token contract 智能合约的golang wrapper ...
- 02-windows 安装以太坊 ethereum 客户端 (win7-64)-大叔思维
以太坊(Ethereum)是一个运行智能合约的去中心化平台(Platform for Smart Contract),平台上的应用按程序设定运行,不存在停机.审查.欺诈.第三方人为干预的可能.以太坊平 ...
- 使用 Go-Ethereum 1.7.2搭建以太坊私有链
目录 [toc] 1.什么是Ethereum(以太坊) 以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约.开源的底层系统,以太坊从诞生到2017年5月,短短3年半时间,全球 ...
- 以太坊挖矿源码:ethash算法
本文具体分析以太坊的共识算法之一:实现了POW的以太坊共识引擎ethash. 关键字:ethash,共识算法,pow,Dagger Hashimoto,ASIC,struct{},nonce,FNV ...
- 以太坊挖矿源码:clique算法
上文我们总结了以太坊最主要的共识算法:ethash算法,本文将重点分析以太坊的另一个共识算法:clique. 关键字:clique,共识算法,puppeth,以太坊地址原理,区块校验,认证结点,POA ...
- 以太坊区块链Java(EthereumJ)学习笔记:概述
本系列文章介绍以太坊区块链基于Java语言的解决方案.通过介绍EthereumJ定义的主要模块和Class,希望为大家学习和使用EthereumJ提供一些帮助. 整体架构 以太坊的Java解决方案主要 ...
随机推荐
- 微信小游戏 main.js没有被压缩
发布时,发现main.js没有被压缩. 在config.wxgame.ts里增加如下图.
- Sequential Minimal Optimization (SMO) 算法
SVM 最终关于 $a$ 目标函数为凸优化问题,该问题具有全局最优解,许多最优化算法都可以解决该问题,但当样本容量相对很大时,通常采用 SMO 算法(比如 LIBSVM),该算法为启发式算法,考虑在约 ...
- sublime3 配置go的开发环境
配置go的环境变量:https://studygolang.com/articles/4910 配置sublime:https://studygolang.com/articles/4938
- django高并发优化
我开始对web开发产生了兴趣,并决定自己也尝试开发一个网站.在此之前,我做过3年的java application的开发,对web开发应该算一无所知.在比较了java,php,ror,和python后 ...
- mysql distinct 后面没有括号
当distinct应用到多个字段的时候,其应用的范围是其后面的所有字段,而不只是紧挨着它的一个字段,而且distinct只能放到所有字段的前面 如下语句是错误的: SELECT country, di ...
- db2 cpu使用率高问题分析处理
性能调优步骤 明确问题->收集数据->分析数据->细化.定位问题->优化 环境: db2 问题:%usr CPU高,大约99%,db2sysc进程使用的最多 收集数据 ---系 ...
- 深度学习中的batch的大小对学习效果的影响
Batch_size参数的作用:决定了下降的方向 极端一: batch_size为全数据集(Full Batch Learning): 好处: 1.由全数据集确定的方向能够更好地代表样本总体,从而更准 ...
- gensim Word2Vec 训练和使用(Model一定要加载到内存中,节省时间!!!)
训练模型利用gensim.models.Word2Vec(sentences)建立词向量模型该构造函数执行了三个步骤:建立一个空的模型对象,遍历一次语料库建立词典,第二次遍历语料库建立神经网络模型可以 ...
- 【每日一题】 UVA - 1599 Ideal Path 字典序最短路
题解:给一个1e5个点2e5条边,每个边有一个值,让你输出一条从1到n边的路径使得:条数最短的前提下字典序最小. 题解:bfs一次找最短路(因为权值都是1,不用dijkstra),再bfs一次存一下路 ...
- AudioUnit录音和播放同时进行的一些注意点
录音(播放)和暂停 -(void)start { self.soundTotalLength = 0.0f; if (!self.unitHaveStart) { NSError *error = n ...