来自:NervosFans
以太坊gas可谓以太坊生态的命脉。 Gas用来量化执行某些操作的所需的计算。以太坊上进行的任何操作,小到一般交易、智能合约亦或是ICO这种大型事件,都需要gas。
或者这么来理解,打车的咪表。
以太坊作为服务商,想在上面做点什么,总归需要支付些费用,gas专门用来计费。进入gas前,先了解些基本概念。
比特币、以太坊、智能合约
比特币的创建,是因为人们对两件事有疑惑。
- 两人间转账,能不能做到点对点,不要中间商那种。有无可能,创建出运行在区块链上的去中心化资本。
Satoshi Nakamoto用比特币回答了这两个问题,即一个点对点的去中心化货币制度。
但是,初代区块链都有这么个问题,就是只有转账这一项功能,然后还不让添加其他功能。
Alice给Bob 转 BTC的过程中,除了Alice、Bob的自证,基本不再施加其他条件。好比,Alice不能要求Bob先打套降龙十八掌,然后再领钱。
打降龙十八掌这种具体的要求,需要非常复杂的脚本,就是智能合约了。
智能合约
智能合约厉害了:资金、财产、股份,任何有价值事务的交换,都可以借智能合约之手,以透明、无冲突、去中间商的方式执行。
以太坊算是丰满了区块链技术的羽翼。
智能合约是自动合约,根据写入自身代码的具体指令,条件满足时自动执行。
可以把智能合约看做是以太坊生态中基本单元。想在以太坊上做点什么,先得跟一个或一群人签订智能合约。
以太坊智能合约是一系列用 solidity编写的指令。基本上就是一波接一波的执行指令直到合约结束。
我们请出著名的贩卖机解释一下吧:
执行的每个步骤都类似于下一步执行的触发器,有点类似多米诺骨牌。假装在贩卖机上买水:
- 步骤1:给贩卖机塞点零钱。
- 步骤2:按下与水对应的按钮。步骤3:水掉下来,拿走。
每一步都直接引发下一步对吧。还有,整个过程就我跟贩卖机在互动对吧?
镜头转到以太坊:
- 步骤1:给贩卖机塞点零钱,以太坊网络中的所有节点记录下这个动作,且交易在账本上被更新。
- 步骤2:按下与水对应的按钮,节点接着记录并更新。步骤3:水掉下来,拿走,节点接着记录并更新。
与智能合约的每步互动都被网络节点记录并更新。就是看着合约参与方的意思,告诉你不能胡闹,都看着呢。
以太坊虚拟机
了解以太坊虚拟机(EVM)之前,先了解下 “虚拟机”做什么的。
那么,先回到智能合约,说:称职的智能合约应该有哪些属性?
首先,区块链上运行的任何事务必须是不可变的;其次,必须能够在不损害自身完整性的情况下运行多个节点。因此,智能合约需要满足以下三点:
特点#1:确定性
确定性程序指给定输入的情形下,每次的输出都一致。好比,若 3 + 1 = 4,则3 + 1永远等于4(假设基数相同)。因此,不同计算机上给定同组输入得出相同输出的程序,称之为确定性程序。
程序以非确定性方式行动的情形:
- 调用非确定性系统函数:程序员调用程序中非确定性函数时。
- 非确定性数据资源:程序运行时获取数据且数据为非确定性,则程序变得非确定性。比方说,某程序获取某查询的前10位谷歌搜索结果,该结果列表非一成不变的。动态调用:程序调用第二个程序时,称为动态调用。由于调用目标仅在执行期间为确定性,因此本质上是非确定性的。
特点#2:可终止性
数学逻辑中,有个概念叫“图灵停机问题”。
不存在这样一个程序(算法),能够计算出任何程序(算法)在给定输入上是否会结束(停机)。
意思是说,无法确定给定程序能否在某个时间限制将全部功能执行完。1936年,阿兰·图灵(Alan Turing)用康托尔对角线证明(Cantor’s DiagonalProblem)推出这个结论。
智能合约明显会落到这个坑里,合约嘛,不能执行起来没完没了,否则将耗尽全部资源。有鉴于此,需要施加一些手段,能及时‘终止’无限循环:
- 图灵不完备:图灵不完备的区块链功能有限,因此无法进行跳跃或循环,因此不会进入无限循环。
- “步数/咪表”:步数表指程序自行记录自己的“步数”,意思是已执行的指令数量,超过步数限制即终止;另外,还有咪表的方式,指预付费执行合约。相当于每条指令的执行都有费用,费用用完即终止。定时器:就是放个预设的定时器。若合同执行超过时间限制,则外部中止。
特点#3:隔离的
区块链中,任何人都可以上传智能合约,所以合约难免会故意不故意的包含病毒和bug。
若合约非相互隔离,整个系统都有可能收到威胁。于是乎,必须把合约置于沙盒中隔离,保护整个生态系统免受任何负面影响。
好合约的优秀品质看完了,下面看看合约的执行。运行智能合约一般有两种系统可选:
- 虚拟机:以太坊用虚拟机。Docker:Fabric用docker。
比较下这两种(Ethereum vs.Fabric),看看谁能在生态友好的命题中胜出。就从合约的确定性、可终止性和隔离三方面,横向对比一下:
确定性方面:
EVM合约无非确定性函数,且数据仅限于链上信息。但合约会执行动态调用,因此合约本质上是非确定性的,好在可访问数据都是确定性。
Docker的设计肌理就是依仗用户创建确定性的智能合约,这种不算是最优解。
可终止性方面:
以太坊用的是费用表。意思是合约的每一步操作都消耗gas。Gas消耗超过预付费用时,合约被终止。
Fabric用的定时器,但是节点间的定时器不一定都一样,毕竟各个节点的计算力会有差别,因此有可能影响共识进程。
隔离性方面:
虚拟机本身就有很好的隔离属性。
Docker是依赖命名空间的,隔离性不太理想。
因此,
虚拟机在确定性、可终止性和隔离三方面为智能合约提供更好的环境。但是,Dokcer有个明显的优势:人家的编码语言很灵活,以太坊虚拟机的话,需要掌握一门新语言,就是Solidity,才能创建智能合约。
以太坊中所有智能合约都运行在虚拟机(EVM)中,是个简单而强的图灵完备256位EVM。
图灵完备就是说给定资源及内存,虚拟机中运行的程序能解决任何问题。
以太坊Gas
上面解释过,gas是衡量执行操作所需计算量的单位。
EVM中运行的大部分智能合约都使用Solidity编码(以太坊计划将来从Solidity转向Vyper)。执行Solidity中每一行代码都需要一定的gas。
以下图片摘自以太坊黄皮书,大概其给出了各种指令对应的gas费用。比方说,单笔交易至少要21000 个gas。
用类比解释下gas 的工作原理。说,Bob准备自驾游,出发前有几个标准动作:
- 去加油站,告诉工作人员加多少油。
- 然后加油。然后给油钱。
下面镜头转向以太坊。
开车好比执行智能合约的某功能。
汽油就是gas。
加油站相当于矿工,油钱相当于矿工费。
想在以太坊中执行任何操作,都必须提供gas,gas的费用结构包括:
- 为操作本身的数据支付gas,也就是本gas(本金)。为整个计算支付gas。
有人问,为什么要设置gas体系?
当然是激励手段啦。
与所有PoW机制的点对点体制一样,以太坊也是强烈依赖矿工算力的。矿工越多,算力越大,系统越强健。
那么,为吸引矿工,系统就要相应的激励手段,以太坊中,矿工可以通过两种方式赚钱:
说下矿工费。
这点跟比特币相似又不同。
相似指为将交易打包入块,矿工需要投入计算力验证智能合约,那么作为记账服务方,收取点费用无可厚非。
不同指的是,以太坊的矿工费以gas形式出现。
有钱干嘛不来以太坊赚。
那么,如何取费?
这来需要插播一下gas的计量方法。
其实gas单位就是个。发送至以太坊网络的交易gas费用,看具体执行多少步EVM指令,不是一口价那种,好比说一共下来差不多100个gas这种Feel。
Gas价格以太币计
没有强制规定。交易发送者可以自行定价gas。但是注意,矿工也是自行选择需要验证的交易的,也就是说什么呢,矿工一般会挑 gas高的交易验证。平均gas价格约为20 Gwei(20 Gwei = 0.00000002ETH),但网络交易量比较大的时候,gas价格会上升,所谓用gas拉高自己交易的优先级。
以下是以太坊平均gas价格。
Image courtesy: Etherscan.
接下来看看gas上限。
Gas上限
为在以太坊中完成操作,交易发起人提交交易前必须首先指定gas上限。上限嘛,意思是单笔交易最多愿意花多少交易费(gas)。
指定gas上限时,须考虑以下几点:
- 操作不同,gas费用自然不同。
- 若gas耗尽,则矿工中止执行。若gas剩余,则返回至操作发起人。
举个例子:
假设,现在Bob添加两个数字,那么合约的动作是这样的:
- 变量中存储10,花45个gas。
- 添加两个变量,花10个gas。存储结果,再花45个gas。
假设发送人指定gas上限是120。
矿工运行计算一共需要45+10+45 = 100 gas。
所以,假设1 gas = 20Gwei,那么欠矿工(100 * 20Gwei)= 0.000002 ETH
Gas上限为120 ,剩20个gas,(20 * 20 Gwei)= 0.0000004 ETH。
算的一气呵成。
话虽如此,有两种情况需要考虑:
情景#1: gas上限过低
若操作耗尽gas,则返回初始状态,就是打回原形的意思。但是,花出去的gas可回不来了,因为矿工实实诚诚的投入计算力的呀。而且,操作即便未执行,也会被添加至区块链。
回到自驾游的例子,油不够肯定到不了目的地。而且,加油站不会退油钱的,对吧。
上面的假智能合约中,gas要120对吧。要是gas上限定成90怎么办?
矿工干价值90个gas的活儿,领取相当于(90 * 20 Gwei))= 0.0000018 ETH。
然后合约返回初始状态,交易被记录至区块链。
情景#2:gas上限过高
那么,gas上限过高怎么办?
有人讲,宁滥无缺啊,不是说剩余gas返回给发送人么。
真不是这样。
因为矿工也是受区块gas上限的控制的,好比给矿工费加了个屋顶,意思是打包入块的交易gas总和必须小于等于区块gas上限。
比方说是这个区块gas上限是670万个gas吧,然后基本交易(ETH转账)至少要21000个gas。
Image courtesy: Hackernoon
假设由交易A、B、C:交易A是基本交易,指定上限是42000个gas;交易B、C也是基本交易,上限都是21000个gas。
那么,于矿工来讲,选择哪个打包合适?
- 打包A,然后返回一大笔剩余gas。还是打包交易B和C,然后返回非常少的gas。
第二个方案貌似比较合适。这也说明了gas上限过高或许并不明智。只要高一点就可以了。
Image Courtesy: Etherscan
高低gas vs. 高低费用
现在,我们知道gas跟以太币不太是一回事了。简言之,gas指需要的计算力的数量,以太币就是数字货币,能购买gas。
若操作的gas较低,则矿工不理会该操作,原因是计算完成前gas就会耗尽。
若操作的费用较低,gas有可能够用,但矿工也不会很感兴趣。
若操作的gas较高,说明操作的gas上限过于臃肿,那么矿工也不会理会。
若操作的费用较高,矿工会即刻处理该操作,因为人家能赚钱嘛。
以下是Ethgasstation当前推荐的同类型交易速度不对应的gas价格:
Gas退款
Solidity中,有两个命令确保获得gas退款。
- 自杀:相当于杀死智能合约,并返回24000个gas。SSTORE:删除存储,返回15000个gas。
如上所述,假设合约消耗14000个gas,然后删除存储,能返回15000个gas,那么一共返回1000个gas对吧?
怎么可能?
矿工给你计算完,还得倒找你1000个gas。
为避免此情形,得加个条件。
Gas退款不得超过计算耗尽gas的一半。
这么说吧,一个智能合约,需要消耗14000个gas。
Gas上限定20000个。
然后,智能合约还包含SSTORAGE命令。
求计算后合约创建人收到的gas退款。
首先,未消耗gas为(20000-14000)= 6000个。
记住,有SSTORAGE命令,所以理论上返回的gas应该是15000个。
但是,合约消耗14000个gas,而且15000 > 7000 (14000/2),则返回7000个gas。
那么,创建人最终获得的gas退款总数为6000 + 7000 = 13000。
再举个例子:
设合约消耗70000个gas 且包含自杀功能。
上面说了,SUICIDE功能返回24000个gas,且24000 < 35000(70000/2)。
因此,gas退款总额为24000 + 未使用的gas数量。
批评Gas的声音:凭什么?
Gas机制之前因运行流畅、矿工友好而广受好评。但是最近有人反映说这个机制对开发者跟合约创建人来说用起来有点贵。
考虑以下情形:
以太坊上,两个数字相加100万次,得花差不多26.55刀。
然后有人算了笔账,大概其说:标准AWS里边,用python把两个数字相加100万次,耗时0.04秒,按Amazon EC2 费率的0.0059刀/小时的话,费用是0.000000066刀。
26.55/0.000000066 = 402272727
也就是说以太坊的计算成本高的不是一星半点,4亿倍好么?
以下是援引:
两个数字相加100万次,这例子举得是有点极端。合约的计算量真到这种地步,应该是把计算挪至链下,主抓合约状态更新。而且一般不会把海量数据储存在链上,具体看什么项目,一般是在链上存储个加密参考(哈希),剩下的放在链下。
话归如此,作为开发者,开发dApps之前,必须对费用心里有数,所谓找到链上链下复杂性之间的平衡,同时仍借力区块链的去中心化力量。
https://blockgeeks.com/guides/ethereum-gas-step-by-step-guide/ |