btc的挖矿原理

这段代码是比特币(Bitcoin)或其衍生项目之一的矿工模块的实现。它负责构建新的区块,并将其添加到区块链中。以下是对代码的详细解释:

主要功能

  1. 更新区块时间(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;
    }
    

    这个函数更新区块的时间戳,并在必要时调整工作难度。

  2. 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);
      }
      
  3. 交易选择和添加

    • onlyUnconfirmed:确保只测试未确认的交易。
    • TestPackage:检查交易包是否符合区块的大小和操作数限制。
    • TestPackageTransactions:检查交易包中的每个交易是否符合最终性和见证数据的要求。
    • AddToBlock:将交易添加到区块中,并更新相关统计信息。
    • UpdatePackagesForAdded:更新已添加交易的后代交易。
    • SkipMapTxEntry:跳过已经在区块中的交易或已经失败的交易。
    • SortForBlock:对交易包进行排序,以确保交易的依赖关系正确。
    • addPackageTxs:选择交易包并添加到区块中。
  4. 增加额外的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值的作用

  1. 确保哈希的唯一性
    Nonce是一个可变的数字,用于生成不同的区块哈希值。通过不断改变Nonce值,矿工可以尝试找到一个满足网络难度目标的哈希值。

  2. 解决哈希碰撞
    当矿工在尝试不同的Nonce值时,可能会遇到哈希碰撞(即不同的Nonce值产生相同的哈希)。通过增加额外的Nonce值,可以进一步增加哈希的多样性,避免碰撞。

  3. 增加搜索空间
    Nonce值的范围是有限的(32位无符号整数),当所有可能的Nonce值都被尝试后,矿工可以通过增加额外的Nonce值来扩展搜索空间。

如何确定有效哈希

一个有效的区块哈希必须满足当前的难度目标,即哈希值的前若干个比特必须为零。具体步骤如下:

  1. 更新区块头信息
    在每次尝试新的Nonce值时,矿工需要更新区块头信息,包括时间戳和Merkle根哈希。

  2. 计算区块哈希
    使用SHA-256哈希函数计算区块头的哈希值。

  3. 比较哈希值与难度目标
    将计算得到的哈希值与当前的难度目标进行比较。如果哈希值小于或等于难度目标,则该哈希值是有效的。

代码示例

以下是如何在代码中实现这些步骤的示例:

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. 目标值的表示
    目标值通常表示为一个大整数,称为“目标哈希”。这个值越小,难度越高。

  2. 哈希值的比较
    矿工计算出的区块哈希值必须小于或等于这个目标值,才能被认为是有效的。

具体实现

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值,计算区块头的哈希值,并与目标值进行比较,直到找到一个有效的哈希。这个过程确保了区块链的安全性和一致性。

版权声明:
作者:Alex
链接:https://www.techfm.club/p/157393.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
< <上一篇
下一篇>>