zoukankan      html  css  js  c++  java
  • 通过源码学习比特币 -- 挖矿

    挖矿的过程就是区块生成的过程 同时也是比特币“发行”的过程。

    1. 矿工节点通过暴力碰撞法找到满足条件的哈希值(下文详述) 即为挖矿成功,从而获取比特币奖励

    • 大约每十分钟产生一个区块, 每210000个区块(大约4年)奖励比特币减半
    • 2009.1 – 50个比特币, 2012.11 – 25个, 2016 – 12.5个
    • 到2040年, 总比特币数量达到 2099 9999.98个
    • 2140年后 新区快不再奖励新比特币 矿工收益全部来自交易费

    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的第一笔交易

    • 只有一个vin, 其指向的utxo所在的交易hash为0x0000…(32字节)
    • utxo 的输出索引vout nOut 为0xFFFFFFFF 表示不指向任何UTXO;
    • 交易输出金额为系统奖励(目前为12.5BTC) 发给挖矿节点自己的地址,比特币就是这么发行的
    • 不包含scriptSig脚本, 以区块高度开头,剩余字节可由矿工任意填充 (最大100字节)

    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所在的区块则成为了一个分叉…

    • 因此对于大额交易,一般要等至少6个区块确认之后在交付商品,以避免51%算力双重支付攻击。

    10. 拒绝服务攻击

    • 拥有超级算力的节点或矿池, 通过删除区块中的某些特定地址的交易 从而使某些地址的交易一直不能被加入到区块链。
    版权声明:转载请注明出处 https://blog.csdn.net/zhz_5/article/details/81117746
     
  • 相关阅读:
    Fidder4 顶部提示 “The system proxy was changed,click to reenable fiddler capture”。
    redis 哨兵 sentinel master slave 连接建立过程
    虚拟点赞浏览功能的大数据量测试
    python基础练习题(题目 字母识词)
    python基础练习题(题目 回文数)
    python基础练习题(题目 递归求等差数列)
    python基础练习题(题目 递归输出)
    python基础练习题(题目 递归求阶乘)
    python基础练习题(题目 阶乘求和)
    python基础练习题(题目 斐波那契数列II)
  • 原文地址:https://www.cnblogs.com/timlong/p/9503238.html
Copyright © 2011-2022 走看看