用户在使用钱包的转账时,常常疑惑于Nonce, gas, gas price等参数。本文将以以太坊和HPB为例,从区块链系统底层和交易流程的角度(如图1所示)来分析这些参数的作用,并分析这些参数配置错误可能导致转账异常的原因。最后本文提及HPB区块链系统在此部分的优化和创新。

 

图1 HPB 交易流程图


区块链系统中的Nonce

Nonce在区块链中是一个非常重要的概念。在比特币中,Nonce主要用于调整pow挖矿的难度,而在以太坊和HPB等图灵完整的区块链系统中,Nonce除了调整挖矿难度外,在外部账户的每笔交易中也都存在一个Nonce。这个Nonce是一个连续的整数,在每个账户发送交易时所产生,其主要设计目的是为防止双花。 每个外部账户(私钥控制的账户)都有一个Nonce值,每一个账户从同一个节点发起交易时从0开始连续累加,每累加一次,代表完成一笔交易。当前面的Nonce处理完成之后才会处理后面的Nonce。

 

前提条件是相同的地址在相同的节点发送交易。

 

1.1 Nonce的运行原理和使用规则

以下是Nonce使用的几条规则:● 当用户提供的交易的Nonce太小(小于之前已经有交易使用的Nonce值,如图中a小于的b时),交易会被直接拒绝。

 

 

● 当用户提供的交易的Nonce太大(大于之前已经有交易使用的Nonce值,如图中的a远大于b时),此时用户的交易将被放在txpool中国的queued列表中,直到缺失的Nonce被提交到交易池中, 该交易才会进入交易池。  

 

 


● 当发送一个比较大的Nonce值,然后补齐开始Nonce到那个值之间的Nonce,那么交易依旧可以被执行。● 当交易处于queue中时,停止geth客户端,那么queued列表中的交易会被清除掉。● 当有一笔处于pending状态的交易,新的一笔交易与其拥有相同的Nonce值,如果新交易的gas price太小,无法覆盖pending状态的交易,如果新交易的gas price高于原交易的110%,则原交易会被覆盖掉。● 交易队列只保存最多64个从同一个账户发出的交易。换句话说,如果要批量转账,同一节点不要发出超过64笔交易。● 如果发起一笔交易,但是因为gwei比较低或者网络比较忙的时候,该交易还没矿工挖出,可以通过使用相同的Nonce和较高的gas费用,从而“覆盖”前一笔交易。

 

1.2 Nonce使用时常见问题整理

基于以上规则,我们来探讨实际使用时可能出现的问题。 ● 同时发送相同Nonce下的两笔交易, 系统可能会报错。如果发送了Nonce为45的交易,此时再发送一笔交易,并指定Nonce和之前的Nonce相同(gas price没有达到前一笔的110%)。则第二笔交易会提示“Nonce too low”的问题。  

 

> web3.eth.send Transaction({from: "0xb8d22d1a950cd52897b8687f6bc13898f6f0f6cc", to: " 0x290402ee6f59bc247a8dd478b8f0f96d906abefe", value: "1000000000000000000", Nonce: "45"})Error: Nonce too low    at web3.js:3143:20    at web3.js:6347:15    at web3.js:5081:36    at :1:1

 

 ● 获取pending中的Nonce,然后手动的+1,对交易进行发送,结果系统提示“Nonce too low”。此时由于pending中的交易可能正在被挖矿,客户端使用GetNonce方法获取当前地址在交易池中的Nonce值可能会偏小(只能获取成功区块的最后Nonce而不能获取txpool的最后Nonce)。进而导致用户即使对Nonce进行了累加操作,系统中实际Nonce依然比客户端中的大,因此会造成“Nonce too low”的问题。 ● 在没有完成交易之前,Nonce在区块链的单个节点中保存并计数,换言之,Nonce不存储在区块链上,而是通过计算一个帐户的已确认交易总额进行动态计算。因此当同一帐户同时使用多个钱包节点来源,可能导致Nonce的使用紊乱。因此最好的方式,同一个账户仅仅在一个钱包节点中进行操作,否则会出现交易异常的情况。



区块链系统中的gas机制

区块链中gas、gas price、gas limit是一种权衡了安全,可用性和经济模型的系统机制。

 

2.1 交易中的gas

gas是“燃料”的意思,在以太坊区块链上实现了一个EVM(以太坊虚拟机)的代码运行环境,在链上执行写入操作时,网络中的每个全节点都会进行相同的计算并存储相同的值,这种执行的消耗是昂贵的,为了促使大家将能在链下进行的运算都不放到链上进行,也为了奖励矿工,因此在链上每执行一个写入操作时,都需要支付一定的费用,用gas为单位来计数,每个在链上可以执行的命令都设置了一个消耗的gas值,例:PUSH操作需要消耗3个gas,一次转账一般要消耗21000gas,gas使用Eth来支付。 

 

2.2 交易中的gas price

gas price 是你愿意为每单位 gas 支付的Ether,一般用 Gwei 作单位。所以 gas price 越高,就代表着交易中每运算一步,付出更多的 Eth。大家可能对 Gwei 比较陌生,Gwei 其实就是 10 ^ -9 Eth,换言之, 1 Gwei = 0.000000001 Eth。所以,当你设定 gas price = 20 Gwei ,就是愿意为每个运算付出 0.00000002 Eth既代价了。 

 

手续费 (Tx Fee) = 实际运行步数 (Actual Gas Used) * 每步价钱(Gas Price)

 

 

 例如你要Ethereum 行50 步先完成运算,而 gas price 是 2 Gwei ,整个交易的手续费就会是 50 * 2 = 100 Gwei 了。

 


值得一提的是:无论您执行的命令是成功还是失败,都需要支付计算费用,即使失败,节点也验证并执行了您的交易(计算),因此必须和成功执行支付一样的费用。

 

2.3 区块中的gas limit

每个区块有gas limit,即单个区块允许的最多gas总量,以此可以用来决定单个区块中能打包多少笔交易(所有交易gas总和最大,并不一定是交易数量)。我们每一次交易或合约调用都要设置一个gas limit,如果该次操作所使用的gas数量小于或等于您所设置的gas limit,则会被执行,但如果gas总消耗量超过gas limit,所有的操作都会被重置,但费用依旧会被收取。在执行中实际消耗的gas值总和叫gas used,没有使用完的gas会退还到原账号。如果您尝试将一个会使用超过当前区块gas limit的交易打包,则会被网络拒绝,会反馈“below gas limit”。

 

2.4 区块中gas limit和交易中的gas limit关系

每个交易也会有自己的gas limit,即单个交易允许的最多gas总量,以此也可以推断出单个区块中能打包多少笔交易(所有交易gas总和最大,并不一定是交易数量)。单项的增大区块链的gas limit可以促使区块中打包交易的增多,区块也会变的臃肿。过大的区块在网络同步中如果带宽的接收速度跟不上区块的验证速度,就会造成区块的网络拥挤,严重影响区块链的网络性能。同时过低的交易gas limit也会造成大量无用的交易被抛弃,浪费gas的消耗(被撤销的交易,依然消耗了gas)。所以合理的区块链gas limit需要综合考虑矿工的机器性能和网络带宽等因素,目前HPB的区块的gas设置如下图所示。 

 

 

HPB的创新点

HPB使用了硬件来加速交易签名的验证,并且在V1.0.7.0版本升级了txpool的功能,减少了基础交易的gas消耗,降低了gas price的价格,降低成本,使得每个区块能容纳更多的交易,提高了TPS。 但是交易成本降低,就有可能被人进行DDOS攻击,拥堵网络影响正常交易的执行和打包。

 

 

3.1 如何防止DDOS的攻击

DDOS攻击(分布式拒绝服务攻击)是指处于不同位置的多个攻击者同时向一个或数个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。由于攻击的发出点是分布在不同地方的,这类攻击称为分布式拒绝服务攻击,其中的攻击者可以有多个。 

 

 

3.1.1 txpool过滤机制

首先不管是节点本地接受到的交易,还是通过p2p网络广播到来的交易,要先进入交易池txpool,每一个节点的txpool的过滤机制都是不太一样的,可以根据节点自己的需求来个性化配置。 

 

 

 
● 过滤机制的第一步,每个节点的txpool都会设置最低gas price,低于这个gas price的tx直接就会被丢掉。DDOS的原理必然是使用大量低gas price交易,每个节点的配置不一样,这些垃圾交易就不会在网络中蔓延。● 过滤机制的第二步,gas price的配置可以防止在网络中蔓延,但是单个节点会被攻击者堵满交易,这个时候limit配置就可以解决,由节点自己设置,可以接受多少个账户,每个账户可以缓存多少笔交易。超出limit的会被拒绝,需要发送更高的price的交易来替换,这对攻击者是得不偿失的。可以看交易池添加交易的逻辑: 

 

 

 ● 过滤机制的第三步,当节点交易池的缓存满了之后,不接受新的交易。会触发一个超时机制,将超期没有打包的交易删除。 关于节点txpool 最低gas price的讨论:交易池的最低gas price配置是节点个性化配置之一,代表着节点能从网络或者rpc接受的最低价格交易。如果是矿工节点的话,那关系到自己出块能够收取多少手续费,所以当网络交易很多的时候,矿工可以适当的提高交易池的gas price,只接受价格高的交易来增加自己的收入,当网络交易比较少,可以降低价格,尽可能的多接收交易,来维持手续费的收入不会降低。

 

这里需要注意的一点,如果使用者只是一个同步的节点,当他的节点gas price低于所有矿工节点的gas price的话。那么他交易池里的某些交易有可能无法被打包,虽然交易符合要求,但是因为价格太低,矿工拒绝打包,交易无法真正的执行。所以同步节点gas price的选择还是要参考一下最近被打包交易的gas price的设置。
 

3.1.2 HPB 的gas机制

txpool的过滤机制只是在节点的入口来做防范,智能合约虚拟机可以在交易的执行过程中来阻止攻击。用户可以在其节点上运行任意程序。但如果用户编写了一个无限循环的程序,那么这些节点的 CPU、存储、带宽资源就会被消耗光,从而导致整个系统崩溃。

 


为了防止这样的DDOS攻击设计了矿工费gas机制,任何运行在区块链网络上的程序,都会按需要消耗的资源划分计算步骤,每个步骤需要支付一定的gas。而当用户运行这个程序时,需要提前支付一定量的gas总额就是图中的gas limit,如果在运算过程中提前支付gas消耗光了,那就强行停止这个程序。通过这种方式可以阻止用户对网络发起DDOS攻击。

 

在继承了以太坊的机制的基础上,HPB适当地提高了gas limit, 进一步增加了系统的安全性。 

 

文章引用

1. https://www.jianshu.com/p/630438bd3660

 

2. https://medium.com/myethacademy/1-%E5%88%86%E9%90%98%E6%90%9E%E6%B8%85-gas-gas-price-gas-limit-f50a9688db5e

 

3. https://support.mycrypto.com/general-knowledge/ethereum-blockchain/what-is-gas