int main(int argc, char* const* argv) { using namespace stellar; sodium_init(); Logging::init(); std::string cfgFile("stellar-core.cfg"); std::string command; el::Level logLevel = el::Level::Info; std::vector<char*> rest; optional<bool> forceSCP = nullptr; bool newDB = false; bool getInfo = false; std::vector<std::string> newHistories; std::vector<std::string> metrics; int opt; while ((opt = getopt_long_only(argc, argv, "", stellar_core_options, nullptr)) != -1) { switch (opt) { case OPT_CMD: command = optarg; rest.insert(rest.begin(), argv + optind, argv + argc); break; case OPT_CONF: cfgFile = std::string(optarg); break; case OPT_CONVERTID: StrKeyUtils::logKey(std::cout, std::string(optarg)); return 0; case OPT_DUMPXDR: dumpxdr(std::string(optarg)); return 0; case OPT_FORCESCP: forceSCP = make_optional<bool>(optarg == nullptr || string(optarg) == "true"); break; case OPT_FUZZ: fuzz(std::string(optarg), logLevel, metrics); return 0; case OPT_GENFUZZ: genfuzz(std::string(optarg)); return 0; case OPT_GENSEED: { SecretKey key = SecretKey::random(); std::cout << "Secret seed: " << key.getStrKeySeed() << std::endl; std::cout << "Public: " << key.getStrKeyPublic() << std::endl; return 0; } case OPT_INFO: getInfo = true; break; case OPT_LOGLEVEL: logLevel = Logging::getLLfromString(std::string(optarg)); break; case OPT_METRIC: metrics.push_back(std::string(optarg)); break; case OPT_NEWDB: newDB = true; break; case OPT_NEWHIST: newHistories.push_back(std::string(optarg)); break; case OPT_TEST: { rest.push_back(*argv); rest.insert(++rest.begin(), argv + optind, argv + argc); return test(static_cast<int>(rest.size()), &rest[0], logLevel, metrics); } case OPT_VERSION: std::cout << STELLAR_CORE_VERSION; return 0; default: usage(0); return 0; } } Config cfg; try { // yes you really have to do this 3 times Logging::setLogLevel(logLevel, nullptr); if (cfgFile == "-" || fs::exists(cfgFile)) { cfg.load(cfgFile); } else { std::string s; s = "No config file "; s += cfgFile + " found"; throw std::invalid_argument(s); } Logging::setFmt( PubKeyUtils::toShortString(cfg.NODE_SEED.getPublicKey())); Logging::setLogLevel(logLevel, nullptr); if (command.size()) { sendCommand(command, rest, cfg.HTTP_PORT); return 0; } // don't log to file if just sending a command if (cfg.LOG_FILE_PATH.size()) Logging::setLoggingToFile(cfg.LOG_FILE_PATH); Logging::setLogLevel(logLevel, nullptr); cfg.REBUILD_DB = newDB; cfg.REPORT_METRICS = metrics; if (forceSCP || newDB || getInfo) { setNoListen(cfg); if (newDB) initializeDatabase(cfg); if (forceSCP) setForceSCPFlag(cfg, *forceSCP); if (getInfo) showInfo(cfg); return 0; } else if (!newHistories.empty()) { setNoListen(cfg); return initializeHistories(cfg, newHistories); } if (cfg.MANUAL_CLOSE) { // in manual close mode, we set FORCE_SCP // so that the node starts fully in sync // (this is to avoid to force scp all the time when testing) cfg.FORCE_SCP = true; } } catch (std::exception& e) { LOG(FATAL) << "Got an exception: " << e.what(); return 1; } // run outside of catch block so that we properly capture crashes return startApp(cfgFile, cfg); }
int main(int argc, char* const* argv) { using namespace stellar; Logging::init(); if (sodium_init() != 0) { LOG(FATAL) << "Could not initialize crypto"; return 1; } std::string cfgFile("stellar-core.cfg"); std::string command; el::Level logLevel = el::Level::Info; std::vector<char*> rest; optional<bool> forceSCP = nullptr; bool base64 = false; bool doCatchupAt = false; uint32_t catchupAtTarget = 0; bool doCatchupComplete = false; bool doCatchupRecent = false; uint32_t catchupRecentCount = 0; bool doCatchupTo = false; uint32_t catchupToTarget = 0; bool inferQuorum = false; bool checkQuorum = false; bool graphQuorum = false; bool newDB = false; bool getOfflineInfo = false; auto doReportLastHistoryCheckpoint = false; std::string outputFile; std::string loadXdrBucket; std::vector<std::string> newHistories; std::vector<std::string> metrics; int opt; while ((opt = getopt_long_only(argc, argv, "c:", stellar_core_options, nullptr)) != -1) { switch (opt) { case OPT_BASE64: base64 = true; break; case OPT_CATCHUP_AT: doCatchupAt = true; catchupAtTarget = parseLedger(optarg); break; case OPT_CATCHUP_COMPLETE: doCatchupComplete = true; break; case OPT_CATCHUP_RECENT: doCatchupRecent = true; catchupRecentCount = parseLedgerCount(optarg); break; case OPT_CATCHUP_TO: doCatchupTo = true; catchupToTarget = parseLedger(optarg); break; case 'c': case OPT_CMD: command = optarg; rest.insert(rest.begin(), argv + optind, argv + argc); optind = argc; break; case OPT_CONF: cfgFile = std::string(optarg); break; case OPT_CONVERTID: StrKeyUtils::logKey(std::cout, std::string(optarg)); return 0; case OPT_DUMPXDR: dumpxdr(std::string(optarg)); return 0; case OPT_PRINTTXN: printtxn(std::string(optarg), base64); return 0; case OPT_SIGNTXN: signtxn(std::string(optarg), base64); return 0; case OPT_SEC2PUB: priv2pub(); return 0; case OPT_NETID: signtxn_network_id = optarg; return 0; case OPT_LOADXDR: loadXdrBucket = std::string(optarg); break; case OPT_FORCESCP: forceSCP = make_optional<bool>(optarg == nullptr || string(optarg) == "true"); break; case OPT_FUZZ: fuzz(std::string(optarg), logLevel, metrics); return 0; case OPT_GENFUZZ: genfuzz(std::string(optarg)); return 0; case OPT_GENSEED: { SecretKey key = SecretKey::random(); std::cout << "Secret seed: " << key.getStrKeySeed().value << std::endl; std::cout << "Public: " << key.getStrKeyPublic() << std::endl; return 0; } case OPT_INFERQUORUM: inferQuorum = true; break; case OPT_CHECKQUORUM: checkQuorum = true; break; case OPT_GRAPHQUORUM: graphQuorum = true; break; case OPT_OFFLINEINFO: getOfflineInfo = true; break; case OPT_OUTPUT_FILE: outputFile = optarg; break; case OPT_LOGLEVEL: logLevel = Logging::getLLfromString(std::string(optarg)); break; case OPT_METRIC: metrics.push_back(std::string(optarg)); break; case OPT_NEWDB: newDB = true; break; case OPT_NEWHIST: newHistories.push_back(std::string(optarg)); break; case OPT_REPORT_LAST_HISTORY_CHECKPOINT: doReportLastHistoryCheckpoint = true; break; case OPT_TEST: { rest.push_back(*argv); rest.insert(++rest.begin(), argv + optind, argv + argc); return test(static_cast<int>(rest.size()), &rest[0], logLevel, metrics); } case OPT_VERSION: std::cout << STELLAR_CORE_VERSION << std::endl; return 0; case OPT_HELP: default: usage(0); return 0; } } Config cfg; try { // yes you really have to do this 3 times Logging::setLogLevel(logLevel, nullptr); if (cfgFile == "-" || fs::exists(cfgFile)) { cfg.load(cfgFile); } else { std::string s; s = "No config file "; s += cfgFile + " found"; throw std::invalid_argument(s); } Logging::setFmt(KeyUtils::toShortString(cfg.NODE_SEED.getPublicKey())); Logging::setLogLevel(logLevel, nullptr); if (command.size()) { sendCommand(command, rest, cfg.HTTP_PORT); return 0; } // don't log to file if just sending a command if (cfg.LOG_FILE_PATH.size()) Logging::setLoggingToFile(cfg.LOG_FILE_PATH); Logging::setLogLevel(logLevel, nullptr); cfg.REPORT_METRICS = metrics; if (forceSCP || newDB || getOfflineInfo || !loadXdrBucket.empty() || inferQuorum || graphQuorum || checkQuorum || doCatchupAt || doCatchupComplete || doCatchupRecent || doCatchupTo || doReportLastHistoryCheckpoint) { Json::Value catchupInfo; auto result = 0; setNoListen(cfg); if ((result == 0) && newDB) initializeDatabase(cfg); if ((result == 0) && doCatchupAt) result = catchupAt(cfg, catchupAtTarget, catchupInfo); if ((result == 0) && doCatchupComplete) result = catchupComplete(cfg, catchupInfo); if ((result == 0) && doCatchupRecent) result = catchupRecent(cfg, catchupRecentCount, catchupInfo); if ((result == 0) && doCatchupTo) result = catchupTo(cfg, catchupToTarget, catchupInfo); if (!catchupInfo.isNull()) writeCatchupInfo(catchupInfo, outputFile); if ((result == 0) && forceSCP) setForceSCPFlag(cfg, *forceSCP); if ((result == 0) && getOfflineInfo) showOfflineInfo(cfg); if ((result == 0) && doReportLastHistoryCheckpoint) result = reportLastHistoryCheckpoint(cfg, outputFile); if ((result == 0) && !loadXdrBucket.empty()) loadXdr(cfg, loadXdrBucket); if ((result == 0) && inferQuorum) inferQuorumAndWrite(cfg); if ((result == 0) && checkQuorum) checkQuorumIntersection(cfg); if ((result == 0) && graphQuorum) writeQuorumGraph(cfg, outputFile); return result; } else if (!newHistories.empty()) { setNoListen(cfg); return initializeHistories(cfg, newHistories); } if (cfg.MANUAL_CLOSE) { // in manual close mode, we set FORCE_SCP // so that the node starts fully in sync // (this is to avoid to force scp all the time when testing) cfg.FORCE_SCP = true; } } catch (std::exception& e) { LOG(FATAL) << "Got an exception: " << e.what(); return 1; } // run outside of catch block so that we properly capture crashes return startApp(cfgFile, cfg); }
void Config::parseNodeID(std::string configStr, PublicKey& retKey, SecretKey& sKey, bool isSeed) { if (configStr.size() < 2) throw std::invalid_argument("invalid key"); // check if configStr is a PublicKey or a common name if (configStr[0] == '$') { if (isSeed) { throw std::invalid_argument("aliases only store public keys"); } if (!resolveNodeID(configStr, retKey)) { std::stringstream msg; msg << "unknown key in config: " << configStr; throw std::invalid_argument(msg.str()); } } else { std::istringstream iss(configStr); std::string nodestr; iss >> nodestr; if (isSeed) { sKey = SecretKey::fromStrKeySeed(nodestr); retKey = sKey.getPublicKey(); nodestr = sKey.getStrKeyPublic(); } else { retKey = PubKeyUtils::fromStrKey(nodestr); } if (iss) { // get any common name they have added std::string commonName; iss >> commonName; if (commonName.size()) { std::string cName = "$"; cName += commonName; if (resolveNodeID(cName, retKey)) { throw std::invalid_argument("name already used"); } if (!VALIDATOR_NAMES.emplace(std::make_pair(nodestr, commonName)).second) { std::stringstream msg; msg << "naming node twice: " << commonName; throw std::invalid_argument(msg.str()); } } } } }