Prevents fee sniping
MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -746,7 +746,8 @@ namespace WalletWasabi.Services
throw new NotSupportedException(feeStrategy.Type.ToString());
}
},
- allowedInputs);
+ allowedInputs,
+ SelectLockTimeForTransaction);
}
public void RenameLabel(SmartCoin coin, SmartLabel newLabel)
@@ -759,6 +760,23 @@ namespace WalletWasabi.Services
}
}
+ private LockTime SelectLockTimeForTransaction()
+ {
+ try
+ {
+ // discourage "fee sniping".
+ var tipHeight = Synchronizer.BitcoinStore.HashChain.TipHeight;
+ var rand = new Random();
+ // sometimes pick locktime a bit further back, to help privacy.
+ var randomize = rand.Next(0, 10) == 0;
+ return tipHeight - (randomize ? rand.Next(0, 10) : 0);
+ }
+ catch(Exception)
+ {
+ return LockTime.Zero;
+ }
+ }
+
private static long SendCount = 0;
private async Task BroadcastTransactionToNetworkNodeAsync(SmartTransaction transaction, Node node)

MODIFY
WalletWasabi/Transactions/TransactionFactory.cs
WalletWasabi/Transactions/TransactionFactory.cs
@@ -39,7 +39,7 @@ namespace WalletWasabi.Transactions
PaymentIntent payments,
FeeRate feeRate,
IEnumerable<TxoRef> allowedInputs = null)
- => BuildTransaction(payments, () => feeRate, allowedInputs);
+ => BuildTransaction(payments, () => feeRate, allowedInputs, ()=> LockTime.Zero);
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ArgumentNullException"></exception>
@@ -47,9 +47,11 @@ namespace WalletWasabi.Transactions
public BuildTransactionResult BuildTransaction(
PaymentIntent payments,
Func<FeeRate> feeRateFetcher,
- IEnumerable<TxoRef> allowedInputs = null)
+ IEnumerable<TxoRef> allowedInputs = null,
+ Func<LockTime> lockTimeSelector = null)
{
payments = Guard.NotNull(nameof(payments), payments);
+ lockTimeSelector ??= ()=> LockTime.Zero;
long totalAmount = payments.TotalAmount.Satoshi;
if (totalAmount < 0 || totalAmount > Constants.MaximumNumberOfSatoshis)
@@ -217,6 +219,7 @@ namespace WalletWasabi.Transactions
{
IEnumerable<ExtKey> signingKeys = KeyManager.GetSecrets(Password, spentCoins.Select(x => x.ScriptPubKey).ToArray());
builder = builder.AddKeys(signingKeys.ToArray());
+ builder.SetLockTime(lockTimeSelector());
builder.SignPSBT(psbt);
psbt.Finalize();
tx = psbt.ExtractTransaction();

Prevents fee sniping