diff --git a/src/miner.cpp b/src/miner.cpp --- a/src/miner.cpp +++ b/src/miner.cpp @@ -179,7 +179,7 @@ std::sort(std::begin(pblock->vtx) + 1, std::end(pblock->vtx), [](const std::shared_ptr &a, const std::shared_ptr &b) -> bool { - return a->GetId() > b->GetId(); + return a->GetId() < b->GetId(); }); } diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -1270,10 +1270,51 @@ void DisconnectedBlockTransactions::addForBlock( const std::vector &vtx) { - // Save transactions to re-add to mempool at end of reorg - for (const auto &tx : boost::adaptors::reverse(vtx)) { + for (const auto &tx : vtx | boost::adaptors::sliced(1, vtx.size())) { + // If we already added it, just skip. + auto it = queuedTx.find(tx->GetId()); + if (it != queuedTx.end()) { + continue; + } + + // Insert the transaction into the pool. addTransaction(tx); + + // Fill in the set of parents. + std::unordered_set parents; + for (const CTxIn &in : tx->vin) { + parents.insert(in.prevout.GetTxId()); + } + + // In order to make sure we keep things in topological order, we check + // if we already know of the parent of the current transaction. If so, + // we remove them from the set and then add them back. + while (parents.size() > 0) { + std::unordered_set worklist = + std::move(parents); + for (const TxId &txid : worklist) { + // If we do not have that txid in the set, nothing needs to be + // done. + auto it = queuedTx.find(txid); + if (it == queuedTx.end()) { + continue; + } + + // We have parent in our set, we reinsert them at the right + // position. + const CTransactionRef ptx = *it; + queuedTx.erase(it); + queuedTx.insert(ptx); + + // And we make sure ancestors are covered. + for (const CTxIn &in : ptx->vin) { + parents.insert(in.prevout.GetTxId()); + } + } + } } + + // Keep the size under control. while (DynamicMemoryUsage() > MAX_DISCONNECTED_TX_POOL_SIZE) { // Drop the earliest entry, and remove its children from the // mempool. diff --git a/test/functional/abc-transaction-ordering.py b/test/functional/abc-transaction-ordering.py --- a/test/functional/abc-transaction-ordering.py +++ b/test/functional/abc-transaction-ordering.py @@ -40,6 +40,7 @@ self.tip = None self.blocks = {} self.extra_args = [['-whitelist=127.0.0.1', + '-relaypriority=0', "-magneticanomalyactivationtime=%d" % MAGNETIC_ANOMALY_START_TIME, "-replayprotectionactivationtime=%d" % (2 * MAGNETIC_ANOMALY_START_TIME)]] @@ -252,6 +253,7 @@ assert_equal(node.getblockheader(forkblockhash)[ 'mediantime'], MAGNETIC_ANOMALY_START_TIME) + assert_equal(len(node.getrawmempool()), 15) node.generate(1) generatedblockhash = node.getbestblockhash() assert(forkblockhash != generatedblockhash)