Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
87 0 0
工作证明
1 m3 A& r1 F/ U- P工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。
: m8 ?( K% y8 u$ z$ Z" z比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。9 M+ C! f7 V5 `
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。
  H7 E1 o+ ^* N* D9 @+ b挖矿
9 l3 B3 ]4 m2 W$ P: X挖矿即不断接入新的Block延续Block Chain的过程。& [3 H2 m0 m" w: T

( c+ @& }- @  Z4 e4 b挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
8 h; k6 `1 x. ]9 z发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全4 g. l# H. k8 K* H; A; T
金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
' n/ m' W+ Y# A+ m1 Q# C+ e# K4 `( A2 p6 J/ g6 f/ p& d7 ^+ N
Block Hash算法
+ E$ M% S8 `! ?) a5 b+ ^! oBlock头部信息的构成:" Y* d8 z) \' u! e, j" G1 L
$ ?/ y1 d" [. K2 C9 g; n
下面采用高度为125552的block数据为例,演示block hash的计算过程:& N9 T. O4 i+ a: ?1 Y0 T4 T/ m

) p  ~0 Y' d3 w: e( D5 V该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。3 r5 ~1 D# ~7 u( i% [( |- C7 M
产量调节
8 i0 Y: P: z- o" V6 `, l; s1 zBlock的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。
5 O  l. K- D# q" h// 目标时间窗口长度:两周
0 x. Q- q. y1 ^) K, E, Ustatic const int64 nTargetTimespan = 14 * 24 * 60 * 60;
9 k% R( T+ Z# ^// block频率,每10分钟一块
+ f; `6 h2 _' m1 Lstatic const int64 nTargetSpacing  = 10 * 60;
1 f8 g) Z, y4 [* y& ~9 a9 D// 每两周的产量2016,也是调节周期( X  l! ]. V7 c0 y! s6 |) S
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;! d2 g- V2 Y$ l9 v/ E
但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.* k  p: n& a4 Y
// Only change once per interval
! ]+ r# @5 l( J1 ~. `9 H! Rif ((pindexLast->nHeight+1) % nInterval != 0) {
, H  z6 L2 g2 [4 j# E3 V. Z    // 未达到周期个数,无需调节
% F. D, C$ O& K9 t    return pindexLast->nBits;
( a9 W8 t) g/ B. O" C. f. r3 j}7 m2 S& D; `' C2 V
// Go back by what we want to be 14 days worth of blocks$ Z8 W$ ^( R3 z6 E, |1 C; N- \
const CBlockIndex* pindexFirst = pindexLast;5 M- @8 {$ `1 x- g( B
for (int i = 0; pindexFirst && i pprev;+ v4 c/ |! O0 Q; B3 U1 v  Z% j' u# x
// 计算本次2016个块的实际产生时间
3 O# J, Q+ o+ H" N# i// Limit adjustment step
* ?! x- @; z4 z% {7 L6 X8 tint64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
6 Z# T% y( l# \; {) d  @// 限定幅度,最低为1/4,最高为4倍, z' _$ M+ v1 z& I8 P
if (nActualTimespan  nTargetTimespan*4)
" Q5 @) D, ?0 L: H    nActualTimespan = nTargetTimespan*4;, c! h6 p5 E  C9 y; ]0 Q) t& O- L- u
// 根据最近2016个块的时间,重新计算目标难度 0 {, T5 \, _5 `4 D4 s9 H/ ?
// Retarget8 x8 i& o! {2 l1 h' X
CBigNum bnNew;( H% t* q2 E; ]
bnNew.SetCompact(pindexLast->nBits);
% e7 U3 B! K0 E  @6 ubnNew *= nActualTimespan;# b# g. H+ ~; a8 M
bnNew /= nTargetTimespan;
; A5 Y% z' O( m* X
- o1 b( ~' A+ S' r: G& nif (bnNew > bnProofOfWorkLimit), u  w  H' |  s9 O# N( e
    bnNew = bnProofOfWorkLimit;
# M6 o6 \+ W0 o" ^( R
# i3 T1 ]) T) v4 v: Rreturn bnNew.GetCompact();; l8 p' a$ `! a: I4 d
Block字段详解! E8 }) L: h& h5 L! Q
Version,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻& d$ Q$ a9 e# p# R& M
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:
, A3 C0 k+ h) O
, d/ h0 l7 S. O/ ?
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
9 D3 {' ^- t5 g( I6 `! Q. X% h, K# A6 a; V/ I# Y( ?% z
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。* j- h7 \' e* G' a# S) y; }  w
新block诞生过程3 Q6 N) P# B! [' ~; n( [2 b  q
下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
* q+ `; C& ~9 K" U7 \6 B% c* U8 @节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿- y5 z$ v0 c! B- c1 ~
由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。' F9 P* T. V- c5 X+ k+ c
2 P: P- f& S% k) E
主链分叉
: R* y1 D$ j, i2 M8 d从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:& m! f  n( D3 p& l0 n2 z
不同高度的分支,总是接受最高(即最长)的那条分支
% T4 [; b: [0 v  N' a相同高度的,接受难度最大的7 V* F) [. K% B; N0 R* K# Z6 Q
高度相同且难度一致的,接受时间最早的1 E+ P; T( r( `$ d4 o
若所有均相同,则按照从网络接受的顺序  H+ s. n; z' p8 }
等待Block Chain高度增一,则重新选择Best Chain# Z0 I# h8 q* ?) `7 v
$ W' _/ r! g: J! k7 @; Q& F# m
按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
& n- o' X, y5 B' N6 \& R6 C分支博弈
: G4 i1 x# n2 G- ]' k我们假设所有的节点:$ m% P1 [8 q6 E4 l( d9 F" I
都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
9 ?: x& r2 k7 B: v" }0 F3 d. M# I& y# Y  t
所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。
7 ]# Y/ S$ Q( Q一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
- e1 g- I; e/ R对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。$ \+ G/ K0 o6 [1 Y& a% W; m
Hash Dance/ q' _( T- @( N; m0 Z* W4 t
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
& J* y, K( Z# E' K  i  EHash Dance起名源于Google Dance.7 x' i2 n% T" D5 u7 r, K3 \6 Z
算力攻击的概率
* H4 m) W* D  A  c$ n! [7 D本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
# ], a1 o* I9 }0 A8 x算力攻击是一个概率问题,这里作简单叙述:
; [4 w" K  t) |/ b% j" S, ^. L, _p = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率2 Y. {( ?5 q! ?& p6 {
7 i1 W2 ?7 R' v; F2 B/ e( n6 H5 g9 c
4 F3 w4 \& I! F, L
我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:
8 c! h# y& a& z9 b) d! q
4 N) ]3 R( e% Z; _" p6 O攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
' I) F& a  n3 m3 m3 ^  c( g2 c3 m+ O
展开为如下形式:
% N& M6 ~2 J8 J& x. G) w: @' H% g' E$ s9 S& y$ N" ]6 I- k: k
计算该过程的C语言代码如下:
+ [$ Z9 w% [" S5 B' A9 s/ n# H#include 7 o0 s1 O$ A3 z' n) ^$ P: m
double AttackerSuccessProbability(double q, int z)
; J# G# G; q" J# R; \! P; h0 N: T{
, Y% g/ U7 `6 p5 k8 z+ N; Z    double sum    = 1.0;
1 V+ h8 G* [; S4 e9 [6 c    double p      = 1.0 - q;
% E+ b2 a+ y9 [- o$ c0 w. M    double lambda = z * (q / p);4 N# S1 `8 W9 p8 j0 s! T0 J
    int i, k;
9 p. Y( H1 C! V0 D4 c; v    for (k = 0; k
- m2 \+ P4 E! j我们选取几个值,结果如下:$ D  x! P- R. \' A$ m7 W

# b5 \3 P7 i7 w, C可以看到,由于block的链式形式,随着块数的上升,攻击者赢得的概率呈指数下降。这是很多应用等待六个甚至六个以上确认的原因,一旦超过N个确认,攻击者得逞的可能微乎其微,概率值快速趋近零。
" Y( m- U$ r' l- ?% l9 V5 x; q当攻击者的算力超过50%时,便可以控制Block Chain,俗称51%攻击。1 u+ [+ @5 Y# D6 ^) ]+ v2 M4 H
算力攻击的危害" ?: v; {0 r8 @
攻击者算出block后,block&Txs必须能够通过验证,否则其他节点都会拒掉,攻击便无意义。攻击者无法做出下列行为:
% ~  e8 B7 X5 T3 w6 k偷盗他人的币。消费某个地址的币时,需要对应的ECDSA私钥签名,而私钥是无法破解的。凭空制造比特币。每个block奖励的币值是统一的规则,篡改奖励币值会导致其他节点会拒绝该block。
/ Q4 |3 n, F0 {# I1 O$ e+ v
; K8 P+ c$ G8 a3 {8 H唯一的益处是可以选择性的收录进入block的交易,对自己的币进行多重消费(Double Spending)。3 S) b  d0 d2 K6 T( m
过程是这样的:假设现在block高度为100,攻击者给商户发了一个交易10BTC,记作交易A,通常这笔交易会被收录进高度101的block中,当商户在101块中看到这笔交易后,就把货物给了攻击者。此时,攻击者便开始构造另一个高度为101的block,但用交易B替换了交易A,交易B中的输入是同一笔,使得发给商户的那笔钱发给他自己。同时,攻击者需要努力计算block,使得他的分支能够赶上主分支,并合并(Merge)被大家接受,一旦接受,便成功地完成了一次Double Spending。
+ ?- [9 a5 ^  {" y攻击难度呈指数上升,所以成功的Double Spending通常是一个极小概率事件。
& l# z: m# s# O) s8 b9 _* r/ C算力巨头
$ O* w, Y1 x1 s  h全网算力的上升对比特币是极其有利的,这是毫无疑问的。但目前大矿池与矿业巨头使得算力高度集中化,这与中本聪所设想的一CPU一票(one-CPU-one-vote)的分散局面背道而驰,或许是他未曾预料的。6 w: ]# M$ s; |4 w/ D) _8 N
挖矿是一项专业劳动,最后必然会交给最专业的人或团队,因为这样才能实现资源配置最优,效率最高。普通投资人通过购买算力巨头的股票:1. 完成投资;2. 分享算力红利。看似中心化的背后其实依然是分散的:# E5 j" s; n' v" T5 B+ [) C! `1 f
1.矿业公司的背后是无数分散的投资人
, E6 E% f7 a+ _) T/ w- _2.矿池背后是无数分散的个体算力
9 B0 ^; d6 t7 ]$ @) Z既得利益使得算力巨头倾向于维护系统而不是破坏,因其收益均建立在比特币系统之上,既得利益者断然不会搬石头砸自己脚。甚至很多巨头在达到一定算力占比后会主动控制算力增长,使得低于某阈值内。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33