mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Merge NewcoinAddress.
This commit is contained in:
@@ -100,50 +100,59 @@ bool Database::getColNumber(const char* colName,int* retIndex)
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
int Database::getSingleDBValueInt(const char* sql)
|
int Database::getSingleDBValueInt(const char* sql)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
if( executeSQL(sql) && startIterRows() && getNextRow())
|
if( executeSQL(sql) && startIterRows()
|
||||||
{
|
{
|
||||||
ret=getInt(0);
|
ret=getInt(0);
|
||||||
endIterRows();
|
endIterRows();
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//theUI->statusMsg("ERROR with database: %s",sql);
|
//theUI->statusMsg("ERROR with database: %s",sql);
|
||||||
ret=0;
|
ret=0;
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
float Database::getSingleDBValueFloat(const char* sql)
|
float Database::getSingleDBValueFloat(const char* sql)
|
||||||
{
|
{
|
||||||
float ret;
|
float ret;
|
||||||
if( executeSQL(sql) && startIterRows() && getNextRow())
|
if(executeSQL(sql) && startIterRows() && getNextRow())
|
||||||
{
|
{
|
||||||
ret=getFloat(0);
|
ret=getFloat(0);
|
||||||
endIterRows();
|
endIterRows();
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//theUI->statusMsg("ERROR with database: %s",sql);
|
//theUI->statusMsg("ERROR with database: %s",sql);
|
||||||
ret=0;
|
ret=0;
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
char* Database::getSingleDBValueStr(const char* sql,std::string& retStr)
|
char* Database::getSingleDBValueStr(const char* sql,std::string& retStr)
|
||||||
{
|
{
|
||||||
char* ret;
|
char* ret;
|
||||||
if( executeSQL(sql) && startIterRows() && getNextRow())
|
if(executeSQL(sql) && startIterRows())
|
||||||
{
|
{
|
||||||
ret=getStr(0,retStr);
|
ret=getStr(0,retStr);
|
||||||
endIterRows();
|
endIterRows();
|
||||||
}else
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
//theUI->statusMsg("ERROR with database: %s",sql);
|
//theUI->statusMsg("ERROR with database: %s",sql);
|
||||||
ret=0;
|
ret=0;
|
||||||
}
|
}
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string Database::escape(const std::string strValue)
|
std::string Database::escape(const std::string strValue)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,10 +69,9 @@ public:
|
|||||||
virtual int getBinary(int colIndex,unsigned char* buf,int maxSize)=0;
|
virtual int getBinary(int colIndex,unsigned char* buf,int maxSize)=0;
|
||||||
virtual uint64 getBigInt(int colIndex)=0;
|
virtual uint64 getBigInt(int colIndex)=0;
|
||||||
|
|
||||||
int getSingleDBValueInt(const char* sql);
|
// int getSingleDBValueInt(const char* sql);
|
||||||
float getSingleDBValueFloat(const char* sql);
|
// float getSingleDBValueFloat(const char* sql);
|
||||||
char* getSingleDBValueStr(const char* sql, std::string& retStr);
|
// char* getSingleDBValueStr(const char* sql, std::string& retStr);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,11 @@ public:
|
|||||||
typedef boost::shared_ptr<AccountState> pointer;
|
typedef boost::shared_ptr<AccountState> pointer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NewcoinAddress mAccountID;
|
NewcoinAddress mAccountID;
|
||||||
SerializedLedgerEntry::pointer mLedgerEntry;
|
NewcoinAddress mAuthorizedKey;
|
||||||
bool mValid;
|
SerializedLedgerEntry::pointer mLedgerEntry;
|
||||||
|
|
||||||
|
bool mValid;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AccountState(const NewcoinAddress& AccountID); // For new accounts
|
AccountState(const NewcoinAddress& AccountID); // For new accounts
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ DatabaseCon::DatabaseCon(const std::string& name, const char *initStrings[], int
|
|||||||
std::string path=strprintf("%s%s", theConfig.DATA_DIR.c_str(), name.c_str());
|
std::string path=strprintf("%s%s", theConfig.DATA_DIR.c_str(), name.c_str());
|
||||||
mDatabase=new SqliteDatabase(path.c_str());
|
mDatabase=new SqliteDatabase(path.c_str());
|
||||||
mDatabase->connect();
|
mDatabase->connect();
|
||||||
for(int i=0; i<initCount; i++)
|
for(int i = 0; i < initCount; ++i)
|
||||||
mDatabase->executeSQL(initStrings[i], true);
|
mDatabase->executeSQL(initStrings[i], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,11 +41,9 @@ DatabaseCon::~DatabaseCon()
|
|||||||
delete mDatabase;
|
delete mDatabase;
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application() :
|
Application::Application() : mNetOps(mIOService), mUNL(mIOService),
|
||||||
mUNL(mIOService),
|
|
||||||
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
|
||||||
mConnectionPool(mIOService),
|
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
|
||||||
mPeerDoor(NULL), mRPCDoor(NULL)
|
|
||||||
{
|
{
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
@@ -57,7 +55,7 @@ void Application::stop()
|
|||||||
{
|
{
|
||||||
mIOService.stop();
|
mIOService.stop();
|
||||||
|
|
||||||
std::cerr << "Stopped: " << mIOService.stopped() << std::endl;
|
std::cerr << "Stopped: " << mIOService.stopped() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::run()
|
void Application::run()
|
||||||
@@ -82,43 +80,96 @@ void Application::run()
|
|||||||
//
|
//
|
||||||
// Allow peer connections.
|
// Allow peer connections.
|
||||||
//
|
//
|
||||||
if(theConfig.PEER_PORT)
|
if(!theConfig.PEER_IP.empty() && theConfig.PEER_PORT)
|
||||||
{
|
{
|
||||||
mPeerDoor=new PeerDoor(mIOService);
|
mPeerDoor=new PeerDoor(mIOService);
|
||||||
}//else BOOST_LOG_TRIVIAL(info) << "No Peer Port set. Not listening for connections.";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Peer interface: disabled" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Allow RPC connections.
|
// Allow RPC connections.
|
||||||
//
|
//
|
||||||
if(theConfig.RPC_PORT)
|
if(!theConfig.RPC_IP.empty() && theConfig.RPC_PORT)
|
||||||
{
|
{
|
||||||
mRPCDoor=new RPCDoor(mIOService);
|
mRPCDoor=new RPCDoor(mIOService);
|
||||||
}//else BOOST_LOG_TRIVIAL(info) << "No RPC Port set. Not listening for commands.";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "RPC interface: disabled" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Begin connectting to network.
|
// Begin connecting to network.
|
||||||
//
|
//
|
||||||
mConnectionPool.start();
|
mConnectionPool.start();
|
||||||
|
|
||||||
mTimingService.start(mIOService);
|
// New stuff.
|
||||||
|
NewcoinAddress rootSeedMaster;
|
||||||
|
NewcoinAddress rootGeneratorMaster;
|
||||||
|
NewcoinAddress rootAddress;
|
||||||
|
|
||||||
|
rootSeedMaster.setFamilySeed(CKey::PassPhraseToKey("Master passphrase."));
|
||||||
|
rootGeneratorMaster.setFamilyGenerator(rootSeedMaster);
|
||||||
|
|
||||||
|
rootAddress.setAccountPublic(rootGeneratorMaster, 0);
|
||||||
|
|
||||||
|
std::cerr << "Master seed: " << rootSeedMaster.humanFamilySeed() << std::endl;
|
||||||
|
std::cerr << "Master generator: " << rootGeneratorMaster.humanFamilyGenerator() << std::endl;
|
||||||
|
std::cerr << "Root address: " << rootAddress.humanAccountPublic() << std::endl;
|
||||||
|
#if 0
|
||||||
|
NewcoinAddress rootSeedRegular;
|
||||||
|
NewcoinAddress rootGeneratorRegular;
|
||||||
|
NewcoinAddress reservedPublicRegular;
|
||||||
|
NewcoinAddress reservedPrivateRegular;
|
||||||
|
|
||||||
|
rootSeedRegular.setFamilySeed(CKey::PassPhraseToKey("Regular passphrase."));
|
||||||
|
rootGeneratorRegular.setFamilyGenerator(rootSeedRegular);
|
||||||
|
|
||||||
|
reservedPublicRegular.setAccountPublic(rootGeneratorRegular, -1);
|
||||||
|
reservedPrivateRegular.setAccountPrivate(rootGeneratorRegular, rootSeedRegular, -1);
|
||||||
|
|
||||||
|
// hash of regular account #reserved public key.
|
||||||
|
uint160 uiGeneratorID = reservedPublicRegular.getAccountID();
|
||||||
|
|
||||||
|
// std::cerr << "uiGeneratorID: " << uiGeneratorID << std::endl;
|
||||||
|
|
||||||
|
// Encrypt with regular account #reserved private key.
|
||||||
|
std::vector<unsigned char> vucGeneratorCipher = reservedPrivateRegular.accountPrivateEncrypt(reservedPublicRegular, rootGeneratorMaster.getFamilyGenerator());
|
||||||
|
|
||||||
|
std::cerr << "Plain: " << strHex(rootGeneratorMaster.getFamilyGenerator()) << std::endl;
|
||||||
|
|
||||||
|
std::cerr << "Cipher: " << strHex(vucGeneratorCipher) << std::endl;
|
||||||
|
|
||||||
|
std::vector<unsigned char> vucGeneratorText = reservedPrivateRegular.accountPrivateDecrypt(reservedPublicRegular, vucGeneratorCipher);
|
||||||
|
|
||||||
|
std::cerr << "Plain: " << strHex(vucGeneratorText) << std::endl;
|
||||||
|
std::cerr << "Regular seed: " << rootSeedRegular.humanFamilySeed() << std::endl;
|
||||||
|
std::cerr << "Regular generator: " << rootGeneratorRegular.humanFamilyGenerator() << std::endl;
|
||||||
|
std::cerr << "Reserved public regular: " << reservedPublicRegular.humanAccountPublic() << std::endl;
|
||||||
|
std::cerr << "Reserved private regular: " << reservedPrivateRegular.humanAccountPrivate() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Temporary root account will be ["This is my payphrase."]:0
|
// Temporary root account will be ["This is my payphrase."]:0
|
||||||
NewcoinAddress rootFamilySeed; // Hold the 128 password.
|
NewcoinAddress rootFamilySeed; // Hold the 128 password.
|
||||||
NewcoinAddress rootFamilyGenerator; // Hold the generator.
|
NewcoinAddress rootFamilyGenerator; // Hold the generator.
|
||||||
NewcoinAddress rootAddress;
|
// NewcoinAddress rootAddress;
|
||||||
|
|
||||||
rootFamilySeed.setFamilySeed(CKey::PassPhraseToKey("This is my payphrase."));
|
rootFamilySeed.setFamilySeed(CKey::PassPhraseToKey("This is my payphrase."));
|
||||||
rootFamilyGenerator.setFamilyGenerator(rootFamilySeed);
|
rootFamilyGenerator.setFamilyGenerator(rootFamilySeed);
|
||||||
rootAddress.setAccountPublic(rootFamilyGenerator, 0);
|
rootAddress.setAccountPublic(rootFamilyGenerator, 0);
|
||||||
std::cerr << "Root account: " << rootAddress.humanAccountID() << std::endl;
|
std::cerr << "Root account: " << rootAddress.humanAccountID() << std::endl;
|
||||||
|
|
||||||
Ledger::pointer firstLedger(new Ledger(rootAddress, 100000000));
|
Ledger::pointer firstLedger = boost::make_shared<Ledger>(rootAddress, 100000000);
|
||||||
assert(!!firstLedger->getAccountState(rootAddress));
|
assert(!!firstLedger->getAccountState(rootAddress));
|
||||||
|
firstLedger->updateHash();
|
||||||
firstLedger->setClosed();
|
firstLedger->setClosed();
|
||||||
firstLedger->setAccepted();
|
firstLedger->setAccepted();
|
||||||
mMasterLedger.pushLedger(firstLedger);
|
mMasterLedger.pushLedger(firstLedger);
|
||||||
|
|
||||||
Ledger::pointer secondLedger = firstLedger->closeLedger(time(NULL));
|
Ledger::pointer secondLedger = boost::make_shared<Ledger>(firstLedger);
|
||||||
mMasterLedger.pushLedger(secondLedger);
|
mMasterLedger.pushLedger(secondLedger);
|
||||||
assert(!!secondLedger->getAccountState(rootAddress));
|
assert(!!secondLedger->getAccountState(rootAddress));
|
||||||
mMasterLedger.setSynced();
|
mMasterLedger.setSynced();
|
||||||
@@ -126,6 +177,7 @@ void Application::run()
|
|||||||
|
|
||||||
mWallet.load();
|
mWallet.load();
|
||||||
// mWallet.syncToLedger(true, &(*secondLedger));
|
// mWallet.syncToLedger(true, &(*secondLedger));
|
||||||
|
mNetOps.setStateTimer(5);
|
||||||
|
|
||||||
// temporary
|
// temporary
|
||||||
mIOService.run(); // This blocks
|
mIOService.run(); // This blocks
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include "UniqueNodeList.h"
|
#include "UniqueNodeList.h"
|
||||||
#include "ConnectionPool.h"
|
#include "ConnectionPool.h"
|
||||||
#include "TimingService.h"
|
|
||||||
#include "PubKeyCache.h"
|
#include "PubKeyCache.h"
|
||||||
#include "ScopedLock.h"
|
#include "ScopedLock.h"
|
||||||
#include "LedgerMaster.h"
|
#include "LedgerMaster.h"
|
||||||
@@ -34,12 +33,10 @@ public:
|
|||||||
|
|
||||||
class Application
|
class Application
|
||||||
{
|
{
|
||||||
NetworkOPs mNetOps;
|
|
||||||
Wallet mWallet;
|
|
||||||
|
|
||||||
boost::asio::io_service mIOService;
|
boost::asio::io_service mIOService;
|
||||||
|
|
||||||
TimingService mTimingService;
|
NetworkOPs mNetOps;
|
||||||
|
Wallet mWallet;
|
||||||
UniqueNodeList mUNL;
|
UniqueNodeList mUNL;
|
||||||
PubKeyCache mPKCache;
|
PubKeyCache mPKCache;
|
||||||
LedgerMaster mMasterLedger;
|
LedgerMaster mMasterLedger;
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
#ifndef __BINARYFORMATS__
|
#ifndef __BINARYFORMATS__
|
||||||
#define __BINARYFORMATS__
|
#define __BINARYFORMATS__
|
||||||
|
|
||||||
// binary transaction
|
|
||||||
const int BTxSize=145;
|
|
||||||
const int BTxPDestAcct=0, BTxLDestAact=20; // destination account pubkey Hash160
|
|
||||||
const int BTxPAmount=20, BTxLAmount=8; // amount
|
|
||||||
const int BTxPSASeq=28, BTxLASeq=4; // source account sequence number
|
|
||||||
const int BTxPSLIdx=32, BTxLSLIdx=4; // source ledger index
|
|
||||||
const int BTxPSTag=36, BTxLSTag=4; // source tag
|
|
||||||
const int BTxPSPubK=40, BTxLSPubK=33; // source public key
|
|
||||||
const int BTxPSig=73, BTxLSig=72; // signature
|
|
||||||
|
|
||||||
// ledger (note: fields after the timestamp are not part of the hash)
|
// ledger (note: fields after the timestamp are not part of the hash)
|
||||||
const int BLgSize=192;
|
const int BLgSize=190;
|
||||||
const int BLgPIndex=0, BLgLIndex=4; // ledger index
|
const int BLgPIndex=0, BLgLIndex=4; // ledger index
|
||||||
const int BLgPTotCoins=4, BLgLTotCoins=8; // total native coins
|
const int BLgPTotCoins=4, BLgLTotCoins=8; // total native coins
|
||||||
const int BLgPPrevLg=12, BLgLPrevLg=32; // previous ledger hash
|
const int BLgPPrevLg=12, BLgLPrevLg=32; // previous ledger hash
|
||||||
const int BLgPTxT=44, BLgLTxT=32; // transaction tree hash
|
const int BLgPTxT=44, BLgLTxT=32; // transaction tree hash
|
||||||
const int BLgPAcT=76, BLgLPAct=32; // account state hash
|
const int BLgPAcT=76, BLgLPAct=32; // account state hash
|
||||||
const int BLgPClTs=108, BLgLClTs=8; // closing timestamp
|
const int BLgPClTs=108, BLgLClTs=8; // closing timestamp
|
||||||
const int BLgPConf=116, BLgLPConf=4; // confidence
|
const int BLgPNlIn=116, BLgLNlIn=2;
|
||||||
const int BLgPSig=120, BLgLSig=72; // signature
|
const int BLgPSig=118, BLgLSig=72; // signature
|
||||||
|
|
||||||
// account status
|
|
||||||
const int BAsSize=32;
|
|
||||||
const int BAsPID=0, BAsLID=20; // account pubkey Hash160
|
|
||||||
const int BAsPBalance=20, BAsLBalance=8; // account balance
|
|
||||||
const int BAsPSequence=28, BASLSequence=4; // account sequence
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ int commandLineRPC(const std::vector<std::string>& vCmd)
|
|||||||
int nRet = 0;
|
int nRet = 0;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (vCmd.size() < 2) return 1;
|
if (!vCmd.size()) return 1;
|
||||||
|
|
||||||
std::string strMethod = vCmd[0];
|
std::string strMethod = vCmd[0];
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
#define SECTION_PEER_START_MAX "peer_start_max"
|
#define SECTION_PEER_START_MAX "peer_start_max"
|
||||||
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
|
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
|
||||||
#define SECTION_NETWORK_QUORUM "network_quorum"
|
#define SECTION_NETWORK_QUORUM "network_quorum"
|
||||||
#define SECTION_BELIEF_QUORUM "belief_quorum"
|
#define SECTION_VALIDATION_QUORUM "validation_quorum"
|
||||||
|
|
||||||
Config theConfig;
|
Config theConfig;
|
||||||
|
|
||||||
@@ -33,8 +33,8 @@ Config::Config()
|
|||||||
RPC_PORT = 5001;
|
RPC_PORT = 5001;
|
||||||
NUMBER_CONNECTIONS = 30;
|
NUMBER_CONNECTIONS = 30;
|
||||||
|
|
||||||
// a new ledger every 30 min
|
// a new ledger every minute
|
||||||
LEDGER_SECONDS = (60*30);
|
LEDGER_SECONDS = 60;
|
||||||
|
|
||||||
RPC_USER = "admin";
|
RPC_USER = "admin";
|
||||||
RPC_PASSWORD = "pass";
|
RPC_PASSWORD = "pass";
|
||||||
@@ -49,8 +49,8 @@ Config::Config()
|
|||||||
|
|
||||||
TRANSACTION_FEE_BASE = 1000;
|
TRANSACTION_FEE_BASE = 1000;
|
||||||
|
|
||||||
NETWORK_QUORUM = 0;
|
NETWORK_QUORUM = 0; // Don't need to see other nodes
|
||||||
BELIEF_QUORUM = 1;
|
VALIDATION_QUORUM = 1; // Only need one node to vouch
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::load()
|
void Config::load()
|
||||||
@@ -101,10 +101,10 @@ void Config::load()
|
|||||||
PEER_CONNECT_LOW_WATER = MAX(1, boost::lexical_cast<int>(strTemp));
|
PEER_CONNECT_LOW_WATER = MAX(1, boost::lexical_cast<int>(strTemp));
|
||||||
|
|
||||||
if (sectionSingleB(secConfig, SECTION_NETWORK_QUORUM, strTemp))
|
if (sectionSingleB(secConfig, SECTION_NETWORK_QUORUM, strTemp))
|
||||||
NETWORK_QUORUM = MIN(0, boost::lexical_cast<int>(strTemp));
|
NETWORK_QUORUM = MAX(0, boost::lexical_cast<int>(strTemp));
|
||||||
|
|
||||||
if (sectionSingleB(secConfig, SECTION_BELIEF_QUORUM, strTemp))
|
if (sectionSingleB(secConfig, SECTION_VALIDATION_QUORUM, strTemp))
|
||||||
BELIEF_QUORUM = MIN(0, boost::lexical_cast<int>(strTemp));
|
VALIDATION_QUORUM = MAX(0, boost::lexical_cast<int>(strTemp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#define VALIDATORS_SITE "redstem.com"
|
#define VALIDATORS_SITE "redstem.com"
|
||||||
|
|
||||||
#define VALIDATORS_FILE_NAME "validators.txt"
|
#define VALIDATORS_FILE_NAME "validators.txt"
|
||||||
const int SYSTEM_PEER_PORT=6561;
|
const int SYSTEM_PEER_PORT = 6561;
|
||||||
|
|
||||||
// Allow anonymous DH.
|
// Allow anonymous DH.
|
||||||
#define DEFAULT_PEER_SSL_CIPHER_LIST "ALL:!LOW:!EXP:!MD5:@STRENGTH"
|
#define DEFAULT_PEER_SSL_CIPHER_LIST "ALL:!LOW:!EXP:!MD5:@STRENGTH"
|
||||||
@@ -35,8 +35,9 @@ public:
|
|||||||
int LEDGER_PROPOSAL_DELAY_SECONDS;
|
int LEDGER_PROPOSAL_DELAY_SECONDS;
|
||||||
int LEDGER_AVALANCHE_SECONDS;
|
int LEDGER_AVALANCHE_SECONDS;
|
||||||
|
|
||||||
|
// Note: The following parameters do not relate to the UNL or trust at all
|
||||||
int NETWORK_QUORUM; // Minimum number of nodes to consider the network present
|
int NETWORK_QUORUM; // Minimum number of nodes to consider the network present
|
||||||
int BELIEF_QUORUM; // Percent agreement needed to sync ledger w/o validations
|
int VALIDATION_QUORUM; // Minimum validations to consider ledger authoritative
|
||||||
|
|
||||||
// node networking parameters
|
// node networking parameters
|
||||||
std::string PEER_IP;
|
std::string PEER_IP;
|
||||||
|
|||||||
@@ -123,8 +123,9 @@ void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg)
|
|||||||
BOOST_FOREACH(naPeer pair, mConnectedMap)
|
BOOST_FOREACH(naPeer pair, mConnectedMap)
|
||||||
{
|
{
|
||||||
Peer::pointer peer = pair.second;
|
Peer::pointer peer = pair.second;
|
||||||
|
if (!peer)
|
||||||
if(!fromPeer || !(peer.get() == fromPeer))
|
std::cerr << "CP::RM null peer in list" << std::endl;
|
||||||
|
else if (!fromPeer || !(peer.get() == fromPeer))
|
||||||
peer->sendPacket(msg);
|
peer->sendPacket(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +177,7 @@ bool ConnectionPool::connectTo(const std::string& strIp, int iPort)
|
|||||||
if (it == mIpMap.end())
|
if (it == mIpMap.end())
|
||||||
{
|
{
|
||||||
// Did not find it. Not already connecting or connected.
|
// Did not find it. Not already connecting or connected.
|
||||||
std::cerr << "ConnectionPool::connectTo: Connectting: "
|
std::cerr << "ConnectionPool::connectTo: Connecting: "
|
||||||
<< strIp << " " << iPort << std::endl;
|
<< strIp << " " << iPort << std::endl;
|
||||||
|
|
||||||
Peer::pointer peer(Peer::create(theApp->getIOService(), mCtx));
|
Peer::pointer peer(Peer::create(theApp->getIOService(), mCtx));
|
||||||
@@ -208,8 +209,23 @@ Json::Value ConnectionPool::getPeersJson()
|
|||||||
BOOST_FOREACH(naPeer pair, mConnectedMap)
|
BOOST_FOREACH(naPeer pair, mConnectedMap)
|
||||||
{
|
{
|
||||||
Peer::pointer peer = pair.second;
|
Peer::pointer peer = pair.second;
|
||||||
|
if (!peer)
|
||||||
|
std::cerr << "CP::GPH null peer" << std::endl;
|
||||||
|
else ret.append(peer->getJson());
|
||||||
|
}
|
||||||
|
|
||||||
ret.append(peer->getJson());
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Peer::pointer> ConnectionPool::getPeerVector()
|
||||||
|
{
|
||||||
|
std::vector<Peer::pointer> ret;
|
||||||
|
ret.reserve(mConnectedMap.size());
|
||||||
|
|
||||||
|
BOOST_FOREACH(naPeer pair, mConnectedMap)
|
||||||
|
{
|
||||||
|
assert(!!pair.second);
|
||||||
|
ret.push_back(pair.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -221,7 +237,7 @@ bool ConnectionPool::peerConnected(Peer::pointer peer, const NewcoinAddress& na)
|
|||||||
bool bSuccess;
|
bool bSuccess;
|
||||||
|
|
||||||
std::cerr << "ConnectionPool::peerConnected: " << na.humanNodePublic() << std::endl;
|
std::cerr << "ConnectionPool::peerConnected: " << na.humanNodePublic() << std::endl;
|
||||||
|
assert(!!peer);
|
||||||
if (na == theApp->getWallet().getNodePublic())
|
if (na == theApp->getWallet().getNodePublic())
|
||||||
{
|
{
|
||||||
std::cerr << "ConnectionPool::peerConnected: To self." << std::endl;
|
std::cerr << "ConnectionPool::peerConnected: To self." << std::endl;
|
||||||
@@ -281,9 +297,12 @@ void ConnectionPool::peerDisconnected(Peer::pointer peer, const ipPort& ipPeer,
|
|||||||
|
|
||||||
void ConnectionPool::peerFailed(const std::string& strIp, int iPort)
|
void ConnectionPool::peerFailed(const std::string& strIp, int iPort)
|
||||||
{
|
{
|
||||||
if (bScanning && !mScanIp.compare(strIp), mScanPort == iPort)
|
// If the fail was our scan, we are no longer scanning.
|
||||||
|
if (bScanning && !mScanIp.compare(strIp) && mScanPort == iPort)
|
||||||
{
|
{
|
||||||
bScanning = false;
|
bScanning = false;
|
||||||
|
|
||||||
|
// Look for more to scan.
|
||||||
scanRefresh();
|
scanRefresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ public:
|
|||||||
void peerFailed(const std::string& strIp, int iPort);
|
void peerFailed(const std::string& strIp, int iPort);
|
||||||
|
|
||||||
Json::Value getPeersJson();
|
Json::Value getPeersJson();
|
||||||
|
std::vector<Peer::pointer> getPeerVector();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Scanning
|
// Scanning
|
||||||
|
|||||||
@@ -9,21 +9,21 @@
|
|||||||
|
|
||||||
bool HashedObject::checkHash() const
|
bool HashedObject::checkHash() const
|
||||||
{
|
{
|
||||||
uint256 hash=Serializer::getSHA512Half(mData);
|
uint256 hash = Serializer::getSHA512Half(mData);
|
||||||
return hash==mHash;
|
return hash == mHash;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HashedObject::checkFixHash()
|
bool HashedObject::checkFixHash()
|
||||||
{
|
{
|
||||||
uint256 hash=Serializer::getSHA512Half(mData);
|
uint256 hash = Serializer::getSHA512Half(mData);
|
||||||
if(hash==mHash) return true;
|
if (hash == mHash) return true;
|
||||||
mHash=hash;
|
mHash = hash;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashedObject::setHash()
|
void HashedObject::setHash()
|
||||||
{
|
{
|
||||||
mHash=Serializer::getSHA512Half(mData);
|
mHash = Serializer::getSHA512Half(mData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -39,12 +39,12 @@ CREATE INDEX ObjectLocate ON CommittedObjects(LedgerIndex, ObjType);
|
|||||||
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
|
bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<unsigned char>& data,
|
||||||
const uint256& hash)
|
const uint256& hash)
|
||||||
{
|
{
|
||||||
if(!theApp->getHashNodeDB()) return true;
|
if (!theApp->getHashNodeDB()) return true;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Serializer s(data);
|
Serializer s(data);
|
||||||
assert(hash==s.getSHA512Half());
|
assert(hash == s.getSHA512Half());
|
||||||
#endif
|
#endif
|
||||||
std::string sql="INSERT INTO CommitedObjects (Hash,ObjType,LedgerIndex,Object) VALUES ('";
|
std::string sql = "INSERT INTO CommitedObjects (Hash,ObjType,LedgerIndex,Object) VALUES ('";
|
||||||
sql.append(hash.GetHex());
|
sql.append(hash.GetHex());
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
@@ -63,8 +63,8 @@ bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<
|
|||||||
sql.append(");");
|
sql.append(");");
|
||||||
|
|
||||||
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
|
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
|
||||||
Database* db=theApp->getHashNodeDB()->getDB();
|
Database* db = theApp->getHashNodeDB()->getDB();
|
||||||
return db->executeSQL(sql.c_str());
|
return db->executeSQL(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HashedObject::store() const
|
bool HashedObject::store() const
|
||||||
@@ -77,8 +77,8 @@ bool HashedObject::store() const
|
|||||||
|
|
||||||
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
||||||
{
|
{
|
||||||
if(!theApp->getHashNodeDB()) return HashedObject::pointer();
|
if (!theApp->getHashNodeDB()) return HashedObject::pointer();
|
||||||
std::string sql="SELECT * from CommitedObjects WHERE Hash='";
|
std::string sql = "SELECT * from CommitedObjects WHERE Hash='";
|
||||||
sql.append(hash.GetHex());
|
sql.append(hash.GetHex());
|
||||||
sql.append("';");
|
sql.append("';");
|
||||||
|
|
||||||
@@ -86,39 +86,41 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash)
|
|||||||
uint32 index;
|
uint32 index;
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
data.reserve(8192);
|
data.reserve(8192);
|
||||||
if(1)
|
|
||||||
{
|
{
|
||||||
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
|
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
|
||||||
Database* db=theApp->getHashNodeDB()->getDB();
|
Database* db = theApp->getHashNodeDB()->getDB();
|
||||||
|
|
||||||
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
|
if (!db->executeSQL(sql) || !db->startIterRows())
|
||||||
return HashedObject::pointer();
|
return HashedObject::pointer();
|
||||||
|
|
||||||
std::string type;
|
std::string type;
|
||||||
db->getStr("ObjType", type);
|
db->getStr("ObjType", type);
|
||||||
if(type.size()==0) return HashedObject::pointer();
|
if (type.size() == 0) return HashedObject::pointer();
|
||||||
|
|
||||||
index=db->getBigInt("LedgerIndex");
|
|
||||||
|
|
||||||
int size=db->getBinary("Object", NULL, 0);
|
index = db->getBigInt("LedgerIndex");
|
||||||
|
|
||||||
|
int size = db->getBinary("Object", NULL, 0);
|
||||||
data.resize(size);
|
data.resize(size);
|
||||||
db->getBinary("Object", &(data.front()), size);
|
db->getBinary("Object", &(data.front()), size);
|
||||||
db->endIterRows();
|
db->endIterRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
HashedObjectType htype=UNKNOWN;
|
HashedObjectType htype = UNKNOWN;
|
||||||
switch(type[0])
|
switch(type[0])
|
||||||
{
|
{
|
||||||
case 'L': htype=LEDGER; break;
|
case 'L': htype = LEDGER; break;
|
||||||
case 'T': htype=TRANSACTION; break;
|
case 'T': htype = TRANSACTION; break;
|
||||||
case 'A': htype=ACCOUNT_NODE; break;
|
case 'A': htype = ACCOUNT_NODE; break;
|
||||||
case 'N': htype=TRANSACTION_NODE; break;
|
case 'N': htype = TRANSACTION_NODE; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashedObject::pointer obj(new HashedObject(htype, index, data));
|
HashedObject::pointer obj = boost::make_shared<HashedObject>(htype, index, data);
|
||||||
obj->mHash=hash;
|
obj->mHash = hash;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(obj->checkHash());
|
assert(obj->checkHash());
|
||||||
#endif
|
#endif
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -167,7 +167,7 @@ void HttpsClient::handleConnect(const boost::system::error_code& ecResult)
|
|||||||
|
|
||||||
if (!mShutdown)
|
if (!mShutdown)
|
||||||
{
|
{
|
||||||
// std::cerr << "Connectted." << std::endl;
|
// std::cerr << "Connected." << std::endl;
|
||||||
|
|
||||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
|
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_peer);
|
||||||
|
|||||||
123
src/Ledger.cpp
123
src/Ledger.cpp
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "../obj/src/newcoin.pb.h"
|
#include "../obj/src/newcoin.pb.h"
|
||||||
#include "PackedMessage.h"
|
#include "PackedMessage.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
@@ -16,7 +17,8 @@
|
|||||||
#include "BinaryFormats.h"
|
#include "BinaryFormats.h"
|
||||||
|
|
||||||
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount),
|
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount),
|
||||||
mTimeStamp(0), mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
|
mCloseTime(0), mLedgerSeq(0), mLedgerInterval(60), mClosed(false), mValidHash(false),
|
||||||
|
mAccepted(false), mImmutable(false)
|
||||||
{
|
{
|
||||||
mTransactionMap = boost::make_shared<SHAMap>();
|
mTransactionMap = boost::make_shared<SHAMap>();
|
||||||
mAccountStateMap = boost::make_shared<SHAMap>();
|
mAccountStateMap = boost::make_shared<SHAMap>();
|
||||||
@@ -35,22 +37,24 @@ Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(s
|
|||||||
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
Ledger::Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||||
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq)
|
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq)
|
||||||
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
|
: mParentHash(parentHash), mTransHash(transHash), mAccountHash(accountHash),
|
||||||
mTotCoins(totCoins), mTimeStamp(timeStamp), mLedgerSeq(ledgerSeq),
|
mTotCoins(totCoins), mCloseTime(timeStamp), mLedgerSeq(ledgerSeq), mLedgerInterval(60),
|
||||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
|
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false)
|
||||||
{
|
{
|
||||||
updateHash();
|
updateHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::Ledger(Ledger &prevLedger, uint64 ts) : mTimeStamp(ts),
|
Ledger::Ledger(Ledger::pointer prevLedger) : mParentHash(prevLedger->getHash()), mTotCoins(prevLedger->mTotCoins),
|
||||||
|
mLedgerSeq(prevLedger->mLedgerSeq + 1), mLedgerInterval(prevLedger->mLedgerInterval),
|
||||||
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
|
mClosed(false), mValidHash(false), mAccepted(false), mImmutable(false),
|
||||||
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger.mAccountStateMap)
|
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger->mAccountStateMap)
|
||||||
{
|
{
|
||||||
mParentHash = prevLedger.getHash();
|
prevLedger->setClosed();
|
||||||
mLedgerSeq = prevLedger.mLedgerSeq+1;
|
prevLedger->updateHash();
|
||||||
mAccountStateMap->setSeq(mLedgerSeq);
|
mAccountStateMap->setSeq(mLedgerSeq);
|
||||||
|
mCloseTime = prevLedger->getNextLedgerClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mTimeStamp(0),
|
Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mCloseTime(0),
|
||||||
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
|
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
|
||||||
{
|
{
|
||||||
Serializer s(rawLedger);
|
Serializer s(rawLedger);
|
||||||
@@ -60,7 +64,8 @@ Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mTim
|
|||||||
if (!s.get256(mParentHash, BLgPPrevLg)) return;
|
if (!s.get256(mParentHash, BLgPPrevLg)) return;
|
||||||
if (!s.get256(mTransHash, BLgPTxT)) return;
|
if (!s.get256(mTransHash, BLgPTxT)) return;
|
||||||
if (!s.get256(mAccountHash, BLgPAcT)) return;
|
if (!s.get256(mAccountHash, BLgPAcT)) return;
|
||||||
if (!s.get64(mTimeStamp, BLgPClTs)) return;
|
if (!s.get64(mCloseTime, BLgPClTs)) return;
|
||||||
|
if (!s.get16(mLedgerInterval, BLgPNlIn)) return;
|
||||||
updateHash();
|
updateHash();
|
||||||
if(mValidHash)
|
if(mValidHash)
|
||||||
{
|
{
|
||||||
@@ -69,7 +74,7 @@ Ledger::Ledger(const std::vector<unsigned char>& rawLedger) : mTotCoins(0), mTim
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::Ledger(const std::string& rawLedger) : mTotCoins(0), mTimeStamp(0),
|
Ledger::Ledger(const std::string& rawLedger) : mTotCoins(0), mCloseTime(0),
|
||||||
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
|
mLedgerSeq(0), mClosed(false), mValidHash(false), mAccepted(false), mImmutable(true)
|
||||||
{
|
{
|
||||||
Serializer s(rawLedger);
|
Serializer s(rawLedger);
|
||||||
@@ -79,7 +84,8 @@ Ledger::Ledger(const std::string& rawLedger) : mTotCoins(0), mTimeStamp(0),
|
|||||||
if (!s.get256(mParentHash, BLgPPrevLg)) return;
|
if (!s.get256(mParentHash, BLgPPrevLg)) return;
|
||||||
if (!s.get256(mTransHash, BLgPTxT)) return;
|
if (!s.get256(mTransHash, BLgPTxT)) return;
|
||||||
if (!s.get256(mAccountHash, BLgPAcT)) return;
|
if (!s.get256(mAccountHash, BLgPAcT)) return;
|
||||||
if (!s.get64(mTimeStamp, BLgPClTs)) return;
|
if (!s.get64(mCloseTime, BLgPClTs)) return;
|
||||||
|
if (!s.get16(mLedgerInterval, BLgPNlIn)) return;
|
||||||
updateHash();
|
updateHash();
|
||||||
if(mValidHash)
|
if(mValidHash)
|
||||||
{
|
{
|
||||||
@@ -100,7 +106,7 @@ void Ledger::updateHash()
|
|||||||
|
|
||||||
Serializer s(116);
|
Serializer s(116);
|
||||||
addRaw(s);
|
addRaw(s);
|
||||||
mHash =s.getSHA512Half();
|
mHash = s.getSHA512Half();
|
||||||
mValidHash = true;
|
mValidHash = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +117,8 @@ void Ledger::addRaw(Serializer &s)
|
|||||||
s.add256(mParentHash);
|
s.add256(mParentHash);
|
||||||
s.add256(mTransHash);
|
s.add256(mTransHash);
|
||||||
s.add256(mAccountHash);
|
s.add256(mAccountHash);
|
||||||
s.add64(mTimeStamp);
|
s.add64(mCloseTime);
|
||||||
|
s.add16(mLedgerInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
|
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
|
||||||
@@ -124,7 +131,7 @@ AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
|
|||||||
if (!item)
|
if (!item)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
// std::cerr << " notfound" << std::endl;
|
// std::cerr << " notfound" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return AccountState::pointer();
|
return AccountState::pointer();
|
||||||
}
|
}
|
||||||
@@ -175,14 +182,6 @@ Transaction::pointer Ledger::getTransaction(const uint256& transID) const
|
|||||||
return txn;
|
return txn;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer Ledger::closeLedger(uint64 timeStamp)
|
|
||||||
{ // close this ledger, return a pointer to the next ledger
|
|
||||||
// CAUTION: New ledger needs its SHAMap's connected to storage
|
|
||||||
updateHash();
|
|
||||||
setClosed();
|
|
||||||
return Ledger::pointer(new Ledger(*this, timeStamp)); // can't use make_shared, constructor is protected
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Ledger::unitTest()
|
bool Ledger::unitTest()
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
@@ -225,13 +224,13 @@ bool Ledger::unitTest()
|
|||||||
uint256 Ledger::getHash()
|
uint256 Ledger::getHash()
|
||||||
{
|
{
|
||||||
if(!mValidHash) updateHash();
|
if(!mValidHash) updateHash();
|
||||||
return(mHash);
|
return(mHash);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
||||||
{
|
{
|
||||||
std::string sql="INSERT INTO Ledgers "
|
std::string sql="INSERT INTO Ledgers "
|
||||||
"(LedgerHash,LedgerSeq,TotalCoins,,ClosingTime,AccountSetHash,TransSetHash) VALUES ('";
|
"(LedgerHash,LedgerSeq,TotalCoins,ClosingTime,AccountSetHash,TransSetHash) VALUES ('";
|
||||||
sql.append(ledger->getHash().GetHex());
|
sql.append(ledger->getHash().GetHex());
|
||||||
sql.append("','");
|
sql.append("','");
|
||||||
sql.append(boost::lexical_cast<std::string>(ledger->mLedgerSeq));
|
sql.append(boost::lexical_cast<std::string>(ledger->mLedgerSeq));
|
||||||
@@ -240,7 +239,7 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
|||||||
sql.append("','");
|
sql.append("','");
|
||||||
sql.append(boost::lexical_cast<std::string>(ledger->mTotCoins));
|
sql.append(boost::lexical_cast<std::string>(ledger->mTotCoins));
|
||||||
sql.append("','");
|
sql.append("','");
|
||||||
sql.append(boost::lexical_cast<std::string>(ledger->mTimeStamp));
|
sql.append(boost::lexical_cast<std::string>(ledger->mCloseTime));
|
||||||
sql.append("','");
|
sql.append("','");
|
||||||
sql.append(ledger->mAccountHash.GetHex());
|
sql.append(ledger->mAccountHash.GetHex());
|
||||||
sql.append("','");
|
sql.append("','");
|
||||||
@@ -248,7 +247,7 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
|
|||||||
sql.append("');");
|
sql.append("');");
|
||||||
|
|
||||||
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
||||||
theApp->getLedgerDB()->getDB()->executeSQL(sql.c_str());
|
theApp->getLedgerDB()->getDB()->executeSQL(sql);
|
||||||
|
|
||||||
// write out dirty nodes
|
// write out dirty nodes
|
||||||
while(ledger->mTransactionMap->flushDirty(64, TRANSACTION_NODE, ledger->mLedgerSeq))
|
while(ledger->mTransactionMap->flushDirty(64, TRANSACTION_NODE, ledger->mLedgerSeq))
|
||||||
@@ -269,7 +268,8 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
|
|||||||
{
|
{
|
||||||
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
|
||||||
Database *db = theApp->getLedgerDB()->getDB();
|
Database *db = theApp->getLedgerDB()->getDB();
|
||||||
if (!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
|
|
||||||
|
if (!db->executeSQL(sql) || !db->startIterRows())
|
||||||
return Ledger::pointer();
|
return Ledger::pointer();
|
||||||
|
|
||||||
db->getStr("LedgerHash", hash);
|
db->getStr("LedgerHash", hash);
|
||||||
@@ -285,7 +285,7 @@ Ledger::pointer Ledger::getSQL(const std::string& sql)
|
|||||||
ledgerSeq = db->getBigInt("LedgerSeq");
|
ledgerSeq = db->getBigInt("LedgerSeq");
|
||||||
db->endIterRows();
|
db->endIterRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer ret=boost::make_shared<Ledger>(prevHash, transHash, accountHash, totCoins, closingTime, ledgerSeq);
|
Ledger::pointer ret=boost::make_shared<Ledger>(prevHash, transHash, accountHash, totCoins, closingTime, ledgerSeq);
|
||||||
if (ret->getHash() != ledgerHash)
|
if (ret->getHash() != ledgerHash)
|
||||||
{
|
{
|
||||||
@@ -316,18 +316,21 @@ void Ledger::addJson(Json::Value& ret)
|
|||||||
Json::Value ledger(Json::objectValue);
|
Json::Value ledger(Json::objectValue);
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
ledger["ParentHash"]=mParentHash.GetHex();
|
ledger["ParentHash"] = mParentHash.GetHex();
|
||||||
|
|
||||||
if(mClosed)
|
if(mClosed)
|
||||||
{
|
{
|
||||||
ledger["Hash"]=mHash.GetHex();
|
ledger["Hash"] = mHash.GetHex();
|
||||||
ledger["TransactionHash"]=mTransHash.GetHex();
|
ledger["TransactionHash"] = mTransHash.GetHex();
|
||||||
ledger["AccountHash"]=mAccountHash.GetHex();
|
ledger["AccountHash"] = mAccountHash.GetHex();
|
||||||
ledger["Closed"]=true;
|
ledger["Closed"] = true;
|
||||||
ledger["Accepted"]=mAccepted;
|
ledger["Accepted"] = mAccepted;
|
||||||
|
ledger["TotalCoins"] = boost::lexical_cast<std::string>(mTotCoins);
|
||||||
}
|
}
|
||||||
else ledger["Closed"]=false;
|
else ledger["Closed"] = false;
|
||||||
ret[boost::lexical_cast<std::string>(mLedgerSeq)]=ledger;
|
if (mCloseTime != 0)
|
||||||
|
ledger["CloseTime"] = boost::posix_time::to_simple_string(ptFromSeconds(mCloseTime));
|
||||||
|
ret[boost::lexical_cast<std::string>(mLedgerSeq)] = ledger;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger::pointer newPrevious, int limit)
|
Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger::pointer newPrevious, int limit)
|
||||||
@@ -339,42 +342,42 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
|
|||||||
int count;
|
int count;
|
||||||
|
|
||||||
// 1) Validate sequences and make sure the specified ledger is a valid prior ledger
|
// 1) Validate sequences and make sure the specified ledger is a valid prior ledger
|
||||||
if(newPrevious->getLedgerSeq()!=oldPrevious->getLedgerSeq()) return Ledger::pointer();
|
if (newPrevious->getLedgerSeq() != oldPrevious->getLedgerSeq()) return Ledger::pointer();
|
||||||
|
|
||||||
// 2) Begin building a new ledger with the specified ledger as previous.
|
// 2) Begin building a new ledger with the specified ledger as previous.
|
||||||
Ledger* newLedger=new Ledger(*newPrevious, mTimeStamp);
|
Ledger::pointer newLedger = boost::make_shared<Ledger>(newPrevious);
|
||||||
|
|
||||||
// 3) For any transactions in our previous ledger but not in the new previous ledger, add them to the set
|
// 3) For any transactions in our previous ledger but not in the new previous ledger, add them to the set
|
||||||
SHAMap::SHAMapDiff mapDifferences;
|
SHAMap::SHAMapDiff mapDifferences;
|
||||||
std::map<uint256, std::pair<Transaction::pointer, Transaction::pointer> > TxnDiff;
|
std::map<uint256, std::pair<Transaction::pointer, Transaction::pointer> > TxnDiff;
|
||||||
if(!newPrevious->mTransactionMap->compare(oldPrevious->mTransactionMap, mapDifferences, limit))
|
if (!newPrevious->mTransactionMap->compare(oldPrevious->mTransactionMap, mapDifferences, limit))
|
||||||
return Ledger::pointer();
|
return Ledger::pointer();
|
||||||
if(!Transaction::convertToTransactions(oldPrevious->getLedgerSeq(), newPrevious->getLedgerSeq(),
|
if (!Transaction::convertToTransactions(oldPrevious->getLedgerSeq(), newPrevious->getLedgerSeq(),
|
||||||
false, true, mapDifferences, TxnDiff))
|
false, true, mapDifferences, TxnDiff))
|
||||||
return Ledger::pointer(); // new previous ledger contains invalid transactions
|
return Ledger::pointer(); // new previous ledger contains invalid transactions
|
||||||
|
|
||||||
// 4) Try to add those transactions to the new ledger.
|
// 4) Try to add those transactions to the new ledger.
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
count=0;
|
count = 0;
|
||||||
std::map<uint256, std::pair<Transaction::pointer, Transaction::pointer> >::iterator it = TxnDiff.begin();
|
std::map<uint256, std::pair<Transaction::pointer, Transaction::pointer> >::iterator it = TxnDiff.begin();
|
||||||
while (it != TxnDiff.end())
|
while (it != TxnDiff.end())
|
||||||
{
|
{
|
||||||
Transaction::pointer& tx = it->second.second;
|
Transaction::pointer& tx = it->second.second;
|
||||||
if (!tx || newLedger->addTransaction(tx))
|
if (!tx || newLedger->addTransaction(tx)) // FIXME: addTransaction doesn't do checks
|
||||||
{
|
{
|
||||||
count++;
|
++count;
|
||||||
TxnDiff.erase(it++);
|
TxnDiff.erase(it++);
|
||||||
}
|
}
|
||||||
else ++it;
|
else ++it;
|
||||||
}
|
}
|
||||||
} while (count!=0);
|
} while (count != 0);
|
||||||
|
|
||||||
// WRITEME: Handle rejected transactions left in TxnDiff
|
// WRITEME: Handle rejected transactions left in TxnDiff
|
||||||
|
|
||||||
// 5) Try to add transactions from this ledger to the new ledger.
|
// 5) Try to add transactions from this ledger to the new ledger.
|
||||||
std::map<uint256, Transaction::pointer> txnMap;
|
std::map<uint256, Transaction::pointer> txnMap;
|
||||||
for(SHAMapItem::pointer mit = peekTransactionMap()->peekFirstItem();
|
for (SHAMapItem::pointer mit = peekTransactionMap()->peekFirstItem();
|
||||||
!!mit; mit = peekTransactionMap()->peekNextItem(mit->getTag()))
|
!!mit; mit = peekTransactionMap()->peekNextItem(mit->getTag()))
|
||||||
{
|
{
|
||||||
uint256 txnID = mit->getTag();
|
uint256 txnID = mit->getTag();
|
||||||
@@ -385,18 +388,18 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
count=0;
|
count = 0;
|
||||||
std::map<uint256, Transaction::pointer>::iterator it = txnMap.begin();
|
std::map<uint256, Transaction::pointer>::iterator it = txnMap.begin();
|
||||||
while (it != txnMap.end())
|
while (it != txnMap.end())
|
||||||
{
|
{
|
||||||
if(newLedger->addTransaction(it->second))
|
if (newLedger->addTransaction(it->second)) // FIXME: addTransaction doesn't do checks
|
||||||
{
|
{
|
||||||
count++;
|
++count;
|
||||||
txnMap.erase(it++);
|
txnMap.erase(it++);
|
||||||
}
|
}
|
||||||
else ++it;
|
else ++it;
|
||||||
}
|
}
|
||||||
} while(count!=0);
|
} while(count != 0);
|
||||||
|
|
||||||
|
|
||||||
// WRITEME: Handle rejected transactions left in txnMap
|
// WRITEME: Handle rejected transactions left in txnMap
|
||||||
@@ -406,7 +409,7 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
|
|||||||
|
|
||||||
void Ledger::setAcquiring(void)
|
void Ledger::setAcquiring(void)
|
||||||
{
|
{
|
||||||
if(!mTransactionMap || !mAccountStateMap) throw SHAMapException(InvalidMap);
|
if (!mTransactionMap || !mAccountStateMap) throw SHAMapException(InvalidMap);
|
||||||
mTransactionMap->setSynching();
|
mTransactionMap->setSynching();
|
||||||
mAccountStateMap->setSynching();
|
mAccountStateMap->setSynching();
|
||||||
}
|
}
|
||||||
@@ -425,3 +428,25 @@ bool Ledger::isAcquiringAS(void)
|
|||||||
{
|
{
|
||||||
return mAccountStateMap->isSynching();
|
return mAccountStateMap->isSynching();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boost::posix_time::ptime Ledger::getCloseTime() const
|
||||||
|
{
|
||||||
|
return ptFromSeconds(mCloseTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ledger::setCloseTime(boost::posix_time::ptime ptm)
|
||||||
|
{
|
||||||
|
mCloseTime = iToSeconds(ptm);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 Ledger::getNextLedgerClose() const
|
||||||
|
{
|
||||||
|
if (mCloseTime == 0)
|
||||||
|
{
|
||||||
|
uint64 closeTime = theApp->getOPs().getNetworkTimeNC() + mLedgerInterval - 1;
|
||||||
|
return closeTime - (closeTime % mLedgerInterval);
|
||||||
|
}
|
||||||
|
return mCloseTime + mLedgerInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
73
src/Ledger.h
73
src/Ledger.h
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
#include "../json/value.h"
|
#include "../json/value.h"
|
||||||
|
|
||||||
@@ -15,13 +16,12 @@
|
|||||||
#include "BitcoinUtil.h"
|
#include "BitcoinUtil.h"
|
||||||
#include "SHAMap.h"
|
#include "SHAMap.h"
|
||||||
|
|
||||||
|
|
||||||
enum LedgerStateParms
|
enum LedgerStateParms
|
||||||
{
|
{
|
||||||
lepNONE = 0, // no special flags
|
lepNONE = 0, // no special flags
|
||||||
|
|
||||||
// input flags
|
// input flags
|
||||||
lepCREATE, // Create if not present
|
lepCREATE, // Create if not present
|
||||||
|
|
||||||
// output flags
|
// output flags
|
||||||
lepOKAY, // success
|
lepOKAY, // success
|
||||||
@@ -37,43 +37,42 @@ class Ledger : public boost::enable_shared_from_this<Ledger>
|
|||||||
public:
|
public:
|
||||||
typedef boost::shared_ptr<Ledger> pointer;
|
typedef boost::shared_ptr<Ledger> pointer;
|
||||||
|
|
||||||
|
|
||||||
enum TransResult
|
enum TransResult
|
||||||
{
|
{
|
||||||
TR_ERROR =-1,
|
TR_ERROR = -1,
|
||||||
TR_SUCCESS =0,
|
TR_SUCCESS = 0,
|
||||||
TR_NOTFOUND =1,
|
TR_NOTFOUND = 1,
|
||||||
TR_ALREADY =2,
|
TR_ALREADY = 2,
|
||||||
TR_BADTRANS =3, // the transaction itself is corrupt
|
TR_BADTRANS = 3, // the transaction itself is corrupt
|
||||||
TR_BADACCT =4, // one of the accounts is invalid
|
TR_BADACCT = 4, // one of the accounts is invalid
|
||||||
TR_INSUFF =5, // the sending(apply)/receiving(remove) account is broke
|
TR_INSUFF = 5, // the sending(apply)/receiving(remove) account is broke
|
||||||
TR_PASTASEQ =6, // account is past this transaction
|
TR_PASTASEQ = 6, // account is past this transaction
|
||||||
TR_PREASEQ =7, // account is missing transactions before this
|
TR_PREASEQ = 7, // account is missing transactions before this
|
||||||
TR_BADLSEQ =8, // ledger too early
|
TR_BADLSEQ = 8, // ledger too early
|
||||||
TR_TOOSMALL =9, // amount is less than Tx fee
|
TR_TOOSMALL = 9, // amount is less than Tx fee
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
uint256 mHash, mParentHash, mTransHash, mAccountHash;
|
||||||
uint64 mTotCoins, mTimeStamp;
|
uint64 mTotCoins;
|
||||||
|
uint64 mCloseTime; // when this ledger closes
|
||||||
uint32 mLedgerSeq;
|
uint32 mLedgerSeq;
|
||||||
|
uint16 mLedgerInterval;
|
||||||
bool mClosed, mValidHash, mAccepted, mImmutable;
|
bool mClosed, mValidHash, mAccepted, mImmutable;
|
||||||
|
|
||||||
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
SHAMap::pointer mTransactionMap, mAccountStateMap;
|
||||||
|
|
||||||
mutable boost::recursive_mutex mLock;
|
mutable boost::recursive_mutex mLock;
|
||||||
|
|
||||||
Ledger(const Ledger&); // no implementation
|
Ledger(const Ledger&); // no implementation
|
||||||
Ledger& operator=(const Ledger&); // no implementation
|
Ledger& operator=(const Ledger&); // no implementation
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Ledger(Ledger& previous, uint64 timestamp); // ledger after this one
|
|
||||||
void updateHash();
|
|
||||||
|
|
||||||
bool addTransaction(Transaction::pointer);
|
bool addTransaction(Transaction::pointer);
|
||||||
bool addTransaction(const uint256& id, const Serializer& txn, uint64_t fee);
|
bool addTransaction(const uint256& id, const Serializer& txn, uint64_t fee);
|
||||||
|
|
||||||
static Ledger::pointer getSQL(const std::string& sqlStatement);
|
static Ledger::pointer getSQL(const std::string& sqlStatement);
|
||||||
|
|
||||||
SerializedLedgerEntry::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
SerializedLedgerEntry::pointer getASNode(LedgerStateParms& parms, const uint256& nodeID,
|
||||||
@@ -82,25 +81,33 @@ protected:
|
|||||||
public:
|
public:
|
||||||
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
|
||||||
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
Ledger(const uint256 &parentHash, const uint256 &transHash, const uint256 &accountHash,
|
||||||
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for received ledgers
|
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq); // used for database ledgers
|
||||||
Ledger(const std::vector<unsigned char>& rawLedger);
|
Ledger(const std::vector<unsigned char>& rawLedger);
|
||||||
Ledger(const std::string& rawLedger);
|
Ledger(const std::string& rawLedger);
|
||||||
|
Ledger(Ledger::pointer previous); // ledger after this one
|
||||||
|
|
||||||
void setClosed() { mClosed=true; }
|
void updateHash();
|
||||||
void setAccepted() { mAccepted=true; }
|
void setClosed() { mClosed = true; }
|
||||||
bool isClosed() { return mClosed; }
|
void setAccepted() { mAccepted = true; }
|
||||||
bool isAccepted() { return mAccepted; }
|
bool isClosed() { return mClosed; }
|
||||||
|
bool isAccepted() { return mAccepted; }
|
||||||
|
|
||||||
// ledger signature operations
|
// ledger signature operations
|
||||||
void addRaw(Serializer &s);
|
void addRaw(Serializer &s);
|
||||||
|
|
||||||
uint256 getHash();
|
uint256 getHash();
|
||||||
const uint256& getParentHash() const { return mParentHash; }
|
const uint256& getParentHash() const { return mParentHash; }
|
||||||
const uint256& getTransHash() const { return mTransHash; }
|
const uint256& getTransHash() const { return mTransHash; }
|
||||||
const uint256& getAccountHash() const { return mAccountHash; }
|
const uint256& getAccountHash() const { return mAccountHash; }
|
||||||
uint64 getTotalCoins() const { return mTotCoins; }
|
uint64 getTotalCoins() const { return mTotCoins; }
|
||||||
uint64 getTimeStamp() const { return mTimeStamp; }
|
uint64 getCloseTimeNC() const { return mCloseTime; }
|
||||||
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
uint32 getLedgerSeq() const { return mLedgerSeq; }
|
||||||
|
uint16 getInterval() const { return mLedgerInterval; }
|
||||||
|
|
||||||
|
// close time functions
|
||||||
|
boost::posix_time::ptime getCloseTime() const;
|
||||||
|
void setCloseTime(boost::posix_time::ptime);
|
||||||
|
uint64 getNextLedgerClose() const;
|
||||||
|
|
||||||
// low level functions
|
// low level functions
|
||||||
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
|
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
|
||||||
@@ -116,7 +123,7 @@ public:
|
|||||||
bool hasTransaction(const uint256& TransID) const;
|
bool hasTransaction(const uint256& TransID) const;
|
||||||
Transaction::pointer getTransaction(const uint256& transID) const;
|
Transaction::pointer getTransaction(const uint256& transID) const;
|
||||||
|
|
||||||
Ledger::pointer switchPreviousLedger(Ledger::pointer oldPrevious, Ledger::pointer newPrevious, int limit);
|
Ledger::pointer switchPreviousLedger(Ledger::pointer oldPrevious, Ledger::pointer newPrevious, int limit);
|
||||||
|
|
||||||
// high-level functions
|
// high-level functions
|
||||||
AccountState::pointer getAccountState(const NewcoinAddress& acctID);
|
AccountState::pointer getAccountState(const NewcoinAddress& acctID);
|
||||||
@@ -144,7 +151,6 @@ public:
|
|||||||
const uint160& currency)
|
const uint160& currency)
|
||||||
{ return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); }
|
{ return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); }
|
||||||
|
|
||||||
Ledger::pointer closeLedger(uint64 timestamp);
|
|
||||||
bool isCompatible(boost::shared_ptr<Ledger> other);
|
bool isCompatible(boost::shared_ptr<Ledger> other);
|
||||||
bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko);
|
bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko);
|
||||||
|
|
||||||
@@ -164,3 +170,4 @@ inline LedgerStateParms operator&(const LedgerStateParms& l1, const LedgerStateP
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,38 +1,51 @@
|
|||||||
|
|
||||||
#include "boost/foreach.hpp"
|
|
||||||
#include "boost/make_shared.hpp"
|
|
||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "LedgerAcquire.h"
|
#include "LedgerAcquire.h"
|
||||||
|
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
#define LEDGER_ACQUIRE_TIMEOUT 2
|
||||||
|
|
||||||
LedgerAcquire::LedgerAcquire(const uint256& hash) : mHash(hash),
|
LedgerAcquire::LedgerAcquire(const uint256& hash) : mHash(hash),
|
||||||
mComplete(false), mFailed(false), mHaveBase(false), mHaveState(false), mHaveTransactions(false)
|
mComplete(false), mFailed(false), mHaveBase(false), mHaveState(false), mHaveTransactions(false),
|
||||||
|
mTimer(theApp->getIOService())
|
||||||
{
|
{
|
||||||
;
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Acquiring ledger " << mHash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::done()
|
void LedgerAcquire::done()
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Done acquiring ledger " << mHash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
std::vector< boost::function<void (LedgerAcquire::pointer)> > triggers;
|
std::vector< boost::function<void (LedgerAcquire::pointer)> > triggers;
|
||||||
|
|
||||||
mLock.lock();
|
mLock.lock();
|
||||||
triggers=mOnComplete;
|
triggers = mOnComplete;
|
||||||
mOnComplete.empty();
|
mOnComplete.empty();
|
||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
|
|
||||||
for(int i=0; i<triggers.size(); i++)
|
for (int i = 0; i<triggers.size(); ++i)
|
||||||
triggers[i](shared_from_this());
|
triggers[i](shared_from_this());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::setTimer()
|
void LedgerAcquire::resetTimer()
|
||||||
{
|
{
|
||||||
// WRITEME
|
mTimer.expires_from_now(boost::posix_time::seconds(LEDGER_ACQUIRE_TIMEOUT));
|
||||||
|
mTimer.async_wait(boost::bind(&LedgerAcquire::timerEntry,
|
||||||
|
boost::weak_ptr<LedgerAcquire>(shared_from_this()), boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::timerEntry(boost::weak_ptr<LedgerAcquire> wptr)
|
void LedgerAcquire::timerEntry(boost::weak_ptr<LedgerAcquire> wptr, const boost::system::error_code& result)
|
||||||
{
|
{
|
||||||
LedgerAcquire::pointer ptr=wptr.lock();
|
if (result == boost::asio::error::operation_aborted) return;
|
||||||
if(ptr) ptr->trigger(true);
|
LedgerAcquire::pointer ptr = wptr.lock();
|
||||||
|
if (!!ptr) ptr->trigger(Peer::pointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)> trigger)
|
void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)> trigger)
|
||||||
@@ -42,29 +55,49 @@ void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)>
|
|||||||
mLock.unlock();
|
mLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::trigger(bool timer)
|
void LedgerAcquire::trigger(Peer::pointer peer)
|
||||||
{
|
{
|
||||||
if(mComplete || mFailed) return;
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Trigger acquiring ledger " << mHash.GetHex() << std::endl;
|
||||||
if(!mHaveBase)
|
std::cerr << "complete=" << mComplete << " failed=" << mFailed << std::endl;
|
||||||
|
std::cerr << "base=" << mHaveBase << " tx=" << mHaveTransactions << " as=" << mHaveState << std::endl;
|
||||||
|
#endif
|
||||||
|
if (mComplete || mFailed)
|
||||||
|
return;
|
||||||
|
if (!mHaveBase)
|
||||||
{
|
{
|
||||||
// WRITEME: Do we need to search for peers?
|
#ifdef DEBUG
|
||||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL=boost::make_shared<newcoin::TMGetLedger>();
|
std::cerr << "need base" << std::endl;
|
||||||
|
#endif
|
||||||
|
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||||
tmGL->set_itype(newcoin::liBASE);
|
tmGL->set_itype(newcoin::liBASE);
|
||||||
sendRequest(tmGL);
|
if (peer)
|
||||||
|
{
|
||||||
|
sendRequest(tmGL, peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else sendRequest(tmGL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mHaveBase && !mHaveTransactions)
|
if (mHaveBase && !mHaveTransactions)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "need tx" << std::endl;
|
||||||
|
#endif
|
||||||
assert(mLedger);
|
assert(mLedger);
|
||||||
if(mLedger->peekTransactionMap()->getHash().isZero())
|
if (mLedger->peekTransactionMap()->getHash().isZero())
|
||||||
{ // we need the root node
|
{ // we need the root node
|
||||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL=boost::make_shared<newcoin::TMGetLedger>();
|
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||||
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
||||||
tmGL->set_itype(newcoin::liTX_NODE);
|
tmGL->set_itype(newcoin::liTX_NODE);
|
||||||
*(tmGL->add_nodeids())=SHAMapNode().getRawString();
|
*(tmGL->add_nodeids()) = SHAMapNode().getRawString();
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
sendRequest(tmGL, peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendRequest(tmGL);
|
sendRequest(tmGL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -72,38 +105,51 @@ void LedgerAcquire::trigger(bool timer)
|
|||||||
std::vector<SHAMapNode> nodeIDs;
|
std::vector<SHAMapNode> nodeIDs;
|
||||||
std::vector<uint256> nodeHashes;
|
std::vector<uint256> nodeHashes;
|
||||||
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
mLedger->peekTransactionMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
||||||
if(nodeIDs.empty())
|
if (nodeIDs.empty())
|
||||||
{
|
{
|
||||||
if(!mLedger->peekTransactionMap()->isValid()) mFailed=true;
|
if (!mLedger->peekTransactionMap()->isValid()) mFailed = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mHaveTransactions=true;
|
mHaveTransactions = true;
|
||||||
if(mHaveState) mComplete=true;
|
if (mHaveState) mComplete = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL=boost::make_shared<newcoin::TMGetLedger>();
|
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||||
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
||||||
tmGL->set_itype(newcoin::liTX_NODE);
|
tmGL->set_itype(newcoin::liTX_NODE);
|
||||||
for(std::vector<SHAMapNode>::iterator it=nodeIDs.begin(); it!=nodeIDs.end(); ++it)
|
for (std::vector<SHAMapNode>::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it)
|
||||||
*(tmGL->add_nodeids())=it->getRawString();
|
*(tmGL->add_nodeids()) = it->getRawString();
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
sendRequest(tmGL, peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendRequest(tmGL);
|
sendRequest(tmGL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mHaveBase && !mHaveState)
|
if (mHaveBase && !mHaveState)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "need as" << std::endl;
|
||||||
|
#endif
|
||||||
assert(mLedger);
|
assert(mLedger);
|
||||||
if(mLedger->peekAccountStateMap()->getHash().isZero())
|
if (mLedger->peekAccountStateMap()->getHash().isZero())
|
||||||
{ // we need the root node
|
{ // we need the root node
|
||||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL=boost::make_shared<newcoin::TMGetLedger>();
|
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||||
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
||||||
tmGL->set_itype(newcoin::liAS_NODE);
|
tmGL->set_itype(newcoin::liAS_NODE);
|
||||||
*(tmGL->add_nodeids())=SHAMapNode().getRawString();
|
*(tmGL->add_nodeids()) = SHAMapNode().getRawString();
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
sendRequest(tmGL, peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendRequest(tmGL);
|
sendRequest(tmGL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -111,50 +157,61 @@ void LedgerAcquire::trigger(bool timer)
|
|||||||
std::vector<SHAMapNode> nodeIDs;
|
std::vector<SHAMapNode> nodeIDs;
|
||||||
std::vector<uint256> nodeHashes;
|
std::vector<uint256> nodeHashes;
|
||||||
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
mLedger->peekAccountStateMap()->getMissingNodes(nodeIDs, nodeHashes, 128);
|
||||||
if(nodeIDs.empty())
|
if (nodeIDs.empty())
|
||||||
{
|
{
|
||||||
if(!mLedger->peekAccountStateMap()->isValid()) mFailed=true;
|
if (!mLedger->peekAccountStateMap()->isValid()) mFailed = true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mHaveState=true;
|
mHaveState = true;
|
||||||
if(mHaveTransactions) mComplete=true;
|
if (mHaveTransactions) mComplete = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::shared_ptr<newcoin::TMGetLedger> tmGL=boost::make_shared<newcoin::TMGetLedger>();
|
boost::shared_ptr<newcoin::TMGetLedger> tmGL = boost::make_shared<newcoin::TMGetLedger>();
|
||||||
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
tmGL->set_ledgerhash(mHash.begin(), mHash.size());
|
||||||
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
|
||||||
tmGL->set_itype(newcoin::liAS_NODE);
|
tmGL->set_itype(newcoin::liAS_NODE);
|
||||||
for(std::vector<SHAMapNode>::iterator it=nodeIDs.begin(); it!=nodeIDs.end(); ++it)
|
for (std::vector<SHAMapNode>::iterator it =nodeIDs.begin(); it != nodeIDs.end(); ++it)
|
||||||
*(tmGL->add_nodeids())=it->getRawString();
|
*(tmGL->add_nodeids()) = it->getRawString();
|
||||||
|
if (peer)
|
||||||
|
{
|
||||||
|
sendRequest(tmGL, peer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sendRequest(tmGL);
|
sendRequest(tmGL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mComplete || mFailed)
|
if (mComplete || mFailed)
|
||||||
done();
|
done();
|
||||||
else if(timer)
|
else
|
||||||
setTimer();
|
resetTimer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL, Peer::pointer peer)
|
||||||
|
{
|
||||||
|
peer->sendPacket(boost::make_shared<PackedMessage>(tmGL, newcoin::mtGET_LEDGER));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
|
void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
if(mPeers.empty()) return;
|
if (mPeers.empty()) return;
|
||||||
|
|
||||||
PackedMessage::pointer packet=boost::make_shared<PackedMessage>(tmGL, newcoin::mtGET_LEDGER);
|
PackedMessage::pointer packet = boost::make_shared<PackedMessage>(tmGL, newcoin::mtGET_LEDGER);
|
||||||
|
|
||||||
std::list<boost::weak_ptr<Peer> >::iterator it=mPeers.begin();
|
std::list<boost::weak_ptr<Peer> >::iterator it = mPeers.begin();
|
||||||
while(it!=mPeers.end())
|
while(it != mPeers.end())
|
||||||
{
|
{
|
||||||
if(it->expired())
|
if (it->expired())
|
||||||
mPeers.erase(it++);
|
mPeers.erase(it++);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// FIXME: Track last peer sent to and time sent
|
// FIXME: Track last peer sent to and time sent
|
||||||
it->lock()->sendPacket(packet);
|
Peer::pointer peer = it->lock();
|
||||||
|
if (peer) peer->sendPacket(packet);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,33 +220,34 @@ void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
|
|||||||
void LedgerAcquire::peerHas(Peer::pointer ptr)
|
void LedgerAcquire::peerHas(Peer::pointer ptr)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
std::list<boost::weak_ptr<Peer> >::iterator it=mPeers.begin();
|
std::list<boost::weak_ptr<Peer> >::iterator it = mPeers.begin();
|
||||||
while(it!=mPeers.end())
|
while (it != mPeers.end())
|
||||||
{
|
{
|
||||||
Peer::pointer pr=it->lock();
|
Peer::pointer pr = it->lock();
|
||||||
if(!pr) // we have a dead entry, remove it
|
if (!pr) // we have a dead entry, remove it
|
||||||
it=mPeers.erase(it);
|
it = mPeers.erase(it);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(pr->samePeer(ptr)) return; // we already have this peer
|
if (pr->samePeer(ptr)) return; // we already have this peer
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mPeers.push_back(ptr);
|
mPeers.push_back(ptr);
|
||||||
|
if (mPeers.size() == 1) trigger(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LedgerAcquire::badPeer(Peer::pointer ptr)
|
void LedgerAcquire::badPeer(Peer::pointer ptr)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
std::list<boost::weak_ptr<Peer> >::iterator it=mPeers.begin();
|
std::list<boost::weak_ptr<Peer> >::iterator it=mPeers.begin();
|
||||||
while(it!=mPeers.end())
|
while (it != mPeers.end())
|
||||||
{
|
{
|
||||||
Peer::pointer pr=it->lock();
|
Peer::pointer pr = it->lock();
|
||||||
if(!pr) // we have a dead entry, remove it
|
if (!pr) // we have a dead entry, remove it
|
||||||
it=mPeers.erase(it);
|
it = mPeers.erase(it);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(ptr->samePeer(pr))
|
if (ptr->samePeer(pr))
|
||||||
{ // We found a pointer to the bad peer
|
{ // We found a pointer to the bad peer
|
||||||
mPeers.erase(it);
|
mPeers.erase(it);
|
||||||
return;
|
return;
|
||||||
@@ -199,110 +257,164 @@ void LedgerAcquire::badPeer(Peer::pointer ptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerAcquire::takeBase(const std::string& data)
|
bool LedgerAcquire::takeBase(const std::string& data, Peer::pointer peer)
|
||||||
{ // Return value: true=normal, false=bad data
|
{ // Return value: true=normal, false=bad data
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "got base acquiring ledger " << mHash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
if(mHaveBase) return true;
|
if (mHaveBase) return true;
|
||||||
Ledger* ledger=new Ledger(data);
|
mLedger = boost::make_shared<Ledger>(data);
|
||||||
if(ledger->getHash()!=mHash)
|
if (mLedger->getHash() != mHash)
|
||||||
{
|
{
|
||||||
delete ledger;
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Acquire hash mismatch" << std::endl;
|
||||||
|
std::cerr << mLedger->getHash().GetHex() << "!=" << mHash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
|
mLedger = Ledger::pointer();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
mLedger=Ledger::pointer(ledger);
|
mHaveBase = true;
|
||||||
|
if (!mLedger->getTransHash()) mHaveTransactions = true;
|
||||||
|
if (!mLedger->getAccountHash()) mHaveState = true;
|
||||||
mLedger->setAcquiring();
|
mLedger->setAcquiring();
|
||||||
mHaveBase=true;
|
trigger(peer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
|
bool LedgerAcquire::takeTxNode(const std::list<SHAMapNode>& nodeIDs,
|
||||||
const std::list<std::vector<unsigned char> >& data)
|
const std::list<std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||||
{
|
{
|
||||||
if(!mHaveBase) return false;
|
if (!mHaveBase) return false;
|
||||||
std::list<SHAMapNode>::const_iterator nodeIDit=nodeIDs.begin();
|
std::list<SHAMapNode>::const_iterator nodeIDit = nodeIDs.begin();
|
||||||
std::list<std::vector<unsigned char> >::const_iterator nodeDatait=data.begin();
|
std::list<std::vector<unsigned char> >::const_iterator nodeDatait = data.begin();
|
||||||
while(nodeIDit!=nodeIDs.end())
|
while (nodeIDit != nodeIDs.end())
|
||||||
{
|
{
|
||||||
if(!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
if (nodeIDit->isRoot())
|
||||||
|
{
|
||||||
|
if (!mLedger->peekTransactionMap()->addRootNode(mLedger->getTransHash(), *nodeDatait))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!mLedger->peekTransactionMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
||||||
return false;
|
return false;
|
||||||
++nodeIDit;
|
++nodeIDit;
|
||||||
++nodeDatait;
|
++nodeDatait;
|
||||||
}
|
}
|
||||||
if(!mLedger->peekTransactionMap()->isSynching()) mHaveTransactions=true;
|
if (!mLedger->peekTransactionMap()->isSynching())
|
||||||
|
{
|
||||||
|
mHaveTransactions = true;
|
||||||
|
if (mHaveState) mComplete = true;
|
||||||
|
}
|
||||||
|
trigger(peer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
|
bool LedgerAcquire::takeAsNode(const std::list<SHAMapNode>& nodeIDs,
|
||||||
const std::list<std::vector<unsigned char> >& data)
|
const std::list<std::vector<unsigned char> >& data, Peer::pointer peer)
|
||||||
{
|
{
|
||||||
if(!mHaveBase) return false;
|
#ifdef DEBUG
|
||||||
std::list<SHAMapNode>::const_iterator nodeIDit=nodeIDs.begin();
|
std::cerr << "got ASdata acquiring ledger " << mHash.GetHex() << std::endl;
|
||||||
std::list<std::vector<unsigned char> >::const_iterator nodeDatait=data.begin();
|
#endif
|
||||||
while(nodeIDit!=nodeIDs.end())
|
if (!mHaveBase) return false;
|
||||||
|
std::list<SHAMapNode>::const_iterator nodeIDit = nodeIDs.begin();
|
||||||
|
std::list<std::vector<unsigned char> >::const_iterator nodeDatait = data.begin();
|
||||||
|
while (nodeIDit != nodeIDs.end())
|
||||||
{
|
{
|
||||||
if(!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
if (nodeIDit->isRoot())
|
||||||
|
{
|
||||||
|
if (!mLedger->peekAccountStateMap()->addRootNode(mLedger->getAccountHash(), *nodeDatait))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (!mLedger->peekAccountStateMap()->addKnownNode(*nodeIDit, *nodeDatait))
|
||||||
return false;
|
return false;
|
||||||
++nodeIDit;
|
++nodeIDit;
|
||||||
++nodeDatait;
|
++nodeDatait;
|
||||||
}
|
}
|
||||||
if(!mLedger->peekAccountStateMap()->isSynching()) mHaveState=true;
|
if (!mLedger->peekAccountStateMap()->isSynching())
|
||||||
|
{
|
||||||
|
mHaveState = true;
|
||||||
|
if (mHaveTransactions) mComplete = true;
|
||||||
|
}
|
||||||
|
trigger(peer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash)
|
LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
LedgerAcquire::pointer& ptr=mLedgers[hash];
|
LedgerAcquire::pointer& ptr = mLedgers[hash];
|
||||||
if(ptr) return ptr;
|
if (ptr) return ptr;
|
||||||
return boost::make_shared<LedgerAcquire>(hash);
|
ptr = boost::make_shared<LedgerAcquire>(hash);
|
||||||
|
assert(mLedgers[hash] == ptr);
|
||||||
|
ptr->resetTimer(); // Cannot call in constructor
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LedgerAcquire::pointer LedgerAcquireMaster::find(const uint256& hash)
|
LedgerAcquire::pointer LedgerAcquireMaster::find(const uint256& hash)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
std::map<uint256, LedgerAcquire::pointer>::iterator it=mLedgers.find(hash);
|
std::map<uint256, LedgerAcquire::pointer>::iterator it = mLedgers.find(hash);
|
||||||
if(it!=mLedgers.end()) return it->second;
|
if (it != mLedgers.end()) return it->second;
|
||||||
return LedgerAcquire::pointer();
|
return LedgerAcquire::pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerAcquireMaster::hasLedger(const uint256& hash)
|
bool LedgerAcquireMaster::hasLedger(const uint256& hash)
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
return mLedgers.find(hash)!=mLedgers.end();
|
return mLedgers.find(hash) != mLedgers.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet)
|
bool LedgerAcquireMaster::dropLedger(const uint256& hash)
|
||||||
{
|
{
|
||||||
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
|
return mLedgers.erase(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer peer)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "got data for acquiring ledger ";
|
||||||
|
#endif
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
if(packet.ledgerhash().size()!=32) return false;
|
if (packet.ledgerhash().size() != 32)
|
||||||
memcpy(&hash, packet.ledgerhash().data(), 32);
|
|
||||||
|
|
||||||
LedgerAcquire::pointer ledger=find(hash);
|
|
||||||
if(!ledger) return false;
|
|
||||||
|
|
||||||
if(packet.type()==newcoin::liBASE)
|
|
||||||
{
|
{
|
||||||
if(packet.nodes_size()!=1) return false;
|
#ifdef DEBUG
|
||||||
const newcoin::TMLedgerNode& node=packet.nodes(0);
|
std::cerr << "error" << std::endl;
|
||||||
if(!node.has_nodedata()) return false;
|
#endif
|
||||||
return ledger->takeBase(node.nodedata());
|
return false;
|
||||||
}
|
}
|
||||||
else if( (packet.type()==newcoin::liTX_NODE) || (packet.type()==newcoin::liAS_NODE) )
|
memcpy(&hash, packet.ledgerhash().data(), 32);
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << hash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LedgerAcquire::pointer ledger = find(hash);
|
||||||
|
if (!ledger) return false;
|
||||||
|
|
||||||
|
if (packet.type() == newcoin::liBASE)
|
||||||
|
{
|
||||||
|
if (packet.nodes_size() != 1) return false;
|
||||||
|
const newcoin::TMLedgerNode& node = packet.nodes(0);
|
||||||
|
if (!node.has_nodedata()) return false;
|
||||||
|
return ledger->takeBase(node.nodedata(), peer);
|
||||||
|
}
|
||||||
|
else if ((packet.type() == newcoin::liTX_NODE) || (packet.type() == newcoin::liAS_NODE))
|
||||||
{
|
{
|
||||||
std::list<SHAMapNode> nodeIDs;
|
std::list<SHAMapNode> nodeIDs;
|
||||||
std::list<std::vector<unsigned char> > nodeData;
|
std::list<std::vector<unsigned char> > nodeData;
|
||||||
|
|
||||||
if(packet.nodes().size()<=0) return false;
|
if (packet.nodes().size()<=0) return false;
|
||||||
for(int i=0; i<packet.nodes().size(); i++)
|
for (int i = 0; i<packet.nodes().size(); ++i)
|
||||||
{
|
{
|
||||||
const newcoin::TMLedgerNode& node=packet.nodes(i);
|
const newcoin::TMLedgerNode& node=packet.nodes(i);
|
||||||
if(!node.has_nodeid() || !node.has_nodedata()) return false;
|
if (!node.has_nodeid() || !node.has_nodedata()) return false;
|
||||||
|
|
||||||
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
|
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
|
||||||
nodeData.push_back(std::vector<unsigned char>(node.nodedata().begin(), node.nodedata().end()));
|
nodeData.push_back(std::vector<unsigned char>(node.nodedata().begin(), node.nodedata().end()));
|
||||||
}
|
}
|
||||||
if(packet.type()==newcoin::liTX_NODE) return ledger->takeTxNode(nodeIDs, nodeData);
|
if (packet.type() == newcoin::liTX_NODE) return ledger->takeTxNode(nodeIDs, nodeData, peer);
|
||||||
else return ledger->takeAsNode(nodeIDs, nodeData);
|
else return ledger->takeAsNode(nodeIDs, nodeData, peer);
|
||||||
}
|
}
|
||||||
else return false;
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,10 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "boost/enable_shared_from_this.hpp"
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include "boost/function.hpp"
|
#include <boost/function.hpp>
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
#include <boost/thread/mutex.hpp>
|
||||||
|
|
||||||
#include "Ledger.h"
|
#include "Ledger.h"
|
||||||
#include "Peer.h"
|
#include "Peer.h"
|
||||||
@@ -21,35 +23,41 @@ protected:
|
|||||||
Ledger::pointer mLedger;
|
Ledger::pointer mLedger;
|
||||||
uint256 mHash;
|
uint256 mHash;
|
||||||
bool mComplete, mFailed, mHaveBase, mHaveState, mHaveTransactions;
|
bool mComplete, mFailed, mHaveBase, mHaveState, mHaveTransactions;
|
||||||
|
|
||||||
|
boost::asio::deadline_timer mTimer;
|
||||||
|
|
||||||
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
|
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
|
||||||
|
|
||||||
std::list<boost::weak_ptr<Peer> > mPeers; // peers known to have this ledger
|
std::list<boost::weak_ptr<Peer> > mPeers; // peers known to have this ledger
|
||||||
|
|
||||||
void done();
|
void done();
|
||||||
void trigger(bool timer);
|
|
||||||
|
|
||||||
static void timerEntry(boost::weak_ptr<LedgerAcquire>);
|
static void timerEntry(boost::weak_ptr<LedgerAcquire>, const boost::system::error_code&);
|
||||||
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message);
|
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message);
|
||||||
void setTimer();
|
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message, Peer::pointer peer);
|
||||||
|
void trigger(Peer::pointer peer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LedgerAcquire(const uint256& hash);
|
LedgerAcquire(const uint256& hash);
|
||||||
|
|
||||||
const uint256& getHash() const { return mHash; }
|
const uint256& getHash() const { return mHash; }
|
||||||
bool isComplete() const { return mComplete; }
|
bool isComplete() const { return mComplete; }
|
||||||
bool isFailed() const { return mFailed; }
|
bool isFailed() const { return mFailed; }
|
||||||
bool isBase() const { return mHaveBase; }
|
bool isBase() const { return mHaveBase; }
|
||||||
bool isAcctStComplete() const { return mHaveState; }
|
bool isAcctStComplete() const { return mHaveState; }
|
||||||
bool isTransComplete() const { return mHaveTransactions; }
|
bool isTransComplete() const { return mHaveTransactions; }
|
||||||
Ledger::pointer getLedger() { return mLedger; }
|
Ledger::pointer getLedger() { return mLedger; }
|
||||||
|
|
||||||
void addOnComplete(boost::function<void (LedgerAcquire::pointer)>);
|
void addOnComplete(boost::function<void (LedgerAcquire::pointer)>);
|
||||||
|
|
||||||
void peerHas(Peer::pointer);
|
void peerHas(Peer::pointer);
|
||||||
void badPeer(Peer::pointer);
|
void badPeer(Peer::pointer);
|
||||||
bool takeBase(const std::string& data);
|
bool takeBase(const std::string& data, Peer::pointer);
|
||||||
bool takeTxNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data);
|
bool takeTxNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data,
|
||||||
bool takeAsNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data);
|
Peer::pointer);
|
||||||
|
bool takeAsNode(const std::list<SHAMapNode>& IDs, const std::list<std::vector<unsigned char> >& data,
|
||||||
|
Peer::pointer);
|
||||||
|
void resetTimer();
|
||||||
};
|
};
|
||||||
|
|
||||||
class LedgerAcquireMaster
|
class LedgerAcquireMaster
|
||||||
@@ -60,11 +68,13 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
LedgerAcquireMaster() { ; }
|
LedgerAcquireMaster() { ; }
|
||||||
|
|
||||||
LedgerAcquire::pointer findCreate(const uint256& hash);
|
LedgerAcquire::pointer findCreate(const uint256& hash);
|
||||||
LedgerAcquire::pointer find(const uint256& hash);
|
LedgerAcquire::pointer find(const uint256& hash);
|
||||||
bool hasLedger(const uint256& ledgerHash);
|
bool hasLedger(const uint256& ledgerHash);
|
||||||
bool gotLedgerData(newcoin::TMLedgerData& packet);
|
bool dropLedger(const uint256& ledgerHash);
|
||||||
|
bool gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ LedgerEntryFormat LedgerFormats[]=
|
|||||||
{ S_FIELD(Balance), STI_UINT64, SOE_REQUIRED, 0 },
|
{ S_FIELD(Balance), STI_UINT64, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
|
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
|
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
|
||||||
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 1 },
|
{ S_FIELD(AuthorizedKey),STI_VL, SOE_IFFLAG, 1 },
|
||||||
{ S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 2 },
|
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
|
||||||
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 4 },
|
{ S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 4 },
|
||||||
|
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
@@ -33,6 +34,13 @@ LedgerEntryFormat LedgerFormats[]=
|
|||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
|
{ "GeneratorMap", ltGENERATOR_MAP, {
|
||||||
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
|
{ S_FIELD(GeneratorID), STI_ACCOUNT, SOE_REQUIRED, 0 },
|
||||||
|
{ S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 },
|
||||||
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
|
},
|
||||||
{ "Nickname", ltNICKNAME, {
|
{ "Nickname", ltNICKNAME, {
|
||||||
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
|
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
|
|
||||||
enum LedgerEntryType
|
enum LedgerEntryType
|
||||||
{
|
{
|
||||||
ltINVALID=-1,
|
ltINVALID =-1,
|
||||||
ltACCOUNT_ROOT=0,
|
ltACCOUNT_ROOT =0,
|
||||||
ltRIPPLE_STATE=1,
|
ltRIPPLE_STATE =1,
|
||||||
ltNICKNAME=2
|
ltGENERATOR_MAP =2,
|
||||||
|
ltNICKNAME =3
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LedgerEntryFormat
|
struct LedgerEntryFormat
|
||||||
@@ -21,3 +22,4 @@ struct LedgerEntryFormat
|
|||||||
extern LedgerEntryFormat LedgerFormats[];
|
extern LedgerEntryFormat LedgerFormats[];
|
||||||
extern LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
|
extern LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)
|
|||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
std::map<uint32, Ledger::pointer>::iterator it(mLedgersByIndex.find(index));
|
std::map<uint32, Ledger::pointer>::iterator it(mLedgersByIndex.find(index));
|
||||||
if(it!=mLedgersByIndex.end()) return it->second;
|
if (it != mLedgersByIndex.end()) return it->second;
|
||||||
sl.unlock();
|
sl.unlock();
|
||||||
|
|
||||||
Ledger::pointer ret(Ledger::loadByIndex(index));
|
Ledger::pointer ret(Ledger::loadByIndex(index));
|
||||||
if(!ret) return ret;
|
if (!ret) return ret;
|
||||||
assert(ret->getLedgerSeq()==index);
|
assert(ret->getLedgerSeq() == index);
|
||||||
|
|
||||||
sl.lock();
|
sl.lock();
|
||||||
mLedgersByHash.canonicalize(ret->getHash(), ret);
|
mLedgersByHash.canonicalize(ret->getHash(), ret);
|
||||||
@@ -54,16 +54,16 @@ Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)
|
|||||||
|
|
||||||
Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash)
|
Ledger::pointer LedgerHistory::getLedgerByHash(const uint256& hash)
|
||||||
{
|
{
|
||||||
Ledger::pointer ret=mLedgersByHash.fetch(hash);
|
Ledger::pointer ret = mLedgersByHash.fetch(hash);
|
||||||
if(ret) return ret;
|
if (ret) return ret;
|
||||||
|
|
||||||
ret=Ledger::loadByHash(hash);
|
ret = Ledger::loadByHash(hash);
|
||||||
if(!ret) return ret;
|
if (!ret) return ret;
|
||||||
assert(ret->getHash()==hash);
|
assert(ret->getHash() == hash);
|
||||||
|
|
||||||
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
mLedgersByHash.canonicalize(hash, ret);
|
mLedgersByHash.canonicalize(hash, ret);
|
||||||
if(ret->isAccepted()) mLedgersByIndex[ret->getLedgerSeq()]=ret;
|
if (ret->isAccepted()) mLedgersByIndex[ret->getLedgerSeq()] = ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,16 +71,17 @@ Ledger::pointer LedgerHistory::canonicalizeLedger(Ledger::pointer ledger, bool s
|
|||||||
{
|
{
|
||||||
uint256 h(ledger->getHash());
|
uint256 h(ledger->getHash());
|
||||||
|
|
||||||
if(!save)
|
if (!save)
|
||||||
{ // return input ledger if not in map, otherwise, return corresponding map ledger
|
{ // return input ledger if not in map, otherwise, return corresponding map ledger
|
||||||
Ledger::pointer ret=mLedgersByHash.fetch(h);
|
Ledger::pointer ret = mLedgersByHash.fetch(h);
|
||||||
if(ret) return ret;
|
if (ret) return ret;
|
||||||
return ledger;
|
return ledger;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save input ledger in map if not in map, otherwise return corresponding map ledger
|
// save input ledger in map if not in map, otherwise return corresponding map ledger
|
||||||
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
|
||||||
mLedgersByHash.canonicalize(h, ledger);
|
mLedgersByHash.canonicalize(h, ledger);
|
||||||
if(ledger->isAccepted()) mLedgersByIndex[ledger->getLedgerSeq()]=ledger;
|
if (ledger->isAccepted()) mLedgersByIndex[ledger->getLedgerSeq()]=ledger;
|
||||||
return ledger;
|
return ledger;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class LedgerHistory
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
LedgerHistory();
|
LedgerHistory();
|
||||||
|
|
||||||
void addLedger(Ledger::pointer ledger);
|
void addLedger(Ledger::pointer ledger);
|
||||||
void addAcceptedLedger(Ledger::pointer ledger);
|
void addAcceptedLedger(Ledger::pointer ledger);
|
||||||
|
|
||||||
|
|||||||
@@ -14,3 +14,4 @@ uint256 Ledger::getRippleIndex(const uint160& accountID, const uint160& extendTo
|
|||||||
memcpy(base.begin() + (160/8), (accountID^currency).begin(), (256/8)-(160/8));
|
memcpy(base.begin() + (160/8), (accountID^currency).begin(), (256/8)-(160/8));
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "LedgerMaster.h"
|
#include "LedgerMaster.h"
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "NewcoinAddress.h"
|
#include "NewcoinAddress.h"
|
||||||
#include "TimingService.h"
|
|
||||||
#include "Conversion.h"
|
#include "Conversion.h"
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
|
|
||||||
@@ -36,6 +35,17 @@ void LedgerMaster::pushLedger(Ledger::pointer newLedger)
|
|||||||
mEngine.setLedger(newLedger);
|
mEngine.setLedger(newLedger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LedgerMaster::switchLedgers(Ledger::pointer lastClosed, Ledger::pointer current)
|
||||||
|
{
|
||||||
|
mFinalizedLedger = lastClosed;
|
||||||
|
mFinalizedLedger->setClosed();
|
||||||
|
mFinalizedLedger->setAccepted();
|
||||||
|
|
||||||
|
mCurrentLedger = current;
|
||||||
|
assert(!mCurrentLedger->isClosed());
|
||||||
|
mEngine.setLedger(mCurrentLedger);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
void LedgerMaster::startFinalization()
|
void LedgerMaster::startFinalization()
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
{ return mEngine.applyTransaction(txn, params); }
|
{ return mEngine.applyTransaction(txn, params); }
|
||||||
|
|
||||||
void pushLedger(Ledger::pointer newLedger);
|
void pushLedger(Ledger::pointer newLedger);
|
||||||
|
void switchLedgers(Ledger::pointer lastClosed, Ledger::pointer newCurrent);
|
||||||
|
|
||||||
Ledger::pointer getLedgerBySeq(uint32 index)
|
Ledger::pointer getLedgerBySeq(uint32 index)
|
||||||
{
|
{
|
||||||
@@ -66,3 +67,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -109,3 +109,4 @@ SerializedLedgerEntry::pointer Ledger::getNickname(LedgerStateParms& parms, cons
|
|||||||
return SerializedLedgerEntry::pointer();
|
return SerializedLedgerEntry::pointer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
// core account information
|
// core account information
|
||||||
CKey::pointer mPublicKey;
|
CKey::pointer mPublicKey;
|
||||||
NewcoinAddress mAcctID;
|
NewcoinAddress mAccount;
|
||||||
std::string mComment;
|
std::string mComment;
|
||||||
|
|
||||||
// family information
|
// family information
|
||||||
@@ -32,7 +32,7 @@ public:
|
|||||||
bool updateName(); // writes changed name/comment
|
bool updateName(); // writes changed name/comment
|
||||||
bool updateBalance(); // writes changed balance/seq
|
bool updateBalance(); // writes changed balance/seq
|
||||||
|
|
||||||
const NewcoinAddress& getAddress() const { return mAcctID; }
|
const NewcoinAddress& getAddress() const { return mAccount; }
|
||||||
int getAcctFSeq() const { return mAccountFSeq; }
|
int getAcctFSeq() const { return mAccountFSeq; }
|
||||||
|
|
||||||
std::string getFullName() const;
|
std::string getFullName() const;
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
|
|
||||||
#include "Application.h"
|
|
||||||
#include "NetworkOPs.h"
|
#include "NetworkOPs.h"
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <boost/unordered_map.hpp>
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
#include "Application.h"
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
|
|
||||||
|
|
||||||
// This is the primary interface into the "client" portion of the program.
|
// This is the primary interface into the "client" portion of the program.
|
||||||
// Code that wants to do normal operations on the network such as
|
// Code that wants to do normal operations on the network such as
|
||||||
// creating and monitoring accounts, creating transactions, and so on
|
// creating and monitoring accounts, creating transactions, and so on
|
||||||
@@ -14,9 +20,18 @@
|
|||||||
// code assumes this node is synched (and will continue to do so until
|
// code assumes this node is synched (and will continue to do so until
|
||||||
// there's a functional network.
|
// there's a functional network.
|
||||||
|
|
||||||
uint64 NetworkOPs::getNetworkTime()
|
NetworkOPs::NetworkOPs(boost::asio::io_service& io_service) : mMode(omDISCONNECTED), mNetTimer(io_service)
|
||||||
{
|
{
|
||||||
return time(NULL);
|
}
|
||||||
|
|
||||||
|
boost::posix_time::ptime NetworkOPs::getNetworkTimePT()
|
||||||
|
{
|
||||||
|
return boost::posix_time::second_clock::universal_time();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 NetworkOPs::getNetworkTimeNC()
|
||||||
|
{
|
||||||
|
return iToSeconds(getNetworkTimePT());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 NetworkOPs::getCurrentLedgerID()
|
uint32 NetworkOPs::getCurrentLedgerID()
|
||||||
@@ -26,10 +41,10 @@ uint32 NetworkOPs::getCurrentLedgerID()
|
|||||||
|
|
||||||
Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, Peer* source)
|
Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans, Peer* source)
|
||||||
{
|
{
|
||||||
Transaction::pointer dbtx=theApp->getMasterTransaction().fetch(trans->getID(), true);
|
Transaction::pointer dbtx = theApp->getMasterTransaction().fetch(trans->getID(), true);
|
||||||
if(dbtx) return dbtx;
|
if (dbtx) return dbtx;
|
||||||
|
|
||||||
if(!trans->checkSign())
|
if (!trans->checkSign())
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Transaction has bad signature" << std::endl;
|
std::cerr << "Transaction has bad signature" << std::endl;
|
||||||
@@ -38,10 +53,10 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
|||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionEngineResult r=theApp->getMasterLedger().doTransaction(*trans->getSTransaction(), tepNONE);
|
TransactionEngineResult r = theApp->getMasterLedger().doTransaction(*trans->getSTransaction(), tepNONE);
|
||||||
if(r==terFAILED) throw Fault(IO_ERROR);
|
if (r == terFAILED) throw Fault(IO_ERROR);
|
||||||
|
|
||||||
if(r == terPRE_SEQ)
|
if (r == terPRE_SEQ)
|
||||||
{ // transaction should be held
|
{ // transaction should be held
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Transaction should be held" << std::endl;
|
std::cerr << "Transaction should be held" << std::endl;
|
||||||
@@ -51,7 +66,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
|||||||
theApp->getMasterLedger().addHeldTransaction(trans);
|
theApp->getMasterLedger().addHeldTransaction(trans);
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
if ( (r==terPAST_SEQ || r==terPAST_LEDGER) )
|
if ((r == terPAST_SEQ) || (r == terPAST_LEDGER))
|
||||||
{ // duplicate or conflict
|
{ // duplicate or conflict
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Transaction is obsolete" << std::endl;
|
std::cerr << "Transaction is obsolete" << std::endl;
|
||||||
@@ -60,7 +75,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
|||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(r==terSUCCESS)
|
if (r == terSUCCESS)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Transaction is now included, synching to wallet" << std::endl;
|
std::cerr << "Transaction is now included, synching to wallet" << std::endl;
|
||||||
@@ -73,13 +88,13 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
|
|||||||
// no cache the account balance information and always get it from the current ledger
|
// no cache the account balance information and always get it from the current ledger
|
||||||
// theApp->getWallet().applyTransaction(trans);
|
// theApp->getWallet().applyTransaction(trans);
|
||||||
|
|
||||||
newcoin::TMTransaction *tx=new newcoin::TMTransaction();
|
boost::shared_ptr<newcoin::TMTransaction> tx = boost::make_shared<newcoin::TMTransaction>();
|
||||||
|
|
||||||
Serializer::pointer s;
|
Serializer::pointer s;
|
||||||
trans->getSTransaction()->getTransaction(*s, false);
|
trans->getSTransaction()->getTransaction(*s, false);
|
||||||
tx->set_rawtransaction(&s->getData().front(), s->getLength());
|
tx->set_rawtransaction(&s->getData().front(), s->getLength());
|
||||||
tx->set_status(newcoin::tsCURRENT);
|
tx->set_status(newcoin::tsCURRENT);
|
||||||
tx->set_receivetimestamp(getNetworkTime());
|
tx->set_receivetimestamp(getNetworkTimeNC());
|
||||||
tx->set_ledgerindexpossible(trans->getLedger());
|
tx->set_ledgerindexpossible(trans->getLedger());
|
||||||
|
|
||||||
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(tx), newcoin::mtTRANSACTION));
|
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(tx), newcoin::mtTRANSACTION));
|
||||||
@@ -104,20 +119,20 @@ Transaction::pointer NetworkOPs::findTransactionByID(const uint256& transactionI
|
|||||||
int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
|
int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
|
||||||
const NewcoinAddress& sourceAccount, uint32 minSeq, uint32 maxSeq)
|
const NewcoinAddress& sourceAccount, uint32 minSeq, uint32 maxSeq)
|
||||||
{
|
{
|
||||||
AccountState::pointer state=getAccountState(sourceAccount);
|
AccountState::pointer state = getAccountState(sourceAccount);
|
||||||
if(!state) return 0;
|
if (!state) return 0;
|
||||||
if(minSeq>state->getSeq()) return 0;
|
if (minSeq > state->getSeq()) return 0;
|
||||||
if(maxSeq>state->getSeq()) maxSeq=state->getSeq();
|
if (maxSeq > state->getSeq()) maxSeq = state->getSeq();
|
||||||
if(maxSeq>minSeq) return 0;
|
if (maxSeq > minSeq) return 0;
|
||||||
|
|
||||||
int count=0;
|
int count = 0;
|
||||||
for(int i=minSeq; i<=maxSeq; i++)
|
for(int i = minSeq; i <= maxSeq; ++i)
|
||||||
{
|
{
|
||||||
Transaction::pointer txn=Transaction::findFrom(sourceAccount, i);
|
Transaction::pointer txn = Transaction::findFrom(sourceAccount, i);
|
||||||
if(txn)
|
if(txn)
|
||||||
{
|
{
|
||||||
txns.push_back(txn);
|
txns.push_back(txn);
|
||||||
count++;
|
++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@@ -134,3 +149,215 @@ AccountState::pointer NetworkOPs::getAccountState(const NewcoinAddress& accountI
|
|||||||
{
|
{
|
||||||
return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID);
|
return theApp->getMasterLedger().getCurrentLedger()->getAccountState(accountID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetworkOPs::setStateTimer(int sec)
|
||||||
|
{ // set timer early if ledger is closing
|
||||||
|
uint64 closedTime = theApp->getMasterLedger().getCurrentLedger()->getCloseTimeNC();
|
||||||
|
uint64 now = getNetworkTimeNC();
|
||||||
|
|
||||||
|
if (mMode == omFULL)
|
||||||
|
{
|
||||||
|
if (now >= closedTime) sec = 0;
|
||||||
|
else if (sec > (closedTime - now)) sec = (closedTime - now);
|
||||||
|
}
|
||||||
|
|
||||||
|
mNetTimer.expires_from_now(boost::posix_time::seconds(sec));
|
||||||
|
mNetTimer.async_wait(boost::bind(&NetworkOPs::checkState, this, boost::asio::placeholders::error));
|
||||||
|
}
|
||||||
|
|
||||||
|
class ValidationCount
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int trustedValidations, untrustedValidations, nodesUsing;
|
||||||
|
NewcoinAddress highNode;
|
||||||
|
|
||||||
|
ValidationCount() : trustedValidations(0), untrustedValidations(0), nodesUsing(0) { ; }
|
||||||
|
bool operator>(const ValidationCount& v)
|
||||||
|
{
|
||||||
|
if (trustedValidations > v.trustedValidations) return true;
|
||||||
|
if (trustedValidations < v.trustedValidations) return false;
|
||||||
|
if (untrustedValidations > v.untrustedValidations) return true;
|
||||||
|
if (untrustedValidations < v.untrustedValidations) return false;
|
||||||
|
if (nodesUsing > v.nodesUsing) return true;
|
||||||
|
if (nodesUsing < v.nodesUsing) return false;
|
||||||
|
return highNode > v.highNode;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void NetworkOPs::checkState(const boost::system::error_code& result)
|
||||||
|
{ // Network state machine
|
||||||
|
if (result == boost::asio::error::operation_aborted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<Peer::pointer> peerList = theApp->getConnectionPool().getPeerVector();
|
||||||
|
|
||||||
|
// do we have sufficient peers? If not, we are disconnected.
|
||||||
|
if (peerList.size() < theConfig.NETWORK_QUORUM)
|
||||||
|
{
|
||||||
|
if (mMode != omDISCONNECTED)
|
||||||
|
{
|
||||||
|
mMode = omDISCONNECTED;
|
||||||
|
std::cerr << "Node count (" << peerList.size() <<
|
||||||
|
") has fallen below quorum (" << theConfig.NETWORK_QUORUM << ")." << std::endl;
|
||||||
|
}
|
||||||
|
setStateTimer(5);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mMode == omDISCONNECTED)
|
||||||
|
{
|
||||||
|
mMode = omCONNECTED;
|
||||||
|
std::cerr << "Node count (" << peerList.size() << ") is sufficient." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do we have sufficient validations for our last closed ledger? Or do sufficient nodes
|
||||||
|
// agree? And do we have no better ledger available?
|
||||||
|
// If so, we are either tracking or full.
|
||||||
|
boost::unordered_map<uint256, ValidationCount, hash_SMN> ledgers;
|
||||||
|
|
||||||
|
for (std::vector<Peer::pointer>::iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
|
||||||
|
{
|
||||||
|
if (!*it)
|
||||||
|
{
|
||||||
|
std::cerr << "NOP::CS Dead pointer in peer list" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint256 peerLedger = (*it)->getClosedLedgerHash();
|
||||||
|
if (!!peerLedger)
|
||||||
|
{
|
||||||
|
// FIXME: If we have this ledger, don't count it if it's too far past its close time
|
||||||
|
ValidationCount& vc = ledgers[peerLedger];
|
||||||
|
if ((vc.nodesUsing == 0) || ((*it)->getNodePublic() > vc.highNode))
|
||||||
|
vc.highNode = (*it)->getNodePublic();
|
||||||
|
++vc.nodesUsing;
|
||||||
|
// WRITEME: Validations, trusted peers
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ledger::pointer currentClosed = theApp->getMasterLedger().getClosedLedger();
|
||||||
|
uint256 closedLedger = currentClosed->getHash();
|
||||||
|
ValidationCount& vc = ledgers[closedLedger];
|
||||||
|
if ((vc.nodesUsing == 0) || (theApp->getWallet().getNodePublic() > vc.highNode))
|
||||||
|
vc.highNode = theApp->getWallet().getNodePublic();
|
||||||
|
++ledgers[closedLedger].nodesUsing;
|
||||||
|
|
||||||
|
// 3) Is there a network ledger we'd like to switch to? If so, do we have it?
|
||||||
|
bool switchLedgers = false;
|
||||||
|
for(boost::unordered_map<uint256, ValidationCount>::iterator it = ledgers.begin(), end = ledgers.end();
|
||||||
|
it != end; ++it)
|
||||||
|
{
|
||||||
|
if (it->second > vc)
|
||||||
|
{
|
||||||
|
vc = it->second;
|
||||||
|
closedLedger = it->first;
|
||||||
|
switchLedgers = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (switchLedgers)
|
||||||
|
{
|
||||||
|
std::cerr << "We are not running on the consensus ledger" << std::endl;
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Our LCL " << currentClosed->getHash().GetHex() << std::endl;
|
||||||
|
std::cerr << "Net LCL " << closedLedger.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
|
if ((mMode == omTRACKING) || (mMode == omFULL)) mMode = omTRACKING;
|
||||||
|
Ledger::pointer consensus = theApp->getMasterLedger().getLedgerByHash(closedLedger);
|
||||||
|
if (!consensus)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Acquiring consensus ledger" << std::endl;
|
||||||
|
#endif
|
||||||
|
LedgerAcquire::pointer acq = theApp->getMasterLedgerAcquire().findCreate(closedLedger);
|
||||||
|
if (!acq || acq->isFailed())
|
||||||
|
{
|
||||||
|
theApp->getMasterLedgerAcquire().dropLedger(closedLedger);
|
||||||
|
std::cerr << "Network ledger cannot be acquired" << std::endl;
|
||||||
|
setStateTimer(10);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!acq->isComplete())
|
||||||
|
{ // add more peers
|
||||||
|
// FIXME: A peer may not have a ledger just because it accepts it as the network's consensus
|
||||||
|
for (std::vector<Peer::pointer>::iterator it = peerList.begin(), end = peerList.end(); it != end; ++it)
|
||||||
|
if ((*it)->getClosedLedgerHash() == closedLedger)
|
||||||
|
acq->peerHas(*it);
|
||||||
|
setStateTimer(5);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
consensus = acq->getLedger();
|
||||||
|
}
|
||||||
|
switchLastClosedLedger(consensus, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMode == omCONNECTED)
|
||||||
|
{
|
||||||
|
// check if the ledger is good enough to go to omTRACKING
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMode == omTRACKING)
|
||||||
|
{
|
||||||
|
// check if the ledger is good enough to go to omFULL
|
||||||
|
// check if the ledger is bad enough to go to omCONNECTED
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mMode == omFULL)
|
||||||
|
{
|
||||||
|
// check if the ledger is bad enough to go to omTRACKING
|
||||||
|
}
|
||||||
|
|
||||||
|
Ledger::pointer currentLedger = theApp->getMasterLedger().getCurrentLedger();
|
||||||
|
if (getNetworkTimeNC() >= currentLedger->getCloseTimeNC())
|
||||||
|
{
|
||||||
|
currentLedger->setClosed();
|
||||||
|
switchLastClosedLedger(currentLedger, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
setStateTimer(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NetworkOPs::switchLastClosedLedger(Ledger::pointer newLedger, bool normal)
|
||||||
|
{ // set the newledger as our last closed ledger
|
||||||
|
// FIXME: Correct logic is:
|
||||||
|
// 1) Mark this ledger closed, schedule it to be saved
|
||||||
|
// 2) If normal, reprocess transactions
|
||||||
|
// 3) Open a new subsequent ledger
|
||||||
|
// 4) Walk back the previous ledger chain from our current ledger and the new last closed ledger
|
||||||
|
// find a common previous ledger, if possible. Try to insert any transactions in our ledger
|
||||||
|
// chain into the new open ledger. Broadcast any that make it in.
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Switching last closed ledger to " << newLedger->getHash().GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
newLedger->setClosed();
|
||||||
|
Ledger::pointer openLedger = boost::make_shared<Ledger>(newLedger);
|
||||||
|
theApp->getMasterLedger().switchLedgers(newLedger, openLedger);
|
||||||
|
|
||||||
|
if (getNetworkTimeNC() > openLedger->getCloseTimeNC())
|
||||||
|
{ // this ledger has already closed
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::shared_ptr<newcoin::TMStatusChange> s = boost::make_shared<newcoin::TMStatusChange>();
|
||||||
|
|
||||||
|
s->set_newevent(normal ? newcoin::neACCEPTED_LEDGER : newcoin::neSWITCHED_LEDGER);
|
||||||
|
s->set_ledgerseq(newLedger->getLedgerSeq());
|
||||||
|
s->set_networktime(getNetworkTimeNC());
|
||||||
|
|
||||||
|
uint256 lhash = newLedger->getHash();
|
||||||
|
s->set_ledgerhash(lhash.begin(), lhash.size());
|
||||||
|
lhash = newLedger->getParentHash();
|
||||||
|
s->set_previousledgerhash(lhash.begin(), lhash.size());
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Broadcasting ledger change" << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PackedMessage::pointer packet =
|
||||||
|
boost::make_shared<PackedMessage>(PackedMessage::MessagePointer(s), newcoin::mtSTATUS_CHANGE);
|
||||||
|
theApp->getConnectionPool().relayMessage(NULL, packet);
|
||||||
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,40 +1,49 @@
|
|||||||
#ifndef __NETWORK_OPS__
|
#ifndef __NETWORK_OPS__
|
||||||
#define __NETWORK_OPS__
|
#define __NETWORK_OPS__
|
||||||
|
|
||||||
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
#include "Transaction.h"
|
#include "Transaction.h"
|
||||||
#include "AccountState.h"
|
#include "AccountState.h"
|
||||||
|
#include "Ledger.h"
|
||||||
|
|
||||||
// Operations that clients may wish to perform against the network
|
// Operations that clients may wish to perform against the network
|
||||||
|
// Master operational handler, server sequencer, network tracker
|
||||||
|
|
||||||
class Peer;
|
class Peer;
|
||||||
|
|
||||||
class NetworkOPs
|
class NetworkOPs
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
enum Fault
|
enum Fault
|
||||||
{ // exceptions these functions can throw
|
{ // exceptions these functions can throw
|
||||||
IO_ERROR=1,
|
IO_ERROR = 1,
|
||||||
NO_NETWORK=2,
|
NO_NETWORK = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum OperatingMode
|
enum OperatingMode
|
||||||
{ // how we process transactions or account balance requests
|
{ // how we process transactions or account balance requests
|
||||||
FAULTED=0, // we are unable to process requests (not ready or no network)
|
omDISCONNECTED = 0, // not ready to process requests
|
||||||
FULL_LOCAL=1, // we are in full local sync
|
omCONNECTED = 1, // convinced we are talking to the network
|
||||||
PART_LOCAL=2, // we can validate remote data but have to request it
|
omTRACKING = 2, // convinced we agree with the network
|
||||||
REMOTE=3 // we have to trust remote nodes
|
omFULL = 3 // we have the ledger and can even validate
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
|
OperatingMode mMode;
|
||||||
|
boost::asio::deadline_timer mNetTimer;
|
||||||
|
|
||||||
// context information
|
public:
|
||||||
OperatingMode getOperatingMode();
|
NetworkOPs(boost::asio::io_service& io_service);
|
||||||
|
|
||||||
// network information
|
// network information
|
||||||
uint64 getNetworkTime();
|
uint64 getNetworkTimeNC();
|
||||||
|
boost::posix_time::ptime getNetworkTimePT();
|
||||||
uint32 getCurrentLedgerID();
|
uint32 getCurrentLedgerID();
|
||||||
|
OperatingMode getOperatingMode() { return mMode; }
|
||||||
|
|
||||||
// transaction operations
|
// transaction operations
|
||||||
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source=NULL);
|
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source = NULL);
|
||||||
Transaction::pointer findTransactionByID(const uint256& transactionID);
|
Transaction::pointer findTransactionByID(const uint256& transactionID);
|
||||||
int findTransactionsBySource(std::list<Transaction::pointer>&, const NewcoinAddress& sourceAccount,
|
int findTransactionsBySource(std::list<Transaction::pointer>&, const NewcoinAddress& sourceAccount,
|
||||||
uint32 minSeq, uint32 maxSeq);
|
uint32 minSeq, uint32 maxSeq);
|
||||||
@@ -44,19 +53,24 @@ public:
|
|||||||
// account operations
|
// account operations
|
||||||
AccountState::pointer getAccountState(const NewcoinAddress& accountID);
|
AccountState::pointer getAccountState(const NewcoinAddress& accountID);
|
||||||
|
|
||||||
// contact block operations
|
|
||||||
|
|
||||||
// raw object operations
|
// raw object operations
|
||||||
bool findRawLedger(const uint256& ledgerHash, std::vector<unsigned char>& rawLedger);
|
bool findRawLedger(const uint256& ledgerHash, std::vector<unsigned char>& rawLedger);
|
||||||
bool findRawTransaction(const uint256& transactionHash, std::vector<unsigned char>& rawTransaction);
|
bool findRawTransaction(const uint256& transactionHash, std::vector<unsigned char>& rawTransaction);
|
||||||
bool findAccountNode(const uint256& nodeHash, std::vector<unsigned char>& rawAccountNode);
|
bool findAccountNode(const uint256& nodeHash, std::vector<unsigned char>& rawAccountNode);
|
||||||
bool findTransactionNode(const uint256& nodeHash, std::vector<unsigned char>& rawTransactionNode);
|
bool findTransactionNode(const uint256& nodeHash, std::vector<unsigned char>& rawTransactionNode);
|
||||||
|
|
||||||
// tree synchronzation operations
|
// tree synchronization operations
|
||||||
bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID,
|
bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID,
|
||||||
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
||||||
bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId,
|
bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId,
|
||||||
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
|
||||||
|
|
||||||
|
// network state machine
|
||||||
|
void checkState(const boost::system::error_code& result);
|
||||||
|
void switchLastClosedLedger(Ledger::pointer newLedger, bool normal);
|
||||||
|
void setStateTimer(int seconds);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "BitcoinUtil.h"
|
#include "BitcoinUtil.h"
|
||||||
#include "rfc1751.h"
|
#include "rfc1751.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
#include "openssl/rand.h"
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include <boost/functional/hash.hpp>
|
#include <boost/functional/hash.hpp>
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
|
||||||
NewcoinAddress::NewcoinAddress()
|
NewcoinAddress::NewcoinAddress()
|
||||||
{
|
{
|
||||||
@@ -273,7 +273,7 @@ void NewcoinAddress::setAccountPublic(const std::vector<unsigned char>& vPublic)
|
|||||||
|
|
||||||
void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
|
void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
|
||||||
{
|
{
|
||||||
CKey pubkey = CKey(generator, seq);
|
CKey pubkey = CKey(generator, seq+1);
|
||||||
|
|
||||||
setAccountPublic(pubkey.GetPubKey());
|
setAccountPublic(pubkey.GetPubKey());
|
||||||
}
|
}
|
||||||
@@ -282,14 +282,14 @@ void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
|
|||||||
// AccountPrivate
|
// AccountPrivate
|
||||||
//
|
//
|
||||||
|
|
||||||
uint256 NewcoinAddress::getAccountPrivate() const
|
const std::vector<unsigned char>& NewcoinAddress::getAccountPrivate() const
|
||||||
{
|
{
|
||||||
switch (nVersion) {
|
switch (nVersion) {
|
||||||
case VER_NONE:
|
case VER_NONE:
|
||||||
throw std::runtime_error("unset source");
|
throw std::runtime_error("unset source");
|
||||||
|
|
||||||
case VER_ACCOUNT_PRIVATE:
|
case VER_ACCOUNT_PRIVATE:
|
||||||
return uint256(vchData);
|
return vchData;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
throw std::runtime_error(str(boost::format("bad source: %d") % int(nVersion)));
|
||||||
@@ -325,6 +325,73 @@ void NewcoinAddress::setAccountPrivate(uint256 hash256)
|
|||||||
SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32);
|
SetData(VER_ACCOUNT_PRIVATE, hash256.begin(), 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NewcoinAddress::setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq)
|
||||||
|
{
|
||||||
|
CKey privkey = CKey(generator, seed.getFamilyPrivateKey(), seq+1);
|
||||||
|
|
||||||
|
setAccountPrivate(privkey.GetPrivKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> NewcoinAddress::accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText)
|
||||||
|
{
|
||||||
|
CKey ckPrivate;
|
||||||
|
CKey ckPublic;
|
||||||
|
std::vector<unsigned char> vucCipherText;
|
||||||
|
|
||||||
|
if (!ckPublic.SetPubKey(naPublicTo.getAccountPublic()))
|
||||||
|
{
|
||||||
|
// Bad public key.
|
||||||
|
std::cerr << "accountPrivateEncrypt: Bad public key." << std::endl;
|
||||||
|
}
|
||||||
|
else if (!ckPrivate.SetPrivKey(getAccountPrivate()))
|
||||||
|
{
|
||||||
|
// Bad private key.
|
||||||
|
std::cerr << "accountPrivateEncrypt: Bad private key." << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
vucCipherText = ckPrivate.encryptECIES(ckPublic, vucPlainText);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
nothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vucCipherText;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> NewcoinAddress::accountPrivateDecrypt(const NewcoinAddress& naPublicFrom, const std::vector<unsigned char>& vucCipherText)
|
||||||
|
{
|
||||||
|
CKey ckPrivate;
|
||||||
|
CKey ckPublic;
|
||||||
|
std::vector<unsigned char> vucPlainText;
|
||||||
|
|
||||||
|
if (!ckPublic.SetPubKey(naPublicFrom.getAccountPublic()))
|
||||||
|
{
|
||||||
|
// Bad public key.
|
||||||
|
std::cerr << "accountPrivateDecrypt: Bad public key." << std::endl;
|
||||||
|
}
|
||||||
|
else if (!ckPrivate.SetPrivKey(getAccountPrivate()))
|
||||||
|
{
|
||||||
|
// Bad private key.
|
||||||
|
std::cerr << "accountPrivateDecrypt: Bad private key." << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
vucPlainText = ckPrivate.decryptECIES(ckPublic, vucCipherText);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
nothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vucPlainText;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Family Generators
|
// Family Generators
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -78,13 +78,20 @@ public:
|
|||||||
//
|
//
|
||||||
// Accounts Private
|
// Accounts Private
|
||||||
//
|
//
|
||||||
uint256 getAccountPrivate() const;
|
const std::vector<unsigned char>& getAccountPrivate() const;
|
||||||
|
|
||||||
std::string humanAccountPrivate() const;
|
std::string humanAccountPrivate() const;
|
||||||
|
|
||||||
bool setAccountPrivate(const std::string& strPrivate);
|
bool setAccountPrivate(const std::string& strPrivate);
|
||||||
void setAccountPrivate(const std::vector<unsigned char>& vPrivate);
|
void setAccountPrivate(const std::vector<unsigned char>& vPrivate);
|
||||||
void setAccountPrivate(uint256 hash256);
|
void setAccountPrivate(uint256 hash256);
|
||||||
|
void setAccountPrivate(const NewcoinAddress& generator, const NewcoinAddress& seed, int seq);
|
||||||
|
|
||||||
|
// Encrypt a message.
|
||||||
|
std::vector<unsigned char> accountPrivateEncrypt(const NewcoinAddress& naPublicTo, const std::vector<unsigned char>& vucPlainText);
|
||||||
|
|
||||||
|
// Decrypt a message.
|
||||||
|
std::vector<unsigned char> accountPrivateDecrypt(const NewcoinAddress& naPublicFrom, const std::vector<unsigned char>& vucCipherText);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Family Generators
|
// Family Generators
|
||||||
|
|||||||
@@ -13,14 +13,13 @@ void PackedMessage::encodeHeader(unsigned size, int type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PackedMessage::PackedMessage(MessagePointer msg, int type)
|
PackedMessage::PackedMessage(MessagePointer msg, int type) : mMsg(msg)
|
||||||
: mMsg(msg)
|
|
||||||
{
|
{
|
||||||
unsigned msg_size = mMsg->ByteSize();
|
unsigned msg_size = mMsg->ByteSize();
|
||||||
assert(msg_size);
|
assert(msg_size);
|
||||||
mBuffer.resize(HEADER_SIZE + msg_size);
|
mBuffer.resize(HEADER_SIZE + msg_size);
|
||||||
encodeHeader(msg_size,type);
|
encodeHeader(msg_size, type);
|
||||||
if(msg_size)
|
if (msg_size)
|
||||||
{
|
{
|
||||||
mMsg->SerializeToArray(&mBuffer[HEADER_SIZE], msg_size);
|
mMsg->SerializeToArray(&mBuffer[HEADER_SIZE], msg_size);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@@ -31,30 +30,25 @@ PackedMessage::PackedMessage(MessagePointer msg, int type)
|
|||||||
|
|
||||||
bool PackedMessage::operator == (const PackedMessage& other)
|
bool PackedMessage::operator == (const PackedMessage& other)
|
||||||
{
|
{
|
||||||
return(mBuffer==other.mBuffer);
|
return (mBuffer == other.mBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned PackedMessage::getLength(std::vector<uint8_t>& buf)
|
unsigned PackedMessage::getLength(std::vector<uint8_t>& buf)
|
||||||
{
|
{
|
||||||
if(buf.size() < HEADER_SIZE) return 0;
|
if(buf.size() < HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
int ret=buf[0];
|
int ret = buf[0];
|
||||||
ret<<=8;
|
ret <<= 8; ret |= buf[1]; ret <<= 8; ret |= buf[2]; ret <<= 8; ret |= buf[3];
|
||||||
ret|=buf[1];
|
return ret;
|
||||||
ret<<=8;
|
|
||||||
ret|=buf[2];
|
|
||||||
ret<<=8;
|
|
||||||
ret|=buf[3];
|
|
||||||
|
|
||||||
return(ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PackedMessage::getType(std::vector<uint8_t>& buf)
|
int PackedMessage::getType(std::vector<uint8_t>& buf)
|
||||||
{
|
{
|
||||||
if(buf.size() < HEADER_SIZE) return 0;
|
if(buf.size() < HEADER_SIZE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
int ret=buf[4];
|
int ret = buf[4];
|
||||||
ret<<=8;
|
ret <<= 8; ret |= buf[5];
|
||||||
ret|=buf[5];
|
return ret;
|
||||||
return(ret);
|
|
||||||
}
|
}
|
||||||
|
|||||||
197
src/Peer.cpp
197
src/Peer.cpp
@@ -19,9 +19,10 @@
|
|||||||
// Node has this long to verify its identity from connection accepted or connection attempt.
|
// Node has this long to verify its identity from connection accepted or connection attempt.
|
||||||
#define NODE_VERIFY_SECONDS 15
|
#define NODE_VERIFY_SECONDS 15
|
||||||
|
|
||||||
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
|
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx) :
|
||||||
: mSocketSsl(io_service, ctx),
|
mConnected(false),
|
||||||
mVerifyTimer(io_service)
|
mSocketSsl(io_service, ctx),
|
||||||
|
mVerifyTimer(io_service)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,20 +30,20 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
|
|||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(error)
|
if(error)
|
||||||
std::cerr << "Peer::handle_write Error: " << error << " bytes: " << bytes_transferred << std::endl;
|
std::cerr << "Peer::handle_write Error: " << error << " bytes: " << bytes_transferred << std::endl;
|
||||||
else
|
else
|
||||||
std::cerr << "Peer::handle_write bytes: "<< bytes_transferred << std::endl;
|
std::cerr << "Peer::handle_write bytes: "<< bytes_transferred << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mSendingPacket=PackedMessage::pointer();
|
mSendingPacket = PackedMessage::pointer();
|
||||||
|
|
||||||
if(error)
|
if (error)
|
||||||
{
|
{
|
||||||
detach();
|
detach("hw");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!mSendQ.empty())
|
if (!mSendQ.empty())
|
||||||
{
|
{
|
||||||
PackedMessage::pointer packet=mSendQ.front();
|
PackedMessage::pointer packet=mSendQ.front();
|
||||||
if(packet)
|
if(packet)
|
||||||
@@ -53,17 +54,21 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Peer::detach()
|
void Peer::detach(const char *rsn)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "DETACHING PEER: " << rsn << std::endl;
|
||||||
|
#endif
|
||||||
boost::system::error_code ecCancel;
|
boost::system::error_code ecCancel;
|
||||||
|
|
||||||
(void) mVerifyTimer.cancel();
|
(void) mVerifyTimer.cancel();
|
||||||
|
|
||||||
mSendQ.clear();
|
mSendQ.clear();
|
||||||
// mSocketSsl.close();
|
|
||||||
|
|
||||||
if (!mIpPort.first.empty()) {
|
if (!mIpPort.first.empty())
|
||||||
|
{
|
||||||
if (mClientConnect)
|
if (mClientConnect)
|
||||||
|
// Connection might be part of scanning. Inform connect failed.
|
||||||
theApp->getConnectionPool().peerFailed(mIpPort.first, mIpPort.second);
|
theApp->getConnectionPool().peerFailed(mIpPort.first, mIpPort.second);
|
||||||
|
|
||||||
theApp->getConnectionPool().peerDisconnected(shared_from_this(), mIpPort, mNodePublic);
|
theApp->getConnectionPool().peerDisconnected(shared_from_this(), mIpPort, mNodePublic);
|
||||||
@@ -78,34 +83,35 @@ void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
|
|||||||
// Timer canceled because deadline no longer needed.
|
// Timer canceled because deadline no longer needed.
|
||||||
// std::cerr << "Deadline cancelled." << std::endl;
|
// std::cerr << "Deadline cancelled." << std::endl;
|
||||||
|
|
||||||
nothing(); // Aborter is done.
|
nothing(); // Aborter is done.
|
||||||
}
|
}
|
||||||
else if (ecResult)
|
else if (ecResult)
|
||||||
{
|
{
|
||||||
std::cerr << "Peer verify timer error: " << std::endl;
|
std::cerr << "Peer verify timer error: " << std::endl;
|
||||||
|
|
||||||
// Can't do anything sound.
|
// Can't do anything sound.
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Peer failed to verify in time." << std::endl;
|
std::cerr << "Peer failed to verify in time." << std::endl;
|
||||||
detach();
|
detach("hvt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin trying to connect. We are not connected till we know and accept peer's public key.
|
// Begin trying to connect. We are not connected till we know and accept peer's public key.
|
||||||
// Only takes IP addresses (not domains).
|
// Only takes IP addresses (not domains).
|
||||||
void Peer::connect(const std::string strIp, int iPort)
|
void Peer::connect(const std::string strIp, int iPort)
|
||||||
{
|
{
|
||||||
int iPortAct = iPort < 0 ? SYSTEM_PEER_PORT : iPort;
|
int iPortAct = (iPort <= 0) ? SYSTEM_PEER_PORT : iPort;
|
||||||
|
|
||||||
mClientConnect = true;
|
mClientConnect = true;
|
||||||
|
|
||||||
std::cerr << "Peer::connect: " << strIp << " " << iPort << std::endl;
|
std::cerr << "Peer::connect: " << strIp << " " << iPort << std::endl;
|
||||||
mIpPort = make_pair(strIp, iPort);
|
mIpPort = make_pair(strIp, iPort);
|
||||||
|
assert(!mIpPort.first.empty());
|
||||||
|
|
||||||
boost::asio::ip::tcp::resolver::query query(strIp, boost::lexical_cast<std::string>(iPortAct),
|
boost::asio::ip::tcp::resolver::query query(strIp, boost::lexical_cast<std::string>(iPortAct),
|
||||||
boost::asio::ip::resolver_query_base::numeric_host|boost::asio::ip::resolver_query_base::numeric_service);
|
boost::asio::ip::resolver_query_base::numeric_host|boost::asio::ip::resolver_query_base::numeric_service);
|
||||||
boost::asio::ip::tcp::resolver resolver(theApp->getIOService());
|
boost::asio::ip::tcp::resolver resolver(theApp->getIOService());
|
||||||
boost::system::error_code err;
|
boost::system::error_code err;
|
||||||
@@ -114,7 +120,8 @@ void Peer::connect(const std::string strIp, int iPort)
|
|||||||
if (err || itrEndpoint == boost::asio::ip::tcp::resolver::iterator())
|
if (err || itrEndpoint == boost::asio::ip::tcp::resolver::iterator())
|
||||||
{
|
{
|
||||||
std::cerr << "Peer::connect: Bad IP" << std::endl;
|
std::cerr << "Peer::connect: Bad IP" << std::endl;
|
||||||
detach();
|
detach("c");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -124,13 +131,14 @@ void Peer::connect(const std::string strIp, int iPort)
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
std::cerr << "Peer::connect: Failed to set timer." << std::endl;
|
std::cerr << "Peer::connect: Failed to set timer." << std::endl;
|
||||||
detach();
|
detach("c2");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
std::cerr << "Peer::connect: Connectting: " << mIpPort.first << " " << mIpPort.second << std::endl;
|
std::cerr << "Peer::connect: Connecting: " << mIpPort.first << " " << mIpPort.second << std::endl;
|
||||||
|
|
||||||
boost::asio::async_connect(
|
boost::asio::async_connect(
|
||||||
mSocketSsl.lowest_layer(),
|
mSocketSsl.lowest_layer(),
|
||||||
@@ -152,7 +160,7 @@ void Peer::handleStart(const boost::system::error_code& error)
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
std::cerr << "Peer::handleStart: failed:" << error << std::endl;
|
std::cerr << "Peer::handleStart: failed:" << error << std::endl;
|
||||||
detach();
|
detach("hs");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -167,16 +175,16 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
std::cerr << "Connect peer: failed:" << error << std::endl;
|
std::cerr << "Connect peer: failed:" << error << std::endl;
|
||||||
detach();
|
detach("hc");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cerr << "Connect peer: success." << std::endl;
|
std::cerr << "Connect peer: success." << std::endl;
|
||||||
|
|
||||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||||
|
|
||||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::client,
|
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::client,
|
||||||
boost::bind(&Peer::handleStart, shared_from_this(), boost::asio::placeholders::error));
|
boost::bind(&Peer::handleStart, shared_from_this(), boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,13 +204,13 @@ void Peer::connected(const boost::system::error_code& error)
|
|||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
std::cerr << "Remote peer: accept error: " << strIp << " " << iPort << " : " << error << std::endl;
|
std::cerr << "Remote peer: accept error: " << strIp << " " << iPort << " : " << error << std::endl;
|
||||||
detach();
|
detach("ctd");
|
||||||
}
|
}
|
||||||
else if (!theApp->getConnectionPool().peerRegister(shared_from_this(), strIp, iPort))
|
else if (!theApp->getConnectionPool().peerRegister(shared_from_this(), strIp, iPort))
|
||||||
{
|
{
|
||||||
std::cerr << "Remote peer: rejecting: " << strIp << " " << iPort << std::endl;
|
std::cerr << "Remote peer: rejecting: " << strIp << " " << iPort << std::endl;
|
||||||
// XXX Reject with a rejection message: already connected
|
// XXX Reject with a rejection message: already connected
|
||||||
detach();
|
detach("ctd2");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -212,11 +220,12 @@ void Peer::connected(const boost::system::error_code& error)
|
|||||||
//BOOST_LOG_TRIVIAL(info) << "Connected to Peer.";
|
//BOOST_LOG_TRIVIAL(info) << "Connected to Peer.";
|
||||||
|
|
||||||
mIpPort = make_pair(strIp, iPort);
|
mIpPort = make_pair(strIp, iPort);
|
||||||
|
assert(!mIpPort.first.empty());
|
||||||
|
|
||||||
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
|
||||||
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
|
||||||
|
|
||||||
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::server,
|
mSocketSsl.async_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::server,
|
||||||
boost::bind(&Peer::handleStart, shared_from_this(), boost::asio::placeholders::error));
|
boost::bind(&Peer::handleStart, shared_from_this(), boost::asio::placeholders::error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,9 +256,6 @@ void Peer::sendPacket(PackedMessage::pointer packet)
|
|||||||
|
|
||||||
void Peer::start_read_header()
|
void Peer::start_read_header()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
|
||||||
std::cerr << "SRH" << std::endl;
|
|
||||||
#endif
|
|
||||||
mReadbuf.clear();
|
mReadbuf.clear();
|
||||||
mReadbuf.resize(HEADER_SIZE);
|
mReadbuf.resize(HEADER_SIZE);
|
||||||
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
|
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
|
||||||
@@ -275,15 +281,15 @@ void Peer::handle_read_header(const boost::system::error_code& error)
|
|||||||
// WRITEME: Compare to maximum message length, abort if too large
|
// WRITEME: Compare to maximum message length, abort if too large
|
||||||
if(msg_len>(32*1024*1024))
|
if(msg_len>(32*1024*1024))
|
||||||
{
|
{
|
||||||
detach();
|
detach("hrh");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
start_read_body(msg_len);
|
start_read_body(msg_len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
detach();
|
detach("hrh2");
|
||||||
std::cerr << "Peer::handle_read_header: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
std::cerr << "Peer::handle_read_header: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,8 +302,8 @@ void Peer::handle_read_body(const boost::system::error_code& error)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
detach();
|
detach("hrb");
|
||||||
std::cerr << "Peer::handle_read_body: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
std::cerr << "Peer::handle_read_body: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -309,11 +315,13 @@ void Peer::processReadBuffer()
|
|||||||
std::cerr << "PRB(" << type << "), len=" << (mReadbuf.size()-HEADER_SIZE) << std::endl;
|
std::cerr << "PRB(" << type << "), len=" << (mReadbuf.size()-HEADER_SIZE) << std::endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If not connected, only accept mtHELLO. Otherwise, don't accept mtHELLO.
|
std::cerr << "Peer::processReadBuffer: " << mIpPort.first << " " << mIpPort.second << std::endl;
|
||||||
if (mIpPort.first.empty() == (type == newcoin::mtHELLO))
|
|
||||||
|
// If connected and get a mtHELLO or if not connected and get a non-mtHELLO, wrong message was sent.
|
||||||
|
if (mConnected == (type == newcoin::mtHELLO))
|
||||||
{
|
{
|
||||||
std::cerr << "Wrong message type: " << type << std::endl;
|
std::cerr << "Wrong message type: " << type << std::endl;
|
||||||
detach();
|
detach("prb1");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -324,7 +332,7 @@ void Peer::processReadBuffer()
|
|||||||
newcoin::TMHello msg;
|
newcoin::TMHello msg;
|
||||||
if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||||
recvHello(msg);
|
recvHello(msg);
|
||||||
else std::cerr << "parse error: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
else std::cerr << "parse error: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -400,6 +408,17 @@ void Peer::processReadBuffer()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case newcoin::mtSTATUS_CHANGE:
|
||||||
|
{
|
||||||
|
newcoin::TMStatusChange msg;
|
||||||
|
if(msg.ParseFromArray(&mReadbuf[HEADER_SIZE], mReadbuf.size() - HEADER_SIZE))
|
||||||
|
recvStatus(msg);
|
||||||
|
else std::cerr << "parse error: " << type << std::endl;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case newcoin::mtGET_LEDGER:
|
case newcoin::mtGET_LEDGER:
|
||||||
{
|
{
|
||||||
newcoin::TMGetLedger msg;
|
newcoin::TMGetLedger msg;
|
||||||
@@ -474,7 +493,7 @@ void Peer::processReadBuffer()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
std::cerr << "Unknown Msg: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
std::cerr << "Unknown Msg: " << type << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,21 +534,33 @@ void Peer::recvHello(newcoin::TMHello& packet)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// XXX At this point we could add the inbound connection to our IP list. However, the inbound IP address might be that of
|
// At this point we could add the inbound connection to our IP list. However, the inbound IP address might be that of
|
||||||
// a NAT. It would be best to only add it if and only if we can immediatly verify it.
|
// a NAT. It would be best to only add it if and only if we can immediatly verify it.
|
||||||
nothing();
|
nothing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Consider us connected. No longer accepting mtHELLO.
|
||||||
|
mConnected = true;
|
||||||
|
|
||||||
// XXX Set timer: connection is in grace period to be useful.
|
// XXX Set timer: connection is in grace period to be useful.
|
||||||
// XXX Set timer: connection idle (idle may vary depending on connection type.)
|
// XXX Set timer: connection idle (idle may vary depending on connection type.)
|
||||||
|
|
||||||
|
if ((packet.has_closedledger()) && (packet.closedledger().size() == (256 / 8)))
|
||||||
|
{
|
||||||
|
memcpy(mClosedLedgerHash.begin(), packet.closedledger().data(), 256 / 8);
|
||||||
|
if ((packet.has_previousledger()) && (packet.previousledger().size() == (256 / 8)))
|
||||||
|
memcpy(mPreviousLedgerHash.begin(), packet.previousledger().data(), 256 / 8);
|
||||||
|
else mPreviousLedgerHash.zero();
|
||||||
|
mClosedLedgerTime = boost::posix_time::second_clock::universal_time();
|
||||||
|
}
|
||||||
|
|
||||||
bDetach = false;
|
bDetach = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bDetach)
|
if (bDetach)
|
||||||
{
|
{
|
||||||
mNodePublic.clear();
|
mNodePublic.clear();
|
||||||
detach();
|
detach("recvh");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -618,33 +649,55 @@ void Peer::recvAccount(newcoin::TMAccount& packet)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Peer::recvStatus(newcoin::TMStatusChange& packet)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "Received status change from peer" << std::endl;
|
||||||
|
#endif
|
||||||
|
if (packet.has_ledgerhash() && (packet.ledgerhash().size() == (256 / 8)))
|
||||||
|
{ // a peer has changed ledgers
|
||||||
|
if (packet.has_previousledgerhash() && (packet.previousledgerhash().size() == (256 / 8)))
|
||||||
|
memcpy(mPreviousLedgerHash.begin(), packet.previousledgerhash().data(), 256 / 8);
|
||||||
|
else
|
||||||
|
mPreviousLedgerHash = mClosedLedgerHash;
|
||||||
|
memcpy(mClosedLedgerHash.begin(), packet.ledgerhash().data(), 256 / 8);
|
||||||
|
if (packet.has_networktime())
|
||||||
|
mClosedLedgerTime = ptFromSeconds(packet.networktime());
|
||||||
|
else
|
||||||
|
mClosedLedgerTime = theApp->getOPs().getNetworkTimePT();
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::cerr << "peer LCL is " << mClosedLedgerHash.GetHex() << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
||||||
{
|
{
|
||||||
// Figure out what ledger they want
|
// Figure out what ledger they want
|
||||||
Ledger::pointer ledger;
|
Ledger::pointer ledger;
|
||||||
if(packet.has_ledgerhash())
|
if (packet.has_ledgerhash())
|
||||||
{
|
{
|
||||||
uint256 ledgerhash;
|
uint256 ledgerhash;
|
||||||
if(packet.ledgerhash().size()!=32)
|
if (packet.ledgerhash().size() != 32)
|
||||||
{
|
{
|
||||||
punishPeer(PP_INVALID_REQUEST);
|
punishPeer(PP_INVALID_REQUEST);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memcpy(&ledgerhash, packet.ledgerhash().data(), 32);
|
memcpy(&ledgerhash, packet.ledgerhash().data(), 32);
|
||||||
ledger=theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
ledger = theApp->getMasterLedger().getLedgerByHash(ledgerhash);
|
||||||
}
|
}
|
||||||
else if(packet.has_ledgerseq())
|
else if (packet.has_ledgerseq())
|
||||||
ledger=theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq());
|
ledger = theApp->getMasterLedger().getLedgerBySeq(packet.ledgerseq());
|
||||||
else if(packet.has_ltype() && (packet.ltype() == newcoin::ltCURRENT) )
|
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCURRENT))
|
||||||
ledger=theApp->getMasterLedger().getCurrentLedger();
|
ledger = theApp->getMasterLedger().getCurrentLedger();
|
||||||
else if(packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSING) )
|
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSING))
|
||||||
{
|
{
|
||||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||||
}
|
}
|
||||||
else if(packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSED) )
|
else if (packet.has_ltype() && (packet.ltype() == newcoin::ltCLOSED) )
|
||||||
{
|
{
|
||||||
ledger = theApp->getMasterLedger().getClosedLedger();
|
ledger = theApp->getMasterLedger().getClosedLedger();
|
||||||
if(ledger && !ledger->isClosed())
|
if (ledger && !ledger->isClosed())
|
||||||
ledger = theApp->getMasterLedger().getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
ledger = theApp->getMasterLedger().getLedgerBySeq(ledger->getLedgerSeq() - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -660,18 +713,17 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Figure out what information they want
|
// Figure out what information they want
|
||||||
newcoin::TMLedgerData* data=new newcoin::TMLedgerData;
|
boost::shared_ptr<newcoin::TMLedgerData> data = boost::make_shared<newcoin::TMLedgerData>();
|
||||||
uint256 lHash=ledger->getHash();
|
uint256 lHash = ledger->getHash();
|
||||||
data->set_ledgerhash(lHash.begin(), lHash.size());
|
data->set_ledgerhash(lHash.begin(), lHash.size());
|
||||||
data->set_ledgerseq(ledger->getLedgerSeq());
|
data->set_ledgerseq(ledger->getLedgerSeq());
|
||||||
data->set_type(packet.itype());
|
data->set_type(packet.itype());
|
||||||
|
|
||||||
if(packet.itype()==newcoin::liBASE)
|
if(packet.itype() == newcoin::liBASE)
|
||||||
{
|
{
|
||||||
Serializer nData(116);
|
Serializer nData(116);
|
||||||
ledger->addRaw(nData);
|
ledger->addRaw(nData);
|
||||||
newcoin::TMLedgerNode* node=data->add_nodes();
|
data->add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
|
||||||
node->set_nodedata(nData.getDataPtr(), nData.getLength());
|
|
||||||
}
|
}
|
||||||
else if ( (packet.itype()==newcoin::liTX_NODE) || (packet.itype()==newcoin::liAS_NODE) )
|
else if ( (packet.itype()==newcoin::liTX_NODE) || (packet.itype()==newcoin::liAS_NODE) )
|
||||||
{
|
{
|
||||||
@@ -696,13 +748,13 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
|||||||
if(map->getNodeFat(mn, nodeIDs, rawNodes))
|
if(map->getNodeFat(mn, nodeIDs, rawNodes))
|
||||||
{
|
{
|
||||||
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
std::vector<SHAMapNode>::iterator nodeIDIterator;
|
||||||
std::list<std::vector<unsigned char> >::iterator rawNodeIterator;
|
std::list<std::vector<unsigned char> >::iterator rawNodeIterator;
|
||||||
for(nodeIDIterator=nodeIDs.begin(), rawNodeIterator=rawNodes.begin();
|
for(nodeIDIterator=nodeIDs.begin(), rawNodeIterator=rawNodes.begin();
|
||||||
nodeIDIterator!=nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
|
nodeIDIterator!=nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
|
||||||
{
|
{
|
||||||
newcoin::TMLedgerNode* node=data->add_nodes();
|
|
||||||
Serializer nID(33);
|
Serializer nID(33);
|
||||||
nodeIDIterator->addIDRaw(nID);
|
nodeIDIterator->addIDRaw(nID);
|
||||||
|
newcoin::TMLedgerNode* node=data->add_nodes();
|
||||||
node->set_nodeid(nID.getDataPtr(), nID.getLength());
|
node->set_nodeid(nID.getDataPtr(), nID.getLength());
|
||||||
node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size());
|
node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size());
|
||||||
}
|
}
|
||||||
@@ -721,7 +773,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
|
|||||||
|
|
||||||
void Peer::recvLedger(newcoin::TMLedgerData& packet)
|
void Peer::recvLedger(newcoin::TMLedgerData& packet)
|
||||||
{
|
{
|
||||||
if(!theApp->getMasterLedgerAcquire().gotLedgerData(packet))
|
if(!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()))
|
||||||
punishPeer(PP_UNWANTED_DATA);
|
punishPeer(PP_UNWANTED_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,22 +816,23 @@ void Peer::sendHello()
|
|||||||
|
|
||||||
theApp->getWallet().getNodePrivate().signNodePrivate(mCookieHash, vchSig);
|
theApp->getWallet().getNodePrivate().signNodePrivate(mCookieHash, vchSig);
|
||||||
|
|
||||||
newcoin::TMHello* h = new newcoin::TMHello();
|
boost::shared_ptr<newcoin::TMHello> h = boost::make_shared<newcoin::TMHello>();
|
||||||
|
|
||||||
h->set_version(theConfig.VERSION);
|
h->set_version(theConfig.VERSION);
|
||||||
h->set_ledgerindex(theApp->getOPs().getCurrentLedgerID());
|
h->set_ledgerindex(theApp->getOPs().getCurrentLedgerID());
|
||||||
h->set_nettime(theApp->getOPs().getNetworkTime());
|
h->set_nettime(theApp->getOPs().getNetworkTimeNC());
|
||||||
h->set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic());
|
h->set_nodepublic(theApp->getWallet().getNodePublic().humanNodePublic());
|
||||||
h->set_nodeproof(&vchSig[0], vchSig.size());
|
h->set_nodeproof(&vchSig[0], vchSig.size());
|
||||||
h->set_ipv4port(theConfig.PEER_PORT);
|
h->set_ipv4port(theConfig.PEER_PORT);
|
||||||
|
|
||||||
Ledger::pointer closedLedger = theApp->getMasterLedger().getClosedLedger();
|
Ledger::pointer closedLedger = theApp->getMasterLedger().getClosedLedger();
|
||||||
assert(closedLedger && closedLedger->isClosed());
|
assert(closedLedger && closedLedger->isClosed());
|
||||||
if(closedLedger->isClosed())
|
if (closedLedger->isClosed())
|
||||||
{
|
{
|
||||||
Serializer s(128);
|
uint256 hash = closedLedger->getHash();
|
||||||
closedLedger->addRaw(s);
|
h->set_closedledger(hash.begin(), hash.GetSerializeSize());
|
||||||
h->set_closedledger(s.getDataPtr(), s.getLength());
|
hash = closedLedger->getParentHash();
|
||||||
|
h->set_previousledger(hash.begin(), hash.GetSerializeSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
PackedMessage::pointer packet = boost::make_shared<PackedMessage>
|
PackedMessage::pointer packet = boost::make_shared<PackedMessage>
|
||||||
|
|||||||
25
src/Peer.h
25
src/Peer.h
@@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
enum PeerPunish
|
enum PeerPunish
|
||||||
{
|
{
|
||||||
PP_INVALID_REQUEST=1, // The peer sent a request that makes no sense
|
PP_INVALID_REQUEST = 1, // The peer sent a request that makes no sense
|
||||||
PP_UNKNOWN_REQUEST=2, // The peer sent a request that might be garbage
|
PP_UNKNOWN_REQUEST = 2, // The peer sent a request that might be garbage
|
||||||
PP_UNWANTED_DATA=3, // The peer sent us data we didn't want/need
|
PP_UNWANTED_DATA = 3, // The peer sent us data we didn't want/need
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::pair<std::string,int> ipPort;
|
typedef std::pair<std::string,int> ipPort;
|
||||||
@@ -25,18 +25,23 @@ typedef std::pair<std::string,int> ipPort;
|
|||||||
class Peer : public boost::enable_shared_from_this<Peer>
|
class Peer : public boost::enable_shared_from_this<Peer>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static const int psbGotHello=0, psbSentHello=1, psbInMap=2, psbTrusted=3;
|
static const int psbGotHello = 0, psbSentHello = 1, psbInMap = 2, psbTrusted = 3;
|
||||||
static const int psbNoLedgers=4, psbNoTransactions=5, psbDownLevel=6;
|
static const int psbNoLedgers = 4, psbNoTransactions = 5, psbDownLevel = 6;
|
||||||
|
|
||||||
void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it);
|
void handleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator it);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mClientConnect; // In process of connecting as client.
|
bool mClientConnect; // In process of connecting as client.
|
||||||
|
bool mConnected; // True, if hello accepted.
|
||||||
NewcoinAddress mNodePublic; // Node public key of peer.
|
NewcoinAddress mNodePublic; // Node public key of peer.
|
||||||
ipPort mIpPort;
|
ipPort mIpPort;
|
||||||
uint256 mCookieHash;
|
uint256 mCookieHash;
|
||||||
|
|
||||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
|
// network state information
|
||||||
|
uint256 mClosedLedgerHash, mPreviousLedgerHash;
|
||||||
|
boost::posix_time::ptime mClosedLedgerTime;
|
||||||
|
|
||||||
|
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> mSocketSsl;
|
||||||
|
|
||||||
boost::asio::deadline_timer mVerifyTimer;
|
boost::asio::deadline_timer mVerifyTimer;
|
||||||
|
|
||||||
@@ -62,8 +67,6 @@ protected:
|
|||||||
void sendPacketForce(PackedMessage::pointer packet);
|
void sendPacketForce(PackedMessage::pointer packet);
|
||||||
|
|
||||||
void sendHello();
|
void sendHello();
|
||||||
void sendTransaction(newcoin::TMTransaction& packet);
|
|
||||||
void sendValidation();
|
|
||||||
|
|
||||||
void recvHello(newcoin::TMHello& packet);
|
void recvHello(newcoin::TMHello& packet);
|
||||||
void recvTransaction(newcoin::TMTransaction& packet);
|
void recvTransaction(newcoin::TMTransaction& packet);
|
||||||
@@ -81,6 +84,7 @@ protected:
|
|||||||
void recvAccount(newcoin::TMAccount& packet);
|
void recvAccount(newcoin::TMAccount& packet);
|
||||||
void recvGetLedger(newcoin::TMGetLedger& packet);
|
void recvGetLedger(newcoin::TMGetLedger& packet);
|
||||||
void recvLedger(newcoin::TMLedgerData& packet);
|
void recvLedger(newcoin::TMLedgerData& packet);
|
||||||
|
void recvStatus(newcoin::TMStatusChange& packet);
|
||||||
|
|
||||||
void getSessionCookie(std::string& strDst);
|
void getSessionCookie(std::string& strDst);
|
||||||
|
|
||||||
@@ -101,7 +105,7 @@ public:
|
|||||||
|
|
||||||
void connect(const std::string strIp, int iPort);
|
void connect(const std::string strIp, int iPort);
|
||||||
void connected(const boost::system::error_code& error);
|
void connected(const boost::system::error_code& error);
|
||||||
void detach();
|
void detach(const char *);
|
||||||
bool samePeer(Peer::pointer p) { return samePeer(*p); }
|
bool samePeer(Peer::pointer p) { return samePeer(*p); }
|
||||||
bool samePeer(const Peer& p) { return this == &p; }
|
bool samePeer(const Peer& p) { return this == &p; }
|
||||||
|
|
||||||
@@ -118,6 +122,9 @@ public:
|
|||||||
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);
|
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);
|
||||||
static PackedMessage::pointer createValidation(Ledger::pointer ledger);
|
static PackedMessage::pointer createValidation(Ledger::pointer ledger);
|
||||||
static PackedMessage::pointer createGetFullLedger(uint256& hash);
|
static PackedMessage::pointer createGetFullLedger(uint256& hash);
|
||||||
|
|
||||||
|
uint256 getClosedLedgerHash() const { return mClosedLedgerHash; }
|
||||||
|
NewcoinAddress getNodePublic() const { return mNodePublic; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
|
|||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
data.reserve(65); // our public keys are actually 33 bytes
|
data.reserve(65); // our public keys are actually 33 bytes
|
||||||
int pkSize;
|
int pkSize;
|
||||||
if(1)
|
|
||||||
{ // is it in the database
|
{ // is it in the database
|
||||||
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
||||||
Database* db=theApp->getTxnDB()->getDB();
|
Database* db=theApp->getTxnDB()->getDB();
|
||||||
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
|
if(!db->executeSQL(sql) || !db->startIterRows())
|
||||||
return CKey::pointer();
|
return CKey::pointer();
|
||||||
pkSize=db->getBinary("PubKey", &(data.front()), data.size());
|
pkSize=db->getBinary("PubKey", &(data.front()), data.size());
|
||||||
db->endIterRows();
|
db->endIterRows();
|
||||||
@@ -36,7 +36,6 @@ CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
|
|||||||
return CKey::pointer();
|
return CKey::pointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(1)
|
|
||||||
{ // put it in cache (okay if we race with another retriever)
|
{ // put it in cache (okay if we race with another retriever)
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
mCache.insert(std::make_pair(id, ckp));
|
mCache.insert(std::make_pair(id, ckp));
|
||||||
@@ -46,7 +45,6 @@ CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
|
|||||||
|
|
||||||
CKey::pointer PubKeyCache::store(const NewcoinAddress& id, CKey::pointer key)
|
CKey::pointer PubKeyCache::store(const NewcoinAddress& id, CKey::pointer key)
|
||||||
{ // stored if needed, returns cached copy (possibly the original)
|
{ // stored if needed, returns cached copy (possibly the original)
|
||||||
if(1)
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
std::pair<std::map<NewcoinAddress,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
|
std::pair<std::map<NewcoinAddress,CKey::pointer>::iterator, bool> pit(mCache.insert(std::make_pair(id, key)));
|
||||||
@@ -65,7 +63,7 @@ CKey::pointer PubKeyCache::store(const NewcoinAddress& id, CKey::pointer key)
|
|||||||
sql.append(");");
|
sql.append(");");
|
||||||
|
|
||||||
ScopedLock dbl(theApp->getTxnDB()->getDBLock());
|
ScopedLock dbl(theApp->getTxnDB()->getDBLock());
|
||||||
theApp->getTxnDB()->getDB()->executeSQL(sql.c_str(), true);
|
theApp->getTxnDB()->getDB()->executeSQL(sql, true);
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,3 +72,4 @@ void PubKeyCache::clear()
|
|||||||
boost::mutex::scoped_lock sl(mLock);
|
boost::mutex::scoped_lock sl(mLock);
|
||||||
mCache.empty();
|
mCache.empty();
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ Json::Value RPCServer::doNewAccount(Json::Value ¶ms)
|
|||||||
return JSONRPCError(500, "Family required");
|
return JSONRPCError(500, "Family required");
|
||||||
|
|
||||||
NewcoinAddress family = parseFamily(fParam);
|
NewcoinAddress family = parseFamily(fParam);
|
||||||
if(!family.isValid()) return JSONRPCError(500, "Family not found.");
|
if (!family.isValid()) return JSONRPCError(500, "Family not found.");
|
||||||
|
|
||||||
LocalAccount::pointer account(theApp->getWallet().getNewLocalAccount(family));
|
LocalAccount::pointer account(theApp->getWallet().getNewLocalAccount(family));
|
||||||
if(!account)
|
if(!account)
|
||||||
|
|||||||
150
src/SHAMap.cpp
150
src/SHAMap.cpp
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
|
SHAMap::SHAMap(uint32 seq) : mSeq(seq), mState(Modifying)
|
||||||
{
|
{
|
||||||
root=boost::make_shared<SHAMapTreeNode>(SHAMapNode(0, uint256()), mSeq);
|
root = boost::make_shared<SHAMapTreeNode>(SHAMapNode(0, uint256()), mSeq);
|
||||||
root->makeInner();
|
root->makeInner();
|
||||||
mTNByID[*root]=root;
|
mTNByID[*root] = root;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool include_nonmatching_leaf)
|
std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool include_nonmatching_leaf)
|
||||||
@@ -21,27 +21,27 @@ std::stack<SHAMapTreeNode::pointer> SHAMap::getStack(const uint256& id, bool inc
|
|||||||
// Walk the tree as far as possible to the specified identifier
|
// Walk the tree as far as possible to the specified identifier
|
||||||
// produce a stack of nodes along the way, with the terminal node at the top
|
// produce a stack of nodes along the way, with the terminal node at the top
|
||||||
std::stack<SHAMapTreeNode::pointer> stack;
|
std::stack<SHAMapTreeNode::pointer> stack;
|
||||||
SHAMapTreeNode::pointer node=root;
|
SHAMapTreeNode::pointer node = root;
|
||||||
|
|
||||||
while(!node->isLeaf())
|
while (!node->isLeaf())
|
||||||
{
|
{
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
|
|
||||||
int branch=node->selectBranch(id);
|
int branch = node->selectBranch(id);
|
||||||
assert(branch>=0);
|
assert(branch >= 0);
|
||||||
|
|
||||||
uint256 hash=node->getChildHash(branch);
|
uint256 hash = node->getChildHash(branch);
|
||||||
if(hash.isZero()) return stack;
|
if (hash.isZero()) return stack;
|
||||||
|
|
||||||
node=getNode(node->getChildNodeID(branch), hash, false);
|
node = getNode(node->getChildNodeID(branch), hash, false);
|
||||||
if(!node)
|
if (!node)
|
||||||
{
|
{
|
||||||
if(isSynching()) return stack;
|
if (isSynching()) return stack;
|
||||||
throw SHAMapException(MissingNode);
|
throw SHAMapException(MissingNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(include_nonmatching_leaf || (node->peekItem()->getTag()==id))
|
if (include_nonmatching_leaf || (node->peekItem()->getTag() == id))
|
||||||
stack.push(node);
|
stack.push(node);
|
||||||
|
|
||||||
return stack;
|
return stack;
|
||||||
@@ -51,20 +51,20 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
|
|||||||
{ // walk the tree up from through the inner nodes to the root
|
{ // walk the tree up from through the inner nodes to the root
|
||||||
// update linking hashes and add nodes to dirty list
|
// update linking hashes and add nodes to dirty list
|
||||||
|
|
||||||
assert(mState!=Synching && mState!=Immutable);
|
assert((mState != Synching) && (mState != Immutable));
|
||||||
|
|
||||||
while(!stack.empty())
|
while (!stack.empty())
|
||||||
{
|
{
|
||||||
SHAMapTreeNode::pointer node=stack.top();
|
SHAMapTreeNode::pointer node=stack.top();
|
||||||
stack.pop();
|
stack.pop();
|
||||||
assert(node->isInnerNode());
|
assert(node->isInnerNode());
|
||||||
|
|
||||||
int branch=node->selectBranch(target);
|
int branch = node->selectBranch(target);
|
||||||
assert(branch>=0);
|
assert(branch >= 0);
|
||||||
|
|
||||||
returnNode(node, true);
|
returnNode(node, true);
|
||||||
|
|
||||||
if(!node->setChildHash(branch, prevHash))
|
if (!node->setChildHash(branch, prevHash))
|
||||||
{
|
{
|
||||||
std::cerr << "dirtyUp terminates early" << std::endl;
|
std::cerr << "dirtyUp terminates early" << std::endl;
|
||||||
assert(false);
|
assert(false);
|
||||||
@@ -73,44 +73,44 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
|
|||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash.GetHex() << std::endl;
|
std::cerr << "dirtyUp sets branch " << branch << " to " << prevHash.GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
prevHash=node->getNodeHash();
|
prevHash = node->getNodeHash();
|
||||||
assert(prevHash.isNonZero());
|
assert(prevHash.isNonZero());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapTreeNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
|
SHAMapTreeNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
|
||||||
{
|
{
|
||||||
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it=mTNByID.find(iNode);
|
boost::unordered_map<SHAMapNode, SHAMapTreeNode::pointer>::iterator it = mTNByID.find(iNode);
|
||||||
if(it==mTNByID.end()) return SHAMapTreeNode::pointer();
|
if (it == mTNByID.end()) return SHAMapTreeNode::pointer();
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify)
|
SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify)
|
||||||
{ // walk down to the terminal node for this ID
|
{ // walk down to the terminal node for this ID
|
||||||
|
SHAMapTreeNode::pointer inNode = root;
|
||||||
|
|
||||||
SHAMapTreeNode::pointer inNode=root;
|
while (!inNode->isLeaf())
|
||||||
|
|
||||||
while(!inNode->isLeaf())
|
|
||||||
{
|
{
|
||||||
int branch=inNode->selectBranch(id);
|
int branch = inNode->selectBranch(id);
|
||||||
if(inNode->isEmptyBranch(branch)) return inNode;
|
if (inNode->isEmptyBranch(branch)) return inNode;
|
||||||
uint256 childHash=inNode->getChildHash(branch);
|
uint256 childHash = inNode->getChildHash(branch);
|
||||||
if(childHash.isZero()) return inNode;
|
if (childHash.isZero()) return inNode;
|
||||||
|
|
||||||
SHAMapTreeNode::pointer nextNode=getNode(inNode->getChildNodeID(branch), childHash, false);
|
SHAMapTreeNode::pointer nextNode = getNode(inNode->getChildNodeID(branch), childHash, false);
|
||||||
if(!nextNode) throw SHAMapException(MissingNode);
|
if (!nextNode) throw SHAMapException(MissingNode);
|
||||||
inNode=nextNode;
|
inNode = nextNode;
|
||||||
}
|
}
|
||||||
if(modify) returnNode(inNode, true);
|
if (inNode->getTag() != id) return SHAMapTreeNode::pointer();
|
||||||
|
if (modify) returnNode(inNode, true);
|
||||||
return inNode;
|
return inNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& hash, bool modify)
|
SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& hash, bool modify)
|
||||||
{ // retrieve a node whose node hash is known
|
{ // retrieve a node whose node hash is known
|
||||||
SHAMapTreeNode::pointer node=checkCacheNode(id);
|
SHAMapTreeNode::pointer node = checkCacheNode(id);
|
||||||
if(node)
|
if (node)
|
||||||
{
|
{
|
||||||
if(node->getNodeHash()!=hash)
|
if (node->getNodeHash()!=hash)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Attempt to get node, hash not in tree" << std::endl;
|
std::cerr << "Attempt to get node, hash not in tree" << std::endl;
|
||||||
@@ -128,10 +128,10 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has
|
|||||||
std::vector<unsigned char> nodeData;
|
std::vector<unsigned char> nodeData;
|
||||||
if(!fetchNode(hash, nodeData)) return SHAMapTreeNode::pointer();
|
if(!fetchNode(hash, nodeData)) return SHAMapTreeNode::pointer();
|
||||||
|
|
||||||
node=boost::make_shared<SHAMapTreeNode>(id, nodeData, mSeq);
|
node = boost::make_shared<SHAMapTreeNode>(id, nodeData, mSeq);
|
||||||
if(node->getNodeHash()!=hash) throw SHAMapException(InvalidNode);
|
if (node->getNodeHash() != hash) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(!mTNByID.insert(std::make_pair(id, node)).second)
|
if (!mTNByID.insert(std::make_pair(id, node)).second)
|
||||||
assert(false);
|
assert(false);
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -139,15 +139,15 @@ SHAMapTreeNode::pointer SHAMap::getNode(const SHAMapNode& id, const uint256& has
|
|||||||
void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify)
|
void SHAMap::returnNode(SHAMapTreeNode::pointer& node, bool modify)
|
||||||
{ // make sure the node is suitable for the intended operation (copy on write)
|
{ // make sure the node is suitable for the intended operation (copy on write)
|
||||||
assert(node->isValid());
|
assert(node->isValid());
|
||||||
if(node && modify && (node->getSeq()!=mSeq))
|
if (node && modify && (node->getSeq()!=mSeq))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "returnNode COW" << std::endl;
|
std::cerr << "returnNode COW" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
if(mDirtyNodes) (*mDirtyNodes)[*node]=node;
|
if (mDirtyNodes) (*mDirtyNodes)[*node] = node;
|
||||||
node=boost::make_shared<SHAMapTreeNode>(*node, mSeq);
|
node = boost::make_shared<SHAMapTreeNode>(*node, mSeq);
|
||||||
assert(node->isValid());
|
assert(node->isValid());
|
||||||
mTNByID[*node]=node;
|
mTNByID[*node] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,24 +163,24 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode::pointer node)
|
|||||||
#endif
|
#endif
|
||||||
do
|
do
|
||||||
{ // Walk down the tree
|
{ // Walk down the tree
|
||||||
if(node->hasItem()) return node->peekItem();
|
if (node->hasItem()) return node->peekItem();
|
||||||
|
|
||||||
bool foundNode=false;
|
bool foundNode = false;
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
std::cerr << " FB: node " << node->getString() << std::endl;
|
std::cerr << " FB: node " << node->getString() << std::endl;
|
||||||
std::cerr << " has non-empty branch " << i << " : " <<
|
std::cerr << " has non-empty branch " << i << " : " <<
|
||||||
node->getChildNodeID(i).getString() << ", " << node->getChildHash(i).GetHex() << std::endl;
|
node->getChildNodeID(i).getString() << ", " << node->getChildHash(i).GetHex() << std::endl;
|
||||||
#endif
|
#endif
|
||||||
node=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!node) throw SHAMapException(MissingNode);
|
if (!node) throw SHAMapException(MissingNode);
|
||||||
foundNode=true;
|
foundNode = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!foundNode) return SHAMapItem::pointer();
|
if (!foundNode) return SHAMapItem::pointer();
|
||||||
} while(1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
||||||
@@ -191,46 +191,46 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{ // Walk down the tree
|
{ // Walk down the tree
|
||||||
if(node->hasItem()) return node->peekItem();
|
if (node->hasItem()) return node->peekItem();
|
||||||
|
|
||||||
bool foundNode=false;
|
bool foundNode = false;
|
||||||
for(int i=15; i>=0; i++)
|
for (int i = 15; i >= 0; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
node=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!node) throw SHAMapException(MissingNode);
|
if (!node) throw SHAMapException(MissingNode);
|
||||||
foundNode=true;
|
foundNode = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!foundNode) return SHAMapItem::pointer();
|
if (!foundNode) return SHAMapItem::pointer();
|
||||||
} while(1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode::pointer node)
|
SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode::pointer node)
|
||||||
{
|
{
|
||||||
// If there is only one item below this node, return it
|
// If there is only one item below this node, return it
|
||||||
bool found;
|
bool found;
|
||||||
while(!node->isLeaf())
|
while (!node->isLeaf())
|
||||||
{
|
{
|
||||||
found=false;
|
found = false;
|
||||||
SHAMapTreeNode::pointer nextNode;
|
SHAMapTreeNode::pointer nextNode;
|
||||||
|
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(!node->isEmptyBranch(i))
|
if (!node->isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
if(found) return SHAMapItem::pointer(); // two leaves below
|
if( found) return SHAMapItem::pointer(); // two leaves below
|
||||||
nextNode=getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
nextNode = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
|
||||||
if(!nextNode) throw SHAMapException(MissingNode);
|
if (!nextNode) throw SHAMapException(MissingNode);
|
||||||
found=true;
|
found = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
std::cerr << node->getString() << std::endl;
|
std::cerr << node->getString() << std::endl;
|
||||||
assert(false);
|
assert(false);
|
||||||
return SHAMapItem::pointer();
|
return SHAMapItem::pointer();
|
||||||
}
|
}
|
||||||
node=nextNode;
|
node = nextNode;
|
||||||
}
|
}
|
||||||
assert(node->hasItem());
|
assert(node->hasItem());
|
||||||
return node->peekItem();
|
return node->peekItem();
|
||||||
@@ -342,7 +342,7 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id)
|
|||||||
|
|
||||||
bool SHAMap::hasItem(const uint256& id)
|
bool SHAMap::hasItem(const uint256& id)
|
||||||
{ // does the tree have an item with this ID
|
{ // does the tree have an item with this ID
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
SHAMapTreeNode::pointer leaf=walkTo(id, false);
|
SHAMapTreeNode::pointer leaf=walkTo(id, false);
|
||||||
if(!leaf) return false;
|
if(!leaf) return false;
|
||||||
SHAMapItem::pointer item=leaf->peekItem();
|
SHAMapItem::pointer item=leaf->peekItem();
|
||||||
@@ -472,7 +472,7 @@ bool SHAMap::addGiveItem(SHAMapItem::pointer item, bool isTransaction)
|
|||||||
node->makeInner();
|
node->makeInner();
|
||||||
|
|
||||||
int b1, b2;
|
int b1, b2;
|
||||||
|
|
||||||
while( (b1=node->selectBranch(tag)) == (b2=node->selectBranch(otherItem->getTag())) )
|
while( (b1=node->selectBranch(tag)) == (b2=node->selectBranch(otherItem->getTag())) )
|
||||||
{ // we need a new inner node, since both go on same branch at this level
|
{ // we need a new inner node, since both go on same branch at this level
|
||||||
#ifdef ST_DEBUG
|
#ifdef ST_DEBUG
|
||||||
@@ -618,11 +618,11 @@ void SHAMap::dump(bool hash)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<unsigned char>IntToVUC(int i)
|
static std::vector<unsigned char>IntToVUC(int v)
|
||||||
{
|
{
|
||||||
std::vector<unsigned char> vuc;
|
std::vector<unsigned char> vuc;
|
||||||
for(int i=0; i<32; i++)
|
for (int i = 0; i < 32; ++i)
|
||||||
vuc.push_back((unsigned char) i);
|
vuc.push_back(static_cast<unsigned char>(v));
|
||||||
return vuc;
|
return vuc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -675,4 +675,4 @@ bool SHAMap::TestSHAMap()
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
48
src/SHAMap.h
48
src/SHAMap.h
@@ -40,14 +40,14 @@ public:
|
|||||||
SHAMapNode(int depth, const uint256& hash);
|
SHAMapNode(int depth, const uint256& hash);
|
||||||
int getDepth() const { return mDepth; }
|
int getDepth() const { return mDepth; }
|
||||||
const uint256& getNodeID() const { return mNodeID; }
|
const uint256& getNodeID() const { return mNodeID; }
|
||||||
bool isValid() const { return (mDepth>=0) && (mDepth<64); }
|
bool isValid() const { return (mDepth >= 0) && (mDepth < 64); }
|
||||||
|
|
||||||
virtual bool isPopulated() const { return false; }
|
virtual bool isPopulated() const { return false; }
|
||||||
|
|
||||||
SHAMapNode getParentNodeID() const
|
SHAMapNode getParentNodeID() const
|
||||||
{
|
{
|
||||||
assert(mDepth);
|
assert(mDepth);
|
||||||
return SHAMapNode(mDepth-1, mNodeID);
|
return SHAMapNode(mDepth - 1, mNodeID);
|
||||||
}
|
}
|
||||||
SHAMapNode getChildNodeID(int m) const;
|
SHAMapNode getChildNodeID(int m) const;
|
||||||
int selectBranch(const uint256& hash) const;
|
int selectBranch(const uint256& hash) const;
|
||||||
@@ -108,18 +108,18 @@ public:
|
|||||||
|
|
||||||
void updateData(const std::vector<unsigned char>& data) { mData=data; }
|
void updateData(const std::vector<unsigned char>& data) { mData=data; }
|
||||||
|
|
||||||
bool operator<(const SHAMapItem& i) const { return mTag<i.mTag; }
|
bool operator<(const SHAMapItem& i) const { return mTag < i.mTag; }
|
||||||
bool operator>(const SHAMapItem& i) const { return mTag>i.mTag; }
|
bool operator>(const SHAMapItem& i) const { return mTag > i.mTag; }
|
||||||
bool operator==(const SHAMapItem& i) const { return mTag==i.mTag; }
|
bool operator==(const SHAMapItem& i) const { return mTag == i.mTag; }
|
||||||
bool operator!=(const SHAMapItem& i) const { return mTag!=i.mTag; }
|
bool operator!=(const SHAMapItem& i) const { return mTag != i.mTag; }
|
||||||
bool operator<=(const SHAMapItem& i) const { return mTag<=i.mTag; }
|
bool operator<=(const SHAMapItem& i) const { return mTag <= i.mTag; }
|
||||||
bool operator>=(const SHAMapItem& i) const { return mTag>=i.mTag; }
|
bool operator>=(const SHAMapItem& i) const { return mTag >= i.mTag; }
|
||||||
bool operator<(const uint256& i) const { return mTag<i; }
|
bool operator<(const uint256& i) const { return mTag < i; }
|
||||||
bool operator>(const uint256& i) const { return mTag>i; }
|
bool operator>(const uint256& i) const { return mTag > i; }
|
||||||
bool operator==(const uint256& i) const { return mTag==i; }
|
bool operator==(const uint256& i) const { return mTag == i; }
|
||||||
bool operator!=(const uint256& i) const { return mTag!=i; }
|
bool operator!=(const uint256& i) const { return mTag != i; }
|
||||||
bool operator<=(const uint256& i) const { return mTag<=i; }
|
bool operator<=(const uint256& i) const { return mTag <= i; }
|
||||||
bool operator>=(const uint256& i) const { return mTag>=i; }
|
bool operator>=(const uint256& i) const { return mTag >= i; }
|
||||||
virtual void dump();
|
virtual void dump();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -132,10 +132,10 @@ public:
|
|||||||
|
|
||||||
enum TNType
|
enum TNType
|
||||||
{
|
{
|
||||||
tnERROR =0,
|
tnERROR = 0,
|
||||||
tnINNER =1,
|
tnINNER = 1,
|
||||||
tnTRANSACTION =2,
|
tnTRANSACTION = 2,
|
||||||
tnACCOUNT_STATE =3
|
tnACCOUNT_STATE = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -251,11 +251,11 @@ protected:
|
|||||||
|
|
||||||
bool walkBranch(SHAMapTreeNode::pointer node, SHAMapItem::pointer otherMapItem, bool isFirstMap,
|
bool walkBranch(SHAMapTreeNode::pointer node, SHAMapItem::pointer otherMapItem, bool isFirstMap,
|
||||||
SHAMapDiff& differences, int& maxCount);
|
SHAMapDiff& differences, int& maxCount);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// build new map
|
// build new map
|
||||||
SHAMap(uint32 seq=0);
|
SHAMap(uint32 seq = 0);
|
||||||
|
|
||||||
// hold the map stable across operations
|
// hold the map stable across operations
|
||||||
ScopedLock Lock() const { return ScopedLock(mLock); }
|
ScopedLock Lock() const { return ScopedLock(mLock); }
|
||||||
@@ -295,7 +295,7 @@ public:
|
|||||||
// status functions
|
// status functions
|
||||||
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
|
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
|
||||||
void clearImmutable(void) { mState = Modifying; }
|
void clearImmutable(void) { mState = Modifying; }
|
||||||
bool isSynching(void) const { return mState == Floating || mState == Synching; }
|
bool isSynching(void) const { return (mState == Floating) || (mState == Synching); }
|
||||||
void setSynching(void) { mState = Synching; }
|
void setSynching(void) { mState = Synching; }
|
||||||
void setFloating(void) { mState = Floating; }
|
void setFloating(void) { mState = Floating; }
|
||||||
void clearSynching(void) { mState = Modifying; }
|
void clearSynching(void) { mState = Modifying; }
|
||||||
@@ -315,6 +315,11 @@ public:
|
|||||||
|
|
||||||
bool operator==(const SHAMap& s) { return getHash() == s.getHash(); }
|
bool operator==(const SHAMap& s) { return getHash() == s.getHash(); }
|
||||||
|
|
||||||
|
// trusted path operations - prove a particular node is in a particular ledger
|
||||||
|
std::list<std::vector<unsigned char> > getTrustedPath(const uint256& index);
|
||||||
|
static std::vector<unsigned char> checkTrustedPath(const uint256& ledgerHash, const uint256& leafIndex,
|
||||||
|
const std::list<std::vector<unsigned char> >& path);
|
||||||
|
|
||||||
static bool TestSHAMap();
|
static bool TestSHAMap();
|
||||||
static bool syncTest();
|
static bool syncTest();
|
||||||
bool deepCompare(SHAMap& other);
|
bool deepCompare(SHAMap& other);
|
||||||
@@ -322,3 +327,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -97,11 +97,11 @@ SHAMapNode::SHAMapNode(int depth, const uint256 &hash) : mDepth(depth)
|
|||||||
|
|
||||||
SHAMapNode::SHAMapNode(const void *ptr, int len)
|
SHAMapNode::SHAMapNode(const void *ptr, int len)
|
||||||
{
|
{
|
||||||
if(len<33) mDepth=-1;
|
if (len < 33) mDepth = -1;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memcpy(&mNodeID, ptr, 32);
|
memcpy(&mNodeID, ptr, 32);
|
||||||
mDepth=*(static_cast<const unsigned char *>(ptr) + 32);
|
mDepth = *(static_cast<const unsigned char *>(ptr) + 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,21 +120,21 @@ std::string SHAMapNode::getRawString() const
|
|||||||
|
|
||||||
SHAMapNode SHAMapNode::getChildNodeID(int m) const
|
SHAMapNode SHAMapNode::getChildNodeID(int m) const
|
||||||
{ // This can be optimized to avoid the << if needed
|
{ // This can be optimized to avoid the << if needed
|
||||||
assert((m>=0) && (m<16));
|
assert((m >= 0) && (m < 16));
|
||||||
|
|
||||||
uint256 child(mNodeID);
|
uint256 child(mNodeID);
|
||||||
child.PeekAt(mDepth/8) |= m << (4*(mDepth%8));
|
child.PeekAt(mDepth / 8) |= m << (4 * (mDepth % 8));
|
||||||
return SHAMapNode(mDepth+1, child);
|
return SHAMapNode(mDepth + 1, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SHAMapNode::selectBranch(const uint256& hash) const
|
int SHAMapNode::selectBranch(const uint256& hash) const
|
||||||
{ // Which branch would contain the specified hash
|
{ // Which branch would contain the specified hash
|
||||||
if(mDepth==63)
|
if (mDepth == 63)
|
||||||
{
|
{
|
||||||
assert(false);
|
assert(false);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if((hash&smMasks[mDepth])!=mNodeID)
|
if ((hash & smMasks[mDepth]) != mNodeID)
|
||||||
{
|
{
|
||||||
std::cerr << "selectBranch(" << getString() << std::endl;
|
std::cerr << "selectBranch(" << getString() << std::endl;
|
||||||
std::cerr << " " << hash.GetHex() << " off branch" << std::endl;
|
std::cerr << " " << hash.GetHex() << " off branch" << std::endl;
|
||||||
@@ -142,11 +142,11 @@ int SHAMapNode::selectBranch(const uint256& hash) const
|
|||||||
return -1; // does not go under this node
|
return -1; // does not go under this node
|
||||||
}
|
}
|
||||||
|
|
||||||
int branch=*(hash.begin()+(mDepth/2));
|
int branch = *(hash.begin() + (mDepth / 2));
|
||||||
if(mDepth%2) branch>>=4;
|
if (mDepth % 2) branch >>= 4;
|
||||||
else branch&=0xf;
|
else branch &= 0xf;
|
||||||
|
|
||||||
assert(branch>=0 && branch<16);
|
assert((branch >= 0) && (branch < 16));
|
||||||
return branch;
|
return branch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
|
|||||||
mHash(node.mHash), mItem(node.mItem), mSeq(seq), mType(node.mType), mFullBelow(false)
|
mHash(node.mHash), mItem(node.mItem), mSeq(seq), mType(node.mType), mFullBelow(false)
|
||||||
{
|
{
|
||||||
if(node.mItem)
|
if(node.mItem)
|
||||||
mItem=boost::make_shared<SHAMapItem>(*node.mItem);
|
mItem = boost::make_shared<SHAMapItem>(*node.mItem);
|
||||||
else
|
else
|
||||||
memcpy(mHashes, node.mHashes, sizeof(mHashes));
|
memcpy(mHashes, node.mHashes, sizeof(mHashes));
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapTreeNode& node, uint32 seq) : SHAMapN
|
|||||||
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::pointer item, TNType type, uint32 seq) :
|
SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& node, SHAMapItem::pointer item, TNType type, uint32 seq) :
|
||||||
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true)
|
SHAMapNode(node), mItem(item), mSeq(seq), mType(type), mFullBelow(true)
|
||||||
{
|
{
|
||||||
assert(item->peekData().size()>=12);
|
assert(item->peekData().size() >= 12);
|
||||||
updateHash();
|
updateHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,41 +181,41 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
{
|
{
|
||||||
Serializer s(rawNode);
|
Serializer s(rawNode);
|
||||||
|
|
||||||
int type=s.removeLastByte();
|
int type = s.removeLastByte();
|
||||||
int len=s.getLength();
|
int len = s.getLength();
|
||||||
if( (type<0) || (type>3) || (len<32) ) throw SHAMapException(InvalidNode);
|
if ((type < 0) || (type > 3) || (len < 32)) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(type==0)
|
if (type == 0)
|
||||||
{ // transaction
|
{ // transaction
|
||||||
mItem=boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(s.getSHA512Half(), s.peekData());
|
||||||
mType=tnTRANSACTION;
|
mType = tnTRANSACTION;
|
||||||
}
|
}
|
||||||
else if(type==1)
|
else if (type == 1)
|
||||||
{ // account state
|
{ // account state
|
||||||
uint256 u;
|
uint256 u;
|
||||||
s.get256(u, len-32);
|
s.get256(u, len - 32);
|
||||||
s.chop(256/8);
|
s.chop(256 / 8);
|
||||||
if(u.isZero()) throw SHAMapException(InvalidNode);
|
if (u.isZero()) throw SHAMapException(InvalidNode);
|
||||||
mItem=boost::make_shared<SHAMapItem>(u, s.peekData());
|
mItem = boost::make_shared<SHAMapItem>(u, s.peekData());
|
||||||
mType=tnACCOUNT_STATE;
|
mType = tnACCOUNT_STATE;
|
||||||
}
|
}
|
||||||
else if(type==2)
|
else if (type == 2)
|
||||||
{ // full inner
|
{ // full inner
|
||||||
if(len!=512) throw SHAMapException(InvalidNode);
|
if (len != 512) throw SHAMapException(InvalidNode);
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
s.get256(mHashes[i], i*32);
|
s.get256(mHashes[i], i * 32);
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
}
|
}
|
||||||
else if(type==3)
|
else if (type == 3)
|
||||||
{ // compressed inner
|
{ // compressed inner
|
||||||
for(int i=0; i<(len/33); i++)
|
for (int i = 0; i < (len / 33); ++i)
|
||||||
{
|
{
|
||||||
int pos;
|
int pos;
|
||||||
s.get8(pos, 32+(i*33));
|
s.get8(pos, 32 + (i * 33));
|
||||||
if( (pos<0) || (pos>=16)) throw SHAMapException(InvalidNode);
|
if ((pos < 0) || (pos >= 16)) throw SHAMapException(InvalidNode);
|
||||||
s.get256(mHashes[pos], i*33);
|
s.get256(mHashes[pos], i * 33);
|
||||||
}
|
}
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateHash();
|
updateHash();
|
||||||
@@ -223,17 +223,17 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
|
|||||||
|
|
||||||
void SHAMapTreeNode::addRaw(Serializer &s)
|
void SHAMapTreeNode::addRaw(Serializer &s)
|
||||||
{
|
{
|
||||||
if(mType==tnERROR) throw SHAMapException(InvalidNode);
|
if (mType == tnERROR) throw SHAMapException(InvalidNode);
|
||||||
|
|
||||||
if(mType==tnTRANSACTION)
|
if (mType == tnTRANSACTION)
|
||||||
{
|
{
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add8(0);
|
s.add8(0);
|
||||||
assert(s.getLength()>32);
|
assert(s.getLength() > 32);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mType==tnACCOUNT_STATE)
|
if (mType == tnACCOUNT_STATE)
|
||||||
{
|
{
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add256(mItem->getTag());
|
s.add256(mItem->getTag());
|
||||||
@@ -241,10 +241,10 @@ void SHAMapTreeNode::addRaw(Serializer &s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getBranchCount()<12)
|
if (getBranchCount() < 12)
|
||||||
{ // compressed node
|
{ // compressed node
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero())
|
if (mHashes[i].isNonZero())
|
||||||
{
|
{
|
||||||
s.add256(mHashes[i]);
|
s.add256(mHashes[i]);
|
||||||
s.add8(i);
|
s.add8(i);
|
||||||
@@ -253,7 +253,7 @@ void SHAMapTreeNode::addRaw(Serializer &s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
s.add256(mHashes[i]);
|
s.add256(mHashes[i]);
|
||||||
s.add8(2);
|
s.add8(2);
|
||||||
}
|
}
|
||||||
@@ -262,44 +262,44 @@ bool SHAMapTreeNode::updateHash()
|
|||||||
{
|
{
|
||||||
uint256 nh;
|
uint256 nh;
|
||||||
|
|
||||||
if(mType==tnINNER)
|
if (mType == tnINNER)
|
||||||
{
|
{
|
||||||
bool empty=true;
|
bool empty = true;
|
||||||
for(int i=0; i<16; i++)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero())
|
if (mHashes[i].isNonZero())
|
||||||
{
|
{
|
||||||
empty=false;
|
empty = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!empty)
|
if(!empty)
|
||||||
nh=Serializer::getSHA512Half(reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
|
nh = Serializer::getSHA512Half(reinterpret_cast<unsigned char *>(mHashes), sizeof(mHashes));
|
||||||
}
|
}
|
||||||
else if(mType==tnACCOUNT_STATE)
|
else if (mType == tnACCOUNT_STATE)
|
||||||
{
|
{
|
||||||
Serializer s;
|
Serializer s;
|
||||||
mItem->addRaw(s);
|
mItem->addRaw(s);
|
||||||
s.add160(mItem->getTag().to160());
|
s.add160(mItem->getTag().to160());
|
||||||
nh=s.getSHA512Half();
|
nh = s.getSHA512Half();
|
||||||
}
|
}
|
||||||
else if(mType==tnTRANSACTION)
|
else if (mType == tnTRANSACTION)
|
||||||
{
|
{
|
||||||
nh=Serializer::getSHA512Half(mItem->peekData());
|
nh = Serializer::getSHA512Half(mItem->peekData());
|
||||||
}
|
}
|
||||||
else assert(false);
|
else assert(false);
|
||||||
|
|
||||||
if(nh==mHash) return false;
|
if (nh == mHash) return false;
|
||||||
mHash=nh;
|
mHash = nh;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAMapTreeNode::setItem(SHAMapItem::pointer& i, TNType type)
|
bool SHAMapTreeNode::setItem(SHAMapItem::pointer& i, TNType type)
|
||||||
{
|
{
|
||||||
uint256 hash=getNodeHash();
|
uint256 hash = getNodeHash();
|
||||||
mType=type;
|
mType = type;
|
||||||
mItem=i;
|
mItem = i;
|
||||||
assert(isLeaf());
|
assert(isLeaf());
|
||||||
updateHash();
|
updateHash();
|
||||||
return getNodeHash()==hash;
|
return getNodeHash() == hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
||||||
@@ -311,17 +311,17 @@ SHAMapItem::pointer SHAMapTreeNode::getItem() const
|
|||||||
int SHAMapTreeNode::getBranchCount() const
|
int SHAMapTreeNode::getBranchCount() const
|
||||||
{
|
{
|
||||||
assert(isInner());
|
assert(isInner());
|
||||||
int ret=0;
|
int ret = 0;
|
||||||
for(int i=0; i<16; ++i)
|
for (int i = 0; i < 16; ++i)
|
||||||
if(mHashes[i].isNonZero()) ++ret;
|
if (mHashes[i].isNonZero()) ++ret;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHAMapTreeNode::makeInner()
|
void SHAMapTreeNode::makeInner()
|
||||||
{
|
{
|
||||||
mItem=SHAMapItem::pointer();
|
mItem = SHAMapItem::pointer();
|
||||||
memset(mHashes, 0, sizeof(mHashes));
|
memset(mHashes, 0, sizeof(mHashes));
|
||||||
mType=tnINNER;
|
mType = tnINNER;
|
||||||
mHash.zero();
|
mHash.zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,39 +332,40 @@ void SHAMapTreeNode::dump()
|
|||||||
|
|
||||||
std::string SHAMapTreeNode::getString() const
|
std::string SHAMapTreeNode::getString() const
|
||||||
{
|
{
|
||||||
std::string ret="NodeID(";
|
std::string ret = "NodeID(";
|
||||||
ret+=boost::lexical_cast<std::string>(getDepth());
|
ret += boost::lexical_cast<std::string>(getDepth());
|
||||||
ret+=",";
|
ret += ",";
|
||||||
ret+=getNodeID().GetHex();
|
ret += getNodeID().GetHex();
|
||||||
ret+=")";
|
ret += ")";
|
||||||
if(isInner())
|
if (isInner())
|
||||||
{
|
{
|
||||||
for(int i=0; i<16; i++)
|
for(int i = 0; i < 16; ++i)
|
||||||
if(!isEmptyBranch(i))
|
if (!isEmptyBranch(i))
|
||||||
{
|
{
|
||||||
ret+=",b";
|
ret += ",b";
|
||||||
ret+=boost::lexical_cast<std::string>(i);
|
ret += boost::lexical_cast<std::string>(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(isLeaf())
|
if (isLeaf())
|
||||||
{
|
{
|
||||||
ret+=",leaf";
|
ret += ",leaf";
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
|
bool SHAMapTreeNode::setChildHash(int m, const uint256 &hash)
|
||||||
{
|
{
|
||||||
assert( (m>=0) && (m<16) );
|
assert((m >= 0) && (m < 16));
|
||||||
assert(mType==tnINNER);
|
assert(mType == tnINNER);
|
||||||
if(mHashes[m]==hash)
|
if(mHashes[m] == hash)
|
||||||
return false;
|
return false;
|
||||||
mHashes[m]=hash;
|
mHashes[m] = hash;
|
||||||
return updateHash();
|
return updateHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint256& SHAMapTreeNode::getChildHash(int m) const
|
const uint256& SHAMapTreeNode::getChildHash(int m) const
|
||||||
{
|
{
|
||||||
assert( (m>=0) && (m<16) && (mType==tnINNER) );
|
assert((m >= 0) && (m < 16) && (mType == tnINNER));
|
||||||
return mHashes[m];
|
return mHashes[m];
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -348,6 +348,26 @@ static bool confuseMap(SHAMap &map, int count)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::list<std::vector<unsigned char> > SHAMap::getTrustedPath(const uint256& index)
|
||||||
|
{
|
||||||
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
|
std::stack<SHAMapTreeNode::pointer> stack = SHAMap::getStack(index, false);
|
||||||
|
|
||||||
|
if (stack.empty() || !stack.top()->isLeaf())
|
||||||
|
throw std::runtime_error("requested leaf not present");
|
||||||
|
|
||||||
|
std::list< std::vector<unsigned char> > path;
|
||||||
|
Serializer s;
|
||||||
|
while (!stack.empty())
|
||||||
|
{
|
||||||
|
stack.top()->addRaw(s);
|
||||||
|
path.push_back(s.getData());
|
||||||
|
s.erase();
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
bool SHAMap::syncTest()
|
bool SHAMap::syncTest()
|
||||||
{
|
{
|
||||||
unsigned int seed;
|
unsigned int seed;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ std::string SerializedLedgerEntry::getFullText() const
|
|||||||
ret += mIndex.GetHex();
|
ret += mIndex.GetHex();
|
||||||
ret += "\" = { ";
|
ret += "\" = { ";
|
||||||
ret += mFormat->t_name;
|
ret += mFormat->t_name;
|
||||||
ret += ", ";
|
ret += ", ";
|
||||||
ret += mObject.getFullText();
|
ret += mObject.getFullText();
|
||||||
ret += "}";
|
ret += "}";
|
||||||
return ret;
|
return ret;
|
||||||
@@ -71,3 +71,4 @@ bool SerializedLedgerEntry::isEquivalent(const SerializedType& t) const
|
|||||||
if (mObject != v->mObject) return false;
|
if (mObject != v->mObject) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public:
|
|||||||
std::vector<unsigned char> getIFieldVL(SOE_Field field) const { return mObject.getValueFieldVL(field); }
|
std::vector<unsigned char> getIFieldVL(SOE_Field field) const { return mObject.getValueFieldVL(field); }
|
||||||
std::vector<TaggedListItem> getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); }
|
std::vector<TaggedListItem> getIFieldTL(SOE_Field field) const { return mObject.getValueFieldTL(field); }
|
||||||
NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); }
|
NewcoinAddress getIValueFieldAccount(SOE_Field field) const { return mObject.getValueFieldAccount(field); }
|
||||||
void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); }
|
void setIFieldU8(SOE_Field field, unsigned char v) { return mObject.setValueFieldU8(field, v); }
|
||||||
void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); }
|
void setIFieldU16(SOE_Field field, uint16 v) { return mObject.setValueFieldU16(field, v); }
|
||||||
void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); }
|
void setIFieldU32(SOE_Field field, uint32 v) { return mObject.setValueFieldU32(field, v); }
|
||||||
void setIFieldU64(SOE_Field field, uint32 v) { return mObject.setValueFieldU64(field, v); }
|
void setIFieldU64(SOE_Field field, uint32 v) { return mObject.setValueFieldU64(field, v); }
|
||||||
@@ -74,3 +74,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -467,6 +467,16 @@ void STObject::setValueFieldH160(SOE_Field field, const uint160& v)
|
|||||||
cf->setValue(v);
|
cf->setValue(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void STObject::setValueFieldH256(SOE_Field field, const uint256& v)
|
||||||
|
{
|
||||||
|
SerializedType* rf = getPField(field);
|
||||||
|
if (!rf) throw std::runtime_error("Field not found");
|
||||||
|
if (rf->getSType() == STI_NOTPRESENT) rf = makeFieldPresent(field);
|
||||||
|
STHash256* cf = dynamic_cast<STHash256*>(rf);
|
||||||
|
if (!cf) throw std::runtime_error("Wrong field type");
|
||||||
|
cf->setValue(v);
|
||||||
|
}
|
||||||
|
|
||||||
void STObject::setValueFieldAccount(SOE_Field field, const uint160& v)
|
void STObject::setValueFieldAccount(SOE_Field field, const uint160& v)
|
||||||
{
|
{
|
||||||
SerializedType* rf = getPField(field);
|
SerializedType* rf = getPField(field);
|
||||||
|
|||||||
@@ -27,11 +27,12 @@ enum SOE_Field
|
|||||||
sfFlags, sfExtensions, sfTargetLedger, sfSourceTag, sfIdentifier,
|
sfFlags, sfExtensions, sfTargetLedger, sfSourceTag, sfIdentifier,
|
||||||
sfDestination, sfTarget, sfAmount, sfCurrency,
|
sfDestination, sfTarget, sfAmount, sfCurrency,
|
||||||
sfAmountIn, sfAmountOut, sfCurrencyIn, sfCurrencyOut,
|
sfAmountIn, sfAmountOut, sfCurrencyIn, sfCurrencyOut,
|
||||||
sfInvoiceID, sfExpireLedger, sfMessageKey, sfCurrentRate, sfRateLock,
|
sfInvoiceID, sfExpireLedger, sfMessageKey, sfSigningKey, sfCurrentRate, sfRateLock,
|
||||||
sfAccount, sfSequence, sfBalance, sfWalletLocator, sfEmailHash,
|
sfAccount, sfSequence, sfBalance, sfWalletLocator, sfEmailHash,
|
||||||
sfBorrower, sfLendfer, sfLimit, sfOfferCurrency,
|
sfBorrower, sfLender, sfLimit, sfOfferCurrency, sfLedgerHash,
|
||||||
sfLastReceive, sfLastTxn, sfLender, sfNextRate, sfNextRateLgr, sfNextRateExp,
|
sfLastReceive, sfLastTxn, sfNextRate, sfNextRateLgr, sfNextRateExp,
|
||||||
sfNickname, sfMinimumOffer,
|
sfNickname, sfMinimumOffer,
|
||||||
|
sfAuthorizedKey, sfGenerator, sfGeneratorID, sfAccountID,
|
||||||
|
|
||||||
// test fields
|
// test fields
|
||||||
sfTest1, sfTest2, sfTest3, sfTest4
|
sfTest1, sfTest2, sfTest3, sfTest4
|
||||||
@@ -131,3 +132,4 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -38,14 +38,6 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length
|
|||||||
mMiddleTxn.giveObject(new STUInt64("Fee", sit.get64()));
|
mMiddleTxn.giveObject(new STUInt64("Fee", sit.get64()));
|
||||||
|
|
||||||
mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction");
|
mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction");
|
||||||
updateSourceAccount();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SerializedTransaction::updateSourceAccount()
|
|
||||||
{
|
|
||||||
NewcoinAddress a;
|
|
||||||
a.setAccountPublic(peekSigningPubKey());
|
|
||||||
mSourceAccount.setAccountID(a.getAccountID());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SerializedTransaction::getLength() const
|
int SerializedTransaction::getLength() const
|
||||||
@@ -217,12 +209,25 @@ std::vector<unsigned char>& SerializedTransaction::peekSigningPubKey()
|
|||||||
return v->peekValue();
|
return v->peekValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
const NewcoinAddress& SerializedTransaction::setSigningPubKey(const std::vector<unsigned char>& s)
|
const NewcoinAddress& SerializedTransaction::setSigningPubKey(const NewcoinAddress& naSignPubKey)
|
||||||
{
|
{
|
||||||
|
mSignPubKey = naSignPubKey;
|
||||||
|
|
||||||
STVariableLength* v = dynamic_cast<STVariableLength*>(mMiddleTxn.getPIndex(TransactionISigningPubKey));
|
STVariableLength* v = dynamic_cast<STVariableLength*>(mMiddleTxn.getPIndex(TransactionISigningPubKey));
|
||||||
if (!v) throw std::runtime_error("corrupt transaction");
|
if (!v) throw std::runtime_error("corrupt transaction");
|
||||||
v->setValue(s);
|
v->setValue(mSignPubKey.getAccountPublic());
|
||||||
updateSourceAccount();
|
|
||||||
|
return mSignPubKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NewcoinAddress& SerializedTransaction::setSourceAccount(const NewcoinAddress& naSource)
|
||||||
|
{
|
||||||
|
mSourceAccount = naSource;
|
||||||
|
|
||||||
|
STHash160* v = dynamic_cast<STHash160*>(mMiddleTxn.getPIndex(TransactionISourceID));
|
||||||
|
if (!v) throw std::runtime_error("corrupt transaction");
|
||||||
|
v->setValue(mSourceAccount.getAccountID());
|
||||||
|
|
||||||
return mSourceAccount;
|
return mSourceAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,3 +288,4 @@ Json::Value SerializedTransaction::getJson(int options) const
|
|||||||
ret["Inner"] = mInnerTxn.getJson(options);
|
ret["Inner"] = mInnerTxn.getJson(options);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -16,14 +16,13 @@ public:
|
|||||||
typedef boost::shared_ptr<SerializedTransaction> pointer;
|
typedef boost::shared_ptr<SerializedTransaction> pointer;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
NewcoinAddress mSignPubKey;
|
||||||
NewcoinAddress mSourceAccount;
|
NewcoinAddress mSourceAccount;
|
||||||
TransactionType mType;
|
TransactionType mType;
|
||||||
STVariableLength mSignature;
|
STVariableLength mSignature;
|
||||||
STObject mMiddleTxn, mInnerTxn;
|
STObject mMiddleTxn, mInnerTxn;
|
||||||
TransactionFormat* mFormat;
|
TransactionFormat* mFormat;
|
||||||
|
|
||||||
void updateSourceAccount();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit
|
SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit
|
||||||
SerializedTransaction(TransactionType type);
|
SerializedTransaction(TransactionType type);
|
||||||
@@ -42,7 +41,7 @@ public:
|
|||||||
const std::vector<unsigned char>& peekSignature() const;
|
const std::vector<unsigned char>& peekSignature() const;
|
||||||
void setSignature(const std::vector<unsigned char>& s);
|
void setSignature(const std::vector<unsigned char>& s);
|
||||||
uint256 getSigningHash() const;
|
uint256 getSigningHash() const;
|
||||||
|
|
||||||
// middle transaction functions
|
// middle transaction functions
|
||||||
uint32 getVersion() const;
|
uint32 getVersion() const;
|
||||||
void setVersion(uint32);
|
void setVersion(uint32);
|
||||||
@@ -55,14 +54,15 @@ public:
|
|||||||
std::vector<unsigned char> getSigningPubKey() const;
|
std::vector<unsigned char> getSigningPubKey() const;
|
||||||
const std::vector<unsigned char>& peekSigningPubKey() const;
|
const std::vector<unsigned char>& peekSigningPubKey() const;
|
||||||
std::vector<unsigned char>& peekSigningPubKey();
|
std::vector<unsigned char>& peekSigningPubKey();
|
||||||
const NewcoinAddress& setSigningPubKey(const std::vector<unsigned char>& s);
|
const NewcoinAddress& setSigningPubKey(const NewcoinAddress& naSignPubKey);
|
||||||
|
const NewcoinAddress& setSourceAccount(const NewcoinAddress& naSource);
|
||||||
std::string getTransactionType() const { return mFormat->t_name; }
|
std::string getTransactionType() const { return mFormat->t_name; }
|
||||||
|
|
||||||
// inner transaction functions
|
// inner transaction functions
|
||||||
uint32 getFlags() const { return mInnerTxn.getFlags(); }
|
uint32 getFlags() const { return mInnerTxn.getFlags(); }
|
||||||
void setFlag(uint32 v) { mInnerTxn.setFlag(v); }
|
void setFlag(uint32 v) { mInnerTxn.setFlag(v); }
|
||||||
void clearFlag(uint32 v) { mInnerTxn.clearFlag(v); }
|
void clearFlag(uint32 v) { mInnerTxn.clearFlag(v); }
|
||||||
|
|
||||||
uint32 getSequence() const;
|
uint32 getSequence() const;
|
||||||
void setSequence(uint32);
|
void setSequence(uint32);
|
||||||
|
|
||||||
@@ -116,3 +116,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "SerializedObject.h"
|
#include "SerializedObject.h"
|
||||||
#include "TransactionFormats.h"
|
#include "TransactionFormats.h"
|
||||||
#include "NewcoinAddress.h"
|
#include "NewcoinAddress.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
std::string SerializedType::getFullText() const
|
std::string SerializedType::getFullText() const
|
||||||
{
|
{
|
||||||
@@ -133,18 +134,14 @@ bool STHash256::isEquivalent(const SerializedType& t) const
|
|||||||
return v && (value == v->value);
|
return v && (value == v->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string hex(const std::vector<unsigned char>& value)
|
STVariableLength::STVariableLength(SerializerIterator& st, const char *name) : SerializedType(name)
|
||||||
{
|
{
|
||||||
int dlen=value.size(), i=0;
|
value = st.getVL();
|
||||||
char psz[dlen*2 + 1];
|
|
||||||
for(std::vector<unsigned char>::const_iterator it=value.begin(), end=value.end(); it!=end; ++it)
|
|
||||||
sprintf(psz + 2*(i++), "%02X", *it);
|
|
||||||
return std::string(psz, psz + value.size()*2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string STVariableLength::getText() const
|
std::string STVariableLength::getText() const
|
||||||
{
|
{
|
||||||
return hex(value);
|
return strHex(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
STVariableLength* STVariableLength::construct(SerializerIterator& u, const char *name)
|
STVariableLength* STVariableLength::construct(SerializerIterator& u, const char *name)
|
||||||
@@ -225,7 +222,7 @@ std::string STTaggedList::getText() const
|
|||||||
{
|
{
|
||||||
ret += boost::lexical_cast<std::string>(it->first);
|
ret += boost::lexical_cast<std::string>(it->first);
|
||||||
ret += ",";
|
ret += ",";
|
||||||
ret += hex(it->second);
|
ret += strHex(it->second);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
|
|
||||||
STUInt8(unsigned char v=0) : value(v) { ; }
|
STUInt8(unsigned char v=0) : value(v) { ; }
|
||||||
STUInt8(const char *n, unsigned char v=0) : SerializedType(n), value(v) { ; }
|
STUInt8(const char *n, unsigned char v=0) : SerializedType(n), value(v) { ; }
|
||||||
static STUInt8* construct(SerializerIterator&, const char *name=NULL);
|
static STUInt8* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 1; }
|
int getLength() const { return 1; }
|
||||||
SerializedTypeID getSType() const { return STI_UINT8; }
|
SerializedTypeID getSType() const { return STI_UINT8; }
|
||||||
@@ -91,7 +91,7 @@ public:
|
|||||||
|
|
||||||
STUInt16(uint16 v=0) : value(v) { ; }
|
STUInt16(uint16 v=0) : value(v) { ; }
|
||||||
STUInt16(const char *n, uint16 v=0) : SerializedType(n), value(v) { ; }
|
STUInt16(const char *n, uint16 v=0) : SerializedType(n), value(v) { ; }
|
||||||
static STUInt16* construct(SerializerIterator&, const char *name=NULL);
|
static STUInt16* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 2; }
|
int getLength() const { return 2; }
|
||||||
SerializedTypeID getSType() const { return STI_UINT16; }
|
SerializedTypeID getSType() const { return STI_UINT16; }
|
||||||
@@ -116,7 +116,7 @@ public:
|
|||||||
|
|
||||||
STUInt32(uint32 v=0) : value(v) { ; }
|
STUInt32(uint32 v=0) : value(v) { ; }
|
||||||
STUInt32(const char *n, uint32 v=0) : SerializedType(n), value(v) { ; }
|
STUInt32(const char *n, uint32 v=0) : SerializedType(n), value(v) { ; }
|
||||||
static STUInt32* construct(SerializerIterator&, const char *name=NULL);
|
static STUInt32* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 4; }
|
int getLength() const { return 4; }
|
||||||
SerializedTypeID getSType() const { return STI_UINT32; }
|
SerializedTypeID getSType() const { return STI_UINT32; }
|
||||||
@@ -141,7 +141,7 @@ public:
|
|||||||
|
|
||||||
STUInt64(uint64 v=0) : value(v) { ; }
|
STUInt64(uint64 v=0) : value(v) { ; }
|
||||||
STUInt64(const char *n, uint64 v=0) : SerializedType(n), value(v) { ; }
|
STUInt64(const char *n, uint64 v=0) : SerializedType(n), value(v) { ; }
|
||||||
static STUInt64* construct(SerializerIterator&, const char *name=NULL);
|
static STUInt64* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 8; }
|
int getLength() const { return 8; }
|
||||||
SerializedTypeID getSType() const { return STI_UINT64; }
|
SerializedTypeID getSType() const { return STI_UINT64; }
|
||||||
@@ -247,10 +247,11 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
STHash128(const uint128& v=uint128()) : value(v) { ; }
|
STHash128(const uint128& v) : value(v) { ; }
|
||||||
STHash128(const char *n, const uint128& v=uint128()) : SerializedType(n), value(v) { ; }
|
STHash128(const char *n, const uint128& v) : SerializedType(n), value(v) { ; }
|
||||||
|
STHash128(const char *n) : SerializedType(n) { ; }
|
||||||
STHash128() { ; }
|
STHash128() { ; }
|
||||||
static STHash128* construct(SerializerIterator&, const char *name=NULL);
|
static STHash128* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 20; }
|
int getLength() const { return 20; }
|
||||||
SerializedTypeID getSType() const { return STI_HASH128; }
|
SerializedTypeID getSType() const { return STI_HASH128; }
|
||||||
@@ -273,10 +274,11 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
STHash160(const uint160& v=uint160()) : value(v) { ; }
|
STHash160(const uint160& v) : value(v) { ; }
|
||||||
STHash160(const char *n, const uint160& v=uint160()) : SerializedType(n), value(v) { ; }
|
STHash160(const char *n, const uint160& v) : SerializedType(n), value(v) { ; }
|
||||||
|
STHash160(const char *n) : SerializedType(n) { ; }
|
||||||
STHash160() { ; }
|
STHash160() { ; }
|
||||||
static STHash160* construct(SerializerIterator&, const char *name=NULL);
|
static STHash160* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 20; }
|
int getLength() const { return 20; }
|
||||||
SerializedTypeID getSType() const { return STI_HASH160; }
|
SerializedTypeID getSType() const { return STI_HASH160; }
|
||||||
@@ -300,9 +302,10 @@ protected:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
STHash256(const uint256& v) : value(v) { ; }
|
STHash256(const uint256& v) : value(v) { ; }
|
||||||
STHash256(const char *n, const uint256& v=uint256()) : SerializedType(n), value(v) { ; }
|
STHash256(const char *n, const uint256& v) : SerializedType(n), value(v) { ; }
|
||||||
|
STHash256(const char *n) : SerializedType(n) { ; }
|
||||||
STHash256() { ; }
|
STHash256() { ; }
|
||||||
static STHash256* construct(SerializerIterator&, const char *name=NULL);
|
static STHash256* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const { return 32; }
|
int getLength() const { return 32; }
|
||||||
SerializedTypeID getSType() const { return STI_HASH256; }
|
SerializedTypeID getSType() const { return STI_HASH256; }
|
||||||
@@ -328,8 +331,9 @@ public:
|
|||||||
STVariableLength(const std::vector<unsigned char>& v) : value(v) { ; }
|
STVariableLength(const std::vector<unsigned char>& v) : value(v) { ; }
|
||||||
STVariableLength(const char *n, const std::vector<unsigned char>& v) : SerializedType(n), value(v) { ; }
|
STVariableLength(const char *n, const std::vector<unsigned char>& v) : SerializedType(n), value(v) { ; }
|
||||||
STVariableLength(const char *n) : SerializedType(n) { ; }
|
STVariableLength(const char *n) : SerializedType(n) { ; }
|
||||||
|
STVariableLength(SerializerIterator&, const char *name = NULL);
|
||||||
STVariableLength() { ; }
|
STVariableLength() { ; }
|
||||||
static STVariableLength* construct(SerializerIterator&, const char *name=NULL);
|
static STVariableLength* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const;
|
int getLength() const;
|
||||||
virtual SerializedTypeID getSType() const { return STI_VL; }
|
virtual SerializedTypeID getSType() const { return STI_VL; }
|
||||||
@@ -380,7 +384,7 @@ public:
|
|||||||
STTaggedList(const char *n) : SerializedType(n) { ; }
|
STTaggedList(const char *n) : SerializedType(n) { ; }
|
||||||
STTaggedList(const std::vector<TaggedListItem>& v) : value(v) { ; }
|
STTaggedList(const std::vector<TaggedListItem>& v) : value(v) { ; }
|
||||||
STTaggedList(const char *n, const std::vector<TaggedListItem>& v) : SerializedType(n), value(v) { ; }
|
STTaggedList(const char *n, const std::vector<TaggedListItem>& v) : SerializedType(n), value(v) { ; }
|
||||||
static STTaggedList* construct(SerializerIterator&, const char *name=NULL);
|
static STTaggedList* construct(SerializerIterator&, const char *name = NULL);
|
||||||
|
|
||||||
int getLength() const;
|
int getLength() const;
|
||||||
SerializedTypeID getSType() const { return STI_TL; }
|
SerializedTypeID getSType() const { return STI_TL; }
|
||||||
@@ -406,3 +410,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
93
src/SerializedValidation.cpp
Normal file
93
src/SerializedValidation.cpp
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
|
||||||
|
#include "SerializedValidation.h"
|
||||||
|
|
||||||
|
SOElement SerializedValidation::sValidationFormat[] = {
|
||||||
|
{ sfFlags, "Flags", STI_UINT32, SOE_FLAGS, 0 },
|
||||||
|
{ sfLedgerHash, "LedgerHash", STI_HASH256, SOE_REQUIRED, 0 },
|
||||||
|
{ sfSigningKey, "SigningKey", STI_VL, SOE_REQUIRED, 0 },
|
||||||
|
{ sfExtensions, "Extensions", STI_TL, SOE_IFFLAG, 0x01000000 },
|
||||||
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 },
|
||||||
|
};
|
||||||
|
|
||||||
|
const uint32 SerializedValidation::sFullFlag = 0x00010000;
|
||||||
|
const uint32 SerializedValidation::sValidationMagic = 0x4c575200; // "LGR"
|
||||||
|
|
||||||
|
SerializedValidation::SerializedValidation(SerializerIterator& sit, bool checkSignature)
|
||||||
|
: STObject(sValidationFormat, sit), mSignature(sit, "Signature")
|
||||||
|
{
|
||||||
|
if (!isValid()) throw std::runtime_error("Invalid validation");
|
||||||
|
}
|
||||||
|
|
||||||
|
SerializedValidation::SerializedValidation(const uint256& ledgerHash, CKey::pointer nodeKey, bool isFull)
|
||||||
|
: STObject(sValidationFormat), mSignature("Signature")
|
||||||
|
{
|
||||||
|
setValueFieldH256(sfLedgerHash, ledgerHash);
|
||||||
|
setValueFieldVL(sfSigningKey, nodeKey->GetPubKey());
|
||||||
|
if (!isFull) setFlag(sFullFlag);
|
||||||
|
|
||||||
|
if (!nodeKey->Sign(getSigningHash(), mSignature.peekValue()))
|
||||||
|
throw std::runtime_error("Unable to sign validation");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 SerializedValidation::getSigningHash() const
|
||||||
|
{
|
||||||
|
Serializer s;
|
||||||
|
s.add32(sValidationMagic);
|
||||||
|
add(s);
|
||||||
|
return s.getSHA512Half();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint256 SerializedValidation::getLedgerHash() const
|
||||||
|
{
|
||||||
|
return getValueFieldH256(sfLedgerHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SerializedValidation::isValid() const
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CKey pubKey;
|
||||||
|
return pubKey.SetPubKey(getValueFieldVL(sfSigningKey)) &&
|
||||||
|
pubKey.Verify(getSigningHash(), mSignature.peekValue());
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NewcoinAddress SerializedValidation::getSignerPublic() const
|
||||||
|
{
|
||||||
|
NewcoinAddress a;
|
||||||
|
a.setNodePublic(getValueFieldVL(sfSigningKey));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SerializedValidation::isFull() const
|
||||||
|
{
|
||||||
|
return (getFlags() & sFullFlag) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializedValidation::addSigned(Serializer& s) const
|
||||||
|
{
|
||||||
|
add(s);
|
||||||
|
mSignature.add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SerializedValidation::addSignature(Serializer& s) const
|
||||||
|
{
|
||||||
|
mSignature.add(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> SerializedValidation::getSigned() const
|
||||||
|
{
|
||||||
|
Serializer s;
|
||||||
|
addSigned(s);
|
||||||
|
return s.peekData();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<unsigned char> SerializedValidation::getSignature() const
|
||||||
|
{
|
||||||
|
return mSignature.peekValue();
|
||||||
|
}
|
||||||
|
// vim:ts=4
|
||||||
38
src/SerializedValidation.h
Normal file
38
src/SerializedValidation.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef __VALIDATION__
|
||||||
|
#define __VALIDATION__
|
||||||
|
|
||||||
|
#include "SerializedObject.h"
|
||||||
|
|
||||||
|
class SerializedValidation : public STObject
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
STVariableLength mSignature;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef boost::shared_ptr<SerializedValidation> pointer;
|
||||||
|
|
||||||
|
static SOElement sValidationFormat[16];
|
||||||
|
static const uint32 sFullFlag;
|
||||||
|
static const uint32 sValidationMagic;
|
||||||
|
|
||||||
|
// These throw if the object is not valid
|
||||||
|
SerializedValidation(SerializerIterator& sit, bool checkSignature = true);
|
||||||
|
SerializedValidation(const Serializer& s, bool checkSignature = true);
|
||||||
|
|
||||||
|
SerializedValidation(const uint256& ledgerHash, CKey::pointer nodeKey, bool isFull);
|
||||||
|
|
||||||
|
uint256 getLedgerHash() const;
|
||||||
|
NewcoinAddress getSignerPublic() const;
|
||||||
|
bool isValid() const;
|
||||||
|
bool isFull() const;
|
||||||
|
CKey::pointer getSigningKey() const;
|
||||||
|
uint256 getSigningHash() const;
|
||||||
|
|
||||||
|
void addSigned(Serializer&) const;
|
||||||
|
void addSignature(Serializer&) const;
|
||||||
|
std::vector<unsigned char> getSigned() const;
|
||||||
|
std::vector<unsigned char> getSignature() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
@@ -81,28 +81,31 @@ int Serializer::addRaw(const void *ptr, int len)
|
|||||||
bool Serializer::get16(uint16& o, int offset) const
|
bool Serializer::get16(uint16& o, int offset) const
|
||||||
{
|
{
|
||||||
if ((offset + 2) > mData.size()) return false;
|
if ((offset + 2) > mData.size()) return false;
|
||||||
o = mData.at(offset++);
|
const unsigned char *ptr = &mData[offset];
|
||||||
o <<= 8; o |= mData.at(offset);
|
o = *ptr++; o <<= 8; o |= *ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Serializer::get32(uint32& o, int offset) const
|
bool Serializer::get32(uint32& o, int offset) const
|
||||||
{
|
{
|
||||||
if ((offset + 4) > mData.size()) return false;
|
if ((offset + 4) > mData.size()) return false;
|
||||||
o=mData.at(offset++);
|
const unsigned char *ptr = &mData[offset];
|
||||||
o<<=8; o |= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
|
o = *ptr++;
|
||||||
o<<=8; o |= mData.at(offset);
|
o <<= 8; o |= *ptr++;
|
||||||
|
o <<= 8; o |= *ptr++;
|
||||||
|
o <<= 8; o |= *ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Serializer::get64(uint64& o, int offset) const
|
bool Serializer::get64(uint64& o, int offset) const
|
||||||
{
|
{
|
||||||
if ((offset + 8) > mData.size()) return false;
|
if ((offset + 8) > mData.size()) return false;
|
||||||
o=mData.at(offset++);
|
const unsigned char *ptr = &mData[offset];
|
||||||
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
|
o = *ptr++;
|
||||||
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
|
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
|
||||||
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
|
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
|
||||||
o<<=8; o|= mData.at(offset);
|
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
|
||||||
|
o <<= 8; o |= *ptr;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,7 @@ int Serializer::removeLastByte()
|
|||||||
bool Serializer::getRaw(std::vector<unsigned char>& o, int offset, int length) const
|
bool Serializer::getRaw(std::vector<unsigned char>& o, int offset, int length) const
|
||||||
{
|
{
|
||||||
if ((offset + length) > mData.size()) return false;
|
if ((offset + length) > mData.size()) return false;
|
||||||
o.assign(mData.begin() + offset, mData.begin() + offset+length);
|
o.assign(mData.begin() + offset, mData.begin() + offset + length);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,12 +236,12 @@ bool Serializer::checkSignature(int pubkeyOffset, int signatureOffset) const
|
|||||||
|
|
||||||
CKey pubCKey;
|
CKey pubCKey;
|
||||||
if (!pubCKey.SetPubKey(pubkey)) return false;
|
if (!pubCKey.SetPubKey(pubkey)) return false;
|
||||||
return pubCKey.Verify(getSHA512Half(signatureOffset), signature);
|
return pubCKey.Verify(getSHA512Half(signatureOffset), signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Serializer::checkSignature(const std::vector<unsigned char> &signature, CKey& key) const
|
bool Serializer::checkSignature(const std::vector<unsigned char> &signature, CKey& key) const
|
||||||
{
|
{
|
||||||
return key.Verify(getSHA512Half(), signature);
|
return key.Verify(getSHA512Half(), signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Serializer::makeSignature(std::vector<unsigned char> &signature, CKey& key) const
|
bool Serializer::makeSignature(std::vector<unsigned char> &signature, CKey& key) const
|
||||||
@@ -259,7 +262,7 @@ int Serializer::addVL(const std::vector<unsigned char>& vector)
|
|||||||
{
|
{
|
||||||
int ret = addRaw(encodeVL(vector.size()));
|
int ret = addRaw(encodeVL(vector.size()));
|
||||||
addRaw(vector);
|
addRaw(vector);
|
||||||
assert(mData.size() + (ret + vector.size() + encodeLengthLength(vector.size())));
|
assert(mData.size() == (ret + vector.size() + encodeLengthLength(vector.size())));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,12 +365,12 @@ bool Serializer::getVLLength(int& length, int offset) const
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (lenLen == 1)
|
if (lenLen == 1)
|
||||||
length=decodeVLLength(b1);
|
length = decodeVLLength(b1);
|
||||||
else if (lenLen == 2)
|
else if (lenLen == 2)
|
||||||
{
|
{
|
||||||
int b2;
|
int b2;
|
||||||
if (!get8(b2, offset++)) return false;
|
if (!get8(b2, offset++)) return false;
|
||||||
length=decodeVLLength(b1, b2);
|
length = decodeVLLength(b1, b2);
|
||||||
}
|
}
|
||||||
else if (lenLen == 3)
|
else if (lenLen == 3)
|
||||||
{
|
{
|
||||||
@@ -391,7 +394,7 @@ bool Serializer::getTaggedList(std::list<TaggedListItem>& list, int offset, int&
|
|||||||
int startOffset = offset;
|
int startOffset = offset;
|
||||||
int numElem;
|
int numElem;
|
||||||
if (!get8(numElem, offset++)) return false;
|
if (!get8(numElem, offset++)) return false;
|
||||||
for (int i = 0; i<numElem; i++)
|
for (int i = 0; i<numElem; ++i)
|
||||||
{
|
{
|
||||||
int tag, len;
|
int tag, len;
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
@@ -407,10 +410,10 @@ bool Serializer::getTaggedList(std::list<TaggedListItem>& list, int offset, int&
|
|||||||
bool Serializer::getTaggedList(std::vector<TaggedListItem>& list, int offset, int& length) const
|
bool Serializer::getTaggedList(std::vector<TaggedListItem>& list, int offset, int& length) const
|
||||||
{
|
{
|
||||||
list.clear();
|
list.clear();
|
||||||
int startOffset=offset;
|
int startOffset = offset;
|
||||||
int numElem;
|
int numElem;
|
||||||
if (!get8(numElem, offset++)) return false;
|
if (!get8(numElem, offset++)) return false;
|
||||||
for (int i=0; i<numElem; i++)
|
for (int i = 0; i<numElem; ++i)
|
||||||
{
|
{
|
||||||
int tag, len;
|
int tag, len;
|
||||||
std::vector<unsigned char> data;
|
std::vector<unsigned char> data;
|
||||||
@@ -502,7 +505,7 @@ unsigned char SerializerIterator::get8()
|
|||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
if (!mSerializer.get8(val, mPos)) throw std::runtime_error("invalid serializer get8");
|
if (!mSerializer.get8(val, mPos)) throw std::runtime_error("invalid serializer get8");
|
||||||
mPos++;
|
++mPos;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,7 +513,7 @@ uint16 SerializerIterator::get16()
|
|||||||
{
|
{
|
||||||
uint16 val;
|
uint16 val;
|
||||||
if (!mSerializer.get16(val, mPos)) throw std::runtime_error("invalid serializer get16");
|
if (!mSerializer.get16(val, mPos)) throw std::runtime_error("invalid serializer get16");
|
||||||
mPos += 16/8;
|
mPos += 16 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,7 +521,7 @@ uint32 SerializerIterator::get32()
|
|||||||
{
|
{
|
||||||
uint32 val;
|
uint32 val;
|
||||||
if (!mSerializer.get32(val, mPos)) throw std::runtime_error("invalid serializer get32");
|
if (!mSerializer.get32(val, mPos)) throw std::runtime_error("invalid serializer get32");
|
||||||
mPos += 32/8;
|
mPos += 32 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +529,7 @@ uint64 SerializerIterator::get64()
|
|||||||
{
|
{
|
||||||
uint64 val;
|
uint64 val;
|
||||||
if (!mSerializer.get64(val, mPos)) throw std::runtime_error("invalid serializer get64");
|
if (!mSerializer.get64(val, mPos)) throw std::runtime_error("invalid serializer get64");
|
||||||
mPos += 64/8;
|
mPos += 64 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +537,7 @@ uint128 SerializerIterator::get128()
|
|||||||
{
|
{
|
||||||
uint128 val;
|
uint128 val;
|
||||||
if (!mSerializer.get128(val, mPos)) throw std::runtime_error("invalid serializer get128");
|
if (!mSerializer.get128(val, mPos)) throw std::runtime_error("invalid serializer get128");
|
||||||
mPos += 128/8;
|
mPos += 128 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -542,7 +545,7 @@ uint160 SerializerIterator::get160()
|
|||||||
{
|
{
|
||||||
uint160 val;
|
uint160 val;
|
||||||
if (!mSerializer.get160(val, mPos)) throw std::runtime_error("invalid serializer get160");
|
if (!mSerializer.get160(val, mPos)) throw std::runtime_error("invalid serializer get160");
|
||||||
mPos += 160/8;
|
mPos += 160 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,7 +553,7 @@ uint256 SerializerIterator::get256()
|
|||||||
{
|
{
|
||||||
uint256 val;
|
uint256 val;
|
||||||
if (!mSerializer.get256(val, mPos)) throw std::runtime_error("invalid serializer get256");
|
if (!mSerializer.get256(val, mPos)) throw std::runtime_error("invalid serializer get256");
|
||||||
mPos += 256/8;
|
mPos += 256 / 8;
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -571,3 +574,4 @@ std::vector<TaggedListItem> SerializerIterator::getTaggedList()
|
|||||||
mPos += length;
|
mPos += length;
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
#include "TimingService.h"
|
|
||||||
#include "Config.h"
|
|
||||||
#include "Application.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <ctime>
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using namespace boost;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Only needs to start once we determine the network time
|
|
||||||
*/
|
|
||||||
|
|
||||||
TimingService::TimingService() : mLedgerTimer(NULL), mPropTimer(NULL), mValidTimer(NULL)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimingService::start(boost::asio::io_service& ioService)
|
|
||||||
{
|
|
||||||
// TODO: calculate the amount of seconds left in the current ledger
|
|
||||||
mLedgerTimer=new asio::deadline_timer(ioService, posix_time::seconds(theConfig.LEDGER_SECONDS)),
|
|
||||||
mLedgerTimer->async_wait(boost::bind(&TimingService::handleLedger, this));
|
|
||||||
|
|
||||||
mPropTimer=new asio::deadline_timer(ioService, posix_time::seconds(theConfig.LEDGER_PROPOSAL_DELAY_SECONDS));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimingService::handleLedger()
|
|
||||||
{
|
|
||||||
cout << "publish ledger" << endl;
|
|
||||||
#if 0
|
|
||||||
theApp->getLedgerMaster().startFinalization();
|
|
||||||
mLedgerTimer->expires_at(mLedgerTimer->expires_at() + boost::posix_time::seconds(theConfig.LEDGER_SECONDS));
|
|
||||||
mLedgerTimer->async_wait(boost::bind(&TimingService::handleLedger, this));
|
|
||||||
|
|
||||||
mPropTimer->expires_at(mLedgerTimer->expires_at() + boost::posix_time::seconds(theConfig.LEDGER_PROPOSAL_DELAY_SECONDS));
|
|
||||||
mPropTimer->async_wait(boost::bind(&TimingService::handleProp, this));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimingService::handleProp()
|
|
||||||
{
|
|
||||||
// theApp->getLedgerMaster().sendProposal();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TimingService::handleValid()
|
|
||||||
{
|
|
||||||
// theApp->getLedgerMaster().endFinalization();
|
|
||||||
}
|
|
||||||
|
|
||||||
int TimingService::getCurrentLedgerIndex()
|
|
||||||
{
|
|
||||||
return( (time(NULL)-theConfig.NETWORK_START_TIME)/theConfig.LEDGER_SECONDS );
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#ifndef __TIMINGSERVICE__
|
|
||||||
#define __TIMINGSERVICE__
|
|
||||||
|
|
||||||
#include <boost/asio.hpp>
|
|
||||||
|
|
||||||
/* responsible for keeping track of network time
|
|
||||||
and kicking off the publishing process
|
|
||||||
*/
|
|
||||||
|
|
||||||
class TimingService
|
|
||||||
{
|
|
||||||
boost::asio::deadline_timer* mLedgerTimer;
|
|
||||||
boost::asio::deadline_timer* mPropTimer;
|
|
||||||
boost::asio::deadline_timer* mValidTimer;
|
|
||||||
|
|
||||||
void handleLedger();
|
|
||||||
void handleProp();
|
|
||||||
void handleValid();
|
|
||||||
public:
|
|
||||||
TimingService();
|
|
||||||
void start(boost::asio::io_service& ioService);
|
|
||||||
|
|
||||||
static int getCurrentLedgerIndex();
|
|
||||||
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
@@ -23,7 +23,14 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd
|
|||||||
|
|
||||||
mFromPubKey = fromLocalAccount->getPublicKey();
|
mFromPubKey = fromLocalAccount->getPublicKey();
|
||||||
assert(mFromPubKey);
|
assert(mFromPubKey);
|
||||||
mTransaction->setSigningPubKey(mFromPubKey->GetPubKey());
|
|
||||||
|
// XXX Temporary: We don't really have local accounts.
|
||||||
|
NewcoinAddress signPubKey;
|
||||||
|
|
||||||
|
signPubKey.setAccountPublic(mFromPubKey->GetPubKey());
|
||||||
|
|
||||||
|
mTransaction->setSigningPubKey(signPubKey);
|
||||||
|
mTransaction->setSourceAccount(mAccountFrom);
|
||||||
|
|
||||||
mTransaction->setSequence(accountState->getSeq());
|
mTransaction->setSequence(accountState->getSeq());
|
||||||
assert(mTransaction->getSequence() != 0);
|
assert(mTransaction->getSequence() != 0);
|
||||||
@@ -105,6 +112,7 @@ Transaction::Transaction(const std::vector<unsigned char>& raw, bool validate) :
|
|||||||
mStatus = NEW;
|
mStatus = NEW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID,
|
Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID,
|
||||||
CKey::pointer pubKey, uint64 amount, uint64 fee, uint32 fromSeq, uint32 fromLedger,
|
CKey::pointer pubKey, uint64 amount, uint64 fee, uint32 fromSeq, uint32 fromLedger,
|
||||||
uint32 ident, const std::vector<unsigned char>& signature, uint32 ledgerSeq, TransStatus st) :
|
uint32 ident, const std::vector<unsigned char>& signature, uint32 ledgerSeq, TransStatus st) :
|
||||||
@@ -113,7 +121,8 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI
|
|||||||
mTransaction = boost::make_shared<SerializedTransaction>(ttMAKE_PAYMENT);
|
mTransaction = boost::make_shared<SerializedTransaction>(ttMAKE_PAYMENT);
|
||||||
mTransaction->setSignature(signature);
|
mTransaction->setSignature(signature);
|
||||||
mTransaction->setTransactionFee(fee);
|
mTransaction->setTransactionFee(fee);
|
||||||
mTransaction->setSigningPubKey(pubKey->GetPubKey());
|
mTransaction->setSigningPubKey(pubKey); // BROKEN
|
||||||
|
mTransaction->setSourceAccount(mAccountFrom); // BROKEN
|
||||||
mTransaction->setSequence(fromSeq);
|
mTransaction->setSequence(fromSeq);
|
||||||
if (fromLedger != 0)
|
if (fromLedger != 0)
|
||||||
{
|
{
|
||||||
@@ -129,6 +138,7 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI
|
|||||||
mTransaction->setITFieldAccount(sfDestination, toID.getAccountID());
|
mTransaction->setITFieldAccount(sfDestination, toID.getAccountID());
|
||||||
updateID();
|
updateID();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
|
bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
|
||||||
{
|
{
|
||||||
@@ -225,10 +235,10 @@ bool Transaction::save() const
|
|||||||
theApp->getTxnDB()->getDB()->escape(static_cast<const unsigned char *>(s.getDataPtr()), s.getLength(), rawTxn);
|
theApp->getTxnDB()->getDB()->escape(static_cast<const unsigned char *>(s.getDataPtr()), s.getLength(), rawTxn);
|
||||||
sql.append(rawTxn);
|
sql.append(rawTxn);
|
||||||
sql.append(");");
|
sql.append(");");
|
||||||
|
|
||||||
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
||||||
Database* db = theApp->getTxnDB()->getDB();
|
Database* db = theApp->getTxnDB()->getDB();
|
||||||
return db->executeSQL(sql.c_str());
|
return db->executeSQL(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
||||||
@@ -237,12 +247,11 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
|||||||
std::string status;
|
std::string status;
|
||||||
|
|
||||||
rawTxn.reserve(2048);
|
rawTxn.reserve(2048);
|
||||||
if(1)
|
|
||||||
{
|
{
|
||||||
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
ScopedLock sl(theApp->getTxnDB()->getDBLock());
|
||||||
Database* db = theApp->getTxnDB()->getDB();
|
Database* db = theApp->getTxnDB()->getDB();
|
||||||
|
|
||||||
if (!db->executeSQL(sql.c_str(), true) || !db->startIterRows() || !db->getNextRow())
|
if (!db->executeSQL(sql, true) || !db->startIterRows())
|
||||||
return Transaction::pointer();
|
return Transaction::pointer();
|
||||||
|
|
||||||
db->getStr("Status", status);
|
db->getStr("Status", status);
|
||||||
@@ -258,7 +267,7 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
|
|||||||
Transaction::pointer tr = boost::make_shared<Transaction>(txn, true);
|
Transaction::pointer tr = boost::make_shared<Transaction>(txn, true);
|
||||||
|
|
||||||
TransStatus st(INVALID);
|
TransStatus st(INVALID);
|
||||||
switch(status[0])
|
switch (status[0])
|
||||||
{
|
{
|
||||||
case 'N': st = NEW; break;
|
case 'N': st = NEW; break;
|
||||||
case 'A': st = INCLUDED; break;
|
case 'A': st = INCLUDED; break;
|
||||||
@@ -340,7 +349,7 @@ static bool isHex(char j)
|
|||||||
if ((j >= 'a') && (j <= 'f')) return true;
|
if ((j >= 'a') && (j <= 'f')) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Transaction::isHexTxID(const std::string& txid)
|
bool Transaction::isHexTxID(const std::string& txid)
|
||||||
{
|
{
|
||||||
if (txid.size() != 64) return false;
|
if (txid.size() != 64) return false;
|
||||||
@@ -382,3 +391,4 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -6,21 +6,63 @@
|
|||||||
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
|
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
|
||||||
TransactionEngineParams params)
|
TransactionEngineParams params)
|
||||||
{
|
{
|
||||||
|
TransactionEngineResult result = terSUCCESS;
|
||||||
|
|
||||||
uint256 txID = txn.getTransactionID();
|
uint256 txID = txn.getTransactionID();
|
||||||
if(!txID) return terINVALID;
|
if(!txID) return terINVALID;
|
||||||
|
|
||||||
// extract signing key
|
// Extract signing key
|
||||||
|
// Transactions contain a signing key. This allows us to trivially verify a transaction has at least been properly signed
|
||||||
|
// without going to disk. Each transaction also notes a source account id. This is used to verify that the signing key is
|
||||||
|
// associated with the account.
|
||||||
CKey acctKey;
|
CKey acctKey;
|
||||||
if (!acctKey.SetPubKey(txn.peekSigningPubKey())) return terINVALID;
|
if (!acctKey.SetPubKey(txn.peekSigningPubKey())) return terINVALID;
|
||||||
|
|
||||||
// check signature
|
// check signature
|
||||||
if (!txn.checkSign(acctKey)) return terINVALID;
|
if (!txn.checkSign(acctKey)) return terINVALID;
|
||||||
|
|
||||||
|
bool bPrepaid = false;
|
||||||
|
|
||||||
|
// Customize behavoir based on transaction type.
|
||||||
|
switch(txn.getTxnType())
|
||||||
|
{
|
||||||
|
case ttCLAIM:
|
||||||
|
bPrepaid = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ttMAKE_PAYMENT:
|
||||||
|
case ttINVOICE:
|
||||||
|
case ttEXCHANGE_OFFER:
|
||||||
|
result = terSUCCESS;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ttINVALID:
|
||||||
|
result = terINVALID;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
result = terUNKNOWN;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (terSUCCESS != result)
|
||||||
|
return result;
|
||||||
|
|
||||||
uint64 txnFee = txn.getTransactionFee();
|
uint64 txnFee = txn.getTransactionFee();
|
||||||
if ( (params & tepNO_CHECK_FEE) != tepNONE)
|
if ( (params & tepNO_CHECK_FEE) != tepNONE)
|
||||||
{
|
{
|
||||||
// WRITEME: Check if fee is adequate
|
if (bPrepaid)
|
||||||
if (txnFee == 0) return terINSUF_FEE_P;
|
{
|
||||||
|
if (txnFee)
|
||||||
|
// Transaction is malformed.
|
||||||
|
return terINSUF_FEE_P;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// WRITEME: Check if fee is adequate
|
||||||
|
if (txnFee == 0)
|
||||||
|
return terINSUF_FEE_P;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get source account ID
|
// get source account ID
|
||||||
@@ -30,39 +72,59 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
boost::recursive_mutex::scoped_lock sl(mLedger->mLock);
|
boost::recursive_mutex::scoped_lock sl(mLedger->mLock);
|
||||||
|
|
||||||
// find source account
|
// find source account
|
||||||
|
// If we are only verifying some transactions, this would be probablistic.
|
||||||
LedgerStateParms qry = lepNONE;
|
LedgerStateParms qry = lepNONE;
|
||||||
SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount);
|
SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount);
|
||||||
if (!src) return terNO_ACCOUNT;
|
if (!src) return terNO_ACCOUNT;
|
||||||
|
|
||||||
// deduct the fee, so it's not available during the transaction
|
// deduct the fee, so it's not available during the transaction
|
||||||
// we only write the account back if the transaction succeeds
|
// we only write the account back if the transaction succeeds
|
||||||
uint64 balance = src->getIFieldU64(sfBalance);
|
if (txnFee)
|
||||||
if (balance < txnFee)
|
|
||||||
return terINSUF_FEE_B;
|
|
||||||
src->setIFieldU64(sfBalance, balance - txnFee);
|
|
||||||
|
|
||||||
// validate sequence
|
|
||||||
uint32 t_seq = txn.getSequence();
|
|
||||||
uint32 a_seq = src->getIFieldU32(sfSequence);
|
|
||||||
if (t_seq != a_seq)
|
|
||||||
{
|
{
|
||||||
// WRITEME: Special case code for changing transaction key
|
uint64 balance = src->getIFieldU64(sfBalance);
|
||||||
if (a_seq < t_seq) return terPRE_SEQ;
|
|
||||||
if (mLedger->hasTransaction(txID))
|
if (balance < txnFee)
|
||||||
return terALREADY;
|
return terINSUF_FEE_B;
|
||||||
return terPAST_SEQ;
|
|
||||||
|
src->setIFieldU64(sfBalance, balance - txnFee);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate sequence
|
||||||
|
uint32 t_seq = txn.getSequence();
|
||||||
|
|
||||||
|
if (bPrepaid)
|
||||||
|
{
|
||||||
|
if (t_seq)
|
||||||
|
return terPAST_SEQ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 a_seq = src->getIFieldU32(sfSequence);
|
||||||
|
|
||||||
|
if (t_seq != a_seq)
|
||||||
|
{
|
||||||
|
// WRITEME: Special case code for changing transaction key
|
||||||
|
if (a_seq < t_seq) return terPRE_SEQ;
|
||||||
|
if (mLedger->hasTransaction(txID))
|
||||||
|
return terALREADY;
|
||||||
|
return terPAST_SEQ;
|
||||||
|
}
|
||||||
|
else src->setIFieldU32(sfSequence, t_seq);
|
||||||
}
|
}
|
||||||
else src->setIFieldU32(sfSequence, t_seq);
|
|
||||||
|
|
||||||
std::vector<AffectedAccount> accounts;
|
std::vector<AffectedAccount> accounts;
|
||||||
accounts.push_back(std::make_pair(taaMODIFY, src));
|
accounts.push_back(std::make_pair(taaMODIFY, src));
|
||||||
TransactionEngineResult result = terUNKNOWN;
|
|
||||||
switch(txn.getTxnType())
|
switch(txn.getTxnType())
|
||||||
{
|
{
|
||||||
case ttINVALID:
|
case ttINVALID:
|
||||||
result = terINVALID;
|
result = terINVALID;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case ttCLAIM:
|
||||||
|
result = doClaim(txn, accounts);
|
||||||
|
break;
|
||||||
|
|
||||||
case ttMAKE_PAYMENT:
|
case ttMAKE_PAYMENT:
|
||||||
result = doPayment(txn, accounts);
|
result = doPayment(txn, accounts);
|
||||||
break;
|
break;
|
||||||
@@ -85,8 +147,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
// WRITEME: Special case code for changing transaction key
|
// WRITEME: Special case code for changing transaction key
|
||||||
for(std::vector<AffectedAccount>::iterator it=accounts.begin(), end=accounts.end();
|
for(std::vector<AffectedAccount>::iterator it=accounts.begin(), end=accounts.end();
|
||||||
it != end; ++it)
|
it != end; ++it)
|
||||||
{
|
{ if (it->first == taaCREATE)
|
||||||
if ( (it->first==taaMODIFY) || (it->first==taaCREATE) )
|
{
|
||||||
|
if (mLedger->writeBack(lepCREATE, it->second) & lepERROR)
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
else if (it->first==taaMODIFY)
|
||||||
{
|
{
|
||||||
if(mLedger->writeBack(lepNONE, it->second) & lepERROR)
|
if(mLedger->writeBack(lepNONE, it->second) & lepERROR)
|
||||||
assert(false);
|
assert(false);
|
||||||
@@ -106,6 +172,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn,
|
||||||
|
std::vector<AffectedAccount>& accounts)
|
||||||
|
{
|
||||||
|
return terUNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
|
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
|
||||||
std::vector<AffectedAccount>& accounts)
|
std::vector<AffectedAccount>& accounts)
|
||||||
{
|
{
|
||||||
@@ -187,3 +259,4 @@ TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction&
|
|||||||
{
|
{
|
||||||
return terUNKNOWN;
|
return terUNKNOWN;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ enum TransactionEngineResult
|
|||||||
terUNFUNDED, // Source account had insufficient balance for transactin
|
terUNFUNDED, // Source account had insufficient balance for transactin
|
||||||
terNO_PATH, // No path existed or met transaction/balance requirements
|
terNO_PATH, // No path existed or met transaction/balance requirements
|
||||||
terPAST_SEQ, // This sequence number has already past
|
terPAST_SEQ, // This sequence number has already past
|
||||||
|
terBAD_SEQ, // This sequence number should be zero for prepaid transactions.
|
||||||
terPRE_SEQ, // Missing/inapplicable prior transaction
|
terPRE_SEQ, // Missing/inapplicable prior transaction
|
||||||
terPAST_LEDGER, // The transaction expired and can't be applied
|
terPAST_LEDGER, // The transaction expired and can't be applied
|
||||||
};
|
};
|
||||||
@@ -51,13 +52,14 @@ class TransactionEngine
|
|||||||
protected:
|
protected:
|
||||||
Ledger::pointer mLedger;
|
Ledger::pointer mLedger;
|
||||||
|
|
||||||
TransactionEngineResult doPayment(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doCancel(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
|
TransactionEngineResult doClaim(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
|
TransactionEngineResult doDelete(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doInvoice(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
TransactionEngineResult doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doPayment(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
TransactionEngineResult doCancel(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
|
||||||
TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doStore(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
TransactionEngineResult doDelete(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionEngine() { ; }
|
TransactionEngine() { ; }
|
||||||
@@ -80,3 +82,4 @@ inline TransactionEngineParams operator&(const TransactionEngineParams& l1, cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -13,7 +13,14 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 2 },
|
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 2 },
|
||||||
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 4 },
|
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 4 },
|
||||||
{ S_FIELD(InvoiceID), STI_HASH256, SOE_IFFLAG, 8 },
|
{ S_FIELD(InvoiceID), STI_HASH256, SOE_IFFLAG, 8 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
|
},
|
||||||
|
{ "Claim", ttCLAIM, {
|
||||||
|
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
|
||||||
|
{ S_FIELD(GeneratorID), STI_AMOUNT, SOE_REQUIRED, 0 },
|
||||||
|
{ S_FIELD(Generator), STI_VL, SOE_REQUIRED, 0 },
|
||||||
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ "Invoice", ttINVOICE, {
|
{ "Invoice", ttINVOICE, {
|
||||||
@@ -25,7 +32,7 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 4 },
|
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 4 },
|
||||||
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 8 },
|
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 8 },
|
||||||
{ S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 16 },
|
{ S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 16 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ "Offer", ttEXCHANGE_OFFER, {
|
{ "Offer", ttEXCHANGE_OFFER, {
|
||||||
@@ -39,7 +46,7 @@ TransactionFormat InnerTxnFormats[]=
|
|||||||
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 32 },
|
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 32 },
|
||||||
{ S_FIELD(ExpireLedger), STI_UINT32, SOE_IFFLAG, 64 },
|
{ S_FIELD(ExpireLedger), STI_UINT32, SOE_IFFLAG, 64 },
|
||||||
{ S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 128 },
|
{ S_FIELD(Identifier), STI_VL, SOE_IFFLAG, 128 },
|
||||||
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
|
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x02000000 },
|
||||||
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
|
||||||
},
|
},
|
||||||
{ NULL, ttINVALID }
|
{ NULL, ttINVALID }
|
||||||
@@ -55,3 +62,4 @@ TransactionFormat* getTxnFormat(TransactionType t)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
|
|
||||||
enum TransactionType
|
enum TransactionType
|
||||||
{
|
{
|
||||||
ttINVALID=-1,
|
ttINVALID = -1,
|
||||||
ttMAKE_PAYMENT=0,
|
ttMAKE_PAYMENT = 0,
|
||||||
ttINVOICE=1,
|
ttCLAIM = 1,
|
||||||
ttEXCHANGE_OFFER=2
|
ttINVOICE = 2,
|
||||||
|
ttEXCHANGE_OFFER = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TransactionFormat
|
struct TransactionFormat
|
||||||
@@ -18,10 +19,14 @@ struct TransactionFormat
|
|||||||
SOElement elements[16];
|
SOElement elements[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
const int32 TransactionMagic=0x54584E00;
|
const int32 TransactionMagic = 0x54584E00; // 'TXN'
|
||||||
|
|
||||||
const int TransactionIVersion=0, TransactionISigningPubKey=1, TransactionISequence=2;
|
const int TransactionIVersion = 0;
|
||||||
const int TransactionIType=3, TransactionIFee=4;
|
const int TransactionISigningPubKey = 1;
|
||||||
|
const int TransactionISourceID = 2;
|
||||||
|
const int TransactionISequence = 3;
|
||||||
|
const int TransactionIType = 4;
|
||||||
|
const int TransactionIFee = 5;
|
||||||
|
|
||||||
const int TransactionMinLen=32;
|
const int TransactionMinLen=32;
|
||||||
const int TransactionMaxLen=1048576;
|
const int TransactionMaxLen=1048576;
|
||||||
@@ -29,3 +34,4 @@ const int TransactionMaxLen=1048576;
|
|||||||
extern TransactionFormat InnerTxnFormats[];
|
extern TransactionFormat InnerTxnFormats[];
|
||||||
extern TransactionFormat* getTxnFormat(TransactionType t);
|
extern TransactionFormat* getTxnFormat(TransactionType t);
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -38,3 +38,4 @@ bool TransactionMaster::canonicalize(Transaction::pointer& txn, bool may_be_new)
|
|||||||
theApp->getIOService().post(boost::bind(&Transaction::saveTransaction, txn));
|
theApp->getIOService().post(boost::bind(&Transaction::saveTransaction, txn));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -22,3 +22,4 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ void ValidationCollection::addToDB(newcoin::Validation& valid,int weCare)
|
|||||||
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
|
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
|
||||||
db->escape(sig.begin(),sig.GetSerializeSize(),sigStr);
|
db->escape(sig.begin(),sig.GetSerializeSize(),sigStr);
|
||||||
string sql=strprintf("INSERT INTO Validations (LedgerIndex,Hash,Hanko,SeqNum,Sig,WeCare) values (%d,%s,%s,%d,%s,%d)",valid.ledgerindex(),hashStr.c_str(),hankoStr.c_str(),valid.seqnum(),sigStr.c_str(),weCare);
|
string sql=strprintf("INSERT INTO Validations (LedgerIndex,Hash,Hanko,SeqNum,Sig,WeCare) values (%d,%s,%s,%d,%s,%d)",valid.ledgerindex(),hashStr.c_str(),hankoStr.c_str(),valid.seqnum(),sigStr.c_str(),weCare);
|
||||||
db->executeSQL(sql.c_str());
|
db->executeSQL(sql);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,24 +50,18 @@ bool ValidationCollection::hasValidation(uint32 ledgerIndex,uint160& hanko,uint3
|
|||||||
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
|
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
|
||||||
string sql=strprintf("SELECT ValidationID,seqnum from Validations where LedgerIndex=%d and hanko=%s",
|
string sql=strprintf("SELECT ValidationID,seqnum from Validations where LedgerIndex=%d and hanko=%s",
|
||||||
ledgerIndex,hankoStr.c_str());
|
ledgerIndex,hankoStr.c_str());
|
||||||
if(db->executeSQL(sql.c_str()))
|
if(db->executeSQL(sql) && db->startIterRows())
|
||||||
{
|
{
|
||||||
if(db->startIterRows())
|
uint32 currentSeqNum=db->getInt(1);
|
||||||
|
if(currentSeqNum>=seqnum)
|
||||||
{
|
{
|
||||||
if(db->getNextRow())
|
db->endIterRows();
|
||||||
{
|
return(true);
|
||||||
uint32 currentSeqNum=db->getInt(1);
|
|
||||||
if(currentSeqNum>=seqnum)
|
|
||||||
{
|
|
||||||
db->endIterRows();
|
|
||||||
return(true);
|
|
||||||
}
|
|
||||||
// delete the old validation we were storing
|
|
||||||
sql=strprintf("DELETE FROM Validations where ValidationID=%d",db->getInt(0));
|
|
||||||
db->endIterRows();
|
|
||||||
db->executeSQL(sql.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// delete the old validation we were storing
|
||||||
|
sql=strprintf("DELETE FROM Validations where ValidationID=%d",db->getInt(0));
|
||||||
|
db->endIterRows();
|
||||||
|
db->executeSQL(sql);
|
||||||
}
|
}
|
||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
@@ -191,7 +185,6 @@ void ValidationCollection::getValidations(uint32 ledgerIndex,vector<newcoin::Val
|
|||||||
string sql=strprintf("SELECT * From Validations where LedgerIndex=%d and wecare=1",ledgerIndex);
|
string sql=strprintf("SELECT * From Validations where LedgerIndex=%d and wecare=1",ledgerIndex);
|
||||||
|
|
||||||
// TODO: ValidationCollection::getValidations(uint32 ledgerIndex)
|
// TODO: ValidationCollection::getValidations(uint32 ledgerIndex)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -203,7 +196,6 @@ bool ValidationCollection::getConsensusLedger(uint32 ledgerIndex, uint256& ourHa
|
|||||||
bool ret=false;
|
bool ret=false;
|
||||||
if(mIndexGroups.count(ledgerIndex))
|
if(mIndexGroups.count(ledgerIndex))
|
||||||
{
|
{
|
||||||
|
|
||||||
unsigned int maxVotes=theConfig.MIN_VOTES_FOR_CONSENSUS;
|
unsigned int maxVotes=theConfig.MIN_VOTES_FOR_CONSENSUS;
|
||||||
vector< Group >& groups=mIndexGroups[ledgerIndex];
|
vector< Group >& groups=mIndexGroups[ledgerIndex];
|
||||||
Group empty;
|
Group empty;
|
||||||
@@ -228,6 +220,7 @@ bool ValidationCollection::getConsensusLedger(uint32 ledgerIndex, uint256& ourHa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
// vim:ts=4
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
LocalAccount::LocalAccount(boost::shared_ptr<LocalAccountFamily> family, int familySeq) :
|
LocalAccount::LocalAccount(boost::shared_ptr<LocalAccountFamily> family, int familySeq) :
|
||||||
mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq)
|
mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq)
|
||||||
{
|
{
|
||||||
mAcctID.setAccountPublic(mPublicKey->GetPubKey());
|
mAccount.setAccountPublic(mPublicKey->GetPubKey());
|
||||||
if(theApp!=NULL) mPublicKey = theApp->getPubKeyCache().store(mAcctID, mPublicKey);
|
if (theApp != NULL) mPublicKey = theApp->getPubKeyCache().store(mAccount, mPublicKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LocalAccount::getFullName() const
|
std::string LocalAccount::getFullName() const
|
||||||
@@ -52,7 +52,7 @@ std::string LocalAccount::getFamilyName() const
|
|||||||
|
|
||||||
AccountState::pointer LocalAccount::getAccountState() const
|
AccountState::pointer LocalAccount::getAccountState() const
|
||||||
{
|
{
|
||||||
return theApp->getOPs().getAccountState(mAcctID);
|
return theApp->getOPs().getAccountState(mAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 LocalAccount::getEffectiveBalance() const
|
uint64 LocalAccount::getEffectiveBalance() const
|
||||||
@@ -73,12 +73,13 @@ Json::Value LocalAccount::getJson() const
|
|||||||
ret["IsLocked"] = mFamily->isLocked();
|
ret["IsLocked"] = mFamily->isLocked();
|
||||||
|
|
||||||
AccountState::pointer as = getAccountState();
|
AccountState::pointer as = getAccountState();
|
||||||
if (!as) ret["Account"] = "None";
|
if (!as) ret["State"] = "None";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert(as->getAccountID().getAccountID() == mAccount.getAccountID());
|
||||||
Json::Value acct(Json::objectValue);
|
Json::Value acct(Json::objectValue);
|
||||||
as->addJson(acct);
|
as->addJson(acct);
|
||||||
ret["Account"] = acct;
|
ret["State"] = acct;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -190,7 +191,7 @@ LocalAccountFamily::pointer LocalAccountFamily::readFamily(const NewcoinAddress&
|
|||||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||||
Database *db=theApp->getWalletDB()->getDB();
|
Database *db=theApp->getWalletDB()->getDB();
|
||||||
|
|
||||||
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
|
if(!db->executeSQL(sql) || !db->startIterRows())
|
||||||
return LocalAccountFamily::pointer();
|
return LocalAccountFamily::pointer();
|
||||||
|
|
||||||
db->getStr("Comment", comment);
|
db->getStr("Comment", comment);
|
||||||
@@ -223,7 +224,7 @@ void LocalAccountFamily::write(bool is_new)
|
|||||||
sql.append(");");
|
sql.append(");");
|
||||||
|
|
||||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||||
theApp->getWalletDB()->getDB()->executeSQL(sql.c_str());
|
theApp->getWalletDB()->getDB()->executeSQL(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LocalAccountFamily::getSQLFields()
|
std::string LocalAccountFamily::getSQLFields()
|
||||||
@@ -446,7 +447,7 @@ void Wallet::load()
|
|||||||
|
|
||||||
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
ScopedLock sl(theApp->getWalletDB()->getDBLock());
|
||||||
Database *db=theApp->getWalletDB()->getDB();
|
Database *db=theApp->getWalletDB()->getDB();
|
||||||
if(!db->executeSQL(sql.c_str()))
|
if(!db->executeSQL(sql))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::cerr << "Unable to load wallet" << std::endl;
|
std::cerr << "Unable to load wallet" << std::endl;
|
||||||
@@ -456,8 +457,7 @@ void Wallet::load()
|
|||||||
|
|
||||||
if(!db->startIterRows()) return;
|
if(!db->startIterRows()) return;
|
||||||
|
|
||||||
while(db->getNextRow())
|
do {
|
||||||
{
|
|
||||||
std::string strGenerator, strComment;
|
std::string strGenerator, strComment;
|
||||||
|
|
||||||
db->getStr("FamilyGenerator", strGenerator);
|
db->getStr("FamilyGenerator", strGenerator);
|
||||||
@@ -476,7 +476,8 @@ void Wallet::load()
|
|||||||
f->setComment(strComment);
|
f->setComment(strComment);
|
||||||
}
|
}
|
||||||
else assert(false);
|
else assert(false);
|
||||||
}
|
} while(db->getNextRow());
|
||||||
|
|
||||||
db->endIterRows();
|
db->endIterRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -484,17 +485,17 @@ void Wallet::load()
|
|||||||
LocalAccount::pointer Wallet::getNewLocalAccount(const NewcoinAddress& family)
|
LocalAccount::pointer Wallet::getNewLocalAccount(const NewcoinAddress& family)
|
||||||
{
|
{
|
||||||
boost::recursive_mutex::scoped_lock sl(mLock);
|
boost::recursive_mutex::scoped_lock sl(mLock);
|
||||||
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit=mFamilies.find(family);
|
std::map<NewcoinAddress, LocalAccountFamily::pointer>::iterator fit = mFamilies.find(family);
|
||||||
if(fit==mFamilies.end()) return LocalAccount::pointer();
|
if (fit == mFamilies.end()) return LocalAccount::pointer();
|
||||||
|
|
||||||
uint32 seq=fit->second->getSeq();
|
uint32 seq = fit->second->getSeq();
|
||||||
NewcoinAddress acct=fit->second->getAccount(seq, true);
|
NewcoinAddress acct = fit->second->getAccount(seq, true);
|
||||||
fit->second->setSeq(seq+1); // FIXME: writeout new seq
|
fit->second->setSeq(seq + 1); // FIXME: writeout new seq
|
||||||
|
|
||||||
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait=mAccounts.find(acct);
|
std::map<NewcoinAddress, LocalAccount::pointer>::iterator ait = mAccounts.find(acct);
|
||||||
if(ait!=mAccounts.end()) return ait->second;
|
if (ait != mAccounts.end()) return ait->second;
|
||||||
|
|
||||||
LocalAccount::pointer lac=boost::make_shared<LocalAccount>(fit->second, seq);
|
LocalAccount::pointer lac = boost::make_shared<LocalAccount>(fit->second, seq);
|
||||||
mAccounts.insert(std::make_pair(acct, lac));
|
mAccounts.insert(std::make_pair(acct, lac));
|
||||||
|
|
||||||
sl.unlock();
|
sl.unlock();
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ protected:
|
|||||||
|
|
||||||
NewcoinAddress mNodePublicKey;
|
NewcoinAddress mNodePublicKey;
|
||||||
NewcoinAddress mNodePrivateKey;
|
NewcoinAddress mNodePrivateKey;
|
||||||
DH* mDh512;
|
DH* mDh512;
|
||||||
DH* mDh1024;
|
DH* mDh1024;
|
||||||
|
|
||||||
std::map<NewcoinAddress, LocalAccountFamily::pointer> mFamilies;
|
std::map<NewcoinAddress, LocalAccountFamily::pointer> mFamilies;
|
||||||
std::map<NewcoinAddress, LocalAccount::pointer> mAccounts;
|
std::map<NewcoinAddress, LocalAccount::pointer> mAccounts;
|
||||||
@@ -53,8 +53,8 @@ public:
|
|||||||
// - Maintain peer connectivity through validation and peer management.
|
// - Maintain peer connectivity through validation and peer management.
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
NewcoinAddress& getNodePublic() { return mNodePublicKey; }
|
const NewcoinAddress& getNodePublic() const { return mNodePublicKey; }
|
||||||
NewcoinAddress& getNodePrivate() { return mNodePrivateKey; }
|
const NewcoinAddress& getNodePrivate() const { return mNodePrivateKey; }
|
||||||
DH* getDh512() { return DHparams_dup(mDh512); }
|
DH* getDh512() { return DHparams_dup(mDh512); }
|
||||||
DH* getDh1024() { return DHparams_dup(mDh1024); }
|
DH* getDh1024() { return DHparams_dup(mDh1024); }
|
||||||
|
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
|
bool operator==(const CBase58Data& b58) const { return CompareTo(b58) == 0; }
|
||||||
|
bool operator!=(const CBase58Data& b58) const { return CompareTo(b58) != 0; }
|
||||||
bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
|
bool operator<=(const CBase58Data& b58) const { return CompareTo(b58) <= 0; }
|
||||||
bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
|
bool operator>=(const CBase58Data& b58) const { return CompareTo(b58) >= 0; }
|
||||||
bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
|
bool operator< (const CBase58Data& b58) const { return CompareTo(b58) < 0; }
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ enum MessageType {
|
|||||||
mtGET_CONTACTS= 10;
|
mtGET_CONTACTS= 10;
|
||||||
mtCONTACT= 11;
|
mtCONTACT= 11;
|
||||||
|
|
||||||
|
|
||||||
// operations for 'small' nodes
|
// operations for 'small' nodes
|
||||||
mtSEARCH_TRANSACTION= 20;
|
mtSEARCH_TRANSACTION= 20;
|
||||||
mtGET_ACCOUNT= 21;
|
mtGET_ACCOUNT= 21;
|
||||||
@@ -22,6 +21,7 @@ enum MessageType {
|
|||||||
mtLEDGER= 32;
|
mtLEDGER= 32;
|
||||||
mtPROPOSE_LEDGER= 33;
|
mtPROPOSE_LEDGER= 33;
|
||||||
mtCLOSE_LEDGER= 35;
|
mtCLOSE_LEDGER= 35;
|
||||||
|
mtSTATUS_CHANGE= 36;
|
||||||
|
|
||||||
// data replication and synchronization
|
// data replication and synchronization
|
||||||
mtGET_VALIDATIONS= 40;
|
mtGET_VALIDATIONS= 40;
|
||||||
@@ -41,7 +41,8 @@ message TMHello {
|
|||||||
optional bytes nodePublic = 4; // node may opt to remain anonymous
|
optional bytes nodePublic = 4; // node may opt to remain anonymous
|
||||||
optional bytes nodeProof = 5;
|
optional bytes nodeProof = 5;
|
||||||
optional uint32 ipv4Port = 6;
|
optional uint32 ipv4Port = 6;
|
||||||
optional bytes closedLedger = 7;
|
optional bytes closedLedger = 7; // our last closed ledger
|
||||||
|
optional bytes previousLedger = 8; // the ledger before the last closed ledger
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -71,6 +72,33 @@ message TMTransaction {
|
|||||||
optional bytes conflictingTransaction = 13;
|
optional bytes conflictingTransaction = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
enum NodeStatus {
|
||||||
|
nsCONNECTING = 1; // acquiring connections
|
||||||
|
nsCONNECTED = 2; // convinced we are connected to the real network
|
||||||
|
nsMONITORING = 3; // we know what the previous ledger is
|
||||||
|
nsVALIDATING = 4; // we have the full ledger contents
|
||||||
|
}
|
||||||
|
|
||||||
|
enum NodeEvent {
|
||||||
|
neCLOSED_LEDGER = 1; // closing a ledger because its close time has come
|
||||||
|
neACCEPTED_LEDGER = 2; // accepting a closed ledger, we have finished computing it
|
||||||
|
neSWITCHED_LEDGER = 3; // switching ledgers due to network consensus
|
||||||
|
neSHUTTING_DOWN = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message TMStatusChange {
|
||||||
|
optional NodeStatus newStatus = 1;
|
||||||
|
optional NodeEvent newEvent = 2;
|
||||||
|
optional uint32 ledgerSeq = 3;
|
||||||
|
optional bytes ledgerHash = 4;
|
||||||
|
optional bytes previousLedgerHash = 5;
|
||||||
|
optional uint64 networkTime = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
message TMProposeLedger {
|
message TMProposeLedger {
|
||||||
required uint32 closingSeq = 1;
|
required uint32 closingSeq = 1;
|
||||||
required uint32 secondsSinceClose = 2;
|
required uint32 secondsSinceClose = 2;
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ void DH_der_gen_hex(std::string& strDer, int iKeyLength)
|
|||||||
|
|
||||||
DH_der_gen(strBuf, iKeyLength);
|
DH_der_gen(strBuf, iKeyLength);
|
||||||
|
|
||||||
strHex(strDer, strBuf);
|
strDer = strHex(strBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
DH* DH_der_load(const std::string& strDer)
|
DH* DH_der_load(const std::string& strDer)
|
||||||
|
|||||||
14
src/utils.h
14
src/utils.h
@@ -36,8 +36,10 @@ std::string strJoin(Iterator first, Iterator last, std::string strSeperator)
|
|||||||
char charHex(int iDigit);
|
char charHex(int iDigit);
|
||||||
|
|
||||||
template<class Iterator>
|
template<class Iterator>
|
||||||
void strHex(std::string& strDst, Iterator first, int iSize)
|
std::string strHex(Iterator first, int iSize)
|
||||||
{
|
{
|
||||||
|
std::string strDst;
|
||||||
|
|
||||||
strDst.resize(iSize*2);
|
strDst.resize(iSize*2);
|
||||||
|
|
||||||
for (int i = 0; i < iSize; i++) {
|
for (int i = 0; i < iSize; i++) {
|
||||||
@@ -46,14 +48,16 @@ void strHex(std::string& strDst, Iterator first, int iSize)
|
|||||||
strDst[i*2] = charHex(c >> 4);
|
strDst[i*2] = charHex(c >> 4);
|
||||||
strDst[i*2+1] = charHex(c & 15);
|
strDst[i*2+1] = charHex(c & 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return strDst;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void strHex(std::string& strDst, const std::string& strSrc) {
|
inline const std::string strHex(const std::string& strSrc) {
|
||||||
strHex(strDst, strSrc.begin(), strSrc.size());
|
return strHex(strSrc.begin(), strSrc.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void strHex(std::string& strDst, const std::vector<unsigned char> vchData) {
|
inline std::string strHex(const std::vector<unsigned char> vchData) {
|
||||||
strHex(strDst, vchData.begin(), vchData.size());
|
return strHex(vchData.begin(), vchData.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
int charUnHex(char cDigit);
|
int charUnHex(char cDigit);
|
||||||
|
|||||||
Reference in New Issue
Block a user