diff --git a/newcoind.cfg b/newcoind.cfg index ea55a0a280..77c942b2a8 100644 --- a/newcoind.cfg +++ b/newcoind.cfg @@ -38,6 +38,7 @@ # Example: newcoin.org # # [unl_default]: +# XXX This should be called: [validators_file] # Specifies how to bootstrap the UNL list. The UNL list is based on a # validators.txt file and is maintained in the databases. When newcoind # starts up, if the databases are missing or are obsolete due to an upgrade @@ -54,6 +55,16 @@ # Examples: C:/home/johndoe/newcoin/validators.txt # /home/johndoe/newcoin/validators.txt # +# [validators]: +# List of nodes to accept as validators speficied by public key or domain. +# +# For domains, newcoind will probe for https web servers at the specied +# domain in the following order: newcoin.DOMAIN, www.DOMAIN, DOMAIN +# +# Examples: redstem.com +# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5 +# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe +# # [peer_ip]: # IP address or domain to bind to allow external connections from peers. # Defaults to not allow external connections from peers. diff --git a/src/Config.cpp b/src/Config.cpp index 6aaf809c6a..f399b05965 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -1,14 +1,11 @@ #include "Config.h" -#include "ParseSection.h" #include "utils.h" #include #include #include -#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg - #define SECTION_ACCOUNT_PROBE_MAX "account_probe_max" #define SECTION_FEE_ACCOUNT_CREATE "fee_account_create" #define SECTION_FEE_DEFAULT "fee_default" @@ -28,6 +25,7 @@ #define SECTION_VALIDATION_SEED "validation_seed" #define SECTION_WEBSOCKET_IP "websocket_ip" #define SECTION_WEBSOCKET_PORT "websocket_port" +#define SECTION_VALIDATORS "validators" #define SECTION_VALIDATORS_SITE "validators_site" // Fees are in XNB. @@ -173,6 +171,15 @@ void Config::load() section secConfig = ParseSection(strConfigFile, true); std::string strTemp; + section::mapped_type* smtTmp; + + smtTmp = sectionEntries(secConfig, SECTION_VALIDATORS); + if (smtTmp) + { + VALIDATORS = *smtTmp; + sectionEntriesPrint(&VALIDATORS, SECTION_VALIDATORS); + } + (void) sectionSingleB(secConfig, SECTION_VALIDATORS_SITE, VALIDATORS_SITE); (void) sectionSingleB(secConfig, SECTION_PEER_IP, PEER_IP); diff --git a/src/Config.h b/src/Config.h index 17f25dca21..693b00d373 100644 --- a/src/Config.h +++ b/src/Config.h @@ -2,8 +2,9 @@ #define __CONFIG__ #include "types.h" -#include "SerializedTypes.h" #include "NewcoinAddress.h" +#include "ParseSection.h" +#include "SerializedTypes.h" #include #include @@ -17,6 +18,8 @@ #define SYSTEM_CURRENCY_PARTS 1000000ull // 10^SYSTEM_CURRENCY_PRECISION #define SYSTEM_CURRENCY_START (SYSTEM_CURRENCY_GIFT*SYSTEM_CURRENCY_USERS*SYSTEM_CURRENCY_PARTS) +#define CONFIG_FILE_NAME SYSTEM_NAME "d.cfg" // newcoind.cfg + #define DEFAULT_VALIDATORS_SITE "redstem.com" #define VALIDATORS_FILE_NAME "validators.txt" const int SYSTEM_PEER_PORT = 6561; @@ -46,8 +49,8 @@ public: boost::filesystem::path DATA_DIR; boost::filesystem::path UNL_DEFAULT; - // Where to find validators.txt on the Internet. - std::string VALIDATORS_SITE; + std::string VALIDATORS_SITE; // Where to find validators.txt on the Internet. + std::vector VALIDATORS; // Validators from newcoind.cfg // Network parameters int NETWORK_START_TIME; // The Unix time we start ledger 0 diff --git a/src/ParseSection.cpp b/src/ParseSection.cpp index 1f95662135..839d3c85ee 100644 --- a/src/ParseSection.cpp +++ b/src/ParseSection.cpp @@ -56,18 +56,25 @@ section ParseSection(const std::string& strInput, const bool bTrim) return secResult; } -void PrintSection(section secInput) +void sectionEntriesPrint(std::vector* vspEntries, const std::string& strSection) +{ + std::cerr << "[" << strSection << "]" << std::endl; + + if (vspEntries) + { + BOOST_FOREACH(std::string& strValue, *vspEntries) + { + std::cerr << strValue << std::endl; + } + } +} + +void sectionPrint(section secInput) { - std::cerr << "PrintSection>" << std::endl; BOOST_FOREACH(section::value_type& pairSection, secInput) { - std::cerr << "[" << pairSection.first << "]" << std::endl; - BOOST_FOREACH(std::string& value, pairSection.second) - { - std::cerr << value << std::endl; - } + sectionEntriesPrint(&pairSection.second, pairSection.first); } - std::cerr << "PrintSection<" << std::endl; } section::mapped_type* sectionEntries(section& secSource, const std::string& strSection) diff --git a/src/ParseSection.h b/src/ParseSection.h index 76095416a3..ca60f26aac 100644 --- a/src/ParseSection.h +++ b/src/ParseSection.h @@ -8,7 +8,8 @@ typedef std::map > section; section ParseSection(const std::string& strInput, const bool bTrim); -void PrintSection(section secInput); +void sectionPrint(section secInput); +void sectionEntriesPrint(std::vector* vspEntries, const std::string& strSection); bool sectionSingleB(section& secSource, const std::string& strSection, std::string& strValue); int sectionCount(section& secSource, const std::string& strSection); section::mapped_type* sectionEntries(section& secSource, const std::string& strSection); diff --git a/src/UniqueNodeList.cpp b/src/UniqueNodeList.cpp index 0e8fdc109e..ae36513bce 100644 --- a/src/UniqueNodeList.cpp +++ b/src/UniqueNodeList.cpp @@ -692,10 +692,11 @@ void UniqueNodeList::processIps(const std::string& strSite, const NewcoinAddress // --> strValidatorsSrc: source details for display // --> naNodePublic: remote source public key - not valid for local // --> vsWhy: reason for adding validator to SeedDomains or SeedNodes. -void UniqueNodeList::processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators) +int UniqueNodeList::processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators) { Database* db = theApp->getWalletDB()->getDB(); - std::string strNodePublic = naNodePublic.isValid() ? naNodePublic.humanNodePublic() : "local"; + std::string strNodePublic = naNodePublic.isValid() ? naNodePublic.humanNodePublic() : strValidatorsSrc; + int iValues = 0; std::cerr << str(boost::format("Validator: '%s' : '%s' : processing %d validators.") @@ -718,7 +719,6 @@ void UniqueNodeList::processValidators(const std::string& strSite, const std::st vstrValues.reserve(MIN(pmtVecStrValidators->size(), REFERRAL_VALIDATORS_MAX)); - int iValues = 0; BOOST_FOREACH(std::string strReferral, *pmtVecStrValidators) { if (iValues == REFERRAL_VALIDATORS_MAX) @@ -734,7 +734,7 @@ void UniqueNodeList::processValidators(const std::string& strSite, const std::st if (!boost::regex_match(strReferral, smMatch, reReferral)) { std::cerr - << str(boost::format("Validator: '%s' ["SECTION_VALIDATORS"]: rejecting '%s'") + << str(boost::format("Validator: '%s' ["SECTION_VALIDATORS"]: rejecting line: '%s'") % strSite % strReferral) << std::endl; } @@ -744,7 +744,7 @@ void UniqueNodeList::processValidators(const std::string& strSite, const std::st std::string strComment = smMatch[2]; NewcoinAddress naValidator; - // std::cerr << str(boost::format("Validator: '%s' : '%s'") % strRefered % strComment) << std::endl; + std::cerr << str(boost::format("Validator='%s', Comment='%s'") % strRefered % strComment) << std::endl; if (naValidator.setNodePublic(strRefered)) { @@ -781,6 +781,8 @@ void UniqueNodeList::processValidators(const std::string& strSite, const std::st } fetchDirty(); + + return iValues; } // Given a section with IPs, parse and persist it for a validator. @@ -823,7 +825,7 @@ void UniqueNodeList::getIpsUrl(const NewcoinAddress& naNodePublic, section secSi } } -// Given a section with validators, parse and persist it. +// After fetching a newcoin.txt from a web site, given a section with validators, parse and persist it. void UniqueNodeList::responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile) { if (!err) @@ -1137,10 +1139,11 @@ int UniqueNodeList::iSourceScore(validatorSource vsWhy) int iScore = 0; switch (vsWhy) { + case vsConfig: iScore = 1500; break; case vsManual: iScore = 1500; break; + case vsReferral: iScore = 0; break; case vsValidator: iScore = 1000; break; case vsWeb: iScore = 200; break; - case vsReferral: iScore = 0; break; default: throw std::runtime_error("Internal error: bad validatorSource."); } @@ -1529,7 +1532,7 @@ bool UniqueNodeList::nodeLoad(boost::filesystem::path pConfig) return false; } - nodeDefault(strValidators, pConfig.native()); + nodeProcess("local", strValidators, pConfig.native()); std::cerr << str(boost::format("Processing: %s") % pConfig) << std::endl; @@ -1542,7 +1545,7 @@ void UniqueNodeList::validatorsResponse(const boost::system::error_code& err, st if (!err) { - nodeDefault(strResponse, theConfig.VALIDATORS_SITE); + nodeProcess("network", strResponse, theConfig.VALIDATORS_SITE); } else { @@ -1597,6 +1600,17 @@ void UniqueNodeList::nodeBootstrap() bLoaded = nodeLoad(VALIDATORS_FILE_NAME); } + // Always load from newcoind.cfg + if (!theConfig.VALIDATORS.empty()) + { + NewcoinAddress naInvalid; // Don't want a referrer on added entries. + + std::cerr << "Bootstrapping UNL: loading from " CONFIG_FILE_NAME "." << std::endl; + + if (processValidators("local", CONFIG_FILE_NAME, naInvalid, vsConfig, &theConfig.VALIDATORS)) + bLoaded = true; + } + if (!bLoaded) { std::cerr << "Bootstrapping UNL: loading from " << theConfig.VALIDATORS_SITE << "." << std::endl; @@ -1606,8 +1620,9 @@ void UniqueNodeList::nodeBootstrap() } // Process a validators.txt. +// --> strSite: source of validators // --> strValidators: contents of a validators.txt -void UniqueNodeList::nodeDefault(const std::string& strValidators, const std::string& strSource) { +void UniqueNodeList::nodeProcess(const std::string& strSite, const std::string& strValidators, const std::string& strSource) { section secValidators = ParseSection(strValidators, true); section::mapped_type* pmtEntries = sectionEntries(secValidators, SECTION_VALIDATORS); @@ -1616,7 +1631,7 @@ void UniqueNodeList::nodeDefault(const std::string& strValidators, const std::st NewcoinAddress naInvalid; // Don't want a referrer on added entries. // YYY Unspecified might be bootstrap or rpc command - processValidators("unspecified", strSource, naInvalid, vsValidator, pmtEntries); + processValidators(strSite, strSource, naInvalid, vsValidator, pmtEntries); } else { diff --git a/src/UniqueNodeList.h b/src/UniqueNodeList.h index 6b39f9fee5..2149c313fe 100644 --- a/src/UniqueNodeList.h +++ b/src/UniqueNodeList.h @@ -32,10 +32,11 @@ class UniqueNodeList { public: typedef enum { + vsConfig = 'C', // newcoind.cfg vsManual = 'M', + vsReferral = 'R', vsValidator = 'V', // validators.txt vsWeb = 'W', - vsReferral = 'R', } validatorSource; typedef long score; @@ -121,7 +122,7 @@ private: void responseValidators(const std::string& strValidatorsUrl, const NewcoinAddress& naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile); void processIps(const std::string& strSite, const NewcoinAddress& naNodePublic, section::mapped_type* pmtVecStrIps); - void processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators); + int processValidators(const std::string& strSite, const std::string& strValidatorsSrc, const NewcoinAddress& naNodePublic, validatorSource vsWhy, section::mapped_type* pmtVecStrValidators); void processFile(const std::string strDomain, const NewcoinAddress& naNodePublic, section secSite); @@ -132,7 +133,7 @@ private: void setSeedNodes(const seedNode& snSource, bool bNext); void validatorsResponse(const boost::system::error_code& err, std::string strResponse); - void nodeDefault(const std::string& strValidators, const std::string& strSource); + void nodeProcess(const std::string& strSite, const std::string& strValidators, const std::string& strSource); public: UniqueNodeList(boost::asio::io_service& io_service);