以太坊手续费
Noun
以太坊是新兴的区块链技术平台,其目标是成为“永不停机的世界计算机”,人们在其上可以部署各种应用供全世界使用。以太币是以太坊公链这台虚拟世界计算机器运行的“燃油”(以太坊英文名Ethereum词根eum含有燃油的意思),其理念是以太坊平台运行需要消耗资源,比如各节点的CPU、存储、带宽等资源,而这些资源消耗由以太坊平台给以计量和计价,并通过挖矿时对矿工的奖励给予补偿,这种奖励同时也是以太币去中心化的发行机制。
以太坊手续费
以太坊是新兴的区块链技术平台,其目标是成为“永不停机的世界计算机”,人们在其上可以部署各种应用供全世界使用。以太币是以太坊公链这台虚拟世界计算机器运行的“燃油”(以太坊英文名Ethereum词根eum含有燃油的意思),其理念是以太坊平台运行需要消耗资源,比如各节点的CPU、存储、带宽等资源,而这些资源消耗由以太坊平台给以计量和计价,并通过挖矿时对矿工的奖励给予补偿,这种奖励同时也是以太币去中心化的发行机制。
以太坊转账手续费的特点
对资源消耗的计量和计价,在以太坊中有专有的名词,叫某笔交易的gasUsed和gasPrice。前者体现了这笔交易消耗了以太坊这台虚拟世界计算机的资源的量(比如多少CPU时间之类),后者体现了这笔交易消耗的资源的量的单位价格(比如每单位CPU时间值多少以太币)。用开车打个比方,比如你出去旅行一趟,过程消耗燃油20升,当前油价每升6元,相当于你这次旅行的燃油成本是(20升 * 6元每升 = 120元)。同样地,一笔以太坊交易的手续费,其计算公式就是:
交易手续费Fee(单位:以太) = 过程油耗gasUsed * 当前油价gasPrice
以太坊交易的手续费,有三个特点,值得注意:
手续费和转账金额无关。不像银行,转钱越多手续费越高。
手续费给谁事先是不知道的。不像银行,手续费肯定是给银行的。
费用不会固定。由于油价gasPrice的实时变化,经常是相隔几分钟的交易,其消耗的手续费都是不同的。
手续费具体的计算和扣收过程
第一次检查是交易pending的时候,这时候的手续费计算是简单看其余额是否足够支付手续费,是单个交易的模拟检查,并没有将这笔交易纳入到整个区块的整体中计算
事前:真正开始交易钱先检查手续费,这时候要计算一次手续费,看账户中余额是否够手续费
事中:交易过程中对手续费的扣缴,因为以太坊交易分3类,普通转账,合约创建,合约执行,这3种口手续费的地方都不一样
事后:最后一次计算,有手续费剩余的时候(leftover),这部分预交冻结的手续费要返回给发起者
currentBlock.getGasLimit() 动态的本区块所能消耗的gas量的限制
gasUsedInTheBlock 简单累加计算得到的本区块已经消耗的gas量
tx.getGasLimit() 复杂计算统计各个指令得到的本交易所能消耗的gas量
basicTxCost 读取配置得基本交易gas量
手续费中油耗是如何计算的
一笔交易,手续费计算有3次,最后进行扣收。
|--JsonRpcImpl.eth_sendTransaction(CallArguments args)
|---前端新发一笔交易请求到节点时的程序入口
|----EthereumImpl.submitTransaction(tx)
|-----节点接收到后,进行初步的数据非空检查后创建一个Transaction对象并提交
|------pendingState.addPendingTransaction(transaction)
|-------节点新建一个广播任务,将交易异步广播出去;并加入本地的待确认交易表
|--------PendingStateImpl.addPendingTransactionImpl(final Transaction tx)
|---------对该笔交易进行验证,各数据项格式是否符合要求,并起模拟环境验证
|----------PendingStateImpl.executeTx(tx)
|-----------该处执行交易沙盒验证,因为是单笔交易验证,会创建一个假区块
|-----------假区块中无其他交易,已发生油耗也设为0,这样只校验单笔是否超标
2)第二次检查是区块挖出前进行模拟计算,这时候就是一个区块的整体了,除了检查账户中是否有足够支付单笔交易手续费的余额,还看区块中所有交易的手续费加起来是否超过区块的手续费总额限制,检查开始有了整体观
3)第三次检查及最后的手续费扣收,是区块挖出后的实际执行,检查限制是同第二次,但这时候是实际扣缴了,而且就算合约交易在虚拟机中执行失败,手续费是照旧扣收的
如上第2、3小点流程基本一致,区别在于执行环境是否为真,调用关系如下:
|----BlockchainImpl.createNewBlock(parent, txs, uncles, time)
|-----第2点中,创建新区块时需要模拟校验该手续费情况,沙盒执行
|----BlockchainImpl.addPendingTransaction(transaction)
|-----第3点中,区块挖矿出来后最终执行交易,扣收手续费,真实环境执行
|--------BlockchainImpl.applyBlock(repo, block)
|---------传入执行环境和当前块,对区块中的交易进行验证
|----------for (Transaction tx : block.getTransactionsList())
|-----------对于区块中的每笔交易进行手续费的检查并执行
|-----------2、3小点区别在于前者是模拟执行环境,后者是真是执行环境
以太坊交易过程中有4个重要的函数,分别是:init()、execute()、go()、finalization()
(图全貌见附录)
对应的手续费有3个动作:
注意,上述手续费检查的限制都是针对gas量,最终手续费的计算还要乘以gasPrice。
针对这部分的代码分析:
四个变量:
两个判断关系:
1)如果:(tx.getGasLimit() + gasUsedInTheBlock) > currentBlock.getGasLimit()
则提示:Too much gas used in this block:
业务含义是本区块已经消耗的gas,加上本交易消耗的gas如果超过了整个区块的gasLimit,就报错
2)如果:txGasLimit.compareTo(BigInteger.valueOf(basicTxCost)) < 0
则提示:Not enough gas for transaction execution: Require: basicTxCost Got: txGasLimit
业务含义是如果这个交易消耗的gas,太大了就超出了区块的gasLimit,如果太小了就不符合最低交易手续费的要求
以太坊不像比特币那样,手续费统一,因为以太坊设计成可以运行智能合约,而各个智能合约其消耗的资源显然是不一样的,所以不能收统一的手续费。故而,以太坊将各种基本操作分类,评估每个细节操作的耗费,汇总起来就是一个指令的油耗
如何计算见《以太坊黄皮书》中附录,费率表:
不同种类指令有不同的费用,目前最贵的合约创建,花费32000单位的油耗,最便宜的跳转指令只要花费1单位的油耗,最贵最便宜资源消耗量相差了32000倍!