@@ -130,10 +130,11 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
130130 }
131131
132132 // 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,
134134 // any tx having a mempool ancestor would mean the package exceeds ancestor limits.
135135 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 ());
137138 }
138139 }
139140 } else {
@@ -158,21 +159,23 @@ std::optional<std::string> PackageV3Checks(const CTransactionRef& ptx, int64_t v
158159 return std::nullopt ;
159160}
160161
161- std::optional<std::string> SingleV3Checks (const CTransactionRef& ptx,
162+ std::optional<std::pair<std:: string, CTransactionRef> > SingleV3Checks (const CTransactionRef& ptx,
162163 const CTxMemPool::setEntries& mempool_ancestors,
163164 const std::set<Txid>& direct_conflicts,
164165 int64_t vsize)
165166{
166167 // Check v3 and non-v3 inheritance.
167168 for (const auto & entry : mempool_ancestors) {
168169 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)" ,
170171 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 );
172174 } 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)" ,
174176 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 );
176179 }
177180 }
178181
@@ -185,16 +188,18 @@ std::optional<std::string> SingleV3Checks(const CTransactionRef& ptx,
185188
186189 // Check that V3_ANCESTOR_LIMIT would not be violated.
187190 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 );
190194 }
191195
192196 // Remaining checks only pertain to transactions with unconfirmed ancestors.
193197 if (mempool_ancestors.size () > 0 ) {
194198 // If this transaction spends V3 parents, it cannot be too large.
195199 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 );
198203 }
199204
200205 // Check the descendant counts of in-mempool ancestors.
@@ -210,9 +215,20 @@ std::optional<std::string> SingleV3Checks(const CTransactionRef& ptx,
210215 std::any_of (children.cbegin (), children.cend (),
211216 [&direct_conflicts](const CTxMemPoolEntry& child){return direct_conflicts.count (child.GetTx ().GetHash ()) > 0 ;});
212217 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 );
216232 }
217233 }
218234 return std::nullopt ;
0 commit comments