Skip to content
Bitcoin Roots

v29.4-roots.4 · Commit 3: [PATCH 03/37] policy: restore conservative relay and network controls

src/validation.cpp

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

File metadata
index ff281bc1a6f885fd9efe1f01cfc2b91d230df084..c2530e7d119fcc4fe7fb0f89824eeaad60e13a37 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
@@ -104,6 +104,8 @@ const std::vector<std::string> CHECKLEVEL_DOC {
104
  "level 4 tries to reconnect the blocks",
105
  "each level includes the checks of the previous levels",
106
  };
 
 
107
  /** The number of blocks to keep below the deepest prune lock.
108
  * There is nothing special about this number. It is higher than what we
109
  * expect to see in regular mainnet reorgs, but not so high that it would
@@ -270,7 +272,39 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip,
270
  // Returns the script flags which should be checked for a given block
271
  static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman);
272
 
273
- static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
275
  {
276
  AssertLockHeld(::cs_main);
@@ -457,7 +491,7 @@ public:
457
  struct ATMPArgs {
458
  const CChainParams& m_chainparams;
459
  const int64_t m_accept_time;
460
- const bool m_bypass_limits;
461
  /*
462
  * Return any outpoints which were not previously present in the coins
463
  * 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-unconfirmed-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
  }
@@ -781,7 +833,7 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
781
 
782
  // Copy/alias what we need out of args
783
  const int64_t nAcceptTime = args.m_accept_time;
784
- const bool bypass_limits = args.m_bypass_limits;
785
  std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
786
 
787
  // Alias what we need out of ws
@@ -795,21 +847,25 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
795
  if (tx.IsCoinBase())
796
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");
797
 
 
 
 
 
798
  // Rather not work on nonstandard transactions (unless -testnet/-regtest)
799
  std::string reason;
800
- 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)) {
801
  return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
802
  }
803
 
804
  // Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
805
  if (::GetSerializeSize(TX_NO_WITNESS(tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)
806
- return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
807
 
808
  // Only accept nLockTime-using transactions that can be mined in the next
809
  // block; we don't want our mempool filled up with transactions that can't
810
  // be mined yet.
811
  if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
812
- return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
813
  }
814
 
815
  if (m_pool.exists(GenTxid::Wtxid(tx.GetWitnessHash()))) {
@@ -821,16 +877,68 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
821
  return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
822
  }
823
 
 
 
 
 
 
 
824
  // Check for conflicts with in-memory transactions
825
  for (const CTxIn &txin : tx.vin)
826
  {
827
  const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);
828
  if (ptxConflicting) {
829
  if (!args.m_allow_replacement) {
830
- // Transaction conflicts with a mempool tx, but we're not allowing replacements in this context.
831
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");
832
  }
833
- ws.m_conflicts.insert(ptxConflicting->GetHash());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
834
  }
835
  }
836
 
@@ -876,22 +984,67 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
876
  // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
877
  // backend was removed, it no longer pulls coins from the mempool.
878
  const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};
 
879
  if (!lock_points.has_value() || !CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), *lock_points)) {
880
  return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
881
  }
882
 
883
  // The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
884
- if (!Consensus::CheckTxInputs(tx, state, m_view, m_active_chainstate.m_chain.Height() + 1, ws.m_base_fees)) {
 
 
885
  return false; // state filled in by CheckTxInputs
886
  }
887
 
888
- if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view)) {
889
- return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "bad-txns-nonstandard-inputs");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
890
  }
891
 
892
  // Check for non-standard witnesses.
893
- if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view)) {
894
- return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-witness-nonstandard");
895
  }
896
 
897
  int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
@@ -907,29 +1060,63 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws)
907
  }
908
  }
909
 
910
- // Set entry_sequence to 0 when bypass_limits is used; this allows txs from a block
 
 
 
 
 
 
 
911
  // reorg to be marked earlier than any child txs that were already in the mempool.
912
- const uint64_t entry_sequence = bypass_limits ? 0 : m_pool.GetSequence();
 
913
  if (!m_subpackage.m_changeset) {
914
  m_subpackage.m_changeset = m_pool.GetChangeSet();
915
  }
916
- 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());
 
 
 
 
 
 
917
 
918
  // ws.m_modified_fees includes any fee deltas from PrioritiseTransaction
919
  ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();
920
 
921
  ws.m_vsize = ws.m_tx_handle->GetTxSize();
922
 
 
 
 
 
 
 
 
 
 
104
  "level 4 tries to reconnect the blocks",
105
  "each level includes the checks of the previous levels",
106
  };
107
+
108
+ SpkReuseModes SpkReuseMode{SRM_ALLOW};
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
  // 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
+ /** Compute accurate total signature operation cost of a transaction.
276
+ * Not consensus-critical, since legacy sigops counting is always used in the protocol.
277
+ */
278
+ int64_t GetAccurateTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
279
+ {
280
+ if (tx.IsCoinBase()) {
281
+ return 0;
282
+ }
283
+
284
+ unsigned int nSigOps = 0;
285
+ for (const auto& txin : tx.vin) {
286
+ nSigOps += txin.scriptSig.GetSigOpCount(false);
287
+ }
288
+
289
+ if (flags & SCRIPT_VERIFY_P2SH) {
290
+ nSigOps += GetP2SHSigOpCount(tx, inputs);
291
+ }
292
+
293
+ nSigOps *= WITNESS_SCALE_FACTOR;
294
+
295
+ if (flags & SCRIPT_VERIFY_WITNESS) {
296
+ for (const auto& txin : tx.vin) {
297
+ const Coin& coin = inputs.AccessCoin(txin.prevout);
298
+ assert(!coin.IsSpent());
299
+ const CTxOut &prevout = coin.out;
300
+ nSigOps += CountWitnessSigOps(txin.scriptSig, prevout.scriptPubKey, &txin.scriptWitness, flags);
301
+ }
302
+ }
303
+
304
+ return nSigOps;
305
+ }
306
+
307
+ void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache)
308
  EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs)
309
  {
310
  AssertLockHeld(::cs_main);
 
491
  struct ATMPArgs {
492
  const CChainParams& m_chainparams;
493
  const int64_t m_accept_time;
494
+ const ignore_rejects_type& m_ignore_rejects;
495
  /*
496
  * Return any outpoints which were not previously present in the coins
497
  * 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-unconfirmed-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
  }
 
833
 
834
  // Copy/alias what we need out of args
835
  const int64_t nAcceptTime = args.m_accept_time;
836
+ const ignore_rejects_type& ignore_rejects = args.m_ignore_rejects;
837
  std::vector<COutPoint>& coins_to_uncache = args.m_coins_to_uncache;
838
 
839
  // Alias what we need out of ws
 
847
  if (tx.IsCoinBase())
848
  return state.Invalid(TxValidationResult::TX_CONSENSUS, "coinbase");
849
 
850
+ if (tx.version == TRUC_VERSION && m_pool.m_opts.truc_policy == TRUCPolicy::Reject) {
851
+ return state.Invalid(TxValidationResult::TX_NOT_STANDARD, "version");
852
+ }
853
+
854
  // Rather not work on nonstandard transactions (unless -testnet/-regtest)
855
  std::string reason;
856
+ if (m_pool.m_opts.require_standard && !IsStandardTx(tx, m_pool.m_opts, reason, ignore_rejects)) {
857
  return state.Invalid(TxValidationResult::TX_NOT_STANDARD, reason);
858
  }
859
 
860
  // Transactions smaller than 65 non-witness bytes are not relayed to mitigate CVE-2017-12842.
861
  if (::GetSerializeSize(TX_NO_WITNESS(tx)) < MIN_STANDARD_TX_NONWITNESS_SIZE)
862
+ MaybeReject(TxValidationResult::TX_NOT_STANDARD, "tx-size-small");
863
 
864
  // Only accept nLockTime-using transactions that can be mined in the next
865
  // block; we don't want our mempool filled up with transactions that can't
866
  // be mined yet.
867
  if (!CheckFinalTxAtTip(*Assert(m_active_chainstate.m_chain.Tip()), tx)) {
868
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "non-final");
869
  }
870
 
871
  if (m_pool.exists(GenTxid::Wtxid(tx.GetWitnessHash()))) {
 
877
  return state.Invalid(TxValidationResult::TX_CONFLICT, "txn-same-nonwitness-data-in-mempool");
878
  }
879
 
880
+ auto spk_reuse_mode = SpkReuseMode;
881
+ if (ignore_rejects.count("txn-spk-reused")) {
882
+ spk_reuse_mode = SRM_ALLOW;
883
+ }
884
+ SPKStates_t mapSPK;
885
+
886
  // Check for conflicts with in-memory transactions
887
  for (const CTxIn &txin : tx.vin)
888
  {
889
  const CTransaction* ptxConflicting = m_pool.GetConflictTx(txin.prevout);
890
  if (ptxConflicting) {
891
  if (!args.m_allow_replacement) {
892
+ // Transaction conflicts with a mempool tx, but we're not allowing replacements.
893
  return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "bip125-replacement-disallowed");
894
  }
895
+ if (!ws.m_conflicts_incl_policy.count(ptxConflicting->GetHash()))
896
+ {
897
+ // Transactions that don't explicitly signal replaceability are
898
+ // *not* replaceable with the current logic, even if one of their
899
+ // unconfirmed ancestors signals replaceability. This diverges
900
+ // from BIP125's inherited signaling description (see CVE-2021-31876).
901
+ // Applications relying on first-seen mempool behavior should
902
+ // check all unconfirmed ancestors; otherwise an opt-in ancestor
903
+ // might be replaced, causing removal of this descendant.
904
+ //
905
+ // All TRUC transactions are considered replaceable.
906
+ //
907
+ // Replaceability signaling of the original transactions may be
908
+ // ignored due to node setting.
909
+ bool allow_rbf;
910
+ if (m_pool.m_opts.rbf_policy == RBFPolicy::Always || ignore_rejects.count("txn-mempool-conflict")) {
911
+ allow_rbf = true;
912
+ } else if (m_pool.m_opts.rbf_policy == RBFPolicy::Never) {
913
+ allow_rbf = false;
914
+ } else {
915
+ allow_rbf = SignalsOptInRBF(*ptxConflicting) || ptxConflicting->version == TRUC_VERSION;
916
+ }
917
+ if (!allow_rbf) {
918
+ return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "txn-mempool-conflict");
919
+ }
920
+
921
+ ws.m_conflicts_incl_policy.emplace(ptxConflicting->GetHash(), true);
922
+ }
923
+ }
924
+ }
925
+
926
+ if (spk_reuse_mode != SRM_ALLOW) {
927
+ for (const CTxOut& txout : tx.vout) {
928
+ uint160 hashSPK = ScriptHashkey(txout.scriptPubKey);
929
+ const auto& SPKUsedIn = m_pool.mapUsedSPK.find(hashSPK);
930
+ if (SPKUsedIn != m_pool.mapUsedSPK.end()) {
931
+ if (SPKUsedIn->second.first) {
932
+ ws.m_conflicts_incl_policy.emplace(SPKUsedIn->second.first->GetHash(), false);
933
+ }
934
+ if (SPKUsedIn->second.second) {
935
+ ws.m_conflicts_incl_policy.emplace(SPKUsedIn->second.second->GetHash(), false);
936
+ }
937
+ }
938
+ if (mapSPK.find(hashSPK) != mapSPK.end()) {
939
+ MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-twinoutputs");
940
+ }
941
+ mapSPK[hashSPK] = MemPool_SPK_State(mapSPK[hashSPK] | MSS_CREATED);
942
  }
943
  }
944
 
 
984
  // Pass in m_view which has all of the relevant inputs cached. Note that, since m_view's
985
  // backend was removed, it no longer pulls coins from the mempool.
986
  const std::optional<LockPoints> lock_points{CalculateLockPointsAtTip(m_active_chainstate.m_chain.Tip(), m_view, tx)};
987
+ // NOTE: The miner doesn't check this again, so for now it may not be overridden.
988
  if (!lock_points.has_value() || !CheckSequenceLocksAtTip(m_active_chainstate.m_chain.Tip(), *lock_points)) {
989
  return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "non-BIP68-final");
990
  }
991
 
992
  // The mempool holds txs for the next block, so pass height+1 to CheckTxInputs
993
+ const auto block_height_current = m_active_chainstate.m_chain.Height();
994
+ const auto block_height_next = block_height_current + 1;
995
+ if (!Consensus::CheckTxInputs(tx, state, m_view, block_height_next, ws.m_base_fees)) {
996
  return false; // state filled in by CheckTxInputs
997
  }
998
 
999
+ if (m_pool.m_opts.minrelaymaturity) {
1000
+ auto max_coin_height = block_height_next - m_pool.m_opts.minrelaymaturity;
1001
+ static_assert(std::is_signed_v<decltype(max_coin_height)>, "Unsigned max_coin_height needs a range check");
1002
+ for (const CTxIn &txin : tx.vin) {
1003
+ const Coin &coin = m_view.AccessCoin(txin.prevout);
1004
+ if (coin.nHeight > max_coin_height) {
1005
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-depth");
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ if (spk_reuse_mode != SRM_ALLOW) {
1011
+ for (const CTxIn& txin : tx.vin) {
1012
+ const Coin &coin = m_view.AccessCoin(txin.prevout);
1013
+ uint160 hashSPK = ScriptHashkey(coin.out.scriptPubKey);
1014
+
1015
+ SPKStates_t::iterator mssit = mapSPK.find(hashSPK);
1016
+ if (mssit != mapSPK.end()) {
1017
+ if (mssit->second & MSS_CREATED) {
1018
+ MaybeReject(TxValidationResult::TX_MEMPOOL_POLICY, "txn-spk-reused-change");
1019
+ }
1020
+ }
1021
+ const auto& SPKit = m_pool.mapUsedSPK.find(hashSPK);
1022
+ if (SPKit != m_pool.mapUsedSPK.end()) {
1023
+ if (SPKit->second.second /* Spent */) {
1024
+ ws.m_conflicts_incl_policy.emplace(SPKit->second.second->GetHash(), false);
1025
+ }
1026
+ }
1027
+ mapSPK[hashSPK] = MemPool_SPK_State(mapSPK[hashSPK] | MSS_SPENT);
1028
+ }
1029
+ }
1030
+
1031
+ if (m_pool.m_opts.require_standard && !AreInputsStandard(tx, m_view, m_pool.m_opts, "bad-txns-input-", reason, ignore_rejects)) {
1032
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, reason);
1033
+ }
1034
+
1035
+ if (m_pool.m_opts.datacarrier_fullcount || !m_pool.m_opts.accept_non_std_datacarrier) {
1036
+ const auto dcb = DatacarrierBytes(tx, m_view);
1037
+ if (dcb.second > 0 && !(m_pool.m_opts.accept_non_std_datacarrier || ignore_rejects.count("txn-datacarrier-nonstandard"))) {
1038
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-nonstandard");
1039
+ }
1040
+ 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)) {
1041
+ return state.Invalid(TxValidationResult::TX_INPUTS_NOT_STANDARD, "txn-datacarrier-exceeded");
1042
+ }
1043
  }
1044
 
1045
  // Check for non-standard witnesses.
1046
+ if (tx.HasWitness() && m_pool.m_opts.require_standard && !IsWitnessStandard(tx, m_view, "bad-witness-", reason, ignore_rejects)) {
1047
+ return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, reason);
1048
  }
1049
 
1050
  int64_t nSigOpsCost = GetTransactionSigOpCost(tx, m_view, STANDARD_SCRIPT_VERIFY_FLAGS);
 
1060
  }
1061
  }
1062
 
1063
+ // Since entries arrive *after* the tip's height, their priority is for the height+1
1064
+ const auto coin_age = GetCoinAge(tx, m_view, block_height_next);
1065
+
1066
+ if (coin_age.inputs_coin_age < m_pool.m_opts.minrelaycoinblocks) {
1067
+ MaybeReject(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-input-immature-coinblocks");
1068
+ }
1069
+
1070
+ // Set entry_sequence to 0 when rejectmsg_zero_mempool_entry_seq is used; this allows txs from a block
1071
  // reorg to be marked earlier than any child txs that were already in the mempool.
1072
+ const uint64_t entry_sequence = args.m_ignore_rejects.count(rejectmsg_zero_mempool_entry_seq) ? 0 : m_pool.GetSequence();
1073
+ int32_t extra_weight = CalculateExtraTxWeight(*ptx, m_view, ::g_weight_per_data_byte);
1074
  if (!m_subpackage.m_changeset) {
1075
  m_subpackage.m_changeset = m_pool.GetChangeSet();
1076
  }
1077
+ 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());
1078
+
1079
+ if (spk_reuse_mode != SRM_ALLOW) {
1080
+ m_subpackage.m_changeset->m_to_add.modify(ws.m_tx_handle, [=](CTxMemPoolEntry& e) {
1081
+ e.mapSPK = mapSPK;
1082
+ });
1083
+ }
1084
 
1085
  // ws.m_modified_fees includes any fee deltas from PrioritiseTransaction
1086
  ws.m_modified_fees = ws.m_tx_handle->GetModifiedFee();
1087
 
1088
  ws.m_vsize = ws.m_tx_handle->GetTxSize();
1089
 
1090
+ // Reduce effective fee by dust threshold for each sub-dust output
1091
+ if (m_pool.m_opts.subdustfeepenalty) {
1092
+ CAmount dust_penalty{0};
1093
+ for (const auto& txout : tx.vout) {
1094
+ const CAmount dust_threshold = GetDustThreshold(txout, m_pool.m_opts.dust_relay_feerate);
1095
+ if (txout.nValue < dust_threshold) {
1096
+ dust_penalty = SaturatingAdd(dust_penalty, dust_threshold - txout.nValue);
1097
+ }