1. 程式人生 > >通過原始碼學習比特幣 -- 挖礦

通過原始碼學習比特幣 -- 挖礦

挖礦的過程就是區塊生成的過程 同時也是比特幣“發行”的過程。

1. 礦工節點通過暴力碰撞法找到滿足條件的雜湊值(下文詳述) 即為挖礦成功,從而獲取比特幣獎勵

  • 大約每十分鐘產生一個區塊, 每210000個區塊(大約4年)獎勵比特幣減半
  • 2009.1 – 50個比特幣, 2012.11 – 25個, 2016 – 12.5個
  • 到2040年, 總比特幣數量達到 2099 9999.98個
  • 2140年後 新區快不再獎勵新比特幣 礦工收益全部來自交易費

2. 礦工獎勵分為兩部分:coin base 交易獎勵 + 新建區塊中交易費用總和

下面是計算礦工獎勵的比特幣原始碼:

 int64_t GetBlockValue(int
nHeight, int64_t nFees) {// nFees = Sum(vin[i]) - Sum (vout[i]) 區塊包含的交易費用總和 int64_t nSubsidy = 50 * COIN; //COIN = 100000000 (一億聰),初始獎勵50比特幣 int nHalving = nHeight / 210000; //nHeight:區塊高度 if (nHalving >= 64) return nFees; nSubsidy >>= nHalving; //每210000個區塊獎勵減半(右移位操作 提高運算效率)
return nSubsidy + nFees; }

3. 交易發起者建立交易後,將其broadcast到相鄰節點。每個節點獨立的對接收到的交易進行驗證

下面是比特幣原始碼相關函式

   CheckInputs()CheckTransaction()AcceptToMemoryPool()

符合規則的交易被加入記憶體的交易池並broadcast到其他節點

4. 挖礦節點對記憶體交易池的交易按優先順序排序,由於區塊大小有限制 ,優先順序低的交易不能被打包進區塊

交易優先順序計算:


priority = sum (vin[i].value * vin[i] age)/sizeof(Tx)

- vin[i].value: 交易輸入金額 以聰為單位;
- vin[i] age : 交易輸入所指向的utxo所在的區塊的深度 (距離最新區塊高度的距離 每天增大144)

- 轉賬金額越大 所使用的utxo越老 位元組數越小 的交易優先順序越高!
- priority > 57600000 的tx 定義高優先順序;(100 000 000 satoshi * 144)/ 250 byte
- 每個區塊的前50k空間留給高優先順序的tx , 剩下的按照”交易費/Kb”由高到低排序 直到達到MAX_BLOCK_SIZE;
- 節點軟體重啟 記憶體交易池會被清空;
- 如果交易長時間未被加入區塊,交易發起節點應提高交易費重新發送;

5. 創幣交易:即上文提到的給礦工的coin base 交易獎勵, 作為每個新生成的block的第一筆交易

  • 只有一個vin, 其指向的utxo所在的交易hash為0x0000…(32位元組)
  • utxo 的輸出索引vout nOut 為0xFFFFFFFF 表示不指向任何UTXO;
  • 交易輸出金額為系統獎勵(目前為12.5BTC) 發給挖礦節點自己的地址,比特幣就是這麼發行的
  • 不包含scriptSig指令碼, 以區塊高度開頭,剩餘位元組可由礦工任意填充 (最大100位元組)

6. 挖礦演算法:通過不斷變換nNonce值 使SHA256(SHA256(區塊頭))的雜湊值小於等於目標雜湊值nhashTarget

  • nhashTarget 由區塊頭中的nBits值決定,其大小是依據全網算力不斷調整的,全網算力越高難度越大,從而使區塊生成速度保持在10分鐘左右

  • 難度值調整 函式: GetNextWorkRequired()

7. 區塊鏈分叉
- 節點依據最長鏈(最多工作量)原則選擇主鏈, 幾乎每週都會發生單塊的分叉,雙塊分叉幾乎很少發生;
- 當兩個塊A,B幾乎同時產生時, 節點會加入先收到的塊A,拋棄後收到的B(另一部分節點先收到B);
- 如果先收到B的節點又收到新塊C時,B->C作為最長鏈(主鏈)廣播到全網,A塊就會變成備用分叉鏈;
- 孤塊:節點收到一個新塊,它的父塊沒有在自己的鏈中找到,則將其加入孤塊池,直到接收到其父塊後再將其加入主鏈;
- 每10分鐘產生一個新塊,是在更快的交易確認速度和更少的分叉之間做出的權衡。

8. 51%攻擊:

  • 並不是擁有51%以上的算力才能攻擊,只是擁有的算力越高 成功的概率就越大,事實上 擁有30%的算力就可以嘗試攻擊。

  • 目前全網算力達到近40Eh/s, 承指數級增長

    1Eh == 1000Ph; 
    1Ph == 1000Th; 
    1Th == 1000Gh; 
    1Gh == 1000Mh; 
    1Mh==1000Kh  
    (h:hash/sha256)

9. 雙重支付攻擊

  • 小額交易A時(買咖啡) 商家不等交易A被區塊確認就交付了商品,這時買家又用同一個utxo進行另外一筆交易B(轉給自己的另外一個地址),這交易B就有可能先被加入礦工的區塊從而使交易A失效

  • 51% 算力使區塊鏈分叉

    當一筆交易A被加入到一個區塊中得到確認後,買家通過自己控制的擁有超高算力的礦池,生成一個交易B 並將交易A的utxo發給自己錢包 同時刪除交易A, 利用自己強大的算力生成分叉區塊並讓自己的分叉成為主鏈。之前交易A所在的區塊則成為了一個分叉…

  • 因此對於大額交易,一般要等至少6個區塊確認之後在交付商品,以避免51%算力雙重支付攻擊。

10. 拒絕服務攻擊

  • 擁有超級算力的節點或礦池, 通過刪除區塊中的某些特定地址的交易 從而使某些地址的交易一直不能被加入到區塊鏈。