2727
2828#include < boost/thread.hpp>
2929#include < boost/tuple/tuple.hpp>
30+ #include < queue>
3031
3132using namespace std ;
3233
@@ -40,48 +41,18 @@ using namespace std;
4041// transactions in the memory pool. When we select transactions from the
4142// pool, we select by highest priority or fee rate, so we might consider
4243// transactions that depend on transactions that aren't yet in the block.
43- // The COrphan class keeps track of these 'temporary orphans' while
44- // CreateBlock is figuring out which transactions to include.
45- //
46- class COrphan
47- {
48- public:
49- const CTransaction* ptx;
50- set<uint256> setDependsOn;
51- CFeeRate feeRate;
52- double dPriority;
53-
54- COrphan (const CTransaction* ptxIn) : ptx(ptxIn), feeRate(0 ), dPriority(0 )
55- {
56- }
57- };
5844
5945uint64_t nLastBlockTx = 0 ;
6046uint64_t nLastBlockSize = 0 ;
6147
62- // We want to sort transactions by priority and fee rate, so:
63- typedef boost::tuple<double , CFeeRate, const CTransaction*> TxPriority;
64- class TxPriorityCompare
48+ class ScoreCompare
6549{
66- bool byFee;
67-
6850public:
69- TxPriorityCompare ( bool _byFee) : byFee(_byFee) { }
51+ ScoreCompare () { }
7052
71- bool operator ()(const TxPriority& a, const TxPriority& b)
53+ bool operator ()(const CTxMemPool::txiter a, const CTxMemPool::txiter b)
7254 {
73- if (byFee)
74- {
75- if (a.get <1 >() == b.get <1 >())
76- return a.get <0 >() < b.get <0 >();
77- return a.get <1 >() < b.get <1 >();
78- }
79- else
80- {
81- if (a.get <0 >() == b.get <0 >())
82- return a.get <1 >() < b.get <1 >();
83- return a.get <0 >() < b.get <0 >();
84- }
55+ return CompareTxMemPoolEntryByScore ()(*b,*a); // Convert to less than
8556 }
8657};
8758
@@ -141,6 +112,22 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
141112 nBlockMinSize = std::min (nBlockMaxSize, nBlockMinSize);
142113
143114 // Collect memory pool transactions into the block
115+ CTxMemPool::setEntries inBlock;
116+ CTxMemPool::setEntries waitSet;
117+
118+ // This vector will be sorted into a priority queue:
119+ vector<TxCoinAgePriority> vecPriority;
120+ TxCoinAgePriorityCompare pricomparer;
121+ std::map<CTxMemPool::txiter, double , CTxMemPool::CompareIteratorByHash> waitPriMap;
122+ typedef std::map<CTxMemPool::txiter, double , CTxMemPool::CompareIteratorByHash>::iterator waitPriIter;
123+ double actualPriority = -1 ;
124+
125+ std::priority_queue<CTxMemPool::txiter, std::vector<CTxMemPool::txiter>, ScoreCompare> clearedTxs;
126+ bool fPrintPriority = GetBoolArg (" -printpriority" , DEFAULT_PRINTPRIORITY);
127+ uint64_t nBlockSize = 1000 ;
128+ uint64_t nBlockTx = 0 ;
129+ unsigned int nBlockSigOps = 100 ;
130+ int lastFewTxs = 0 ;
144131 CAmount nFees = 0 ;
145132
146133 {
@@ -149,157 +136,102 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
149136 const int nHeight = pindexPrev->nHeight + 1 ;
150137 pblock->nTime = GetAdjustedTime ();
151138 const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast ();
152- CCoinsViewCache view (pcoinsTip);
153-
154- // Priority order to process transactions
155- list<COrphan> vOrphan; // list memory doesn't move
156- map<uint256, vector<COrphan*> > mapDependers;
157- bool fPrintPriority = GetBoolArg (" -printpriority" , DEFAULT_PRINTPRIORITY);
158-
159- // This vector will be sorted into a priority queue:
160- vector<TxPriority> vecPriority;
161- vecPriority.reserve (mempool.mapTx .size ());
162- for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx .begin ();
163- mi != mempool.mapTx .end (); ++mi)
164- {
165- const CTransaction& tx = mi->GetTx ();
166-
167- int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
168- ? nMedianTimePast
169- : pblock->GetBlockTime ();
170-
171- if (tx.IsCoinBase () || !IsFinalTx (tx, nHeight, nLockTimeCutoff))
172- continue ;
173-
174- COrphan* porphan = NULL ;
175- double dPriority = 0 ;
176- CAmount nTotalIn = 0 ;
177- bool fMissingInputs = false ;
178- BOOST_FOREACH (const CTxIn& txin, tx.vin )
179- {
180- // Read prev transaction
181- if (!view.HaveCoins (txin.prevout .hash ))
182- {
183- // This should never happen; all transactions in the memory
184- // pool should connect to either transactions in the chain
185- // or other transactions in the memory pool.
186- if (!mempool.mapTx .count (txin.prevout .hash ))
187- {
188- LogPrintf (" ERROR: mempool transaction missing input\n " );
189- if (fDebug ) assert (" mempool transaction missing input" == 0 );
190- fMissingInputs = true ;
191- if (porphan)
192- vOrphan.pop_back ();
193- break ;
194- }
195-
196- // Has to wait for dependencies
197- if (!porphan)
198- {
199- // Use list for automatic deletion
200- vOrphan.push_back (COrphan (&tx));
201- porphan = &vOrphan.back ();
202- }
203- mapDependers[txin.prevout .hash ].push_back (porphan);
204- porphan->setDependsOn .insert (txin.prevout .hash );
205- nTotalIn += mempool.mapTx .find (txin.prevout .hash )->GetTx ().vout [txin.prevout .n ].nValue ;
206- continue ;
207- }
208- const CCoins* coins = view.AccessCoins (txin.prevout .hash );
209- assert (coins);
210-
211- CAmount nValueIn = coins->vout [txin.prevout .n ].nValue ;
212- nTotalIn += nValueIn;
213-
214- int nConf = nHeight - coins->nHeight ;
215-
216- dPriority += (double )nValueIn * nConf;
217- }
218- if (fMissingInputs ) continue ;
219-
220- // Priority is sum(valuein * age) / modified_txsize
221- unsigned int nTxSize = ::GetSerializeSize (tx, SER_NETWORK, PROTOCOL_VERSION);
222- dPriority = tx.ComputePriority (dPriority, nTxSize);
223-
224- uint256 hash = tx.GetHash ();
225- mempool.ApplyDeltas (hash, dPriority, nTotalIn);
226139
227- CFeeRate feeRate (nTotalIn-tx.GetValueOut (), nTxSize);
140+ int64_t nLockTimeCutoff = (STANDARD_LOCKTIME_VERIFY_FLAGS & LOCKTIME_MEDIAN_TIME_PAST)
141+ ? nMedianTimePast
142+ : pblock->GetBlockTime ();
228143
229- if (porphan)
144+ bool fPriorityBlock = nBlockPrioritySize > 0 ;
145+ if (fPriorityBlock ) {
146+ vecPriority.reserve (mempool.mapTx .size ());
147+ for (CTxMemPool::indexed_transaction_set::iterator mi = mempool.mapTx .begin ();
148+ mi != mempool.mapTx .end (); ++mi)
230149 {
231- porphan->dPriority = dPriority;
232- porphan->feeRate = feeRate;
150+ double dPriority = mi->GetPriority (nHeight);
151+ CAmount dummy;
152+ mempool.ApplyDeltas (mi->GetTx ().GetHash (), dPriority, dummy);
153+ vecPriority.push_back (TxCoinAgePriority (dPriority, mi));
233154 }
234- else
235- vecPriority.push_back (TxPriority (dPriority, feeRate, &(mi->GetTx ())));
155+ std::make_heap (vecPriority.begin (), vecPriority.end (), pricomparer);
236156 }
237157
238- // Collect transactions into block
239- uint64_t nBlockSize = 1000 ;
240- uint64_t nBlockTx = 0 ;
241- int nBlockSigOps = 100 ;
242- bool fSortedByFee = (nBlockPrioritySize <= 0 );
158+ CTxMemPool::indexed_transaction_set::nth_index<3 >::type::iterator mi = mempool.mapTx .get <3 >().begin ();
159+ CTxMemPool::txiter iter;
243160
244- TxPriorityCompare comparer (fSortedByFee );
245- std::make_heap (vecPriority.begin (), vecPriority.end (), comparer);
246-
247- while (!vecPriority.empty ())
161+ while (mi != mempool.mapTx .get <3 >().end () || !clearedTxs.empty ())
248162 {
249- // Take highest priority transaction off the priority queue:
250- double dPriority = vecPriority.front ().get <0 >();
251- CFeeRate feeRate = vecPriority.front ().get <1 >();
252- const CTransaction& tx = *(vecPriority.front ().get <2 >());
253-
254- std::pop_heap (vecPriority.begin (), vecPriority.end (), comparer);
255- vecPriority.pop_back ();
256-
257- // Size limits
258- unsigned int nTxSize = ::GetSerializeSize (tx, SER_NETWORK, PROTOCOL_VERSION);
259- if (nBlockSize + nTxSize >= nBlockMaxSize)
260- continue ;
163+ bool priorityTx = false ;
164+ if (fPriorityBlock && !vecPriority.empty ()) { // add a tx from priority queue to fill the blockprioritysize
165+ priorityTx = true ;
166+ iter = vecPriority.front ().second ;
167+ actualPriority = vecPriority.front ().first ;
168+ std::pop_heap (vecPriority.begin (), vecPriority.end (), pricomparer);
169+ vecPriority.pop_back ();
170+ }
171+ else if (clearedTxs.empty ()) { // add tx with next highest score
172+ iter = mempool.mapTx .project <0 >(mi);
173+ mi++;
174+ }
175+ else { // try to add a previously postponed child tx
176+ iter = clearedTxs.top ();
177+ clearedTxs.pop ();
178+ }
261179
262- // Legacy limits on sigOps:
263- unsigned int nTxSigOps = GetLegacySigOpCount (tx);
264- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
265- continue ;
180+ if (inBlock.count (iter))
181+ continue ; // could have been added to the priorityBlock
266182
267- // Skip free transactions if we're past the minimum block size:
268- const uint256& hash = tx.GetHash ();
269- double dPriorityDelta = 0 ;
270- CAmount nFeeDelta = 0 ;
271- mempool.ApplyDeltas (hash, dPriorityDelta, nFeeDelta);
272- if (fSortedByFee && (dPriorityDelta <= 0 ) && (nFeeDelta <= 0 ) && (feeRate < ::minRelayTxFee) && (nBlockSize + nTxSize >= nBlockMinSize))
273- continue ;
183+ const CTransaction& tx = iter->GetTx ();
274184
275- // Prioritise by fee once past the priority size or we run out of high-priority
276- // transactions:
277- if (!fSortedByFee &&
278- ((nBlockSize + nTxSize >= nBlockPrioritySize) || !AllowFree (dPriority)))
185+ bool fOrphan = false ;
186+ BOOST_FOREACH (CTxMemPool::txiter parent, mempool.GetMemPoolParents (iter))
279187 {
280- fSortedByFee = true ;
281- comparer = TxPriorityCompare (fSortedByFee );
282- std::make_heap (vecPriority.begin (), vecPriority.end (), comparer);
188+ if (!inBlock.count (parent)) {
189+ fOrphan = true ;
190+ break ;
191+ }
283192 }
284-
285- if (!view.HaveInputs (tx))
193+ if (fOrphan ) {
194+ if (priorityTx)
195+ waitPriMap.insert (std::make_pair (iter,actualPriority));
196+ else
197+ waitSet.insert (iter);
286198 continue ;
199+ }
287200
288- CAmount nTxFees = view.GetValueIn (tx)-tx.GetValueOut ();
289-
290- nTxSigOps += GetP2SHSigOpCount (tx, view);
291- if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
201+ unsigned int nTxSize = iter->GetTxSize ();
202+ if (fPriorityBlock &&
203+ (nBlockSize + nTxSize >= nBlockPrioritySize || !AllowFree (actualPriority))) {
204+ fPriorityBlock = false ;
205+ waitPriMap.clear ();
206+ }
207+ if (!priorityTx &&
208+ (iter->GetModifiedFee () < ::minRelayTxFee.GetFee (nTxSize) && nBlockSize >= nBlockMinSize)) {
209+ break ;
210+ }
211+ if (nBlockSize + nTxSize >= nBlockMaxSize) {
212+ if (nBlockSize > nBlockMaxSize - 100 || lastFewTxs > 50 ) {
213+ break ;
214+ }
215+ // Once we're within 1000 bytes of a full block, only look at 50 more txs
216+ // to try to fill the remaining space.
217+ if (nBlockSize > nBlockMaxSize - 1000 ) {
218+ lastFewTxs++;
219+ }
292220 continue ;
221+ }
293222
294- // Note that flags: we don't want to set mempool/IsStandard()
295- // policy here, but we still have to ensure that the block we
296- // create only contains transactions that are valid in new blocks.
297- CValidationState state;
298- if (!CheckInputs (tx, state, view, true , MANDATORY_SCRIPT_VERIFY_FLAGS, true ))
223+ if (!IsFinalTx (tx, nHeight, nLockTimeCutoff))
299224 continue ;
300225
301- UpdateCoins (tx, state, view, nHeight);
226+ unsigned int nTxSigOps = iter->GetSigOpCount ();
227+ if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS) {
228+ if (nBlockSigOps > MAX_BLOCK_SIGOPS - 2 ) {
229+ break ;
230+ }
231+ continue ;
232+ }
302233
234+ CAmount nTxFees = iter->GetFee ();
303235 // Added
304236 pblock->vtx .push_back (tx);
305237 pblocktemplate->vTxFees .push_back (nTxFees);
@@ -311,31 +243,37 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
311243
312244 if (fPrintPriority )
313245 {
246+ double dPriority = iter->GetPriority (nHeight);
247+ CAmount dummy;
248+ mempool.ApplyDeltas (tx.GetHash (), dPriority, dummy);
314249 LogPrintf (" priority %.1f fee %s txid %s\n " ,
315- dPriority, feeRate .ToString (), tx.GetHash ().ToString ());
250+ dPriority , CFeeRate (iter-> GetModifiedFee (), nTxSize) .ToString (), tx.GetHash ().ToString ());
316251 }
317252
253+ inBlock.insert (iter);
254+
318255 // Add transactions that depend on this one to the priority queue
319- if (mapDependers. count (hash ))
256+ BOOST_FOREACH (CTxMemPool::txiter child, mempool. GetMemPoolChildren (iter ))
320257 {
321- BOOST_FOREACH (COrphan* porphan, mapDependers[hash])
322- {
323- if (!porphan->setDependsOn .empty ())
324- {
325- porphan->setDependsOn .erase (hash);
326- if (porphan->setDependsOn .empty ())
327- {
328- vecPriority.push_back (TxPriority (porphan->dPriority , porphan->feeRate , porphan->ptx ));
329- std::push_heap (vecPriority.begin (), vecPriority.end (), comparer);
330- }
258+ if (fPriorityBlock ) {
259+ waitPriIter wpiter = waitPriMap.find (child);
260+ if (wpiter != waitPriMap.end ()) {
261+ vecPriority.push_back (TxCoinAgePriority (wpiter->second ,child));
262+ std::push_heap (vecPriority.begin (), vecPriority.end (), pricomparer);
263+ waitPriMap.erase (wpiter);
264+ }
265+ }
266+ else {
267+ if (waitSet.count (child)) {
268+ clearedTxs.push (child);
269+ waitSet.erase (child);
331270 }
332271 }
333272 }
334273 }
335-
336274 nLastBlockTx = nBlockTx;
337275 nLastBlockSize = nBlockSize;
338- LogPrintf (" CreateNewBlock(): total size %u\n " , nBlockSize);
276+ LogPrintf (" CreateNewBlock(): total size %u txs: %u fees: %ld sigops %d \n " , nBlockSize, nBlockTx, nFees, nBlockSigOps );
339277
340278 // Compute final coinbase transaction.
341279 txNew.vout [0 ].nValue = nFees + GetBlockSubsidy (nHeight, chainparams.GetConsensus ());
@@ -351,8 +289,9 @@ CBlockTemplate* CreateNewBlock(const CChainParams& chainparams, const CScript& s
351289 pblocktemplate->vTxSigOps [0 ] = GetLegacySigOpCount (pblock->vtx [0 ]);
352290
353291 CValidationState state;
354- if (!TestBlockValidity (state, chainparams, *pblock, pindexPrev, false , false ))
355- throw std::runtime_error (" CreateNewBlock(): TestBlockValidity failed" );
292+ if (!TestBlockValidity (state, chainparams, *pblock, pindexPrev, false , false )) {
293+ throw std::runtime_error (strprintf (" %s: TestBlockValidity failed: %s" , __func__, FormatStateMessage (state)));
294+ }
356295 }
357296
358297 return pblocktemplate.release ();
0 commit comments