Start implementing RPC periodic query.
MODIFY
WalletWasabi.Tests/UnitTests/BitcoinCore/P2pBasedTests.cs
WalletWasabi.Tests/UnitTests/BitcoinCore/P2pBasedTests.cs
@@ -138,7 +138,7 @@ namespace WalletWasabi.Tests.UnitTests.BitcoinCore
h => notifier.OnBlock -= h);
var hash = (await rpc.GenerateAsync(1)).First();
- var block = await blockEventAwaiter.WaitAsync(TimeSpan.FromSeconds(7));
+ var block = await blockEventAwaiter.WaitAsync(TimeSpan.FromSeconds(21));
Assert.Equal(hash, block.GetHash());
// Make sure we get notifications about 10 blocks created the same time.
@@ -166,7 +166,6 @@ namespace WalletWasabi.Tests.UnitTests.BitcoinCore
h => notifier.OnReorg += h,
h => notifier.OnReorg -= h,
reorgNum);
- blockNum = 10;
blockEventsAwaiter = new EventsAwaiter<Block>(
h => notifier.OnBlock += h,
h => notifier.OnBlock -= h,

MODIFY
WalletWasabi/BitcoinCore/CoreNode.cs
WalletWasabi/BitcoinCore/CoreNode.cs
@@ -117,7 +117,12 @@ namespace WalletWasabi.BitcoinCore
coreNode.RpcClient = new RPCClient($"{authString}", coreNode.RpcEndPoint.ToString(coreNode.Network.DefaultPort), coreNode.Network);
- if (coreNodeParams.TryRestart && await coreNode.TryStopAsync(false).ConfigureAwait(false) && coreNodeParams.TryDeleteDataDir)
+ if (coreNodeParams.TryRestart)
+ {
+ await coreNode.TryStopAsync(false).ConfigureAwait(false);
+ }
+
+ if (coreNodeParams.TryDeleteDataDir)
{
await IoHelpers.DeleteRecursivelyWithMagicDustAsync(coreNode.DataDir).ConfigureAwait(false);
}
@@ -161,8 +166,10 @@ namespace WalletWasabi.BitcoinCore
desiredConfigLines.Insert(0, sectionComment);
}
- if (coreNode.Config.AddOrUpdate(string.Join(Environment.NewLine, desiredConfigLines)))
+ if (coreNode.Config.AddOrUpdate(string.Join(Environment.NewLine, desiredConfigLines))
+ || !File.Exists(configPath))
{
+ IoHelpers.EnsureContainingDirectoryExists(configPath);
await File.WriteAllTextAsync(configPath, coreNode.Config.ToString());
}
var configFileName = Path.GetFileName(configPath);
@@ -231,15 +238,29 @@ namespace WalletWasabi.BitcoinCore
/// <param name="onlyOwned">Only stop if this node owns the process.</param>
public async Task<bool> TryStopAsync(bool onlyOwned = true)
+ {
+ if (BlockNotifier != null)
{
await BlockNotifier.StopAsync().ConfigureAwait(false);
+ }
DisconnectDisposeNullP2pNode();
Exception exThrown = null;
+
+ BitcoindRpcProcessBridge bridge = null;
if (Bridge != null)
+ {
+ bridge = Bridge;
+ }
+ else if (!onlyOwned)
+ {
+ bridge = new BitcoindRpcProcessBridge(RpcClient, DataDir, printToConsole: false);
+ }
+
+ if (bridge != null)
{
try
{
- await Bridge.StopAsync(onlyOwned).ConfigureAwait(false);
+ await bridge.StopAsync(onlyOwned).ConfigureAwait(false);
Logger.LogInfo("Stopped.");
return true;
}

MODIFY
WalletWasabi/Blockchain/Blocks/BlockNotifier.cs
WalletWasabi/Blockchain/Blocks/BlockNotifier.cs
using NBitcoin;
using NBitcoin.RPC;
+using Nito.AsyncEx;
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using WalletWasabi.Bases;
using WalletWasabi.Helpers;
+using WalletWasabi.Logging;
using WalletWasabi.Services;
namespace WalletWasabi.Blockchain.Blocks
@@ -19,23 +22,55 @@ namespace WalletWasabi.Blockchain.Blocks
public RPCClient RpcClient { get; set; }
public TrustedNodeNotifyingBehavior P2pNotifier { get; }
+ private List<BlockHeader> ProcessedBlocks { get; }
+ private AsyncLock Lock { get; } = new AsyncLock();
public BlockNotifier(TimeSpan period, RPCClient rpcClient, TrustedNodeNotifyingBehavior p2pNotifier) : base(period, null)
{
RpcClient = Guard.NotNull(nameof(rpcClient), rpcClient);
P2pNotifier = Guard.NotNull(nameof(p2pNotifier), p2pNotifier);
+ ProcessedBlocks = new List<BlockHeader>();
+
P2pNotifier.BlockInv += P2pNotifier_BlockInv;
}
- private void P2pNotifier_BlockInv(object sender, uint256 e)
+ private void P2pNotifier_BlockInv(object sender, uint256 blockHash)
{
- throw new NotImplementedException();
}
public override async Task<uint256> ActionAsync(CancellationToken cancel)
{
- throw new NotImplementedException();
+ using (await Lock.LockAsync().ConfigureAwait(false))
+ {
+ var bestBlockHash = await RpcClient.GetBestBlockHashAsync().ConfigureAwait(false);
+
+ // If there's no new block.
+ // Don't notify about the genesis block.
+ if (bestBlockHash == Status || bestBlockHash == RpcClient.Network.GenesisHash)
+ {
+ return bestBlockHash;
+ }
+
+ var arrivedBlock = await RpcClient.GetBlockAsync(bestBlockHash).ConfigureAwait(false);
+ var arrivedHeader = arrivedBlock.Header;
+ arrivedHeader.PrecomputeHash(false, true);
+
+ // If we haven't processed any block yet then we're processing it without checks.
+ if (!ProcessedBlocks.Any())
+ {
+ AddBlock(arrivedBlock);
+ return bestBlockHash;
+ }
+
+ return bestBlockHash;
+ }
+ }
+
+ private void AddBlock(Block block)
+ {
+ ProcessedBlocks.Add(block.Header);
+ OnBlock?.Invoke(this, block);
}
public new async Task StopAsync()

Start implementing RPC periodic query.