Try implement P2P backend connection.
MODIFY
WalletWasabi.Backend/Global.cs
WalletWasabi.Backend/Global.cs
@@ -8,6 +8,8 @@ using System.IO;
using System.Net;
using System.Threading.Tasks;
using WalletWasabi.Models.ChaumianCoinJoin;
+using System.Threading;
+using NBitcoin.Protocol;
namespace WalletWasabi.Backend
{
@@ -29,6 +31,8 @@ namespace WalletWasabi.Backend
public static RPCClient RpcClient { get; private set; }
+ public static Node LocalNode { get; private set; }
+
public static IndexBuilderService IndexBuilderService { get; private set; }
public static CcjCoordinator Coordinator { get; private set; }
@@ -45,8 +49,12 @@ namespace WalletWasabi.Backend
RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig);
RpcClient = Guard.NotNull(nameof(rpc), rpc);
+ // Make sure RPC works.
await AssertRpcNodeFullyInitializedAsync();
+ // Make sure P2P works.
+ InitializeP2pNode(config.Network, config.GetBitcoinCoreEndPoint());
+
// Initialize index building
var indexBuilderServiceDir = Path.Combine(DataDir, nameof(IndexBuilderService));
var indexFilePath = Path.Combine(indexBuilderServiceDir, $"Index{RpcClient.Network}.dat");
@@ -82,6 +90,88 @@ namespace WalletWasabi.Backend
}
}
+ public static void DisconnectDisposeNullLocalNode()
+ {
+ if (LocalNode != null)
+ {
+ try
+ {
+ LocalNode?.Disconnect();
+ }
+ catch (Exception ex)
+ {
+ Logger.LogDebug<WalletService>(ex);
+ }
+ finally
+ {
+ try
+ {
+ LocalNode?.Dispose();
+ }
+ catch (Exception ex)
+ {
+ Logger.LogDebug<WalletService>(ex);
+ }
+ finally
+ {
+ LocalNode = null;
+ try
+ {
+ Logger.LogInfo<WalletService>("Local Bitcoin Node is disconnected.");
+ }
+ catch (Exception)
+ {
+ throw;
+ }
+ }
+ }
+ }
+ }
+
+ private static void InitializeP2pNode(Network network, IPEndPoint iPEndPoint)
+ {
+ Guard.NotNull(nameof(network), network);
+ Guard.NotNull(nameof(iPEndPoint), iPEndPoint);
+
+ using (var handshakeTimeout = new CancellationTokenSource())
+ {
+ handshakeTimeout.CancelAfter(TimeSpan.FromSeconds(10));
+ var nodeConnectionParameters = new NodeConnectionParameters()
+ {
+ ConnectCancellation = handshakeTimeout.Token,
+ IsRelay = true
+ };
+
+ var node = Node.Connect(network, iPEndPoint, nodeConnectionParameters);
+ try
+ {
+ Logger.LogInfo<Node>($"TCP Connection succeeded, handshaking...");
+ node.VersionHandshake(Constants.LocalBackendNodeRequirements, handshakeTimeout.Token);
+ var peerServices = node.PeerVersion.Services;
+
+ if (!peerServices.HasFlag(NodeServices.Network) && !peerServices.HasFlag(NodeServices.NODE_NETWORK_LIMITED))
+ {
+ throw new InvalidOperationException($"Wasabi cannot use the local node because it doesn't provide blocks.");
+ }
+
+ Logger.LogInfo<Node>($"Handshake completed successfully.");
+
+ if (!node.IsConnected)
+ {
+ throw new InvalidOperationException($"Wasabi could not complete the handshake with the local node and dropped the connection.{Environment.NewLine}" +
+ $"Probably this is because the node doesn't support retrieving full blocks or segwit serialization.");
+ }
+ LocalNode = node;
+ }
+ catch (OperationCanceledException) when (handshakeTimeout.IsCancellationRequested)
+ {
+ Logger.LogWarning<Node>($"Wasabi could not complete the handshake with the local node. Probably Wasabi is not whitelisted by the node.{Environment.NewLine}" +
+ $"Use \"whitebind\" or \"whitelist\" in the node configuration. (Typically whitelist=127.0.0.1 if Wasabi and the node are on the same machine.)");
+ throw;
+ }
+ }
+ }
+
public static async void IndexBuilderService_NewBlockAsync(object sender, Block block)
{
try

MODIFY
WalletWasabi.Backend/Startup.cs
WalletWasabi.Backend/Startup.cs
@@ -110,6 +110,9 @@ namespace WalletWasabi.Backend
await Task.WhenAll(stopTasks);
Logger.LogInfo<Startup>("IndexBuilderService is disposed.");
Logger.LogInfo<Startup>("RoundConfigWatcher is disposed.");
+
+ Global.DisconnectDisposeNullLocalNode();
+ Logger.LogInfo<Startup>("LocalNode is disposed.");
}
}
}

MODIFY
WalletWasabi.Tests/XunitConfiguration/RegTestFixture.cs
WalletWasabi.Tests/XunitConfiguration/RegTestFixture.cs
using Microsoft.AspNetCore.Hosting;
using NBitcoin;
using System;
+using System.Net;
using System.Threading.Tasks;
using WalletWasabi.Backend;
using WalletWasabi.Logging;
@@ -31,7 +32,7 @@ namespace WalletWasabi.Tests.XunitConfiguration
var authString = rpc.Authentication.Split(':');
- var config = new Config(rpc.Network, authString[0], authString[1]);
+ var config = new Config(rpc.Network, authString[0], authString[1], IPAddress.Loopback.ToString(), IPAddress.Loopback.ToString(), IPAddress.Loopback.ToString(), Network.Main.DefaultPort, Network.TestNet.DefaultPort, Network.RegTest.DefaultPort);
var roundConfig = new CcjRoundConfig(Money.Coins(0.1m), 144, 0.1m, 100, 120, 60, 60, 60, 1, 24, true, 11);

MODIFY
WalletWasabi/Helpers/Constants.cs
WalletWasabi/Helpers/Constants.cs
@@ -29,6 +29,21 @@ namespace WalletWasabi.Helpers
MinProtocolCapabilities = new ProtocolCapabilities { SupportGetBlock = true, SupportWitness = true }
};
+ public static readonly NodeRequirement LocalBackendNodeRequirements = new NodeRequirement
+ {
+ RequiredServices = NodeServices.NODE_WITNESS,
+ MinVersion = ProtocolVersion_WITNESS_VERSION,
+ MinProtocolCapabilities = new ProtocolCapabilities
+ {
+ SupportGetBlock = true,
+ SupportWitness = true,
+ SupportMempoolQuery = true,
+ SupportSendHeaders = true,
+ SupportPingPong = true,
+ PeerTooOld = true
+ }
+ };
+
public const int P2wpkhInputSizeInBytes = 41;
public const int P2pkhInputSizeInBytes = 145;
public const int OutputSizeInBytes = 33;

Try implement P2P backend connection.