Example #1
0
        public static async Task <CoreNode> CreateAsync(CoreNodeParams coreNodeParams, CancellationToken cancel)
        {
            Guard.NotNull(nameof(coreNodeParams), coreNodeParams);
            using (BenchmarkLogger.Measure())
            {
                var coreNode = new CoreNode();
                coreNode.HostedServices = coreNodeParams.HostedServices;
                coreNode.DataDir        = coreNodeParams.DataDir;
                coreNode.Network        = coreNodeParams.Network;
                coreNode.MempoolService = coreNodeParams.MempoolService;

                var configPath = Path.Combine(coreNode.DataDir, "bitcoin.conf");
                coreNode.Config = new CoreConfig();
                if (File.Exists(configPath))
                {
                    var configString = await File.ReadAllTextAsync(configPath).ConfigureAwait(false);

                    coreNode.Config.AddOrUpdate(configString);                     // Bitcoin Core considers the last entry to be valid.
                }
                cancel.ThrowIfCancellationRequested();

                var configTranslator = new CoreConfigTranslator(coreNode.Config, coreNode.Network);

                string    rpcUser           = configTranslator.TryGetRpcUser();
                string    rpcPassword       = configTranslator.TryGetRpcPassword();
                string    rpcCookieFilePath = configTranslator.TryGetRpcCookieFile();
                string    rpcHost           = configTranslator.TryGetRpcBind();
                int?      rpcPort           = configTranslator.TryGetRpcPort();
                WhiteBind whiteBind         = configTranslator.TryGetWhiteBind();

                string authString;
                bool   cookieAuth = rpcCookieFilePath is { };
                if (cookieAuth)
                {
                    authString = $"cookiefile={rpcCookieFilePath}";
                }
                else
                {
                    rpcUser ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                    rpcPassword ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                    authString = $"{rpcUser}:{rpcPassword}";
                }

                coreNode.P2pEndPoint = whiteBind?.EndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;
                rpcHost ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetHostOrDefault();
                rpcPort ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetPortOrDefault();
                EndPointParser.TryParse($"{rpcHost}:{rpcPort}", coreNode.Network.RPCPort, out EndPoint rpce);
                coreNode.RpcEndPoint = rpce;

                var rpcClient = new RPCClient(
                    $"{authString}",
                    coreNode.RpcEndPoint.ToString(coreNode.Network.DefaultPort),
                    coreNode.Network);
                coreNode.RpcClient = new CachedRpcClient(rpcClient, new MemoryCache(new MemoryCacheOptions {
                    SizeLimit = 1_000
                }));
        public static async Task <CoreNode> CreateAsync(CoreNodeParams coreNodeParams, CancellationToken cancel)
        {
            Guard.NotNull(nameof(coreNodeParams), coreNodeParams);
            using (BenchmarkLogger.Measure())
            {
                var coreNode = new CoreNode();
                coreNode.HostedServices = coreNodeParams.HostedServices;
                coreNode.DataDir        = coreNodeParams.DataDir;
                coreNode.Network        = coreNodeParams.Network;
                coreNode.MempoolService = coreNodeParams.MempoolService;

                var configPath = Path.Combine(coreNode.DataDir, "bitcoin.conf");
                coreNode.Config = new CoreConfig();
                if (File.Exists(configPath))
                {
                    var configString = await File.ReadAllTextAsync(configPath).ConfigureAwait(false);

                    coreNode.Config.AddOrUpdate(configString);                     // Bitcoin Core considers the last entry to be valid.
                }
                cancel.ThrowIfCancellationRequested();

                var configTranslator = new CoreConfigTranslator(coreNode.Config, coreNode.Network);

                string    rpcUser           = configTranslator.TryGetRpcUser();
                string    rpcPassword       = configTranslator.TryGetRpcPassword();
                string    rpcCookieFilePath = configTranslator.TryGetRpcCookieFile();
                string    rpcHost           = configTranslator.TryGetRpcBind();
                int?      rpcPort           = configTranslator.TryGetRpcPort();
                WhiteBind whiteBind         = configTranslator.TryGetWhiteBind();

                string authString;
                bool   cookieAuth = rpcCookieFilePath is { };
                if (cookieAuth)
                {
                    authString = $"cookiefile={rpcCookieFilePath}";
                }
                else
                {
                    rpcUser ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                    rpcPassword ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                    authString = $"{rpcUser}:{rpcPassword}";
                }

                coreNode.P2pEndPoint = whiteBind?.EndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;
                rpcHost ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetHostOrDefault();
                rpcPort ??= coreNodeParams.RpcEndPointStrategy.EndPoint.GetPortOrDefault();
                EndPointParser.TryParse($"{rpcHost}:{rpcPort}", coreNode.Network.RPCPort, out EndPoint rpce);
                coreNode.RpcEndPoint = rpce;

                var rpcClient = new RPCClient(
                    $"{authString}",
                    coreNode.RpcEndPoint.ToString(coreNode.Network.DefaultPort),
                    coreNode.Network);
                coreNode.RpcClient = new CachedRpcClient(rpcClient, coreNodeParams.Cache);

                if (coreNodeParams.TryRestart)
                {
                    await coreNode.TryStopAsync(false).ConfigureAwait(false);
                }
                cancel.ThrowIfCancellationRequested();

                if (coreNodeParams.TryDeleteDataDir)
                {
                    await IoHelpers.DeleteRecursivelyWithMagicDustAsync(coreNode.DataDir).ConfigureAwait(false);
                }
                cancel.ThrowIfCancellationRequested();

                IoHelpers.EnsureDirectoryExists(coreNode.DataDir);

                var configPrefix             = NetworkTranslator.GetConfigPrefix(coreNode.Network);
                var whiteBindPermissionsPart = !string.IsNullOrWhiteSpace(whiteBind?.Permissions) ? $"{whiteBind?.Permissions}@" : "";
                var desiredConfigLines       = new List <string>()
                {
                    $"{configPrefix}.server			= 1",
                    $"{configPrefix}.listen			= 1",
                    $"{configPrefix}.whitebind		= {whiteBindPermissionsPart}{coreNode.P2pEndPoint.ToString(coreNode.Network.DefaultPort)}",
                    $"{configPrefix}.rpcbind		= {coreNode.RpcEndPoint.GetHostOrDefault()}",
                    $"{configPrefix}.rpcallowip		= {IPAddress.Loopback}",
                    $"{configPrefix}.rpcport		= {coreNode.RpcEndPoint.GetPortOrDefault()}"
                };

                if (!cookieAuth)
                {
                    desiredConfigLines.Add($"{configPrefix}.rpcuser		= {coreNode.RpcClient.CredentialString.UserPassword.UserName}");
                    desiredConfigLines.Add($"{configPrefix}.rpcpassword	= {coreNode.RpcClient.CredentialString.UserPassword.Password}");
                }

                if (coreNodeParams.TxIndex is { })
Example #3
0
    public static async Task <CoreNode> CreateAsync(CoreNodeParams coreNodeParams, CancellationToken cancel)
    {
        Guard.NotNull(nameof(coreNodeParams), coreNodeParams);
        using (BenchmarkLogger.Measure())
        {
            var coreNode = new CoreNode
            {
                DataDir        = coreNodeParams.DataDir,
                Network        = coreNodeParams.Network,
                MempoolService = coreNodeParams.MempoolService
            };

            var configPath = Path.Combine(coreNode.DataDir, "bitcoin.conf");
            coreNode.Config = new CoreConfig();
            if (File.Exists(configPath))
            {
                var configString = await File.ReadAllTextAsync(configPath, cancel).ConfigureAwait(false);

                coreNode.Config.AddOrUpdate(configString);                 // Bitcoin Core considers the last entry to be valid.
            }
            cancel.ThrowIfCancellationRequested();

            var configTranslator = new CoreConfigTranslator(coreNode.Config, coreNode.Network);

            string?   rpcUser           = configTranslator.TryGetRpcUser();
            string?   rpcPassword       = configTranslator.TryGetRpcPassword();
            string?   rpcCookieFilePath = configTranslator.TryGetRpcCookieFile();
            string?   rpcHost           = configTranslator.TryGetRpcBind();
            int?      rpcPort           = configTranslator.TryGetRpcPort();
            WhiteBind?whiteBind         = configTranslator.TryGetWhiteBind();

            string authString;
            bool   cookieAuth = rpcCookieFilePath is not null;
            if (cookieAuth)
            {
                authString = $"cookiefile={rpcCookieFilePath}";
            }
            else
            {
                rpcUser ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                rpcPassword ??= Encoders.Hex.EncodeData(RandomUtils.GetBytes(21));
                authString = $"{rpcUser}:{rpcPassword}";
            }

            coreNode.P2pEndPoint = whiteBind?.EndPoint ?? coreNodeParams.P2pEndPointStrategy.EndPoint;

            if (rpcHost is null)
            {
                coreNodeParams.RpcEndPointStrategy.EndPoint.TryGetHost(out rpcHost);
            }

            if (rpcPort is null)
            {
                coreNodeParams.RpcEndPointStrategy.EndPoint.TryGetPort(out rpcPort);
            }

            if (!EndPointParser.TryParse($"{rpcHost}:{rpcPort}", coreNode.Network.RPCPort, out EndPoint? rpce))
            {
                throw new InvalidOperationException($"Failed to get RPC endpoint on {rpcHost}:{rpcPort}.");
            }
            coreNode.RpcEndPoint = rpce;

            var rpcClient = new RPCClient(
                $"{authString}",
                coreNode.RpcEndPoint.ToString(coreNode.Network.DefaultPort),
                coreNode.Network);
            coreNode.RpcClient = new CachedRpcClient(rpcClient, coreNodeParams.Cache);

            if (coreNodeParams.TryRestart)
            {
                await coreNode.TryStopAsync(false).ConfigureAwait(false);
            }
            cancel.ThrowIfCancellationRequested();

            if (coreNodeParams.TryDeleteDataDir)
            {
                await IoHelpers.TryDeleteDirectoryAsync(coreNode.DataDir).ConfigureAwait(false);
            }
            cancel.ThrowIfCancellationRequested();

            IoHelpers.EnsureDirectoryExists(coreNode.DataDir);

            var configPrefix             = NetworkTranslator.GetConfigPrefix(coreNode.Network);
            var whiteBindPermissionsPart = !string.IsNullOrWhiteSpace(whiteBind?.Permissions) ? $"{whiteBind?.Permissions}@" : "";

            if (!coreNode.RpcEndPoint.TryGetHost(out string?rpcBindParameter) || !coreNode.RpcEndPoint.TryGetPort(out int?rpcPortParameter))
            {
                throw new ArgumentException("Endpoint type is not supported.", nameof(coreNode.RpcEndPoint));
            }

            var desiredConfigLines = new List <string>()
            {
                $"{configPrefix}.server			= 1",
                $"{configPrefix}.listen			= 1",
                $"{configPrefix}.daemon			= 0",                                 // https://github.com/zkSNACKs/WalletWasabi/issues/3588
                $"{configPrefix}.whitebind		= {whiteBindPermissionsPart}{coreNode.P2pEndPoint.ToString(coreNode.Network.DefaultPort)}",
                $"{configPrefix}.rpcbind		= {rpcBindParameter}",
                $"{configPrefix}.rpcallowip		= {IPAddress.Loopback}",
                $"{configPrefix}.rpcport		= {rpcPortParameter}"
            };

            if (!cookieAuth)
            {
                desiredConfigLines.Add($"{configPrefix}.rpcuser		= {coreNode.RpcClient.CredentialString.UserPassword.UserName}");
                desiredConfigLines.Add($"{configPrefix}.rpcpassword	= {coreNode.RpcClient.CredentialString.UserPassword.Password}");
            }

            if (coreNodeParams.TxIndex is { })