Change RPC unl_default to unl_load & unl_network and add UNL bootstrapping.

This commit is contained in:
Arthur Britto
2012-06-16 11:46:17 -07:00
parent 9964689f8f
commit f774baefeb
6 changed files with 169 additions and 95 deletions

View File

@@ -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;

View File

@@ -1,5 +1,4 @@
#include <fstream>
#include <iostream>
#include <boost/bind.hpp>
@@ -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,75 +1893,6 @@ 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<char>(ifsDefault)),
std::istreambuf_iterator<char>());
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 <domain>|<public_key>
Json::Value RPCServer::doUnlDelete(Json::Value& params)
{
@@ -1995,19 +1917,42 @@ Json::Value RPCServer::doUnlDelete(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, },

View File

@@ -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<RPCServer> pointer;

View File

@@ -17,6 +17,13 @@
#include <boost/mem_fn.hpp>
#include <boost/regex.hpp>
#include <fstream>
#include <iostream>
#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<char>(ifsDefault)),
std::istreambuf_iterator<char>());
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) {

View File

@@ -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();
};

View File

@@ -61,6 +61,8 @@ void printHelp(const po::options_description& desc)
cout << " unl_add <domain>|<public> [<comment>]" << endl;
cout << " unl_delete <domain>|<public_key>" << endl;
cout << " unl_list" << endl;
cout << " unl_load" << endl;
cout << " unl_network" << endl;
cout << " unl_reset" << endl;
cout << " validation_create [<seed>|<pass_phrase>|<key>]" << endl;
cout << " validation_seed [<seed>|<pass_phrase>|<key>]" << endl;