挖矿的过程就是区块生成的过程 同时也是比特币“发行”的过程。
1. 矿工节点通过暴力碰撞法找到满足条件的哈希值(下文详述) 即为挖矿成功,从而获取比特币奖励
2. 矿工奖励分为两部分:coin base 交易奖励 + 新建区块中交易费用总和
下面是计算矿工奖励的比特币源码:
int64_t GetBlockValue(int nHeight, int64_t nFees) {// nFees = Sum(vin[i]) - Sum (vout[i]) 区块包含的交易费用总和
int64_t nSubsidy = 50 * COIN; //COIN = 100000000 (一亿聪),初始奖励50比特币
int nHalving = nHeight / 210000; //nHeight:区块高度
if (nHalving >= 64)
return nFees;
nSubsidy >>= nHalving; //每210000个区块奖励减半(右移位操作 提高运算效率)
return nSubsidy + nFees;
}
3. 交易发起者创建交易后,将其broadcast到相邻节点。每个节点独立的对接收到的交易进行验证
下面是比特币源码相关函数
CheckInputs();
CheckTransaction();
AcceptToMemoryPool();
符合规则的交易被加入内存的交易池并broadcast到其他节点
4. 挖矿节点对内存交易池的交易按优先级排序,由于区块大小有限制 ,优先级低的交易不能被打包进区块
交易优先级计算:
priority = sum (vin[i].value * vin[i] age)/sizeof(Tx)
- vin[i].value: 交易输入金额 以聪为单位;
- vin[i] age : 交易输入所指向的utxo所在的区块的深度 (距离最新区块高度的距离 每天增大144)
- 转账金额越大 所使用的utxo越老 字节数越小 的交易优先级越高!
- priority > 57600000 的tx 定义高优先级;(100 000 000 satoshi * 144)/ 250 byte
- 每个区块的前50k空间留给高优先级的tx , 剩下的按照”交易费/Kb”由高到低排序 直到达到MAX_BLOCK_SIZE;
- 节点软件重启 内存交易池会被清空;
- 如果交易长时间未被加入区块,交易发起节点应提高交易费重新发送;
5. 创币交易:即上文提到的给矿工的coin base 交易奖励, 作为每个新生成的block的第一笔交易
6. 挖矿算法:通过不断变换nNonce值 使SHA256(SHA256(区块头))的哈希值小于等于目标哈希值nhashTarget
nhashTarget 由区块头中的nBits值决定,其大小是依据全网算力不断调整的,全网算力越高难度越大,从而使区块生成速度保持在10分钟左右
难度值调整 函数: GetNextWorkRequired()
详情请参考另一篇博客: https://www.jianshu.com/p/122642177711
7. 区块链分叉
- 节点依据最长链(最多工作量)原则选择主链, 几乎每周都会发生单块的分叉,双块分叉几乎很少发生;
- 当两个块A,B几乎同时产生时, 节点会加入先收到的块A,抛弃后收到的B(另一部分节点先收到B);
- 如果先收到B的节点又收到新块C时,B->C作为最长链(主链)广播到全网,A块就会变成备用分叉链;
- 孤块:节点收到一个新块,它的父块没有在自己的链中找到,则将其加入孤块池,直到接收到其父块后再将其加入主链;
- 每10分钟产生一个新块,是在更快的交易确认速度和更少的分叉之间做出的权衡。
8. 51%攻击:
并不是拥有51%以上的算力才能攻击,只是拥有的算力越高 成功的概率就越大,事实上 拥有30%的算力就可以尝试攻击。
目前全网算力达到近40Eh/s, 承指数级增长
1Eh == 1000Ph;
1Ph == 1000Th;
1Th == 1000Gh;
1Gh == 1000Mh;
1Mh==1000Kh
(h:hash/sha256)
9. 双重支付攻击
小额交易A时(买咖啡) 商家不等交易A被区块确认就交付了商品,这时买家又用同一个utxo进行另外一笔交易B(转给自己的另外一个地址),这交易B就有可能先被加入矿工的区块从而使交易A失效
51% 算力使区块链分叉
当一笔交易A被加入到一个区块中得到确认后,买家通过自己控制的拥有超高算力的矿池,生成一个交易B 并将交易A的utxo发给自己钱包 同时删除交易A, 利用自己强大的算力生成分叉区块并让自己的分叉成为主链。之前交易A所在的区块则成为了一个分叉…
10. 拒绝服务攻击