Adjust NodeTimeout
MODIFY
WalletWasabi/Helpers/RuntimeParams.cs
WalletWasabi/Helpers/RuntimeParams.cs
@@ -21,7 +21,7 @@ namespace WalletWasabi.Helpers
get
{
if (_instance is null)
- _instance = LoadAsync().GetAwaiter().GetResult();
+ throw new InvalidOperationException("Not loaded! Use LoadAsync() first!");
return _instance;
}
}
@@ -61,7 +61,7 @@ namespace WalletWasabi.Helpers
}
}
- public static async Task<RuntimeParams> LoadAsync()
+ public static async Task LoadAsync()
{
try
{
@@ -72,13 +72,14 @@ namespace WalletWasabi.Helpers
}
string jsonString = await File.ReadAllTextAsync(FilePath, Encoding.UTF8);
- return JsonConvert.DeserializeObject<RuntimeParams>(jsonString);
+ _instance = JsonConvert.DeserializeObject<RuntimeParams>(jsonString);
+ return;
}
catch (Exception ex)
{
Logger.LogInfo<RuntimeParams>($"Could not load RuntimeParams: {ex}.");
}
- return new RuntimeParams();
+ _instance = new RuntimeParams();
}
#endregion

MODIFY
WalletWasabi/Services/WalletService.cs
WalletWasabi/Services/WalletService.cs
@@ -42,6 +42,8 @@ namespace WalletWasabi.Services
private AsyncLock BlockDownloadLock { get; }
private AsyncLock BlockFolderLock { get; }
+ private int _nodeTimeouts;
+
// These are static functions, so we will make sure when blocks are downloading with multiple wallet services, they don't conflict.
private static int _concurrentBlockDownload = 0;
@@ -255,6 +257,8 @@ namespace WalletWasabi.Services
throw new NotSupportedException($"{nameof(Synchronizer)} is not running.");
}
+ await RuntimeParams.LoadAsync();
+
using (HandleFiltersLock.Lock())
using (WalletBlocksLock.Lock())
{
@@ -769,7 +773,7 @@ namespace WalletWasabi.Services
{
ConcurrentBlockDownloadNumberChanged?.Invoke(this, Interlocked.Increment(ref _concurrentBlockDownload));
- using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(64))) // 1/2 ADSL 512 kbit/s 00:00:32
+ using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(RuntimeParams.Instance.NetworkNodeTimeout))) // 1/2 ADSL 512 kbit/s 00:00:32
{
block = node.GetBlocks(new uint256[] { hash }, cts.Token)?.Single();
}
@@ -793,12 +797,17 @@ namespace WalletWasabi.Services
Logger.LogInfo<WalletService>($"Disconnected node: {node.RemoteSocketAddress}. Block downloaded: {block.GetHash()}");
node.DisconnectAsync("Thank you!");
}
+
+ await NodeTimeoutsAsync(false);
}
catch (Exception ex) when (ex is OperationCanceledException
|| ex is TaskCanceledException
|| ex is TimeoutException)
{
Logger.LogInfo<WalletService>($"Disconnected node: {node.RemoteSocketAddress}, because block download took too long.");
+
+ await NodeTimeoutsAsync(true);
+
node.DisconnectAsync("Block download took too long.");
continue;
}
@@ -1325,6 +1334,50 @@ namespace WalletWasabi.Services
}
}
+ // Current timeout used when downloading a block from the remote node. It is defined in seconds.
+ private async Task NodeTimeoutsAsync(bool increaseDecrease)
+ {
+ if (increaseDecrease)
+ {
+ _nodeTimeouts++;
+ }
+ else
+ {
+ _nodeTimeouts--;
+ }
+
+ var timeout = RuntimeParams.Instance.NetworkNodeTimeout;
+
+ // If it times out 2 times in a row then increase the timeout.
+ if (_nodeTimeouts >= 2)
+ {
+ _nodeTimeouts = 0;
+ timeout *= 2;
+ }
+ else if (_nodeTimeouts <= -3) // If it doesn't time out 3 times in a row, lower the timeout.
+ {
+ _nodeTimeouts = 0;
+ timeout = (int)Math.Round(timeout * 0.7);
+ }
+
+ // Sanity check
+ if (timeout < 32)
+ {
+ timeout = 32;
+ }
+ else if (timeout > 600)
+ {
+ timeout = 600;
+ }
+
+ if (timeout == RuntimeParams.Instance.NetworkNodeTimeout) return;
+
+ RuntimeParams.Instance.NetworkNodeTimeout = timeout;
+ await RuntimeParams.Instance.SaveAsync();
+
+ Logger.LogInfo<WalletService>($"Current timeout value used on block download is: {timeout} seconds.");
+ }
+
#region IDisposable Support
private volatile bool _disposedValue = false; // To detect redundant calls

Adjust NodeTimeout