Reduce bandwith by not downloading same block
MODIFY
WalletWasabi.Gui/Global.cs
WalletWasabi.Gui/Global.cs
@@ -339,7 +339,7 @@ namespace WalletWasabi.Gui
#region Blocks provider
var blockProvider = new CachedBlockProvider(
- new P2pBlockProvider(Nodes, BitcoinCoreNode, Synchronizer, Config.ServiceConfiguration, Network),
+ new SmartBlockProvider(new P2pBlockProvider(Nodes, BitcoinCoreNode, Synchronizer, Config.ServiceConfiguration, Network)),
new FileSystemBlockRepository(blocksFolderPath, Network));
#endregion Blocks provider

ADD
WalletWasabi.Tests/UnitTests/SmartBlockProviderTests.cs
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using NBitcoin;
+using WalletWasabi.Legal;
+using WalletWasabi.Wallets;
+using Xunit;
+
+namespace WalletWasabi.Tests.UnitTests
+{
+ public class SmartBlockProviderTests
+ {
+ [Fact]
+ public async void TestAsync()
+ {
+ var blocks = new Dictionary<uint256, Block>
+ {
+ [uint256.Zero] = Block.CreateBlock(Network.Main),
+ [uint256.One] = Block.CreateBlock(Network.Main)
+ };
+
+ var source = new MockProvider();
+ source.OnGetBlockAsync = async (hash, cancel) =>
+ {
+ await Task.Delay(TimeSpan.FromSeconds(0.5));
+ var block = Block.CreateBlock(Network.Main);
+ return block;
+ };
+ var blockProvider = new SmartBlockProvider(source);
+
+ var b1 = blockProvider.GetBlockAsync(uint256.Zero, CancellationToken.None);
+ var b2 = blockProvider.GetBlockAsync(uint256.One, CancellationToken.None);
+ var b3 = blockProvider.GetBlockAsync(uint256.Zero, CancellationToken.None);
+
+ await Task.WhenAll(b1, b2, b3);
+ Assert.Equal(await b1, await b3);
+ Assert.NotEqual(await b1, await b2);
+ }
+
+ class MockProvider : IBlockProvider
+ {
+ public Func<uint256, CancellationToken, Task<Block>> OnGetBlockAsync { get; set; }
+
+ public Task<Block> GetBlockAsync(uint256 hash, CancellationToken cancel)
+ {
+ return OnGetBlockAsync(hash, cancel);
+ }
+ }
+ }
+}

ADD
WalletWasabi/Wallets/SmartBlockProvider.cs
+using NBitcoin;
+using NBitcoin.Protocol;
+using NBitcoin.Protocol.Behaviors;
+using Nito.AsyncEx;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using WalletWasabi.BitcoinCore;
+using WalletWasabi.Helpers;
+using WalletWasabi.Logging;
+using WalletWasabi.Models;
+using WalletWasabi.Services;
+
+namespace WalletWasabi.Wallets
+{
+ /// <summary>
+ /// SmartP2pBlockProvider is a blocks provider that can provides
+ /// blocks from multiple requesters.
+ /// </summary>
+ public class SmartBlockProvider : IBlockProvider
+ {
+ public SmartBlockProvider(IBlockProvider provider)
+ {
+ InnerBlockProvider = provider;
+ }
+
+ private AsyncLock Lock { get; } = new AsyncLock();
+
+ private Dictionary<uint256, Task<Block>> Requests = new Dictionary<uint256, Task<Block>>();
+
+ private IBlockProvider InnerBlockProvider { get; }
+
+ public Task<Block> GetBlockAsync(uint256 hash, CancellationToken cancel)
+ {
+ lock (Lock)
+ {
+ if (!Requests.TryGetValue(hash, out var getBlockTask))
+ {
+ getBlockTask = InnerBlockProvider.GetBlockAsync(hash, cancel);
+ Requests.Add(hash, getBlockTask);
+ }
+ return getBlockTask;
+ }
+ }
+ }
+}
\ No newline at end of file

Reduce bandwith by not downloading same block