@@ -582,12 +582,13 @@ static bool IsCurrentForAntiFeeSniping(interfaces::Chain& chain, const uint256&
582
582
}
583
583
584
584
/* *
585
- * Return a height-based locktime for new transactions (uses the height of the
585
+ * Set a height-based locktime for new transactions (uses the height of the
586
586
* current chain tip unless we are not synced with the current chain
587
587
*/
588
- static uint32_t GetLocktimeForNewTransaction ( interfaces::Chain& chain, const uint256& block_hash, int block_height)
588
+ static void DiscourageFeeSniping (CMutableTransaction& tx, interfaces::Chain& chain, const uint256& block_hash, int block_height)
589
589
{
590
- uint32_t locktime;
590
+ // All inputs must be added by now
591
+ assert (!tx.vin .empty ());
591
592
// Discourage fee sniping.
592
593
//
593
594
// For a large miner the value of the transactions in the best block and
@@ -609,22 +610,34 @@ static uint32_t GetLocktimeForNewTransaction(interfaces::Chain& chain, const uin
609
610
// now we ensure code won't be written that makes assumptions about
610
611
// nLockTime that preclude a fix later.
611
612
if (IsCurrentForAntiFeeSniping (chain, block_hash)) {
612
- locktime = block_height;
613
+ tx. nLockTime = block_height;
613
614
614
615
// Secondly occasionally randomly pick a nLockTime even further back, so
615
616
// that transactions that are delayed after signing for whatever reason,
616
617
// e.g. high-latency mix networks and some CoinJoin implementations, have
617
618
// better privacy.
618
- if (GetRandInt (10 ) == 0 )
619
- locktime = std::max (0 , (int )locktime - GetRandInt (100 ));
619
+ if (GetRandInt (10 ) == 0 ) {
620
+ tx.nLockTime = std::max (0 , int (tx.nLockTime ) - GetRandInt (100 ));
621
+ }
620
622
} else {
621
623
// If our chain is lagging behind, we can't discourage fee sniping nor help
622
624
// the privacy of high-latency transactions. To avoid leaking a potentially
623
625
// unique "nLockTime fingerprint", set nLockTime to a constant.
624
- locktime = 0 ;
626
+ tx.nLockTime = 0 ;
627
+ }
628
+ // Sanity check all values
629
+ assert (tx.nLockTime < LOCKTIME_THRESHOLD); // Type must be block height
630
+ assert (tx.nLockTime <= uint64_t (block_height));
631
+ for (const auto & in : tx.vin ) {
632
+ // Can not be FINAL for locktime to work
633
+ assert (in.nSequence != CTxIn::SEQUENCE_FINAL);
634
+ // May be MAX NONFINAL to disable both BIP68 and BIP125
635
+ if (in.nSequence == CTxIn::MAX_SEQUENCE_NONFINAL) continue ;
636
+ // May be MAX BIP125 to disable BIP68 and enable BIP125
637
+ if (in.nSequence == MAX_BIP125_RBF_SEQUENCE) continue ;
638
+ // The wallet does not support any other sequence-use right now.
639
+ assert (false );
625
640
}
626
- assert (locktime < LOCKTIME_THRESHOLD);
627
- return locktime;
628
641
}
629
642
630
643
static bool CreateTransactionInternal (
@@ -641,7 +654,6 @@ static bool CreateTransactionInternal(
641
654
AssertLockHeld (wallet.cs_wallet );
642
655
643
656
CMutableTransaction txNew; // The resulting transaction that we make
644
- txNew.nLockTime = GetLocktimeForNewTransaction (wallet.chain (), wallet.GetLastBlockHash (), wallet.GetLastBlockHeight ());
645
657
646
658
CoinSelectionParams coin_selection_params; // Parameters for coin selection, init with dummy
647
659
coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends ;
@@ -787,8 +799,8 @@ static bool CreateTransactionInternal(
787
799
// Shuffle selected coins and fill in final vin
788
800
std::vector<CInputCoin> selected_coins = result->GetShuffledInputVector ();
789
801
790
- // Note how the sequence number is set to non-maxint so that
791
- // the nLockTime set above actually works.
802
+ // The sequence number is set to non-maxint so that DiscourageFeeSniping
803
+ // works.
792
804
//
793
805
// BIP125 defines opt-in RBF as any nSequence < maxint-1, so
794
806
// we use the highest possible value in that range (maxint-2)
@@ -799,6 +811,7 @@ static bool CreateTransactionInternal(
799
811
for (const auto & coin : selected_coins) {
800
812
txNew.vin .push_back (CTxIn (coin.outpoint , CScript (), nSequence));
801
813
}
814
+ DiscourageFeeSniping (txNew, wallet.chain (), wallet.GetLastBlockHash (), wallet.GetLastBlockHeight ());
802
815
803
816
// Calculate the transaction fee
804
817
TxSize tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), &wallet, &coin_control);
0 commit comments