diff --git a/src/Application.cpp b/src/Application.cpp index cf6809392a..d451e91645 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -58,11 +58,11 @@ void Application::run() // // Construct databases. // - mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount); - mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount); - mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount); - mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount); - mNetNodeDB = new DatabaseCon("netnode.db", NetNodeDBInit, NetNodeDBCount); + mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount); + mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount); + mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount); + mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount); + mNetNodeDB = new DatabaseCon("netnode.db", NetNodeDBInit, NetNodeDBCount); // // Begin validation and ip maintenance. @@ -73,7 +73,7 @@ void Application::run() // // Allow peer connections. // - if(!theConfig.PEER_IP.empty() && theConfig.PEER_PORT) + if (!theConfig.PEER_IP.empty() && theConfig.PEER_PORT) { mPeerDoor = new PeerDoor(mIOService); } @@ -85,7 +85,7 @@ void Application::run() // // Allow RPC connections. // - if(!theConfig.RPC_IP.empty() && theConfig.RPC_PORT) + if (!theConfig.RPC_IP.empty() && theConfig.RPC_PORT) { mRPCDoor = new RPCDoor(mIOService); } @@ -122,7 +122,8 @@ void Application::run() mNetOps.setStateTimer(0); - // temporary + getUNL().nodeBootstrap(); + mIOService.run(); // This blocks std::cout << "Done." << std::endl; diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index c1f59e5a1a..c2ded709b4 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1,5 +1,4 @@ -#include #include #include @@ -25,14 +24,6 @@ #include "NicknameState.h" #include "utils.h" -#define VALIDATORS_FETCH_SECONDS 30 -#define VALIDATORS_FILE_PATH "/" VALIDATORS_FILE_NAME -#define VALIDATORS_FILE_BYTES_MAX (50 << 10) - -/* -Just read from wire until the entire request is in. -*/ - RPCServer::RPCServer(boost::asio::io_service& io_service , NetworkOPs* nopNetwork) : mNetOps(nopNetwork), mSocket(io_service) { @@ -1902,77 +1893,8 @@ Json::Value RPCServer::doWalletSeed(Json::Value& params) } } -void RPCServer::validatorsResponse(const boost::system::error_code& err, std::string strResponse) -{ - std::cerr << "Fetch '" VALIDATORS_FILE_NAME "' complete." << std::endl; - - if (!err) - { - theApp->getUNL().nodeDefault(strResponse); - } - else - { - std::cerr << "Error: " << err.message() << std::endl; - } -} - -// Populate the UNL from a validators.txt file. -Json::Value RPCServer::doUnlDefault(Json::Value& params) { - if (!params.size() || (1==params.size() && !params[0u].compare("network"))) - { - bool bNetwork = 1 == params.size(); - std::string strValidators; - - if (!bNetwork) - { - std::ifstream ifsDefault(VALIDATORS_FILE_NAME, std::ios::in); - - if (!ifsDefault) - { - std::cerr << "Failed to open '" VALIDATORS_FILE_NAME "'." << std::endl; - - bNetwork = true; - } - else - { - strValidators.assign((std::istreambuf_iterator(ifsDefault)), - std::istreambuf_iterator()); - - if (ifsDefault.bad()) - { - std::cerr << "Failed to read '" VALIDATORS_FILE_NAME "'." << std::endl; - - bNetwork = true; - } - } - } - - if (bNetwork) - { - HttpsClient::httpsGet( - theApp->getIOService(), - VALIDATORS_SITE, - 443, - VALIDATORS_FILE_PATH, - VALIDATORS_FILE_BYTES_MAX, - boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS), - boost::bind(&RPCServer::validatorsResponse, this, _1, _2)); - - return "fetching " VALIDATORS_FILE_NAME; - } - else - { - theApp->getUNL().nodeDefault(strValidators); - - return "processing " VALIDATORS_FILE_NAME; - } - } - else - return RPCError(rpcINVALID_PARAMS); -} - // unl_delete | -Json::Value RPCServer::doUnlDelete(Json::Value& params) +Json::Value RPCServer::doUnlDelete(Json::Value& params) { std::string strNode = params[0u].asString(); @@ -1992,22 +1914,45 @@ Json::Value RPCServer::doUnlDelete(Json::Value& params) } } -Json::Value RPCServer::doUnlList(Json::Value& params) +Json::Value RPCServer::doUnlList(Json::Value& params) { Json::Value obj(Json::objectValue); + obj["unl"]=theApp->getUNL().getUnlJson(); + return obj; } +// Populate the UNL from a local validators.txt file. +Json::Value RPCServer::doUnlLoad(Json::Value& params) +{ + if (!theApp->getUNL().nodeLoad()) + { + return RPCError(rpcLOAD_FAILED); + } + + return "loading"; +} + +// Populate the UNL from newcoin.org's validators.txt file. +Json::Value RPCServer::doUnlNetwork(Json::Value& params) +{ + theApp->getUNL().nodeNetwork(); + + return "fetching"; +} + // unl_reset -Json::Value RPCServer::doUnlReset(Json::Value& params) { +Json::Value RPCServer::doUnlReset(Json::Value& params) +{ theApp->getUNL().nodeReset(); return "removing nodes"; } // unl_score -Json::Value RPCServer::doUnlScore(Json::Value& params) { +Json::Value RPCServer::doUnlScore(Json::Value& params) +{ theApp->getUNL().nodeScore(); return "scoring requested"; @@ -2053,9 +1998,10 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params { "tx", &RPCServer::doTx, 1, 1, }, { "unl_add", &RPCServer::doUnlAdd, 1, 2, }, - { "unl_default", &RPCServer::doUnlDefault, 0, 1, }, { "unl_delete", &RPCServer::doUnlDelete, 1, 1, }, { "unl_list", &RPCServer::doUnlList, 0, 0, }, + { "unl_load", &RPCServer::doUnlLoad, 0, 0, }, + { "unl_network", &RPCServer::doUnlNetwork, 0, 0, }, { "unl_reset", &RPCServer::doUnlReset, 0, 0, }, { "unl_score", &RPCServer::doUnlScore, 0, 0, }, diff --git a/src/RPCServer.h b/src/RPCServer.h index 4a3c6ece99..af9274e514 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -17,6 +17,9 @@ public: enum { rpcSUCCESS, + // Misc failure + rpcLOAD_FAILED, + // Networking rpcNO_CLOSED, rpcNO_CURRENT, @@ -40,7 +43,7 @@ public: rpcINVALID_PARAMS, rpcUNKNOWN_COMMAND, - // Bad paramater + // Bad parameter rpcACT_MALFORMED, rpcBAD_SEED, rpcDST_ACT_MALFORMED, @@ -131,10 +134,11 @@ private: Json::Value doTx(Json::Value& params); Json::Value doUnlAdd(Json::Value& params); - Json::Value doUnlDefault(Json::Value& params); Json::Value doUnlDelete(Json::Value& params); Json::Value doUnlFetch(Json::Value& params); Json::Value doUnlList(Json::Value& params); + Json::Value doUnlLoad(Json::Value& params); + Json::Value doUnlNetwork(Json::Value& params); Json::Value doUnlReset(Json::Value& params); Json::Value doUnlScore(Json::Value& params); @@ -151,8 +155,6 @@ private: Json::Value doWalletUnlock(Json::Value& params); Json::Value doWalletVerify(Json::Value& params); - void validatorsResponse(const boost::system::error_code& err, std::string strResponse); - public: typedef boost::shared_ptr pointer; diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 1427e3db8a..e52b4e5041 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -17,6 +17,13 @@ #include #include +#include +#include + +#define VALIDATORS_FETCH_SECONDS 30 +#define VALIDATORS_FILE_PATH "/" VALIDATORS_FILE_NAME +#define VALIDATORS_FILE_BYTES_MAX (50 << 10) + // Gather string constants. #define SECTION_CURRENCIES "currencies" #define SECTION_DOMAIN "domain" @@ -1409,6 +1416,116 @@ Json::Value UniqueNodeList::getUnlJson() return ret; } +bool UniqueNodeList::nodeLoad() +{ + if (theConfig.UNL_DEFAULT.empty()) + { + std::cerr << "UNL_DEFAULT not specified." << std::endl; + + return false; + } + + if (!boost::filesystem::exists(theConfig.UNL_DEFAULT)) + { + std::cerr << str(boost::format("UNL_DEFAULT not found: '%s'") % theConfig.UNL_DEFAULT) << std::endl; + + return false; + } + + if (!boost::filesystem::is_regular_file(theConfig.UNL_DEFAULT)) + { + std::cerr << str(boost::format("UNL_DEFAULT not regular file: '%s'") % theConfig.UNL_DEFAULT) << std::endl; + + return false; + } + + std::ifstream ifsDefault(theConfig.UNL_DEFAULT.native().c_str(), std::ios::in); + + if (!ifsDefault) + { + std::cerr << str(boost::format("Failed to open: '%s'") % theConfig.UNL_DEFAULT) << std::endl; + + return false; + } + + std::string strValidators; + + strValidators.assign((std::istreambuf_iterator(ifsDefault)), + std::istreambuf_iterator()); + + if (ifsDefault.bad()) + { + std::cerr << str(boost::format("Failed to read: '%s'") % theConfig.UNL_DEFAULT) << std::endl; + + return false; + } + + nodeDefault(strValidators); + + std::cerr << str(boost::format("Processing: '%s'") % theConfig.UNL_DEFAULT) << std::endl; + + return true; +} + +void UniqueNodeList::validatorsResponse(const boost::system::error_code& err, std::string strResponse) +{ + std::cerr << "Fetch '" VALIDATORS_FILE_NAME "' complete." << std::endl; + + if (!err) + { + nodeDefault(strResponse); + } + else + { + std::cerr << "Error: " << err.message() << std::endl; + } +} + +void UniqueNodeList::nodeNetwork() +{ + HttpsClient::httpsGet( + theApp->getIOService(), + VALIDATORS_SITE, + 443, + VALIDATORS_FILE_PATH, + VALIDATORS_FILE_BYTES_MAX, + boost::posix_time::seconds(VALIDATORS_FETCH_SECONDS), + boost::bind(&UniqueNodeList::validatorsResponse, this, _1, _2)); +} + +void UniqueNodeList::nodeBootstrap() +{ + int iDomains = 0; + int iNodes = 0; + + { + Database* db=theApp->getWalletDB()->getDB(); + + ScopedLock sl(theApp->getWalletDB()->getDBLock()); + + if (db->executeSQL("SELECT COUNT(*) AS Count FROM SeedDomains;") && db->startIterRows()) + iDomains = db->getInt("Count"); + + if (db->executeSQL("SELECT COUNT(*) AS Count FROM SeedNodes;") && db->startIterRows()) + iNodes = db->getInt("Count"); + } + + bool bLoaded = iDomains || iNodes; + + if (!bLoaded && !theConfig.UNL_DEFAULT.empty()) + { + std::cerr << "Bootstrapping UNL: loading from file." << std::endl; + + bLoaded = nodeLoad(); + } + + if (!bLoaded) + { + std::cerr << "Bootstrapping UNL: loading from " VALIDATORS_SITE "." << std::endl; + nodeNetwork(); + } +} + // Process a validators.txt. // --> strValidators: a validators.txt void UniqueNodeList::nodeDefault(const std::string& strValidators) { diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h index 622fd589c8..d8c3853ca7 100644 --- a/src/UniqueNodeList.h +++ b/src/UniqueNodeList.h @@ -131,6 +131,8 @@ private: bool getSeedNodes(const NewcoinAddress& naNodePublic, seedNode& dstSeedNode); void setSeedNodes(const seedNode& snSource, bool bNext); + void validatorsResponse(const boost::system::error_code& err, std::string strResponse); + public: UniqueNodeList(boost::asio::io_service& io_service); @@ -148,6 +150,10 @@ public: bool nodeInUNL(const NewcoinAddress& naNodePublic); + void nodeBootstrap(); + bool nodeLoad(); + void nodeNetwork(); + Json::Value getUnlJson(); }; diff --git a/src/main.cpp b/src/main.cpp index e60720feb6..8ec61c211a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -61,6 +61,8 @@ void printHelp(const po::options_description& desc) cout << " unl_add | []" << endl; cout << " unl_delete |" << endl; cout << " unl_list" << endl; + cout << " unl_load" << endl; + cout << " unl_network" << endl; cout << " unl_reset" << endl; cout << " validation_create [||]" << endl; cout << " validation_seed [||]" << endl;