aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp264
1 files changed, 194 insertions, 70 deletions
diff --git a/src/main.cpp b/src/main.cpp
index e56a163199..23c6d988aa 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -564,7 +564,7 @@ bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
// Continuously rate-limit free transactions
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
- // be annoying or make other's transactions take longer to confirm.
+ // be annoying or make others' transactions take longer to confirm.
if (nFees < MIN_RELAY_TX_FEE)
{
static CCriticalSection cs;
@@ -653,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();
@@ -846,7 +855,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;
@@ -997,7 +1006,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
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");
+ printf("InvalidChainFound: Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.\n");
}
void CBlock::UpdateTime(const CBlockIndex* pindexPrev)
@@ -1048,7 +1057,7 @@ bool CTransaction::DisconnectInputs(CTxDB& txdb)
// Remove transaction from index
// This can fail if a duplicate of this transaction was in a chain that got
// reorganized away. This is only possible if this transaction was completely
- // spent, so erasing it would be a no-op anway.
+ // spent, so erasing it would be a no-op anyway.
txdb.EraseTxIndex(*this);
return true;
@@ -1111,7 +1120,7 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
}
}
- // Make sure all prevout.n's are valid:
+ // Make sure all prevout.n indexes are valid:
for (unsigned int i = 0; i < vin.size(); i++)
{
const COutPoint prevout = vin[i].prevout;
@@ -1334,10 +1343,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,
@@ -1347,7 +1356,7 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
// being sent to another address.
// See BIP30 and http://r6.ca/blog/20120206T005236Z.html for more information.
// This logic is not necessary for memory pool transactions, as AcceptToMemoryPool
- // already refuses previously-known transaction id's entirely.
+ // already refuses previously-known transaction ids entirely.
// This rule applies to all blocks whose timestamp is after March 15, 2012, 0:00 UTC.
int64 nBIP30SwitchTime = 1331769600;
bool fEnforceBIP30 = (pindex->nTime > nBIP30SwitchTime);
@@ -1357,7 +1366,13 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
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;
@@ -1380,7 +1395,8 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
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())
@@ -1408,6 +1424,12 @@ bool CBlock::ConnectBlock(CTxDB& txdb, CBlockIndex* pindex)
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)
{
@@ -1415,9 +1437,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)
@@ -1603,7 +1622,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
return error("SetBestChain() : Reorganize failed");
}
- // Connect futher blocks
+ // Connect further blocks
BOOST_REVERSE_FOREACH(CBlockIndex *pindex, vpindexSecondary)
{
CBlock block;
@@ -1657,7 +1676,7 @@ bool CBlock::SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew)
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");
+ strMiscWarning = _("Warning: This version is obsolete, upgrade required!");
}
std::string strCmd = GetArg("-blocknotify", "");
@@ -1722,7 +1741,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.
@@ -1732,7 +1751,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
@@ -1769,8 +1788,8 @@ bool CBlock::CheckBlock() const
if (nSigOps > MAX_BLOCK_SIGOPS)
return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));
- // Check merkleroot
- if (hashMerkleRoot != BuildMerkleTree())
+ // Check merkle root
+ if (fCheckMerkleRoot && hashMerkleRoot != BuildMerkleTree())
return DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
return true;
@@ -1805,7 +1824,7 @@ bool CBlock::AcceptBlock()
// Check that the block chain matches the known block chain up to a checkpoint
if (!Checkpoints::CheckBlock(nHeight, hash))
- return DoS(100, error("AcceptBlock() : rejected by checkpoint lockin at %d", nHeight));
+ return DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight));
// Write block to history file
if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION)))
@@ -1923,7 +1942,7 @@ bool CheckDiskSpace(uint64 nAdditionalBytes)
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes)
{
fShutdown = true;
- string strMessage = _("Warning: Disk space is low");
+ string strMessage = _("Warning: Disk space is low!");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
uiInterface.ThreadSafeMessageBox(strMessage, "Bitcoin", CClientUIInterface::OK | CClientUIInterface::ICON_EXCLAMATION | CClientUIInterface::MODAL);
@@ -1963,7 +1982,7 @@ FILE* AppendBlockFile(unsigned int& nFileRet)
return NULL;
if (fseek(file, 0, SEEK_END) != 0)
return NULL;
- // FAT32 filesize max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
+ // FAT32 file size max 4GB, fseek and ftell max 2GB, so we must stay under 2GB
if (ftell(file) < 0x7F000000 - MAX_SIZE)
{
nFileRet = nCurrentBlockFile;
@@ -1978,10 +1997,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");
}
@@ -2055,7 +2074,7 @@ bool LoadBlockIndex(bool fAllowNew)
void PrintBlockTree()
{
- // precompute tree structure
+ // pre-compute tree structure
map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
for (map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
{
@@ -2108,7 +2127,7 @@ void PrintBlockTree()
PrintWallets(block);
- // put the main timechain first
+ // put the main time-chain first
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
{
@@ -2218,7 +2237,7 @@ string GetWarnings(string strFor)
if (pindexBest && bnBestInvalidWork > bnBestChainWork + pindexBest->GetBlockWork() * 6)
{
nPriority = 2000;
- strStatusBar = strRPC = "WARNING: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.";
+ strStatusBar = strRPC = _("Warning: Displayed transactions may not be correct! You may need to upgrade, or other nodes may need to upgrade.");
}
// Alerts
@@ -2347,7 +2366,7 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
// The message start string is designed to be unlikely to occur in normal data.
-// The characters are rarely used upper ascii, not valid as UTF-8, and produce
+// The characters are rarely used upper ASCII, not valid as UTF-8, and produce
// a large 4-byte int at any alignment.
unsigned char pchMessageStart[4] = { 0xf9, 0xbe, 0xb4, 0xd9 };
@@ -3030,12 +3049,12 @@ bool ProcessMessages(CNode* pfrom)
{
if (strstr(e.what(), "end of data"))
{
- // Allow exceptions from underlength message on vRecv
+ // Allow exceptions from under-length message on vRecv
printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught, normally caused by a message being shorter than its stated length\n", strCommand.c_str(), nMessageSize, e.what());
}
else if (strstr(e.what(), "size too large"))
{
- // Allow exceptions from overlong size
+ // Allow exceptions from over-long size
printf("ProcessMessages(%s, %u bytes) : Exception '%s' caught\n", strCommand.c_str(), nMessageSize, e.what());
}
else
@@ -3284,9 +3303,9 @@ unsigned int static ScanHash_CryptoPP(char* pmidstate, char* pdata, char* phash1
unsigned int& nNonce = *(unsigned int*)(pdata + 12);
for (;;)
{
- // Crypto++ SHA-256
+ // Crypto++ SHA256
// Hash pdata using pmidstate as the starting state into
- // preformatted buffer phash1, then hash phash1 into phash
+ // pre-formatted buffer phash1, then hash phash1 into phash
nNonce++;
SHA256Transform(phash1, pdata, pmidstate);
SHA256Transform(phash, phash1, pSHA256InitState);
@@ -3312,16 +3331,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());
}
@@ -3331,6 +3352,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;
@@ -3350,6 +3398,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;
{
@@ -3359,7 +3431,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;
@@ -3368,6 +3443,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
@@ -3375,6 +3452,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)
{
@@ -3384,34 +3474,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
@@ -3419,16 +3508,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:
@@ -3436,9 +3533,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
@@ -3449,8 +3556,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)
@@ -3468,6 +3573,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))
@@ -3478,7 +3589,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);
+ }
}
}
}
@@ -3488,16 +3602,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();
}
@@ -3522,7 +3642,7 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int&
void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1)
{
//
- // Prebuild hash buffers
+ // Pre-build hash buffers
//
struct
{
@@ -3613,6 +3733,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;
@@ -3642,11 +3765,12 @@ 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));
//
- // Prebuild hash buffers
+ // Pre-build hash buffers
//
char pmidstatebuf[32+16]; char* pmidstate = alignup<16>(pmidstatebuf);
char pdatabuf[128+16]; char* pdata = alignup<16>(pdatabuf);
@@ -3671,7 +3795,7 @@ void static BitcoinMiner(CWallet *pwallet)
unsigned int nHashesDone = 0;
unsigned int nNonceFound;
- // Crypto++ SHA-256
+ // Crypto++ SHA256
nNonceFound = ScanHash_CryptoPP(pmidstate, pdata + 64, phash1,
(char*)&hash, nHashesDone);