Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
173 0 0
工作证明) `3 q7 w5 G0 p% U% {9 K9 w8 y
工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。
& P9 q8 B( |& _& n比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。
) C( M! L5 f, [工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。
5 P7 y" T+ H8 w" ?$ \挖矿
( v) J% @8 S; L4 `, O: f* N: y* H挖矿即不断接入新的Block延续Block Chain的过程。  G7 Y6 Y* X- p; k* E

5 k+ N( J0 W: k9 f2 u$ o# n+ _; i1 I挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:' N. z3 v' w2 K+ p: ~# n
发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全& X8 g& R7 u+ t4 r
金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。
* q7 e  I7 ?. @! |9 I- H' ~+ M% J0 @0 U7 U4 U% ?) C2 ^+ Z" f6 V
Block Hash算法! [& }2 }2 I& D3 _9 X
Block头部信息的构成:; l0 n7 y9 N, b& }; B
! N' G8 m8 _$ M" k+ o- V
下面采用高度为125552的block数据为例,演示block hash的计算过程:6 H$ j9 l. N# l" d1 S

8 i% u- Y1 ^+ O2 ^) |" E该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
5 O: [+ F* ~0 l产量调节0 p* g) f# s, q& V9 t& u
Block的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。; Z; b. S' e- v! M" `. e* b* w
// 目标时间窗口长度:两周; ^! p& t8 Y* w% E
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;6 L9 r: L! ^2 k; y! T% j% ~
// block频率,每10分钟一块5 u+ p( C# V# u3 f- X% U: Q
static const int64 nTargetSpacing  = 10 * 60;
3 |* `7 A, x; B7 w: r// 每两周的产量2016,也是调节周期
  w/ q  c& k$ F5 Qstatic const int64 nInterval       = nTargetTimespan / nTargetSpacing;
4 S; z5 a. [+ N( ^! |. [& \" @# K3 E但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.
# i6 Q( J+ J7 I5 p9 p2 {3 g8 y! P% l// Only change once per interval5 a7 F- M- Q' v* L* ]8 c
if ((pindexLast->nHeight+1) % nInterval != 0) {
& k) F( q& K  m    // 未达到周期个数,无需调节+ ^! E! l* j. r5 K; @
    return pindexLast->nBits;
  `; J: W" o- E) L}
# j* v$ v8 E* V" r& u$ T# q// Go back by what we want to be 14 days worth of blocks9 d# Z# y$ V, B" s  {3 x7 t
const CBlockIndex* pindexFirst = pindexLast;
& X1 E. `$ D2 o1 ]/ G( }* Ffor (int i = 0; pindexFirst && i pprev;5 k; o/ J# z/ p1 }# O1 M8 q7 X
// 计算本次2016个块的实际产生时间0 F; T  J' t0 n& f# f
// Limit adjustment step
& R# J# B$ @1 E+ ^% _int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();+ c. c- Y. X( q) Q3 R9 g0 M, |6 X5 B
// 限定幅度,最低为1/4,最高为4倍
* X- T9 b, V# s# J% D# u0 |5 `5 gif (nActualTimespan  nTargetTimespan*4)
  h) B7 R3 _0 {    nActualTimespan = nTargetTimespan*4;
) }- r9 A3 k3 j0 C% c) U// 根据最近2016个块的时间,重新计算目标难度   L: Y! O- x# J. w& U% g6 v# G% _9 J/ Z
// Retarget$ [( g7 z9 x5 C* }! U# q
CBigNum bnNew;
( h3 w& }  B3 V7 |6 K$ \bnNew.SetCompact(pindexLast->nBits);
2 n5 p# m% @8 r3 ^/ lbnNew *= nActualTimespan;, d/ y5 m, p+ w" Z
bnNew /= nTargetTimespan;
0 T: e9 |. T: s- Y$ Y
! Y1 S) U& Q! k0 {' j4 _if (bnNew > bnProofOfWorkLimit)
! W2 d/ Y: f; N1 q    bnNew = bnProofOfWorkLimit;9 Y8 u0 H2 Y6 F& P& @! ~8 V' L

* W, G5 U1 o4 Z8 _: b" a3 ^. K. \# t; w" {return bnNew.GetCompact();
) {# c$ J; X4 xBlock字段详解
: c9 E3 X% x6 M4 D* V) S- w0 ]Version,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻
* g% Q# q4 D* K# p! X- y最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:0 L; Q3 z, X& O

9 s' o2 @/ P% x$ Y: c8 J1 p形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)& v2 Q. l* V% w
  E. _6 n8 P7 H7 O4 u! K$ y2 |
每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。& X) l6 b; T4 A  Q
新block诞生过程
% H! C# [( H/ E8 Y; Q( Y下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
% }/ j9 w4 ?1 ?, L) }8 r节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿; W. h: L+ g0 h- A  v$ i
由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。0 \7 Y( N! Y2 I' z# z' }) B

; D, \8 L5 n+ s3 U主链分叉) k- Z% [+ M* D4 Z& f2 C* d4 j$ l
从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:/ o1 N  E  R( c  l: P! f& t! b
不同高度的分支,总是接受最高(即最长)的那条分支
, B& W+ |+ \* M8 [% y( c相同高度的,接受难度最大的7 F- D4 r# o+ e
高度相同且难度一致的,接受时间最早的
1 m' U0 t0 U7 [" c6 G6 C若所有均相同,则按照从网络接受的顺序
5 h1 w: |  P- T4 ^等待Block Chain高度增一,则重新选择Best Chain
1 j4 F& ?8 t- o+ [
* f+ g; [' c3 |5 _6 T按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。
7 r9 i9 h4 n7 S% x6 |2 K7 ?+ r分支博弈+ {1 U: Y# j9 C: s# ^
我们假设所有的节点:
3 ?0 _# @! o: G. y- s; [都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
* f' k( K" }' Q. A  ]/ g4 A; U, l
& N, i$ _0 \9 e7 j* ]所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。
) Q2 S9 q# G+ D" E- X一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
( y: M6 i8 I; m+ q+ ~对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。+ z  o, ?( _3 u3 T7 s( [$ h
Hash Dance
, E6 t* Z+ h6 [Block hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
% }- \; f: V' U0 lHash Dance起名源于Google Dance.) K1 j! |/ R  z, b" B
算力攻击的概率  L1 O1 P! [& `
本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
5 M8 k5 R) D2 }2 C算力攻击是一个概率问题,这里作简单叙述:
% Z4 ^6 h! N' M5 G8 |/ e) Wp = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率# G' \/ m* \& F

, {; U+ _2 p% T' N. G$ U; E  M& [, r/ n+ w
我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:8 I1 v! X; h  u# `4 ~( c: P  P+ u
9 B# }, u5 J" W' Z1 {" R
攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k, c( o  v; g  _4 c8 E/ i( Z

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33