mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Merge branch 'bootstrap'
This commit is contained in:
@@ -31,6 +31,7 @@ for dir in ['src', 'database', 'json', 'util']:
|
||||
env.ParseConfig('pkg-config --cflags --libs openssl')
|
||||
|
||||
env.Append(LIBS = [
|
||||
'boost_date_time-mt',
|
||||
'boost_filesystem-mt',
|
||||
'boost_program_options-mt',
|
||||
'boost_regex-mt',
|
||||
|
||||
@@ -120,6 +120,11 @@ bool SqliteDatabase::getNextRow()
|
||||
}
|
||||
}
|
||||
|
||||
bool SqliteDatabase::getNull(int colIndex)
|
||||
{
|
||||
return(SQLITE_NULL == sqlite3_column_type(mCurrentStmt, colIndex));
|
||||
}
|
||||
|
||||
char* SqliteDatabase::getStr(int colIndex,std::string& retStr)
|
||||
{
|
||||
retStr=(char*)sqlite3_column_text(mCurrentStmt, colIndex);
|
||||
@@ -172,4 +177,5 @@ void SqliteDatabase::escape(const unsigned char* start, int size, std::string& r
|
||||
|
||||
}
|
||||
retStr.push_back('\'');
|
||||
}
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -29,6 +29,7 @@ public:
|
||||
// will return false if there are no more rows
|
||||
bool getNextRow();
|
||||
|
||||
bool getNull(int colIndex);
|
||||
char* getStr(int colIndex,std::string& retStr);
|
||||
int32 getInt(int colIndex);
|
||||
float getFloat(int colIndex);
|
||||
@@ -39,4 +40,4 @@ public:
|
||||
|
||||
void escape(const unsigned char* start,int size,std::string& retStr);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,6 +14,15 @@ Database::~Database()
|
||||
{
|
||||
}
|
||||
|
||||
bool Database::getNull(const char* colName)
|
||||
{
|
||||
int index;
|
||||
if(getColNumber(colName,&index))
|
||||
{
|
||||
return(getNull(index));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
char* Database::getStr(const char* colName,std::string& retStr)
|
||||
{
|
||||
@@ -134,4 +143,14 @@ char* Database::getSingleDBValueStr(const char* sql,std::string& retStr)
|
||||
ret=0;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Database::escape(const std::string strValue)
|
||||
{
|
||||
std::string strReturn;
|
||||
|
||||
escape(reinterpret_cast<const unsigned char*>(strValue.c_str()), strValue.size(), strReturn);
|
||||
|
||||
return strReturn;
|
||||
}
|
||||
// vim:ts=4
|
||||
|
||||
@@ -30,7 +30,8 @@ public:
|
||||
std::string& getPass(){ return(mDBPass); }
|
||||
|
||||
virtual void escape(const unsigned char* start,int size,std::string& retStr)=0;
|
||||
|
||||
std::string escape(const std::string strValue);
|
||||
|
||||
// returns true if the query went ok
|
||||
virtual bool executeSQL(const char* sql, bool fail_okay=false)=0;
|
||||
|
||||
@@ -47,6 +48,7 @@ public:
|
||||
virtual bool getNextRow()=0;
|
||||
|
||||
// get Data from the current row
|
||||
bool getNull(const char* colName);
|
||||
char* getStr(const char* colName,std::string& retStr);
|
||||
int32 getInt(const char* colName);
|
||||
float getFloat(const char* colName);
|
||||
@@ -55,6 +57,7 @@ public:
|
||||
int getBinary(const char* colName,unsigned char* buf,int maxSize);
|
||||
uint64 getBigInt(const char* colName);
|
||||
|
||||
virtual bool getNull(int colIndex)=0;
|
||||
virtual char* getStr(int colIndex,std::string& retStr)=0;
|
||||
virtual int32 getInt(int colIndex)=0;
|
||||
virtual float getFloat(int colIndex)=0;
|
||||
|
||||
@@ -41,6 +41,7 @@ DatabaseCon::~DatabaseCon()
|
||||
}
|
||||
|
||||
Application::Application() :
|
||||
mUNL(mIOService),
|
||||
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||
mPeerDoor(NULL), mRPCDoor(NULL)
|
||||
{
|
||||
@@ -61,17 +62,32 @@ void Application::run()
|
||||
{
|
||||
assert(mTxnDB==NULL);
|
||||
|
||||
//
|
||||
// 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);
|
||||
|
||||
//
|
||||
// Begin validation and ip maintenance.
|
||||
//
|
||||
|
||||
mWallet.start();
|
||||
|
||||
//
|
||||
// Allow peer connections.
|
||||
//
|
||||
if(theConfig.PEER_PORT)
|
||||
{
|
||||
mPeerDoor=new PeerDoor(mIOService);
|
||||
}//else BOOST_LOG_TRIVIAL(info) << "No Peer Port set. Not listening for connections.";
|
||||
|
||||
//
|
||||
// Allow RPC connections.
|
||||
//
|
||||
if(theConfig.RPC_PORT)
|
||||
{
|
||||
mRPCDoor=new RPCDoor(mIOService);
|
||||
@@ -79,6 +95,7 @@ void Application::run()
|
||||
|
||||
mConnectionPool.connectToNetwork(mKnownNodes, mIOService);
|
||||
mTimingService.start(mIOService);
|
||||
|
||||
std::cout << "Before Run." << std::endl;
|
||||
|
||||
// Temporary root account will be ["This is my payphrase."]:0
|
||||
|
||||
@@ -38,6 +38,8 @@ class Application
|
||||
NetworkOPs mNetOps;
|
||||
Wallet mWallet;
|
||||
|
||||
boost::asio::io_service mIOService;
|
||||
|
||||
TimingService mTimingService;
|
||||
UniqueNodeList mUNL;
|
||||
KnownNodeList mKnownNodes;
|
||||
@@ -55,8 +57,6 @@ class Application
|
||||
std::map<std::string, Peer::pointer> mPeerMap;
|
||||
boost::recursive_mutex mPeerMapLock;
|
||||
|
||||
boost::asio::io_service mIOService;
|
||||
|
||||
public:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
17
src/Config.h
17
src/Config.h
@@ -3,14 +3,13 @@
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
|
||||
// core software parameters
|
||||
int VERSION;
|
||||
std::string VERSION_STR;
|
||||
|
||||
// network parameters
|
||||
std::string NETWORK_ID;
|
||||
std::string NETWORK_DNS_SEEDS;
|
||||
// std::string NETWORK_ID;
|
||||
// std::string NETWORK_DNS_SEEDS;
|
||||
int NETWORK_START_TIME; // The Unix time we start ledger 0
|
||||
int TRANSACTION_FEE_BASE;
|
||||
int LEDGER_SECONDS;
|
||||
@@ -23,13 +22,13 @@ public:
|
||||
std::string PEER_IP;
|
||||
int PEER_PORT;
|
||||
int NUMBER_CONNECTIONS;
|
||||
bool NODE_INBOUND; // we accept inbound connections
|
||||
bool NODE_DATABASE; // we offer historical data services
|
||||
bool NODE_PUBLIC; // we do not attempt to hide our identity
|
||||
bool NODE_DUMB; // we are a 'dumb' client
|
||||
bool NODE_SMART; // we offer services to 'dumb' clients
|
||||
// bool NODE_INBOUND; // we accept inbound connections
|
||||
// bool NODE_DATABASE; // we offer historical data services
|
||||
// bool NODE_PUBLIC; // we do not attempt to hide our identity
|
||||
// bool NODE_DUMB; // we are a 'dumb' client
|
||||
// bool NODE_SMART; // we offer services to 'dumb' clients
|
||||
|
||||
std::string HANKO_PRIVATE;
|
||||
// std::string HANKO_PRIVATE;
|
||||
|
||||
// RPC parameters
|
||||
std::string RPC_IP;
|
||||
|
||||
141
src/DBInit.cpp
141
src/DBInit.cpp
@@ -55,14 +55,144 @@ const char *WalletDBInit[] = {
|
||||
Seq BIGINT UNSIGNED, \
|
||||
Comment TEXT \
|
||||
);",
|
||||
|
||||
// XXX Don't really need this.
|
||||
// We should generate communication identity per launch.
|
||||
// Validation id is provided via rpc or stored in config.
|
||||
"CREATE TABLE NodeIdentity ( \
|
||||
PublicKey CHARACTER(53), \
|
||||
PrivateKey CHARACTER(52) \
|
||||
);",
|
||||
"CREATE TABLE TrustedNodes ( \
|
||||
PublicKey CHARACTER(53) PRIMARY KEY, \
|
||||
|
||||
// Miscellaneous persistent information
|
||||
// ScoresUpdated: when scores was last updated.
|
||||
// Scores need updating if:
|
||||
// - This time is 0
|
||||
// - This time is prior to the most recent SeedDomains or SeedNodes fetch.
|
||||
"CREATE TABLE Misc ( \
|
||||
ScoresUpdated DATETIME \
|
||||
);",
|
||||
|
||||
// Domain:
|
||||
// Domain source for https.
|
||||
// PublicKey:
|
||||
// Set if ever succeeded.
|
||||
// XXX Use NULL in place of ""
|
||||
// Source:
|
||||
// 'M' = Manually added. : 1500
|
||||
// 'V' = validators.txt : 1000
|
||||
// 'W' = Web browsing. : 200
|
||||
// 'R' = Referral : 0
|
||||
// Next:
|
||||
// Time of next fetch attempt.
|
||||
// Scan:
|
||||
// Time of last fetch attempt.
|
||||
// Fetch:
|
||||
// Time of last successful fetch.
|
||||
// Sha256:
|
||||
// Checksum of last fetch.
|
||||
// Comment:
|
||||
// User supplied comment.
|
||||
// Table of Domains user has asked to trust.
|
||||
"CREATE TABLE SeedDomains ( \
|
||||
Domain TEXT PRIMARY KEY NOT NULL, \
|
||||
PublicKey CHARACTER(53), \
|
||||
Source CHARACTER(1) NOT NULL, \
|
||||
Next DATETIME, \
|
||||
Scan DATETIME, \
|
||||
Fetch DATETIME, \
|
||||
Sha256 CHARACTER[64], \
|
||||
Comment TEXT \
|
||||
);"
|
||||
);",
|
||||
|
||||
// Allow us to easily find the next SeedDomain to fetch.
|
||||
"CREATE INDEX SeedDomainNext ON SeedDomains (Next);",
|
||||
|
||||
// Table of PublicKeys user has asked to trust.
|
||||
// Fetches are made to the CAS.
|
||||
// Next:
|
||||
// Time of next fetch attempt.
|
||||
// Scan:
|
||||
// Time of last fetch attempt.
|
||||
// Fetch:
|
||||
// Time of last successful fetch.
|
||||
// Sha256:
|
||||
// Checksum of last fetch.
|
||||
// Comment:
|
||||
// User supplied comment.
|
||||
"CREATE TABLE SeedNodes ( \
|
||||
PublicKey CHARACTER(53) PRIMARY KEY NOT NULL, \
|
||||
Next DATETIME, \
|
||||
Scan DATETIME, \
|
||||
Fetch DATETIME, \
|
||||
Sha256 CHARACTER[64], \
|
||||
Comment TEXT \
|
||||
);",
|
||||
|
||||
// Allow us to easily find the next SeedNode to fetch.
|
||||
"CREATE INDEX SeedNodeNext ON SeedNodes (Next);",
|
||||
|
||||
// Table of trusted nodes.
|
||||
// Score:
|
||||
// Computed trust score. Higher is better.
|
||||
// Seen:
|
||||
// Last validation received.
|
||||
"CREATE TABLE TrustedNodes ( \
|
||||
PublicKey CHARACTER(53) PRIMARY KEY NOT NULL, \
|
||||
Score INTEGER, \
|
||||
Seen DATETIME \
|
||||
);",
|
||||
|
||||
// List of referrals.
|
||||
// - There may be multiple sources for a Validator. The last source is used.
|
||||
// Validator:
|
||||
// Public key of referrer.
|
||||
// Index:
|
||||
// Entry index in [validators] table.
|
||||
// Referral:
|
||||
// Public key of referred or Domain.
|
||||
// XXX Index by validator for fast delete
|
||||
"CREATE TABLE ValidatorReferrals ( \
|
||||
Validator CHARACTER(53), \
|
||||
Entry INTEGER, \
|
||||
Referral TEXT \
|
||||
);",
|
||||
|
||||
// List of referrals.
|
||||
// Validator:
|
||||
// Public key of referree.
|
||||
// Index:
|
||||
// Entry index in [validators] table.
|
||||
// IP:
|
||||
// IP of referred.
|
||||
"CREATE TABLE IpReferrals ( \
|
||||
Validator CHARACTER(53), \
|
||||
Index INTEGER, \
|
||||
IP TEXT \
|
||||
);",
|
||||
|
||||
// Table of IPs to contact the nextwork.
|
||||
// IP:
|
||||
// IP address to contact.
|
||||
// Port:
|
||||
// Port to contact. 0=default.
|
||||
// Score:
|
||||
// Computed trust score. Higher is better.
|
||||
// Source:
|
||||
// 'V' = Validation file
|
||||
// 'M' = Manually added.
|
||||
// 'I' = Inbound connection.
|
||||
// 'O' = Other.
|
||||
// Contact:
|
||||
// Time of last contact.
|
||||
// XXX Update on connect and hourly.
|
||||
"CREATE TABLE PeerIps ( \
|
||||
IP TEXT PRIMARY KEY, \
|
||||
PORT INTEGER, \
|
||||
Score INTEGER, \
|
||||
Source CHARACTER(1), \
|
||||
Contact DATETIME \
|
||||
);",
|
||||
};
|
||||
|
||||
#if 0
|
||||
@@ -78,7 +208,6 @@ const char *WalletDBInit[] = {
|
||||
|
||||
int WalletDBCount=sizeof(WalletDBInit)/sizeof(const char *);
|
||||
|
||||
|
||||
// Hash node database holds nodes indexed by hash
|
||||
const char *HashNodeDBInit[] = {
|
||||
"CREATE TABLE CommittedObjects \
|
||||
@@ -88,11 +217,13 @@ const char *HashNodeDBInit[] = {
|
||||
Object BLOB \
|
||||
);",
|
||||
"CREATE INDEX ObjectLocate ON \
|
||||
CommittedObjects(LedgerIndex, ObjType);" };
|
||||
CommittedObjects(LedgerIndex, ObjType);"
|
||||
};
|
||||
|
||||
int HashNodeDBCount=sizeof(HashNodeDBInit)/sizeof(const char *);
|
||||
|
||||
// Net node database holds nodes seen on the network
|
||||
// XXX Not really used needs replacement.
|
||||
const char *NetNodeDBInit[] = {
|
||||
"CREATE TABLE KnownNodes ( \
|
||||
Hanko CHARACTER(35) PRIMARY KEY, \
|
||||
|
||||
@@ -44,13 +44,13 @@ void HttpsClient::httpsGet(
|
||||
|
||||
void HttpsClient::httpsNext()
|
||||
{
|
||||
std::cerr << "Fetch: " << mDeqSites[0] << std::endl;
|
||||
// std::cerr << "Fetch: " << mDeqSites[0] << std::endl;
|
||||
boost::shared_ptr<boost::asio::ip::tcp::resolver::query> query(new boost::asio::ip::tcp::resolver::query(mDeqSites[0], boost::lexical_cast<std::string>(mPort),
|
||||
ip::resolver_query_base::numeric_service|ip::resolver_query_base::numeric_service));
|
||||
mQuery = query;
|
||||
|
||||
mCtx.set_default_verify_paths(mShutdown);
|
||||
if (!mShutdown)
|
||||
if (mShutdown)
|
||||
{
|
||||
std::cerr << "set_default_verify_paths: " << mShutdown.message() << std::endl;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ void HttpsClient::httpsNext()
|
||||
{
|
||||
mDeadline.expires_from_now(mTimeout, mShutdown);
|
||||
|
||||
std::cerr << "expires_from_now: " << mShutdown.message() << std::endl;
|
||||
// std::cerr << "expires_from_now: " << mShutdown.message() << std::endl;
|
||||
}
|
||||
|
||||
if (!mShutdown)
|
||||
@@ -73,7 +73,7 @@ void HttpsClient::httpsNext()
|
||||
|
||||
if (!mShutdown)
|
||||
{
|
||||
std::cerr << "Resolving: " << mDeqSites[0] << std::endl;
|
||||
// std::cerr << "Resolving: " << mDeqSites[0] << std::endl;
|
||||
|
||||
mResolver.async_resolve(*mQuery,
|
||||
boost::bind(
|
||||
@@ -92,9 +92,9 @@ void HttpsClient::handleDeadline(const boost::system::error_code& ecResult)
|
||||
if (ecResult == boost::asio::error::operation_aborted)
|
||||
{
|
||||
// Timer canceled because deadline no longer needed.
|
||||
std::cerr << "Deadline cancelled." << std::endl;
|
||||
// std::cerr << "Deadline cancelled." << std::endl;
|
||||
|
||||
// Do nothing. Aborter is done.
|
||||
// nothing(); // Aborter is done.
|
||||
}
|
||||
else if (ecResult)
|
||||
{
|
||||
@@ -142,7 +142,7 @@ void HttpsClient::handleResolve(
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Resolve complete." << std::endl;
|
||||
// std::cerr << "Resolve complete." << std::endl;
|
||||
|
||||
boost::asio::async_connect(
|
||||
mSocketSsl.lowest_layer(),
|
||||
@@ -166,7 +166,7 @@ void HttpsClient::handleConnect(const boost::system::error_code& ecResult)
|
||||
|
||||
if (!mShutdown)
|
||||
{
|
||||
std::cerr << "Connected." << std::endl;
|
||||
// std::cerr << "Connectted." << std::endl;
|
||||
|
||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||
@@ -206,7 +206,7 @@ void HttpsClient::handleRequest(const boost::system::error_code& ecResult)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "SSL session started." << std::endl;
|
||||
// std::cerr << "SSL session started." << std::endl;
|
||||
|
||||
std::ostream osRequest(&mRequest);
|
||||
|
||||
@@ -238,7 +238,7 @@ void HttpsClient::handleWrite(const boost::system::error_code& ecResult)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Wrote." << std::endl;
|
||||
// std::cerr << "Wrote." << std::endl;
|
||||
|
||||
boost::asio::async_read(
|
||||
mSocketSsl,
|
||||
@@ -265,7 +265,8 @@ void HttpsClient::handleData(const boost::system::error_code& ecResult)
|
||||
{
|
||||
if (mShutdown)
|
||||
{
|
||||
std::cerr << "Complete." << std::endl;
|
||||
// std::cerr << "Complete." << std::endl;
|
||||
// nothing();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -9,17 +9,23 @@
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
NewcoinAddress::NewcoinAddress()
|
||||
{
|
||||
nVersion = VER_NONE;
|
||||
}
|
||||
|
||||
bool NewcoinAddress::IsValid()
|
||||
bool NewcoinAddress::IsValid() const
|
||||
{
|
||||
return !vchData.empty();
|
||||
}
|
||||
|
||||
void NewcoinAddress::clear()
|
||||
{
|
||||
nVersion = VER_NONE;
|
||||
}
|
||||
|
||||
//
|
||||
// Hanko
|
||||
//
|
||||
@@ -38,7 +44,7 @@ uint160 NewcoinAddress::getHanko() const
|
||||
return Hash160(vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +67,7 @@ std::string NewcoinAddress::humanHanko() const
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +102,7 @@ const std::vector<unsigned char>& NewcoinAddress::getNodePublic() const
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +119,7 @@ std::string NewcoinAddress::humanNodePublic() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +147,7 @@ uint256 NewcoinAddress::getNodePrivate() const
|
||||
return uint256(vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +161,7 @@ std::string NewcoinAddress::humanNodePrivate() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +197,7 @@ uint160 NewcoinAddress::getAccountID() const
|
||||
return Hash160(vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +220,7 @@ std::string NewcoinAddress::humanAccountID() const
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +252,7 @@ const std::vector<unsigned char>& NewcoinAddress::getAccountPublic() const
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +269,7 @@ std::string NewcoinAddress::humanAccountPublic() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,7 +304,7 @@ uint256 NewcoinAddress::getAccountPrivate() const
|
||||
return uint256(vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,7 +318,7 @@ std::string NewcoinAddress::humanAccountPrivate() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +352,7 @@ BIGNUM* NewcoinAddress::getFamilyGeneratorBN() const
|
||||
break;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
|
||||
BIGNUM* ret = BN_bin2bn(&vchData[0], vchData.size(), NULL);
|
||||
@@ -366,7 +372,7 @@ const std::vector<unsigned char>& NewcoinAddress::getFamilyGenerator() const
|
||||
return vchData;
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +386,7 @@ std::string NewcoinAddress::humanFamilyGenerator() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -426,7 +432,7 @@ uint128 NewcoinAddress::getFamilySeed() const
|
||||
return uint128(vchData);
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -462,7 +468,7 @@ std::string NewcoinAddress::humanFamilySeed1751() const
|
||||
}
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,7 +482,7 @@ std::string NewcoinAddress::humanFamilySeed() const
|
||||
return ToString();
|
||||
|
||||
default:
|
||||
throw std::runtime_error("bad source");
|
||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,8 @@ private:
|
||||
public:
|
||||
NewcoinAddress();
|
||||
|
||||
bool IsValid();
|
||||
bool IsValid() const;
|
||||
void clear();
|
||||
|
||||
//
|
||||
// hanko
|
||||
|
||||
@@ -69,7 +69,7 @@ void PrintSection(section secInput)
|
||||
std::cerr << "PrintSection<" << std::endl;
|
||||
}
|
||||
|
||||
section::mapped_type* sectionEntries(section& secSource, std::string strSection)
|
||||
section::mapped_type* sectionEntries(section& secSource, const std::string strSection)
|
||||
{
|
||||
section::iterator it;
|
||||
section::mapped_type* smtResult;
|
||||
@@ -96,7 +96,7 @@ int sectionCount(section& secSource, std::string strSection)
|
||||
return pmtEntries ? -1 : pmtEntries->size();
|
||||
}
|
||||
|
||||
bool sectionSingleB(section& secSource, std::string strSection, std::string& strValue)
|
||||
bool sectionSingleB(section& secSource, const std::string strSection, std::string& strValue)
|
||||
{
|
||||
section::mapped_type* pmtEntries = sectionEntries(secSource, strSection);
|
||||
bool bSingle = pmtEntries && 1 == pmtEntries->size();
|
||||
|
||||
@@ -9,8 +9,8 @@ typedef std::map<const std::string, std::vector<std::string> > section;
|
||||
|
||||
section ParseSection(const std::string strInput, const bool bTrim);
|
||||
void PrintSection(section secInput);
|
||||
bool sectionSingleB(section& secSource, std::string strSection, std::string& strValue);
|
||||
bool sectionSingleB(section& secSource, const std::string strSection, std::string& strValue);
|
||||
int sectionCount(section& secSource, std::string strSection);
|
||||
section::mapped_type* sectionEntries(section& secSource, std::string strSection);
|
||||
section::mapped_type* sectionEntries(section& secSource, const std::string strSection);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -505,27 +505,28 @@ Json::Value RPCServer::doLedger(Json::Value& params)
|
||||
return "not implemented";
|
||||
}
|
||||
|
||||
// unl_add <node_public>
|
||||
// unl_add <node_public> <comment>
|
||||
// unl_add <domain><node_public> [<comment>]
|
||||
Json::Value RPCServer::doUnlAdd(Json::Value& params) {
|
||||
if(params.size()==1 || params.size()==2)
|
||||
{
|
||||
std::string strNodePublic=params[0u].asString();
|
||||
std::string strNode = params[0u].asString();
|
||||
std::string strComment=params.size() == 2
|
||||
? ""
|
||||
: params[1u].asString();
|
||||
|
||||
NewcoinAddress nodePublic;
|
||||
|
||||
if(nodePublic.setNodePublic(strNodePublic))
|
||||
if(nodePublic.setNodePublic(strNode))
|
||||
{
|
||||
theApp->getUNL().nodeAdd(nodePublic, strComment);
|
||||
theApp->getUNL().nodeAddPublic(nodePublic, strComment);
|
||||
|
||||
return "adding node";
|
||||
return "adding node by public key";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "invalid public key";
|
||||
theApp->getUNL().nodeAddDomain(strNode, UniqueNodeList::vsManual, strComment);
|
||||
|
||||
return "adding node by domain";
|
||||
}
|
||||
}
|
||||
else return "invalid params";
|
||||
@@ -535,6 +536,9 @@ Json::Value RPCServer::doUnlAdd(Json::Value& params) {
|
||||
// validation_create <pass_phrase>
|
||||
// validation_create <seed>
|
||||
// validation_create <seed_key>
|
||||
//
|
||||
// NOTE: It is poor security to specify secret information on the command line. This information might be saved in the command
|
||||
// shell history file (e.g. .bash_history) and it may be leaked via the process status command (i.e. ps).
|
||||
Json::Value RPCServer::doValidatorCreate(Json::Value& params) {
|
||||
NewcoinAddress familySeed;
|
||||
NewcoinAddress familyGenerator;
|
||||
@@ -675,18 +679,6 @@ Json::Value RPCServer::doUnlDelete(Json::Value& params) {
|
||||
else return "invalid params";
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doUnlFetch(Json::Value& params) {
|
||||
if(params.size() == 1)
|
||||
{
|
||||
std::string strDomain=params[0u].asString();
|
||||
|
||||
theApp->getUNL().nodeFetch(strDomain);
|
||||
|
||||
return "fetching domain";
|
||||
}
|
||||
else return "invalid params";
|
||||
}
|
||||
|
||||
Json::Value RPCServer::doUnlList(Json::Value& params) {
|
||||
return theApp->getUNL().getUnlJson();
|
||||
}
|
||||
@@ -716,7 +708,6 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params
|
||||
if(command=="unl_add") return doUnlAdd(params);
|
||||
if(command=="unl_default") return doUnlDefault(params);
|
||||
if(command=="unl_delete") return doUnlDelete(params);
|
||||
if(command=="unl_fetch") return doUnlFetch(params);
|
||||
if(command=="unl_list") return doUnlList(params);
|
||||
if(command=="unl_reset") return doUnlReset(params);
|
||||
|
||||
|
||||
@@ -213,6 +213,11 @@ uint256 Serializer::getSHA512Half(const unsigned char *data, int len)
|
||||
return j[0];
|
||||
}
|
||||
|
||||
uint256 Serializer::getSHA512Half(const std::string& strData)
|
||||
{
|
||||
return getSHA512Half(reinterpret_cast<const unsigned char*>(strData.c_str()), strData.size());
|
||||
}
|
||||
|
||||
bool Serializer::checkSignature(int pubkeyOffset, int signatureOffset) const
|
||||
{
|
||||
std::vector<unsigned char> pubkey, signature;
|
||||
|
||||
@@ -68,6 +68,7 @@ class Serializer
|
||||
uint256 getSHA512Half(int size=-1) const;
|
||||
static uint256 getSHA512Half(const std::vector<unsigned char>& data, int size=-1);
|
||||
static uint256 getSHA512Half(const unsigned char *data, int len);
|
||||
static uint256 getSHA512Half(const std::string& strData);
|
||||
|
||||
// totality functions
|
||||
int getLength() const { return mData.size(); }
|
||||
|
||||
@@ -2,208 +2,362 @@
|
||||
#include "Conversion.h"
|
||||
#include "HttpsClient.h"
|
||||
#include "ParseSection.h"
|
||||
#include "Serializer.h"
|
||||
#include "UniqueNodeList.h"
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/mem_fn.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
// Gather string constants.
|
||||
#define SECTION_CURRENCIES "currencies"
|
||||
#define SECTION_DOMAIN "domain"
|
||||
#define SECTION_IPS "ips"
|
||||
#define SECTION_IPS_URL "ips_url"
|
||||
#define SECTION_PUBLIC_KEY "node_public_key"
|
||||
#define SECTION_PUBLIC_KEY "validation_public_key"
|
||||
#define SECTION_VALIDATORS "validators"
|
||||
#define SECTION_VALIDATORS_URL "validators_url"
|
||||
|
||||
UniqueNodeList::UniqueNodeList() : mFetchActive(0)
|
||||
// Limit pollution of database.
|
||||
#define REFERRAL_VALIDATORS_MAX 50
|
||||
#define REFERRAL_IPS_MAX 50
|
||||
|
||||
static boost::posix_time::ptime ptEpoch()
|
||||
{
|
||||
return boost::posix_time::ptime(boost::gregorian::date(2000, boost::gregorian::Jan, 1));
|
||||
}
|
||||
|
||||
static int iToSeconds(boost::posix_time::ptime ptWhen)
|
||||
{
|
||||
boost::posix_time::time_duration td = ptWhen - ptEpoch();
|
||||
|
||||
return td.total_seconds();
|
||||
}
|
||||
|
||||
static boost::posix_time::ptime ptFromSeconds(int iSeconds)
|
||||
{
|
||||
return ptEpoch() + boost::posix_time::seconds(iSeconds);
|
||||
}
|
||||
|
||||
UniqueNodeList::UniqueNodeList(boost::asio::io_service& io_service) :
|
||||
mFetchActive(0),
|
||||
mdtFetchTimer(io_service)
|
||||
{
|
||||
}
|
||||
|
||||
void UniqueNodeList::processIps(section::mapped_type& vecStrIps) {
|
||||
std::cerr << "Processing ips." << std::endl;
|
||||
|
||||
// XXX Do something with ips.
|
||||
}
|
||||
|
||||
void UniqueNodeList::processValidators(section::mapped_type& vecStrValidators)
|
||||
void UniqueNodeList::start()
|
||||
{
|
||||
std::cerr << "Processing validators." << std::endl;
|
||||
|
||||
// XXX Do something with validators.
|
||||
fetchNext(); // Start fetching.
|
||||
}
|
||||
|
||||
void UniqueNodeList::responseIps(const boost::system::error_code& err, const std::string strIpsFile)
|
||||
{
|
||||
section secFile = ParseSection(strIpsFile, true);
|
||||
section::mapped_type* pmtEntries = sectionEntries(secFile, SECTION_IPS);
|
||||
|
||||
if (pmtEntries)
|
||||
processIps(*pmtEntries);
|
||||
|
||||
getValidatorsUrl();
|
||||
}
|
||||
|
||||
void UniqueNodeList::responseValidators(const boost::system::error_code& err, const std::string strValidatorsFile)
|
||||
{
|
||||
section secFile = ParseSection(strValidatorsFile, true);
|
||||
section::mapped_type* pmtEntries = sectionEntries(secFile, SECTION_VALIDATORS);
|
||||
|
||||
if (pmtEntries)
|
||||
processValidators(*pmtEntries);
|
||||
|
||||
getFinish();
|
||||
}
|
||||
|
||||
void UniqueNodeList::getIpsUrl()
|
||||
{
|
||||
std::string strDomain;
|
||||
std::string strPath;
|
||||
|
||||
if (!mStrIpsUrl.empty() && HttpsClient::httpsParseUrl(mStrIpsUrl, strDomain, strPath))
|
||||
{
|
||||
HttpsClient::httpsGet(
|
||||
theApp->getIOService(),
|
||||
strDomain,
|
||||
443,
|
||||
strPath,
|
||||
NODE_FILE_BYTES_MAX,
|
||||
boost::posix_time::seconds(NODE_FETCH_SECONDS),
|
||||
boost::bind(&UniqueNodeList::responseIps, this, _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
getValidatorsUrl();
|
||||
}
|
||||
}
|
||||
|
||||
void UniqueNodeList::getValidatorsUrl()
|
||||
{
|
||||
std::string strDomain;
|
||||
std::string strPath;
|
||||
|
||||
if (!mStrValidatorsUrl.empty() && HttpsClient::httpsParseUrl(mStrValidatorsUrl, strDomain, strPath))
|
||||
{
|
||||
HttpsClient::httpsGet(
|
||||
theApp->getIOService(),
|
||||
strDomain,
|
||||
443,
|
||||
strPath,
|
||||
NODE_FILE_BYTES_MAX,
|
||||
boost::posix_time::seconds(NODE_FETCH_SECONDS),
|
||||
boost::bind(&UniqueNodeList::responseValidators, this, _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
getFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void UniqueNodeList::getFinish()
|
||||
void UniqueNodeList::fetchFinish()
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mFetchLock);
|
||||
mFetchActive--;
|
||||
}
|
||||
|
||||
std::cerr << "Fetch active: " << mFetchActive << std::endl;
|
||||
fetchNext();
|
||||
}
|
||||
|
||||
void UniqueNodeList::responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile)
|
||||
void UniqueNodeList::processIps(const std::string& strSite, section::mapped_type* pmtVecStrIps)
|
||||
{
|
||||
std::cerr << "Fetch complete." << std::endl;
|
||||
std::cerr << "Error: " << err.message() << std::endl;
|
||||
std::cerr
|
||||
<< str(boost::format("Validator: '%s' processing %d ips.")
|
||||
% strSite % ( pmtVecStrIps ? pmtVecStrIps->size() : 0))
|
||||
<< std::endl;
|
||||
|
||||
section secSite = ParseSection(strSiteFile, true);
|
||||
bool bGood = !err;
|
||||
// XXX Do something with ips.
|
||||
}
|
||||
|
||||
//
|
||||
// Verify file domain
|
||||
//
|
||||
std::string strSite;
|
||||
void UniqueNodeList::processValidators(const std::string& strSite, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrValidators)
|
||||
{
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
|
||||
if (bGood)
|
||||
{
|
||||
bGood = sectionSingleB(secSite, SECTION_DOMAIN, strSite);
|
||||
if (strSite != strDomain)
|
||||
std::string strEscNodePublic = db->escape(naNodePublic.humanNodePublic());
|
||||
|
||||
std::cerr
|
||||
<< str(boost::format("Validator: '%s' processing %d validators.")
|
||||
% strSite % ( pmtVecStrValidators ? pmtVecStrValidators->size() : 0))
|
||||
<< std::endl;
|
||||
|
||||
// Remove all current entries Validator in ValidatorReferrals
|
||||
// XXX INDEX BY ValidatorReferralsIndex
|
||||
std::string strSql = str(boost::format("DELETE FROM ValidatorReferrals WHERE Validator=%s;")
|
||||
% strEscNodePublic);
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
db->executeSQL(strSql.c_str());
|
||||
// XXX Check result.
|
||||
|
||||
// Add new referral entries.
|
||||
if (pmtVecStrValidators->size()) {
|
||||
std::ostringstream ossValues;
|
||||
|
||||
int i = 0;
|
||||
BOOST_FOREACH(std::string strReferral, *pmtVecStrValidators)
|
||||
{
|
||||
bGood = false;
|
||||
if (i == REFERRAL_VALIDATORS_MAX)
|
||||
break;
|
||||
|
||||
std::cerr << "Warning: Site '" << strDomain << "' provides '" NODE_FILE_NAME "' for '" << strSite << "', ignoring." << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "Processing: Site '" << strDomain << "' '" NODE_FILE_NAME "'" << std::endl;
|
||||
ossValues <<
|
||||
str(boost::format("%s(%s,%d,%s)")
|
||||
% ( i ? "," : "") % strEscNodePublic % i % db->escape(strReferral));
|
||||
i++;
|
||||
|
||||
NewcoinAddress naValidator;
|
||||
|
||||
if (naValidator.setNodePublic(strReferral))
|
||||
{
|
||||
// A public key.
|
||||
// XXX Schedule for CAS lookup.
|
||||
}
|
||||
else
|
||||
{
|
||||
// A domain.
|
||||
nodeAddDomain(strReferral, vsReferral);
|
||||
}
|
||||
}
|
||||
|
||||
std::string strSql = str(boost::format("INSERT INTO ValidatorReferrals (Validator,Entry,Referral) VALUES %s;")
|
||||
% ossValues.str());
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
|
||||
db->executeSQL(strSql.c_str());
|
||||
// XXX Check result.
|
||||
}
|
||||
|
||||
//
|
||||
// Process public key
|
||||
//
|
||||
std::string strNodePublicKey;
|
||||
// XXX Set timer to cause rebuild.
|
||||
}
|
||||
|
||||
if (bGood && (bGood = sectionSingleB(secSite, SECTION_PUBLIC_KEY, strNodePublicKey)))
|
||||
void UniqueNodeList::responseIps(const std::string& strSite, const boost::system::error_code& err, const std::string strIpsFile)
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
NewcoinAddress naNodePublic;
|
||||
section secFile = ParseSection(strIpsFile, true);
|
||||
|
||||
if (naNodePublic.setNodePublic(strNodePublicKey))
|
||||
{
|
||||
std::cerr << strDomain << ": " << strNodePublicKey << std::endl;
|
||||
|
||||
nodeAdd(naNodePublic, strDomain);
|
||||
}
|
||||
processIps(strSite, sectionEntries(secFile, SECTION_IPS));
|
||||
}
|
||||
|
||||
fetchFinish();
|
||||
}
|
||||
|
||||
//
|
||||
// Process [ips_url]
|
||||
//
|
||||
void UniqueNodeList::getIpsUrl(section secSite)
|
||||
{
|
||||
std::string strIpsUrl;
|
||||
std::string strDomain;
|
||||
std::string strPath;
|
||||
|
||||
if (sectionSingleB(secSite, SECTION_IPS_URL, strIpsUrl)
|
||||
&& !strIpsUrl.empty()
|
||||
&& HttpsClient::httpsParseUrl(strIpsUrl, strDomain, strPath))
|
||||
{
|
||||
HttpsClient::httpsGet(
|
||||
theApp->getIOService(),
|
||||
strDomain,
|
||||
443,
|
||||
strPath,
|
||||
NODE_FILE_BYTES_MAX,
|
||||
boost::posix_time::seconds(NODE_FETCH_SECONDS),
|
||||
boost::bind(&UniqueNodeList::responseIps, this, strDomain, _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
fetchFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void UniqueNodeList::responseValidators(NewcoinAddress naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile)
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
section secFile = ParseSection(strValidatorsFile, true);
|
||||
|
||||
processValidators(strSite, naNodePublic, sectionEntries(secFile, SECTION_VALIDATORS));
|
||||
}
|
||||
|
||||
getIpsUrl(secSite);
|
||||
}
|
||||
|
||||
//
|
||||
// Process [validators_url]
|
||||
//
|
||||
void UniqueNodeList::getValidatorsUrl(NewcoinAddress naNodePublic, section secSite)
|
||||
{
|
||||
std::string strValidatorsUrl;
|
||||
std::string strDomain;
|
||||
std::string strPath;
|
||||
|
||||
if (sectionSingleB(secSite, SECTION_VALIDATORS_URL, strValidatorsUrl)
|
||||
&& !strValidatorsUrl.empty()
|
||||
&& HttpsClient::httpsParseUrl(strValidatorsUrl, strDomain, strPath))
|
||||
{
|
||||
HttpsClient::httpsGet(
|
||||
theApp->getIOService(),
|
||||
strDomain,
|
||||
443,
|
||||
strPath,
|
||||
NODE_FILE_BYTES_MAX,
|
||||
boost::posix_time::seconds(NODE_FETCH_SECONDS),
|
||||
boost::bind(&UniqueNodeList::responseValidators, this, naNodePublic, secSite, strDomain, _1, _2));
|
||||
}
|
||||
else
|
||||
{
|
||||
getIpsUrl(secSite);
|
||||
}
|
||||
}
|
||||
|
||||
// Process a newcoin.txt.
|
||||
void UniqueNodeList::processFile(const std::string strDomain, NewcoinAddress naNodePublic, section secSite)
|
||||
{
|
||||
//
|
||||
// Process Validators
|
||||
//
|
||||
processValidators(strDomain, naNodePublic, sectionEntries(secSite, SECTION_VALIDATORS));
|
||||
|
||||
//
|
||||
// Process ips
|
||||
//
|
||||
section::mapped_type* pvIps;
|
||||
|
||||
if (bGood && (pvIps = sectionEntries(secSite, SECTION_IPS)) && pvIps->size())
|
||||
{
|
||||
std::cerr << "Ips: " << pvIps->size() << std::endl;
|
||||
|
||||
processIps(*pvIps);
|
||||
}
|
||||
|
||||
//
|
||||
// Process ips_url
|
||||
//
|
||||
if (bGood)
|
||||
(void) sectionSingleB(secSite, SECTION_IPS_URL, mStrIpsUrl);
|
||||
|
||||
//
|
||||
// Process Validators
|
||||
//
|
||||
section::mapped_type* pvValidators;
|
||||
|
||||
if (bGood && (pvValidators = sectionEntries(secSite, SECTION_VALIDATORS)) && pvValidators->size())
|
||||
{
|
||||
processValidators(*pvValidators);
|
||||
}
|
||||
|
||||
//
|
||||
// Process validators_url
|
||||
//
|
||||
|
||||
if (bGood)
|
||||
(void) sectionSingleB(secSite, SECTION_VALIDATORS_URL, mStrValidatorsUrl);
|
||||
processIps(strDomain, sectionEntries(secSite, SECTION_IPS));
|
||||
|
||||
//
|
||||
// Process currencies
|
||||
//
|
||||
section::mapped_type* pvCurrencies;
|
||||
|
||||
if (bGood && (pvCurrencies = sectionEntries(secSite, SECTION_CURRENCIES)) && pvCurrencies->size())
|
||||
if ((pvCurrencies = sectionEntries(secSite, SECTION_CURRENCIES)) && pvCurrencies->size())
|
||||
{
|
||||
// XXX Process currencies.
|
||||
std::cerr << "Ignoring currencies: not implemented." << std::endl;
|
||||
}
|
||||
|
||||
getIpsUrl();
|
||||
getValidatorsUrl(naNodePublic, secSite);
|
||||
}
|
||||
|
||||
void UniqueNodeList::responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile)
|
||||
{
|
||||
section secSite = ParseSection(strSiteFile, true);
|
||||
bool bGood = !err;
|
||||
|
||||
if (bGood)
|
||||
{
|
||||
std::cerr << boost::format("Validator: '%s' received " NODE_FILE_NAME ".") % strDomain << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr
|
||||
<< boost::format("Validator: '%s' unabile to retrieve " NODE_FILE_NAME ": %s")
|
||||
% strDomain
|
||||
% err.message()
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify file domain
|
||||
//
|
||||
std::string strSite;
|
||||
|
||||
if (bGood && !sectionSingleB(secSite, SECTION_DOMAIN, strSite))
|
||||
{
|
||||
bGood = false;
|
||||
|
||||
std::cerr
|
||||
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " missing single entry for " SECTION_DOMAIN ".")
|
||||
% strDomain
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (bGood && strSite != strDomain)
|
||||
{
|
||||
bGood = false;
|
||||
|
||||
std::cerr
|
||||
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_DOMAIN " does not match: %s")
|
||||
% strDomain
|
||||
% strSite
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
//
|
||||
// Process public key
|
||||
//
|
||||
std::string strNodePublicKey;
|
||||
|
||||
if (bGood && !sectionSingleB(secSite, SECTION_PUBLIC_KEY, strNodePublicKey))
|
||||
{
|
||||
// Bad [validation_public_key] section.
|
||||
bGood = false;
|
||||
|
||||
std::cerr
|
||||
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " does not have single entry.")
|
||||
% strDomain
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
NewcoinAddress naNodePublic;
|
||||
|
||||
if (bGood && !naNodePublic.setNodePublic(strNodePublicKey))
|
||||
{
|
||||
// Bad public key.
|
||||
bGood = false;
|
||||
|
||||
std::cerr
|
||||
<< boost::format("Validator: '%s' bad " NODE_FILE_NAME " " SECTION_PUBLIC_KEY " is bad: ")
|
||||
% strDomain
|
||||
% strNodePublicKey
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (bGood)
|
||||
{
|
||||
// std::cerr << boost::format("naNodePublic: '%s'") % naNodePublic.humanNodePublic() << std::endl;
|
||||
|
||||
seedDomain sdCurrent;
|
||||
|
||||
bool bFound = getSeedDomans(strDomain, sdCurrent);
|
||||
|
||||
assert(bFound);
|
||||
|
||||
uint256 iSha256 = Serializer::getSHA512Half(strSiteFile);
|
||||
bool bChangedB = sdCurrent.iSha256 != iSha256;
|
||||
|
||||
sdCurrent.strDomain = strDomain;
|
||||
// XXX If the node public key is changing, delete old public key information?
|
||||
// XXX Only if no other refs to keep it arround, other wise we have an attack vector.
|
||||
sdCurrent.naPublicKey = naNodePublic;
|
||||
|
||||
// std::cerr << boost::format("sdCurrent.naPublicKey: '%s'") % sdCurrent.naPublicKey.humanNodePublic() << std::endl;
|
||||
|
||||
sdCurrent.tpFetch = boost::posix_time::second_clock::universal_time();
|
||||
sdCurrent.iSha256 = iSha256;
|
||||
|
||||
setSeedDomans(sdCurrent);
|
||||
|
||||
if (bChangedB)
|
||||
{
|
||||
std::cerr << boost::format("Validator: '%s' processing new " NODE_FILE_NAME ".") % strDomain << std::endl;
|
||||
processFile(strDomain, naNodePublic, secSite);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << boost::format("Validator: '%s' no change for " NODE_FILE_NAME ".") % strDomain << std::endl;
|
||||
fetchFinish();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Failed: Update
|
||||
|
||||
// XXX If we have public key, perhaps try look up in CAS?
|
||||
fetchFinish();
|
||||
}
|
||||
}
|
||||
|
||||
// Get the newcoin.txt and process it.
|
||||
@@ -211,15 +365,9 @@ void UniqueNodeList::fetchProcess(std::string strDomain)
|
||||
{
|
||||
std::cerr << "Fetching '" NODE_FILE_NAME "' from '" << strDomain << "'." << std::endl;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mFetchLock);
|
||||
mFetchActive++;
|
||||
}
|
||||
|
||||
std::deque<std::string> deqSites;
|
||||
|
||||
std::ostringstream ossNewcoin;
|
||||
std::ostringstream ossWeb;
|
||||
std::ostringstream ossNewcoin;
|
||||
std::ostringstream ossWeb;
|
||||
|
||||
ossNewcoin << SYSTEM_NAME "." << strDomain;
|
||||
ossWeb << "www." << strDomain;
|
||||
@@ -238,40 +386,234 @@ void UniqueNodeList::fetchProcess(std::string strDomain)
|
||||
boost::bind(&UniqueNodeList::responseFetch, this, strDomain, _1, _2));
|
||||
}
|
||||
|
||||
void UniqueNodeList::fetchTimerHandler(const boost::system::error_code& err)
|
||||
{
|
||||
if (!err)
|
||||
{
|
||||
// Time to check for another fetch.
|
||||
std::cerr << "fetchTimerHandler" << std::endl;
|
||||
fetchNext();
|
||||
}
|
||||
}
|
||||
|
||||
// Try to process the next fetch.
|
||||
void UniqueNodeList::fetchNext()
|
||||
{
|
||||
bool work;
|
||||
std::string strDomain;
|
||||
bool bFull;
|
||||
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mFetchLock);
|
||||
work = mFetchActive != NODE_FETCH_JOBS && !mFetchPending.empty();
|
||||
if (work) {
|
||||
strDomain = mFetchPending.front();
|
||||
mFetchPending.pop_front();
|
||||
}
|
||||
|
||||
bFull = mFetchActive == NODE_FETCH_JOBS;
|
||||
}
|
||||
|
||||
if (!strDomain.empty())
|
||||
if (!bFull)
|
||||
{
|
||||
fetchProcess(strDomain);
|
||||
// Determine next scan.
|
||||
std::string strSql("SELECT Domain,Next FROM SeedDomains ORDER BY Next ASC LIMIT 1;");
|
||||
std::string strDomain;
|
||||
boost::posix_time::ptime tpNext;
|
||||
boost::posix_time::ptime tpNow;
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database *db=theApp->getWalletDB()->getDB();
|
||||
|
||||
if (db->executeSQL(strSql.c_str()) && db->startIterRows())
|
||||
{
|
||||
int iNext = db->getInt("Next");
|
||||
|
||||
tpNext = ptFromSeconds(iNext);
|
||||
tpNow = boost::posix_time::second_clock::universal_time();
|
||||
|
||||
db->getStr("Domain", strDomain);
|
||||
|
||||
db->endIterRows();
|
||||
}
|
||||
|
||||
if (!strDomain.empty())
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mFetchLock);
|
||||
|
||||
bFull = mFetchActive == NODE_FETCH_JOBS;
|
||||
|
||||
if (!bFull && tpNext <= tpNow) {
|
||||
mFetchActive++;
|
||||
}
|
||||
}
|
||||
|
||||
if (strDomain.empty() || bFull)
|
||||
{
|
||||
// nothing();
|
||||
}
|
||||
else if (tpNext > tpNow)
|
||||
{
|
||||
// Fetch needs to happen in the future. Set a timer to wake us.
|
||||
mtpFetchNext = tpNext;
|
||||
|
||||
mdtFetchTimer.expires_at(mtpFetchNext);
|
||||
mdtFetchTimer.async_wait(boost::bind(&UniqueNodeList::fetchTimerHandler, this, _1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fetch needs to happen now.
|
||||
mtpFetchNext = boost::posix_time::ptime(boost::posix_time::not_a_date_time);
|
||||
|
||||
seedDomain sdCurrent;
|
||||
bool bFound = getSeedDomans(strDomain, sdCurrent);
|
||||
|
||||
assert(bFound);
|
||||
|
||||
// Update time of next fetch and this scan attempt.
|
||||
sdCurrent.tpScan = tpNow;
|
||||
|
||||
// XXX Use a longer duration if we have lots of validators.
|
||||
sdCurrent.tpNext = sdCurrent.tpScan+boost::posix_time::hours(7*24);
|
||||
|
||||
setSeedDomans(sdCurrent);
|
||||
|
||||
std::cerr << "Validator: '" << strDomain << "' fetching " NODE_FILE_NAME "." << std::endl;
|
||||
|
||||
fetchProcess(strDomain); // Go get it.
|
||||
|
||||
fetchNext(); // Look for more.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get newcoin.txt from a domain's web server.
|
||||
void UniqueNodeList::nodeFetch(std::string strDomain)
|
||||
int UniqueNodeList::iSourceScore(validatorSource vsWhy)
|
||||
{
|
||||
{
|
||||
boost::mutex::scoped_lock sl(mFetchLock);
|
||||
int iScore = 0;
|
||||
|
||||
mFetchPending.push_back(strDomain);
|
||||
switch (vsWhy) {
|
||||
case vsManual: iScore = 1500; 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.");
|
||||
}
|
||||
|
||||
fetchNext();
|
||||
return iScore;
|
||||
}
|
||||
|
||||
// Queue a domain for a single attempt fetch a newcoin.txt.
|
||||
// --> strComment: only used on vsManual
|
||||
// YYY As a lot of these may happen at once, would be nice to wrap multiple calls in a transaction.
|
||||
void UniqueNodeList::nodeAddDomain(std::string strDomain, validatorSource vsWhy, std::string strComment)
|
||||
{
|
||||
// YYY Would be best to verify strDomain is a valid domain.
|
||||
seedDomain sdCurrent;
|
||||
|
||||
bool bFound = getSeedDomans(strDomain, sdCurrent);
|
||||
bool bChanged = false;
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
sdCurrent.strDomain = strDomain;
|
||||
sdCurrent.tpNext = boost::posix_time::second_clock::universal_time();
|
||||
}
|
||||
|
||||
// Promote source, if needed.
|
||||
if (!bFound || iSourceScore(vsWhy) >= iSourceScore(sdCurrent.vsSource))
|
||||
{
|
||||
sdCurrent.vsSource = vsWhy;
|
||||
bChanged = true;
|
||||
}
|
||||
|
||||
if (vsManual == vsWhy)
|
||||
{
|
||||
// A manual add forces immediate scan.
|
||||
sdCurrent.tpNext = boost::posix_time::second_clock::universal_time();
|
||||
sdCurrent.strComment = strComment;
|
||||
bChanged = true;
|
||||
}
|
||||
|
||||
if (bChanged)
|
||||
setSeedDomans(sdCurrent);
|
||||
}
|
||||
|
||||
bool UniqueNodeList::getSeedDomans(const std::string& strDomain, seedDomain& dstSeedDomain)
|
||||
{
|
||||
bool bResult;
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
|
||||
std::string strSql = str(boost::format("SELECT * FROM SeedDomains WHERE Domain=%s;")
|
||||
% db->escape(strDomain));
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
|
||||
bResult = db->executeSQL(strSql.c_str()) && db->startIterRows();
|
||||
if (bResult)
|
||||
{
|
||||
std::string strPublicKey;
|
||||
std::string strSource;
|
||||
int iNext;
|
||||
int iScan;
|
||||
int iFetch;
|
||||
std::string strSha256;
|
||||
|
||||
db->getStr("Domain", dstSeedDomain.strDomain);
|
||||
|
||||
if (!db->getNull("PublicKey") && db->getStr("PublicKey", strPublicKey))
|
||||
{
|
||||
dstSeedDomain.naPublicKey.setNodePublic(strPublicKey);
|
||||
}
|
||||
else
|
||||
{
|
||||
dstSeedDomain.naPublicKey.clear();
|
||||
}
|
||||
|
||||
db->getStr("Source", strSource);
|
||||
dstSeedDomain.vsSource = static_cast<validatorSource>(strSource[0]);
|
||||
iNext = db->getInt("Next");
|
||||
dstSeedDomain.tpNext = ptFromSeconds(iNext);
|
||||
iScan = db->getInt("Scan");
|
||||
dstSeedDomain.tpScan = ptFromSeconds(iScan);
|
||||
iFetch = db->getInt("Fetch");
|
||||
dstSeedDomain.tpFetch = ptFromSeconds(iFetch);
|
||||
db->getStr("Sha256", strSha256);
|
||||
dstSeedDomain.iSha256.SetHex(strSha256.c_str());
|
||||
db->getStr("Comment", dstSeedDomain.strComment);
|
||||
|
||||
db->endIterRows();
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
|
||||
void UniqueNodeList::setSeedDomans(const seedDomain& sdSource)
|
||||
{
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
|
||||
int iNext = iToSeconds(sdSource.tpNext);
|
||||
int iScan = iToSeconds(sdSource.tpScan);
|
||||
int iFetch = iToSeconds(sdSource.tpFetch);
|
||||
|
||||
std::string strSql = str(boost::format("REPLACE INTO SeedDomains (Domain,PublicKey,Source,Next,Scan,Fetch,Sha256,Comment) VALUES (%s, %s, %s, %d, %d, %d, '%s', %s);")
|
||||
% db->escape(sdSource.strDomain)
|
||||
% (sdSource.naPublicKey.IsValid() ? db->escape(sdSource.naPublicKey.humanNodePublic()) : "NULL")
|
||||
% db->escape(std::string(1, static_cast<char>(sdSource.vsSource)))
|
||||
% iNext
|
||||
% iScan
|
||||
% iFetch
|
||||
% sdSource.iSha256.GetHex()
|
||||
% db->escape(sdSource.strComment)
|
||||
);
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
|
||||
db->executeSQL(strSql.c_str());
|
||||
// XXX Check result.
|
||||
|
||||
if (mtpFetchNext.is_not_a_date_time() || mtpFetchNext > sdSource.tpNext)
|
||||
{
|
||||
// Schedule earlier wake up.
|
||||
fetchNext();
|
||||
}
|
||||
}
|
||||
|
||||
// XXX allow update of comment.
|
||||
void UniqueNodeList::nodeAdd(NewcoinAddress naNodePublic, std::string strComment)
|
||||
void UniqueNodeList::nodeAddPublic(NewcoinAddress naNodePublic, std::string strComment)
|
||||
{
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
|
||||
@@ -279,11 +621,9 @@ void UniqueNodeList::nodeAdd(NewcoinAddress naNodePublic, std::string strComment
|
||||
std::string strTmp;
|
||||
|
||||
std::string strSql="INSERT INTO TrustedNodes (PublicKey,Comment) values (";
|
||||
db->escape(reinterpret_cast<const unsigned char*>(strPublicKey.c_str()), strPublicKey.size(), strTmp);
|
||||
strSql.append(strTmp);
|
||||
strSql.append(db->escape(strPublicKey));
|
||||
strSql.append(",");
|
||||
db->escape(reinterpret_cast<const unsigned char*>(strComment.c_str()), strComment.size(), strTmp);
|
||||
strSql.append(strTmp);
|
||||
strSql.append(db->escape(strComment));
|
||||
strSql.append(")");
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
@@ -314,33 +654,6 @@ void UniqueNodeList::nodeReset()
|
||||
db->executeSQL(strSql.c_str());
|
||||
}
|
||||
|
||||
// 0- we don't care, 1- we care and is valid, 2-invalid signature
|
||||
#if 0
|
||||
int UniqueNodeList::checkValid(newcoin::Validation& valid)
|
||||
{
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
std::string strSql="SELECT pubkey from TrustedNodes where hanko=";
|
||||
std::string hashStr;
|
||||
db->escape((unsigned char*) &(valid.hanko()[0]),valid.hanko().size(),hashStr);
|
||||
strSql.append(hashStr);
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
if( db->executeSQL(strSql.c_str()) )
|
||||
{
|
||||
if(db->startIterRows() && db->getNextRow())
|
||||
{
|
||||
//theApp->getDB()->getBytes();
|
||||
|
||||
// TODO: check that the public key makes the correct signature of the validation
|
||||
db->endIterRows();
|
||||
return(1);
|
||||
}
|
||||
else db->endIterRows();
|
||||
}
|
||||
return(0); // not on our list
|
||||
}
|
||||
#endif
|
||||
|
||||
Json::Value UniqueNodeList::getUnlJson()
|
||||
{
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
@@ -384,7 +697,7 @@ void UniqueNodeList::nodeDefault(std::string strValidators) {
|
||||
{
|
||||
BOOST_FOREACH(std::string strValidator, *pmtEntries)
|
||||
{
|
||||
nodeFetch(strValidator);
|
||||
nodeAddDomain(strValidator, vsValidator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,40 +23,66 @@
|
||||
|
||||
class UniqueNodeList
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
vsManual = 'M',
|
||||
vsValidator = 'V', // validators.txt
|
||||
vsWeb = 'W',
|
||||
vsReferral = 'R',
|
||||
} validatorSource;
|
||||
|
||||
private:
|
||||
typedef struct {
|
||||
std::string strDomain;
|
||||
NewcoinAddress naPublicKey;
|
||||
validatorSource vsSource;
|
||||
boost::posix_time::ptime tpNext;
|
||||
boost::posix_time::ptime tpScan;
|
||||
boost::posix_time::ptime tpFetch;
|
||||
uint256 iSha256;
|
||||
std::string strComment;
|
||||
} seedDomain;
|
||||
|
||||
int iSourceScore(validatorSource vsWhy);
|
||||
|
||||
void responseFetch(const std::string strDomain, const boost::system::error_code& err, const std::string strSiteFile);
|
||||
|
||||
boost::mutex mFetchLock;
|
||||
int mFetchActive; // count of active fetches
|
||||
std::deque<std::string> mFetchPending;
|
||||
boost::mutex mFetchLock;
|
||||
int mFetchActive; // count of active fetches
|
||||
|
||||
std::string mStrIpsUrl;
|
||||
std::string mStrValidatorsUrl;
|
||||
boost::posix_time::ptime mtpFetchNext;
|
||||
boost::asio::deadline_timer mdtFetchTimer;
|
||||
|
||||
void fetchNext();
|
||||
void fetchFinish();
|
||||
void fetchProcess(std::string strDomain);
|
||||
void fetchTimerHandler(const boost::system::error_code& err);
|
||||
|
||||
void getValidatorsUrl();
|
||||
void getIpsUrl();
|
||||
void getFinish();
|
||||
void responseIps(const boost::system::error_code& err, const std::string strIpsFile);
|
||||
void responseValidators(const boost::system::error_code& err, const std::string strValidatorsFile);
|
||||
void getValidatorsUrl(NewcoinAddress naNodePublic, section secSite);
|
||||
void getIpsUrl(section secSite);
|
||||
void responseIps(const std::string& strSite, const boost::system::error_code& err, const std::string strIpsFile);
|
||||
void responseValidators(NewcoinAddress naNodePublic, section secSite, const std::string& strSite, const boost::system::error_code& err, const std::string strValidatorsFile);
|
||||
|
||||
void processIps(section::mapped_type& vecStrIps);
|
||||
void processValidators(section::mapped_type& vecStrValidators);
|
||||
void processIps(const std::string& strSite, section::mapped_type* pmtVecStrIps);
|
||||
void processValidators(const std::string& strSite, NewcoinAddress naNodePublic, section::mapped_type* pmtVecStrValidators);
|
||||
|
||||
void processFile(const std::string strDomain, NewcoinAddress naNodePublic, section secSite);
|
||||
|
||||
bool getSeedDomans(const std::string& strDomain, seedDomain& dstSeedDomain);
|
||||
void setSeedDomans(const seedDomain& dstSeedDomain);
|
||||
|
||||
public:
|
||||
UniqueNodeList();
|
||||
UniqueNodeList(boost::asio::io_service& io_service);
|
||||
|
||||
void nodeAdd(NewcoinAddress naNodePublic, std::string strComment);
|
||||
void nodeFetch(std::string strDomain);
|
||||
// Begin processing.
|
||||
void start();
|
||||
|
||||
void nodeAddPublic(NewcoinAddress naNodePublic, std::string strComment);
|
||||
void nodeAddDomain(std::string strDomain, validatorSource vsWhy, std::string strComment="");
|
||||
void nodeRemove(NewcoinAddress naNodePublic);
|
||||
void nodeDefault(std::string strValidators);
|
||||
void nodeReset();
|
||||
|
||||
// 2- we don't care, 1- we care and is valid, 2-invalid signature
|
||||
// int checkValid(newcoin::Validation& valid);
|
||||
|
||||
Json::Value getUnlJson();
|
||||
};
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include "openssl/ec.h"
|
||||
|
||||
#include "boost/foreach.hpp"
|
||||
#include "boost/lexical_cast.hpp"
|
||||
#include "boost/interprocess/sync/scoped_lock.hpp"
|
||||
#include "boost/make_shared.hpp"
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/interprocess/sync/scoped_lock.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
#include "Wallet.h"
|
||||
#include "Ledger.h"
|
||||
@@ -244,6 +244,10 @@ LocalAccount::pointer LocalAccountFamily::get(int seq)
|
||||
return ret;
|
||||
}
|
||||
|
||||
Wallet::Wallet() : mLedger(0) {
|
||||
mPtScoresUpdated = boost::posix_time::from_time_t(0);
|
||||
}
|
||||
|
||||
NewcoinAddress Wallet::addFamily(const NewcoinAddress& familySeed, bool lock)
|
||||
{
|
||||
LocalAccountFamily::pointer fam(doPrivate(familySeed, true, !lock));
|
||||
@@ -330,12 +334,67 @@ Json::Value Wallet::getFamilyJson(const NewcoinAddress& family)
|
||||
return fit->second->getJson();
|
||||
}
|
||||
|
||||
void Wallet::start()
|
||||
{
|
||||
miscLoad();
|
||||
|
||||
struct tm tmScoresUpdated = to_tm(mPtScoresUpdated);
|
||||
time_t ttScoresUpdated = mktime(&tmScoresUpdated);
|
||||
|
||||
std::cerr << "Validator scores updated: "
|
||||
<< (ttScoresUpdated
|
||||
? "Never"
|
||||
: boost::posix_time::to_simple_string(mPtScoresUpdated)
|
||||
)
|
||||
<< std::endl;
|
||||
|
||||
theApp->getUNL().start();
|
||||
}
|
||||
|
||||
bool Wallet::miscLoad()
|
||||
{
|
||||
std::string strSql("SELECT * FROM Misc;");
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database *db=theApp->getWalletDB()->getDB();
|
||||
|
||||
if(!db->executeSQL(strSql.c_str())) return false;
|
||||
if(!db->startIterRows()) return false;
|
||||
|
||||
time_t ttScoresUpdated = db->getInt("ScoresUpdated");
|
||||
|
||||
mPtScoresUpdated = boost::posix_time::from_time_t(ttScoresUpdated);
|
||||
|
||||
db->endIterRows();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::miscSave()
|
||||
{
|
||||
struct tm tmScoresUpdated = to_tm(mPtScoresUpdated);
|
||||
time_t ttScoresUpdated = mktime(&tmScoresUpdated);
|
||||
std::string strScoresUpdate = boost::lexical_cast<std::string>(ttScoresUpdated);
|
||||
|
||||
std::string strSql("REPLACE INTO Misc (ScoresUpdated) VALUES (");
|
||||
// Should be a parameter.
|
||||
strSql.append(strScoresUpdate);
|
||||
strSql.append(");");
|
||||
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
|
||||
db->executeSQL(strSql.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Wallet::nodeIdentityLoad()
|
||||
{
|
||||
std::string strSql("SELECT * FROM NodeIdentity;");
|
||||
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
Database *db=theApp->getWalletDB()->getDB();
|
||||
Database* db=theApp->getWalletDB()->getDB();
|
||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||
|
||||
if(!db->executeSQL(strSql.c_str())) return false;
|
||||
if(!db->startIterRows()) return false;
|
||||
|
||||
13
src/Wallet.h
13
src/Wallet.h
@@ -5,6 +5,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
@@ -25,6 +26,12 @@ private:
|
||||
bool nodeIdentityLoad();
|
||||
bool nodeIdentityCreate();
|
||||
|
||||
// Misc persistent information
|
||||
boost::posix_time::ptime mPtScoresUpdated;
|
||||
|
||||
bool miscLoad();
|
||||
bool miscSave();
|
||||
|
||||
protected:
|
||||
boost::recursive_mutex mLock;
|
||||
|
||||
@@ -43,7 +50,11 @@ protected:
|
||||
// void addFamily(const NewcoinAddress& family, const std::string& pubKey, int seq, const std::string& name, const std::string& comment);
|
||||
|
||||
public:
|
||||
Wallet() : mLedger(0) { ; }
|
||||
Wallet();
|
||||
|
||||
// Begin processing.
|
||||
// - Maintain peer connectivity through validation and peer management.
|
||||
void start();
|
||||
|
||||
NewcoinAddress addFamily(const std::string& passPhrase, bool lock);
|
||||
NewcoinAddress addFamily(const NewcoinAddress& familySeed, bool lock);
|
||||
|
||||
@@ -36,7 +36,7 @@ void printHelp()
|
||||
cout << " sendto <destination> <amount> [<tag>]" << endl;
|
||||
cout << " stop" << endl;
|
||||
cout << " tx" << endl;
|
||||
cout << " unl_add <public> [<comment>]" << endl;
|
||||
cout << " unl_add <domain>|<public> [<comment>]" << endl;
|
||||
cout << " unl_delete <public_key>" << endl;
|
||||
cout << " unl_list" << endl;
|
||||
cout << " unl_reset" << endl;
|
||||
|
||||
Reference in New Issue
Block a user