Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
141 0 0
工作证明
3 ~* Q- e& ?, e; n: b工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。
+ g2 ?, G5 j1 S8 P0 M0 h: e, ?  m比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。8 `9 e7 O( b+ q, i9 L6 C
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。  N* H  v: i. }7 f' N
挖矿
- _! f& H8 K) Z, E+ _9 C- J挖矿即不断接入新的Block延续Block Chain的过程。
! }. F, {" h$ ]& ~: e1 X6 D$ ~( ~  u- D6 K, I0 k& z
挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
  V: {* X- m6 q2 }- i发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全5 A$ Q# Z( T8 S+ H# E: |! p
金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。$ K/ z# Q; W! I- \. d  h9 ~
, K  M1 v4 W) a  R/ n" G
Block Hash算法
' ~4 c# {. @4 I- I1 TBlock头部信息的构成:
9 b/ `! p  b! g* u: e, T
+ J3 D& A7 l3 h0 t下面采用高度为125552的block数据为例,演示block hash的计算过程:
  d3 J3 c+ B/ R, R! }
$ @" B, t5 f1 b5 r, J( F1 O该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
* {; ]1 z; x2 p% w* e0 l6 `产量调节* {7 ]& {7 s' h; O, D/ x1 Q+ [
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。
) R5 Q* A4 A9 |+ Q2 C// 目标时间窗口长度:两周
% n$ J  }! _! u- H) o2 Vstatic const int64 nTargetTimespan = 14 * 24 * 60 * 60;
4 z* H8 a* ?) w/ Y3 u// block频率,每10分钟一块
) o% z. \. W' @" Jstatic const int64 nTargetSpacing  = 10 * 60;
0 D6 B! L1 X( h4 J. d9 Y, \// 每两周的产量2016,也是调节周期4 j" g3 }* p1 C0 b8 B, P7 R& r
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;
# {. J+ i2 k2 `7 h但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率./ ]6 J. h  y; Q3 R, r; N
// Only change once per interval4 q2 t: Y5 S  L5 h3 X
if ((pindexLast->nHeight+1) % nInterval != 0) {
  W$ g& @0 J. `6 }( X# @    // 未达到周期个数,无需调节
: u% C7 M2 R6 t, l    return pindexLast->nBits;
+ G0 z5 U, A& S3 T/ f3 P- T- \7 ~7 @}
0 m7 Z" r4 F% }' }* [2 c1 `7 a// Go back by what we want to be 14 days worth of blocks
/ G8 J& N: n! R) y! Z# Hconst CBlockIndex* pindexFirst = pindexLast;  N0 m) v& x& c- Q
for (int i = 0; pindexFirst && i pprev;2 i& x7 e! e8 S
// 计算本次2016个块的实际产生时间; _/ |: j2 V: I& r- i8 J
// Limit adjustment step
8 ]  t8 X7 G) a3 n; l2 h2 Pint64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();9 l# w% I& B4 ?# w
// 限定幅度,最低为1/4,最高为4倍# R4 w. w. Q1 x  q  Y% R
if (nActualTimespan  nTargetTimespan*4)
; @- u4 P6 x& y    nActualTimespan = nTargetTimespan*4;
4 c* ]# Y. i- X3 n3 \& d6 h// 根据最近2016个块的时间,重新计算目标难度 1 I$ Z# W1 H' C5 k
// Retarget3 t% D. S! ?+ O4 i1 ?; m
CBigNum bnNew;6 q* v, O/ Q' h; X( R. q( O: ]
bnNew.SetCompact(pindexLast->nBits);- u& Q& P4 z$ A- d
bnNew *= nActualTimespan;
; @7 J1 ~  h7 U* abnNew /= nTargetTimespan;+ W! ~8 J  [1 d! C; E5 ~5 B7 }7 Q
' o! w) K3 S$ F
if (bnNew > bnProofOfWorkLimit)5 A) L  _# \* _! y" o* w4 t) t
    bnNew = bnProofOfWorkLimit;: {; `) J$ J8 T2 b. @8 u% k

9 G8 t. W3 m2 x, P' Z! B+ Treturn bnNew.GetCompact();
! ]: O  u8 q* e% ^- E( OBlock字段详解
! z: V- h; i/ z* b& BVersion,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻( ~, [6 d9 S3 r2 i
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:; d$ i2 j0 F- z+ y

* t& i/ _% b. J5 A1 `5 y形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
5 q- d" U) O& t5 i) K! y
  T5 ?7 u7 N' v" d0 E% s% J1 U$ v每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。+ g# O! S! p  C; L9 ~3 u+ L4 V
新block诞生过程/ k6 P3 [- P( W4 k7 E' q+ u
下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
( U0 D1 P# V. V% V节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿) D. T1 a/ G* w& }( u2 `3 z
由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。
* y/ m5 j! ~- o8 s! G# [8 A6 ?: t# w6 ?7 @5 Y' t
主链分叉
: G# h8 O( o. P# o从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:" w3 _; G7 {; E' f& y
不同高度的分支,总是接受最高(即最长)的那条分支+ |% p, I7 S! r" {; F
相同高度的,接受难度最大的' }. w* \; v! H
高度相同且难度一致的,接受时间最早的
% h0 D" o! [9 m! g, ~9 Y6 |: k若所有均相同,则按照从网络接受的顺序7 c4 i  B, D) I9 Y. }2 q
等待Block Chain高度增一,则重新选择Best Chain
! ^9 C5 I6 g. G7 ~1 h8 F+ r2 h- b; w* `
按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
: j+ {( h" W8 Z( t! \9 d分支博弈
9 w; a9 Q. A7 s! c我们假设所有的节点:
, ]. ^4 A# Y8 K4 H- T1 l( E都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益& Q& }# _9 S5 I4 d3 s

% c, ]! z# x2 G7 w" b所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。+ o+ h6 T! m4 A: h2 u" X5 q. W
一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。: f6 }! b4 X  C# e. T. w  y
对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。3 P" t4 I" A2 _4 g
Hash Dance- ^' v( H# Z* P2 a( I
Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。* `; W- L- C0 L0 t. G2 r! q
Hash Dance起名源于Google Dance.
9 ]2 N* t3 o6 {4 X. h/ Q算力攻击的概率0 c. q8 R) Y, H9 o
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
& y( f4 Z' ]- R' a算力攻击是一个概率问题,这里作简单叙述:
* A  H+ G5 X% e3 h- Wp = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率& u2 ^6 d8 F: C# M- D

* N& g3 R3 i7 e: O+ l+ h$ f7 s0 N9 q; l) }8 O0 `! G
我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:+ k; Z# D. G4 L' U

$ W& {$ e* R% A攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
; r( w( N0 T6 a( M/ k6 h9 }+ Y) V- ?' L8 N8 g6 H
展开为如下形式:$ m; g# r; Y" Z7 a& \# m8 k1 f

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33