Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
208 0 0
工作证明
  {4 u" \. A& ?- Q1 }& L& f; N1 ?工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。7 R% V! ?; K$ d7 I+ x2 e
比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。* E; g1 M+ R) X" Y  d
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。, [  g1 x$ M( v- L& Q
挖矿  `( y4 n" T. `( q' |6 W
挖矿即不断接入新的Block延续Block Chain的过程。9 t& o" v5 n* l8 E
& v  Z1 S2 d. G+ X0 V9 A, W+ ]
挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
5 [; `6 s6 W9 M3 {发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全5 S  P0 @! P: Q; A7 T0 e4 B
金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
; z8 s6 B% i5 N, w" t9 \# m7 D+ _! G4 X1 _4 T3 o7 W+ w
Block Hash算法% g: Q' `. R0 e
Block头部信息的构成:7 t( ?, M+ E( H( Z1 }  }1 f  |6 Y9 }3 v
8 s# V9 s% q! v7 q$ A. i! ^; R- y
下面采用高度为125552的block数据为例,演示block hash的计算过程:
% e/ E+ b6 ^' m
5 z8 Y% {, K4 C+ v3 S该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
* ^4 {1 F' A! b2 [/ H7 y& x4 G产量调节( f) V1 Y- h4 u/ x/ W+ h& h
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。) }1 N! U5 D- \) O( @
// 目标时间窗口长度:两周
" _  N% \' q2 K) b- R5 I0 Q& Cstatic const int64 nTargetTimespan = 14 * 24 * 60 * 60;
9 y( C) ~4 o" w// block频率,每10分钟一块
, E) z1 _3 f9 j( s+ sstatic const int64 nTargetSpacing  = 10 * 60;
4 r. x, U* [) v% B, T" V// 每两周的产量2016,也是调节周期
' d9 y9 M2 U; b( B& F7 p% V4 K* Tstatic const int64 nInterval       = nTargetTimespan / nTargetSpacing;: H: s* |% {/ \: x- z, e
但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.8 r( ?( z4 d$ i9 }
// Only change once per interval
1 w* p  s$ L; v9 P9 U& bif ((pindexLast->nHeight+1) % nInterval != 0) {
) \  R3 x* F2 L* w6 a    // 未达到周期个数,无需调节; p" Q' e2 k% U
    return pindexLast->nBits;
% n4 Z0 G7 d  G/ y$ o2 k+ E7 [}; @5 u, i7 m: \$ b( R! ]! Z
// Go back by what we want to be 14 days worth of blocks
9 q/ l. L& Q* L. \const CBlockIndex* pindexFirst = pindexLast;
& N( n1 X6 @: }- V) W" ffor (int i = 0; pindexFirst && i pprev;* h$ ^* w2 L2 b4 r' h& R- O4 f3 U8 w1 a
// 计算本次2016个块的实际产生时间
( f* k9 V! q! Z3 w2 P: V// Limit adjustment step3 g1 N  {7 v2 V$ B% W+ d! X- ^
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
0 o$ m8 S/ m1 I: s+ A// 限定幅度,最低为1/4,最高为4倍
7 s* E, A+ X$ y& j2 Yif (nActualTimespan  nTargetTimespan*4)8 }1 U1 b- Z( o( }
    nActualTimespan = nTargetTimespan*4;( Q, p" A* A) f3 I9 k; p
// 根据最近2016个块的时间,重新计算目标难度 8 l8 R7 B. K; Z5 f  O, V7 |
// Retarget5 P( [' a" p) X' p
CBigNum bnNew;
$ {; x( k. B! X. W# nbnNew.SetCompact(pindexLast->nBits);+ G( N. q" y6 |& a( [+ B
bnNew *= nActualTimespan;& Y2 o1 e: h1 X# ^; b6 a: I+ Z
bnNew /= nTargetTimespan;
1 y0 L4 e2 k  g& ~3 V, Z( _ 0 T: h* T7 C  }8 R
if (bnNew > bnProofOfWorkLimit)8 Y! t7 V; J0 `! O; \; {3 ]
    bnNew = bnProofOfWorkLimit;7 \3 j+ J6 l( E6 `+ S
) w" R; G4 W. G& v4 Y
return bnNew.GetCompact();8 X' J' \# }# b2 i
Block字段详解
. x! F: Z/ h. C: p  a2 }Version,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻- |& B2 f  n! V: U' i
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:
) L: ?! i1 F! d
- d3 X8 R/ L. `5 S
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
5 b: R) E' r$ T% |: `
# K3 ~% u. u- @; T. t每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。* b* n3 Y) S: w0 w& `$ Q
新block诞生过程
6 X+ n7 i9 B% Q$ ^7 Q2 Q下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
% P/ y6 n) v' ~/ U; P+ F节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿
% J9 `1 R5 {! k! J: I# c1 u由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。" R5 X/ P8 S9 W; Z5 g: _# q

& @8 [+ f9 N7 L+ D主链分叉& G1 \/ R9 \9 O1 Q
从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:
$ E4 r1 d. E8 H9 \不同高度的分支,总是接受最高(即最长)的那条分支9 d7 R+ K( n- Z, @& f2 Q, b
相同高度的,接受难度最大的% w. x/ i: _. z; s2 u) y
高度相同且难度一致的,接受时间最早的: m( M2 Q% e4 h1 V- G
若所有均相同,则按照从网络接受的顺序3 ]! @1 y! }' X$ y3 _
等待Block Chain高度增一,则重新选择Best Chain
: s3 h" p- J: y/ c: G
9 D1 B  f/ P9 s. {' F6 q按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。5 a6 B5 u  E  x% Y1 h( l3 p
分支博弈7 [6 d$ c: O0 S. r) j
我们假设所有的节点:
8 `0 [: Y  |+ ]9 d# J9 A. x+ X都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
% H6 i8 A* N; ~) N! u' z
$ d' l& ^/ I$ u  q! O所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。* S% o# u2 n' N, T: ?
一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。3 T* r  {/ s$ H3 d7 S+ i( n1 i  e8 \
对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。
0 S" f+ ?' I* D$ O: NHash Dance, L9 _" Y' Q2 W0 c  H- L5 S
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。; A8 d5 v/ k( s
Hash Dance起名源于Google Dance.; \1 o1 y0 \3 O
算力攻击的概率8 @: f' |/ h3 L4 l3 V
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System& G& _, `4 ]- I- y/ y
算力攻击是一个概率问题,这里作简单叙述:  k2 ]! U, q$ s6 o
p = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率
4 q9 v2 H, C+ v! z( o0 H

" {& _2 e. `4 e
( ]4 p6 a" K& ^2 I% [我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:! X) _' J/ {$ W1 [

) X. x! P  Z" O$ h& b攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
- ]: ?0 j2 c4 |  f7 z+ B
/ H% t" e9 M4 [0 c7 P2 b4 r展开为如下形式:5 S! w  P* Z" ]- C

+ [) f6 e, j1 s; f% S计算该过程的C语言代码如下:5 y/ g1 i/ P) S4 U3 u% L) I
#include 5 e& H% N9 T% _5 ^% y
double AttackerSuccessProbability(double q, int z)0 C; j6 V$ i% g+ Z0 y2 F
{
. i& O" h4 i8 ]- r' r: r    double sum    = 1.0;
2 n$ r6 j6 I" H% U+ c    double p      = 1.0 - q;0 Y! a, ~7 T; P  G
    double lambda = z * (q / p);! a  j! U% i5 S5 {# @* m
    int i, k;
2 J0 t( [& T0 f# E- U- x    for (k = 0; k
2 T6 D/ s% c' _0 e# x我们选取几个值,结果如下:2 A3 K  J9 t# @

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33