Difficulty-Retargetting
所有節點如何設置和驗證雜湊目標?
如標題所示 - 我知道節點會查看最近兩週計算的雜湊值並調整難度以使平均時間達到 10 分鐘。但是這到底是怎麼做的呢?
特別是,所有節點必須就相同的目標達成一致,否則新探勘的塊將對某些節點有效,而對其他節點無效。這似乎是一個非常困難的共識問題(在傳統意義上,不是比特幣方式),不是嗎?
難度調整算法如下(來自源碼):
unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params& params) { if (params.fPowNoRetargeting) return pindexLast->nBits; // Limit adjustment step int64_t nActualTimespan = pindexLast->GetBlockTime() - nFirstBlockTime; if (nActualTimespan < params.nPowTargetTimespan/4) nActualTimespan = params.nPowTargetTimespan/4; if (nActualTimespan > params.nPowTargetTimespan*4) nActualTimespan = params.nPowTargetTimespan*4; // Retarget const arith_uint256 bnPowLimit = UintToArith256(params.powLimit); arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); bnNew *= nActualTimespan; bnNew /= params.nPowTargetTimespan; if (bnNew > bnPowLimit) bnNew = bnPowLimit; return bnNew.GetCompact(); }
調整僅在 2016 年區塊執行一次。它的作用是獲取上一周期開始時(2016 個區塊之前)的區塊時間戳和調整難度之前區塊的時間戳。然後使用這些時間戳來計算間隔中的第一個塊和間隔中的最後一個塊之間經過的時間量。然後將該時間跨度限制為目標時間跨度的至少 1/4 和目標時間跨度的最多 4 倍。要計算此間隔的新難度,該目標乘以實際經過的時間量,然後除以目標時間量。
由於所有節點都在同一塊計算目標,並且使用相同的先前數據,因此目標計算是確定性的,每個人都會落在同一個目標上。