@@ -71,6 +71,113 @@ bool TestSequenceLocks(const CTransaction &tx, int flags)
71
71
return CheckSequenceLocks (tx, flags);
72
72
}
73
73
74
+ // Test suite for ancestor feerate transaction selection.
75
+ // Implemented as an additional function, rather than a separate test case,
76
+ // to allow reusing the blockchain created in CreateNewBlock_validity.
77
+ // Note that this test assumes blockprioritysize is 0.
78
+ void TestPackageSelection (const CChainParams& chainparams, CScript scriptPubKey, std::vector<CTransaction *>& txFirst)
79
+ {
80
+ // Test the ancestor feerate transaction selection.
81
+ TestMemPoolEntryHelper entry;
82
+
83
+ // Test that a medium fee transaction will be selected after a higher fee
84
+ // rate package with a low fee rate parent.
85
+ CMutableTransaction tx;
86
+ tx.vin .resize (1 );
87
+ tx.vin [0 ].scriptSig = CScript () << OP_1;
88
+ tx.vin [0 ].prevout .hash = txFirst[0 ]->GetHash ();
89
+ tx.vin [0 ].prevout .n = 0 ;
90
+ tx.vout .resize (1 );
91
+ tx.vout [0 ].nValue = 5000000000LL - 1000 ;
92
+ // This tx has a low fee: 1000 satoshis
93
+ uint256 hashParentTx = tx.GetHash (); // save this txid for later use
94
+ mempool.addUnchecked (hashParentTx, entry.Fee (1000 ).Time (GetTime ()).SpendsCoinbase (true ).FromTx (tx));
95
+
96
+ // This tx has a medium fee: 10000 satoshis
97
+ tx.vin [0 ].prevout .hash = txFirst[1 ]->GetHash ();
98
+ tx.vout [0 ].nValue = 5000000000LL - 10000 ;
99
+ uint256 hashMediumFeeTx = tx.GetHash ();
100
+ mempool.addUnchecked (hashMediumFeeTx, entry.Fee (10000 ).Time (GetTime ()).SpendsCoinbase (true ).FromTx (tx));
101
+
102
+ // This tx has a high fee, but depends on the first transaction
103
+ tx.vin [0 ].prevout .hash = hashParentTx;
104
+ tx.vout [0 ].nValue = 5000000000LL - 1000 - 50000 ; // 50k satoshi fee
105
+ uint256 hashHighFeeTx = tx.GetHash ();
106
+ mempool.addUnchecked (hashHighFeeTx, entry.Fee (50000 ).Time (GetTime ()).SpendsCoinbase (false ).FromTx (tx));
107
+
108
+ CBlockTemplate *pblocktemplate = BlockAssembler (chainparams).CreateNewBlock (scriptPubKey);
109
+ BOOST_CHECK (pblocktemplate->block .vtx [1 ].GetHash () == hashParentTx);
110
+ BOOST_CHECK (pblocktemplate->block .vtx [2 ].GetHash () == hashHighFeeTx);
111
+ BOOST_CHECK (pblocktemplate->block .vtx [3 ].GetHash () == hashMediumFeeTx);
112
+
113
+ // Test that a package below the min relay fee doesn't get included
114
+ tx.vin [0 ].prevout .hash = hashHighFeeTx;
115
+ tx.vout [0 ].nValue = 5000000000LL - 1000 - 50000 ; // 0 fee
116
+ uint256 hashFreeTx = tx.GetHash ();
117
+ mempool.addUnchecked (hashFreeTx, entry.Fee (0 ).FromTx (tx));
118
+ size_t freeTxSize = ::GetSerializeSize (tx, SER_NETWORK, PROTOCOL_VERSION);
119
+
120
+ // Calculate a fee on child transaction that will put the package just
121
+ // below the min relay fee (assuming 1 child tx of the same size).
122
+ CAmount feeToUse = minRelayTxFee.GetFee (2 *freeTxSize) - 1 ;
123
+
124
+ tx.vin [0 ].prevout .hash = hashFreeTx;
125
+ tx.vout [0 ].nValue = 5000000000LL - 1000 - 50000 - feeToUse;
126
+ uint256 hashLowFeeTx = tx.GetHash ();
127
+ mempool.addUnchecked (hashLowFeeTx, entry.Fee (feeToUse).FromTx (tx));
128
+ pblocktemplate = BlockAssembler (chainparams).CreateNewBlock (scriptPubKey);
129
+ // Verify that the free tx and the low fee tx didn't get selected
130
+ for (size_t i=0 ; i<pblocktemplate->block .vtx .size (); ++i) {
131
+ BOOST_CHECK (pblocktemplate->block .vtx [i].GetHash () != hashFreeTx);
132
+ BOOST_CHECK (pblocktemplate->block .vtx [i].GetHash () != hashLowFeeTx);
133
+ }
134
+
135
+ // Test that packages above the min relay fee do get included, even if one
136
+ // of the transactions is below the min relay fee
137
+ // Remove the low fee transaction and replace with a higher fee transaction
138
+ std::list<CTransaction> dummy;
139
+ mempool.removeRecursive (tx, dummy);
140
+ tx.vout [0 ].nValue -= 2 ; // Now we should be just over the min relay fee
141
+ hashLowFeeTx = tx.GetHash ();
142
+ mempool.addUnchecked (hashLowFeeTx, entry.Fee (feeToUse+2 ).FromTx (tx));
143
+ pblocktemplate = BlockAssembler (chainparams).CreateNewBlock (scriptPubKey);
144
+ BOOST_CHECK (pblocktemplate->block .vtx [4 ].GetHash () == hashFreeTx);
145
+ BOOST_CHECK (pblocktemplate->block .vtx [5 ].GetHash () == hashLowFeeTx);
146
+
147
+ // Test that transaction selection properly updates ancestor fee
148
+ // calculations as ancestor transactions get included in a block.
149
+ // Add a 0-fee transaction that has 2 outputs.
150
+ tx.vin [0 ].prevout .hash = txFirst[2 ]->GetHash ();
151
+ tx.vout .resize (2 );
152
+ tx.vout [0 ].nValue = 5000000000LL - 100000000 ;
153
+ tx.vout [1 ].nValue = 100000000 ; // 1BTC output
154
+ uint256 hashFreeTx2 = tx.GetHash ();
155
+ mempool.addUnchecked (hashFreeTx2, entry.Fee (0 ).SpendsCoinbase (true ).FromTx (tx));
156
+
157
+ // This tx can't be mined by itself
158
+ tx.vin [0 ].prevout .hash = hashFreeTx2;
159
+ tx.vout .resize (1 );
160
+ feeToUse = minRelayTxFee.GetFee (freeTxSize);
161
+ tx.vout [0 ].nValue = 5000000000LL - 100000000 - feeToUse;
162
+ uint256 hashLowFeeTx2 = tx.GetHash ();
163
+ mempool.addUnchecked (hashLowFeeTx2, entry.Fee (feeToUse).SpendsCoinbase (false ).FromTx (tx));
164
+ pblocktemplate = BlockAssembler (chainparams).CreateNewBlock (scriptPubKey);
165
+
166
+ // Verify that this tx isn't selected.
167
+ for (size_t i=0 ; i<pblocktemplate->block .vtx .size (); ++i) {
168
+ BOOST_CHECK (pblocktemplate->block .vtx [i].GetHash () != hashFreeTx2);
169
+ BOOST_CHECK (pblocktemplate->block .vtx [i].GetHash () != hashLowFeeTx2);
170
+ }
171
+
172
+ // This tx will be mineable, and should cause hashLowFeeTx2 to be selected
173
+ // as well.
174
+ tx.vin [0 ].prevout .n = 1 ;
175
+ tx.vout [0 ].nValue = 100000000 - 10000 ; // 10k satoshi fee
176
+ mempool.addUnchecked (tx.GetHash (), entry.Fee (10000 ).FromTx (tx));
177
+ pblocktemplate = BlockAssembler (chainparams).CreateNewBlock (scriptPubKey);
178
+ BOOST_CHECK (pblocktemplate->block .vtx [8 ].GetHash () == hashLowFeeTx2);
179
+ }
180
+
74
181
// NOTE: These tests rely on CreateNewBlock doing its own self-validation!
75
182
BOOST_AUTO_TEST_CASE (CreateNewBlock_validity)
76
183
{
@@ -385,6 +492,8 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
385
492
SetMockTime (0 );
386
493
mempool.clear ();
387
494
495
+ TestPackageSelection (chainparams, scriptPubKey, txFirst);
496
+
388
497
BOOST_FOREACH (CTransaction *_tx, txFirst)
389
498
delete _tx;
390
499
0 commit comments