Extract RpcBlockProvider to own class
MODIFY
WalletWasabi.Fluent/Global.cs
WalletWasabi.Fluent/Global.cs
@@ -190,7 +190,8 @@ public class Global
var blockProvider = new SmartBlockProvider(
BitcoinStore.BlockRepository,
- new LocalBlockProvider(Network, Config.ServiceConfiguration, BitcoinCoreNode, HttpClientFactory),
+ new RpcBlockProvider(BitcoinCoreNode),
+ new LocalBlockProvider(Network, Config.ServiceConfiguration, HttpClientFactory),
new P2PBlockProvider(Network, HostedServices.Get<P2pNetwork>().Nodes, HttpClientFactory),
Cache);

MODIFY
WalletWasabi.Tests/IntegrationTests/P2pTests.cs
WalletWasabi.Tests/IntegrationTests/P2pTests.cs
@@ -111,7 +111,9 @@ public class P2pTests
IRepository<uint256, Block> blockRepository = bitcoinStore.BlockRepository;
IBlockProvider blockProvider = new SmartBlockProvider(
blockRepository,
- new LocalBlockProvider(network, serviceConfig, null, httpClientFactory),
+
+ new RpcBlockProvider(null),
+ new LocalBlockProvider(network, serviceConfig, httpClientFactory),
new P2PBlockProvider(network, nodes, httpClientFactory),
cache);

MODIFY
WalletWasabi.Tests/RegressionTests/BuildTests.cs
WalletWasabi.Tests/RegressionTests/BuildTests.cs
@@ -66,7 +66,8 @@ public class BuildTests
var blockProvider = new SmartBlockProvider(
bitcoinStore.BlockRepository,
- localBlockProvider: new LocalBlockProvider(network, serviceConfiguration, coreNode: null, httpClientFactory: httpClientFactory),
+ rpcBlockProvider: new RpcBlockProvider(null),
+ localBlockProvider: new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
p2PBlockProvider: new P2PBlockProvider(network, nodes, httpClientFactory),
cache);
@@ -223,8 +224,9 @@ public class BuildTests
var blockProvider = new SmartBlockProvider(
bitcoinStore.BlockRepository,
- localBlockProvider: new LocalBlockProvider(network, serviceConfiguration, coreNode: null, httpClientFactory: httpClientFactory),
- p2PBlockProvider: new P2PBlockProvider(network, nodes, httpClientFactory),
+ new RpcBlockProvider(null),
+ new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
+ new P2PBlockProvider(network, nodes, httpClientFactory),
cache);
WalletManager walletManager = new(network, workDir, new WalletDirectories(network, workDir));

MODIFY
WalletWasabi.Tests/RegressionTests/SendTests.cs
WalletWasabi.Tests/RegressionTests/SendTests.cs
@@ -64,7 +64,8 @@ public class SendTests
var blockProvider = new SmartBlockProvider(
bitcoinStore.BlockRepository,
- new LocalBlockProvider(network, serviceConfiguration, null, httpClientFactory),
+ rpcBlockProvider: new RpcBlockProvider(null),
+ localBlockProvider: new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
new P2PBlockProvider(network, nodes, httpClientFactory),
cache);
@@ -546,7 +547,8 @@ public class SendTests
var blockProvider = new SmartBlockProvider(
bitcoinStore.BlockRepository,
- new LocalBlockProvider(network, serviceConfiguration, null, httpClientFactory),
+ rpcBlockProvider: new RpcBlockProvider(null),
+ localBlockProvider: new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
new P2PBlockProvider(network, nodes, httpClientFactory),
cache);
@@ -724,7 +726,8 @@ public class SendTests
var blockProvider = new SmartBlockProvider(
bitcoinStore.BlockRepository,
- new LocalBlockProvider(network, serviceConfiguration, null, httpClientFactory),
+ new RpcBlockProvider(null),
+ new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
new P2PBlockProvider(network, nodes, httpClientFactory),
cache);

MODIFY
WalletWasabi.Tests/RegressionTests/WalletTests.cs
WalletWasabi.Tests/RegressionTests/WalletTests.cs
@@ -256,9 +256,10 @@ public class WalletTests
ExpirationScanFrequency = TimeSpan.FromSeconds(30)
});
- SmartBlockProvider blockProvider = new(
- blockRepository,
- new LocalBlockProvider(network, serviceConfiguration, null, httpClientFactory),
+ SmartBlockProvider blockProvider = new SmartBlockProvider(
+ bitcoinStore.BlockRepository,
+ new RpcBlockProvider(null),
+ new LocalBlockProvider(network, serviceConfiguration, httpClientFactory: httpClientFactory),
new P2PBlockProvider(network, nodes, httpClientFactory),
cache);

MODIFY
WalletWasabi.Tests/UnitTests/SmartBlockProviderTests.cs
WalletWasabi.Tests/UnitTests/SmartBlockProviderTests.cs
@@ -26,6 +26,11 @@ public class SmartBlockProviderTests
_ = mockBlockRepository.Setup(c => c.SaveAsync(It.IsAny<Block>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
+ // Rpc block provider returns nothing. Simulate that it's not enabled.
+ Mock<IBlockProvider> mockRpcBlockProvider = new(MockBehavior.Strict);
+ _ = mockRpcBlockProvider.Setup(c => c.TryGetBlockAsync(It.IsAny<uint256>(), It.IsAny<CancellationToken>()))
+ .ReturnsAsync((Block?)null);
+
// Local block provider returns nothing. Simulate that it's not enabled.
Mock<IBlockProvider> mockLocalBlockProvider = new(MockBehavior.Strict);
_ = mockLocalBlockProvider.Setup(c => c.TryGetBlockAsync(It.IsAny<uint256>(), It.IsAny<CancellationToken>()))
@@ -43,6 +48,7 @@ public class SmartBlockProviderTests
using MemoryCache cache = new(new MemoryCacheOptions());
IBlockProvider smartBlockProvider = new SmartBlockProvider(
mockBlockRepository.Object,
+ rpcBlockProvider: mockRpcBlockProvider.Object,
localBlockProvider: mockLocalBlockProvider.Object,
p2PBlockProvider: p2PBlockProvider,
cache);

MODIFY
WalletWasabi/Wallets/LocalBlockProvider.cs
WalletWasabi/Wallets/LocalBlockProvider.cs
@@ -16,53 +16,19 @@ namespace WalletWasabi.Wallets;
public class LocalBlockProvider : IBlockProvider
{
- public LocalBlockProvider(Network network, ServiceConfiguration serviceConfiguration, CoreNode? coreNode, HttpClientFactory httpClientFactory)
+ public LocalBlockProvider(Network network, ServiceConfiguration serviceConfiguration, HttpClientFactory httpClientFactory)
{
Network = network;
ServiceConfiguration = serviceConfiguration;
- CoreNode = coreNode;
HttpClientFactory = httpClientFactory;
}
private Network Network { get; }
- private CoreNode? CoreNode { get; }
private Node? LocalBitcoinCoreNode { get; set; }
private ServiceConfiguration ServiceConfiguration { get; }
private HttpClientFactory HttpClientFactory { get; }
public async Task<Block?> TryGetBlockAsync(uint256 hash, CancellationToken cancellationToken)
- {
- Block? rpcResult = null;
-
- if (CoreNode?.RpcClient is not null)
- {
- try
- {
- rpcResult = await GetBlockFromRpcAsync(hash, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- Logger.LogDebug(ex);
- }
- }
-
- return rpcResult ?? await GetBlockFromLocalNodeAsync(hash, cancellationToken).ConfigureAwait(false);
- }
-
- private async Task<Block?> GetBlockFromRpcAsync(uint256 hash, CancellationToken cancellationToken)
- {
- try
- {
- return await CoreNode!.RpcClient.GetBlockAsync(hash, cancellationToken).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- Logger.LogDebug(ex);
- return null;
- }
- }
-
- private async Task<Block?> GetBlockFromLocalNodeAsync(uint256 hash, CancellationToken cancellationToken)
{
try
{

ADD
WalletWasabi/Wallets/RpcBlockProvider.cs
+using System.Threading;
+using System.Threading.Tasks;
+using NBitcoin;
+using WalletWasabi.BitcoinCore;
+using WalletWasabi.Logging;
+
+namespace WalletWasabi.Wallets;
+
+public class RpcBlockProvider : IBlockProvider
+{
+ private CoreNode? CoreNode { get; }
+
+ public RpcBlockProvider(CoreNode? coreNode)
+ {
+ CoreNode = coreNode;
+ }
+
+ public async Task<Block?> TryGetBlockAsync(uint256 hash, CancellationToken cancellationToken)
+ {
+ if (CoreNode?.RpcClient is null)
+ {
+ return null;
+ }
+
+ try
+ {
+ return await CoreNode!.RpcClient.GetBlockAsync(hash, cancellationToken).ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ Logger.LogDebug(ex);
+ return null;
+ }
+ }
+}
\ No newline at end of file

MODIFY
WalletWasabi/Wallets/SmartBlockProvider.cs
WalletWasabi/Wallets/SmartBlockProvider.cs
@@ -19,22 +19,26 @@ public class SmartBlockProvider : IBlockProvider
};
[SuppressMessage("Style", "IDE0004:Remove Unnecessary Cast", Justification = "The cast is necessary to call the other constructor.")]
- public SmartBlockProvider(IRepository<uint256, Block> blockRepository, LocalBlockProvider localBlockProvider, P2PBlockProvider p2PBlockProvider, IMemoryCache cache)
- : this(blockRepository, (IBlockProvider)localBlockProvider, (IBlockProvider)p2PBlockProvider, cache)
+ public SmartBlockProvider(IRepository<uint256, Block> blockRepository, RpcBlockProvider rpcBlockProvider, LocalBlockProvider localBlockProvider, P2PBlockProvider p2PBlockProvider, IMemoryCache cache)
+ : this(blockRepository, (IBlockProvider)rpcBlockProvider, (IBlockProvider)localBlockProvider, (IBlockProvider)p2PBlockProvider, cache)
{
}
/// <summary>
/// For testing.
/// </summary>
- internal SmartBlockProvider(IRepository<uint256, Block> blockRepository, IBlockProvider localBlockProvider, IBlockProvider p2PBlockProvider, IMemoryCache cache)
+ internal SmartBlockProvider(IRepository<uint256, Block> blockRepository, IBlockProvider rpcBlockProvider, IBlockProvider localBlockProvider, IBlockProvider p2PBlockProvider, IMemoryCache cache)
{
BlockRepository = blockRepository;
- P2PProvider = p2PBlockProvider;
+ RpcProvider = localBlockProvider;
LocalProvider = localBlockProvider;
+ P2PProvider = p2PBlockProvider;
Cache = new(cache);
}
+ /// <seealso cref="RpcProvider"/>
+ private IBlockProvider RpcProvider { get; }
+
/// <seealso cref="LocalBlockProvider"/>
private IBlockProvider LocalProvider { get; }
@@ -81,7 +85,8 @@ public class SmartBlockProvider : IBlockProvider
/// <remarks>First ask the local block provider (which may or may not be set up) and use the P2P block provider as a fallback.</remarks>
private async Task<Block?> GetBlockNoCacheAsync(uint256 blockHash, CancellationToken cancellationToken)
{
- return await LocalProvider.TryGetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false)
+ return await RpcProvider.TryGetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false)
+ ?? await LocalProvider.TryGetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false)
?? await P2PProvider.TryGetBlockAsync(blockHash, cancellationToken).ConfigureAwait(false);
}

Extract RpcBlockProvider to own class