Merge NewcoinAddress.

This commit is contained in:
Arthur Britto
2012-05-12 16:51:01 -07:00
66 changed files with 1750 additions and 906 deletions

View File

@@ -100,21 +100,25 @@ bool Database::getColNumber(const char* colName,int* retIndex)
return(false);
}
#if 0
int Database::getSingleDBValueInt(const char* sql)
{
int ret;
if( executeSQL(sql) && startIterRows() && getNextRow())
if( executeSQL(sql) && startIterRows()
{
ret=getInt(0);
endIterRows();
}else
}
else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}
#endif
#if 0
float Database::getSingleDBValueFloat(const char* sql)
{
float ret;
@@ -122,28 +126,33 @@ float Database::getSingleDBValueFloat(const char* sql)
{
ret=getFloat(0);
endIterRows();
}else
}
else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}
#endif
#if 0
char* Database::getSingleDBValueStr(const char* sql,std::string& retStr)
{
char* ret;
if( executeSQL(sql) && startIterRows() && getNextRow())
if(executeSQL(sql) && startIterRows())
{
ret=getStr(0,retStr);
endIterRows();
}else
}
else
{
//theUI->statusMsg("ERROR with database: %s",sql);
ret=0;
}
return(ret);
}
#endif
std::string Database::escape(const std::string strValue)
{

View File

@@ -69,10 +69,9 @@ public:
virtual int getBinary(int colIndex,unsigned char* buf,int maxSize)=0;
virtual uint64 getBigInt(int colIndex)=0;
int getSingleDBValueInt(const char* sql);
float getSingleDBValueFloat(const char* sql);
char* getSingleDBValueStr(const char* sql, std::string& retStr);
// int getSingleDBValueInt(const char* sql);
// float getSingleDBValueFloat(const char* sql);
// char* getSingleDBValueStr(const char* sql, std::string& retStr);
};

View File

@@ -21,7 +21,9 @@ public:
private:
NewcoinAddress mAccountID;
NewcoinAddress mAuthorizedKey;
SerializedLedgerEntry::pointer mLedgerEntry;
bool mValid;
public:

View File

@@ -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());
mDatabase=new SqliteDatabase(path.c_str());
mDatabase->connect();
for(int i=0; i<initCount; i++)
for(int i = 0; i < initCount; ++i)
mDatabase->executeSQL(initStrings[i], true);
}
@@ -41,11 +41,9 @@ DatabaseCon::~DatabaseCon()
delete mDatabase;
}
Application::Application() :
mUNL(mIOService),
Application::Application() : mNetOps(mIOService), mUNL(mIOService),
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mConnectionPool(mIOService),
mPeerDoor(NULL), mRPCDoor(NULL)
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
{
nothing();
}
@@ -82,43 +80,96 @@ void Application::run()
//
// Allow peer connections.
//
if(theConfig.PEER_PORT)
if(!theConfig.PEER_IP.empty() && theConfig.PEER_PORT)
{
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.
//
if(theConfig.RPC_PORT)
if(!theConfig.RPC_IP.empty() && theConfig.RPC_PORT)
{
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();
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
NewcoinAddress rootFamilySeed; // Hold the 128 password.
NewcoinAddress rootFamilyGenerator; // Hold the generator.
NewcoinAddress rootAddress;
// NewcoinAddress rootAddress;
rootFamilySeed.setFamilySeed(CKey::PassPhraseToKey("This is my payphrase."));
rootFamilyGenerator.setFamilyGenerator(rootFamilySeed);
rootAddress.setAccountPublic(rootFamilyGenerator, 0);
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));
firstLedger->updateHash();
firstLedger->setClosed();
firstLedger->setAccepted();
mMasterLedger.pushLedger(firstLedger);
Ledger::pointer secondLedger = firstLedger->closeLedger(time(NULL));
Ledger::pointer secondLedger = boost::make_shared<Ledger>(firstLedger);
mMasterLedger.pushLedger(secondLedger);
assert(!!secondLedger->getAccountState(rootAddress));
mMasterLedger.setSynced();
@@ -126,6 +177,7 @@ void Application::run()
mWallet.load();
// mWallet.syncToLedger(true, &(*secondLedger));
mNetOps.setStateTimer(5);
// temporary
mIOService.run(); // This blocks

View File

@@ -3,7 +3,6 @@
#include "UniqueNodeList.h"
#include "ConnectionPool.h"
#include "TimingService.h"
#include "PubKeyCache.h"
#include "ScopedLock.h"
#include "LedgerMaster.h"
@@ -34,12 +33,10 @@ public:
class Application
{
NetworkOPs mNetOps;
Wallet mWallet;
boost::asio::io_service mIOService;
TimingService mTimingService;
NetworkOPs mNetOps;
Wallet mWallet;
UniqueNodeList mUNL;
PubKeyCache mPKCache;
LedgerMaster mMasterLedger;

View File

@@ -1,31 +1,15 @@
#ifndef __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)
const int BLgSize=192;
const int BLgSize=190;
const int BLgPIndex=0, BLgLIndex=4; // ledger index
const int BLgPTotCoins=4, BLgLTotCoins=8; // total native coins
const int BLgPPrevLg=12, BLgLPrevLg=32; // previous ledger hash
const int BLgPTxT=44, BLgLTxT=32; // transaction tree hash
const int BLgPAcT=76, BLgLPAct=32; // account state hash
const int BLgPClTs=108, BLgLClTs=8; // closing timestamp
const int BLgPConf=116, BLgLPConf=4; // confidence
const int BLgPSig=120, 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
const int BLgPNlIn=116, BLgLNlIn=2;
const int BLgPSig=118, BLgLSig=72; // signature
#endif

View File

@@ -52,7 +52,7 @@ int commandLineRPC(const std::vector<std::string>& vCmd)
int nRet = 0;
try
{
if (vCmd.size() < 2) return 1;
if (!vCmd.size()) return 1;
std::string strMethod = vCmd[0];

View File

@@ -19,7 +19,7 @@
#define SECTION_PEER_START_MAX "peer_start_max"
#define SECTION_PEER_CONNECT_LOW_WATER "peer_connect_low_water"
#define SECTION_NETWORK_QUORUM "network_quorum"
#define SECTION_BELIEF_QUORUM "belief_quorum"
#define SECTION_VALIDATION_QUORUM "validation_quorum"
Config theConfig;
@@ -33,8 +33,8 @@ Config::Config()
RPC_PORT = 5001;
NUMBER_CONNECTIONS = 30;
// a new ledger every 30 min
LEDGER_SECONDS = (60*30);
// a new ledger every minute
LEDGER_SECONDS = 60;
RPC_USER = "admin";
RPC_PASSWORD = "pass";
@@ -49,8 +49,8 @@ Config::Config()
TRANSACTION_FEE_BASE = 1000;
NETWORK_QUORUM = 0;
BELIEF_QUORUM = 1;
NETWORK_QUORUM = 0; // Don't need to see other nodes
VALIDATION_QUORUM = 1; // Only need one node to vouch
}
void Config::load()
@@ -101,10 +101,10 @@ void Config::load()
PEER_CONNECT_LOW_WATER = MAX(1, boost::lexical_cast<int>(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))
BELIEF_QUORUM = MIN(0, boost::lexical_cast<int>(strTemp));
if (sectionSingleB(secConfig, SECTION_VALIDATION_QUORUM, strTemp))
VALIDATION_QUORUM = MAX(0, boost::lexical_cast<int>(strTemp));
}
}

View File

@@ -35,8 +35,9 @@ public:
int LEDGER_PROPOSAL_DELAY_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 BELIEF_QUORUM; // Percent agreement needed to sync ledger w/o validations
int VALIDATION_QUORUM; // Minimum validations to consider ledger authoritative
// node networking parameters
std::string PEER_IP;

View File

@@ -123,8 +123,9 @@ void ConnectionPool::relayMessage(Peer* fromPeer, PackedMessage::pointer msg)
BOOST_FOREACH(naPeer pair, mConnectedMap)
{
Peer::pointer peer = pair.second;
if(!fromPeer || !(peer.get() == fromPeer))
if (!peer)
std::cerr << "CP::RM null peer in list" << std::endl;
else if (!fromPeer || !(peer.get() == fromPeer))
peer->sendPacket(msg);
}
}
@@ -176,7 +177,7 @@ bool ConnectionPool::connectTo(const std::string& strIp, int iPort)
if (it == mIpMap.end())
{
// Did not find it. Not already connecting or connected.
std::cerr << "ConnectionPool::connectTo: Connectting: "
std::cerr << "ConnectionPool::connectTo: Connecting: "
<< strIp << " " << iPort << std::endl;
Peer::pointer peer(Peer::create(theApp->getIOService(), mCtx));
@@ -208,8 +209,23 @@ Json::Value ConnectionPool::getPeersJson()
BOOST_FOREACH(naPeer pair, mConnectedMap)
{
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;
@@ -221,7 +237,7 @@ bool ConnectionPool::peerConnected(Peer::pointer peer, const NewcoinAddress& na)
bool bSuccess;
std::cerr << "ConnectionPool::peerConnected: " << na.humanNodePublic() << std::endl;
assert(!!peer);
if (na == theApp->getWallet().getNodePublic())
{
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)
{
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;
// Look for more to scan.
scanRefresh();
}
}

View File

@@ -72,6 +72,7 @@ public:
void peerFailed(const std::string& strIp, int iPort);
Json::Value getPeersJson();
std::vector<Peer::pointer> getPeerVector();
//
// Scanning

View File

@@ -64,7 +64,7 @@ bool HashedObject::store(HashedObjectType type, uint32 index, const std::vector<
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
Database* db = theApp->getHashNodeDB()->getDB();
return db->executeSQL(sql.c_str());
return db->executeSQL(sql);
}
bool HashedObject::store() const
@@ -86,12 +86,12 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash)
uint32 index;
std::vector<unsigned char> data;
data.reserve(8192);
if(1)
{
ScopedLock sl(theApp->getHashNodeDB()->getDBLock());
Database* db = theApp->getHashNodeDB()->getDB();
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
if (!db->executeSQL(sql) || !db->startIterRows())
return HashedObject::pointer();
std::string type;
@@ -115,10 +115,12 @@ HashedObject::pointer HashedObject::retrieve(const uint256& hash)
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;
#ifdef DEBUG
assert(obj->checkHash());
#endif
return obj;
}
// vim:ts=4

View File

@@ -167,7 +167,7 @@ void HttpsClient::handleConnect(const boost::system::error_code& ecResult)
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.set_verify_mode(boost::asio::ssl::verify_peer);

View File

@@ -7,6 +7,7 @@
#include "Application.h"
#include "Ledger.h"
#include "utils.h"
#include "../obj/src/newcoin.pb.h"
#include "PackedMessage.h"
#include "Config.h"
@@ -16,7 +17,8 @@
#include "BinaryFormats.h"
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>();
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,
uint64 totCoins, uint64 timeStamp, uint32 ledgerSeq)
: 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)
{
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),
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger.mAccountStateMap)
mTransactionMap(new SHAMap()), mAccountStateMap(prevLedger->mAccountStateMap)
{
mParentHash = prevLedger.getHash();
mLedgerSeq = prevLedger.mLedgerSeq+1;
prevLedger->setClosed();
prevLedger->updateHash();
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)
{
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(mTransHash, BLgPTxT)) 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();
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)
{
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(mTransHash, BLgPTxT)) 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();
if(mValidHash)
{
@@ -111,7 +117,8 @@ void Ledger::addRaw(Serializer &s)
s.add256(mParentHash);
s.add256(mTransHash);
s.add256(mAccountHash);
s.add64(mTimeStamp);
s.add64(mCloseTime);
s.add16(mLedgerInterval);
}
AccountState::pointer Ledger::getAccountState(const NewcoinAddress& accountID)
@@ -175,14 +182,6 @@ Transaction::pointer Ledger::getTransaction(const uint256& transID) const
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()
{
#if 0
@@ -231,7 +230,7 @@ uint256 Ledger::getHash()
void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
{
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("','");
sql.append(boost::lexical_cast<std::string>(ledger->mLedgerSeq));
@@ -240,7 +239,7 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
sql.append("','");
sql.append(boost::lexical_cast<std::string>(ledger->mTotCoins));
sql.append("','");
sql.append(boost::lexical_cast<std::string>(ledger->mTimeStamp));
sql.append(boost::lexical_cast<std::string>(ledger->mCloseTime));
sql.append("','");
sql.append(ledger->mAccountHash.GetHex());
sql.append("','");
@@ -248,7 +247,7 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
sql.append("');");
ScopedLock sl(theApp->getLedgerDB()->getDBLock());
theApp->getLedgerDB()->getDB()->executeSQL(sql.c_str());
theApp->getLedgerDB()->getDB()->executeSQL(sql);
// write out dirty nodes
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());
Database *db = theApp->getLedgerDB()->getDB();
if (!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
if (!db->executeSQL(sql) || !db->startIterRows())
return Ledger::pointer();
db->getStr("LedgerHash", hash);
@@ -325,8 +325,11 @@ void Ledger::addJson(Json::Value& ret)
ledger["AccountHash"] = mAccountHash.GetHex();
ledger["Closed"] = true;
ledger["Accepted"] = mAccepted;
ledger["TotalCoins"] = boost::lexical_cast<std::string>(mTotCoins);
}
else ledger["Closed"] = false;
if (mCloseTime != 0)
ledger["CloseTime"] = boost::posix_time::to_simple_string(ptFromSeconds(mCloseTime));
ret[boost::lexical_cast<std::string>(mLedgerSeq)] = ledger;
}
@@ -342,7 +345,7 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
if (newPrevious->getLedgerSeq() != oldPrevious->getLedgerSeq()) return Ledger::pointer();
// 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
SHAMap::SHAMapDiff mapDifferences;
@@ -361,9 +364,9 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
while (it != TxnDiff.end())
{
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++);
}
else ++it;
@@ -389,9 +392,9 @@ Ledger::pointer Ledger::switchPreviousLedger(Ledger::pointer oldPrevious, Ledger
std::map<uint256, Transaction::pointer>::iterator it = txnMap.begin();
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++);
}
else ++it;
@@ -425,3 +428,25 @@ bool Ledger::isAcquiringAS(void)
{
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

View File

@@ -6,6 +6,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "../json/value.h"
@@ -15,7 +16,6 @@
#include "BitcoinUtil.h"
#include "SHAMap.h"
enum LedgerStateParms
{
lepNONE = 0, // no special flags
@@ -37,7 +37,6 @@ class Ledger : public boost::enable_shared_from_this<Ledger>
public:
typedef boost::shared_ptr<Ledger> pointer;
enum TransResult
{
TR_ERROR = -1,
@@ -56,8 +55,10 @@ public:
private:
uint256 mHash, mParentHash, mTransHash, mAccountHash;
uint64 mTotCoins, mTimeStamp;
uint64 mTotCoins;
uint64 mCloseTime; // when this ledger closes
uint32 mLedgerSeq;
uint16 mLedgerInterval;
bool mClosed, mValidHash, mAccepted, mImmutable;
SHAMap::pointer mTransactionMap, mAccountStateMap;
@@ -68,8 +69,6 @@ private:
Ledger& operator=(const Ledger&); // no implementation
protected:
Ledger(Ledger& previous, uint64 timestamp); // ledger after this one
void updateHash();
bool addTransaction(Transaction::pointer);
bool addTransaction(const uint256& id, const Serializer& txn, uint64_t fee);
@@ -82,10 +81,12 @@ protected:
public:
Ledger(const NewcoinAddress& masterID, uint64 startAmount); // used for the starting bootstrap ledger
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::string& rawLedger);
Ledger(Ledger::pointer previous); // ledger after this one
void updateHash();
void setClosed() { mClosed = true; }
void setAccepted() { mAccepted = true; }
bool isClosed() { return mClosed; }
@@ -99,8 +100,14 @@ public:
const uint256& getTransHash() const { return mTransHash; }
const uint256& getAccountHash() const { return mAccountHash; }
uint64 getTotalCoins() const { return mTotCoins; }
uint64 getTimeStamp() const { return mTimeStamp; }
uint64 getCloseTimeNC() const { return mCloseTime; }
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
SHAMap::pointer peekTransactionMap() { return mTransactionMap; }
@@ -144,7 +151,6 @@ public:
const uint160& currency)
{ return getRippleIndex(account.getAccountID(), extendTo.getAccountID(), currency); }
Ledger::pointer closeLedger(uint64 timestamp);
bool isCompatible(boost::shared_ptr<Ledger> other);
bool signLedger(std::vector<unsigned char> &signature, const LocalHanko &hanko);
@@ -164,3 +170,4 @@ inline LedgerStateParms operator&(const LedgerStateParms& l1, const LedgerStateP
}
#endif
// vim:ts=4

View File

@@ -1,18 +1,28 @@
#include "boost/foreach.hpp"
#include "boost/make_shared.hpp"
#include "Application.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),
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()
{
#ifdef DEBUG
std::cerr << "Done acquiring ledger " << mHash.GetHex() << std::endl;
#endif
std::vector< boost::function<void (LedgerAcquire::pointer)> > triggers;
mLock.lock();
@@ -20,19 +30,22 @@ void LedgerAcquire::done()
mOnComplete.empty();
mLock.unlock();
for(int i=0; i<triggers.size(); i++)
for (int i = 0; i<triggers.size(); ++i)
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)
{
if (result == boost::asio::error::operation_aborted) return;
LedgerAcquire::pointer ptr = wptr.lock();
if(ptr) ptr->trigger(true);
if (!!ptr) ptr->trigger(Peer::pointer());
}
void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)> trigger)
@@ -42,21 +55,36 @@ void LedgerAcquire::addOnComplete(boost::function<void (LedgerAcquire::pointer)>
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;
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
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_itype(newcoin::liBASE);
sendRequest(tmGL);
if (peer)
{
sendRequest(tmGL, peer);
return;
}
else sendRequest(tmGL);
}
if (mHaveBase && !mHaveTransactions)
{
#ifdef DEBUG
std::cerr << "need tx" << std::endl;
#endif
assert(mLedger);
if (mLedger->peekTransactionMap()->getHash().isZero())
{ // we need the root node
@@ -65,6 +93,11 @@ void LedgerAcquire::trigger(bool timer)
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
tmGL->set_itype(newcoin::liTX_NODE);
*(tmGL->add_nodeids()) = SHAMapNode().getRawString();
if (peer)
{
sendRequest(tmGL, peer);
return;
}
sendRequest(tmGL);
}
else
@@ -89,6 +122,11 @@ void LedgerAcquire::trigger(bool timer)
tmGL->set_itype(newcoin::liTX_NODE);
for (std::vector<SHAMapNode>::iterator it = nodeIDs.begin(); it != nodeIDs.end(); ++it)
*(tmGL->add_nodeids()) = it->getRawString();
if (peer)
{
sendRequest(tmGL, peer);
return;
}
sendRequest(tmGL);
}
}
@@ -96,6 +134,9 @@ void LedgerAcquire::trigger(bool timer)
if (mHaveBase && !mHaveState)
{
#ifdef DEBUG
std::cerr << "need as" << std::endl;
#endif
assert(mLedger);
if (mLedger->peekAccountStateMap()->getHash().isZero())
{ // we need the root node
@@ -104,6 +145,11 @@ void LedgerAcquire::trigger(bool timer)
tmGL->set_ledgerseq(mLedger->getLedgerSeq());
tmGL->set_itype(newcoin::liAS_NODE);
*(tmGL->add_nodeids()) = SHAMapNode().getRawString();
if (peer)
{
sendRequest(tmGL, peer);
return;
}
sendRequest(tmGL);
}
else
@@ -128,6 +174,11 @@ void LedgerAcquire::trigger(bool timer)
tmGL->set_itype(newcoin::liAS_NODE);
for (std::vector<SHAMapNode>::iterator it =nodeIDs.begin(); it != nodeIDs.end(); ++it)
*(tmGL->add_nodeids()) = it->getRawString();
if (peer)
{
sendRequest(tmGL, peer);
return;
}
sendRequest(tmGL);
}
}
@@ -135,8 +186,13 @@ void LedgerAcquire::trigger(bool timer)
if (mComplete || mFailed)
done();
else if(timer)
setTimer();
else
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)
@@ -154,7 +210,8 @@ void LedgerAcquire::sendRequest(boost::shared_ptr<newcoin::TMGetLedger> tmGL)
else
{
// FIXME: Track last peer sent to and time sent
it->lock()->sendPacket(packet);
Peer::pointer peer = it->lock();
if (peer) peer->sendPacket(packet);
return;
}
}
@@ -176,6 +233,7 @@ void LedgerAcquire::peerHas(Peer::pointer ptr)
}
}
mPeers.push_back(ptr);
if (mPeers.size() == 1) trigger(ptr);
}
void LedgerAcquire::badPeer(Peer::pointer ptr)
@@ -199,53 +257,85 @@ 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
#ifdef DEBUG
std::cerr << "got base acquiring ledger " << mHash.GetHex() << std::endl;
#endif
boost::recursive_mutex::scoped_lock sl(mLock);
if (mHaveBase) return true;
Ledger* ledger=new Ledger(data);
if(ledger->getHash()!=mHash)
mLedger = boost::make_shared<Ledger>(data);
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;
}
mLedger=Ledger::pointer(ledger);
mLedger->setAcquiring();
mHaveBase = true;
if (!mLedger->getTransHash()) mHaveTransactions = true;
if (!mLedger->getAccountHash()) mHaveState = true;
mLedger->setAcquiring();
trigger(peer);
return true;
}
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;
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->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;
++nodeIDit;
++nodeDatait;
}
if(!mLedger->peekTransactionMap()->isSynching()) mHaveTransactions=true;
if (!mLedger->peekTransactionMap()->isSynching())
{
mHaveTransactions = true;
if (mHaveState) mComplete = true;
}
trigger(peer);
return true;
}
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)
{
#ifdef DEBUG
std::cerr << "got ASdata acquiring ledger " << mHash.GetHex() << std::endl;
#endif
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;
++nodeIDit;
++nodeDatait;
}
if(!mLedger->peekAccountStateMap()->isSynching()) mHaveState=true;
if (!mLedger->peekAccountStateMap()->isSynching())
{
mHaveState = true;
if (mHaveTransactions) mComplete = true;
}
trigger(peer);
return true;
}
@@ -254,7 +344,10 @@ LedgerAcquire::pointer LedgerAcquireMaster::findCreate(const uint256& hash)
boost::mutex::scoped_lock sl(mLock);
LedgerAcquire::pointer& ptr = mLedgers[hash];
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)
@@ -271,11 +364,29 @@ bool LedgerAcquireMaster::hasLedger(const uint256& hash)
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;
if(packet.ledgerhash().size()!=32) return false;
if (packet.ledgerhash().size() != 32)
{
#ifdef DEBUG
std::cerr << "error" << std::endl;
#endif
return false;
}
memcpy(&hash, packet.ledgerhash().data(), 32);
#ifdef DEBUG
std::cerr << hash.GetHex() << std::endl;
#endif
LedgerAcquire::pointer ledger = find(hash);
if (!ledger) return false;
@@ -285,7 +396,7 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet)
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());
return ledger->takeBase(node.nodedata(), peer);
}
else if ((packet.type() == newcoin::liTX_NODE) || (packet.type() == newcoin::liAS_NODE))
{
@@ -293,7 +404,7 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet)
std::list<std::vector<unsigned char> > nodeData;
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);
if (!node.has_nodeid() || !node.has_nodedata()) return false;
@@ -301,8 +412,9 @@ bool LedgerAcquireMaster::gotLedgerData(newcoin::TMLedgerData& packet)
nodeIDs.push_back(SHAMapNode(node.nodeid().data(), node.nodeid().size()));
nodeData.push_back(std::vector<unsigned char>(node.nodedata().begin(), node.nodedata().end()));
}
if(packet.type()==newcoin::liTX_NODE) return ledger->takeTxNode(nodeIDs, nodeData);
else return ledger->takeAsNode(nodeIDs, nodeData);
if (packet.type() == newcoin::liTX_NODE) return ledger->takeTxNode(nodeIDs, nodeData, peer);
else return ledger->takeAsNode(nodeIDs, nodeData, peer);
}
else return false;
return false;
}

View File

@@ -4,8 +4,10 @@
#include <vector>
#include <map>
#include "boost/enable_shared_from_this.hpp"
#include "boost/function.hpp"
#include <boost/enable_shared_from_this.hpp>
#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <boost/thread/mutex.hpp>
#include "Ledger.h"
#include "Peer.h"
@@ -21,16 +23,19 @@ protected:
Ledger::pointer mLedger;
uint256 mHash;
bool mComplete, mFailed, mHaveBase, mHaveState, mHaveTransactions;
boost::asio::deadline_timer mTimer;
std::vector< boost::function<void (LedgerAcquire::pointer)> > mOnComplete;
std::list<boost::weak_ptr<Peer> > mPeers; // peers known to have this ledger
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 setTimer();
void sendRequest(boost::shared_ptr<newcoin::TMGetLedger> message, Peer::pointer peer);
void trigger(Peer::pointer peer);
public:
LedgerAcquire(const uint256& hash);
@@ -47,9 +52,12 @@ public:
void peerHas(Peer::pointer);
void badPeer(Peer::pointer);
bool takeBase(const std::string& 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);
bool takeBase(const std::string& data, Peer::pointer);
bool takeTxNode(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
@@ -64,7 +72,9 @@ public:
LedgerAcquire::pointer findCreate(const uint256& hash);
LedgerAcquire::pointer find(const uint256& hash);
bool hasLedger(const uint256& ledgerHash);
bool gotLedgerData(newcoin::TMLedgerData& packet);
bool dropLedger(const uint256& ledgerHash);
bool gotLedgerData(newcoin::TMLedgerData& packet, Peer::pointer);
};
#endif
// vim:ts=4

View File

@@ -12,9 +12,10 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Balance), STI_UINT64, SOE_REQUIRED, 0 },
{ S_FIELD(LastReceive), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(LastTxn), STI_UINT32, SOE_REQUIRED, 0 },
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 1 },
{ S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 2 },
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 4 },
{ S_FIELD(AuthorizedKey),STI_VL, SOE_IFFLAG, 1 },
{ S_FIELD(EmailHash), STI_HASH128, SOE_IFFLAG, 2 },
{ S_FIELD(WalletLocator),STI_HASH256, SOE_IFFLAG, 4 },
{ S_FIELD(MessageKey), STI_VL, SOE_IFFLAG, 8 },
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ sfInvalid, NULL, STI_DONE, SOE_NEVER, -1 } }
},
@@ -33,6 +34,13 @@ LedgerEntryFormat LedgerFormats[]=
{ S_FIELD(Extensions), STI_TL, SOE_IFFLAG, 0x01000000 },
{ 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, {
{ S_FIELD(Flags), STI_UINT32, SOE_FLAGS, 0 },
{ S_FIELD(Nickname), STI_HASH256, SOE_REQUIRED, 0 },

View File

@@ -8,7 +8,8 @@ enum LedgerEntryType
ltINVALID =-1,
ltACCOUNT_ROOT =0,
ltRIPPLE_STATE =1,
ltNICKNAME=2
ltGENERATOR_MAP =2,
ltNICKNAME =3
};
struct LedgerEntryFormat
@@ -21,3 +22,4 @@ struct LedgerEntryFormat
extern LedgerEntryFormat LedgerFormats[];
extern LedgerEntryFormat* getLgrFormat(LedgerEntryType t);
#endif
// vim:ts=4

View File

@@ -84,3 +84,4 @@ Ledger::pointer LedgerHistory::canonicalizeLedger(Ledger::pointer ledger, bool s
if (ledger->isAccepted()) mLedgersByIndex[ledger->getLedgerSeq()]=ledger;
return ledger;
}
// vim:ts=4

View File

@@ -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));
return base;
}
// vim:ts=4

View File

@@ -1,7 +1,6 @@
#include "LedgerMaster.h"
#include "Application.h"
#include "NewcoinAddress.h"
#include "TimingService.h"
#include "Conversion.h"
#include <boost/foreach.hpp>
@@ -36,6 +35,17 @@ void LedgerMaster::pushLedger(Ledger::pointer 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
void LedgerMaster::startFinalization()

View File

@@ -45,6 +45,7 @@ public:
{ return mEngine.applyTransaction(txn, params); }
void pushLedger(Ledger::pointer newLedger);
void switchLedgers(Ledger::pointer lastClosed, Ledger::pointer newCurrent);
Ledger::pointer getLedgerBySeq(uint32 index)
{
@@ -66,3 +67,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -109,3 +109,4 @@ SerializedLedgerEntry::pointer Ledger::getNickname(LedgerStateParms& parms, cons
return SerializedLedgerEntry::pointer();
}
}
// vim:ts=4

View File

@@ -16,7 +16,7 @@ public:
protected:
// core account information
CKey::pointer mPublicKey;
NewcoinAddress mAcctID;
NewcoinAddress mAccount;
std::string mComment;
// family information
@@ -32,7 +32,7 @@ public:
bool updateName(); // writes changed name/comment
bool updateBalance(); // writes changed balance/seq
const NewcoinAddress& getAddress() const { return mAcctID; }
const NewcoinAddress& getAddress() const { return mAccount; }
int getAcctFSeq() const { return mAccountFSeq; }
std::string getFullName() const;

View File

@@ -1,8 +1,14 @@
#include "Application.h"
#include "NetworkOPs.h"
#include <boost/bind.hpp>
#include <boost/unordered_map.hpp>
#include "utils.h"
#include "Application.h"
#include "Transaction.h"
// This is the primary interface into the "client" portion of the program.
// Code that wants to do normal operations on the network such as
// 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
// 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()
@@ -51,7 +66,7 @@ Transaction::pointer NetworkOPs::processTransaction(Transaction::pointer trans,
theApp->getMasterLedger().addHeldTransaction(trans);
return trans;
}
if ( (r==terPAST_SEQ || r==terPAST_LEDGER) )
if ((r == terPAST_SEQ) || (r == terPAST_LEDGER))
{ // duplicate or conflict
#ifdef DEBUG
std::cerr << "Transaction is obsolete" << 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
// theApp->getWallet().applyTransaction(trans);
newcoin::TMTransaction *tx=new newcoin::TMTransaction();
boost::shared_ptr<newcoin::TMTransaction> tx = boost::make_shared<newcoin::TMTransaction>();
Serializer::pointer s;
trans->getSTransaction()->getTransaction(*s, false);
tx->set_rawtransaction(&s->getData().front(), s->getLength());
tx->set_status(newcoin::tsCURRENT);
tx->set_receivetimestamp(getNetworkTime());
tx->set_receivetimestamp(getNetworkTimeNC());
tx->set_ledgerindexpossible(trans->getLedger());
PackedMessage::pointer packet(new PackedMessage(PackedMessage::MessagePointer(tx), newcoin::mtTRANSACTION));
@@ -111,13 +126,13 @@ int NetworkOPs::findTransactionsBySource(std::list<Transaction::pointer>& txns,
if (maxSeq > minSeq) return 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);
if(txn)
{
txns.push_back(txn);
count++;
++count;
}
}
return count;
@@ -134,3 +149,215 @@ AccountState::pointer NetworkOPs::getAccountState(const NewcoinAddress& accountI
{
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

View File

@@ -1,15 +1,20 @@
#ifndef __NETWORK_OPS__
#define __NETWORK_OPS__
#include <boost/asio.hpp>
#include "Transaction.h"
#include "AccountState.h"
#include "Ledger.h"
// Operations that clients may wish to perform against the network
// Master operational handler, server sequencer, network tracker
class Peer;
class NetworkOPs
{
public:
enum Fault
{ // exceptions these functions can throw
IO_ERROR = 1,
@@ -18,20 +23,24 @@ class NetworkOPs
enum OperatingMode
{ // how we process transactions or account balance requests
FAULTED=0, // we are unable to process requests (not ready or no network)
FULL_LOCAL=1, // we are in full local sync
PART_LOCAL=2, // we can validate remote data but have to request it
REMOTE=3 // we have to trust remote nodes
omDISCONNECTED = 0, // not ready to process requests
omCONNECTED = 1, // convinced we are talking to the network
omTRACKING = 2, // convinced we agree with the network
omFULL = 3 // we have the ledger and can even validate
};
public:
protected:
OperatingMode mMode;
boost::asio::deadline_timer mNetTimer;
// context information
OperatingMode getOperatingMode();
public:
NetworkOPs(boost::asio::io_service& io_service);
// network information
uint64 getNetworkTime();
uint64 getNetworkTimeNC();
boost::posix_time::ptime getNetworkTimePT();
uint32 getCurrentLedgerID();
OperatingMode getOperatingMode() { return mMode; }
// transaction operations
Transaction::pointer processTransaction(Transaction::pointer transaction, Peer* source = NULL);
@@ -44,19 +53,24 @@ public:
// account operations
AccountState::pointer getAccountState(const NewcoinAddress& accountID);
// contact block operations
// raw object operations
bool findRawLedger(const uint256& ledgerHash, std::vector<unsigned char>& rawLedger);
bool findRawTransaction(const uint256& transactionHash, std::vector<unsigned char>& rawTransaction);
bool findAccountNode(const uint256& nodeHash, std::vector<unsigned char>& rawAccountNode);
bool findTransactionNode(const uint256& nodeHash, std::vector<unsigned char>& rawTransactionNode);
// tree synchronzation operations
// tree synchronization operations
bool getTransactionTreeNodes(uint32 ledgerSeq, const uint256& myNodeID,
const std::vector<unsigned char>& myNode, std::list<std::vector<unsigned char> >& newNodes);
bool getAccountStateNodes(uint32 ledgerSeq, const uint256& myNodeId,
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
// vim:ts=4

View File

@@ -3,15 +3,15 @@
#include "Config.h"
#include "BitcoinUtil.h"
#include "rfc1751.h"
#include "utils.h"
#include "openssl/rand.h"
#include <cassert>
#include <algorithm>
#include <iostream>
#include <boost/format.hpp>
#include <boost/functional/hash.hpp>
#include <boost/test/unit_test.hpp>
#include <cassert>
#include <iostream>
#include <openssl/rand.h>
NewcoinAddress::NewcoinAddress()
{
@@ -273,7 +273,7 @@ void NewcoinAddress::setAccountPublic(const std::vector<unsigned char>& vPublic)
void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
{
CKey pubkey = CKey(generator, seq);
CKey pubkey = CKey(generator, seq+1);
setAccountPublic(pubkey.GetPubKey());
}
@@ -282,14 +282,14 @@ void NewcoinAddress::setAccountPublic(const NewcoinAddress& generator, int seq)
// AccountPrivate
//
uint256 NewcoinAddress::getAccountPrivate() const
const std::vector<unsigned char>& NewcoinAddress::getAccountPrivate() const
{
switch (nVersion) {
case VER_NONE:
throw std::runtime_error("unset source");
case VER_ACCOUNT_PRIVATE:
return uint256(vchData);
return vchData;
default:
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);
}
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
//

View File

@@ -78,13 +78,20 @@ public:
//
// Accounts Private
//
uint256 getAccountPrivate() const;
const std::vector<unsigned char>& getAccountPrivate() const;
std::string humanAccountPrivate() const;
bool setAccountPrivate(const std::string& strPrivate);
void setAccountPrivate(const std::vector<unsigned char>& vPrivate);
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

View File

@@ -13,8 +13,7 @@ void PackedMessage::encodeHeader(unsigned size, int type)
}
PackedMessage::PackedMessage(MessagePointer msg, int type)
: mMsg(msg)
PackedMessage::PackedMessage(MessagePointer msg, int type) : mMsg(msg)
{
unsigned msg_size = mMsg->ByteSize();
assert(msg_size);
@@ -36,25 +35,20 @@ bool PackedMessage::operator == (const PackedMessage& other)
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];
ret<<=8;
ret|=buf[1];
ret<<=8;
ret|=buf[2];
ret<<=8;
ret|=buf[3];
return(ret);
ret <<= 8; ret |= buf[1]; ret <<= 8; ret |= buf[2]; ret <<= 8; ret |= buf[3];
return ret;
}
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];
ret<<=8;
ret|=buf[5];
return(ret);
ret <<= 8; ret |= buf[5];
return ret;
}

View File

@@ -19,8 +19,9 @@
// Node has this long to verify its identity from connection accepted or connection attempt.
#define NODE_VERIFY_SECONDS 15
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx)
: mSocketSsl(io_service, ctx),
Peer::Peer(boost::asio::io_service& io_service, boost::asio::ssl::context& ctx) :
mConnected(false),
mSocketSsl(io_service, ctx),
mVerifyTimer(io_service)
{
}
@@ -38,7 +39,7 @@ void Peer::handle_write(const boost::system::error_code& error, size_t bytes_tra
if (error)
{
detach();
detach("hw");
return;
}
@@ -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;
(void) mVerifyTimer.cancel();
mSendQ.clear();
// mSocketSsl.close();
if (!mIpPort.first.empty()) {
if (!mIpPort.first.empty())
{
if (mClientConnect)
// Connection might be part of scanning. Inform connect failed.
theApp->getConnectionPool().peerFailed(mIpPort.first, mIpPort.second);
theApp->getConnectionPool().peerDisconnected(shared_from_this(), mIpPort, mNodePublic);
@@ -90,7 +95,7 @@ void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
else
{
std::cerr << "Peer failed to verify in time." << std::endl;
detach();
detach("hvt");
}
}
@@ -98,12 +103,13 @@ void Peer::handleVerifyTimer(const boost::system::error_code& ecResult)
// Only takes IP addresses (not domains).
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;
std::cerr << "Peer::connect: " << strIp << " " << iPort << std::endl;
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::resolver_query_base::numeric_host|boost::asio::ip::resolver_query_base::numeric_service);
@@ -114,7 +120,8 @@ void Peer::connect(const std::string strIp, int iPort)
if (err || itrEndpoint == boost::asio::ip::tcp::resolver::iterator())
{
std::cerr << "Peer::connect: Bad IP" << std::endl;
detach();
detach("c");
return;
}
else
{
@@ -124,13 +131,14 @@ void Peer::connect(const std::string strIp, int iPort)
if (err)
{
std::cerr << "Peer::connect: Failed to set timer." << std::endl;
detach();
detach("c2");
return;
}
}
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(
mSocketSsl.lowest_layer(),
@@ -152,7 +160,7 @@ void Peer::handleStart(const boost::system::error_code& error)
if (error)
{
std::cerr << "Peer::handleStart: failed:" << error << std::endl;
detach();
detach("hs");
}
else
{
@@ -167,7 +175,7 @@ void Peer::handleConnect(const boost::system::error_code& error, boost::asio::ip
if (error)
{
std::cerr << "Connect peer: failed:" << error << std::endl;
detach();
detach("hc");
}
else
{
@@ -196,13 +204,13 @@ void Peer::connected(const boost::system::error_code& error)
if (error)
{
std::cerr << "Remote peer: accept error: " << strIp << " " << iPort << " : " << error << std::endl;
detach();
detach("ctd");
}
else if (!theApp->getConnectionPool().peerRegister(shared_from_this(), strIp, iPort))
{
std::cerr << "Remote peer: rejecting: " << strIp << " " << iPort << std::endl;
// XXX Reject with a rejection message: already connected
detach();
detach("ctd2");
}
else
{
@@ -212,6 +220,7 @@ void Peer::connected(const boost::system::error_code& error)
//BOOST_LOG_TRIVIAL(info) << "Connected to Peer.";
mIpPort = make_pair(strIp, iPort);
assert(!mIpPort.first.empty());
mSocketSsl.lowest_layer().set_option(boost::asio::ip::tcp::no_delay(true));
mSocketSsl.set_verify_mode(boost::asio::ssl::verify_none);
@@ -247,9 +256,6 @@ void Peer::sendPacket(PackedMessage::pointer packet)
void Peer::start_read_header()
{
#ifdef DEBUG
std::cerr << "SRH" << std::endl;
#endif
mReadbuf.clear();
mReadbuf.resize(HEADER_SIZE);
boost::asio::async_read(mSocketSsl, boost::asio::buffer(mReadbuf),
@@ -275,14 +281,14 @@ void Peer::handle_read_header(const boost::system::error_code& error)
// WRITEME: Compare to maximum message length, abort if too large
if(msg_len>(32*1024*1024))
{
detach();
detach("hrh");
return;
}
start_read_body(msg_len);
}
else
{
detach();
detach("hrh2");
std::cerr << "Peer::handle_read_header: Error: " << error << std::endl; //else BOOST_LOG_TRIVIAL(info) << "Error: " << error;
}
}
@@ -296,7 +302,7 @@ void Peer::handle_read_body(const boost::system::error_code& error)
}
else
{
detach();
detach("hrb");
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;
#endif
// If not connected, only accept mtHELLO. Otherwise, don't accept mtHELLO.
if (mIpPort.first.empty() == (type == newcoin::mtHELLO))
std::cerr << "Peer::processReadBuffer: " << mIpPort.first << " " << mIpPort.second << std::endl;
// 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;
detach();
detach("prb1");
}
else
{
@@ -400,6 +408,17 @@ void Peer::processReadBuffer()
}
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:
{
newcoin::TMGetLedger msg;
@@ -515,21 +534,33 @@ void Peer::recvHello(newcoin::TMHello& packet)
}
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.
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 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;
}
if (bDetach)
{
mNodePublic.clear();
detach();
detach("recvh");
}
}
@@ -618,6 +649,28 @@ 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)
{
// Figure out what ledger they want
@@ -660,7 +713,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
}
// 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();
data->set_ledgerhash(lHash.begin(), lHash.size());
data->set_ledgerseq(ledger->getLedgerSeq());
@@ -670,8 +723,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
{
Serializer nData(116);
ledger->addRaw(nData);
newcoin::TMLedgerNode* node=data->add_nodes();
node->set_nodedata(nData.getDataPtr(), nData.getLength());
data->add_nodes()->set_nodedata(nData.getDataPtr(), nData.getLength());
}
else if ( (packet.itype()==newcoin::liTX_NODE) || (packet.itype()==newcoin::liAS_NODE) )
{
@@ -700,9 +752,9 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
for(nodeIDIterator=nodeIDs.begin(), rawNodeIterator=rawNodes.begin();
nodeIDIterator!=nodeIDs.end(); ++nodeIDIterator, ++rawNodeIterator)
{
newcoin::TMLedgerNode* node=data->add_nodes();
Serializer nID(33);
nodeIDIterator->addIDRaw(nID);
newcoin::TMLedgerNode* node=data->add_nodes();
node->set_nodeid(nID.getDataPtr(), nID.getLength());
node->set_nodedata(&rawNodeIterator->front(), rawNodeIterator->size());
}
@@ -721,7 +773,7 @@ void Peer::recvGetLedger(newcoin::TMGetLedger& packet)
void Peer::recvLedger(newcoin::TMLedgerData& packet)
{
if(!theApp->getMasterLedgerAcquire().gotLedgerData(packet))
if(!theApp->getMasterLedgerAcquire().gotLedgerData(packet, shared_from_this()))
punishPeer(PP_UNWANTED_DATA);
}
@@ -764,11 +816,11 @@ void Peer::sendHello()
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_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_nodeproof(&vchSig[0], vchSig.size());
h->set_ipv4port(theConfig.PEER_PORT);
@@ -777,9 +829,10 @@ void Peer::sendHello()
assert(closedLedger && closedLedger->isClosed());
if (closedLedger->isClosed())
{
Serializer s(128);
closedLedger->addRaw(s);
h->set_closedledger(s.getDataPtr(), s.getLength());
uint256 hash = closedLedger->getHash();
h->set_closedledger(hash.begin(), hash.GetSerializeSize());
hash = closedLedger->getParentHash();
h->set_previousledger(hash.begin(), hash.GetSerializeSize());
}
PackedMessage::pointer packet = boost::make_shared<PackedMessage>

View File

@@ -32,10 +32,15 @@ public:
private:
bool mClientConnect; // In process of connecting as client.
bool mConnected; // True, if hello accepted.
NewcoinAddress mNodePublic; // Node public key of peer.
ipPort mIpPort;
uint256 mCookieHash;
// 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;
@@ -62,8 +67,6 @@ protected:
void sendPacketForce(PackedMessage::pointer packet);
void sendHello();
void sendTransaction(newcoin::TMTransaction& packet);
void sendValidation();
void recvHello(newcoin::TMHello& packet);
void recvTransaction(newcoin::TMTransaction& packet);
@@ -81,6 +84,7 @@ protected:
void recvAccount(newcoin::TMAccount& packet);
void recvGetLedger(newcoin::TMGetLedger& packet);
void recvLedger(newcoin::TMLedgerData& packet);
void recvStatus(newcoin::TMStatusChange& packet);
void getSessionCookie(std::string& strDst);
@@ -101,7 +105,7 @@ public:
void connect(const std::string strIp, int iPort);
void connected(const boost::system::error_code& error);
void detach();
void detach(const char *);
bool samePeer(Peer::pointer p) { return samePeer(*p); }
bool samePeer(const Peer& p) { return this == &p; }
@@ -118,6 +122,9 @@ public:
static PackedMessage::pointer createLedgerProposal(Ledger::pointer ledger);
static PackedMessage::pointer createValidation(Ledger::pointer ledger);
static PackedMessage::pointer createGetFullLedger(uint256& hash);
uint256 getClosedLedgerHash() const { return mClosedLedgerHash; }
NewcoinAddress getNodePublic() const { return mNodePublic; }
};
#endif

View File

@@ -19,11 +19,11 @@ CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
std::vector<unsigned char> data;
data.reserve(65); // our public keys are actually 33 bytes
int pkSize;
if(1)
{ // is it in the database
ScopedLock sl(theApp->getTxnDB()->getDBLock());
Database* db=theApp->getTxnDB()->getDB();
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
if(!db->executeSQL(sql) || !db->startIterRows())
return CKey::pointer();
pkSize=db->getBinary("PubKey", &(data.front()), data.size());
db->endIterRows();
@@ -36,7 +36,6 @@ CKey::pointer PubKeyCache::locate(const NewcoinAddress& id)
return CKey::pointer();
}
if(1)
{ // put it in cache (okay if we race with another retriever)
boost::mutex::scoped_lock sl(mLock);
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)
{ // stored if needed, returns cached copy (possibly the original)
if(1)
{
boost::mutex::scoped_lock sl(mLock);
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(");");
ScopedLock dbl(theApp->getTxnDB()->getDBLock());
theApp->getTxnDB()->getDB()->executeSQL(sql.c_str(), true);
theApp->getTxnDB()->getDB()->executeSQL(sql, true);
return key;
}
@@ -74,3 +72,4 @@ void PubKeyCache::clear()
boost::mutex::scoped_lock sl(mLock);
mCache.empty();
}
// vim:ts=4

View File

@@ -51,7 +51,7 @@ void SHAMap::dirtyUp(std::stack<SHAMapTreeNode::pointer>& stack, const uint256&
{ // walk the tree up from through the inner nodes to the root
// update linking hashes and add nodes to dirty list
assert(mState!=Synching && mState!=Immutable);
assert((mState != Synching) && (mState != Immutable));
while (!stack.empty())
{
@@ -87,7 +87,6 @@ SHAMapTreeNode::pointer SHAMap::checkCacheNode(const SHAMapNode& iNode)
SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify)
{ // walk down to the terminal node for this ID
SHAMapTreeNode::pointer inNode = root;
while (!inNode->isLeaf())
@@ -101,6 +100,7 @@ SHAMapTreeNode::pointer SHAMap::walkTo(const uint256& id, bool modify)
if (!nextNode) throw SHAMapException(MissingNode);
inNode = nextNode;
}
if (inNode->getTag() != id) return SHAMapTreeNode::pointer();
if (modify) returnNode(inNode, true);
return inNode;
}
@@ -166,7 +166,7 @@ SHAMapItem::pointer SHAMap::firstBelow(SHAMapTreeNode::pointer node)
if (node->hasItem()) return node->peekItem();
bool foundNode = false;
for(int i=0; i<16; i++)
for (int i = 0; i < 16; ++i)
if (!node->isEmptyBranch(i))
{
#ifdef ST_DEBUG
@@ -194,7 +194,7 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapTreeNode::pointer node)
if (node->hasItem()) return node->peekItem();
bool foundNode = false;
for(int i=15; i>=0; i++)
for (int i = 15; i >= 0; ++i)
if (!node->isEmptyBranch(i))
{
node = getNode(node->getChildNodeID(i), node->getChildHash(i), false);
@@ -215,7 +215,7 @@ SHAMapItem::pointer SHAMap::onlyBelow(SHAMapTreeNode::pointer node)
found = false;
SHAMapTreeNode::pointer nextNode;
for(int i=0; i<16; i++)
for (int i = 0; i < 16; ++i)
if (!node->isEmptyBranch(i))
{
if( found) return SHAMapItem::pointer(); // two leaves below
@@ -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;
for(int i=0; i<32; i++)
vuc.push_back((unsigned char) i);
for (int i = 0; i < 32; ++i)
vuc.push_back(static_cast<unsigned char>(v));
return vuc;
}
@@ -675,4 +675,4 @@ bool SHAMap::TestSHAMap()
return false;
return true;
}
// vim:ts=4

View File

@@ -295,7 +295,7 @@ public:
// status functions
void setImmutable(void) { assert(mState != Invalid); mState = Immutable; }
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 setFloating(void) { mState = Floating; }
void clearSynching(void) { mState = Modifying; }
@@ -315,6 +315,11 @@ public:
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 syncTest();
bool deepCompare(SHAMap& other);
@@ -322,3 +327,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -146,7 +146,7 @@ int SHAMapNode::selectBranch(const uint256& hash) const
if (mDepth % 2) branch >>= 4;
else branch &= 0xf;
assert(branch>=0 && branch<16);
assert((branch >= 0) && (branch < 16));
return branch;
}
@@ -202,13 +202,13 @@ SHAMapTreeNode::SHAMapTreeNode(const SHAMapNode& id, const std::vector<unsigned
else if (type == 2)
{ // full inner
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);
mType = tnINNER;
}
else if (type == 3)
{ // compressed inner
for(int i=0; i<(len/33); i++)
for (int i = 0; i < (len / 33); ++i)
{
int pos;
s.get8(pos, 32 + (i * 33));
@@ -243,7 +243,7 @@ void SHAMapTreeNode::addRaw(Serializer &s)
if (getBranchCount() < 12)
{ // compressed node
for(int i=0; i<16; i++)
for (int i = 0; i < 16; ++i)
if (mHashes[i].isNonZero())
{
s.add256(mHashes[i]);
@@ -253,7 +253,7 @@ void SHAMapTreeNode::addRaw(Serializer &s)
return;
}
for(int i=0; i<16; i++)
for (int i = 0; i < 16; ++i)
s.add256(mHashes[i]);
s.add8(2);
}
@@ -265,7 +265,7 @@ bool SHAMapTreeNode::updateHash()
if (mType == tnINNER)
{
bool empty = true;
for(int i=0; i<16; i++)
for (int i = 0; i < 16; ++i)
if (mHashes[i].isNonZero())
{
empty = false;
@@ -339,7 +339,7 @@ std::string SHAMapTreeNode::getString() const
ret += ")";
if (isInner())
{
for(int i=0; i<16; i++)
for(int i = 0; i < 16; ++i)
if (!isEmptyBranch(i))
{
ret += ",b";
@@ -368,3 +368,4 @@ const uint256& SHAMapTreeNode::getChildHash(int m) const
assert((m >= 0) && (m < 16) && (mType == tnINNER));
return mHashes[m];
}
// vim:ts=4

View File

@@ -348,6 +348,26 @@ static bool confuseMap(SHAMap &map, int count)
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()
{
unsigned int seed;

View File

@@ -71,3 +71,4 @@ bool SerializedLedgerEntry::isEquivalent(const SerializedType& t) const
if (mObject != v->mObject) return false;
return true;
}
// vim:ts=4

View File

@@ -74,3 +74,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -467,6 +467,16 @@ void STObject::setValueFieldH160(SOE_Field field, const uint160& 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)
{
SerializedType* rf = getPField(field);

View File

@@ -27,11 +27,12 @@ enum SOE_Field
sfFlags, sfExtensions, sfTargetLedger, sfSourceTag, sfIdentifier,
sfDestination, sfTarget, sfAmount, sfCurrency,
sfAmountIn, sfAmountOut, sfCurrencyIn, sfCurrencyOut,
sfInvoiceID, sfExpireLedger, sfMessageKey, sfCurrentRate, sfRateLock,
sfInvoiceID, sfExpireLedger, sfMessageKey, sfSigningKey, sfCurrentRate, sfRateLock,
sfAccount, sfSequence, sfBalance, sfWalletLocator, sfEmailHash,
sfBorrower, sfLendfer, sfLimit, sfOfferCurrency,
sfLastReceive, sfLastTxn, sfLender, sfNextRate, sfNextRateLgr, sfNextRateExp,
sfBorrower, sfLender, sfLimit, sfOfferCurrency, sfLedgerHash,
sfLastReceive, sfLastTxn, sfNextRate, sfNextRateLgr, sfNextRateExp,
sfNickname, sfMinimumOffer,
sfAuthorizedKey, sfGenerator, sfGeneratorID, sfAccountID,
// test fields
sfTest1, sfTest2, sfTest3, sfTest4
@@ -131,3 +132,4 @@ public:
#endif
// vim:ts=4

View File

@@ -38,14 +38,6 @@ SerializedTransaction::SerializedTransaction(SerializerIterator& sit, int length
mMiddleTxn.giveObject(new STUInt64("Fee", sit.get64()));
mInnerTxn = STObject(mFormat->elements, sit, "InnerTransaction");
updateSourceAccount();
}
void SerializedTransaction::updateSourceAccount()
{
NewcoinAddress a;
a.setAccountPublic(peekSigningPubKey());
mSourceAccount.setAccountID(a.getAccountID());
}
int SerializedTransaction::getLength() const
@@ -217,12 +209,25 @@ std::vector<unsigned char>& SerializedTransaction::peekSigningPubKey()
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));
if (!v) throw std::runtime_error("corrupt transaction");
v->setValue(s);
updateSourceAccount();
v->setValue(mSignPubKey.getAccountPublic());
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;
}
@@ -283,3 +288,4 @@ Json::Value SerializedTransaction::getJson(int options) const
ret["Inner"] = mInnerTxn.getJson(options);
return ret;
}
// vim:ts=4

View File

@@ -16,14 +16,13 @@ public:
typedef boost::shared_ptr<SerializedTransaction> pointer;
protected:
NewcoinAddress mSignPubKey;
NewcoinAddress mSourceAccount;
TransactionType mType;
STVariableLength mSignature;
STObject mMiddleTxn, mInnerTxn;
TransactionFormat* mFormat;
void updateSourceAccount();
public:
SerializedTransaction(SerializerIterator& sit, int length); // -1=all remaining, 0=get from sit
SerializedTransaction(TransactionType type);
@@ -55,7 +54,8 @@ public:
std::vector<unsigned char> getSigningPubKey() const;
const std::vector<unsigned char>& peekSigningPubKey() const;
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; }
// inner transaction functions
@@ -116,3 +116,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -5,6 +5,7 @@
#include "SerializedObject.h"
#include "TransactionFormats.h"
#include "NewcoinAddress.h"
#include "utils.h"
std::string SerializedType::getFullText() const
{
@@ -133,18 +134,14 @@ bool STHash256::isEquivalent(const SerializedType& t) const
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;
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);
value = st.getVL();
}
std::string STVariableLength::getText() const
{
return hex(value);
return strHex(value);
}
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 += ",";
ret += hex(it->second);
ret += strHex(it->second);
}
return ret;
}

View File

@@ -247,8 +247,9 @@ protected:
public:
STHash128(const uint128& v=uint128()) : value(v) { ; }
STHash128(const char *n, const uint128& v=uint128()) : SerializedType(n), value(v) { ; }
STHash128(const uint128& v) : value(v) { ; }
STHash128(const char *n, const uint128& v) : SerializedType(n), value(v) { ; }
STHash128(const char *n) : SerializedType(n) { ; }
STHash128() { ; }
static STHash128* construct(SerializerIterator&, const char *name = NULL);
@@ -273,8 +274,9 @@ protected:
public:
STHash160(const uint160& v=uint160()) : value(v) { ; }
STHash160(const char *n, const uint160& v=uint160()) : SerializedType(n), value(v) { ; }
STHash160(const uint160& v) : value(v) { ; }
STHash160(const char *n, const uint160& v) : SerializedType(n), value(v) { ; }
STHash160(const char *n) : SerializedType(n) { ; }
STHash160() { ; }
static STHash160* construct(SerializerIterator&, const char *name = NULL);
@@ -300,7 +302,8 @@ protected:
public:
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() { ; }
static STHash256* construct(SerializerIterator&, const char *name = NULL);
@@ -328,6 +331,7 @@ public:
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) : SerializedType(n) { ; }
STVariableLength(SerializerIterator&, const char *name = NULL);
STVariableLength() { ; }
static STVariableLength* construct(SerializerIterator&, const char *name = NULL);
@@ -406,3 +410,4 @@ public:
};
#endif
// vim:ts=4

View 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

View 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

View File

@@ -81,28 +81,31 @@ int Serializer::addRaw(const void *ptr, int len)
bool Serializer::get16(uint16& o, int offset) const
{
if ((offset + 2) > mData.size()) return false;
o = mData.at(offset++);
o <<= 8; o |= mData.at(offset);
const unsigned char *ptr = &mData[offset];
o = *ptr++; o <<= 8; o |= *ptr;
return true;
}
bool Serializer::get32(uint32& o, int offset) const
{
if ((offset + 4) > mData.size()) return false;
o=mData.at(offset++);
o<<=8; o |= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
o<<=8; o |= mData.at(offset);
const unsigned char *ptr = &mData[offset];
o = *ptr++;
o <<= 8; o |= *ptr++;
o <<= 8; o |= *ptr++;
o <<= 8; o |= *ptr;
return true;
}
bool Serializer::get64(uint64& o, int offset) const
{
if ((offset + 8) > mData.size()) return false;
o=mData.at(offset++);
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
o<<=8; o|= mData.at(offset++); o <<= 8; o |= mData.at(offset++);
o<<=8; o|= mData.at(offset);
const unsigned char *ptr = &mData[offset];
o = *ptr++;
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
o <<= 8; o |= *ptr++; o <<= 8; o |= *ptr++;
o <<= 8; o |= *ptr;
return true;
}
@@ -259,7 +262,7 @@ int Serializer::addVL(const std::vector<unsigned char>& vector)
{
int ret = addRaw(encodeVL(vector.size()));
addRaw(vector);
assert(mData.size() + (ret + vector.size() + encodeLengthLength(vector.size())));
assert(mData.size() == (ret + vector.size() + encodeLengthLength(vector.size())));
return ret;
}
@@ -391,7 +394,7 @@ bool Serializer::getTaggedList(std::list<TaggedListItem>& list, int offset, int&
int startOffset = offset;
int numElem;
if (!get8(numElem, offset++)) return false;
for (int i = 0; i<numElem; i++)
for (int i = 0; i<numElem; ++i)
{
int tag, len;
std::vector<unsigned char> data;
@@ -410,7 +413,7 @@ bool Serializer::getTaggedList(std::vector<TaggedListItem>& list, int offset, in
int startOffset = offset;
int numElem;
if (!get8(numElem, offset++)) return false;
for (int i=0; i<numElem; i++)
for (int i = 0; i<numElem; ++i)
{
int tag, len;
std::vector<unsigned char> data;
@@ -502,7 +505,7 @@ unsigned char SerializerIterator::get8()
{
int val;
if (!mSerializer.get8(val, mPos)) throw std::runtime_error("invalid serializer get8");
mPos++;
++mPos;
return val;
}
@@ -571,3 +574,4 @@ std::vector<TaggedListItem> SerializerIterator::getTaggedList()
mPos += length;
return tl;
}
// vim:ts=4

View File

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

View File

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

View File

@@ -23,7 +23,14 @@ Transaction::Transaction(LocalAccount::pointer fromLocalAccount, const NewcoinAd
mFromPubKey = fromLocalAccount->getPublicKey();
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());
assert(mTransaction->getSequence() != 0);
@@ -105,6 +112,7 @@ Transaction::Transaction(const std::vector<unsigned char>& raw, bool validate) :
mStatus = NEW;
}
#if 0
Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toID,
CKey::pointer pubKey, uint64 amount, uint64 fee, uint32 fromSeq, uint32 fromLedger,
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->setSignature(signature);
mTransaction->setTransactionFee(fee);
mTransaction->setSigningPubKey(pubKey->GetPubKey());
mTransaction->setSigningPubKey(pubKey); // BROKEN
mTransaction->setSourceAccount(mAccountFrom); // BROKEN
mTransaction->setSequence(fromSeq);
if (fromLedger != 0)
{
@@ -129,6 +138,7 @@ Transaction::Transaction(const NewcoinAddress& fromID, const NewcoinAddress& toI
mTransaction->setITFieldAccount(sfDestination, toID.getAccountID());
updateID();
}
#endif
bool Transaction::sign(LocalAccount::pointer fromLocalAccount)
{
@@ -228,7 +238,7 @@ bool Transaction::save() const
ScopedLock sl(theApp->getTxnDB()->getDBLock());
Database* db = theApp->getTxnDB()->getDB();
return db->executeSQL(sql.c_str());
return db->executeSQL(sql);
}
Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
@@ -237,12 +247,11 @@ Transaction::pointer Transaction::transactionFromSQL(const std::string& sql)
std::string status;
rawTxn.reserve(2048);
if(1)
{
ScopedLock sl(theApp->getTxnDB()->getDBLock());
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();
db->getStr("Status", status);
@@ -382,3 +391,4 @@ Json::Value Transaction::getJson(bool decorate, bool paid, bool credited) const
return ret;
}
// vim:ts=4

View File

@@ -6,21 +6,63 @@
TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTransaction& txn,
TransactionEngineParams params)
{
TransactionEngineResult result = terSUCCESS;
uint256 txID = txn.getTransactionID();
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;
if (!acctKey.SetPubKey(txn.peekSigningPubKey())) return terINVALID;
// check signature
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();
if ( (params & tepNO_CHECK_FEE) != tepNONE)
{
if (bPrepaid)
{
if (txnFee)
// Transaction is malformed.
return terINSUF_FEE_P;
}
else
{
// WRITEME: Check if fee is adequate
if (txnFee == 0) return terINSUF_FEE_P;
if (txnFee == 0)
return terINSUF_FEE_P;
}
}
// get source account ID
@@ -30,20 +72,35 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
boost::recursive_mutex::scoped_lock sl(mLedger->mLock);
// find source account
// If we are only verifying some transactions, this would be probablistic.
LedgerStateParms qry = lepNONE;
SerializedLedgerEntry::pointer src = mLedger->getAccountRoot(qry, srcAccount);
if (!src) return terNO_ACCOUNT;
// deduct the fee, so it's not available during the transaction
// we only write the account back if the transaction succeeds
if (txnFee)
{
uint64 balance = src->getIFieldU64(sfBalance);
if (balance < txnFee)
return terINSUF_FEE_B;
src->setIFieldU64(sfBalance, balance - txnFee);
// validate sequence
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
@@ -53,16 +110,21 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
return terPAST_SEQ;
}
else src->setIFieldU32(sfSequence, t_seq);
}
std::vector<AffectedAccount> accounts;
accounts.push_back(std::make_pair(taaMODIFY, src));
TransactionEngineResult result = terUNKNOWN;
switch(txn.getTxnType())
{
case ttINVALID:
result = terINVALID;
break;
case ttCLAIM:
result = doClaim(txn, accounts);
break;
case ttMAKE_PAYMENT:
result = doPayment(txn, accounts);
break;
@@ -85,8 +147,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
// WRITEME: Special case code for changing transaction key
for(std::vector<AffectedAccount>::iterator it=accounts.begin(), end=accounts.end();
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)
assert(false);
@@ -106,6 +172,12 @@ TransactionEngineResult TransactionEngine::applyTransaction(const SerializedTran
return result;
}
TransactionEngineResult TransactionEngine::doClaim(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{
return terUNKNOWN;
}
TransactionEngineResult TransactionEngine::doPayment(const SerializedTransaction& txn,
std::vector<AffectedAccount>& accounts)
{
@@ -187,3 +259,4 @@ TransactionEngineResult TransactionEngine::doDelete(const SerializedTransaction&
{
return terUNKNOWN;
}
// vim:ts=4

View File

@@ -25,6 +25,7 @@ enum TransactionEngineResult
terUNFUNDED, // Source account had insufficient balance for transactin
terNO_PATH, // No path existed or met transaction/balance requirements
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
terPAST_LEDGER, // The transaction expired and can't be applied
};
@@ -51,13 +52,14 @@ class TransactionEngine
protected:
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 doOffer(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doTake(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doCancel(const SerializedTransaction&, std::vector<AffectedAccount>&);
TransactionEngineResult doPayment(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:
TransactionEngine() { ; }
@@ -80,3 +82,4 @@ inline TransactionEngineParams operator&(const TransactionEngineParams& l1, cons
}
#endif
// vim:ts=4

View File

@@ -13,7 +13,14 @@ TransactionFormat InnerTxnFormats[]=
{ S_FIELD(SourceTag), STI_UINT32, SOE_IFFLAG, 2 },
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 4 },
{ 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 } }
},
{ "Invoice", ttINVOICE, {
@@ -25,7 +32,7 @@ TransactionFormat InnerTxnFormats[]=
{ S_FIELD(Destination), STI_ACCOUNT, SOE_IFFLAG, 4 },
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 8 },
{ 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 } }
},
{ "Offer", ttEXCHANGE_OFFER, {
@@ -39,7 +46,7 @@ TransactionFormat InnerTxnFormats[]=
{ S_FIELD(TargetLedger), STI_UINT32, SOE_IFFLAG, 32 },
{ S_FIELD(ExpireLedger), STI_UINT32, SOE_IFFLAG, 64 },
{ 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 } }
},
{ NULL, ttINVALID }
@@ -55,3 +62,4 @@ TransactionFormat* getTxnFormat(TransactionType t)
}
return NULL;
}
// vim:ts=4

View File

@@ -7,8 +7,9 @@ enum TransactionType
{
ttINVALID = -1,
ttMAKE_PAYMENT = 0,
ttINVOICE=1,
ttEXCHANGE_OFFER=2
ttCLAIM = 1,
ttINVOICE = 2,
ttEXCHANGE_OFFER = 3
};
struct TransactionFormat
@@ -18,10 +19,14 @@ struct TransactionFormat
SOElement elements[16];
};
const int32 TransactionMagic=0x54584E00;
const int32 TransactionMagic = 0x54584E00; // 'TXN'
const int TransactionIVersion=0, TransactionISigningPubKey=1, TransactionISequence=2;
const int TransactionIType=3, TransactionIFee=4;
const int TransactionIVersion = 0;
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 TransactionMaxLen=1048576;
@@ -29,3 +34,4 @@ const int TransactionMaxLen=1048576;
extern TransactionFormat InnerTxnFormats[];
extern TransactionFormat* getTxnFormat(TransactionType t);
#endif
// vim:ts=4

View File

@@ -38,3 +38,4 @@ bool TransactionMaster::canonicalize(Transaction::pointer& txn, bool may_be_new)
theApp->getIOService().post(boost::bind(&Transaction::saveTransaction, txn));
return false;
}
// vim:ts=4

View File

@@ -22,3 +22,4 @@ public:
};
#endif
// vim:ts=4

View File

@@ -39,7 +39,7 @@ void ValidationCollection::addToDB(newcoin::Validation& valid,int weCare)
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
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);
db->executeSQL(sql.c_str());
db->executeSQL(sql);
}
@@ -50,11 +50,7 @@ bool ValidationCollection::hasValidation(uint32 ledgerIndex,uint160& hanko,uint3
db->escape(hanko.begin(),hanko.GetSerializeSize(),hankoStr);
string sql=strprintf("SELECT ValidationID,seqnum from Validations where LedgerIndex=%d and hanko=%s",
ledgerIndex,hankoStr.c_str());
if(db->executeSQL(sql.c_str()))
{
if(db->startIterRows())
{
if(db->getNextRow())
if(db->executeSQL(sql) && db->startIterRows())
{
uint32 currentSeqNum=db->getInt(1);
if(currentSeqNum>=seqnum)
@@ -65,9 +61,7 @@ bool ValidationCollection::hasValidation(uint32 ledgerIndex,uint160& hanko,uint3
// 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());
}
}
db->executeSQL(sql);
}
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);
// TODO: ValidationCollection::getValidations(uint32 ledgerIndex)
}
@@ -203,7 +196,6 @@ bool ValidationCollection::getConsensusLedger(uint32 ledgerIndex, uint256& ourHa
bool ret=false;
if(mIndexGroups.count(ledgerIndex))
{
unsigned int maxVotes=theConfig.MIN_VOTES_FOR_CONSENSUS;
vector< Group >& groups=mIndexGroups[ledgerIndex];
Group empty;
@@ -231,3 +223,4 @@ bool ValidationCollection::getConsensusLedger(uint32 ledgerIndex, uint256& ourHa
return(ret);
}
// vim:ts=4

View File

@@ -28,8 +28,8 @@
LocalAccount::LocalAccount(boost::shared_ptr<LocalAccountFamily> family, int familySeq) :
mPublicKey(family->getPublicKey(familySeq)), mFamily(family), mAccountFSeq(familySeq)
{
mAcctID.setAccountPublic(mPublicKey->GetPubKey());
if(theApp!=NULL) mPublicKey = theApp->getPubKeyCache().store(mAcctID, mPublicKey);
mAccount.setAccountPublic(mPublicKey->GetPubKey());
if (theApp != NULL) mPublicKey = theApp->getPubKeyCache().store(mAccount, mPublicKey);
}
std::string LocalAccount::getFullName() const
@@ -52,7 +52,7 @@ std::string LocalAccount::getFamilyName() const
AccountState::pointer LocalAccount::getAccountState() const
{
return theApp->getOPs().getAccountState(mAcctID);
return theApp->getOPs().getAccountState(mAccount);
}
uint64 LocalAccount::getEffectiveBalance() const
@@ -73,12 +73,13 @@ Json::Value LocalAccount::getJson() const
ret["IsLocked"] = mFamily->isLocked();
AccountState::pointer as = getAccountState();
if (!as) ret["Account"] = "None";
if (!as) ret["State"] = "None";
else
{
assert(as->getAccountID().getAccountID() == mAccount.getAccountID());
Json::Value acct(Json::objectValue);
as->addJson(acct);
ret["Account"] = acct;
ret["State"] = acct;
}
return ret;
@@ -190,7 +191,7 @@ LocalAccountFamily::pointer LocalAccountFamily::readFamily(const NewcoinAddress&
ScopedLock sl(theApp->getWalletDB()->getDBLock());
Database *db=theApp->getWalletDB()->getDB();
if(!db->executeSQL(sql.c_str()) || !db->startIterRows() || !db->getNextRow())
if(!db->executeSQL(sql) || !db->startIterRows())
return LocalAccountFamily::pointer();
db->getStr("Comment", comment);
@@ -223,7 +224,7 @@ void LocalAccountFamily::write(bool is_new)
sql.append(");");
ScopedLock sl(theApp->getWalletDB()->getDBLock());
theApp->getWalletDB()->getDB()->executeSQL(sql.c_str());
theApp->getWalletDB()->getDB()->executeSQL(sql);
}
std::string LocalAccountFamily::getSQLFields()
@@ -446,7 +447,7 @@ void Wallet::load()
ScopedLock sl(theApp->getWalletDB()->getDBLock());
Database *db=theApp->getWalletDB()->getDB();
if(!db->executeSQL(sql.c_str()))
if(!db->executeSQL(sql))
{
#ifdef DEBUG
std::cerr << "Unable to load wallet" << std::endl;
@@ -456,8 +457,7 @@ void Wallet::load()
if(!db->startIterRows()) return;
while(db->getNextRow())
{
do {
std::string strGenerator, strComment;
db->getStr("FamilyGenerator", strGenerator);
@@ -476,7 +476,8 @@ void Wallet::load()
f->setComment(strComment);
}
else assert(false);
}
} while(db->getNextRow());
db->endIterRows();
}

View File

@@ -53,8 +53,8 @@ public:
// - Maintain peer connectivity through validation and peer management.
void start();
NewcoinAddress& getNodePublic() { return mNodePublicKey; }
NewcoinAddress& getNodePrivate() { return mNodePrivateKey; }
const NewcoinAddress& getNodePublic() const { return mNodePublicKey; }
const NewcoinAddress& getNodePrivate() const { return mNodePrivateKey; }
DH* getDh512() { return DHparams_dup(mDh512); }
DH* getDh1024() { return DHparams_dup(mDh1024); }

View File

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

View File

@@ -10,7 +10,6 @@ enum MessageType {
mtGET_CONTACTS= 10;
mtCONTACT= 11;
// operations for 'small' nodes
mtSEARCH_TRANSACTION= 20;
mtGET_ACCOUNT= 21;
@@ -22,6 +21,7 @@ enum MessageType {
mtLEDGER= 32;
mtPROPOSE_LEDGER= 33;
mtCLOSE_LEDGER= 35;
mtSTATUS_CHANGE= 36;
// data replication and synchronization
mtGET_VALIDATIONS= 40;
@@ -41,7 +41,8 @@ message TMHello {
optional bytes nodePublic = 4; // node may opt to remain anonymous
optional bytes nodeProof = 5;
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;
}
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 {
required uint32 closingSeq = 1;
required uint32 secondsSinceClose = 2;

View File

@@ -69,7 +69,7 @@ void DH_der_gen_hex(std::string& strDer, int iKeyLength)
DH_der_gen(strBuf, iKeyLength);
strHex(strDer, strBuf);
strDer = strHex(strBuf);
}
DH* DH_der_load(const std::string& strDer)

View File

@@ -36,8 +36,10 @@ std::string strJoin(Iterator first, Iterator last, std::string strSeperator)
char charHex(int iDigit);
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);
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+1] = charHex(c & 15);
}
return strDst;
}
inline void strHex(std::string& strDst, const std::string& strSrc) {
strHex(strDst, strSrc.begin(), strSrc.size());
inline const std::string strHex(const std::string& strSrc) {
return strHex(strSrc.begin(), strSrc.size());
}
inline void strHex(std::string& strDst, const std::vector<unsigned char> vchData) {
strHex(strDst, vchData.begin(), vchData.size());
inline std::string strHex(const std::vector<unsigned char> vchData) {
return strHex(vchData.begin(), vchData.size());
}
int charUnHex(char cDigit);