diff options
-rw-r--r-- | src/wallet/coincontrol.cpp | 16 | ||||
-rw-r--r-- | src/wallet/coincontrol.h | 9 | ||||
-rw-r--r-- | src/wallet/spend.cpp | 15 |
3 files changed, 37 insertions, 3 deletions
diff --git a/src/wallet/coincontrol.cpp b/src/wallet/coincontrol.cpp index 00852b5f85..f13b7073be 100644 --- a/src/wallet/coincontrol.cpp +++ b/src/wallet/coincontrol.cpp @@ -72,6 +72,12 @@ std::optional<int64_t> CCoinControl::GetInputWeight(const COutPoint& outpoint) c return it != m_selected.end() ? it->second.GetInputWeight() : std::nullopt; } +std::optional<uint32_t> CCoinControl::GetSequence(const COutPoint& outpoint) const +{ + const auto it = m_selected.find(outpoint); + return it != m_selected.end() ? it->second.GetSequence() : std::nullopt; +} + void PreselectedInput::SetTxOut(const CTxOut& txout) { m_txout = txout; @@ -97,4 +103,14 @@ std::optional<int64_t> PreselectedInput::GetInputWeight() const { return m_weight; } + +void PreselectedInput::SetSequence(uint32_t sequence) +{ + m_sequence = sequence; +} + +std::optional<uint32_t> PreselectedInput::GetSequence() const +{ + return m_sequence; +} } // namespace wallet diff --git a/src/wallet/coincontrol.h b/src/wallet/coincontrol.h index e7a16e37df..32595955f0 100644 --- a/src/wallet/coincontrol.h +++ b/src/wallet/coincontrol.h @@ -31,6 +31,8 @@ private: std::optional<CTxOut> m_txout; //! The input weight for spending this input std::optional<int64_t> m_weight; + //! The sequence number for this input + std::optional<uint32_t> m_sequence; public: /** @@ -47,6 +49,11 @@ public: void SetInputWeight(int64_t weight); /** Retrieve the input weight for this input. */ std::optional<int64_t> GetInputWeight() const; + + /** Set the sequence for this input. */ + void SetSequence(uint32_t sequence); + /** Retrieve the sequence for this input. */ + std::optional<uint32_t> GetSequence() const; }; /** Coin Control Features. */ @@ -128,6 +135,8 @@ public: * Returns the input weight. */ std::optional<int64_t> GetInputWeight(const COutPoint& outpoint) const; + /** Retrieve the sequence for an input */ + std::optional<uint32_t> GetSequence(const COutPoint& outpoint) const; private: //! Selected inputs (inputs that will be used, regardless of whether they're optimal or not) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index c3fd695eb9..7ec2775fb1 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -1150,11 +1150,19 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal( // to avoid conflicting with other possible uses of nSequence, // and in the spirit of "smallest possible change from prior // behavior." - const uint32_t nSequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL}; + bool use_anti_fee_sniping = true; + const uint32_t default_sequence{coin_control.m_signal_bip125_rbf.value_or(wallet.m_signal_rbf) ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL}; for (const auto& coin : selected_coins) { - txNew.vin.emplace_back(coin->outpoint, CScript(), nSequence); + std::optional<uint32_t> sequence = coin_control.GetSequence(coin->outpoint); + if (sequence) { + // If an input has a preset sequence, we can't do anti-fee-sniping + use_anti_fee_sniping = false; + } + txNew.vin.emplace_back(coin->outpoint, CScript(), sequence.value_or(default_sequence)); + } + if (use_anti_fee_sniping) { + DiscourageFeeSniping(txNew, rng_fast, wallet.chain(), wallet.GetLastBlockHash(), wallet.GetLastBlockHeight()); } - DiscourageFeeSniping(txNew, rng_fast, wallet.chain(), wallet.GetLastBlockHash(), wallet.GetLastBlockHeight()); // Calculate the transaction fee TxSize tx_sizes = CalculateMaximumSignedTxSize(CTransaction(txNew), &wallet, &coin_control); @@ -1357,6 +1365,7 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet, // The input was not in the wallet, but is in the UTXO set, so select as external preset_txin.SetTxOut(coins[outPoint].out); } + preset_txin.SetSequence(txin.nSequence); } auto res = CreateTransaction(wallet, vecSend, nChangePosInOut, coinControl, false); |