diff --git a/src/txmempool.cpp b/src/txmempool.cpp --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -435,6 +435,9 @@ bool CTxMemPool::addUnchecked(const uint256 &hash, const CTxMemPoolEntry &entry, setEntries &setAncestors, bool validFeeEstimate) { + + LogPrint(BCLog::MEMPOOL, "addUnchecked: %s\n", hash.ToString()); + NotifyEntryAdded(entry.GetSharedTx()); // Add to memory pool without checking anything. // Used by AcceptToMemoryPool(), which DOES do all the appropriate checks. @@ -493,6 +496,33 @@ } void CTxMemPool::removeUnchecked(txiter it, MemPoolRemovalReason reason) { + const char *reasonStr; + switch (reason) { + case MemPoolRemovalReason::UNKNOWN: + reasonStr = "UNKNOWN"; + break; + case MemPoolRemovalReason::EXPIRY: + reasonStr = "EXPIRY"; + break; + case MemPoolRemovalReason::BLOCK: + reasonStr = "BLOCK"; + break; + case MemPoolRemovalReason::SIZELIMIT: + reasonStr = "SIZELIMIT"; + break; + case MemPoolRemovalReason::REORG: + reasonStr = "REORG"; + break; + case MemPoolRemovalReason::CONFLICT: + reasonStr = "CONFLICT"; + break; + case MemPoolRemovalReason::REPLACED: + reasonStr = "REPLACED"; + break; + } + LogPrint(BCLog::MEMPOOL, "removeUnchecked: %s for %s\n", + it->GetTx().GetId().ToString(), reasonStr); + NotifyEntryRemoved(it->GetSharedTx(), reason); const uint256 txid = it->GetTx().GetId(); for (const CTxIn &txin : it->GetTx().vin) { diff --git a/test/functional/prioritise_transaction.py b/test/functional/prioritise_transaction.py --- a/test/functional/prioritise_transaction.py +++ b/test/functional/prioritise_transaction.py @@ -10,10 +10,38 @@ from test_framework.test_framework import BitcoinTestFramework from test_framework.util import * # FIXME: review how this test needs to be adapted w.r.t _LEGACY_MAX_BLOCK_SIZE -from test_framework.mininode import COIN +from test_framework.mininode import * +from test_framework.script import * from test_framework.cdefs import LEGACY_MAX_BLOCK_SIZE +def create_lots_of_big_transactions(node, utxos, num, fee_multiplier): + txids = [] + + # Some pre-processing to create a bunch of OP_RETURN txouts to insert into transactions we create + # So we have big transactions (and therefore can't fit very many into each block) + # create one script_pubkey + script_pubkey = "6a4d0200" # OP_RETURN OP_PUSH2 512 bytes + for i in range(512*128): + script_pubkey = script_pubkey + "01" + + for _ in range(num): + ctx = CTransaction() + t = utxos.pop() + txid = int(t['txid'], 16) + ctx.vin.append(CTxIn(COutPoint(txid, int(t["vout"])), b"")) + ctx.vout.append(CTxOut(0, bytearray.fromhex(script_pubkey))) + ctx.vout.append( + CTxOut(int(satoshi_round(t['amount']*COIN)), CScript([OP_TRUE]))) + # Create a proper fee for the transaciton to be mined + ctx.vout[1].nValue -= int(fee_multiplier * node.calculate_fee(ctx)) + signresult = node.signrawtransaction( + ToHex(ctx), None, None, "NONE|FORKID") + txid = node.sendrawtransaction(signresult["hex"], True) + txids.append(txid) + return txids + + class PrioritiseTransactionTest(BitcoinTestFramework): def set_test_params(self): self.setup_clean_chain = True @@ -21,7 +49,6 @@ self.extra_args = [["-printpriority=1"]] def run_test(self): - self.txouts = gen_return_txouts() self.relayfee = self.nodes[0].getnetworkinfo()['relayfee'] utxo_count = 90 @@ -37,8 +64,8 @@ txids.append([]) start_range = i * range_size end_range = start_range + range_size - txids[i] = create_lots_of_big_transactions(self.nodes[0], self.txouts, utxos[ - start_range:end_range], end_range - start_range, (i + 1) * base_fee) + txids[i] = create_lots_of_big_transactions(self.nodes[0], utxos[start_range:end_range], + end_range - start_range, 10 * (i + 1)) # Make sure that the size of each group of transactions exceeds # LEGACY_MAX_BLOCK_SIZE -- otherwise the test needs to be revised to create @@ -56,7 +83,7 @@ # also check that a different entry in the cheapest bucket is NOT mined (lower # the priority to ensure its not mined due to priority) self.nodes[0].prioritisetransaction( - txids[0][0], 0, int(3 * base_fee * COIN)) + txids[0][0], 0, 100 * self.nodes[0].calculate_fee_from_txid(txids[0][0])) self.nodes[0].prioritisetransaction(txids[0][1], -1e15, 0) self.nodes[0].generate(1) @@ -66,19 +93,24 @@ assert(txids[0][0] not in mempool) assert(txids[0][1] in mempool) - high_fee_tx = None - for x in txids[2]: - if x not in mempool: - high_fee_tx = x + confirmed_transactions = self.nodes[0].getblock( + self.nodes[0].getbestblockhash())['tx'] + + # Pull the highest fee-rate transaction from a block + high_fee_tx = confirmed_transactions[1] + print(high_fee_tx) # Something high-fee should have been mined! assert(high_fee_tx != None) # Add a prioritisation before a tx is in the mempool (de-prioritising a # high-fee transaction so that it's now low fee). + tx_fee = self.nodes[0].gettransaction(high_fee_tx)['fee'] + print(-int(tx_fee*COIN), + self.nodes[0].calculate_fee_from_txid(high_fee_tx)) self.nodes[0].prioritisetransaction( - high_fee_tx, -1e15, -int(2 * base_fee * COIN)) - + high_fee_tx, -1e15, 0) # -10 * int(tx_fee*COIN) * 100) + # print(self.nodes[0].gettransaction(high_fee_tx)) # Add everything back to mempool self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash()) @@ -92,6 +124,7 @@ while (self.nodes[0].getmempoolinfo()['bytes'] > sizes[0] + sizes[1]): self.nodes[0].generate(1) + print(self.nodes[0].gettransaction(high_fee_tx)) # High fee transaction should not have been mined, but other high fee rate # transactions should have been. mempool = self.nodes[0].getrawmempool()