Skip to content

Commit

Permalink
Refactor CreateNewBlock to extract testable code
Browse files Browse the repository at this point in the history
  • Loading branch information
str4d committed Oct 31, 2016
1 parent 2b2bc69 commit ae1098a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 26 deletions.
79 changes: 53 additions & 26 deletions src/miner.cpp
Expand Up @@ -7,7 +7,6 @@
#include "pow/tromp/equi_miner.h"

#include "amount.h"
#include "chainparams.h"
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "hash.h"
Expand Down Expand Up @@ -109,14 +108,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)

// -regtest only: allow overriding block.nVersion with
// -blockversion=N to test forking scenarios
if (Params().MineBlocksOnDemand())
if (chainparams.MineBlocksOnDemand())
pblock->nVersion = GetArg("-blockversion", pblock->nVersion);

// Add dummy coinbase tx as first transaction
pblock->vtx.push_back(CTransaction());
pblocktemplate->vTxFees.push_back(-1); // updated at end
pblocktemplate->vTxSigOps.push_back(-1); // updated at end

// Largest block you're willing to create:
unsigned int nBlockMaxSize = GetArg("-blockmaxsize", DEFAULT_BLOCK_MAX_SIZE);
// Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
Expand All @@ -132,12 +126,51 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);

{
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
std::function<void(const uint256, double&, CAmount&)> f = [&]
(const uint256 hash, double &dPriorityDelta, CAmount &nFeeDelta) {
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
};

FillNewBlock(pblock, pindexPrev,
scriptPubKeyIn, chainparams,
pblocktemplate->vTxFees,
pblocktemplate->vTxSigOps,
mempool.mapTx, f,
nBlockMaxSize, nBlockPrioritySize, nBlockMinSize);

CValidationState state;
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
}

return pblocktemplate.release();
}

void FillNewBlock(CBlock* pblock,
CBlockIndex* pindexPrev,
const CScript& scriptPubKeyIn,
const CChainParams& chainparams,
std::vector<CAmount>& vTxFees,
std::vector<int64_t>& vTxSigOps,
std::map<uint256, CTxMemPoolEntry>& mapTx,
std::function<void(const uint256, double&, CAmount&)> mempoolApplyDeltas,
unsigned int nBlockMaxSize,
unsigned int nBlockPrioritySize,
unsigned int nBlockMinSize)
{
// Add dummy coinbase tx as first transaction
pblock->vtx.push_back(CTransaction());
vTxFees.push_back(-1); // updated at end
vTxSigOps.push_back(-1); // updated at end

// Collect memory pool transactions into the block
CAmount nFees = 0;

// Leaving indented to reduce diff
{
LOCK2(cs_main, mempool.cs);
CBlockIndex* pindexPrev = chainActive.Tip();
const int nHeight = pindexPrev->nHeight + 1;
pblock->nTime = GetAdjustedTime();
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
Expand All @@ -150,9 +183,9 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)

// This vector will be sorted into a priority queue:
vector<TxPriority> vecPriority;
vecPriority.reserve(mempool.mapTx.size());
for (map<uint256, CTxMemPoolEntry>::iterator mi = mempool.mapTx.begin();
mi != mempool.mapTx.end(); ++mi)
vecPriority.reserve(mapTx.size());
for (map<uint256, CTxMemPoolEntry>::iterator mi = mapTx.begin();
mi != mapTx.end(); ++mi)
{
const CTransaction& tx = mi->second.GetTx();

Expand All @@ -175,7 +208,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
// This should never happen; all transactions in the memory
// pool should connect to either transactions in the chain
// or other transactions in the memory pool.
if (!mempool.mapTx.count(txin.prevout.hash))
if (!mapTx.count(txin.prevout.hash))
{
LogPrintf("ERROR: mempool transaction missing input\n");
if (fDebug) assert("mempool transaction missing input" == 0);
Expand All @@ -194,7 +227,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
}
mapDependers[txin.prevout.hash].push_back(porphan);
porphan->setDependsOn.insert(txin.prevout.hash);
nTotalIn += mempool.mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue;
nTotalIn += mapTx[txin.prevout.hash].GetTx().vout[txin.prevout.n].nValue;
continue;
}
const CCoins* coins = view.AccessCoins(txin.prevout.hash);
Expand All @@ -216,7 +249,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
dPriority = tx.ComputePriority(dPriority, nTxSize);

uint256 hash = tx.GetHash();
mempool.ApplyDeltas(hash, dPriority, nTotalIn);
mempoolApplyDeltas(hash, dPriority, nTotalIn);

CFeeRate feeRate(nTotalIn-tx.GetValueOut(), nTxSize);

Expand Down Expand Up @@ -262,7 +295,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
const uint256& hash = tx.GetHash();
double dPriorityDelta = 0;
CAmount nFeeDelta = 0;
mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta);
mempoolApplyDeltas(hash, dPriorityDelta, nFeeDelta);
if (fSortedByFee && (dPriorityDelta <= 0) && (nFeeDelta <= 0) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
continue;

Expand Down Expand Up @@ -296,8 +329,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)

// Added
pblock->vtx.push_back(tx);
pblocktemplate->vTxFees.push_back(nTxFees);
pblocktemplate->vTxSigOps.push_back(nTxSigOps);
vTxFees.push_back(nTxFees);
vTxSigOps.push_back(nTxSigOps);
nBlockSize += nTxSize;
++nBlockTx;
nBlockSigOps += nTxSigOps;
Expand Down Expand Up @@ -354,7 +387,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;

pblock->vtx[0] = txNew;
pblocktemplate->vTxFees[0] = -nFees;
vTxFees[0] = -nFees;

// Randomise nonce
arith_uint256 nonce = UintToArith256(GetRandHash());
Expand All @@ -369,14 +402,8 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
UpdateTime(pblock, Params().GetConsensus(), pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock, Params().GetConsensus());
pblock->nSolution.clear();
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);

CValidationState state;
if (!TestBlockValidity(state, *pblock, pindexPrev, false, false))
throw std::runtime_error("CreateNewBlock(): TestBlockValidity failed");
vTxSigOps[0] = GetLegacySigOpCount(pblock->vtx[0]);
}

return pblocktemplate.release();
}

void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce)
Expand Down
14 changes: 14 additions & 0 deletions src/miner.h
Expand Up @@ -6,7 +6,9 @@
#ifndef BITCOIN_MINER_H
#define BITCOIN_MINER_H

#include "chainparams.h"
#include "primitives/block.h"
#include "txmempool.h"

#include <stdint.h>

Expand All @@ -25,6 +27,18 @@ struct CBlockTemplate

/** Run the miner threads */
void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads);
/** Fill a new block with transactions */
void FillNewBlock(CBlock* pblock,
CBlockIndex* pindexPrev,
const CScript& scriptPubKeyIn,
const CChainParams& chainparams,
std::vector<CAmount>& vTxFees,
std::vector<int64_t>& vTxSigOps,
std::map<uint256, CTxMemPoolEntry>& mapTx,
std::function<void(const uint256, double&, CAmount&)> mempoolApplyDeltas,
unsigned int nBlockMaxSize,
unsigned int nBlockPrioritySize,
unsigned int nBlockMinSize);
/** Generate a new block, without valid proof-of-work */
CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn);
CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey);
Expand Down

0 comments on commit ae1098a

Please sign in to comment.