Example #1
0
 public ProgramTest()
 {
     this.apiSettings = new NodeHostSettings(NodeSettings.Default(KnownNetworks.TestNet))
     {
         UseHttps = true
     };
     this.certificateToUse = new X509Certificate2();
     this.certificateStore = Substitute.For <ICertificateStore>();
     this.webHostBuilder   = Substitute.For <IWebHostBuilder>();
 }
Example #2
0
        public void GivenStratisTestnet_ThenUseTheCorrectPort()
        {
            // Arrange.
            NodeSettings nodeSettings = NodeSettings.Default(KnownNetworks.StratisTest);

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(KnownNetworks.StratisTest.DefaultAPIPort, settings.ApiPort);
        }
Example #3
0
        public void GivenBitcoinMain_ThenUseTheCorrectPort()
        {
            // Arrange.
            NodeSettings nodeSettings = NodeSettings.Default(KnownNetworks.Main);

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(KnownNetworks.Main.DefaultAPIPort, settings.ApiPort);
        }
Example #4
0
 public ApiKeyAuthenticationHandler(
     NodeHostSettings nodeSettings,
     IOptionsMonitor <ApiKeyAuthenticationOptions> options,
     ILoggerFactory logger,
     UrlEncoder encoder,
     ISystemClock clock,
     IGetApiKeyQuery getApiKeyQuery) : base(options, logger, encoder, clock)
 {
     this.nodeSettings   = nodeSettings;
     this.getApiKeyQuery = getApiKeyQuery ?? throw new ArgumentNullException(nameof(getApiKeyQuery));
 }
Example #5
0
        public void GivenCertificateFilePath_ThenUsesTheCorrectFileName()
        {
            // Arrange.
            var certificateFileName = @"abcd/someCertificate.pfx";
            var nodeSettings        = new NodeSettings(KnownNetworks.TestNet, args: new[] { $"-certificatefilepath={certificateFileName}" });

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            settings.HttpsCertificateFilePath.Should().Be(certificateFileName);
        }
Example #6
0
        public void GivenUseHttps_ThenUsesTheCorrectProtocol(bool useHttps, string expectedProtocolPrefix)
        {
            // Arrange.
            var nodeSettings = new NodeSettings(KnownNetworks.TestNet, args: new[] { $"-usehttps={useHttps}", "-certificatefilepath=nonNullValue" });

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            settings.UseHttps.Should().Be(useHttps);
            settings.ApiUri.ToString().Should().StartWith(expectedProtocolPrefix);
        }
Example #7
0
        public void GivenApiPortIsProvided_ThenPortIsUsedWithDefaultApiUri()
        {
            // Arrange.
            int customPort   = 55555;
            var nodeSettings = new NodeSettings(this.Network, args: new[] { $"-apiport={customPort}" });

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(customPort, settings.ApiPort);
            Assert.Equal(new Uri($"{NodeHostSettings.DefaultApiHost}:{customPort}"), settings.ApiUri);
        }
Example #8
0
        public void GivenNoApiSettingsAreProvided_AndOnBitcoinNetwork_ThenDefaultSettingAreUsed()
        {
            // Arrange.
            Network network      = KnownNetworks.Main;
            var     nodeSettings = new NodeSettings(network);

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(network.DefaultAPIPort, settings.ApiPort);
            Assert.Equal(new Uri($"{NodeHostSettings.DefaultApiHost}:{network.DefaultAPIPort}"), settings.ApiUri);
        }
    private static NodeConfigurationData LoadConfigurationData(INodeRuntime runtime, NodeHostSettings settings)
    {
      Debug.Indent();

      Debug.Print("Create Node Config Loader of type '{0}'", settings.ConfigurationLoader);
      var configurationLoader = runtime.CreateObject<IConfigurationLoader>(settings.ConfigurationLoader);

      Debug.Print("Load Node Configuration from '{0}'", settings.ConfigLocations);
      var result = configurationLoader.Load(settings.ConfigLocations.First());

      Debug.Unindent();
      return result;
    }
Example #10
0
        public void GivenApiUriIsProvided_AndGivenBitcoinNetwork_ThenApiUriIsUsedWithDefaultBitcoinApiPort()
        {
            // Arrange.
            string  customApiUri = "http://0.0.0.0";
            Network network      = KnownNetworks.Main;
            var     nodeSettings = new NodeSettings(network, args: new[] { $"-apiuri={customApiUri}" });

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(network.DefaultAPIPort, settings.ApiPort);
            Assert.Equal(new Uri($"{customApiUri}:{network.DefaultAPIPort}"), settings.ApiUri);
        }
Example #11
0
        public void NodeSettings_CanOverrideOnlyApiPort()
        {
            const int apiport = 12345;

            var nodeSettings = new NodeSettings(new BitcoinRegTest(), args: new[] { $"-apiport={apiport}" });

            var apiSettings = new NodeHostSettings(nodeSettings);
            var rpcSettings = new RpcSettings(nodeSettings);
            var configurationManagerSettings = new ConnectionManagerSettings(nodeSettings);

            Assert.Equal(apiport, apiSettings.ApiPort);
            Assert.Equal(nodeSettings.Network.DefaultRPCPort, rpcSettings.RPCPort);
            Assert.Equal(nodeSettings.Network.DefaultPort, configurationManagerSettings.Port);
        }
Example #12
0
        public void GivenApiUriIncludingPortIsProvided_ThenUseThePassedApiUri()
        {
            // Arrange.
            int     customPort   = 5522;
            string  customApiUri = $"http://0.0.0.0:{customPort}";
            Network network      = KnownNetworks.Main;
            var     nodeSettings = new NodeSettings(network, args: new[] { $"-apiuri={customApiUri}" });

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(customPort, settings.ApiPort);
            Assert.Equal(new Uri($"{customApiUri}"), settings.ApiUri);
        }
Example #13
0
        public void GivenNoApiSettingsAreProvided_AndOnStratisNetwork_ThenDefaultSettingAreUsed()
        {
            // Arrange.
            Network network      = KnownNetworks.StratisMain;
            var     nodeSettings = new NodeSettings(network);

            // Act.
            NodeHostSettings settings = FullNodeSetup(nodeSettings);

            // Assert.
            Assert.Equal(network.DefaultAPIPort, settings.ApiPort);
            Assert.Equal(new Uri($"{NodeHostSettings.DefaultApiHost}:{network.DefaultAPIPort}"), settings.ApiUri);

            settings.HttpsCertificateFilePath.Should().BeNull();
            settings.UseHttps.Should().BeFalse();
        }
Example #14
0
        public void NodeSettings_CanOverrideAllPorts()
        {
            // On MacOS ports below 1024 are privileged, and cannot be bound to by anyone other than root.
            const int port    = 1024 + 123;
            const int rpcPort = 1024 + 456;
            const int apiPort = 1024 + 567;

            var args = new[] { $"-port={port.ToString()}", $"-rpcport={rpcPort.ToString()}", $"-apiport={apiPort.ToString()}" };

            var nodeSettings = new NodeSettings(new BitcoinRegTest(), args: args);

            var apiSettings = new NodeHostSettings(nodeSettings);
            var rpcSettings = new RpcSettings(nodeSettings);
            var configurationManagerSettings = new ConnectionManagerSettings(nodeSettings);

            Assert.Equal(apiPort, apiSettings.ApiPort);
            Assert.Equal(rpcPort, rpcSettings.RPCPort);
            Assert.Equal(port, configurationManagerSettings.Port);
        }
Example #15
0
        /// <summary>
        /// The expected sequence of arguments:
        /// <list>
        /// <item>
        /// 1, [network-name] [options] [rpc-command] [rpc-params].
        /// </item>
        /// <item>
        /// 2, [network-name] [options] [api-controller "/" api-command] [api-params].
        /// </item>
        /// </list>
        /// </summary>
        public static void Main(string[] args)
        {
            try
            {
                // Preprocess the command line arguments
                var argList = new List <string>(args);

                string networkName = null;
                if (argList.Any())
                {
                    networkName = argList.First();
                    argList.RemoveAt(0);
                }

                var optionList = new List <string>();
                while ((argList.Any()) && (argList[0].StartsWith('-')))
                {
                    optionList.Add(argList[0]);
                    argList.RemoveAt(0);
                }

                string method = "";
                if (argList.Any())
                {
                    method = argList.First().ToUpper();
                    if (method == "GET" || method == "POST" || method == "DELETE")
                    {
                        argList.RemoveAt(0);
                    }
                    else
                    {
                        method = "";
                    }
                }

                string command = string.Empty;
                if (argList.Any())
                {
                    command = argList.First();
                    argList.RemoveAt(0);
                }

                var commandArgList = new List <string>(argList);

                // Display help if required.
                if (optionList.Contains("-help") || optionList.Contains("--help") || string.IsNullOrWhiteSpace(command))
                {
                    var builder = new StringBuilder();
                    builder.AppendLine("Usage:");
                    builder.AppendLine(" dotnet run <Blockcore.Cli/Blockcore.Cli.dll> [network-name] [options] [method] <command> [arguments]");
                    builder.AppendLine();
                    builder.AppendLine("Command line arguments:");
                    builder.AppendLine();
                    builder.AppendLine("[network-name]                     Name of the network - e.g. \"stratis\" or \"bitcoin\".");
                    builder.AppendLine("[options]                          Options for the CLI (optional) - e.g. -help, -rpcuser, see below.");
                    builder.AppendLine("[method]                           Method to use for API calls - 'GET', 'POST' or 'DELETE'.");
                    builder.AppendLine("[command]                          Name of RPC method or API <controller>/<method>.");
                    builder.AppendLine("[arguments]                        Argument by position (RPC) or Name = Value pairs (API) (optional).");
                    builder.AppendLine();
                    builder.AppendLine("Options:");
                    builder.AppendLine("-help                              This help message");
                    builder.AppendLine("-rpcconnect=<ip>                   Send commands to node running on <ip> (default: 127.0.0.1)");
                    builder.AppendLine("-rpcport=<port>                    Connect to JSON-RPC on <port> (default for Stratis: 26174 or default for Bitcoin: 8332)");
                    builder.AppendLine("-rpcuser=<user>                    Username for JSON-RPC connections");
                    builder.AppendLine("-rpcpassword=<pw>                  Password for JSON-RPC connections");
                    builder.AppendLine();
                    builder.AppendLine("Examples:");
                    builder.AppendLine();
                    builder.AppendLine("dotnet run stratis -testnet GET Wallet/history WalletName=testwallet - Lists all the historical transactions of the wallet called 'testwallet' on the stratis test network.");
                    builder.AppendLine("dotnet run stratis -rpcuser=stratistestuser -rpcpassword=stratistestpassword -rpcconnect=127.0.0.3 -rpcport=26174 getinfo - Displays general information about the Stratis node on the 127.0.0.3:26174, authenticating with the RPC specified user.");
                    builder.AppendLine("dotnet run bitcoin -rpcuser=btctestuser -rpcpassword=btctestpass getbalance - Displays the current balance of the opened wallet on the 127.0.0.1:8332 node, authenticating with the RPC specified user.");
                    Console.WriteLine(builder);
                    return;
                }

                // Determine API port.
                NetworksSelector networksSelector = null;

                networksSelector = Blockcore.Networks.Bitcoin.Networks.Bitcoin;

                // API calls require both the contoller name and the method name separated by "/".
                // If this is not an API call then assume it is an RPC call.
                if (!command.Contains("/"))
                {
                    // Process RPC call.
                    try
                    {
                        string[] options      = optionList.Append("-server").ToArray();
                        var      nodeSettings = new NodeSettings(networksSelector: networksSelector, args: options)
                        {
                            MinProtocolVersion = ProtocolVersion.POS_PROTOCOL_VERSION
                        };

                        var     rpcSettings = new RpcSettings(nodeSettings);
                        Network network     = nodeSettings.Network;

                        // Find the binding to 127.0.0.1 or the first available. The logic in RPC settings ensures there will be at least 1.
                        System.Net.IPEndPoint nodeEndPoint = rpcSettings.Bind.FirstOrDefault(b => b.Address.ToString() == "127.0.0.1") ?? rpcSettings.Bind[0];
                        var rpcUri = new Uri($"http://{nodeEndPoint}");

                        // Process the command line RPC arguments
                        // TODO: this should probably be moved to the NodeSettings.FromArguments
                        if (options.GetValueOf("-rpcbind") != null)
                        {
                            rpcUri = new Uri($"http://{options.GetValueOf("-rpcbind")}");
                        }

                        if (options.GetValueOf("-rpcconnect") != null || options.GetValueOf("-rpcport") != null)
                        {
                            string rpcAddress = options.GetValueOf("-rpcconnect") ?? "127.0.0.1";

                            int rpcPort = rpcSettings.RPCPort;
                            int.TryParse(options.GetValueOf("-rpcport"), out rpcPort);

                            rpcUri = new Uri($"http://{rpcAddress}:{rpcPort}");
                        }
                        rpcSettings.RpcUser     = options.GetValueOf("-rpcuser") ?? rpcSettings.RpcUser;
                        rpcSettings.RpcPassword = options.GetValueOf("-rpcpassword") ?? rpcSettings.RpcPassword;

                        Console.WriteLine($"Connecting to the following RPC node: http://{rpcSettings.RpcUser}:{rpcSettings.RpcPassword}@{rpcUri.Authority}.");

                        // Initialize the RPC client with the configured or passed userid, password and endpoint.
                        var rpcClient = new RPCClient($"{rpcSettings.RpcUser}:{rpcSettings.RpcPassword}", rpcUri, network);

                        // Execute the RPC command
                        Console.WriteLine($"Sending RPC command '{command} {string.Join(" ", commandArgList)}' to '{rpcUri}'.");
                        RPCResponse response = rpcClient.SendCommand(command, commandArgList.ToArray());

                        // Return the result as a string to the console.
                        Console.WriteLine(response.ResultString);
                    }
                    catch (Exception err)
                    {
                        Console.WriteLine(err.Message);
                    }
                }
                else
                {
                    // Process API call.
                    string[] options      = optionList.ToArray();
                    var      nodeSettings = new NodeSettings(networksSelector: networksSelector, args: options);

                    var apiSettings = new NodeHostSettings(nodeSettings);

                    string url = $"http://localhost:{apiSettings.ApiPort}/api".AppendPathSegment(command);

                    object commandArgObj = GetAnonymousObjectFromDictionary(commandArgList
                                                                            .Select(a => a.Split('='))
                                                                            .ToDictionary(a => a[0], a => a[1]));

                    HttpResponseMessage httpResponse;

                    switch (method)
                    {
                    case "POST":
                        httpResponse = CallApiPost(url, commandArgObj);
                        break;

                    case "DELETE":
                        httpResponse = CallApiDelete(url, commandArgObj);
                        break;

                    default:
                        httpResponse = CallApiGet(url, commandArgObj);
                        break;
                    }

                    var response = httpResponse.Content.ReadAsStringAsync().GetAwaiter().GetResult();

                    // Format and return the result as a string to the console.
                    Console.WriteLine(JsonConvert.SerializeObject(JsonConvert.DeserializeObject <object>(response), Formatting.Indented));
                }
            }
            catch (Exception err)
            {
                // Report any errors to the console.
                Console.WriteLine(ExceptionToString(err));
            }
        }