@@ -130,10 +130,11 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
130
130
}
131
131
132
132
// It shouldn't be possible to have any mempool siblings at this point. SingleV3Checks
133
- // catches mempool siblings. Also, if the package consists of connected transactions,
133
+ // catches mempool siblings and sibling eviction is not extended to packages . Also, if the package consists of connected transactions,
134
134
// any tx having a mempool ancestor would mean the package exceeds ancestor limits.
135
135
if (!Assume (!parent_info.m_has_mempool_descendant )) {
136
- return strprintf (" tx %u would exceed descendant count limit" , parent_info.m_wtxid .ToString ());
136
+ return strprintf (" tx %s (wtxid=%s) would exceed descendant count limit" ,
137
+ parent_info.m_txid .ToString (), parent_info.m_wtxid .ToString ());
137
138
}
138
139
}
139
140
} else {
@@ -158,21 +159,23 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
158
159
return std::nullopt;
159
160
}
160
161
161
- std::optional<std::string> SingleV3Checks (const CTransactionRef& ptx,
162
+ std::optional<std::pair<std:: string, CTransactionRef> > SingleV3Checks (const CTransactionRef& ptx,
162
163
const CTxMemPool::setEntries& mempool_ancestors,
163
164
const std::set<Txid>& direct_conflicts,
164
165
int64_t vsize)
165
166
{
166
167
// Check v3 and non-v3 inheritance.
167
168
for (const auto & entry : mempool_ancestors) {
168
169
if (ptx->nVersion != 3 && entry->GetTx ().nVersion == 3 ) {
169
- return strprintf (" non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)" ,
170
+ return std::make_pair ( strprintf (" non-v3 tx %s (wtxid=%s) cannot spend from v3 tx %s (wtxid=%s)" ,
170
171
ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString (),
171
- entry->GetSharedTx ()->GetHash ().ToString (), entry->GetSharedTx ()->GetWitnessHash ().ToString ());
172
+ entry->GetSharedTx ()->GetHash ().ToString (), entry->GetSharedTx ()->GetWitnessHash ().ToString ()),
173
+ nullptr );
172
174
} else if (ptx->nVersion == 3 && entry->GetTx ().nVersion != 3 ) {
173
- return strprintf (" v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)" ,
175
+ return std::make_pair ( strprintf (" v3 tx %s (wtxid=%s) cannot spend from non-v3 tx %s (wtxid=%s)" ,
174
176
ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString (),
175
- entry->GetSharedTx ()->GetHash ().ToString (), entry->GetSharedTx ()->GetWitnessHash ().ToString ());
177
+ entry->GetSharedTx ()->GetHash ().ToString (), entry->GetSharedTx ()->GetWitnessHash ().ToString ()),
178
+ nullptr );
176
179
}
177
180
}
178
181
@@ -185,16 +188,18 @@ std::optional<std::string> SingleV3Checks(const CTransactionRef& ptx,
185
188
186
189
// Check that V3_ANCESTOR_LIMIT would not be violated.
187
190
if (mempool_ancestors.size () + 1 > V3_ANCESTOR_LIMIT) {
188
- return strprintf (" tx %s (wtxid=%s) would have too many ancestors" ,
189
- ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ());
191
+ return std::make_pair (strprintf (" tx %s (wtxid=%s) would have too many ancestors" ,
192
+ ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString ()),
193
+ nullptr );
190
194
}
191
195
192
196
// Remaining checks only pertain to transactions with unconfirmed ancestors.
193
197
if (mempool_ancestors.size () > 0 ) {
194
198
// If this transaction spends V3 parents, it cannot be too large.
195
199
if (vsize > V3_CHILD_MAX_VSIZE) {
196
- return strprintf (" v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes" ,
197
- ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString (), vsize, V3_CHILD_MAX_VSIZE);
200
+ return std::make_pair (strprintf (" v3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes" ,
201
+ ptx->GetHash ().ToString (), ptx->GetWitnessHash ().ToString (), vsize, V3_CHILD_MAX_VSIZE),
202
+ nullptr );
198
203
}
199
204
200
205
// Check the descendant counts of in-mempool ancestors.
@@ -210,9 +215,20 @@ std::optional<std::string> SingleV3Checks(const CTransactionRef& ptx,
210
215
std::any_of (children.cbegin (), children.cend (),
211
216
[&direct_conflicts](const CTxMemPoolEntry& child){return direct_conflicts.count (child.GetTx ().GetHash ()) > 0 ;});
212
217
if (parent_entry->GetCountWithDescendants () + 1 > V3_DESCENDANT_LIMIT && !child_will_be_replaced) {
213
- return strprintf (" tx %u (wtxid=%s) would exceed descendant count limit" ,
214
- parent_entry->GetSharedTx ()->GetHash ().ToString (),
215
- parent_entry->GetSharedTx ()->GetWitnessHash ().ToString ());
218
+ // Allow sibling eviction for v3 transaction: if another child already exists, even if
219
+ // we don't conflict inputs with it, consider evicting it under RBF rules. We rely on v3 rules
220
+ // only permitting 1 descendant, as otherwise we would need to have logic for deciding
221
+ // which descendant to evict. Skip if this isn't true, e.g. if the transaction has
222
+ // multiple children or the sibling also has descendants due to a reorg.
223
+ const bool consider_sibling_eviction{parent_entry->GetCountWithDescendants () == 2 &&
224
+ children.begin ()->get ().GetCountWithAncestors () == 2 };
225
+
226
+ // Return the sibling if its eviction can be considered. Provide the "descendant count
227
+ // limit" string either way, as the caller may decide not to do sibling eviction.
228
+ return std::make_pair (strprintf (" tx %u (wtxid=%s) would exceed descendant count limit" ,
229
+ parent_entry->GetSharedTx ()->GetHash ().ToString (),
230
+ parent_entry->GetSharedTx ()->GetWitnessHash ().ToString ()),
231
+ consider_sibling_eviction ? children.begin ()->get ().GetSharedTx () : nullptr );
216
232
}
217
233
}
218
234
return std::nullopt;
0 commit comments