Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
88 0 0
工作证明
4 L" r" k% T. U. q工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。- e/ U+ J' T) ~
比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。
7 @7 e! C8 J) A; H工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。
% U% d" I8 \8 W! H% Z挖矿8 Z" u' r* @, }8 ~8 D6 b% T
挖矿即不断接入新的Block延续Block Chain的过程。1 s( t& J+ F% E2 [  x4 l9 y
+ V( g2 A6 u3 x  q
挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
, h* ]2 r  m7 _% o发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全
7 h/ d" c# @  E* x( S金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。3 ?) y$ Y* d0 D2 _- U

( z7 k4 w  w* s2 x* f& IBlock Hash算法
: l3 ^9 F1 R8 V+ ]' SBlock头部信息的构成:( g8 w. W+ r2 Q

- B6 m7 F5 R' |8 U下面采用高度为125552的block数据为例,演示block hash的计算过程:  C, b. P' I+ m5 T* l. Q

$ E. Z; E. j; o- Z. p) G该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
6 G! |" f* S; f产量调节& K* r5 i$ f1 @" l
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。( u( M! {5 i4 V/ \/ O( L
// 目标时间窗口长度:两周+ ~/ g: `- H9 p- n+ l. p0 r
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;
6 W; l3 Y2 W+ o  l// block频率,每10分钟一块* q7 Y1 K4 p) e. U5 e2 y# n
static const int64 nTargetSpacing  = 10 * 60;* S# B- ^  E7 S+ M; x8 k
// 每两周的产量2016,也是调节周期+ V& M) B+ L6 c# h
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;
/ a/ h' x) w  i0 ]' y4 x; {但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.
  w; Q/ B' c; w1 ]// Only change once per interval2 `. o* P) G0 t
if ((pindexLast->nHeight+1) % nInterval != 0) {
) _$ T4 c3 J4 Y$ R" |# u9 Z8 m    // 未达到周期个数,无需调节
% D  J- g1 G/ t% p2 K    return pindexLast->nBits;, `4 B% n7 U) g$ t2 r
}
* m9 i7 v8 F+ o// Go back by what we want to be 14 days worth of blocks9 _- D, c1 d. U, M' l
const CBlockIndex* pindexFirst = pindexLast;0 R! l* X* b) D/ w: @
for (int i = 0; pindexFirst && i pprev;
6 B& G( L9 H$ z/ v- e1 e  x+ a// 计算本次2016个块的实际产生时间3 q3 b4 G0 A3 W3 o( S' k
// Limit adjustment step
  e! w4 M  ^* dint64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
6 x- i0 A- o1 v9 V' Y  S- S% Q/ P  o// 限定幅度,最低为1/4,最高为4倍8 T, J. b* ^- u* a4 z- @+ Z
if (nActualTimespan  nTargetTimespan*4)4 Z9 D0 U9 h+ Q. i9 h
    nActualTimespan = nTargetTimespan*4;1 W, q+ [3 v1 O
// 根据最近2016个块的时间,重新计算目标难度
* O- m" h% `& ?// Retarget9 y  U' h' c. r1 c9 [
CBigNum bnNew;
5 }" s: [- M+ c! c" h0 {! j0 wbnNew.SetCompact(pindexLast->nBits);
% G0 O2 l0 z" n' SbnNew *= nActualTimespan;6 }: n/ O- H# N1 f7 A& z  }
bnNew /= nTargetTimespan;
2 z; n6 Z; {: O5 C( Y3 @7 g1 E) O+ s , L9 \+ g! O0 {  s; W% v: T' T" ]
if (bnNew > bnProofOfWorkLimit); G. W$ d( ]% D8 p7 A6 A
    bnNew = bnProofOfWorkLimit;
6 E4 I8 q# f% l& i7 X . c) J( d) y  a" q4 S  O
return bnNew.GetCompact();1 [( Q% `/ j( L# o  [. x( N
Block字段详解
. {) r1 ?# @5 D2 o0 ]. [* k+ i4 U9 SVersion,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻
2 v5 c0 N" z  r' E3 x! n$ Q( B( M( }最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:
+ O' p: T! a8 q. P4 o( C6 k
2 o* h8 d% K2 q5 t% S! t/ A% t
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
% c7 e- z* f  W' Y3 j& ]3 V2 T. e+ p, X9 c/ Q; q
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。3 Y5 A' {; O& @& D3 H
新block诞生过程
& G2 }5 F3 q$ ?下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:/ D0 f) F9 F. b7 ?4 ?' V0 U, W8 I0 [: K
节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿, Y' Z0 e/ E) }
由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。
  B- z  p' x: n# |3 s; P+ e! b1 e. R6 V+ [
主链分叉
0 \1 m! _2 A7 {' x) V" {从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:+ p* K& U; z$ @9 M: u% Y4 ^6 V
不同高度的分支,总是接受最高(即最长)的那条分支
6 N$ i9 ]% t0 c7 ]" C. S相同高度的,接受难度最大的
; K& z1 w% {  J8 i/ C5 A高度相同且难度一致的,接受时间最早的
- {3 a- ]4 Y+ T" @! C4 B/ T0 }4 p若所有均相同,则按照从网络接受的顺序, J$ S( h: z& J5 A/ D9 f
等待Block Chain高度增一,则重新选择Best Chain
& A/ j/ t4 v) ~( G  F/ n! ]4 I8 ~6 }; ^5 @0 p; g
按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。* [- d- _9 h& M3 r& t
分支博弈
6 B8 r6 m, u+ a2 @3 F* ~" Z我们假设所有的节点:' [. y/ ]: V( e2 e! Y' ~$ V
都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
# A2 d7 ^6 A8 ]! L. X. O) C# d" s& u
所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。
+ Q; j& L6 v3 s6 @. {. j一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。7 R% x/ G; Y7 Z& C8 ?& r. i
对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。
5 a) q8 l# N$ Q/ B. Y& B  z' ~# SHash Dance( ^& o, @. N% M: ^. q2 |' ]; [) x/ U4 Q
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
0 j7 q2 u& a* P- bHash Dance起名源于Google Dance.6 A$ N0 {) T. {1 H6 ]
算力攻击的概率& T5 R4 P" A- e$ ^- i1 N8 I
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
( ?3 a3 B( ]* Q( h' C算力攻击是一个概率问题,这里作简单叙述:
0 V6 D$ Q' P& t* J6 h: T& N3 y) Pp = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率% {! p$ w, x" v! t& U3 i

) X4 p. D) U% j1 D
/ ^/ j7 t% x& b& _; j: b6 l" ?我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:% ^6 w5 G& `2 s4 k+ R
% x6 X. K- s9 Q. h% L/ s
攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k. }' ~5 E4 l5 l; w) e6 R  p6 @

! T  n8 f# d. H6 g7 [! H展开为如下形式:
# s" ^; O; v0 L. a7 q' ^* {) R* b& n3 l
计算该过程的C语言代码如下:
; e9 j7 C% n, ]. o#include ; G6 D* A" E2 F. O9 A: _2 O7 U
double AttackerSuccessProbability(double q, int z)
6 [& y9 t( I3 R% i5 E{
# ]$ L6 _5 q5 }; n    double sum    = 1.0;7 H8 v+ F, @1 O! l$ ?3 }. t
    double p      = 1.0 - q;- c! _3 D# G5 w( ^$ W! `+ N
    double lambda = z * (q / p);  c* b) ^. K9 {& J
    int i, k;' _' ^9 W" m: a) v7 N0 ]
    for (k = 0; k ( n. V# x: T. m: _" K: |
我们选取几个值,结果如下:# t3 j( ]( @# T

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33