Hi 游客

更多精彩,请登录!

比特池塘 区块链前沿 正文

比特币工作证明与挖矿

天然灵凡
85 0 0
工作证明
- }0 S6 ^2 O. a! s工作证明(Proof Of Work,简称POW),顾名思义,即工作量的证明。通常来说只能从结果证明,因为监测工作过程通常是繁琐与低效的。4 U5 E: j& \: r# c
比特币在Block的生成过程中使用了POW机制,一个符合要求的Block Hash由N个前导零构成,零的个数取决于网络的难度值。要得到合理的Block Hash需要经过大量尝试计算,计算时间取决于机器的哈希运算速度。当某个节点提供出一个合理的Block Hash值,说明该节点确实经过了大量的尝试计算,当然,并不能得出计算次数的绝对值,因为寻找合理hash是一个概率事件。当节点拥有占全网n%的算力时,该节点即有n/100的概率找到Block Hash。$ \% g+ {* ], u- S
工作证明机制看似很神秘,其实在社会中的应用非常广泛。例如,毕业证、学位证等证书,就是工作证明,拥有证书即表明你在过去投入了学习与工作。生活大部分事情都是通过结果来判断的。
' ^( F8 r4 c5 K# C1 g  ?; i# ^挖矿
& P, `0 N, Q4 C) \挖矿即不断接入新的Block延续Block Chain的过程。4 S) p8 q, N$ x! p0 r, V6 P
6 l" L$ q3 O1 s  U' c: Y' |
挖矿为整个系统的运转提供原动力,是比特币的发动机,没有挖矿就没有比特币。挖矿有三个重要功能:
/ C5 @/ Q2 P- }. \3 _发行新的货币(总量达到之前)维系货币的支付功能通过算力保障系统安全
7 ^3 p/ H0 e9 x. t) ]金矿消耗资源将黄金注入流通经济,比特币通过“挖矿”完成相同的事情,只不过消耗的是CPU时间与电力。当然,比特币的挖矿意义远大于此。9 [1 j" `0 {/ T  e" ?; w

+ P$ n* j9 Z0 N+ `  `Block Hash算法
/ `2 r) L. Q  o- q% XBlock头部信息的构成:, B% O% ]- g& A9 z) {* v# W+ O

9 I& j2 [) B8 A* _: w下面采用高度为125552的block数据为例,演示block hash的计算过程:
2 N- `& ]- R0 L- ?/ ^2 o, Z
; j6 t* F5 C6 p9 m$ _7 D: D, c该计算过程简单明了:首先将数个字段合并成一块数据,然后对这块数据进行双SHA256运算。
* ~. j0 \# X& P产量调节
2 Z0 R, x( l. b5 h7 s6 C2 K+ v+ sBlock的产量为大约每两周2016个,即每10分钟一块。该规则在每个节点的代码里都固定了。
- n% H  Z2 f+ f// 目标时间窗口长度:两周. s" I2 d) p5 ]0 w$ q0 B$ c
static const int64 nTargetTimespan = 14 * 24 * 60 * 60;
( e! S- p8 E6 `  z+ y// block频率,每10分钟一块
) X' }, C5 g% V4 `, B0 @/ Ystatic const int64 nTargetSpacing  = 10 * 60;
, B5 \7 k% o* v# U( E3 }0 U4 G+ C7 a3 {// 每两周的产量2016,也是调节周期9 Z% e* f8 F, Q2 [2 ]
static const int64 nInterval       = nTargetTimespan / nTargetSpacing;* Q) P9 Q5 A6 V
但由于实际算力总是不断变化的(目前一直是快速上升的),所以需根据最近2016个块的耗费时间来调整难度值,维持每10分钟一个block的频率.
" t0 C7 R5 d5 P& O// Only change once per interval
$ b9 P, m5 Q) @& p+ G% dif ((pindexLast->nHeight+1) % nInterval != 0) {
# s' c# `# ?( @+ Y  G    // 未达到周期个数,无需调节- I' _0 j& G0 A* Y1 t& d
    return pindexLast->nBits;
) K  `7 L; u: g4 d$ v}9 i. e/ o$ w, O* W1 ^
// Go back by what we want to be 14 days worth of blocks( G7 n% ~( @- _. o/ J9 ^
const CBlockIndex* pindexFirst = pindexLast;! J: J) e7 P, }/ J1 \
for (int i = 0; pindexFirst && i pprev;  V+ _( L8 m6 r
// 计算本次2016个块的实际产生时间( b6 X) v3 ^: Z; \1 N; Z6 R( M
// Limit adjustment step, A& h/ Y( [$ F2 |" q
int64 nActualTimespan = pindexLast->GetBlockTime() - pindexFirst->GetBlockTime();
6 }, i# @: d5 w' J8 A4 b7 {9 m// 限定幅度,最低为1/4,最高为4倍6 V% J4 ^1 i) P( d# f
if (nActualTimespan  nTargetTimespan*4)# c( m8 c1 u5 O6 c
    nActualTimespan = nTargetTimespan*4;7 O8 z1 f: K/ x" {8 R3 B
// 根据最近2016个块的时间,重新计算目标难度
. X  b) m+ r. ?2 `* {6 l// Retarget
/ ^5 V& [+ p7 C/ u* ]CBigNum bnNew;
2 W* ^+ O; U. J# N4 ybnNew.SetCompact(pindexLast->nBits);
  n# F/ g" _' ?bnNew *= nActualTimespan;: F. c; L! V1 }" s
bnNew /= nTargetTimespan;* e/ u. `6 d* w% h& u, H9 y+ O1 D9 `

+ d+ y" z. \. k$ i  E3 ?if (bnNew > bnProofOfWorkLimit)6 c0 H. g) Y3 m% G) v
    bnNew = bnProofOfWorkLimit;8 U1 [; b" [* ], m
4 ]- L, ~7 q8 g
return bnNew.GetCompact();; L1 O2 b( M2 P: K& b! e7 L/ ^) |: q5 \
Block字段详解1 S" T9 f, `0 V2 q/ Q  ^
Version,版本号,很少变动,一般用于软件全网升级时做标识hashPrevBlock,前向Block Hash值,该字段强制多个Block之间形成链接hashMerkleRoot,交易Hash树的根节点Hash值,起校验作用,保障Block在网络传输过程中的数据一致性,有新交易加入即发生变化Time,Unix时间戳,每秒自增一,标记Block的生成时间,同时为block hash探寻引入一个频繁的变动因子Bits,可以推算出难度值,用于验证block hash难度是否达标Nonce,随机数,在上面数个字段都固定的情况下,不停地更换随机数来探寻5 m1 n5 h; m5 @# v! G) a
最为关键的字段是hashPrevBlock,该字段使得Block之间链接起来,形成一个巨大的“链条”。Block本是稀松平常的数据结构,但以链式结构组织起来后却使得它们具有非常深远的意义:
9 |& l8 V% N% @3 q

, ^$ N8 B- y0 ]0 F形成分支博弈,使得算力总是在主分支上角逐算力攻击的概率难度呈指数上升(泊松分布)
. d% D) W. \0 h
* Y3 j2 V6 X1 v: [5 j每个block都必须指向前一个block,否则无法验证通过。追溯至源头,便是高度为零的创世纪块(Genesis Block),这里是Block Chain的起点,其前向block hash为零,或者说为空。: m& r+ e6 C8 d5 ?! _& b7 G; {
新block诞生过程
% B+ m5 E0 G! r" D下面是一个简单的步骤描述,实际矿池运作会有区别,复杂一些:
3 S( K5 p8 T, C7 l  h, Y3 M节点监听全网交易,通过验证的交易进入节点的内存池(Tx Mem Pool),并更新交易数据的Merkle Hash值更新时间戳尝试不同的随机数(Nonce),进行hash计算重复该过程至找到合理的hash打包block:先装入block meta信息,然后是交易数据对外部广播出新block其他节点验证通过后,链接至Block Chain,主链高度加一,然后切换至新block后面挖矿
0 {0 X. Q  A+ N. b3 z3 e由于hashPrevBlock字段的存在,使得大家总是在最新的block后面开挖,稍后会分析原因。( x. X% i4 k4 X9 |# s5 F6 z. q/ x! e

: u1 ~! [; ^+ j' R主链分叉- W) @  s8 \  g, o0 K  ~
从block hash算法我们知道,合理的block并不是唯一的,同一高度存在多个block的可能性。那么,当同一个高度出现多个时,主链即出现分叉(Fork)。遇到分叉时,网络会根据下列原则选举出Best Chain:
4 u. G# f1 G. t( H/ q0 ]0 |不同高度的分支,总是接受最高(即最长)的那条分支
+ g3 v$ _/ r2 Z2 Z相同高度的,接受难度最大的
  h9 T/ m+ U5 ?! h+ s8 a3 n$ Y高度相同且难度一致的,接受时间最早的
. q! I1 F# ^; X  W' w# ?若所有均相同,则按照从网络接受的顺序
0 e' ]( A4 E9 U等待Block Chain高度增一,则重新选择Best Chain
# C  q$ X, ]6 d7 ]: k! e* z9 c
  U# F: d7 j; M1 ?- M' `按照这个规则运作的节点,称为诚实节点(Honest Nodes)。节点可以诚实也可以不诚实。6 C  I; F/ P6 `% J/ V
分支博弈) X  S0 F8 H% W% a0 V$ j5 n
我们假设所有的节点:
( _' F1 c* b. g# A9 e' G! S都是理性的,追求收益最大化都是不诚实的,且不惜任何手段获取利益
  X6 {& m: i* E5 N! |# g& t9 H7 u0 K" @. Z; u" l
所有节点均独自挖矿不理会其他节点,并将所得收益放入自己口袋,现象就是一个节点挖一个分支。由于机器的配置总是有差别的,那么算力最强的节点挖得的分支必然是最长的,如果一个节点的分支不是最长的,意味其收益存在不被认可的风险(即零收益)。为了降低、逃避此风险,一些节点肯定会联合起来一起挖某个分支,试图成为最长的分支或保持最长分支优势。
& b6 @7 h$ S8 B一旦出现有少量的节点联合,那么其他节点必然会效仿,否则他们收益为零的风险会更大。于是,分支迅速合并汇集,所有节点都会选择算力更强的分支,只有这样才能保持收益风险最小。最终,只会存在一个这样的分支,就是主干分支(Best/Main Chain)。
; J( `# q$ P6 U% M对于不诚实节点来说,结局是无奈的:能且只能加入主干挖矿。不加入即意味被抛弃,零收益;加入就是老实干活,按占比分成。
$ l% g+ r: U" {' w0 ~7 e8 [! wHash Dance
+ e0 g2 |7 M/ m/ f8 s, `% gBlock hash的计算是随机概率事件,当有节点广播出难度更高的block后,大家便跑到那个分支。在比特币系统运行过程中,算力经常在分支间跳来跳去,此现象称为Hash Dance。一般情况下,分支的高度为1~2,没有大的故障很难出现高于2的分支。
1 s5 w1 V& L5 G  b( `7 BHash Dance起名源于Google Dance.
: r1 @5 J, J: v3 f7 o6 i算力攻击的概率
& L3 x9 m0 ~% ?# W# T) _  G本节内容参考:Bitcoin: A Peer-to-Peer Electronic Cash System
6 d/ V. Z6 S/ {! o+ c算力攻击是一个概率问题,这里作简单叙述:
) k3 W2 L' S# C7 pp = 诚实节点挖出block概率q = 攻击者挖出block概率,q = 1 - pqz = 攻击者从z个block追上的概率7 d9 E: r) j& e' f

% q: i5 s0 S8 c& l1 D+ i& K; J% G  s- m8 Z' J7 w' G$ E8 k
我们假设p>q,否则攻击者掌握了一半以上的算力,那么概率上永远是赢的。该事件(攻击者胜出)的概率是固定,且N次事件之间是相互独立的,那么这一系列随机过程符合泊松分布(Poisson Distribution)。Z个块时,攻击者胜出的期望为lambda:
/ g0 n$ X' W4 P, \. m' {' t
& E- g& g9 M8 b$ N( v攻击者在攻击时已经偷偷的计算了k个块,那么这k个块概率符合泊松分布(下图左侧部分),若k
3 v. o+ q8 \$ O8 R$ \
$ P/ g' Z! Z& s" Y7 e展开为如下形式:7 ^$ T8 x  H  r+ C" m( M; P$ P+ u

1 B7 H) e( D' b! Y: P1 [计算该过程的C语言代码如下:1 U4 G7 W6 Z) J' b
#include
% I3 v) Z& k0 P4 v" d7 P4 J: Hdouble AttackerSuccessProbability(double q, int z)* A2 o% p, t, u6 A8 r0 E8 s& z
{1 l- y3 g8 W! a3 k" ~
    double sum    = 1.0;
: c* f! r. v8 D; A2 N    double p      = 1.0 - q;+ C% M7 Q) a& N+ S* b/ X, k; I
    double lambda = z * (q / p);9 O! {# k) R. g/ S
    int i, k;9 t" K/ B- M" C5 T' m  M) o
    for (k = 0; k ' Z; o8 I1 L2 u; o; p
我们选取几个值,结果如下:6 @4 x! a: y& o! n+ N

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

本版积分规则

成为第一个吐槽的人

天然灵凡 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    33