區塊鍊小註解

最近比特幣 (bitcoin) 又紅了起來, 算算從我上次停止挖礦已經有三年多的時間了. 在這期間比特幣大幅升值, 不過挖礦的難度也上升了! 雖然我的比特幣錢包還能用, 挖礦軟體也還能挖, 但自己挖礦仍然不划算. 雲端挖礦又有龐式騙局, 真是沒意思啊!

除了比特幣本身, 其實我也更想了解區塊鍊 (block chain) 的原理. 坊間有很多講區塊鍊的書, 通常都是講區塊鍊有多偉大多偉大. 不過為何能夠做到去中間化、分散、公信力…這個就很少人討論了. 好比賣藥的都說人蔘是藥王, 但是人蔘皂苷為何能達到那個效果? 舌燦蓮花的導遊可說不上來. 為了明辨那些東西是可以做得到的, 我們還是回頭複習比特幣.

網路上有許多介紹比特幣的文章, 讀完 [1][2] 兩篇就會大概有個了解. 首先一個 block 的大小是 1MB, 這個格式以內用盡了之後, 就沒有新 bitcoin 了. 這是當初人們認為 bitcoin 不會有通貨膨脹的原因. 但人們總是不滿足的, 前幾天 (August 1st 2017, at 12:20pm UT) 硬是分裂了. 原本有一個比特幣 (bitcoin, BTC) 的人會得到一個比特幣 (BTC) 和一個比特幣現金 (BCC, bitcoin cash), 日後才挖的人就一分為二 [3].

礦場現在會問你要照舊? 隨便礦主處置? 還是挖新礦 (根據 NYA = the New York Agreement, hard fork) ?  但根據報導, 80% 的礦工都同意了 NYA [4]. 沒得挖全世界不就都沒搞頭了? 當然挖啊! 我看下一次的 split 也不會太遠了.

再回頭說第一個 block, 它應該是中本聰挖 (規定) 的吧! 也就是所謂的 genesis block [6]. 長相如下:

GetHash() = 0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
hashMerkleRoot = 0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
txNew.vin[0].scriptSig = 486604799 4 0x736B6E616220726F662074756F6C69616220646E6F63657320666F206B6E697262206E6F20726F6C6C65636E61684320393030322F6E614A2F33302073656D695420656854
txNew.vout[0].nValue = 5000000000
txNew.vout[0].scriptPubKey = 0x5F1DF16B2B704C8A578D0BBAF74D385CDE12C11EE50455F3C438EF4C3FBCF649B6DE611FEAE06279A60939E028A8D65C10B73071A6F16719274855FEB0FD8A6704 OP_CHECKSIG
block.nVersion = 1
block.nTime = 1231006505
block.nBits = 0x1d00ffff
block.nNonce = 2083236893

CBlock(hash=000000000019d6, ver=1, hashPrevBlock=00000000000000, hashMerkleRoot=4a5e1e, nTime=1231006505, nBits=1d00ffff, nNonce=2083236893, vtx=1)
CTransaction(hash=4a5e1e, ver=1, vin.size=1, vout.size=1, nLockTime=0)
CTxIn(COutPoint(000000, -1), coinbase 04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73)
CTxOut(nValue=50.00000000, scriptPubKey=0x5F1DF16B2B704C8A578D0B)
vMerkleTree: 4a5e1e

通用的格式如下所示:

Block structure [7]

Field Description Size (Bytes) Updated when…
Magic no value always 0xD9B4BEF9 4  
Blocksize number of bytes following up to end of block 4  
Blockheader consists of 6 items 80  由以下六項組成
– Version Block version number 4 You upgrade the software and it specifies a new version
– hashPrevBlock 256-bit hash of the previous block header 32 A new block comes in
– hashMerkleRoot 256-bit hash based on all of the transactions in the block 32 A transaction is accepted
– Time Current timestamp as seconds since 1970-01-01T00:00 UTC 4 Every few seconds
– Bits Current target in compact format 4 The difficulty is adjusted
– Nonce 32-bit number (starts at 0) 4 A hash is tried (increments)
Transaction counter positive integer VI = VarInt 1 – 9  
transactions the (non empty) list of transactions   <Transaction counter>-many transactions

每一個 block 都得包含前一個 block header 的 hash 值, 日後每一個新的 block 加入 block chain 之後,  都會定時更新所有的 block 的紀錄 – 也就是上表的 “updated when”, 保證大家的資訊都一致. 時間戳記則保障一個 block 不會分岔出兩個分支 – 相當於造假或是一個 bitcoin 賣給兩個人. 細節在大部分的網路文章裡面都有, 就暫且不提.

為何大家常常都是猜、挖, 而不是算呢? 這就要先看 proof-of-work [10] 的流程 [13] (如下圖). 我們先假設一個 block 就是答案, 然後加上前一個 block 的 header 和一個遞增的 nonce 去做 hash, 如果做出來的 hash > target value 才會被接受.

圖的右半部最簡單, 每個 block 都有一個 nonce, 就像 genesis block 的 nonce  = 2083236893, 後續的 block 的 nonce 會愈來愈大.

圖左半部在講難度 (difficulty) [9], 它也就是 block 格式中的 4 Bytes “Bits”. Difficulty 就是要讓挖礦愈來愈難, 這倒不是故意要為難挖礦的人, 而是讓造假的人得付出非常大的代價造出一個完整的 block chain.

系統每 2016 block 就會調整一次難度, 目標是每 10 分鐘生出一個 block, 若兩個星期沒有產出 2016 個 block, 難度就會降低. 根據速算公式[9]: 產生 1 個 block 的時間 = D(Difficult) * 232 / 600. D = 1, 7M Hash/s 可以產生一個 block.

圖的中間線是重點. 根據中本聰的原文, 他是參考 Adam Back 的 HashCash [11], 如下圖. 由於 bitcoin 用 SHA-256 從 bit string x 產生 256 bits 的 HASH, 下面公式中的 k 就是 256. MINT() 是 cost-function, VALUE() 是 evaluation function, 只是確認 T (token) 符合所需.

我的認知是: 用 s 和 x 兩個 bit string 兜成 s||x, 這個 string 經過 SHA-256 之後, 它的前 (左) w bit 若都是 0, 就符合所需 cost function 所需. 很多文章都在講前置 0 愈多愈複雜, 這就是原因了. 因為產生的 HASH 還特別指定長相 (0 的個數), 使得 x 的候選人變得更少. 這群有部分同樣 hash 結果的 bit strings 屬於 partial hash collisions.

Ref [6] 說到: “The hashcash cost-function is based on finding partial hash collisions on the all 0 bits k-bit string 0k. The fastest algorithm for computing partial collisions is brute force.” 換言之, 就是只能用暴力法把可能空間裡面的會產生 partial hash collision 的值都找出來.  

Ref [8] 說到, Honest generators only build onto a block (by referencing it in blocks they create) if it is the latest block in the longest valid chain. “Length” is calculated as total combined difficulty of that chain, not number of blocks, though this distinction is only important in the context of a few potential attacks. A chain is valid if all of the blocks and transactions within it are valid, and only if it starts with the genesis block.

新的 block 必須是從 genesis block 算起來, 能做出最長的 length (最大難度) 的那條路徑上的 block. 下圖 (取自 [8]) 綠色 block 是創世紀區塊 (genesis block), 黑色的 block 是 main chain. 紫色 block 雖然合乎規範, 但是不能用. 那些沒有用的 block 會變成孤兒, 價值為 0.

那怎麼保證我的 block 在 main chain 上呢? 根據 partial collision 的原理, 很有可能大家都發現不同的解答, 然後拼命往下衝! 那如果衝錯不就 GG 了? 根據 [2], 的確很有可能會做虛工! “從第一個區塊到各分支末端中所有區塊難度總和最高的分支稱為主分支,通常也是分支長度最長的。區塊要再經過100 次挖到礦後才被認為成熟,只有主分支上的成熟區塊才能獲得獎勵。”

根據以上的資訊, 雖然沒有 100% 的把握都是正確的. 但我大概可以推論, 大家都只看到區塊鍊建立好之後的優點, 卻忽略了區塊鍊建置的成本. 比特幣的成功建立在大家想賺錢的需求之上, 若任何企業想要建立區塊鍊, 卻不投資成本是不可能的. 先不說挖礦的過程可能會做虛功, 造成多餘的碳排放量. 依照 proof-of-work 的原理, 只要不誠實的 block 比誠實的更多, 整個結果就可以被改寫了. 這個風險真的超大, 歹徒可以弄個幾萬台殭屍電腦一起來投票, 並且把正主的網路切斷 10 分零一秒, 網路上大家都說錢是我的, 等你上線之後, 少數還得服從多數呢! 這個風險在比特幣不成立, 因為 client 眾多, 但新成立的區塊鍊簡直就是很好破啊~~

 

[REF]

  1. 比特幣 (Bit Coin) 到底是什麼?運作原理大揭密
  2. 道高一尺 魔高一丈:比特幣是怎麼回事?
  3. Before and After — the Great Bitcoin Fork
  4. Bitcoin Miners Are Signaling Support for the New York Agreement: Here’s What that Means
  5. SHA-2
  6. https://en.bitcoin.it/wiki/Genesis_block
  7. https://en.bitcoin.it/wiki/Block
  8. https://en.bitcoin.it/wiki/Block_chain
  9. https://en.bitcoin.it/wiki/Difficulty
  10. https://bitcoin.org/bitcoin.pdf
  11. http://www.hashcash.org/papers/hashcash.pdf
  12. https://blockchain.info/blocks/1231538600001
  13. https://www.bitcoinmining.com/what-is-proof-of-work/

 

Leave a Comment


NOTE - You can use these HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>