交易奖励(交易中的Gas消耗)
以太坊的EVM是“图灵完备”的,为了防止出现死循环而导致服务不可用,所以引入了Gas
。在程序的执行过程中,需要消耗Gas
.Gas
消耗完了,程序就不会继续运行。同时,以太坊还给每个区块包含的程序消耗的总Gas设定了上限(Gas Limit
),以免区块中包含的程序过多,影响一些性能比较弱的节点。每个区块能消耗的Gas上限也是可以调整的,由矿工们进行投票决定,目前是6725538Gas。
每笔交易中花费的Gas
可以通过以下公式计算:
Gas = GasUsed * GasPrice
使用web3.js
实现
async function getGas(){
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));//初始化web3
var txhash = "0x0d34221ebb8ce885d7f1c56170f4bec8d9d9b7bc0bb2273580785ee02a3b2fd4";//交易hash
txResult = await web3.eth.getTransaction("txhash"); //获取交易信息
txReceipt = await web3.eth.getTransactionReceipt("txhash");//获取交易的`TransactionReceipt`
fee = (txReceipt.gasUsed)* (txResult.gasPrice); //获取交易费
fee = web3.utils.fromWei(fee.toString());//将交易费的单位从`Wei`转为`Ether`
return feel;
}
若是获取一个区块中消耗的交易费,只要没笔交易费,再乘上交易数量就可以了:
GasInBlock = GasUsed * GasPrice * Txsnum
async function getGasInBlock(){
var web3 = new Web3();
web3.setProvider(new web3.providers.HttpProvider("http://localhost:8545"));//初始化web3
var TxsFee = 0;
var height = 2;//区块高度
for(var i=0;i<txnum;i++){
txResult = await web3.eth.getTransactionFromBlock(height,i);
txReceipt = await web3.eth.getTransactionReceipt(txResult.hash);
fee = (txReceipt.gasUsed)* (txResult.gasPrice);
fee = web3.utils.fromWei(fee.toString());
TxsFee += parseFloat(fee);
}
return TxsFee;
}
区块奖励&数块奖励
以太坊创造了一个新的名词叔块(Uncle Block),不能成为主链一部分的孤儿区块,如果有幸被后来的区块通过uncles字段收留进区块链就变成了叔块。如果一个孤儿区块没有被任何区块收留,这个孤儿区块还是会被丢弃,不会进入区块链,也就是说孤儿区块被收留后才会变成叔块
在以太坊的设计中,数块也可以获得奖励,而且以后的区块链如果谁收留了叔块,收留叔块的区块也可以获得额外奖励。收留叔块也被称为包含叔块。
以太坊为什么要这么设计呢?因为以太坊的区块时间是20秒左右,相对于比特币,更容易出现临时分叉和孤儿区块。而且较短的区块时间,也使得区块在整个网络中更难以充分传播,尤其是对那些网速慢的矿工,这是一种极大的不公平。为了平衡各方利益,才设计了这样一个叔块机制。叔块在全部挖掘出来的区块中占的比例叫叔块率,目前叔块率在9.7%左右。
叔块奖励的计算公式如下:
叔块奖励 = (叔块高度 + 8 - 包含叔块的区块的高度 * 普通区块的奖励/8
区块奖励的计算公式如下:
区块奖励 = 固定奖励 + 区块内包含交易的交易费的总和 + 包含叔块的奖励
在以太坊浏览器上实践区块奖励的计算
实践这边直接引用了以太坊(Ethereum ETH)的奖励机制的介绍:
查看以太坊浏览器中4222300的区块,由于我们是在主链上看到它的,所以它是普通区块。
它的奖励包含三部分:
- 固定奖励:5ETH
- Gas总花费(也有人称之为交易费):0.281837168043699381ETH
- 将两个叔块包含进来的奖励:5 * ( 1 / 32 ) * 2 = 0.3125ETH
在以太坊浏览器上实践叔块奖励的计算
我们再来看一个叔块0x1c2cbba0403f1079dcdb70e5971a87ce0fbc03d4572be30e2d17e4e4a0f136d5,是不是看着挺别扭,叔块不方便用高度来表示,因为同一个高度上已经有了个主链区块,就是这么惨。其实叔块也是有高度的,叔块的父区块的高度+1就是叔块的高度。
直接代入公式:
( 4222271 + 8 - 4222272 ) * 5 / 8 = 4.375ETH
计算奖励代码实现(web3.js)
//获取普通区块奖励,以太坊在4370000高度以前是5 ether,之后是3ether
function getConstReward(height) {
if (height >= 4370000) {
return 3;
}
return 5;
}
//包含一个数块的奖励
function getRewardForUncle(height,uncleNumber) {
var reward = getConstReward(height);
return (reward/32) * uncleNumber;
}
//获取数块奖励,uHeight为数块高度,height为包含区块高度
function getUncleReward(uHeight, height) {
var reward = getConstReward(height);
reward = (uHeight + 8 - height) * reward / 8;
return reward
}
//获取区块奖励,TxsFee上面已经提到如何获得
function getBlockReward(web3,block,TxsFee) {
var reward = parseFloat(getConstReward(block.number));
reward += TxsFee;
ulen = block.uncles.length;
if(ulen >0){
reward += getRewardForUncle(block.number,ulen) ;
}
return reward;
}
这边参考了两篇文章:
以太坊(Ethereum ETH)的奖励机制
以太坊的区块奖励
感兴趣的同学,可以看这两篇文章。讲的挺清楚的。