v31.1-roots.1 · Commit 2: [PATCH 02/17] feat(policy): preserve Roots parsing and local transaction checks
src/validation.cpp
Before: src/validation.cpp · After: src/validation.cpp
File metadata
index d3cabe4464790ef84348df10aef05f268e02488c..5a07852971bb4688ccdd1c4b26f42dbda946ba4b 100644
Download original patch · Release notes
Diff rows 1–99 of 99. 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/validation.cpp
CHANGED
|
@@ -268,6 +268,35 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
|
|
|
268
268
|
return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time});
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
static int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, script_verify_flags flags)
|
|
272
|
+
{
|
|
273
|
+
if (tx.IsCoinBase()) {
|
|
274
|
+
return 0;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
unsigned int nSigOps = 0;
|
|
278
|
+
for (const auto& txin : tx.vin) {
|
|
279
|
+
nSigOps += txin.scriptSig.GetSigOpCount(false);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (flags & SCRIPT_VERIFY_P2SH) {
|
|
283
|
+
nSigOps += GetP2SHSigOpCount(tx, inputs);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
nSigOps *= WITNESS_SCALE_FACTOR;
|
|
287
|
+
|
|
288
|
+
if (flags & SCRIPT_VERIFY_WITNESS) {
|
|
289
|
+
for (const auto& txin : tx.vin) {
|
|
290
|
+
const Coin& coin = inputs.AccessCoin(txin.prevout);
|
|
291
|
+
assert(!coin.IsSpent());
|
|
292
|
+
const CTxOut &prevout = coin.out;
|
|
293
|
+
nSigOps += CountWitnessSigOps(txin.scriptSig, prevout.scriptPubKey, txin.scriptWitness, flags);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return nSigOps;
|
|
298
|
+
}
|
|
299
|
+
|
|
271
300
|
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
|
|
272
301
|
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
|
|
273
302
|
{
|
|
@@ -812,7 +841,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
|
812
841
|
|
|
813
842
|
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
|
814
843
|
std::string reason;
|
|
815
|
-
if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts.max_datacarrier_bytes, m_pool.m_opts.permit_bare_multisig, m_pool.m_opts.dust_relay_feerate, reason)) {
|
|
844
|
+
if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts, reason)) {
|
|
816
845
|
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
|
817
846
|
}
|
|
818
847
|
|
|
@@ -900,13 +929,42 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
|
900
929
|
return false; // state filled in by CheckTxInputs
|
|
901
930
|
}
|
|
902
931
|
|
|
903
|
-
if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view)) {
|
|
904
|
-
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
|
|
932
|
+
// Local policy only. Consensus input maturity remains in CheckTxInputs.
|
|
933
|
+
const int64_t next_height{int64_t{m_active_chainstate.m_chain.Height()} + 1};
|
|
934
|
+
uint64_t coinblocks{0};
|
|
935
|
+
for (const auto& input : tx.vin) {
|
|
936
|
+
const auto& coin = m_view.AccessCoin(input.prevout);
|
|
937
|
+
const int64_t depth{std::max<int64_t>(0, next_height - coin.nHeight)};
|
|
938
|
+
if (depth < m_pool.m_opts.minrelaymaturity) {
|
|
939
|
+
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-depth");
|
|
940
|
+
}
|
|
941
|
+
// Only compare against the configured bound: cap before multiplying.
|
|
942
|
+
const uint64_t remaining{m_pool.m_opts.minrelaycoinblocks - coinblocks};
|
|
943
|
+
if (depth > 0 && coin.out.nValue > 0) {
|
|
944
|
+
const uint64_t value{static_cast<uint64_t>(coin.out.nValue)};
|
|
945
|
+
coinblocks += value > remaining / depth ? remaining : value * depth;
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
if (coinblocks < m_pool.m_opts.minrelaycoinblocks) {
|
|
949
|
+
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-coinblocks");
|
|
950
|
+
}
|
|
951
|
+
if (m_pool.m_opts.datacarrier_fullcount || !m_pool.m_opts.accept_non_std_datacarrier) {
|
|
952
|
+
const auto [standard_bytes, nonstandard_bytes] = DatacarrierBytes(tx, m_view);
|
|
953
|
+
if (nonstandard_bytes && !m_pool.m_opts.accept_non_std_datacarrier) {
|
|
954
|
+
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-nonstandard");
|
|
955
|
+
}
|
|
956
|
+
if (m_pool.m_opts.datacarrier_fullcount && standard_bytes + nonstandard_bytes > m_pool.m_opts.max_datacarrier_bytes.value_or(0)) {
|
|
957
|
+
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-exceeded");
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view, m_pool.m_opts, "bad-txns-input-", reason)) {
|
|
962
|
+
return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, reason);
|
|
905
963
|
}
|
|
906
964
|
|
|
907
965
|
// Check for non-standard witnesses.
|
|
908
|
-
if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view)) {
|
|
909
|
-
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
|
|
966
|
+
if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view, "bad-witness-", reason)) {
|
|
967
|
+
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, reason);
|
|
910
968
|
}
|
|
911
969
|
|
|
912
970
|
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
|
@@ -942,7 +1000,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
|
942
1000
|
}
|
|
943
1001
|
}
|
|
944
1002
|
|
|
945
|
-
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
|
1003
|
+
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST ||
|
|
1004
|
+
(nBytesPerSigOpStrict && GetAccurateTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS) >
|
|
1005
|
+
ws.m_vsize * WITNESS_SCALE_FACTOR / nBytesPerSigOpStrict))
|
|
946
1006
|
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
|
947
1007
|
strprintf("%d", nSigOpsCost));
|
|
948
1008
|
|