Simulate regtest RPC fee
MODIFY
WalletWasabi.Backend/Controllers/BlockchainController.cs
WalletWasabi.Backend/Controllers/BlockchainController.cs
@@ -76,8 +76,6 @@ namespace WalletWasabi.Backend.Controllers
var feeEstimations = new SortedDictionary<int, FeeEstimationPair>();
foreach (int target in confirmationTargetsInts)
- {
- if (Network != Network.RegTest)
{
// 1. Use the sanity check that under 5 satoshi per bytes should not be displayed.
// 2. Use the RPCResponse.Blocks output to avoid redundant RPC queries.
@@ -93,11 +91,6 @@ namespace WalletWasabi.Backend.Controllers
feeEstimations.Add(target, new FeeEstimationPair() { Conservative = conservativeFee, Economical = economicalFee });
}
- else // RegTest cannot estimate fees, so fill up with dummy data
- {
- feeEstimations.Add(target, new FeeEstimationPair() { Conservative = 6 + target, Economical = 5 + target });
- }
- }
return Ok(feeEstimations);
}
@@ -207,7 +200,7 @@ namespace WalletWasabi.Backend.Controllers
if (!Cache.TryGetValue(cacheKey, out EstimateSmartFeeResponse feeResponse))
{
- feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode);
+ feeResponse = await RpcClient.EstimateSmartFeeAsync(target, mode, simulateIfRegTest: true);
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromSeconds(20));

MODIFY
WalletWasabi.Backend/Global.cs
WalletWasabi.Backend/Global.cs
@@ -122,13 +122,11 @@ namespace WalletWasabi.Backend
Logger.LogInfo<RPCClient>("Bitcoin Core is fully synchronized.");
- if (Config.Network != Network.RegTest) // RegTest cannot estimate fees.
- {
- var estimateSmartFeeResponse = await RpcClient.TryEstimateSmartFeeAsync(2, EstimateSmartFeeMode.Conservative);
+ var estimateSmartFeeResponse = await RpcClient.TryEstimateSmartFeeAsync(2, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
if (estimateSmartFeeResponse == null) throw new NotSupportedException($"Bitcoin Core cannot estimate network fees yet.");
Logger.LogInfo<RPCClient>("Bitcoin Core fee estimation is working.");
- }
- else // Make sure there's at least 101 block, if not generate it
+
+ if (Config.Network == Network.RegTest) // Make sure there's at least 101 block, if not generate it
{
if (blocks < 101)
{

MODIFY
WalletWasabi.Tests/RegTests.cs
WalletWasabi.Tests/RegTests.cs
@@ -1459,8 +1459,8 @@ namespace WalletWasabi.Tests
var status = await response.Content.ReadAsJsonAsync<CcjStatusResponse>();
// Never changes.
Assert.Equal(1, status.Version);
- Assert.True(Money.Zero < status.FeePerInputs);
- Assert.True(Money.Zero < status.FeePerOutputs);
+ Assert.Equal(new Money(0.00000544m, MoneyUnit.BTC), status.FeePerInputs);
+ Assert.Equal(new Money(0.00000264m, MoneyUnit.BTC), status.FeePerOutputs);
Assert.Equal(7, status.MaximumInputCountPerPeer);
// Changes per rounds.
Assert.Equal(denomination, status.Denomination);

MODIFY
WalletWasabi/ChaumianCoinJoin/CcjRound.cs
WalletWasabi/ChaumianCoinJoin/CcjRound.cs
@@ -150,7 +150,7 @@ namespace WalletWasabi.ChaumianCoinJoin
var outputSizeInBytes = Constants.OutputSizeInBytes;
try
{
- var estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative);
+ var estimateSmartFeeResponse = await RpcClient.EstimateSmartFeeAsync(ConfirmationTarget, EstimateSmartFeeMode.Conservative, simulateIfRegTest: true);
if (estimateSmartFeeResponse == null) throw new InvalidOperationException("FeeRate is not yet initialized");
var feeRate = estimateSmartFeeResponse.FeeRate;
Money feePerBytes = (feeRate.FeePerK / 1000);

MODIFY
WalletWasabi/Extensions/RPCClientExtensions.cs
WalletWasabi/Extensions/RPCClientExtensions.cs
@@ -34,6 +34,42 @@ namespace NBitcoin.RPC
Hash = uint256.Parse(resp.Result["hash"].ToString())
};
}
+
+ public static async Task<EstimateSmartFeeResponse> EstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false)
+ {
+ if(simulateIfRegTest && rpc.Network == Network.RegTest)
+ {
+ return SimulateRegTestFeeEstimation(confirmationTarget, estimateMode);
+ }
+
+ return await rpc.EstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ }
+
+ public static async Task<EstimateSmartFeeResponse> TryEstimateSmartFeeAsync(this RPCClient rpc, int confirmationTarget, EstimateSmartFeeMode estimateMode = EstimateSmartFeeMode.Conservative, bool simulateIfRegTest = false)
+ {
+ if (simulateIfRegTest && rpc.Network == Network.RegTest)
+ {
+ return SimulateRegTestFeeEstimation(confirmationTarget, estimateMode);
+ }
+
+ return await rpc.TryEstimateSmartFeeAsync(confirmationTarget, estimateMode);
+ }
+
+ private static EstimateSmartFeeResponse SimulateRegTestFeeEstimation(int confirmationTarget, EstimateSmartFeeMode estimateMode)
+ {
+ int staoshiPerBytes;
+ if (estimateMode == EstimateSmartFeeMode.Conservative)
+ {
+ staoshiPerBytes = 6 + confirmationTarget;
+ }
+ else // Economical
+ {
+ staoshiPerBytes = 5 + confirmationTarget;
+ }
+
+ var resp = new EstimateSmartFeeResponse { Blocks = confirmationTarget, FeeRate = new FeeRate(new Money(staoshiPerBytes * 1000, MoneyUnit.Satoshi)) };
+ return resp;
+ }
}
public class BlockInfo

Simulate regtest RPC fee