aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp288
1 files changed, 219 insertions, 69 deletions
diff --git a/src/main.cpp b/src/main.cpp
index d2cb154c1f..0c636cdec1 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -268,6 +268,9 @@ bool CTransaction::ReadFromDisk(COutPoint prevout)
bool CTransaction::IsStandard() const
{
+ if (nVersion > CTransaction::CURRENT_VERSION)
+ return false;
+
BOOST_FOREACH(const CTxIn& txin, vin)
{
// Biggest 'standard' txin is a 3-signature 3-of-3 CHECKMULTISIG
@@ -600,7 +603,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
remove(*ptxOld);
}
- addUnchecked(tx);
+ addUnchecked(hash, tx);
}
///// are we sure this is ok when loading transactions or restoring block txes
@@ -619,13 +622,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs);
}
-bool CTxMemPool::addUnchecked(CTransaction &tx)
+bool CTxMemPool::addUnchecked(const uint256& hash, CTransaction &tx)
{
// Add to memory pool without checking anything. Don't call this directly,
// call CTxMemPool::accept to properly check the transaction first.
{
- LOCK(cs);
- uint256 hash = tx.GetHash();
mapTx[hash] = tx;
for (unsigned int i = 0; i < tx.vin.size(); i++)
mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i);
@@ -652,6 +653,15 @@ bool CTxMemPool::remove(CTransaction &tx)
return true;
}
+void
+CTxMemPool::clear()
+{
+ LOCK(cs);
+ mapTx.clear();
+ mapNextTx.clear();
+ ++nTransactionsUpdated;
+}
+
void CTxMemPool::queryHashes(std::vector<uint256>& vtxid)
{
vtxid.clear();
@@ -827,7 +837,7 @@ int64 static GetBlockValue(int nHeight, int64 nFees)
{
int64 nSubsidy = 50 * COIN;
- // Subsidy is cut in half every 4 years
+ // Subsidy is cut in half every 210000 blocks, which will occur approximately every 4 years
nSubsidy >>= (nHeight / 210000);
return nSubsidy + nFees;
@@ -970,8 +980,13 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
CTxDB().WriteBestInvalidWork(bnBestInvalidWork);
uiInterface.NotifyBlocksChanged();
}
- printf("InvalidChainFound: invalid block=%s height=%d work=%s\n", pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight, pindexNew->bnChainWork.ToString().c_str());
- printf("InvalidChainFound: current best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
+ printf("InvalidChainFound: invalid block=%s height=%d work=%s date=%s\n",
+ pindexNew->GetBlockHash().ToString().substr(0,20).c_str(), pindexNew->nHeight,
+ pindexNew->bnChainWork.ToString().c_str(), DateTimeStrFormat("%x %H:%M:%S",
+ pindexNew->GetBlockTime()).c_str());
+ printf("InvalidChainFound: current best=%s height=%d work=%s date=%s\n",
+ hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(),
+ DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
printf("InvalidChainFound: WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
}
@@ -1310,10 +1325,10 @@ bool CBlock::DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex)
return true;
}
-bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
+bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck)
{
// Check it again in case a previous version let a bad block in
- if (!CheckBlock())
+ if (!CheckBlock(!fJustCheck, !fJustCheck))
return false;
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
@@ -1325,38 +1340,45 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
// already refuses previously-known transaction id's entirely.
// This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC.
- if (pindex->nTime > 1331769600)
- {
- BOOST_FOREACH(CTransaction& tx, vtx)
- {
- CTxIndex txindexOld;
- if (txdb.ReadTxIndex(tx.GetHash(), txindexOld))
- {
- BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
- if (pos.IsNull())
- return false;
- }
- }
- }
+ int64 nBIP30SwitchTime = 1331769600;
+ bool fEnforceBIP30 = (pindex->nTime > nBIP30SwitchTime);
// BIP16 didn't become active until Apr 1 2012
int64 nBIP16SwitchTime = 1333238400;
bool fStrictPayToScriptHash = (pindex->nTime >= nBIP16SwitchTime);
//// issue here: it doesn't know the version
- unsigned int nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - 1 + GetSizeOfCompactSize(vtx.size());
+ unsigned int nTxPos;
+ if (fJustCheck)
+ // FetchInputs treats CDiskTxPos(1,1,1) as a special "refer to memorypool" indicator
+ // Since we're just checking the block and not actually connecting it, it might not (and probably shouldn't) be on the disk to get the transaction from
+ nTxPos = 1;
+ else
+ nTxPos = pindex->nBlockPos + ::GetSerializeSize(CBlock(), SER_DISK, CLIENT_VERSION) - 1 + GetSizeOfCompactSize(vtx.size());
map<uint256, CTxIndex> mapQueuedChanges;
int64 nFees = 0;
unsigned int nSigOps = 0;
BOOST_FOREACH(CTransaction& tx, vtx)
{
+ uint256 hashTx = tx.GetHash();
+
+ if (fEnforceBIP30) {
+ CTxIndex txindexOld;
+ if (txdb.ReadTxIndex(hashTx, txindexOld)) {
+ BOOST_FOREACH(CDiskTxPos &pos, txindexOld.vSpent)
+ if (pos.IsNull())
+ return false;
+ }
+ }
+
nSigOps += tx.GetLegacySigOpCount();
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("ConnectBlock() : too many sigops"));
CDiskTxPos posThisTx(pindex->nFile, pindex->nBlockPos, nTxPos);
- nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
+ if (!fJustCheck)
+ nTxPos += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
MapPrevTx mapInputs;
if (!tx.IsCoinBase())
@@ -1381,9 +1403,15 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
return false;
}
- mapQueuedChanges[tx.GetHash()] = CTxIndex(posThisTx, tx.vout.size());
+ mapQueuedChanges[hashTx] = CTxIndex(posThisTx, tx.vout.size());
}
+ if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
+ return false;
+
+ if (fJustCheck)
+ return true;
+
// Write queued txindex changes
for (map<uint256, CTxIndex>::iterator mi = mapQueuedChanges.begin(); mi != mapQueuedChanges.end(); ++mi)
{
@@ -1391,9 +1419,6 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
return error("ConnectBlock() : UpdateTxIndex failed");
}
- if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
- return false;
-
// Update block index on disk without changing it in memory.
// The memory index structure will be changed after the db commits.
if (pindex->pprev)
@@ -1613,7 +1638,27 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
bnBestChainWork = pindexNew->bnChainWork;
nTimeBestReceived = GetTime();
nTransactionsUpdated++;
- printf("SetBestChain: new best=%s height=%d work=%s\n", hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str());
+ printf("SetBestChain: new best=%s height=%d work=%s date=%s\n",
+ hashBestChain.ToString().substr(0,20).c_str(), nBestHeight, bnBestChainWork.ToString().c_str(),
+ DateTimeStrFormat("%x %H:%M:%S", pindexBest->GetBlockTime()).c_str());
+
+ // Check the version of the last 100 blocks to see if we need to upgrade:
+ if (!fIsInitialDownload)
+ {
+ int nUpgraded = 0;
+ const CBlockIndex* pindex = pindexBest;
+ for (int i = 0; i < 100 && pindex != NULL; i++)
+ {
+ if (pindex->nVersion > CBlock::CURRENT_VERSION)
+ ++nUpgraded;
+ pindex = pindex->pprev;
+ }
+ if (nUpgraded > 0)
+ printf("SetBestChain: %d of last 100 blocks above version %d\n", nUpgraded, CBlock::CURRENT_VERSION);
+ if (nUpgraded > 100/2)
+ // strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
+ strMiscWarning = _("Warning: this version is obsolete, upgrade required");
+ }
std::string strCmd = GetArg("-blocknotify", "");
@@ -1677,7 +1722,7 @@ bool CBlock::AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos)
-bool CBlock::CheckBlock() const
+bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot) const
{
// These are checks that are independent of context
// that can be verified before saving an orphan block.
@@ -1687,7 +1732,7 @@ bool CBlock::CheckBlock() const
return DoS(100, error("CheckBlock() : size limits failed"));
// Check proof of work matches claimed amount
- if (!CheckProofOfWork(GetHash(), nBits))
+ if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
return DoS(50, error("CheckBlock() : proof of work failed"));
// Check timestamp
@@ -1725,7 +1770,7 @@ bool CBlock::CheckBlock() const
return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
// Check merkleroot
- if (hashMerkleRoot != BuildMerkleTree())
+ if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree())
return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
return true;
@@ -1933,10 +1978,10 @@ bool LoadBlockIndex(bool fAllowNew)
{
if (fTestNet)
{
- pchMessageStart[0] = 0xfa;
- pchMessageStart[1] = 0xbf;
- pchMessageStart[2] = 0xb5;
- pchMessageStart[3] = 0xda;
+ pchMessageStart[0] = 0x0b;
+ pchMessageStart[1] = 0x11;
+ pchMessageStart[2] = 0x09;
+ pchMessageStart[3] = 0x07;
hashGenesisBlock = uint256("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943");
}
@@ -3267,16 +3312,18 @@ public:
CTransaction* ptx;
set<uint256> setDependsOn;
double dPriority;
+ double dFeePerKb;
COrphan(CTransaction* ptxIn)
{
ptx = ptxIn;
- dPriority = 0;
+ dPriority = dFeePerKb = 0;
}
void print() const
{
- printf("COrphan(hash=%s, dPriority=%.1f)\n", ptx->GetHash().ToString().substr(0,10).c_str(), dPriority);
+ printf("COrphan(hash=%s, dPriority=%.1f, dFeePerKb=%.1f)\n",
+ ptx->GetHash().ToString().substr(0,10).c_str(), dPriority, dFeePerKb);
BOOST_FOREACH(uint256 hash, setDependsOn)
printf(" setDependsOn %s\n", hash.ToString().substr(0,10).c_str());
}
@@ -3286,6 +3333,33 @@ public:
uint64 nLastBlockTx = 0;
uint64 nLastBlockSize = 0;
+// We want to sort transactions by priority and fee, so:
+typedef boost::tuple<double, double, CTransaction*> TxPriority;
+class TxPriorityCompare
+{
+ bool byFee;
+public:
+ TxPriorityCompare(bool _byFee) : byFee(_byFee) { }
+ bool operator()(const TxPriority& a, const TxPriority& b)
+ {
+ if (byFee)
+ {
+ if (a.get<1>() == b.get<1>())
+ return a.get<0>() < b.get<0>();
+ return a.get<1>() < b.get<1>();
+ }
+ else
+ {
+ if (a.get<0>() == b.get<0>())
+ return a.get<1>() < b.get<1>();
+ return a.get<0>() < b.get<0>();
+ }
+ }
+};
+
+const char* pszDummy = "\0\0";
+CScript scriptDummy(std::vector<unsigned char>(pszDummy, pszDummy + sizeof(pszDummy)));
+
CBlock* CreateNewBlock(CReserveKey& reservekey)
{
CBlockIndex* pindexPrev = pindexBest;
@@ -3305,6 +3379,30 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
// Add our coinbase tx as first transaction
pblock->vtx.push_back(txNew);
+ // Largest block you're willing to create:
+ unsigned int nBlockMaxSize = GetArg("-blockmaxsize", MAX_BLOCK_SIZE_GEN/2);
+ // Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
+ nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
+
+ // How much of the block should be dedicated to high-priority transactions,
+ // included regardless of the fees they pay
+ unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
+ nBlockPrioritySize = std::min(nBlockMaxSize, nBlockPrioritySize);
+
+ // Minimum block size you want to create; block will be filled with free transactions
+ // until there are no more or the block reaches this size:
+ unsigned int nBlockMinSize = GetArg("-blockminsize", 0);
+ nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
+
+ // Fee-per-kilobyte amount considered the same as "free"
+ // Be careful setting this: if you set it to zero then
+ // a transaction spammer can cheaply fill blocks using
+ // 1-satoshi-fee transactions. It should be set above the real
+ // cost to you of processing a transaction.
+ int64 nMinTxFee = MIN_TX_FEE;
+ if (mapArgs.count("-mintxfee"))
+ ParseMoney(mapArgs["-mintxfee"], nMinTxFee);
+
// Collect memory pool transactions into the block
int64 nFees = 0;
{
@@ -3314,7 +3412,10 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
// Priority order to process transactions
list<COrphan> vOrphan; // list memory doesn't move
map<uint256, vector<COrphan*> > mapDependers;
- multimap<double, CTransaction*> mapPriority;
+
+ // This vector will be sorted into a priority queue:
+ vector<TxPriority> vecPriority;
+ vecPriority.reserve(mempool.mapTx.size());
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
{
CTransaction& tx = (*mi).second;
@@ -3323,6 +3424,8 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
COrphan* porphan = NULL;
double dPriority = 0;
+ int64 nTotalIn = 0;
+ bool fMissingInputs = false;
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Read prev transaction
@@ -3330,6 +3433,19 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
CTxIndex txindex;
if (!txPrev.ReadFromDisk(txdb, txin.prevout, txindex))
{
+ // 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))
+ {
+ printf("ERROR: mempool transaction missing input\n");
+ if (fDebug) assert("mempool transaction missing input" == 0);
+ fMissingInputs = true;
+ if (porphan)
+ vOrphan.pop_back();
+ break;
+ }
+
// Has to wait for dependencies
if (!porphan)
{
@@ -3339,34 +3455,33 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
}
mapDependers[txin.prevout.hash].push_back(porphan);
porphan->setDependsOn.insert(txin.prevout.hash);
+ nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue;
continue;
}
int64 nValueIn = txPrev.vout[txin.prevout.n].nValue;
+ nTotalIn += nValueIn;
- // Read block header
int nConf = txindex.GetDepthInMainChain();
-
dPriority += (double)nValueIn * nConf;
-
- if (fDebug && GetBoolArg("-printpriority"))
- printf("priority nValueIn=%-12"PRI64d" nConf=%-5d dPriority=%-20.1f\n", nValueIn, nConf, dPriority);
}
+ if (fMissingInputs) continue;
// Priority is sum(valuein * age) / txsize
- dPriority /= ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+ unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
+ dPriority /= nTxSize;
- if (porphan)
- porphan->dPriority = dPriority;
- else
- mapPriority.insert(make_pair(-dPriority, &(*mi).second));
+ // This is a more accurate fee-per-kilobyte than is used by the client code, because the
+ // client code rounds up the size to the nearest 1K. That's good, because it gives an
+ // incentive to create smaller transactions.
+ double dFeePerKb = double(nTotalIn-tx.GetValueOut()) / (double(nTxSize)/1000.0);
- if (fDebug && GetBoolArg("-printpriority"))
+ if (porphan)
{
- printf("priority %-20.1f %s\n%s", dPriority, tx.GetHash().ToString().substr(0,10).c_str(), tx.ToString().c_str());
- if (porphan)
- porphan->print();
- printf("\n");
+ porphan->dPriority = dPriority;
+ porphan->dFeePerKb = dFeePerKb;
}
+ else
+ vecPriority.push_back(TxPriority(dPriority, dFeePerKb, &(*mi).second));
}
// Collect transactions into block
@@ -3374,16 +3489,24 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
uint64 nBlockSize = 1000;
uint64 nBlockTx = 0;
int nBlockSigOps = 100;
- while (!mapPriority.empty())
+ bool fSortedByFee = (nBlockPrioritySize <= 0);
+
+ TxPriorityCompare comparer(fSortedByFee);
+ std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
+
+ while (!vecPriority.empty())
{
- // Take highest priority transaction off priority queue
- double dPriority = -(*mapPriority.begin()).first;
- CTransaction& tx = *(*mapPriority.begin()).second;
- mapPriority.erase(mapPriority.begin());
+ // Take highest priority transaction off the priority queue:
+ double dPriority = vecPriority.front().get<0>();
+ double dFeePerKb = vecPriority.front().get<1>();
+ CTransaction& tx = *(vecPriority.front().get<2>());
+
+ std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
+ vecPriority.pop_back();
// Size limits
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
- if (nBlockSize + nTxSize >= MAX_BLOCK_SIZE_GEN)
+ if (nBlockSize + nTxSize >= nBlockMaxSize)
continue;
// Legacy limits on sigOps:
@@ -3391,9 +3514,19 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
- // Transaction fee required depends on block size
- bool fAllowFree = (nBlockSize + nTxSize < 4000 || CTransaction::AllowFree(dPriority));
- int64 nMinFee = tx.GetMinFee(nBlockSize, fAllowFree, GMF_BLOCK);
+ // Skip free transactions if we're past the minimum block size:
+ if (fSortedByFee && (dFeePerKb < nMinTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
+ continue;
+
+ // Prioritize by fee once past the priority size or we run out of high-priority
+ // transactions:
+ if (!fSortedByFee &&
+ ((nBlockSize + nTxSize >= nBlockPrioritySize) || (dPriority < COIN * 144 / 250)))
+ {
+ fSortedByFee = true;
+ comparer = TxPriorityCompare(fSortedByFee);
+ std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
+ }
// Connecting shouldn't fail due to dependency on other memory pool transactions
// because we're already processing them in order of dependency
@@ -3404,8 +3537,6 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
continue;
int64 nTxFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
- if (nTxFees < nMinFee)
- continue;
nTxSigOps += tx.GetP2SHSigOpCount(mapInputs);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
@@ -3423,6 +3554,12 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
nBlockSigOps += nTxSigOps;
nFees += nTxFees;
+ if (fDebug && GetBoolArg("-printpriority"))
+ {
+ printf("priority %.1f feeperkb %.1f txid %s\n",
+ dPriority, dFeePerKb, tx.GetHash().ToString().c_str());
+ }
+
// Add transactions that depend on this one to the priority queue
uint256 hash = tx.GetHash();
if (mapDependers.count(hash))
@@ -3433,7 +3570,10 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
{
porphan->setDependsOn.erase(hash);
if (porphan->setDependsOn.empty())
- mapPriority.insert(make_pair(-porphan->dPriority, porphan->ptx));
+ {
+ vecPriority.push_back(TxPriority(porphan->dPriority, porphan->dFeePerKb, porphan->ptx));
+ std::push_heap(vecPriority.begin(), vecPriority.end(), comparer);
+ }
}
}
}
@@ -3443,16 +3583,22 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
nLastBlockSize = nBlockSize;
printf("CreateNewBlock(): total size %lu\n", nBlockSize);
- }
pblock->vtx[0].vout[0].nValue = GetBlockValue(pindexPrev->nHeight+1, nFees);
// Fill in header
pblock->hashPrevBlock = pindexPrev->GetBlockHash();
- pblock->hashMerkleRoot = pblock->BuildMerkleTree();
pblock->UpdateTime(pindexPrev);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock.get());
pblock->nNonce = 0;
+ pblock->vtx[0].vin[0].scriptSig = scriptDummy;
+ CBlockIndex indexDummy(1, 1, *pblock);
+ indexDummy.pprev = pindexPrev;
+ indexDummy.nHeight = pindexPrev->nHeight + 1;
+ if (!pblock->ConnectBlock(txdb, &indexDummy, true))
+ throw std::runtime_error("CreateNewBlock() : ConnectBlock failed");
+ }
+
return pblock.release();
}
@@ -3568,6 +3714,9 @@ void static BitcoinMiner(CWallet *pwallet)
printf("BitcoinMiner started\n");
SetThreadPriority(THREAD_PRIORITY_LOWEST);
+ // Make this thread recognisable as the mining thread
+ RenameThread("bitcoin-miner");
+
// Each thread has its own key and counter
CReserveKey reservekey(pwallet);
unsigned int nExtraNonce = 0;
@@ -3597,7 +3746,8 @@ void static BitcoinMiner(CWallet *pwallet)
return;
IncrementExtraNonce(pblock.get(), pindexPrev, nExtraNonce);
- printf("Running BitcoinMiner with %d transactions in block\n", pblock->vtx.size());
+ printf("Running BitcoinMiner with %d transactions in block (%u bytes)\n", pblock->vtx.size(),
+ ::GetSerializeSize(*pblock, SER_NETWORK, PROTOCOL_VERSION));
//