Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
60 0 0
工作证明
# \/ _; R, z! v; p2 D! \( q工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。
6 H3 a5 e+ J" f* a/ x比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。$ N1 ?4 H3 h7 f5 h, M
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。, N+ b% }( Y$ H/ @6 s4 t
挖矿
& Q1 ~8 c2 {) r; ^3 `挖矿即不断接入新的Block延续Block Chain的过程。
$ k' l4 n  e' {) K# C6 Z! ]$ J  Z
挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:; H, V) @, a! O% c" R! p
发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全
5 ~6 ^; L  n# H/ j金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
( }- l- \& Y7 X( f3 x. L  I( S- `1 c: M# f, n
Block Hash算法
; v8 r( w% v  P# z" W, eBlock头部信息的构成:2 t: s8 M7 E& ^, r" D1 L
7 G) _- B7 l: _( v7 n7 d- N
下面采用高度为125552的block数据为例,演示block hash的计算过程:+ Q* O9 f1 l3 q1 I1 M
; b& ^/ t. C8 W' q- N4 ^$ X
该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。/ r9 K3 N( S8 a. O* u- S
产量调节
7 l  a& P  f% v2 L4 hBlock的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。7 d' O& @/ S; a! M; N+ Q
// 目标时间窗口长度:两周3 p  ~' T& o) c4 r3 D/ i9 a
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;
& C" L( `2 C5 t: R6 i// block频率,每10分钟一块
  \& Y, t1 M/ M6 S+ Ustatic const int64 nTargetSpacing  = 10 * 60;
) |" ?" u8 }+ ~1 p/ O* i// 每两周的产量2016,也是调节周期* ~: A) D, q6 t+ r# @9 {
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;- {$ z" q& U  A
但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.
3 }! e3 T! \7 d( g6 t1 z9 M// Only change once per interval
! \+ e. ]2 ^: g$ c) V6 Hif ((pindexLast->nHeight+1) % nInterval != 0) {
7 I* b5 Y* \0 x$ D" h% k    // 未达到周期个数,无需调节* T5 T/ Z% f& C7 r) f1 X( Z
    return pindexLast->nBits;
; M! u. k% I+ E6 P}4 M2 d; F9 M; R& `3 G
// Go back by what we want to be 14 days worth of blocks
* B* M7 Z2 \* B. _+ _1 h# Fconst CBlockIndex* pindexFirst = pindexLast;
, A! l2 H4 `/ I  J1 f& w! e0 \for (int i = 0; pindexFirst && i pprev;" \# x) X  L$ j. g2 x& S+ M2 i
// 计算本次2016个块的实际产生时间$ c& J1 w& c/ P, x, C
// Limit adjustment step" [& o+ P( ~4 T6 A7 [$ W  M3 ^. F
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
; g: Y6 M' P) k1 z- r- S- N" L// 限定幅度,最低为1/4,最高为4倍
) G5 k; ~5 c. c( Nif (nActualTimespan  nTargetTimespan*4)
7 W' G# @" Y( F; [! P1 R$ Z7 O    nActualTimespan = nTargetTimespan*4;
% z; W5 ?: G5 h; g// 根据最近2016个块的时间,重新计算目标难度 - j" o: T. a0 c, B
// Retarget
1 l) V* p& v3 h7 y! I3 c+ z. }CBigNum bnNew;( x* E. @" a9 M6 e3 {
bnNew.SetCompact(pindexLast->nBits);
2 T9 V( @: [6 u* Y7 pbnNew *= nActualTimespan;! w- q* i4 c+ K! C) F5 W
bnNew /= nTargetTimespan;
9 ]+ X3 ]! W* T" d' P  s. n7 e 5 }' F9 F$ e$ j2 A7 c' m
if (bnNew > bnProofOfWorkLimit). [  s# o! N3 z5 |+ [
    bnNew = bnProofOfWorkLimit;  ?/ \" n( n5 S' g) V( C) H
0 x! ^2 Y# k; z1 e8 e7 |; b+ g
return bnNew.GetCompact();5 _) d+ J2 L' R% y
Block字段详解
. m: h3 F( e$ UVersion,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻, |# s" K) w) V$ O
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:
( W8 K+ s. N/ U/ `& r+ f- C
6 C8 t1 g6 ?) l0 {7 p( V: S
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
; l$ _' m/ N# i* t: v  f$ X. w6 _/ Q' n
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。
; U! t8 `$ [8 D. ^# b1 q( Y1 f新block诞生过程, L1 X; l  H. _6 t0 K
下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:: a" z! [- Y; r+ ^! X0 S0 ~
节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿! o) O1 R; e; j+ Q/ y
由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。) g' a& B- m- }+ g

- j! [% t( c: A; l主链分叉6 y, ]' m* ^# L) G
从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:
6 s4 b5 \$ y5 d: L不同高度的分支,总是接受最高(即最长)的那条分支
* B* \# k+ [; Q- G4 ^3 g相同高度的,接受难度最大的
, c( M. b( a- j7 N: h高度相同且难度一致的,接受时间最早的
  I* V+ ?5 w5 m1 \1 @; K. `若所有均相同,则按照从网络接受的顺序
. u' Q* ]. v7 h$ B  b$ e等待Block Chain高度增一,则重新选择Best Chain) e5 z4 [0 w0 Q0 R

8 U+ Z4 s% u; j: s按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
7 Z: o9 L, Z4 Q5 m# L" O分支博弈! G0 W3 c: |3 _$ V$ \4 D/ n3 W
我们假设所有的节点:
5 J9 Q0 {  f( h% g. g! b6 P4 d都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益* d" N3 c+ n3 P1 z4 E
7 k2 s  \) f. C( `1 S
所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。' X6 |+ f9 @8 ^
一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
9 k, A% a7 v) i3 E9 [- C! a  Q对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。
- U; E' i; }" E' F% xHash Dance
5 O4 ?6 P5 ^5 @) oBlock hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
/ H7 {- n" O( x9 C  [" S# ZHash Dance起名源于Google Dance.
! V3 T% y- z0 T, S算力攻击的概率: y3 T9 U2 D7 l8 Q/ |' |
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
( z% T% k3 o. Z: y' @算力攻击是一个概率问题,这里作简单叙述:9 t$ d) f$ i9 Y% q  x
p = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率2 Y0 {+ ]* e, |. k( @5 c+ N% ?  ?
' S+ Q0 y* R4 \
. ~- w& @) y: P
我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:# a) H- x( E9 B& P" q* U" U( ^1 M
; Q' }9 C+ H. f& |' R
攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
; |1 S0 j% i4 i2 K9 g5 T( X3 ^5 \9 o9 |- H! [2 D8 Y
展开为如下形式:- O  h+ E, o- @
' e  O; E0 L7 M& q8 U
计算该过程的C语言代码如下:
1 L3 {& d$ i  p  x1 V6 ~/ a#include
9 K5 ^2 S7 v8 Y  P+ Jdouble AttackerSuccessProbability(double q, int z)
; n4 Q( ^' b* P% F" E+ B; V{! ~5 k5 x& R7 Z; V! l+ D
    double sum    = 1.0;, q2 ~5 k) i& ]0 t7 b  d! Z
    double p      = 1.0 - q;) C& h( w/ K4 i! @0 R3 r# o. `
    double lambda = z * (q / p);9 c9 g  W6 X4 b
    int i, k;" c. H" |% K9 u# g% {2 v' ]
    for (k = 0; k
) b  U$ a6 ~" y+ l" m0 B我们选取几个值,结果如下:. _9 D) N- |! E7 e# M4 Q7 Z) u. ~

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33