Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
86 0 0
工作证明, @& R/ g* ]2 m9 b5 N/ y5 V+ o1 q- f
工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。
. b% ?+ b# Q; D4 ~! n比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。5 t$ h: N- d' K0 v) y! l
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。
2 L: k: j2 l! }# P挖矿
: F9 t! \8 d+ \. l挖矿即不断接入新的Block延续Block Chain的过程。- g& s1 q  d& {& _4 O

# r6 G) ^$ D: d: D挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:, R  q% p' t2 O" v( V6 q
发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全! J2 U( W4 Y+ k0 d
金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
0 ]7 R' u* `9 Z& u1 e2 @& W+ s# P$ F) R) O; a: s# e0 G
Block Hash算法9 i5 n8 o# c$ s3 m2 v( o* d' y
Block头部信息的构成:
. w2 Q7 }9 Z! o/ q, M
& p% A1 y) q% i1 s  h下面采用高度为125552的block数据为例,演示block hash的计算过程:! d! Q8 d$ v1 ^
& U- x. }& Z6 c# |/ f$ K
该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
8 }- w4 ^5 {  z8 P) n8 |' R产量调节; T& q! R& c+ Y- M2 ~
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。2 C/ U+ b" i* A8 |( ?5 C
// 目标时间窗口长度:两周& z( N- P" j1 X# I& W; w
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;+ v3 _* d' O# l4 {( s/ m7 G+ F
// block频率,每10分钟一块7 X/ b5 S% Q7 c
static const int64 nTargetSpacing  = 10 * 60;# [$ e2 A: }5 g: W8 @" i5 s0 D
// 每两周的产量2016,也是调节周期7 g* S+ j- s- z) X' ~8 M
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;
' j7 J$ Z/ p; S% ~- m0 S) _8 U但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.
' x8 M4 p: z" ^) \' i// Only change once per interval/ a6 d' c1 U5 Z( e
if ((pindexLast->nHeight+1) % nInterval != 0) {' o0 n' Y( W/ k1 U: y  e  U
    // 未达到周期个数,无需调节
' ?  l4 ^# E. `  \$ L    return pindexLast->nBits;
' i0 ?* N% ~. l; o( b: S}0 ?; O# g  W2 @
// Go back by what we want to be 14 days worth of blocks
3 o3 `8 Q& E8 x( Mconst CBlockIndex* pindexFirst = pindexLast;
0 b: l' k$ a$ ^9 f6 i- o: S( L$ afor (int i = 0; pindexFirst && i pprev;* n7 @  M7 g7 [2 b8 U
// 计算本次2016个块的实际产生时间6 `1 I* J* Y8 k
// Limit adjustment step
3 U& u2 t0 o3 Y0 {# ?- s' X" lint64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();3 M" I8 f1 y. y; c
// 限定幅度,最低为1/4,最高为4倍3 r/ B, l$ Y) L$ }( {) y/ s
if (nActualTimespan  nTargetTimespan*4)
: V" z! @$ ~; |    nActualTimespan = nTargetTimespan*4;
9 _, r/ }( O6 H0 P+ w4 j0 O# H// 根据最近2016个块的时间,重新计算目标难度
$ [, r  W2 X$ N" s* ]8 {5 j// Retarget
3 I" v% @% S9 m& t  sCBigNum bnNew;" @, Y8 U* h6 k$ v1 f
bnNew.SetCompact(pindexLast->nBits);# G9 A* ?' t2 {3 u
bnNew *= nActualTimespan;0 b0 \# y0 G2 P' y% v
bnNew /= nTargetTimespan;3 Q4 g% Y& t, E( J" h
# J4 Z) y0 }' d4 h
if (bnNew > bnProofOfWorkLimit)
! G! p9 ~7 L: ?- w9 P' b( |/ v    bnNew = bnProofOfWorkLimit;$ G" F$ A7 i0 J! [- @1 K# w+ e- M

4 |( S0 X% o; T5 x! breturn bnNew.GetCompact();3 n6 `6 ]3 }- r( K; o* [, t$ Z6 y
Block字段详解3 V3 o# ~2 [6 l7 k% b# @8 n( g
Version,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻3 B7 D6 @* S1 T6 {" Z
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:3 A& `8 J6 A1 C9 v& v: a8 u  x
/ b0 [9 h6 |$ o- O/ A
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
) E- u. i8 ^) k0 e% \, ?' `7 N$ W! j7 H' t6 i, s/ `4 H
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。
  |& P. j1 ?' Z& I% L新block诞生过程
0 m/ \; P/ f8 w' O' R3 N; V下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
1 p% V8 X/ |: G9 g9 `( t; w7 w' P节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿
$ j" G9 I% U0 O0 J( c由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。# y; H6 Q0 Q. f
$ C" k  M* P: A8 U) \' F
主链分叉
) v$ _* k/ z: d! P: u' [3 q" `从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:8 G7 j3 ]& l, K6 {+ x' g
不同高度的分支,总是接受最高(即最长)的那条分支( k- u5 k0 ^1 v0 }
相同高度的,接受难度最大的! _% A1 g1 ~  R. d2 p
高度相同且难度一致的,接受时间最早的
( p7 O8 V! ?: E若所有均相同,则按照从网络接受的顺序
/ }" {% g! f1 P' b% k( _# d0 ~4 @等待Block Chain高度增一,则重新选择Best Chain
# s$ [" B8 r. F7 M4 ]; e6 W$ g: U/ W5 v8 O1 d
按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
+ f2 _0 c! ^; I4 K分支博弈* I, P9 I0 F3 z8 V* P+ K9 ~
我们假设所有的节点:
+ K) I5 j3 p- t都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
! b2 r1 ?, Q2 _/ t' K& w' @; J7 [* E
/ \4 O: y$ o2 b3 S: c; d所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。6 T, M$ ^' a. C
一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
" B4 w% C1 R$ W& p- x对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。+ S: H# n0 ~  i' T
Hash Dance. O# F* `8 L5 o
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。0 V0 l& A8 o! ]; S
Hash Dance起名源于Google Dance.
, B0 C$ w! V4 ^* a5 @! y算力攻击的概率) z4 `) W3 P7 V. O  k% N
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
# b, A" m5 {6 }算力攻击是一个概率问题,这里作简单叙述:; L, ~- |+ b9 s5 q% M4 Y' Y% U. V
p = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率; k) L3 X; L! I. E. r+ w+ U$ o, D
; J/ w7 }7 \' i. u, r* m

: `, x  r* \0 s! f! z- a! O我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:: C$ ~7 G6 }8 W0 q
* s9 U  e6 L& }
攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
7 Z$ J0 e/ ]1 u- S
6 t1 L, {- j* C- N展开为如下形式:. j4 o9 n' h( ?' N% K1 {4 c+ j+ ]

0 b! w7 W7 b- {计算该过程的C语言代码如下:7 _- \% g, |7 ]' e" L
#include   m2 n) S* q; k
double AttackerSuccessProbability(double q, int z)) q; }& z8 A4 F) V
{
4 ]: I' ?4 _5 A; J7 r    double sum    = 1.0;
+ T; j( J; @; l, [9 Y, v    double p      = 1.0 - q;" `! u5 N( S/ K, t
    double lambda = z * (q / p);! A! p! T/ s5 u9 x; h3 v- h
    int i, k;& ?/ i# y( a! G, P! p; s
    for (k = 0; k . D0 N2 h% C0 j$ C' V
我们选取几个值,结果如下:
" j' V+ q7 j( A  |; J0 L+ f( x9 e* l6 R4 [3 h
可以看到,由于block的链式形式,随着块数的上升,攻击者赢得的概率呈指数下降。这是很多应用等待六个甚至六个以上确认的原因,一旦超过N个确认,攻击者得逞的可能微乎其微,概率值快速趋近零。: i% f  B+ R4 O0 V; V5 |. e7 ?
当攻击者的算力超过50%时,便可以控制Block Chain,俗称51%攻击。) m- U, ?! N* V" F- X6 ~
算力攻击的危害
) [5 Y6 p0 ?6 K; i攻击者算出block后,block&Txs必须能够通过验证,否则其他节点都会拒掉,攻击便无意义。攻击者无法做出下列行为:* j# f4 u: j* J  ]& c
偷盗他人的币。消费某个地址的币时,需要对应的ECDSA私钥签名,而私钥是无法破解的。凭空制造比特币。每个block奖励的币值是统一的规则,篡改奖励币值会导致其他节点会拒绝该block。& F  V% N5 F3 f$ h
  k  `# W4 X3 }( H, Z0 C( B7 b  H
唯一的益处是可以选择性的收录进入block的交易,对自己的币进行多重消费(Double Spending)。2 H% |% V3 i8 I% \  h: \
过程是这样的:假设现在block高度为100,攻击者给商户发了一个交易10BTC,记作交易A,通常这笔交易会被收录进高度101的block中,当商户在101块中看到这笔交易后,就把货物给了攻击者。此时,攻击者便开始构造另一个高度为101的block,但用交易B替换了交易A,交易B中的输入是同一笔,使得发给商户的那笔钱发给他自己。同时,攻击者需要努力计算block,使得他的分支能够赶上主分支,并合并(Merge)被大家接受,一旦接受,便成功地完成了一次Double Spending。
! K" ]# t  Y  y攻击难度呈指数上升,所以成功的Double Spending通常是一个极小概率事件。9 k3 o/ C. ]( Z/ Y+ s
算力巨头
0 `: P1 ^; E) b/ E全网算力的上升对比特币是极其有利的,这是毫无疑问的。但目前大矿池与矿业巨头使得算力高度集中化,这与中本聪所设想的一CPU一票(one-CPU-one-vote)的分散局面背道而驰,或许是他未曾预料的。5 V$ J/ l* L3 d/ M" e6 ~, a
挖矿是一项专业劳动,最后必然会交给最专业的人或团队,因为这样才能实现资源配置最优,效率最高。普通投资人通过购买算力巨头的股票:1. 完成投资;2. 分享算力红利。看似中心化的背后其实依然是分散的:: d. J/ ]4 e. v. M  C
1.矿业公司的背后是无数分散的投资人
: ~9 W& U' q6 r0 x2.矿池背后是无数分散的个体算力3 Q+ B9 n# N( A0 V6 v
既得利益使得算力巨头倾向于维护系统而不是破坏,因其收益均建立在比特币系统之上,既得利益者断然不会搬石头砸自己脚。甚至很多巨头在达到一定算力占比后会主动控制算力增长,使得低于某阈值内。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33