Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3

src/validation.cpp

Before: src/validation.cpp · After: src/validation.cpp

File metadata
index 21ccf045fbfcd200ec1dea6ad867a65eec02dfbc..89daf215e6c9aec6905aa611c1c360fc980e9921 100644

Download original patch · Release notes

Diff rows 1–400 of 802. 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
@@ -106,6 +106,8 @@ const std::vector<std::string> CHECKLEVEL_DOC {
106
  "level 4 tries to reconnect the blocks",
107
  "each level includes the checks of the previous levels",
108
  };
 
 
109
  /** The number of blocks to keep below the deepest prune lock.
110
  * There is nothing special about this number. It is higher than what we
111
  * expect to see in regular mainnet reorgs, but not so high that it would
@@ -272,7 +274,39 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
272
  // Returns the script flags which should be checked for a given block
273
  static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
274
 
275
- static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
  EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
277
  {
278
  AssertLockHeld(::cs_main);
@@ -459,7 +493,7 @@ public:
459
  struct ATMPArgs {
460
  const CChainParams& m_chainparams;
461
  const int64_t m_accept_time;
462
- const bool m_bypass_limits;
463
  /*
464
  * Return any outpoints which were not previously present in the coins
465
  * cache, but were added as a result of validating the tx for mempool
@@ -494,11 +528,11 @@ public:
494
 
495
  /** Parameters for single transaction mempool validation. */
496
  static ATMPArgs SingleAccept(const CChainParams& chainparams, int64_t accept_time,
497
- bool bypass_limits, std::vector<COutPoint>& coins_to_uncache,
498
  bool test_accept) {
499
  return ATMPArgs{/* m_chainparams */ chainparams,
500
  /* m_accept_time */ accept_time,
501
- /* m_bypass_limits */ bypass_limits,
502
  /* m_coins_to_uncache */ coins_to_uncache,
503
  /* m_test_accept */ test_accept,
504
  /* m_allow_replacement */ true,
@@ -512,10 +546,10 @@ public:
512
 
513
  /** Parameters for test package mempool validation through testmempoolaccept. */
514
  static ATMPArgs PackageTestAccept(const CChainParams& chainparams, int64_t accept_time,
515
- std::vector<COutPoint>& coins_to_uncache) {
516
  return ATMPArgs{/* m_chainparams */ chainparams,
517
  /* m_accept_time */ accept_time,
518
- /* m_bypass_limits */ false,
519
  /* m_coins_to_uncache */ coins_to_uncache,
520
  /* m_test_accept */ true,
521
  /* m_allow_replacement */ false,
@@ -529,10 +563,10 @@ public:
529
 
530
  /** Parameters for child-with-parents package validation. */
531
  static ATMPArgs PackageChildWithParents(const CChainParams& chainparams, int64_t accept_time,
532
- std::vector<COutPoint>& coins_to_uncache, const std::optional<CFeeRate>& client_maxfeerate) {
533
  return ATMPArgs{/* m_chainparams */ chainparams,
534
  /* m_accept_time */ accept_time,
535
- /* m_bypass_limits */ false,
536
  /* m_coins_to_uncache */ coins_to_uncache,
537
  /* m_test_accept */ false,
538
  /* m_allow_replacement */ true,
@@ -548,7 +582,7 @@ public:
548
  static ATMPArgs SingleInPackageAccept(const ATMPArgs& package_args) {
549
  return ATMPArgs{/* m_chainparams */ package_args.m_chainparams,
550
  /* m_accept_time */ package_args.m_accept_time,
551
- /* m_bypass_limits */ false,
552
  /* m_coins_to_uncache */ package_args.m_coins_to_uncache,
553
  /* m_test_accept */ package_args.m_test_accept,
554
  /* m_allow_replacement */ true,
@@ -565,7 +599,7 @@ public:
565
  // mixing up the order of the arguments. Use static functions above instead.
566
  ATMPArgs(const CChainParams& chainparams,
567
  int64_t accept_time,
568
- bool bypass_limits,
569
  std::vector<COutPoint>& coins_to_uncache,
570
  bool test_accept,
571
  bool allow_replacement,
@@ -576,7 +610,7 @@ public:
576
  bool allow_carveouts)
577
  : m_chainparams{chainparams},
578
  m_accept_time{accept_time},
579
- m_bypass_limits{bypass_limits},
580
  m_coins_to_uncache{coins_to_uncache},
581
  m_test_accept{test_accept},
582
  m_allow_replacement{allow_replacement},
@@ -636,7 +670,8 @@ private:
636
  explicit Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
637
  /** Txids of mempool transactions that this transaction directly conflicts with or may
638
  * replace via sibling eviction. */
639
- std::set<Txid> m_conflicts;
 
640
  /** Iterators to mempool entries that this transaction directly conflicts with or may
641
  * replace via sibling eviction. */
642
  CTxMemPool::setEntries m_iters_conflicting;
@@ -670,6 +705,23 @@ private:
670
  PrecomputedTransactionData m_precomputed_txdata;
671
  };
672
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
673
  // Run the policy checks on a given transaction, excluding any script checks.
674
  // Looks up inputs, calculates feerate, considers replacement, evaluates
675
  // package limits, etc. As this function can be invoked for "free" by a peer,
@@ -677,11 +729,11 @@ private:
677
  bool PreChecks(ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
678
 
679
  // Run checks for mempool replace-by-fee, only used in AcceptSingleTransaction.
680
- bool ReplacementChecks(Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
681
 
682
  // Enforce package mempool ancestor/descendant limits (distinct from individual
683
  // ancestor/descendant limits done in PreChecks) and run Package RBF checks.
684
- bool PackageMempoolChecks(const std::vector<CTransactionRef>& txns,
685
  std::vector<Workspace>& workspaces,
686
  int64_t total_vsize,
687
  PackageValidationState& package_state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
@@ -707,16 +759,16 @@ private:
707
  EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
708
 
709
  // Compare a package's feerate against minimum allowed.
710
- bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_pool.cs)
711
  {
712
  AssertLockHeld(::cs_main);
713
  AssertLockHeld(m_pool.cs);
714
  CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
715
- if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee) {
716
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
717
  }
718
 
719
- if (package_fee < m_pool.m_opts.min_relay_feerate.GetFee(package_size)) {
720
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "min relay fee not met",
721
  strprintf("%d < %d", package_fee, m_pool.m_opts.min_relay_feerate.GetFee(package_size)));
722
  }
@@ -800,7 +852,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
800
 
801
  // Copy/alias what we need out of args
802
  const int64_t nAcceptTime = args.m_accept_time;
803
- const bool bypass_limits = args.m_bypass_limits;
804
  std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
805
 
806
  // Alias what we need out of ws
@@ -814,21 +866,25 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
814
  if (tx.IsCoinBase())
815
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");
816
 
 
 
 
 
817
  // Rather not work on nonstandard transactions (unless -testnet/-regtest)
818
  std::string reason;
819
- 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)) {
820
  return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
821
  }
822
 
823
  // Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
824
  if (::GetSerializeSize(TX_NO_WITNESS(tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)
825
- return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
826
 
827
  // Only accept nLockTime-using transactions that can be mined in the next
828
  // block; we don't want our mempool filled up with transactions that can't
829
  // be mined yet.
830
  if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
831
- return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
832
  }
833
 
834
  if (m_pool.exists(tx.GetWitnessHash())) {
@@ -840,16 +896,68 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
840
  return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
841
  }
842
 
 
 
 
 
 
 
843
  // Check for conflicts with in-memory transactions
844
  for (const CTxIn &txin : tx.vin)
845
  {
846
  const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);
847
  if (ptxConflicting) {
848
  if (!args.m_allow_replacement) {
849
- // Transaction conflicts with a mempool tx, but we're not allowing replacements in this context.
850
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");
851
  }
852
- ws.m_conflicts.insert(ptxConflicting->GetHash());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
853
  }
854
  }
855
 
@@ -895,22 +1003,67 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
895
  // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
896
  // backend was removed, it no longer pulls coins from the mempool.
897
  const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};
 
898
  if (!lock_points.has_value() || !CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), *lock_points)) {
899
  return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
900
  }
901
 
902
  // The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
903
- if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_chain.Height() + 1, ws.m_base_fees)) {
 
 
904
  return false; // state filled in by CheckTxInputs
905
  }
906
 
907
- if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view)) {
908
- return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
909
  }
910
 
911
  // Check for non-standard witnesses.
912
- if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view)) {
913
- return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
914
  }
915
 
916
  int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -926,29 +1079,63 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
926
  }
927
  }
928
 
929
- // Set entry_sequence to 0 when bypass_limits is used; this allows txs from a block
 
 
 
 
 
 
 
930
  // reorg to be marked earlier than any child txs that were already in the mempool.
931
- const uint64_t entry_sequence = bypass_limits ? 0 : m_pool.GetSequence();
 
932
  if (!m_subpackage.m_changeset) {
933
  m_subpackage.m_changeset = m_pool.GetChangeSet();
934
  }
935
- ws.m_tx_handle = m_subpackage.m_changeset->StageAddition(ptx, ws.m_base_fees, nAcceptTime, m_active_chainstate.m_chain.Height(), entry_sequence, fSpendsCoinbase, nSigOpsCost, lock_points.value());
 
 
 
 
 
 
936
 
937
  // ws.m_modified_fees includes any fee deltas from PrioritiseTransaction
938
  ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();
939
 
940
  ws.m_vsize = ws.m_tx_handle->GetTxSize();
941
 
 
 
 
 
 
 
 
 
 
106
  "level 4 tries to reconnect the blocks",
107
  "each level includes the checks of the previous levels",
108
  };
109
+
110
+ SpkReuseModes SpkReuseMode{SRM_ALLOW};
111
  /** The number of blocks to keep below the deepest prune lock.
112
  * There is nothing special about this number. It is higher than what we
113
  * expect to see in regular mainnet reorgs, but not so high that it would
 
274
  // Returns the script flags which should be checked for a given block
275
  static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
276
 
277
+ /** Compute accurate total signature operation cost of a transaction.
278
+ * Not consensus-critical, since legacy sigops counting is always used in the protocol.
279
+ */
280
+ int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
281
+ {
282
+ if (tx.IsCoinBase()) {
283
+ return 0;
284
+ }
285
+
286
+ unsigned int nSigOps = 0;
287
+ for (const auto& txin : tx.vin) {
288
+ nSigOps += txin.scriptSig.GetSigOpCount(false);
289
+ }
290
+
291
+ if (flags & SCRIPT_VERIFY_P2SH) {
292
+ nSigOps += GetP2SHSigOpCount(tx, inputs);
293
+ }
294
+
295
+ nSigOps *= WITNESS_SCALE_FACTOR;
296
+
297
+ if (flags & SCRIPT_VERIFY_WITNESS) {
298
+ for (const auto& txin : tx.vin) {
299
+ const Coin& coin = inputs.AccessCoin(txin.prevout);
300
+ assert(!coin.IsSpent());
301
+ const CTxOut &prevout = coin.out;
302
+ nSigOps += CountWitnessSigOps(txin.scriptSig, prevout.scriptPubKey, &txin.scriptWitness, flags);
303
+ }
304
+ }
305
+
306
+ return nSigOps;
307
+ }
308
+
309
+ void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
310
  EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
311
  {
312
  AssertLockHeld(::cs_main);
 
493
  struct ATMPArgs {
494
  const CChainParams& m_chainparams;
495
  const int64_t m_accept_time;
496
+ const ignore_rejects_type& m_ignore_rejects;
497
  /*
498
  * Return any outpoints which were not previously present in the coins
499
  * cache, but were added as a result of validating the tx for mempool
 
528
 
529
  /** Parameters for single transaction mempool validation. */
530
  static ATMPArgs SingleAccept(const CChainParams& chainparams, int64_t accept_time,
531
+ const ignore_rejects_type& ignore_rejects, std::vector<COutPoint>& coins_to_uncache,
532
  bool test_accept) {
533
  return ATMPArgs{/* m_chainparams */ chainparams,
534
  /* m_accept_time */ accept_time,
535
+ /* m_ignore_rejects */ ignore_rejects,
536
  /* m_coins_to_uncache */ coins_to_uncache,
537
  /* m_test_accept */ test_accept,
538
  /* m_allow_replacement */ true,
 
546
 
547
  /** Parameters for test package mempool validation through testmempoolaccept. */
548
  static ATMPArgs PackageTestAccept(const CChainParams& chainparams, int64_t accept_time,
549
+ const ignore_rejects_type& ignore_rejects, std::vector<COutPoint>& coins_to_uncache) {
550
  return ATMPArgs{/* m_chainparams */ chainparams,
551
  /* m_accept_time */ accept_time,
552
+ /* m_ignore_rejects */ ignore_rejects,
553
  /* m_coins_to_uncache */ coins_to_uncache,
554
  /* m_test_accept */ true,
555
  /* m_allow_replacement */ false,
 
563
 
564
  /** Parameters for child-with-parents package validation. */
565
  static ATMPArgs PackageChildWithParents(const CChainParams& chainparams, int64_t accept_time,
566
+ std::vector<COutPoint>& coins_to_uncache, const std::optional<CFeeRate>& client_maxfeerate, const ignore_rejects_type& ignore_rejects) {
567
  return ATMPArgs{/* m_chainparams */ chainparams,
568
  /* m_accept_time */ accept_time,
569
+ /* m_ignore_rejects */ ignore_rejects,
570
  /* m_coins_to_uncache */ coins_to_uncache,
571
  /* m_test_accept */ false,
572
  /* m_allow_replacement */ true,
 
582
  static ATMPArgs SingleInPackageAccept(const ATMPArgs& package_args) {
583
  return ATMPArgs{/* m_chainparams */ package_args.m_chainparams,
584
  /* m_accept_time */ package_args.m_accept_time,
585
+ empty_ignore_rejects,
586
  /* m_coins_to_uncache */ package_args.m_coins_to_uncache,
587
  /* m_test_accept */ package_args.m_test_accept,
588
  /* m_allow_replacement */ true,
 
599
  // mixing up the order of the arguments. Use static functions above instead.
600
  ATMPArgs(const CChainParams& chainparams,
601
  int64_t accept_time,
602
+ const ignore_rejects_type& ignore_rejects,
603
  std::vector<COutPoint>& coins_to_uncache,
604
  bool test_accept,
605
  bool allow_replacement,
 
610
  bool allow_carveouts)
611
  : m_chainparams{chainparams},
612
  m_accept_time{accept_time},
613
+ m_ignore_rejects{ignore_rejects},
614
  m_coins_to_uncache{coins_to_uncache},
615
  m_test_accept{test_accept},
616
  m_allow_replacement{allow_replacement},
 
670
  explicit Workspace(const CTransactionRef& ptx) : m_ptx(ptx), m_hash(ptx->GetHash()) {}
671
  /** Txids of mempool transactions that this transaction directly conflicts with or may
672
  * replace via sibling eviction. */
673
+ /** .second=true is a consensus conflict, and .second=false is a policy conflict. */
674
+ std::map<Txid, bool> m_conflicts_incl_policy;
675
  /** Iterators to mempool entries that this transaction directly conflicts with or may
676
  * replace via sibling eviction. */
677
  CTxMemPool::setEntries m_iters_conflicting;
 
705
  PrecomputedTransactionData m_precomputed_txdata;
706
  };
707
 
708
+ static inline bool MaybeReject_(TxValidationResult reason, const std::string& reason_str, const std::string& debug_msg, const ignore_rejects_type& ignore_rejects, TxValidationState& state) {
709
+ if (ignore_rejects.count(reason_str)) {
710
+ return false;
711
+ }
712
+
713
+ state.Invalid(reason, reason_str, debug_msg);
714
+ return true;
715
+ }
716
+
717
+ #define MaybeRejectDbg(reason, reason_str, debug_msg) do { \
718
+ if (MaybeReject_(reason, reason_str, debug_msg, ignore_rejects, state)) { \
719
+ return false; \
720
+ } \
721
+ } while(0)
722
+
723
+ #define MaybeReject(reason, reason_str) MaybeRejectDbg(reason, reason_str, "")
724
+
725
  // Run the policy checks on a given transaction, excluding any script checks.
726
  // Looks up inputs, calculates feerate, considers replacement, evaluates
727
  // package limits, etc. As this function can be invoked for "free" by a peer,
 
729
  bool PreChecks(ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
730
 
731
  // Run checks for mempool replace-by-fee, only used in AcceptSingleTransaction.
732
+ bool ReplacementChecks(ATMPArgs& args, Workspace& ws) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
733
 
734
  // Enforce package mempool ancestor/descendant limits (distinct from individual
735
  // ancestor/descendant limits done in PreChecks) and run Package RBF checks.
736
+ bool PackageMempoolChecks(const ATMPArgs& args, const std::vector<CTransactionRef>& txns,
737
  std::vector<Workspace>& workspaces,
738
  int64_t total_vsize,
739
  PackageValidationState& package_state) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
 
759
  EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_pool.cs);
760
 
761
  // Compare a package's feerate against minimum allowed.
762
+ bool CheckFeeRate(size_t package_size, CAmount package_fee, TxValidationState& state, const ignore_rejects_type& ignore_rejects) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, m_pool.cs)
763
  {
764
  AssertLockHeld(::cs_main);
765
  AssertLockHeld(m_pool.cs);
766
  CAmount mempoolRejectFee = m_pool.GetMinFee().GetFee(package_size);
767
+ if (mempoolRejectFee > 0 && package_fee < mempoolRejectFee && !ignore_rejects.count(rejectmsg_lowfee_mempool)) {
768
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "mempool min fee not met", strprintf("%d < %d", package_fee, mempoolRejectFee));
769
  }
770
 
771
+ if (package_fee < m_pool.m_opts.min_relay_feerate.GetFee(package_size) && !ignore_rejects.count(rejectmsg_lowfee_relay)) {
772
  return state.Invalid(TxValidationResult::TX_RECONSIDERABLE, "min relay fee not met",
773
  strprintf("%d < %d", package_fee, m_pool.m_opts.min_relay_feerate.GetFee(package_size)));
774
  }
 
852
 
853
  // Copy/alias what we need out of args
854
  const int64_t nAcceptTime = args.m_accept_time;
855
+ const ignore_rejects_type& ignore_rejects = args.m_ignore_rejects;
856
  std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
857
 
858
  // Alias what we need out of ws
 
866
  if (tx.IsCoinBase())
867
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");
868
 
869
+ if (tx.version == TRUC_VERSION && m_pool.m_opts.truc_policy == TRUCPolicy::Reject) {
870
+ return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "version");
871
+ }
872
+
873
  // Rather not work on nonstandard transactions (unless -testnet/-regtest)
874
  std::string reason;
875
+ if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts, reason, ignore_rejects)) {
876
  return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
877
  }
878
 
879
  // Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
880
  if (::GetSerializeSize(TX_NO_WITNESS(tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)
881
+ MaybeReject(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
882
 
883
  // Only accept nLockTime-using transactions that can be mined in the next
884
  // block; we don't want our mempool filled up with transactions that can't
885
  // be mined yet.
886
  if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
887
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
888
  }
889
 
890
  if (m_pool.exists(tx.GetWitnessHash())) {
 
896
  return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
897
  }
898
 
899
+ auto spk_reuse_mode = SpkReuseMode;
900
+ if (ignore_rejects.count("txn-spk-reused")) {
901
+ spk_reuse_mode = SRM_ALLOW;
902
+ }
903
+ SPKStates_t mapSPK;
904
+
905
  // Check for conflicts with in-memory transactions
906
  for (const CTxIn &txin : tx.vin)
907
  {
908
  const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);
909
  if (ptxConflicting) {
910
  if (!args.m_allow_replacement) {
911
+ // Transaction conflicts with a mempool tx, but we're not allowing replacements.
912
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");
913
  }
914
+ if (!ws.m_conflicts_incl_policy.count(ptxConflicting->GetHash()))
915
+ {
916
+ // Transactions that don't explicitly signal replaceability are
917
+ // *not* replaceable with the current logic, even if one of their
918
+ // unconfirmed ancestors signals replaceability. This diverges
919
+ // from BIP125's inherited signaling description (see CVE-2021-31876).
920
+ // Applications relying on first-seen mempool behavior should
921
+ // check all unconfirmed ancestors; otherwise an opt-in ancestor
922
+ // might be replaced, causing removal of this descendant.
923
+ //
924
+ // All TRUC transactions are considered replaceable.
925
+ //
926
+ // Replaceability signaling of the original transactions may be
927
+ // ignored due to node setting.
928
+ bool allow_rbf;
929
+ if (m_pool.m_opts.rbf_policy == RBFPolicy::Always || ignore_rejects.count("txn-mempool-conflict")) {
930
+ allow_rbf = true;
931
+ } else if (m_pool.m_opts.rbf_policy == RBFPolicy::Never) {
932
+ allow_rbf = false;
933
+ } else {
934
+ allow_rbf = SignalsOptInRBF(*ptxConflicting) || ptxConflicting->version == TRUC_VERSION;
935
+ }
936
+ if (!allow_rbf) {
937
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "txn-mempool-conflict");
938
+ }
939
+
940
+ ws.m_conflicts_incl_policy.emplace(ptxConflicting->GetHash(), true);
941
+ }
942
+ }
943
+ }
944
+
945
+ if (spk_reuse_mode != SRM_ALLOW) {
946
+ for (const CTxOut& txout : tx.vout) {
947
+ uint160 hashSPK = ScriptHashkey(txout.scriptPubKey);
948
+ const auto& SPKUsedIn = m_pool.mapUsedSPK.find(hashSPK);
949
+ if (SPKUsedIn != m_pool.mapUsedSPK.end()) {
950
+ if (SPKUsedIn->second.first) {
951
+ ws.m_conflicts_incl_policy.emplace(SPKUsedIn->second.first->GetHash(), false);
952
+ }
953
+ if (SPKUsedIn->second.second) {
954
+ ws.m_conflicts_incl_policy.emplace(SPKUsedIn->second.second->GetHash(), false);
955
+ }
956
+ }
957
+ if (mapSPK.find(hashSPK) != mapSPK.end()) {
958
+ MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-twinoutputs");
959
+ }
960
+ mapSPK[hashSPK] = MemPool_SPK_State(mapSPK[hashSPK] | MSS_CREATED);
961
  }
962
  }
963
 
 
1003
  // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
1004
  // backend was removed, it no longer pulls coins from the mempool.
1005
  const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};
1006
+ // NOTE: The miner doesn't check this again, so for now it may not be overridden.
1007
  if (!lock_points.has_value() || !CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), *lock_points)) {
1008
  return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
1009
  }
1010
 
1011
  // The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
1012
+ const auto block_height_current = m_active_chainstate.m_chain.Height();
1013
+ const auto block_height_next = block_height_current + 1;
1014
+ if (!Consensus::CheckTxInputs(tx, state, m_view, block_height_next, ws.m_base_fees)) {
1015
  return false; // state filled in by CheckTxInputs
1016
  }
1017
 
1018
+ if (m_pool.m_opts.minrelaymaturity) {
1019
+ auto max_coin_height = block_height_next - m_pool.m_opts.minrelaymaturity;
1020
+ static_assert(std::is_signed_v<decltype(max_coin_height)>, "Unsigned max_coin_height needs a range check");
1021
+ for (const CTxIn &txin : tx.vin) {
1022
+ const Coin &coin = m_view.AccessCoin(txin.prevout);
1023
+ if (coin.nHeight > max_coin_height) {
1024
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-depth");
1025
+ }
1026
+ }
1027
+ }
1028
+
1029
+ if (spk_reuse_mode != SRM_ALLOW) {
1030
+ for (const CTxIn& txin : tx.vin) {
1031
+ const Coin &coin = m_view.AccessCoin(txin.prevout);
1032
+ uint160 hashSPK = ScriptHashkey(coin.out.scriptPubKey);
1033
+
1034
+ SPKStates_t::iterator mssit = mapSPK.find(hashSPK);
1035
+ if (mssit != mapSPK.end()) {
1036
+ if (mssit->second & MSS_CREATED) {
1037
+ MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-change");
1038
+ }
1039
+ }
1040
+ const auto& SPKit = m_pool.mapUsedSPK.find(hashSPK);
1041
+ if (SPKit != m_pool.mapUsedSPK.end()) {
1042
+ if (SPKit->second.second /* Spent */) {
1043
+ ws.m_conflicts_incl_policy.emplace(SPKit->second.second->GetHash(), false);
1044
+ }
1045
+ }
1046
+ mapSPK[hashSPK] = MemPool_SPK_State(mapSPK[hashSPK] | MSS_SPENT);
1047
+ }
1048
+ }
1049
+
1050
+ if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view, m_pool.m_opts, "bad-txns-input-", reason, ignore_rejects)) {
1051
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, reason);
1052
+ }
1053
+
1054
+ if (m_pool.m_opts.datacarrier_fullcount || !m_pool.m_opts.accept_non_std_datacarrier) {
1055
+ const auto dcb = DatacarrierBytes(tx, m_view);
1056
+ if (dcb.second > 0 && !(m_pool.m_opts.accept_non_std_datacarrier || ignore_rejects.count("txn-datacarrier-nonstandard"))) {
1057
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-nonstandard");
1058
+ }
1059
+ if (m_pool.m_opts.datacarrier_fullcount && (!ignore_rejects.count("txn-datacarrier-exceeded")) && dcb.first + dcb.second > m_pool.m_opts.max_datacarrier_bytes.value_or(0)) {
1060
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-exceeded");
1061
+ }
1062
  }
1063
 
1064
  // Check for non-standard witnesses.
1065
+ if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view, "bad-witness-", reason, ignore_rejects)) {
1066
+ return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, reason);
1067
  }
1068
 
1069
  int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
 
1079
  }
1080
  }
1081
 
1082
+ // Since entries arrive *after* the tip's height, their priority is for the height+1
1083
+ const auto coin_age = GetCoinAge(tx, m_view, block_height_next);
1084
+
1085
+ if (coin_age.inputs_coin_age < m_pool.m_opts.minrelaycoinblocks) {
1086
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-coinblocks");
1087
+ }
1088
+
1089
+ // Set entry_sequence to 0 when rejectmsg_zero_mempool_entry_seq is used; this allows txs from a block
1090
  // reorg to be marked earlier than any child txs that were already in the mempool.
1091
+ const uint64_t entry_sequence = args.m_ignore_rejects.count(rejectmsg_zero_mempool_entry_seq) ? 0 : m_pool.GetSequence();
1092
+ int32_t extra_weight = CalculateExtraTxWeight(*ptx, m_view, ::g_weight_per_data_byte);
1093
  if (!m_subpackage.m_changeset) {
1094
  m_subpackage.m_changeset = m_pool.GetChangeSet();
1095
  }
1096
+ ws.m_tx_handle = m_subpackage.m_changeset->StageAddition(ptx, ws.m_base_fees, nAcceptTime, block_height_current, entry_sequence, coin_age, fSpendsCoinbase, /*extra_weight=*/ extra_weight, /*sigops_cost=*/ nSigOpsCost, lock_points.value());
1097
+
1098
+ if (spk_reuse_mode != SRM_ALLOW) {
1099
+ m_subpackage.m_changeset->m_to_add.modify(ws.m_tx_handle, [=](CTxMemPoolEntry& e) {
1100
+ e.mapSPK = mapSPK;
1101
+ });
1102
+ }
1103
 
1104
  // ws.m_modified_fees includes any fee deltas from PrioritiseTransaction
1105
  ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();
1106
 
1107
  ws.m_vsize = ws.m_tx_handle->GetTxSize();
1108
 
1109
+ // Reduce effective fee by dust threshold for each sub-dust output
1110
+ if (m_pool.m_opts.subdustfeepenalty) {
1111
+ CAmount dust_penalty{0};
1112
+ for (const auto& txout : tx.vout) {
1113
+ const CAmount dust_threshold = GetDustThreshold(txout, m_pool.m_opts.dust_relay_feerate);
1114
+ if (txout.nValue < dust_threshold) {
1115
+ dust_penalty = SaturatingAdd(dust_penalty, dust_threshold - txout.nValue);
1116
+ }