public CLI(string[] args) { var culture = new CultureInfo("en-US"); CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); /* * for (int i = 0; i < 20; i++) * { * var k = KeyPair.Generate(); * Console.WriteLine(k.ToWIF() + " => " + k.Address.Text); * }*/ var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "validator"); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); string wif = settings.GetString("node.wif"); var nexusName = settings.GetString("nexus.name", "simnet"); switch (mode) { case "sender": string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); RunSender(wif, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; case "validator": break; default: { logger.Error("Unknown mode: " + mode); return; } } int defaultPort = 0; for (int i = 0; i < validatorWIFs.Length; i++) { if (validatorWIFs[i] == wif) { defaultPort = (7073 + i); } } if (defaultPort == 0) { defaultPort = (7073 + validatorWIFs.Length); } int port = settings.GetInt("node.port", defaultPort); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var storagePath = settings.GetString("storage.path", defaultStoragePath); storagePath = storagePath.Replace("\\", "/"); if (!storagePath.EndsWith('/')) { storagePath += '/'; } var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); var node_keys = KeyPair.FromWIF(wif); nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".txt")); bool bootstrap = false; if (wif == validatorWIFs[0]) { if (!nexus.Ready) { logger.Debug("Boostraping nexus..."); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, Timestamp.Now)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GenesisHash); } } else { //nexus = new Nexus(nexusName, genesisAddress, logger); nexus = new Nexus(logger); seeds.Add("127.0.0.1:7073"); } // TODO this should be later optional to enable nexus.AddPlugin(new ChainAddressesPlugin()); nexus.AddPlugin(new TokenTransactionsPlugin()); nexus.AddPlugin(new AddressTransactionsPlugin()); nexus.AddPlugin(new UnclaimedTransactionsPlugin()); running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); this.mempool = new Mempool(node_keys, nexus, blockTime, ReadFromOracle); mempool.Start(ThreadPriority.AboveNormal); mempool.OnTransactionFailed += Mempool_OnTransactionFailed; api = new NexusAPI(nexus, mempool); // RPC setup if (hasRPC) { int rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(api, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } // REST setup if (hasREST) { int restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(api, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } // node setup this.node = new Node(nexus, mempool, node_keys, port, seeds, logger); node.Start(); if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } Console.CancelKeyPress += delegate { Terminate(); }; var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); bool useSimulator = settings.GetBool("simulator.enabled", false); if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); var simulator = new ChainSimulator(this.nexus, node_keys, 1234); logger.Message("Bootstrapping validators"); simulator.BeginBlock(); for (int i = 1; i < validatorWIFs.Length; i++) { simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, Nexus.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, Nexus.StakingTokenDecimals)); } simulator.EndBlock(); for (int i = 0; i < 3; i++) { logger.Message("Generating sim block #" + i); simulator.GenerateRandomBlock(); } NachoServer.InitNachoServer(nexus, simulator, node_keys, logger); MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }
public CLI(string[] args) { var culture = new CultureInfo("en-US"); Thread.CurrentThread.CurrentCulture = culture; CultureInfo.DefaultThreadCurrentCulture = culture; var seeds = new List <string>(); var settings = new Arguments(args); var useGUI = settings.GetBool("gui.enabled", true); if (useGUI) { gui = new ConsoleGUI(); logger = gui; } else { gui = null; logger = new ConsoleLogger(); } string mode = settings.GetString("node.mode", "validator"); restartTime = settings.GetInt("node.reboot", 0); showWebLogs = settings.GetBool("web.log", false); bool apiLog = settings.GetBool("api.log", true); bool hasSync = settings.GetBool("sync.enabled", true); bool hasMempool = settings.GetBool("mempool.enabled", true); bool hasEvents = settings.GetBool("events.enabled", true); bool hasRelay = settings.GetBool("relay.enabled", true); bool hasArchive = settings.GetBool("archive.enabled", true); bool hasRPC = settings.GetBool("rpc.enabled", false); bool hasREST = settings.GetBool("rest.enabled", false); string wif = settings.GetString("node.wif"); var nexusName = settings.GetString("nexus.name", "simnet"); switch (mode) { case "sender": string host = settings.GetString("sender.host"); int threadCount = settings.GetInt("sender.threads", 8); int addressesPerSender = settings.GetInt("sender.addressCount", 100); RunSender(wif, nexusName, host, threadCount, addressesPerSender); Console.WriteLine("Sender finished operations."); return; case "validator": break; default: { logger.Error("Unknown mode: " + mode); return; } } int port = settings.GetInt("node.port", 7073); var defaultStoragePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "/Storage"; var storagePath = settings.GetString("storage.path", defaultStoragePath); var storageBackend = settings.GetString("storage.backend", "file"); logger.Message("Storage backend: " + storageBackend); storagePath = storagePath.Replace("\\", "/"); if (!storagePath.EndsWith('/')) { storagePath += '/'; } var storageFix = settings.GetBool("storage.fix", false); // TODO remove this later if (storageFix) { if (Directory.Exists(storagePath)) { logger.Warning("Storage fix enabled... Cleaning up all storage..."); var di = new DirectoryInfo(storagePath); foreach (FileInfo file in di.EnumerateFiles()) { file.Delete(); } } } logger.Message("Storage path: " + storagePath); var node_keys = PhantasmaKeys.FromWIF(wif); WalletModule.Keys = PhantasmaKeys.FromWIF(wif); if (storageBackend == "file") { nexus = new Nexus(logger, (name) => new BasicDiskStore(storagePath + name + ".csv"), (n) => new SpookOracle(this, n) ); } else if (storageBackend == "db") { nexus = new Nexus(logger, (name) => new DBPartition(storagePath + name), (n) => new SpookOracle(this, n) ); } else { throw new Exception("Backend has to be set to either \"db\" or \"file\""); } bool bootstrap = false; if (!nexus.HasGenesis) { if (settings.GetBool("nexus.bootstrap")) { if (!ValidationUtils.IsValidIdentifier(nexusName)) { logger.Error("Invalid nexus name: " + nexusName); this.Terminate(); return; } logger.Debug($"Boostraping {nexusName} nexus..."); var genesisTimestamp = new Timestamp(settings.GetUInt("genesis.timestamp", Timestamp.Now.Value)); bootstrap = true; if (!nexus.CreateGenesisBlock(nexusName, node_keys, genesisTimestamp)) { throw new ChainException("Genesis block failure"); } logger.Debug("Genesis block created: " + nexus.GetGenesisHash(nexus.RootStorage)); } else { logger.Error("No Nexus found."); this.Terminate(); } } else { logger.Success("Loaded Nexus with genesis " + nexus.GetGenesisHash(nexus.RootStorage)); //seeds.Add("127.0.0.1:7073"); } running = true; // mempool setup int blockTime = settings.GetInt("node.blocktime", Mempool.MinimumBlockTime); int minimumFee; try { minimumFee = settings.GetInt("mempool.fee", 100000); if (minimumFee < 1) { logger.Error("Invalid mempool fee value. Expected a positive value."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } int minimumPow; try { minimumPow = settings.GetInt("mempool.pow", 0); int maxPow = 5; if (minimumPow < 0 || minimumPow > maxPow) { logger.Error($"Invalid mempool pow value. Expected a value between 0 and {maxPow}."); } } catch (Exception e) { logger.Error("Invalid mempool fee value. Expected something in fixed point format."); return; } if (hasMempool) { this.mempool = new Mempool(node_keys, nexus, blockTime, minimumFee, System.Text.Encoding.UTF8.GetBytes(Identifier), 0, logger); var mempoolLogging = settings.GetBool("mempool.log", true); if (mempoolLogging) { mempool.OnTransactionFailed += Mempool_OnTransactionFailed; mempool.OnTransactionAdded += (hash) => logger.Message($"Received transaction {hash}"); mempool.OnTransactionCommitted += (hash) => logger.Message($"Commited transaction {hash}"); mempool.OnTransactionDiscarded += (hash) => logger.Message($"Discarded transaction {hash}"); } mempool.Start(ThreadPriority.AboveNormal); } else { this.mempool = null; } PeerCaps caps = PeerCaps.None; if (hasSync) { caps |= PeerCaps.Sync; } if (hasMempool) { caps |= PeerCaps.Mempool; } if (hasEvents) { caps |= PeerCaps.Events; } if (hasRelay) { caps |= PeerCaps.Relay; } if (hasArchive) { caps |= PeerCaps.Archive; } if (hasRPC) { caps |= PeerCaps.RPC; } if (hasREST) { caps |= PeerCaps.REST; } var possibleCaps = Enum.GetValues(typeof(PeerCaps)).Cast <PeerCaps>().ToArray(); foreach (var cap in possibleCaps) { if (cap != PeerCaps.None && caps.HasFlag(cap)) { logger.Message("Feature enabled: " + cap); } } try { this.node = new Node("Spook v" + SpookVersion, nexus, mempool, node_keys, port, caps, seeds, logger); } catch (Exception e) { logger.Error(e.Message); return; } var useAPICache = settings.GetBool("api.cache", true); logger.Message($"API cache is {(useAPICache ? "enabled" : "disabled")}."); nexusApi = new NexusAPI(nexus, useAPICache, apiLog ? logger : null); nexusApi.Mempool = mempool; nexusApi.Node = node; // RPC setup if (hasRPC) { rpcPort = settings.GetInt("rpc.port", 7077); logger.Message($"RPC server listening on port {rpcPort}..."); var rpcServer = new RPCServer(nexusApi, "/rpc", rpcPort, (level, text) => WebLogMapper("rpc", level, text)); rpcServer.Start(ThreadPriority.AboveNormal); } else { rpcPort = 0; } // REST setup if (hasREST) { restPort = settings.GetInt("rest.port", 7078); logger.Message($"REST server listening on port {restPort}..."); var restServer = new RESTServer(nexusApi, "/api", restPort, (level, text) => WebLogMapper("rest", level, text)); restServer.Start(ThreadPriority.AboveNormal); } else { restPort = 0; } var neoScanURL = settings.GetString("neoscan.url", "https://api.neoscan.io"); var rpcList = settings.GetString("neo.rpc", "http://seed6.ngd.network:10332,http://seed.neoeconomy.io:10332"); var neoRpcURLs = rpcList.Split(','); this.neoAPI = new Neo.Core.RemoteRPCNode(neoScanURL, neoRpcURLs); this.neoAPI.SetLogger((s) => logger.Message(s)); this.neoScanAPI = new NeoScanAPI(neoScanURL, logger, nexus, node_keys); cryptoCompareAPIKey = settings.GetString("cryptocompare.apikey", ""); if (!string.IsNullOrEmpty(cryptoCompareAPIKey)) { logger.Message($"CryptoCompare API enabled..."); } node.Start(); if (gui != null) { int pluginPeriod = settings.GetInt("plugin.refresh", 1); // in seconds if (settings.GetBool("plugin.tps", false)) { RegisterPlugin(new TPSPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.ram", false)) { RegisterPlugin(new RAMPlugin(logger, pluginPeriod)); } if (settings.GetBool("plugin.mempool", false)) { RegisterPlugin(new MempoolPlugin(mempool, logger, pluginPeriod)); } } Console.CancelKeyPress += delegate { Terminate(); }; useSimulator = settings.GetBool("simulator.enabled", false); var dispatcher = new CommandDispatcher(); SetupCommands(dispatcher); if (settings.GetBool("swaps.enabled")) { var tokenSwapper = new TokenSwapper(node_keys, nexusApi, neoScanAPI, neoAPI, minimumFee, logger, settings); nexusApi.TokenSwapper = tokenSwapper; new Thread(() => { logger.Message("Running token swapping service..."); while (running) { Thread.Sleep(5000); if (nodeReady) { tokenSwapper.Update(); } } }).Start(); } if (useSimulator && bootstrap) { new Thread(() => { logger.Message("Initializing simulator..."); simulator = new NexusSimulator(this.nexus, node_keys, 1234); simulator.MinimumFee = minimumFee; /* * logger.Message("Bootstrapping validators"); * simulator.BeginBlock(); * for (int i = 1; i < validatorWIFs.Length; i++) * { * simulator.GenerateTransfer(node_keys, Address.FromWIF(validatorWIFs[i]), this.nexus.RootChain, DomainSettings.StakingTokenSymbol, UnitConversion.ToBigInteger(50000, DomainSettings.StakingTokenDecimals)); * } * simulator.EndBlock();*/ bool fillMarket = settings.GetBool("nacho.market", false); NachoServer.InitNachoServer(nexus, simulator, node_keys, fillMarket, minimumFee, logger); bool genBlocks = settings.GetBool("simulator.blocks", false); if (genBlocks) { int blockNumber = 0; while (running) { Thread.Sleep(5000); blockNumber++; logger.Message("Generating sim block #" + blockNumber); try { simulator.CurrentTime = DateTime.UtcNow; simulator.GenerateRandomBlock(); } catch (Exception e) { logger.Error("Fatal error: " + e.ToString()); Environment.Exit(-1); } } } MakeReady(dispatcher); }).Start(); } else { MakeReady(dispatcher); } this.Run(); }