Make `SmartBlockProvider` to implement `IBlockProvider`
MODIFY
WalletWasabi.Tests/IntegrationTests/P2pTests.cs
WalletWasabi.Tests/IntegrationTests/P2pTests.cs
@@ -35,6 +35,7 @@ public class P2pTests
await RuntimeParams.LoadAsync();
var network = Network.GetNetwork(networkString);
var blocksToDownload = new List<uint256>();
+
if (network == Network.Main)
{
blocksToDownload.Add(new uint256("00000000000000000037c2de35bd85f3e57f14ddd741ce6cee5b28e51473d5d0"));
@@ -65,6 +66,7 @@ public class P2pTests
var addressManagerFilePath = Path.Combine(addressManagerFolderPath, $"AddressManager{network}.dat");
var connectionParameters = new NodeConnectionParameters();
AddressManager addressManager;
+
try
{
addressManager = await NBitcoinHelpers.LoadAddressManagerFromPeerFileAsync(addressManagerFilePath);
@@ -100,14 +102,15 @@ public class P2pTests
var feeProvider = new HybridFeeProvider(synchronizer, null);
ServiceConfiguration serviceConfig = new(new IPEndPoint(IPAddress.Loopback, network.DefaultPort), Money.Coins(Constants.DefaultDustThreshold));
- var cache = new MemoryCache(new MemoryCacheOptions
+ using MemoryCache cache = new(new MemoryCacheOptions
{
SizeLimit = 1_000,
ExpirationScanFrequency = TimeSpan.FromSeconds(30)
});
- var blockProvider = new SmartBlockProvider(
- bitcoinStore.BlockRepository,
+ IRepository<uint256, Block> blockRepository = bitcoinStore.BlockRepository;
+ IBlockProvider blockProvider = new SmartBlockProvider(
+ blockRepository,
new LocalBlockProvider(null, httpClientFactory, serviceConfig, network),
new P2pBlockProvider(nodes, httpClientFactory, serviceConfig, network),
cache);
@@ -161,8 +164,9 @@ public class P2pTests
// So next test will download the block.
foreach (var hash in blocksToDownload)
{
- await blockProvider.RemoveAsync(hash, CancellationToken.None);
+ await blockRepository.RemoveAsync(hash, CancellationToken.None);
}
+
if (wallet is { })
{
await wallet.StopAsync(CancellationToken.None);

MODIFY
WalletWasabi.Tests/UnitTests/TestBlockProvider.cs
WalletWasabi.Tests/UnitTests/TestBlockProvider.cs
@@ -17,6 +17,6 @@ public class TestBlockProvider : IBlockProvider
public Task<Block?> TryGetBlockAsync(uint256 hash, CancellationToken cancel)
{
- return Task.FromResult(Blocks[hash])!;
+ return Task.FromResult<Block?>(Blocks[hash]);
}
}

MODIFY
WalletWasabi/Wallets/IBlockProvider.cs
WalletWasabi/Wallets/IBlockProvider.cs
@@ -9,5 +9,12 @@ namespace WalletWasabi.Wallets;
/// </summary>
public interface IBlockProvider
{
- Task<Block?> TryGetBlockAsync(uint256 hash, CancellationToken cancel);
+ Task<Block?> TryGetBlockAsync(uint256 blockHash, CancellationToken cancellationToken);
+
+ /// <exception cref="InvalidOperationException">If the block cannot be obtained.</exception>
+ async Task<Block> GetBlockAsync(uint256 blockHash, CancellationToken cancellationToken)
+ {
+ return await TryGetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false)
+ ?? throw new InvalidOperationException($"Failed to get block {blockHash}.");
+ }
}

MODIFY
WalletWasabi/Wallets/SmartBlockProvider.cs
WalletWasabi/Wallets/SmartBlockProvider.cs
@@ -9,7 +9,7 @@ namespace WalletWasabi.Wallets;
/// <summary>
/// Block provider that can provide blocks from multiple sources.
/// </summary>
-public class SmartBlockProvider
+public class SmartBlockProvider : IBlockProvider
{
private static MemoryCacheEntryOptions CacheOptions = new()
{
@@ -31,10 +31,9 @@ public class SmartBlockProvider
private IRepository<uint256, Block> BlockRepository { get; }
/// <summary>
- /// Gets the block from file-system storage or from other block providers.
+ /// Tries to get the block from file-system storage or from other block providers.
/// </summary>
- /// <exception cref="InvalidOperationException">If the block cannot be obtained.</exception>
- public async Task<Block> GetBlockAsync(uint256 blockHash, CancellationToken cancellationToken)
+ public async Task<Block?> TryGetBlockAsync(uint256 blockHash, CancellationToken cancellationToken)
{
// Try get the block from the file-system storage.
Block? result = await BlockRepository.TryGetAsync(blockHash, cancellationToken).ConfigureAwait(false);
@@ -46,7 +45,7 @@ public class SmartBlockProvider
// Use the in-memory cache to prevent multiple callers from getting the same block in parallel.
// The cache makes sure that either in-memory or file-system cache is hit by other callers once we get a block.
- string cacheKey = $"{nameof(GetBlockAsync)}:{blockHash}";
+ string cacheKey = $"{nameof(TryGetBlockAsync)}:{blockHash}";
result = await Cache.GetCachedResponseAsync(
cacheKey,
@@ -54,13 +53,11 @@ public class SmartBlockProvider
options: CacheOptions,
cancellationToken).ConfigureAwait(false);
- if (result is null)
+ if (result is not null)
{
- throw new InvalidOperationException($"Block {blockHash} could not be downloaded from any source.");
- }
-
// Store the block to the file-system.
await BlockRepository.SaveAsync(result, cancellationToken).ConfigureAwait(false);
+ }
return result;
}

MODIFY
WalletWasabi/Wallets/Wallet.cs
WalletWasabi/Wallets/Wallet.cs
@@ -128,7 +128,7 @@ public class Wallet : BackgroundService, IWallet
public HybridFeeProvider FeeProvider { get; private set; }
public FilterModel LastProcessedFilter { get; private set; }
- public SmartBlockProvider BlockProvider { get; private set; }
+ public IBlockProvider BlockProvider { get; private set; }
private AsyncLock HandleFiltersLock { get; }
public bool IsLoggedIn { get; private set; }
@@ -166,7 +166,7 @@ public class Wallet : BackgroundService, IWallet
WasabiSynchronizer syncer,
ServiceConfiguration serviceConfiguration,
HybridFeeProvider feeProvider,
- SmartBlockProvider blockProvider)
+ IBlockProvider blockProvider)
{
if (State > WalletState.WaitingForInit)
{
@@ -366,7 +366,11 @@ public class Wallet : BackgroundService, IWallet
using (await HandleFiltersLock.LockAsync().ConfigureAwait(false))
{
uint256 invalidBlockHash = invalidFilter.Header.BlockHash;
- await BlockProvider.RemoveAsync(invalidBlockHash, CancellationToken.None).ConfigureAwait(false);
+
+ if (BlockProvider is SmartBlockProvider smartBlockProvider)
+ {
+ await smartBlockProvider.RemoveAsync(invalidBlockHash, CancellationToken.None).ConfigureAwait(false);
+ }
KeyManager.SetMaxBestHeight(new Height(invalidFilter.Header.Height - 1));
TransactionProcessor.UndoBlock((int)invalidFilter.Header.Height);
@@ -516,7 +520,7 @@ public class Wallet : BackgroundService, IWallet
State = WalletState.WaitingForInit;
}
- public static Wallet CreateAndRegisterServices(Network network, BitcoinStore bitcoinStore, KeyManager keyManager, WasabiSynchronizer synchronizer, string dataDir, ServiceConfiguration serviceConfiguration, HybridFeeProvider feeProvider, SmartBlockProvider blockProvider)
+ public static Wallet CreateAndRegisterServices(Network network, BitcoinStore bitcoinStore, KeyManager keyManager, WasabiSynchronizer synchronizer, string dataDir, ServiceConfiguration serviceConfiguration, HybridFeeProvider feeProvider, IBlockProvider blockProvider)
{
var wallet = new Wallet(dataDir, network, keyManager);
wallet.RegisterServices(bitcoinStore, synchronizer, serviceConfiguration, feeProvider, blockProvider);

MODIFY
WalletWasabi/Wallets/WalletManager.cs
WalletWasabi/Wallets/WalletManager.cs
@@ -67,7 +67,7 @@ public class WalletManager : IWalletProvider
private HybridFeeProvider FeeProvider { get; set; }
public Network Network { get; }
public WalletDirectories WalletDirectories { get; }
- private SmartBlockProvider BlockProvider { get; set; }
+ private IBlockProvider BlockProvider { get; set; }
public string WorkDir { get; }
private void RefreshWalletList()
@@ -375,7 +375,7 @@ public class WalletManager : IWalletProvider
}
}
- public void RegisterServices(BitcoinStore bitcoinStore, WasabiSynchronizer synchronizer, ServiceConfiguration serviceConfiguration, HybridFeeProvider feeProvider, SmartBlockProvider blockProvider)
+ public void RegisterServices(BitcoinStore bitcoinStore, WasabiSynchronizer synchronizer, ServiceConfiguration serviceConfiguration, HybridFeeProvider feeProvider, IBlockProvider blockProvider)
{
BitcoinStore = bitcoinStore;
Synchronizer = synchronizer;

Make `SmartBlockProvider` to implement `IBlockProvider`