public static async Task MainAsync(string[] args) { try { var comparer = new CommandlineArgumentComparer(); var isRegTest = args.Contains("regtest", comparer); var isTestNet = args.Contains("testnet", comparer); var isStratis = args.Contains("stratis", comparer); var isLight = args.Contains("light", comparer); var useRegistration = args.Contains("registration", comparer); var useTumblebit = args.Contains("tumblebit", comparer); var useTor = !args.Contains("noTor", comparer); string registrationStoreDirectoryPath = args.GetValueOf("-storedir"); TumblerProtocolType tumblerProtocol; try { string tumblerProtocolString = args.GetValueOf("-tumblerProtocol"); if (!isRegTest && (tumblerProtocolString != null || !useTor)) { Console.WriteLine("Options -TumblerProtocol and -NoTor can only be used in combination with -RegTest switch."); return; } if (tumblerProtocolString != null) { tumblerProtocol = Enum.Parse <TumblerProtocolType>(tumblerProtocolString, true); } else { tumblerProtocol = TumblerProtocolType.Tcp; } if (useTor && tumblerProtocol == TumblerProtocolType.Http) { Console.WriteLine("TumblerProtocol can only be changed to Http when Tor is disabled. Please use -NoTor switch to disable Tor."); return; } } catch { Console.WriteLine($"Incorrect tumbling prococol specified; the valid values are {TumblerProtocolType.Tcp} and {TumblerProtocolType.Http}"); return; } var agent = "Breeze"; NodeSettings nodeSettings; if (isStratis) { //if (NodeSettings.PrintHelp(args, Network.StratisMain)) // return; Network network; if (isRegTest) { network = Network.StratisRegTest; } else if (isTestNet) { args = args.Append("-addnode=51.141.28.47").ToArray(); // TODO: fix this temp hack network = Network.StratisTest; } else { network = Network.StratisMain; } nodeSettings = new NodeSettings(network, ProtocolVersion.ALT_PROTOCOL_VERSION, agent, args: args, loadConfiguration: false); } else { nodeSettings = new NodeSettings(agent: agent, args: args, loadConfiguration: false); } IFullNodeBuilder fullNodeBuilder = null; if (isLight) { fullNodeBuilder = new FullNodeBuilder() .UseNodeSettings(nodeSettings) .UseLightWallet() .UseWatchOnlyWallet() .UseBlockNotification() .UseTransactionNotification() .UseApi(); } else { fullNodeBuilder = new FullNodeBuilder() .UseNodeSettings(nodeSettings); if (isStratis) { fullNodeBuilder.UsePosConsensus(); } else { fullNodeBuilder.UsePowConsensus(); } fullNodeBuilder.UseBlockStore() .UseMempool() .UseBlockNotification() .UseTransactionNotification() .UseWallet() .UseWatchOnlyWallet(); if (isStratis) { fullNodeBuilder.AddPowPosMining(); } else { fullNodeBuilder.AddMining(); } fullNodeBuilder.AddRPC() .UseApi(); } if (useRegistration) { //fullNodeBuilder.UseInterNodeCommunication(); fullNodeBuilder.UseRegistration(); } // Need this to happen for both TB and non-TB daemon string dataDir = nodeSettings.DataDir; if (string.IsNullOrEmpty(dataDir)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { dataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "StratisNode"); } else { dataDir = Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".stratisnode"); } } string logDir = Path.Combine(dataDir, nodeSettings.Network.RootFolderName, nodeSettings.Network.Name, "Logs"); Logs.Configure(new FuncLoggerFactory(i => new DualLogger(i, (a, b) => true, false)), logDir); // Start NTumbleBit logging to the console SetupTumbleBitConsoleLogs(nodeSettings); // Currently TumbleBit is bitcoin only if (useTumblebit) { if (string.IsNullOrEmpty(registrationStoreDirectoryPath)) { string networkName; if (isRegTest) { networkName = "StratisRegTest"; } else if (isTestNet) { networkName = "StratisTest"; } else { networkName = "StratisMain"; } registrationStoreDirectoryPath = Path.Combine(dataDir, "stratis", networkName, "registrationHistory.json"); } // Those settings are not in NodeSettings yet, so get it directly from the args ConfigurationOptionWrapper <object> registrationStoreDirectory = new ConfigurationOptionWrapper <object>("RegistrationStoreDirectory", registrationStoreDirectoryPath); ConfigurationOptionWrapper <object> torOption = new ConfigurationOptionWrapper <object>("Tor", useTor); ConfigurationOptionWrapper <object> tumblerProtocolOption = new ConfigurationOptionWrapper <object>("TumblerProtocol", tumblerProtocol); ConfigurationOptionWrapper <object> useDummyAddressOption = new ConfigurationOptionWrapper <object>("UseDummyAddress", true); ConfigurationOptionWrapper <object>[] tumblebitConfigurationOptions = { registrationStoreDirectory, torOption, tumblerProtocolOption, useDummyAddressOption }; // We no longer pass the URI in via the command line, the registration feature selects a random one fullNodeBuilder.UseTumbleBit(tumblebitConfigurationOptions); } IFullNode node = fullNodeBuilder.Build(); // Add logging to NLog SetupTumbleBitNLogs(nodeSettings); // Start Full Node - this will also start the API. await node.RunAsync(); } catch (Exception ex) { Console.WriteLine("There was a problem initializing the node. Details: '{0}'", ex.Message); } }
public static void Main(string[] args) { var comparer = new CommandlineArgumentComparer(); var isRegTest = args.Contains("regtest", comparer); var isTestNet = args.Contains("testnet", comparer); var forceRegistration = args.Contains("forceRegistration", comparer); var useTor = !args.Contains("noTor", comparer); TumblerProtocolType?tumblerProtocol = null; try { string tumblerProtocolString = args.Where(a => a.StartsWith("-tumblerProtocol=")).Select(a => a.Substring("-tumblerProtocol=".Length).Replace("\"", "")).FirstOrDefault(); if (!isRegTest && (tumblerProtocolString != null || !useTor)) { Console.WriteLine("Options -TumblerProtocol and -NoTor can only be used in combination with -RegTest switch."); return; } if (tumblerProtocolString != null) { tumblerProtocol = Enum.Parse <TumblerProtocolType>(tumblerProtocolString, true); } if (useTor && tumblerProtocol.HasValue && tumblerProtocol.Value == TumblerProtocolType.Http) { Console.WriteLine("TumblerProtocol can only be changed to Http when Tor is disabled. Please use -NoTor switch to disable Tor."); return; } } catch { Console.WriteLine($"Incorrect tumbling prococol specified; the valid values are {TumblerProtocolType.Tcp} and {TumblerProtocolType.Http}"); return; } var serviceProvider = new ServiceCollection() .AddLogging() .AddSingleton <ITumblerService, TumblerService>() .BuildServiceProvider(); serviceProvider .GetService <ILoggerFactory>() .AddConsole(LogLevel.Debug); // TODO: It is messy having both a BreezeServer logger and an NTumbleBit logger var logger = serviceProvider.GetService <ILoggerFactory>() .CreateLogger <Program>(); logger.LogInformation("{Time} Reading Breeze server configuration", DateTime.Now); // Check OS-specific default config path for the config file. Create default file if it does not exist string configDir = BreezeConfiguration.GetDefaultDataDir("BreezeServer"); if (isRegTest) { configDir = Path.Combine(configDir, "ImpleumRegTest"); } else if (isTestNet) { configDir = Path.Combine(configDir, "ImpleumTest"); } else { configDir = Path.Combine(configDir, "ImpleumMain"); } string configPath = Path.Combine(configDir, "breeze.conf"); logger.LogInformation("{Time} Configuration file path {Path}", DateTime.Now, configPath); BreezeConfiguration config = new BreezeConfiguration(configPath); if (!useTor) { config.UseTor = false; } logger.LogInformation("{Time} Pre-initialising server to obtain parameters for configuration", DateTime.Now); var preTumblerConfig = serviceProvider.GetService <ITumblerService>(); preTumblerConfig.StartTumbler(config, true, torMandatory: !isRegTest, tumblerProtocol: tumblerProtocol); string configurationHash = preTumblerConfig.runtime.ClassicTumblerParameters.GetHash().ToString(); string onionAddress = preTumblerConfig.runtime.TorUri.Host.Substring(0, 16); NTumbleBit.RsaKey tumblerKey = preTumblerConfig.runtime.TumblerKey; // No longer need this instance of the class if (config.UseTor) { preTumblerConfig.runtime.TorConnection.Dispose(); } preTumblerConfig = null; string regStorePath = Path.Combine(configDir, "registrationHistory.json"); logger.LogInformation("{Time} Registration history path {Path}", DateTime.Now, regStorePath); logger.LogInformation("{Time} Checking node registration", DateTime.Now); BreezeRegistration registration = new BreezeRegistration(); if (forceRegistration || !registration.CheckBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey)) { logger.LogInformation("{Time} Creating or updating node registration", DateTime.Now); var regTx = registration.PerformBreezeRegistration(config, regStorePath, configurationHash, onionAddress, tumblerKey); if (regTx != null) { logger.LogInformation("{Time} Submitted transaction {TxId} via RPC for broadcast", DateTime.Now, regTx.GetHash().ToString()); } else { logger.LogInformation("{Time} Unable to broadcast transaction via RPC", DateTime.Now); Environment.Exit(0); } } else { logger.LogInformation("{Time} Node registration has already been performed", DateTime.Now); } // Perform collateral balance check and report the result Money collateralShortfall; if (registration.VerifyCollateral(config, out collateralShortfall)) { logger.LogInformation($"{{Time}} The collateral address {config.TumblerEcdsaKeyAddress} has sufficient funds.", DateTime.Now); } else { logger.LogWarning($"{{Time}} The collateral address {config.TumblerEcdsaKeyAddress} doesn't have enough funds. Collateral requirement is {RegistrationParameters.MASTERNODE_COLLATERAL_THRESHOLD} but only {collateralShortfall} is available at the collateral address. This is expected if you have only just run the masternode for the first time. Please send funds to the collateral address no later than {RegistrationParameters.WINDOW_PERIOD_BLOCK_COUNT} blocks after the registration transaction.", DateTime.Now); } logger.LogInformation("{Time} Starting Tumblebit server", DateTime.Now); // The TimeStamp and BlockSignature flags could be set to true when the Stratis network is instantiated. // We need to set it to false here to ensure compatibility with the Bitcoin protocol. Transaction.TimeStamp = false; Block.BlockSignature = false; var tumbler = serviceProvider.GetService <ITumblerService>(); tumbler.StartTumbler(config, false, torMandatory: !isRegTest, tumblerProtocol: tumblerProtocol); }