深刻比特幣、以太坊源碼帶你解讀POW共識機制

概念

       全稱爲Proof Of Work,又叫工做量證實。POW是最先的共識機制。POW是指工做者經過必定的工做量,提供一個能被大多數驗證者快速驗證的答案,從而獲得獎勵的機制。git

原理

講原理以前,先給你們普及兩個概念:難度值和noncegithub

難度值

       難度值就是礦工挖礦成功的難度成程度,那這個是怎麼判斷的呢?咱們先學習一個公式:
        target值 = 最大目標值 / 難度值
        其中最大目標值是固定的,出塊以前,區塊鏈網絡設置了一個target值,target值越低,生成有效hash的集合就越小,生成有效hash就越困難。當前出塊難度值,它決定了大概須要通過多少次哈希運算才能產生一個合法的區塊。出塊以前,區塊鏈網絡設置了一個target值,target值越低,生成有效hash的集合就越小,生成有效hash就越困難。安全

nonce

       nonce值是什麼呢?它就是一個隨機數,系統區塊工做證實的參數。因爲給定的一組數據只能生成一個hash,礦工如何確保他們生成的hash小於target?它們經過添加一個稱爲nonce的整數(number only used once )來改變輸入的數據,一旦找到一個有效的hash,它就被廣播到網絡中,同時區塊被添加到區塊鏈中,找到這個nonce整數的礦工就能得到獎勵。網絡

原理

       上面兩個概念瞭解了以後呢,原理其實就很容易理解了。pow機制的原理其實就是:系統設定好挖礦難度(比特幣2016個塊以後從新計算,以太坊每次生成區塊都從新計算),而後礦工開始工做出塊,礦工每次出塊都是nonce從1開始遞增進行尋找可用的nonce值,直到找到符合規則、可用的hash爲止,最早找到的礦工可得到挖礦獎勵。ide

源碼解讀

理論咱們講的差很少了,你們坐穩扶好,接下來直接上代碼進行分析,一口氣讀完溫馨感最佳。函數

比特幣
static bool GenerateBlock(ChainstateManager& chainman, CBlock& block, uint64_t& max_tries, unsigned int& extra_nonce, uint256& block_hash)
{
	//  區塊hash置空
    block_hash.SetNull();

    {
        LOCK(cs_main);
        CHECK_NONFATAL(std::addressof(::ChainActive()) == std::addressof(chainman.ActiveChain()));
        IncrementExtraNonce(&block, chainman.ActiveChain().Tip(), extra_nonce);
    }

    CChainParams chainparams(Params());

	// 獲取可用nonce值
    while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) {
        ++block.nNonce;
        --max_tries;
    }
    if (max_tries == 0 || ShutdownRequested()) {
        return false;
    }
    if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
        return true;
    }

    std::shared_ptr<const CBlock> shared_pblock = std::make_shared<const CBlock>(block);
    if (!chainman.ProcessNewBlock(chainparams, shared_pblock, true, nullptr)) {
        throw JSONRPCError(RPC_INTERNAL_ERROR, "ProcessNewBlock, block not accepted");
    }

    block_hash = block.GetHash();
    return true;
}

計算nonce值的那一段咱們單獨進行分析學習

while (max_tries > 0 && block.nNonce < std::numeric_limits<uint32_t>::max() && !CheckProofOfWork(block.GetHash(), block.nBits, chainparams.GetConsensus()) && !ShutdownRequested()) {
    ++block.nNonce;
    --max_tries;
}

        1.首先判斷是否達到最大重試次數MaxTries > 0 ,maxTries默認值DEFAULT_MAX_TRIES爲1000000,達到最大重試次數未得到可用nonce,則該礦工這次挖礦失敗。區塊鏈

if (max_tries == 0 || ShutdownRequested()) {
   return false;
}

        2.判斷nNonce < std::numeric_limits<uint32_t>::max(),即控制nonce在一次挖礦做業中的隨機次數不得超過uint32的最大值。若是nNonce值修改的次數已經超過了規定的次數尚未找到工做量證實的一個解,則廢棄這個候選區塊,從新回到前面建立一個新的候選區塊。ui

if (block.nNonce == std::numeric_limits<uint32_t>::max()) {
    return true;
}

        3.執行CheckProofOfWork,源碼以下code

bool CheckProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params& params)
{
    bool fNegative;
    bool fOverflow;
    arith_uint256 bnTarget;

    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);

    // Check range
    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > UintToArith256(params.powLimit))
        return false;

    // Check proof of work matches claimed amount
    if (UintToArith256(hash) > bnTarget)
        return false;

    return true;
}

上面函數大概意思就是根據nBits難度值獲取到的target,是在可用區間內的,而且計算得出的hash小於target值,則本次hash爲可用hash值。
        4.未挖礦成功則一直循環計算,直到找到可用nonce值或上述一、二、3中某一步驟不符合while循環條件爲止。

以太坊

待整理

優勢

去中心化

將記帳權公平的分派到全部節點,記帳權是經過看節點的PoW, 誰挖礦最快, 誰就能拿到這個礦

安全

破解系統至少須要51%的節點,成本高,耗時長

去信任化

節點之間無需信任保證,經過零知識證實快速驗證安全性

缺點

出塊速度慢,共識時間長

       顧名思義,工做量證實須要大量的工做計算hash,花費的共識時間長,出塊速度慢。好比比特幣出塊時間10分鐘,每秒鐘支持最大交易數僅爲7筆。

能耗大

       挖礦須要大量的哈希運算,須要電力和各類算力資源,並且找到合適的哈希值實際上並無其餘的做用

算力集中化

       因爲礦池的出現,致使如今算力集中在幾家,BTC.COM,Antpool,ViaBTC前三大礦池,已經佔到了全網52.4%的算力水平。

思考

咱們看完文章就應該知道,pow的初衷就是它的破解複雜度,安全性高,pow的破解須要51%的節點纔可能實現。可是算力集中化的出現,致使前幾大礦池擁有的算力超過了51%,可能會出現他們聯合起來惡意出塊的現象,違背了pow的初衷。

比特幣源碼連接:https://github.com/bitcoin/bitcoin

相關文章
相關標籤/搜索