v29.4-roots.1 · Commit 3: [PATCH 03/13] policy: restore conservative relay and network controls
src/policy/truc_policy.cpp
Before: src/policy/truc_policy.cpp · After: src/policy/truc_policy.cpp
File metadata
index 69e8d5ed1d2961d225c9278d68d6132e4322e91b..d1c9e1ca1267ddfacad449ff5d1b90fc7f3317de 100644
Download original patch · Release notes
Diff rows 1–174 of 174. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.
src/policy/truc_policy.cpp
CHANGED
|
@@ -56,6 +56,8 @@ struct ParentInfo {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize,
|
|
59
|
+
const std::string& reason_prefix, std::string& out_reason,
|
|
60
|
+
const ignore_rejects_type& ignore_rejects,
|
|
59
61
|
const Package& package,
|
|
60
62
|
const CTxMemPool::setEntries& mempool_ancestors)
|
|
61
63
|
{
|
|
@@ -68,12 +70,14 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
68
70
|
// Now we have all ancestors, so we can start checking TRUC rules.
|
|
69
71
|
if (ptx->version == TRUC_VERSION) {
|
|
70
72
|
// SingleTRUCChecks should have checked this already.
|
|
71
|
-
if (!Assume(vsize <= TRUC_MAX_VSIZE)) {
|
|
73
|
+
if (!Assume(vsize <= TRUC_MAX_VSIZE || ignore_rejects.count(reason_prefix + "vsize-toobig"))) {
|
|
74
|
+
out_reason = reason_prefix + "vsize-toobig";
|
|
72
75
|
return strprintf("version=3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
|
73
76
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_MAX_VSIZE);
|
|
74
77
|
}
|
|
75
78
|
|
|
76
|
-
if (mempool_ancestors.size() + in_package_parents.size() + 1 > TRUC_ANCESTOR_LIMIT) {
|
|
79
|
+
if (mempool_ancestors.size() + in_package_parents.size() + 1 > TRUC_ANCESTOR_LIMIT && !ignore_rejects.count(reason_prefix + "ancestors-toomany")) {
|
|
80
|
+
out_reason = reason_prefix + "ancestors-toomany";
|
|
77
81
|
return strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
|
78
82
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString());
|
|
79
83
|
}
|
|
@@ -81,7 +85,8 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
81
85
|
const bool has_parent{mempool_ancestors.size() + in_package_parents.size() > 0};
|
|
82
86
|
if (has_parent) {
|
|
83
87
|
// A TRUC child cannot be too large.
|
|
84
|
-
if (vsize > TRUC_CHILD_MAX_VSIZE) {
|
|
88
|
+
if (vsize > TRUC_CHILD_MAX_VSIZE && !ignore_rejects.count(reason_prefix + "child-toobig")) {
|
|
89
|
+
out_reason = reason_prefix + "child-toobig";
|
|
85
90
|
return strprintf("version=3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
|
86
91
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
|
87
92
|
vsize, TRUC_CHILD_MAX_VSIZE);
|
|
@@ -106,7 +111,8 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
106
111
|
}();
|
|
107
112
|
|
|
108
113
|
// If there is a parent, it must have the right version.
|
|
109
|
-
if (parent_info.m_version != TRUC_VERSION) {
|
|
114
|
+
if (parent_info.m_version != TRUC_VERSION && !ignore_rejects.count(reason_prefix + "spends-nontruc")) {
|
|
115
|
+
out_reason = reason_prefix + "spends-nontruc";
|
|
110
116
|
return strprintf("version=3 tx %s (wtxid=%s) cannot spend from non-version=3 tx %s (wtxid=%s)",
|
|
111
117
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
|
112
118
|
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString());
|
|
@@ -120,21 +126,24 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
120
126
|
// Fail if we find another tx with the same parent. We don't check whether the
|
|
121
127
|
// sibling is to-be-replaced (done in SingleTRUCChecks) because these transactions
|
|
122
128
|
// are within the same package.
|
|
123
|
-
if (input.prevout.hash == parent_info.m_txid) {
|
|
129
|
+
if (input.prevout.hash == parent_info.m_txid && !ignore_rejects.count(reason_prefix + "sibling-known")) {
|
|
130
|
+
out_reason = reason_prefix + "sibling-known";
|
|
124
131
|
return strprintf("tx %s (wtxid=%s) would exceed descendant count limit",
|
|
125
132
|
parent_info.m_txid.ToString(),
|
|
126
133
|
parent_info.m_wtxid.ToString());
|
|
127
134
|
}
|
|
128
135
|
|
|
129
136
|
// This tx can't have both a parent and an in-package child.
|
|
130
|
-
if (input.prevout.hash == ptx->GetHash()) {
|
|
137
|
+
if (input.prevout.hash == ptx->GetHash() && !ignore_rejects.count(reason_prefix + "parent-and-child-both")) {
|
|
138
|
+
out_reason = reason_prefix + "parent-and-child-both";
|
|
131
139
|
return strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
|
132
140
|
package_tx->GetHash().ToString(), package_tx->GetWitnessHash().ToString());
|
|
133
141
|
}
|
|
134
142
|
}
|
|
135
143
|
}
|
|
136
144
|
|
|
137
|
-
if (parent_info.m_has_mempool_descendant) {
|
|
145
|
+
if (parent_info.m_has_mempool_descendant && !ignore_rejects.count(reason_prefix + "descendant-toomany")) {
|
|
146
|
+
out_reason = reason_prefix + "descendant-toomany";
|
|
138
147
|
return strprintf("tx %s (wtxid=%s) would exceed descendant count limit",
|
|
139
148
|
parent_info.m_txid.ToString(), parent_info.m_wtxid.ToString());
|
|
140
149
|
}
|
|
@@ -142,14 +151,16 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
142
151
|
} else {
|
|
143
152
|
// Non-TRUC transactions cannot have TRUC parents.
|
|
144
153
|
for (auto it : mempool_ancestors) {
|
|
145
|
-
if (it->GetTx().version == TRUC_VERSION) {
|
|
154
|
+
if (it->GetTx().version == TRUC_VERSION && !ignore_rejects.count(reason_prefix + "spent-by-nontruc")) {
|
|
155
|
+
out_reason = reason_prefix + "spent-by-nontruc";
|
|
146
156
|
return strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
|
147
157
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
|
148
158
|
it->GetSharedTx()->GetHash().ToString(), it->GetSharedTx()->GetWitnessHash().ToString());
|
|
149
159
|
}
|
|
150
160
|
}
|
|
151
161
|
for (const auto& index: in_package_parents) {
|
|
152
|
-
if (package.at(index)->version == TRUC_VERSION) {
|
|
162
|
+
if (package.at(index)->version == TRUC_VERSION && !ignore_rejects.count(reason_prefix + "spent-by-nontruc")) {
|
|
163
|
+
out_reason = reason_prefix + "spent-by-nontruc";
|
|
153
164
|
return strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
|
154
165
|
ptx->GetHash().ToString(),
|
|
155
166
|
ptx->GetWitnessHash().ToString(),
|
|
@@ -161,19 +172,31 @@ std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t
|
|
|
161
172
|
return std::nullopt;
|
|
162
173
|
}
|
|
163
174
|
|
|
175
|
+
std::optional<std::string> PackageTRUCChecks(const CTransactionRef& ptx, int64_t vsize,
|
|
176
|
+
const Package& package,
|
|
177
|
+
const CTxMemPool::setEntries& mempool_ancestors)
|
|
178
|
+
{
|
|
179
|
+
std::string out_reason;
|
|
180
|
+
return PackageTRUCChecks(ptx, vsize, "", out_reason, empty_ignore_rejects, package, mempool_ancestors);
|
|
181
|
+
}
|
|
182
|
+
|
|
164
183
|
std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx,
|
|
184
|
+
const std::string& reason_prefix, std::string& out_reason,
|
|
185
|
+
const ignore_rejects_type& ignore_rejects,
|
|
165
186
|
const CTxMemPool::setEntries& mempool_ancestors,
|
|
166
187
|
const std::set<Txid>& direct_conflicts,
|
|
167
188
|
int64_t vsize)
|
|
168
189
|
{
|
|
169
190
|
// Check TRUC and non-TRUC inheritance.
|
|
170
191
|
for (const auto& entry : mempool_ancestors) {
|
|
171
|
-
if (ptx->version != TRUC_VERSION && entry->GetTx().version == TRUC_VERSION) {
|
|
192
|
+
if (ptx->version != TRUC_VERSION && entry->GetTx().version == TRUC_VERSION && !ignore_rejects.count(reason_prefix + "spent-by-nontruc")) {
|
|
193
|
+
out_reason = reason_prefix + "spent-by-nontruc";
|
|
172
194
|
return std::make_pair(strprintf("non-version=3 tx %s (wtxid=%s) cannot spend from version=3 tx %s (wtxid=%s)",
|
|
173
195
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
|
174
196
|
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
|
175
197
|
nullptr);
|
|
176
|
-
} else if (ptx->version == TRUC_VERSION && entry->GetTx().version != TRUC_VERSION) {
|
|
198
|
+
} else if (ptx->version == TRUC_VERSION && entry->GetTx().version != TRUC_VERSION && !ignore_rejects.count(reason_prefix + "spends-nontruc")) {
|
|
199
|
+
out_reason = reason_prefix + "spends-nontruc";
|
|
177
200
|
return std::make_pair(strprintf("version=3 tx %s (wtxid=%s) cannot spend from non-version=3 tx %s (wtxid=%s)",
|
|
178
201
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(),
|
|
179
202
|
entry->GetSharedTx()->GetHash().ToString(), entry->GetSharedTx()->GetWitnessHash().ToString()),
|
|
@@ -188,14 +211,16 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
|
|
188
211
|
// The rest of the rules only apply to transactions with version=3.
|
|
189
212
|
if (ptx->version != TRUC_VERSION) return std::nullopt;
|
|
190
213
|
|
|
191
|
-
if (vsize > TRUC_MAX_VSIZE) {
|
|
214
|
+
if (vsize > TRUC_MAX_VSIZE && !ignore_rejects.count(reason_prefix + "vsize-toobig")) {
|
|
215
|
+
out_reason = reason_prefix + "vsize-toobig";
|
|
192
216
|
return std::make_pair(strprintf("version=3 tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
|
193
217
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_MAX_VSIZE),
|
|
194
218
|
nullptr);
|
|
195
219
|
}
|
|
196
220
|
|
|
197
221
|
// Check that TRUC_ANCESTOR_LIMIT would not be violated.
|
|
198
|
-
if (mempool_ancestors.size() + 1 > TRUC_ANCESTOR_LIMIT) {
|
|
222
|
+
if (mempool_ancestors.size() + 1 > TRUC_ANCESTOR_LIMIT && !ignore_rejects.count(reason_prefix + "ancestors-toomany")) {
|
|
223
|
+
out_reason = reason_prefix + "ancestors-toomany";
|
|
199
224
|
return std::make_pair(strprintf("tx %s (wtxid=%s) would have too many ancestors",
|
|
200
225
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString()),
|
|
201
226
|
nullptr);
|
|
@@ -204,7 +229,8 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
|
|
204
229
|
// Remaining checks only pertain to transactions with unconfirmed ancestors.
|
|
205
230
|
if (mempool_ancestors.size() > 0) {
|
|
206
231
|
// If this transaction spends TRUC parents, it cannot be too large.
|
|
207
|
-
if (vsize > TRUC_CHILD_MAX_VSIZE) {
|
|
232
|
+
if (vsize > TRUC_CHILD_MAX_VSIZE && !ignore_rejects.count(reason_prefix + "child-toobig")) {
|
|
233
|
+
out_reason = reason_prefix + "child-toobig";
|
|
208
234
|
return std::make_pair(strprintf("version=3 child tx %s (wtxid=%s) is too big: %u > %u virtual bytes",
|
|
209
235
|
ptx->GetHash().ToString(), ptx->GetWitnessHash().ToString(), vsize, TRUC_CHILD_MAX_VSIZE),
|
|
210
236
|
nullptr);
|
|
@@ -222,7 +248,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
|
|
222
248
|
const bool child_will_be_replaced = !children.empty() &&
|
|
223
249
|
std::any_of(children.cbegin(), children.cend(),
|
|
224
250
|
[&direct_conflicts](const CTxMemPoolEntry& child){return direct_conflicts.count(child.GetTx().GetHash()) > 0;});
|
|
225
|
-
if (parent_entry->GetCountWithDescendants() + 1 > TRUC_DESCENDANT_LIMIT && !child_will_be_replaced) {
|
|
251
|
+
if (parent_entry->GetCountWithDescendants() + 1 > TRUC_DESCENDANT_LIMIT && (!child_will_be_replaced) && !ignore_rejects.count(reason_prefix + "descendants-toomany")) {
|
|
226
252
|
// Allow sibling eviction for TRUC transaction: if another child already exists, even if
|
|
227
253
|
// we don't conflict inputs with it, consider evicting it under RBF rules. We rely on TRUC rules
|
|
228
254
|
// only permitting 1 descendant, as otherwise we would need to have logic for deciding
|
|
@@ -233,6 +259,7 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
|
|
233
259
|
|
|
234
260
|
// Return the sibling if its eviction can be considered. Provide the "descendant count
|
|
235
261
|
// limit" string either way, as the caller may decide not to do sibling eviction.
|
|
262
|
+
out_reason = reason_prefix + "descendants-toomany";
|
|
236
263
|
return std::make_pair(strprintf("tx %u (wtxid=%s) would exceed descendant count limit",
|
|
237
264
|
parent_entry->GetSharedTx()->GetHash().ToString(),
|
|
238
265
|
parent_entry->GetSharedTx()->GetWitnessHash().ToString()),
|
|
@@ -241,3 +268,12 @@ std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CT
|
|
|
241
268
|
}
|
|
242
269
|
return std::nullopt;
|
|
243
270
|
}
|
|
271
|
+
|
|
272
|
+
std::optional<std::pair<std::string, CTransactionRef>> SingleTRUCChecks(const CTransactionRef& ptx,
|
|
273
|
+
const CTxMemPool::setEntries& mempool_ancestors,
|
|
274
|
+
const std::set<Txid>& direct_conflicts,
|
|
275
|
+
int64_t vsize)
|
|
276
|
+
{
|
|
277
|
+
std::string out_reason;
|
|
278
|
+
return SingleTRUCChecks(ptx, "", out_reason, empty_ignore_rejects, mempool_ancestors, direct_conflicts, vsize);
|
|
279
|
+
}
|