btc的挖矿原理
这段代码是比特币(Bitcoin)或其衍生项目之一的矿工模块的实现。它负责构建新的区块,并将其添加到区块链中。以下是对代码的详细解释:
主要功能
-
更新区块时间(UpdateTime):
int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParams, const CBlockIndex* pindexPrev) { int64_t nOldTime = pblock->nTime; int64_t nNewTime = std::max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); if (nOldTime < nNewTime) pblock->nTime = nNewTime; if (consensusParams.fPowAllowMinDifficultyBlocks) pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, consensusParams); return nNewTime - nOldTime; }
这个函数更新区块的时间戳,并在必要时调整工作难度。
-
BlockAssembler 类:
BlockAssembler
类负责从内存池中选择交易并构建新的区块。-
构造函数和默认选项:
BlockAssembler::Options::Options() { blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT; } BlockAssembler::BlockAssembler(const CChainParams& params, const Options& options) : chainparams(params) { blockMinFeeRate = options.blockMinFeeRate; nBlockMaxWeight = std::max
(4000, std::min (MAX_BLOCK_WEIGHT - 4000, options.nBlockMaxWeight)); } static BlockAssembler::Options DefaultOptions() { BlockAssembler::Options options; options.nBlockMaxWeight = gArgs.GetArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT); if (gArgs.IsArgSet("-blockmintxfee")) { CAmount n = 0; ParseMoney(gArgs.GetArg("-blockmintxfee", ""), n); options.blockMinFeeRate = CFeeRate(n); } else { options.blockMinFeeRate = CFeeRate(DEFAULT_BLOCK_MIN_TX_FEE); } return options; } BlockAssembler::BlockAssembler(const CChainParams& params) : BlockAssembler(params, DefaultOptions()) {} -
重置区块状态:
void BlockAssembler::resetBlock() { inBlock.clear(); nBlockSize = 1000; nBlockWeight = 4000; nBlockSigOpsCost = 400; fIncludeWitness = false; nBlockTx = 0; nFees = 0; }
-
创建新块(CreateNewBlock):
std::unique_ptr
BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx) { int64_t nTimeStart = GetTimeMicros(); resetBlock(); pblocktemplate.reset(new CBlockTemplate()); if(!pblocktemplate.get()) return nullptr; pblock = &pblocktemplate->block; pblock->vtx.emplace_back(); pblocktemplate->vTxFees.push_back(-1); pblocktemplate->vTxSigOpsCost.push_back(-1); LOCK2(cs_main, mempool.cs); CBlockIndex* pindexPrev = chainActive.Tip(); assert(pindexPrev != nullptr); nHeight = pindexPrev->nHeight + 1; const int32_t nChainId = chainparams.GetConsensus().nAuxpowChainId; const int32_t nVersion = 4; pblock->SetBaseVersion(nVersion, nChainId); if (chainparams.MineBlocksOnDemand()) pblock->SetBaseVersion(gArgs.GetArg("-blockversion", pblock->GetBaseVersion()), nChainId); pblock->nTime = GetAdjustedTime(); const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast(); nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) ? nMedianTimePast : pblock->GetBlockTime(); fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx; int nPackagesSelected = 0; int nDescendantsUpdated = 0; addPackageTxs(nPackagesSelected, nDescendantsUpdated); int64_t nTime1 = GetTimeMicros(); nLastBlockTx = nBlockTx; nLastBlockSize = nBlockSize; nLastBlockWeight = nBlockWeight; CMutableTransaction coinbaseTx; coinbaseTx.vin.resize(1); coinbaseTx.vin[0].prevout.SetNull(); coinbaseTx.vout.resize(1); coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn; coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus()); coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0; pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx)); pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus()); pblocktemplate->vTxFees[0] = -nFees; uint64_t nSerializeSize = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION); LogPrintf("CreateNewBlock(): total size: %u block weight: %u txs: %u fees: %ld sigops %d/n", nSerializeSize, GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost); pblock->hashPrevBlock = pindexPrev->GetBlockHash(); UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus()); pblock->nNonce = 0; pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); CValidationState state; if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) { throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state))); } int64_t nTime2 = GetTimeMicros(); LogPrint(BCLog::BENCH, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)/n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart)); return std::move(pblocktemplate); }
-
-
交易选择和添加:
- onlyUnconfirmed:确保只测试未确认的交易。
- TestPackage:检查交易包是否符合区块的大小和操作数限制。
- TestPackageTransactions:检查交易包中的每个交易是否符合最终性和见证数据的要求。
- AddToBlock:将交易添加到区块中,并更新相关统计信息。
- UpdatePackagesForAdded:更新已添加交易的后代交易。
- SkipMapTxEntry:跳过已经在区块中的交易或已经失败的交易。
- SortForBlock:对交易包进行排序,以确保交易的依赖关系正确。
- addPackageTxs:选择交易包并添加到区块中。
-
增加额外的Nonce(IncrementExtraNonce):
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce) { static uint256 hashPrevBlock; if (hashPrevBlock != pblock->hashPrevBlock) { nExtraNonce = 0; hashPrevBlock = pblock->hashPrevBlock; } ++nExtraNonce; unsigned int nHeight = pindexPrev->nHeight+1; CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS; assert(txCoinbase.vin[0].scriptSig.size() <= 100); pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase)); pblock->hashMerkleRoot = BlockMerkleRoot(*pblock); }
这个函数更新区块的额外Nonce值,以确保区块哈希的唯一性。
总结
这段代码实现了比特币矿工模块的核心功能,包括构建新块、选择和添加交易、更新区块时间和难度、以及处理额外的Nonce值。这些功能对于维护区块链的安全性和一致性至关重要。
构建区块并将其加入到已有链中是一个复杂的过程,涉及多个步骤。以下是一个简化的流程,结合代码中的关键点来解释如何构建区块并将其加入到已有链中。
1. 初始化和重置区块
在构建新块之前,我们需要初始化和重置一些状态变量。
void BlockAssembler::resetBlock()
{
inBlock.clear();
nBlockSize = 1000;
nBlockWeight = 4000;
nBlockSigOpsCost = 400;
fIncludeWitness = false;
nBlockTx = 0;
nFees = 0;
}
2. 创建新块模板
我们使用 CreateNewBlock
函数来创建一个新的区块模板。
std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& scriptPubKeyIn, bool fMineWitnessTx)
{
int64_t nTimeStart = GetTimeMicros();
resetBlock();
pblocktemplate.reset(new CBlockTemplate());
if (!pblocktemplate.get())
return nullptr;
pblock = &pblocktemplate->block;
// Add dummy coinbase tx as first transaction
pblock->vtx.emplace_back();
pblocktemplate->vTxFees.push_back(-1);
pblocktemplate->vTxSigOpsCost.push_back(-1);
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
assert(pindexPrev != nullptr);
nHeight = pindexPrev->nHeight + 1;
const int32_t nChainId = chainparams.GetConsensus().nAuxpowChainId;
const int32_t nVersion = 4;
pblock->SetBaseVersion(nVersion, nChainId);
if (chainparams.MineBlocksOnDemand())
pblock->SetBaseVersion(gArgs.GetArg("-blockversion", pblock->GetBaseVersion()), nChainId);
pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST) ? nMedianTimePast : pblock->GetBlockTime();
fIncludeWitness = IsWitnessEnabled(pindexPrev, chainparams.GetConsensus()) && fMineWitnessTx;
int nPackagesSelected = 0;
int nDescendantsUpdated = 0;
addPackageTxs(nPackagesSelected, nDescendantsUpdated);
int64_t nTime1 = GetTimeMicros();
nLastBlockTx = nBlockTx;
nLastBlockSize = nBlockSize;
nLastBlockWeight = nBlockWeight;
// Create coinbase transaction.
CMutableTransaction coinbaseTx;
coinbaseTx.vin.resize(1);
coinbaseTx.vin[0].prevout.SetNull();
coinbaseTx.vout.resize(1);
coinbaseTx.vout[0].scriptPubKey = scriptPubKeyIn;
coinbaseTx.vout[0].nValue = nFees + GetBlockSubsidy(nHeight, chainparams.GetConsensus());
coinbaseTx.vin[0].scriptSig = CScript() << nHeight << OP_0;
pblock->vtx[0] = MakeTransactionRef(std::move(coinbaseTx));
pblocktemplate->vchCoinbaseCommitment = GenerateCoinbaseCommitment(*pblock, pindexPrev, chainparams.GetConsensus());
pblocktemplate->vTxFees[0] = -nFees;
uint64_t nSerializeSize = GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION);
LogPrintf("CreateNewBlock(): total size: %u block weight: %u txs: %u fees: %ld sigops %d/n", nSerializeSize, GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, chainparams.GetConsensus());
pblock->nNonce = 0;
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
int64_t nTime2 = GetTimeMicros();
LogPrint(BCLog::BENCH, "CreateNewBlock() packages: %.2fms (%d packages, %d updated descendants), validity: %.2fms (total %.2fms)/n", 0.001 * (nTime1 - nTimeStart), nPackagesSelected, nDescendantsUpdated, 0.001 * (nTime2 - nTime1), 0.001 * (nTime2 - nTimeStart));
return std::move(pblocktemplate);
}
3. 选择并添加交易
在 CreateNewBlock
函数中,通过调用 addPackageTxs
函数来选择和添加交易。
void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated)
{
indexed_modified_transaction_set mapModifiedTx;
CTxMemPool::setEntries failedTx;
UpdatePackagesForAdded(inBlock, mapModifiedTx);
CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin();
CTxMemPool::txiter iter;
const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
int64_t nConsecutiveFailed = 0;
while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty())
{
if (mi != mempool.mapTx.get().end() && SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) {
++mi;
continue;
}
bool fUsingModified = false;
modtxscoreiter modit = mapModifiedTx.get().begin();
if (mi == mempool.mapTx.get().end()) {
iter = modit->iter;
fUsingModified = true;
} else {
iter = mempool.mapTx.project<0>(mi);
if (modit != mapModifiedTx.get().end() && CompareTxMemPoolEntryByAncestorFee()(*modit, CTxMemPoolModifiedEntry(iter))) {
iter = modit->iter;
fUsingModified = true;
} else {
++mi;
}
}
assert(!inBlock.count(iter));
uint64_t packageSize = iter->GetSizeWithAncestors();
CAmount packageFees = iter->GetModFeesWithAncestors();
int64_t packageSigOpsCost = iter->GetSigOpCostWithAncestors();
if (fUsingModified) {
packageSize = modit->nSizeWithAncestors;
packageFees = modit->nModFeesWithAncestors;
packageSigOpsCost = modit->nSigOpCostWithAncestors;
}
if (packageFees < blockMinFeeRate.GetFee(packageSize)) {
return;
}
if (!TestPackage(packageSize, packageSigOpsCost)) {
if (fUsingModified) {
mapModifiedTx.get().erase(modit);
failedTx.insert(iter);
}
++nConsecutiveFailed;
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight > nBlockMaxWeight - 4000) {
break;
}
continue;
}
CTxMemPool::setEntries ancestors;
uint64_t nNoLimit = std::numeric_limits::max();
std::string dummy;
mempool.CalculateMemPoolAncestors(*iter, ancestors, nNoLimit, nNoLimit, nNoLimit, nNoLimit, dummy, false);
onlyUnconfirmed(ancestors);
ancestors.insert(iter);
if (!TestPackageTransactions(ancestors)) {
if (fUsingModified) {
mapModifiedTx.get().erase(modit);
failedTx.insert(iter);
}
continue;
}
nConsecutiveFailed = 0;
std::vector sortedEntries;
SortForBlock(ancestors, sortedEntries);
for (size_t i=0; i
4. 验证区块有效性
在 CreateNewBlock
函数的最后,我们调用 TestBlockValidity
函数来验证区块的有效性。
CValidationState state;
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}
5. 增加额外的Nonce
为了确保区块哈希的唯一性,我们需要增加额外的Nonce值。
void IncrementExtraNonce(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
static uint256 hashPrevBlock;
if (hashPrevBlock != pblock->hashPrevBlock)
{
nExtraNonce = 0;
hashPrevBlock = pblock->hashPrevBlock;
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight+1;
CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
}
6. 将区块加入到区块链中
当区块构建完成并通过验证后,矿工将尝试找到一个有效的哈希值(即满足当前难度目标的哈希值),并将区块广播到网络中。一旦区块被其他节点接受并验证,它将被加入到区块链中。
总结
构建区块并将其加入到已有链中涉及多个步骤,包括初始化和重置区块状态、创建区块模板、选择和添加交易、验证区块有效性、增加额外的Nonce值,以及最终将区块广播到网络中。每个步骤都需要严格遵循区块链协议,以确保区块链的安全性和一致性。
在区块链(特别是比特币)中,Nonce(数字计数器)是一个关键元素,用于确保区块哈希值满足网络难度目标。以下是关于Nonce的详细解释,以及如何确定有效哈希的方法。
额外的Nonce值的作用
-
确保哈希的唯一性:
Nonce是一个可变的数字,用于生成不同的区块哈希值。通过不断改变Nonce值,矿工可以尝试找到一个满足网络难度目标的哈希值。 -
解决哈希碰撞:
当矿工在尝试不同的Nonce值时,可能会遇到哈希碰撞(即不同的Nonce值产生相同的哈希)。通过增加额外的Nonce值,可以进一步增加哈希的多样性,避免碰撞。 -
增加搜索空间:
Nonce值的范围是有限的(32位无符号整数),当所有可能的Nonce值都被尝试后,矿工可以通过增加额外的Nonce值来扩展搜索空间。
如何确定有效哈希
一个有效的区块哈希必须满足当前的难度目标,即哈希值的前若干个比特必须为零。具体步骤如下:
-
更新区块头信息:
在每次尝试新的Nonce值时,矿工需要更新区块头信息,包括时间戳和Merkle根哈希。 -
计算区块哈希:
使用SHA-256哈希函数计算区块头的哈希值。 -
比较哈希值与难度目标:
将计算得到的哈希值与当前的难度目标进行比较。如果哈希值小于或等于难度目标,则该哈希值是有效的。
代码示例
以下是如何在代码中实现这些步骤的示例:
1. 更新区块头信息
首先,我们需要更新区块的时间戳和Merkle根哈希。
void UpdateBlockHeader(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
static uint256 hashPrevBlock;
if (hashPrevBlock != pblock->hashPrevBlock)
{
nExtraNonce = 0;
hashPrevBlock = pblock->hashPrevBlock;
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight + 1;
CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
}
2. 计算区块哈希
使用SHA-256哈希函数计算区块头的哈希值。
uint256 CalculateBlockHash(const CBlockHeader& blockHeader)
{
return blockHeader.GetHash();
}
3. 比较哈希值与难度目标
将计算得到的哈希值与当前的难度目标进行比较。
bool IsValidHash(const uint256& hash, const uint256& target)
{
return hash <= target;
}
4. 综合示例
综合以上步骤,矿工在尝试找到有效哈希时的代码逻辑如下:
void MineBlock(CBlock* pblock, const CBlockIndex* pindexPrev, const uint256& target)
{
unsigned int nExtraNonce = 0;
while (true)
{
UpdateBlockHeader(pblock, pindexPrev, nExtraNonce);
for (unsigned int nonce = 0; nonce < std::numeric_limits::max(); ++nonce)
{
pblock->nNonce = nonce;
uint256 hash = CalculateBlockHash(*pblock);
if (IsValidHash(hash, target))
{
std::cout << "Found valid hash: " << hash.ToString() << std::endl;
return;
}
}
}
}
总结
Nonce值和额外的Nonce值在区块链中用于确保区块哈希的唯一性和满足难度目标。通过不断尝试不同的Nonce值,矿工可以找到一个有效的哈希值,使其满足当前的难度目标。这个过程称为“挖矿”,是区块链共识机制的核心部分。
在比特币及其衍生的许多区块链系统中,难度目标的设定是通过比较计算出的哈希值和一个目标值(目标哈希)来实现的。具体来说,计算出的哈希值必须小于或等于这个目标值。这个目标值通常表示为一个大整数,难度目标越高,这个整数越小。
难度目标与哈希值的比较
-
目标值的表示:
目标值通常表示为一个大整数,称为“目标哈希”。这个值越小,难度越高。 -
哈希值的比较:
矿工计算出的区块哈希值必须小于或等于这个目标值,才能被认为是有效的。
具体实现
1. 目标值的计算
目标值是根据当前的难度目标计算出来的。难度目标通常以一个称为“bits”的压缩格式存储在区块头中。
uint256 GetTargetFromBits(uint32_t nBits)
{
int nShift = (nBits >> 24) & 0xff;
uint256 target = nBits & 0xffffff;
if (nShift <= 3) {
target >>= 8 * (3 - nShift);
} else {
target <<= 8 * (nShift - 3);
}
return target;
}
2. 计算区块哈希
矿工需要计算区块头的哈希值。比特币使用的是双重SHA-256哈希函数。
uint256 CalculateBlockHash(const CBlockHeader& blockHeader)
{
return blockHeader.GetHash();
}
3. 比较哈希值与目标值
计算出的哈希值必须小于或等于目标值,才能被认为是有效的。
bool IsValidHash(const uint256& hash, const uint256& target)
{
return hash <= target;
}
综合示例
以下是一个综合示例,展示了如何在代码中实现这些步骤:
#include
#include
#include "uint256.h"
#include "block.h"
void UpdateBlockHeader(CBlock* pblock, const CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
{
static uint256 hashPrevBlock;
if (hashPrevBlock != pblock->hashPrevBlock)
{
nExtraNonce = 0;
hashPrevBlock = pblock->hashPrevBlock;
}
++nExtraNonce;
unsigned int nHeight = pindexPrev->nHeight + 1;
CMutableTransaction txCoinbase(*pblock->vtx[0]);
txCoinbase.vin[0].scriptSig = (CScript() << nHeight << CScriptNum(nExtraNonce)) + COINBASE_FLAGS;
assert(txCoinbase.vin[0].scriptSig.size() <= 100);
pblock->vtx[0] = MakeTransactionRef(std::move(txCoinbase));
pblock->hashMerkleRoot = BlockMerkleRoot(*pblock);
}
uint256 GetTargetFromBits(uint32_t nBits)
{
int nShift = (nBits >> 24) & 0xff;
uint256 target = nBits & 0xffffff;
if (nShift <= 3) {
target >>= 8 * (3 - nShift);
} else {
target <<= 8 * (nShift - 3);
}
return target;
}
uint256 CalculateBlockHash(const CBlockHeader& blockHeader)
{
return blockHeader.GetHash();
}
bool IsValidHash(const uint256& hash, const uint256& target)
{
return hash <= target;
}
void MineBlock(CBlock* pblock, const CBlockIndex* pindexPrev, const uint256& target)
{
unsigned int nExtraNonce = 0;
while (true)
{
UpdateBlockHeader(pblock, pindexPrev, nExtraNonce);
for (unsigned int nonce = 0; nonce < std::numeric_limits::max(); ++nonce)
{
pblock->nNonce = nonce;
uint256 hash = CalculateBlockHash(*pblock);
if (IsValidHash(hash, target))
{
std::cout << "Found valid hash: " << hash.ToString() << std::endl;
return;
}
}
}
}
解释
-
GetTargetFromBits:从压缩格式的
nBits
计算出目标值。 - CalculateBlockHash:计算区块头的哈希值。
- IsValidHash:比较哈希值与目标值,判断是否有效。
- MineBlock:矿工不断尝试不同的Nonce值,直到找到一个有效的哈希。
总结
在比特币及其衍生的区块链系统中,难度目标的设定是通过比较计算出的哈希值和一个目标值来实现的。目标值表示为一个大整数,难度越高,这个整数越小。矿工通过不断尝试不同的Nonce值,计算区块头的哈希值,并与目标值进行比较,直到找到一个有效的哈希。这个过程确保了区块链的安全性和一致性。
共有 0 条评论