Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
206 0 0
工作证明
5 K6 L$ [1 Y% e工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。; m! D+ B- C' N
比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。; f: E7 y0 E+ T( P
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。2 d/ `  D7 B6 _4 H! A! g
挖矿
3 b' P) |+ o5 ?/ H" L) L1 C5 ?) k! R挖矿即不断接入新的Block延续Block Chain的过程。
$ H8 V$ O0 d, l7 i2 q( g/ v( ~
% J+ c/ N+ \: h( ?" L" d/ E( a挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
" H# k; D9 m/ X) j* b发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全
8 E2 x3 o! S; r% w6 {! l( u: z金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
) m! W# W2 H* J' w5 I$ n
5 x0 ^# o5 Z1 _7 x* uBlock Hash算法
1 s9 n6 M. O& E2 [# KBlock头部信息的构成:' ~1 a8 B6 c7 X# `& Z
% |: [7 A  J. R. S% w: J1 R
下面采用高度为125552的block数据为例,演示block hash的计算过程:: L, w) C& \1 W

) [, _& I' U! p/ v! ?该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
! B5 z' ?, j) g# W: u9 f产量调节; b6 @" D6 y- u$ B3 ?
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。" y8 P* p3 G9 R1 U3 ?
// 目标时间窗口长度:两周
. a6 }( E) r) p( G2 ?/ ^- cstatic const int64 nTargetTimespan = 14 * 24 * 60 * 60;
' _1 q6 }. t, J/ ~! ?  F. f// block频率,每10分钟一块
6 V, y# F8 ?( e1 t8 l4 i( {. sstatic const int64 nTargetSpacing  = 10 * 60;/ n4 N$ K2 W0 l5 q! N* E" J' `3 u4 }+ u
// 每两周的产量2016,也是调节周期+ K7 v6 `, E" m' w! b
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;
+ t/ T# u6 w; {3 s; y  {但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.9 C% U7 R; i, j$ ]5 v3 a
// Only change once per interval
9 b, Y) u( z5 @+ B% s7 b( Cif ((pindexLast->nHeight+1) % nInterval != 0) {
2 g0 y: H- j% ?2 o3 V5 G. F6 D    // 未达到周期个数,无需调节9 {+ z6 j- n) ?  e+ _/ M
    return pindexLast->nBits;
  K- l2 K  u) P8 _}' q0 k' p8 A4 n  H
// Go back by what we want to be 14 days worth of blocks
9 C+ k. r$ a; H& }" \const CBlockIndex* pindexFirst = pindexLast;
4 N1 k' q+ E4 I: @* q$ U8 ^3 cfor (int i = 0; pindexFirst && i pprev;
$ ^3 v% c4 h6 _3 b& S// 计算本次2016个块的实际产生时间
) `3 S2 [7 Y# \7 B0 Q// Limit adjustment step
" l, ~' Q  ^/ x% A. @- D9 }% u0 ~int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
% F. M" w% a; b* u// 限定幅度,最低为1/4,最高为4倍
, k" w2 F5 i  r) O4 O( P7 W  ~if (nActualTimespan  nTargetTimespan*4)4 A9 ^) i: h$ @) u: e) m/ J
    nActualTimespan = nTargetTimespan*4;- q: o3 G; k: B% F+ V2 h
// 根据最近2016个块的时间,重新计算目标难度
$ D. y9 J1 \* T! T" m% T) E& i5 R// Retarget9 A2 }- {! u! Y) R" J6 n/ b5 d6 x: A+ V' P
CBigNum bnNew;
% x" C. B' V$ e- D$ {bnNew.SetCompact(pindexLast->nBits);
; _3 n) f/ J6 E4 s5 B: O' t) o7 dbnNew *= nActualTimespan;9 w5 L6 q0 |, Y4 D: H6 R/ ~9 O
bnNew /= nTargetTimespan;: X1 e8 e1 Q9 Q% w* Y( u

0 |% Q  s7 }8 \if (bnNew > bnProofOfWorkLimit)  p$ u4 a! l6 x) s: f& c
    bnNew = bnProofOfWorkLimit;& _+ ?" A- @, ~3 A) T
; K% D% z1 E- R! e- v, [
return bnNew.GetCompact();; n4 k% r; c& ^. |, d* I
Block字段详解
( A  h% b" Z; `) q# e$ V5 A- r: BVersion,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻
- g7 h3 f. E6 I1 w' o! D' g7 l最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:; Q, P1 c& a. s
# n' x  p: X0 Z
形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)! y* b4 ~5 b6 v4 j
. g0 i4 i2 b# {8 \) V
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。" i+ t9 s* `) ]2 k; O, @
新block诞生过程
+ I4 }3 ~3 n& l' n. e下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:3 m3 f/ x+ a5 l9 v4 g/ V
节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿
; ~9 `$ z7 E4 y& m9 C由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。. `" j" m4 P3 t6 r4 r* w
. {6 e5 E0 a( v( E' F2 q& V7 f1 a
主链分叉2 z1 Z; Z8 D. N% e  b7 i8 Q
从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:
7 u" N* P( U$ H1 {% H9 a# M6 ~: e不同高度的分支,总是接受最高(即最长)的那条分支$ I7 {  A8 v5 u% K: s' b7 ~
相同高度的,接受难度最大的
( L( d2 f$ d: ^高度相同且难度一致的,接受时间最早的
- _; z  }: D& ]若所有均相同,则按照从网络接受的顺序
# j1 p% V. q5 L! X等待Block Chain高度增一,则重新选择Best Chain
! r) ^8 l( e* ?, i$ e, G7 ?: d( V+ o8 F- w/ q1 T% N6 e
按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
. J, t$ [# p) d& a; x分支博弈
( \  ~: `8 Z/ k我们假设所有的节点:: u3 f1 E. [1 [$ a3 ]. M, d$ E: Z
都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益2 e3 z% }4 I. R" F+ A6 B* ]

  T/ B: p7 |) Y所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。0 o# h; x- [0 ^7 e6 d( M' ?( y7 d
一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
, O3 t, j' n% k: T  Z/ a$ ?对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。8 F. A& O1 t2 i2 N
Hash Dance& d: K& |$ F8 X7 _7 ?
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
- f% x  N' F( W7 q/ |0 lHash Dance起名源于Google Dance.
; w! G/ W9 ]. `9 T5 z算力攻击的概率
, s9 `4 \. S2 t7 u2 }) i9 n本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
2 |+ w/ ?" W& R算力攻击是一个概率问题,这里作简单叙述:
5 D- ~8 d: c4 ap = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率
0 s) m2 W1 W5 C; r
* d; [: N* s4 P5 e0 t

0 y& N6 B* H7 W0 ~我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:
6 ~2 b3 o: l. F0 n7 E8 r; r
4 e0 z. |$ A+ m+ v  I8 W* O2 g攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k. x) U- D7 f2 u' O
  w. {/ _8 `. z; \0 v, M" ?3 t# @3 u% Q
展开为如下形式:
& C, l) ~$ A- A/ |8 x8 q. p, m( X0 X8 `7 Y6 O  U( j
计算该过程的C语言代码如下:2 c4 R. w, R- \# ]. `  f8 d
#include , Z/ W" |. j7 l1 }% @9 H( {* J
double AttackerSuccessProbability(double q, int z)( ]* ^, U* Z- g5 A3 V$ W
{8 H8 ?; b. P& u& {- R
    double sum    = 1.0;
2 v  p4 V) P3 H+ u    double p      = 1.0 - q;5 ~. z5 b$ L: Z. @+ k* o
    double lambda = z * (q / p);
8 V# [- m1 E7 j: p) H! \    int i, k;" L5 X' r4 t& v0 w* i
    for (k = 0; k
% U) z9 O4 V9 Z! P2 b; F) x我们选取几个值,结果如下:  L# b9 I5 P) z, |/ E
# T7 M" N8 T4 L1 e- U$ L
可以看到,由于block的链式形式,随着块数的上升,攻击者赢得的概率呈指数下降。这是很多应用等待六个甚至六个以上确认的原因,一旦超过N个确认,攻击者得逞的可能微乎其微,概率值快速趋近零。9 c5 N% w1 q# O. d' M
当攻击者的算力超过50%时,便可以控制Block Chain,俗称51%攻击。
6 ?- I' l* O2 }' F算力攻击的危害- W% s( z+ S! H3 E* q6 s8 ]: p$ W
攻击者算出block后,block&Txs必须能够通过验证,否则其他节点都会拒掉,攻击便无意义。攻击者无法做出下列行为:
  ?  x2 L" h' A) T- B( W. o: _: O偷盗他人的币。消费某个地址的币时,需要对应的ECDSA私钥签名,而私钥是无法破解的。凭空制造比特币。每个block奖励的币值是统一的规则,篡改奖励币值会导致其他节点会拒绝该block。
2 p3 k* I6 V5 S$ a' O9 W, k# f8 y) U3 O. ]" C+ p( @
唯一的益处是可以选择性的收录进入block的交易,对自己的币进行多重消费(Double Spending)。
4 K. e) i7 O' j; t5 {0 u过程是这样的:假设现在block高度为100,攻击者给商户发了一个交易10BTC,记作交易A,通常这笔交易会被收录进高度101的block中,当商户在101块中看到这笔交易后,就把货物给了攻击者。此时,攻击者便开始构造另一个高度为101的block,但用交易B替换了交易A,交易B中的输入是同一笔,使得发给商户的那笔钱发给他自己。同时,攻击者需要努力计算block,使得他的分支能够赶上主分支,并合并(Merge)被大家接受,一旦接受,便成功地完成了一次Double Spending。
4 H7 c: Y) H4 U- {攻击难度呈指数上升,所以成功的Double Spending通常是一个极小概率事件。5 X$ g( w9 X! p
算力巨头+ K1 S2 |" `: _5 p: J) {. _
全网算力的上升对比特币是极其有利的,这是毫无疑问的。但目前大矿池与矿业巨头使得算力高度集中化,这与中本聪所设想的一CPU一票(one-CPU-one-vote)的分散局面背道而驰,或许是他未曾预料的。+ j$ Q6 A# z8 O) t) `: H8 d8 S
挖矿是一项专业劳动,最后必然会交给最专业的人或团队,因为这样才能实现资源配置最优,效率最高。普通投资人通过购买算力巨头的股票:1. 完成投资;2. 分享算力红利。看似中心化的背后其实依然是分散的:, c, l' q  l  }+ Z' e0 q
1.矿业公司的背后是无数分散的投资人' y: J( O9 I; e2 X' R/ Q  w5 P5 f' a
2.矿池背后是无数分散的个体算力
! p7 N1 d+ J$ |1 Q: X既得利益使得算力巨头倾向于维护系统而不是破坏,因其收益均建立在比特币系统之上,既得利益者断然不会搬石头砸自己脚。甚至很多巨头在达到一定算力占比后会主动控制算力增长,使得低于某阈值内。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33