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. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/validation.cpp
CHANGED
|
@@ -268,6 +268,35 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
|
|
| 268 |
return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time});
|
| 269 |
}
|
| 270 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
|
| 272 |
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
|
| 273 |
{
|
|
@@ -812,7 +841,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 812 |
|
| 813 |
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
| 814 |
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)) {
|
| 816 |
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
| 817 |
}
|
| 818 |
|
|
@@ -900,13 +929,42 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 900 |
return false; // state filled in by CheckTxInputs
|
| 901 |
}
|
| 902 |
|
| 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");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 905 |
}
|
| 906 |
|
| 907 |
// 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");
|
| 910 |
}
|
| 911 |
|
| 912 |
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
|
@@ -942,7 +1000,9 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
|
|
| 942 |
}
|
| 943 |
}
|
| 944 |
|
| 945 |
-
if (nSigOpsCost > MAX_STANDARD_TX_SIGOPS_COST)
|
|
|
|
|
|
|
| 946 |
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
| 947 |
strprintf("%d", nSigOpsCost));
|
| 948 |
|
|
|
|
| 268 |
return EvaluateSequenceLocks(index, {lock_points.height, lock_points.time});
|
| 269 |
}
|
| 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 |
+
|
| 300 |
static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
|
| 301 |
EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
|
| 302 |
{
|
|
|
|
| 841 |
|
| 842 |
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
| 843 |
std::string reason;
|
| 844 |
+
if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts, reason)) {
|
| 845 |
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
|
| 846 |
}
|
| 847 |
|
|
|
|
| 929 |
return false; // state filled in by CheckTxInputs
|
| 930 |
}
|
| 931 |
|
| 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);
|
| 963 |
}
|
| 964 |
|
| 965 |
// Check for non-standard witnesses.
|
| 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);
|
| 968 |
}
|
| 969 |
|
| 970 |
int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
|
|
|
|
| 1000 |
}
|
| 1001 |
}
|
| 1002 |
|
| 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))
|
| 1006 |
return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "bad-txns-too-many-sigops",
|
| 1007 |
strprintf("%d", nSigOpsCost));
|
| 1008 |
|