Hack around one of the Core abnormal behavior in this issue:
MODIFY
WalletWasabi.Backend/Controllers/BlockchainController.cs
WalletWasabi.Backend/Controllers/BlockchainController.cs
@@ -205,7 +205,7 @@ namespace WalletWasabi.Backend.Controllers
if (!Cache.TryGetValue(cacheKey, out EstimateSmartFeeResponse feeResponse))
{
- feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true);
+ feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true, tryOtherFeeRates: true);
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromSeconds(20));

MODIFY
WalletWasabi.Backend/Global.cs
WalletWasabi.Backend/Global.cs
@@ -112,7 +112,7 @@ namespace WalletWasabi.Backend
Logger.LogInfo<RPCClient>("Bitcoin Core is fully synchronized.");
- var estimateSmartFeeResponse = await RpcClient.TryEstimateSmartFeeAsync(2, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
+ var estimateSmartFeeResponse = await RpcClient.TryEstimateSmartFeeAsync(2, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true, tryOtherFeeRates: true);
if (estimateSmartFeeResponse is null) throw new NotSupportedException("Bitcoin Core cannot estimate network fees yet.");
Logger.LogInfo<RPCClient>("Bitcoin Core fee estimation is working.");

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -2414,7 +2414,7 @@ namespace WalletWasabi.Tests
}
FeeRate feeRateTx = finalCoinjoin.GetFeeRate(coins.ToArray());
- var esr = await rpc.EstimateSmartFeeAsync((int)roundConfig.ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
+ var esr = await rpc.EstimateSmartFeeAsync((int)roundConfig.ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true, tryOtherFeeRates: true);
FeeRate feeRateReal = esr.FeeRate;
Assert.True(feeRateReal.FeePerK - (feeRateReal.FeePerK / 2) < feeRateTx.FeePerK); // Max 50% mistake.

MODIFY
WalletWasabi/Extensions/RPCClientExtensions.cs
WalletWasabi/Extensions/RPCClientExtensions.cs
+using System;
using System.Threading.Tasks;
+using WalletWasabi.Logging;
using WalletWasabi.Models;
namespace NBitcoin.RPC
@@ -28,23 +30,68 @@ namespace NBitcoin.RPC
return (int.Parse(resp.Result["height"].ToString()), uint256.Parse(resp.Result["hash"].ToString()));
}
- public static async Task<EstimateSmartFeeResponse> EstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false)
+ public static async Task<EstimateSmartFeeResponse> EstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tryOtherFeeRates = true)
{
if (simulateIfRegTest && rpc.Network == Network.RegTest)
{
return SimulateRegTestFeeEstimation(confirmationTarget, estimateMode);
}
+ if (tryOtherFeeRates)
+ {
+ try
+ {
+ return await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ }
+ catch
+ {
+ // Hopefully Bitcoin Core brainfart: https://github.com/bitcoin/bitcoin/issues/14431
+ for (int i = 2; i <= 1008; i++)
+ {
+ try
+ {
+ return await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ }
+ catch
+ {
+ }
+ }
+ }
+ // Let's try one more time, whatever.
+ }
+
return await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode);
}
- public static async Task<EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false)
+ public static async Task<EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false, bool tryOtherFeeRates = false)
{
if (simulateIfRegTest && rpc.Network == Network.RegTest)
{
return SimulateRegTestFeeEstimation(confirmationTarget, estimateMode);
}
+ if (tryOtherFeeRates)
+ {
+ EstimateSmartFeeResponse response = await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ if (response != null)
+ {
+ return response;
+ }
+ else
+ {
+ // Hopefully Bitcoin Core brainfart: https://github.com/bitcoin/bitcoin/issues/14431
+ for (int i = 2; i <= 1008; i++)
+ {
+ response = await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ if (response != null)
+ {
+ return response;
+ }
+ }
+ }
+ // Let's try one more time, whatever.
+ }
+
return await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode);
}

MODIFY
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
WalletWasabi/Models/ChaumianCoinJoin/CcjRound.cs
@@ -187,7 +187,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
var outputSizeInBytes = Constants.OutputSizeInBytes;
try
{
- var estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
+ var estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true, tryOtherFeeRates: true);
if (estimateSmartFeeResponse is null) throw new InvalidOperationException("FeeRate is not yet initialized");
var feeRate = estimateSmartFeeResponse.FeeRate;
Money feePerBytes = (feeRate.FeePerK / 1000);
@@ -321,7 +321,7 @@ namespace WalletWasabi.Models.ChaumianCoinJoin
FeeRate currentFeeRate = fee is null ? null : new FeeRate(fee, estimatedFinalTxSize);
// 8.2. Get the most optimal FeeRate.
- EstimateSmartFeeResponse estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
+ EstimateSmartFeeResponse estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true, tryOtherFeeRates: true);
if (estimateSmartFeeResponse is null) throw new InvalidOperationException("FeeRate is not yet initialized");
FeeRate optimalFeeRate = estimateSmartFeeResponse.FeeRate;

Hack around one of the Core abnormal behavior in this issue: https://github.com/bitcoin/bitcoin/issues/14431