通过源码学习比特币 -- 挖矿

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

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

原文地址:https://www.cnblogs.com/timlong/p/9503238.html

时间: 2024-08-30 16:50:51

通过源码学习比特币 -- 挖矿的相关文章

通过源码了解ASP.NET MVC 几种Filter的执行过程

一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源码是个很好的习惯,它不只停留在知道怎么用的阶段,而是让我们知道一系列的为什么,为什么这样设计,为什么这样使用....很多朋友应该看过<asp.net x 框架揭秘>这本书,确实不错,特别是边看源码边看书,可以有不小的收获.Ok,我不是大神,我只是心血来潮想看一下源码! 二.几种常见的Filter

MYSQL Study案例之--通过源码安装Mysql-5.6

MYSQL  Study案例之--通过源码安装Mysql-5.6 系统环境: 操作系统:RedHat EL6 DB Soft:  Mysql 5.6.4-m7 1.系统环境 [[email protected] Packages]# uname -a Linux rh6 2.6.32-358.el6.x86_64 #1 SMP Tue Jan 29 11:47:41 EST 2013 x86_64 x86_64 x86_64 GNU/Linux [[email protected] Packag

Linux下通过源码编译安装程序

ASK: Linux下通过源码编译安装程序(configure/make/make install的作用) configure Linux 平台有各种不同的配置,安装时需要通过 configure 来确定,如:编译器用的是 cc 还是 gcc.不同库文件所在目录等.执行 configure 后会生成 Makefile,Makefile 规定了用什么编译器.编译参数等信息. make 根据 Makefile 中规定的内容进行编译,生成的可执行文件放在当前目录或某个子目录. make install

Ubuntu通过源码编译安装Octave 4.0

本教程/笔记,用于指导在Ubuntu及其他Linux系统上如何通过源码安装Octave. Octave简介 Octave是GNU旗下代替matlab的数学工具软件,语法与matlab高度兼容,并且支持一些独有的更清晰更符合Linux社区习惯的语法.虽然在一些具体工具包和部分特性和效率上不如matlab,但是对于一般用户,它是matlab的一个有效的合法的免费的替代工具. 3.8版本之前官方没有GUI界面,让想使用GUI,必须下载第三方的工具(如qtoctave). 3.8版本加入了实验性的GUI

Linux下通过源码编译GD库

因为之前都通过源码直接编译安装的lamp环境,所以好多扩展库都是没有安装的,突然现在要用到一个验证码类,imagecreate函数显示未定义,所以就来安装编译下GD库, 首先需要先安装 gd 前置库 : freetype ,jpegsrc,libpng. freetype wget "http://download.savannah.gnu.org/releases/freetype/freetype-2.4.0.tar.bz2" tar jxvf freetype-2.4.0.tar

【JDK源码分析】通过源码分析CyclicBarrier

前言 CyclicBarrier它是什么?一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点.类似于朋友之间联系要在中午聚个会,几个朋友全部到齐后才开始喝酒吃菜. 源码 CyclicBarrier属性和构造器 public class CyclicBarrier { // 互斥锁 private final ReentrantLock lock = new ReentrantLock(); // 条件等待 private final Condition trip = lock.new

通过源码分析MyBatis的缓存

看了通过源码分析MyBatis的缓存这篇文章后,自己跟着源码过了一遍,对mybatis的一级缓存和二级缓存有了更清楚的认识. 一级缓存是SqlSession级别的,同一个sqlSession在第二次执行一个相同参数的select语句并且第一次执行后没有对数据进行更新,就会直接从缓存取值,而不再进行查找.通过阅读源码了解了这个过程,首先org.apache.ibatis.session.defaults.DefaultSqlSession.select(String, Object, RowBou

Android 4.4 通过源码进行 root 操作

2019-05-28 关键字:rk root 笔者手里有一块运行着 Android4.4 操作系统的 rk3128 开发板.刚好还没 root 的,摸索了一方,找到一个可以成功 root 的方式,特此记录一下. 整个过程其实并没有网上说的这么复杂,就简单几步,照着做就好了. step 1 预置外部 su 程序进系统.这个 su 程序已经作为附件上传到网上了.下载链接如下 链接: https://pan.baidu.com/s/1dHBfJ-SipGx6rGbpuW-p6A 提取码: fda6 这

通过源码查看Spring SmartLifecycle 的执行顺序

最新需要用到SmartLifecycle ,写了一个测试类,打印了一下执行顺序如下: /** * * * @author cuiyt * @date: 2017年8月31日 上午8:47:54 */ public class TestSmartLifecycle implements SmartLifecycle { private boolean isRunning = false; @Override public void start() { System.out.println("tes