Merge branch 'master' of github.com:jedmccaleb/NewCoin

This commit is contained in:
jed
2012-06-10 05:50:43 -07:00
15 changed files with 717 additions and 613 deletions

View File

@@ -35,16 +35,15 @@ DatabaseCon::~DatabaseCon()
Application::Application() :
mUNL(mIOService),
mNetOps(mIOService, &mMasterLedger), mNodeCache(16384, 600),
mTxnDB(NULL), mAcctTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL),
mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL)
{
RAND_bytes(mNonce256.begin(), mNonce256.size());
RAND_bytes(reinterpret_cast<unsigned char *>(&mNonceST), sizeof(mNonceST));
}
extern const char *AcctTxnDBInit[], *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[],
*HashNodeDBInit[], *NetNodeDBInit[];
extern int TxnDBCount, AcctTxnDBCount, LedgerDBCount, WalletDBCount, HashNodeDBCount, NetNodeDBCount;
extern const char *TxnDBInit[], *LedgerDBInit[], *WalletDBInit[], *HashNodeDBInit[], *NetNodeDBInit[];
extern int TxnDBCount, LedgerDBCount, WalletDBCount, HashNodeDBCount, NetNodeDBCount;
void Application::stop()
{
@@ -61,7 +60,6 @@ void Application::run()
// Construct databases.
//
mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount);
mAcctTxnDB = new DatabaseCon("transacct.db", AcctTxnDBInit, AcctTxnDBCount);
mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount);
mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount);
mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount);
@@ -140,7 +138,6 @@ void Application::run()
Application::~Application()
{
delete mTxnDB;
delete mAcctTxnDB;
delete mLedgerDB;
delete mWalletDB;
delete mHashNodeDB;

View File

@@ -45,7 +45,7 @@ class Application
NetworkOPs mNetOps;
NodeCache mNodeCache;
DatabaseCon *mTxnDB, *mAcctTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
DatabaseCon *mTxnDB, *mLedgerDB, *mWalletDB, *mHashNodeDB, *mNetNodeDB;
ConnectionPool mConnectionPool;
PeerDoor* mPeerDoor;
@@ -76,7 +76,6 @@ public:
NodeCache& getNodeCache() { return mNodeCache; }
DatabaseCon* getTxnDB() { return mTxnDB; }
DatabaseCon* getAcctTxnDB() { return mAcctTxnDB; }
DatabaseCon* getLedgerDB() { return mLedgerDB; }
DatabaseCon* getWalletDB() { return mWalletDB; }
DatabaseCon* getHashNodeDB() { return mHashNodeDB; }

View File

@@ -7,35 +7,25 @@ const char *TxnDBInit[] = {
TransType CHARACTER(24) \
FromAcct CHARACTER(35), \
FromSeq BIGINT UNSIGNED, \
OtherAcct CHARACTER(40), \
Amount BIGINT UNSIGNED, \
FirstSeen TEXT, \
CommitSeq BIGINT UNSIGNED, \
LedgerSeq BIGINT UNSIGNED, \
Status CHARACTER(1), \
RawTxn BLOB \
);",
"CREATE TABLE PubKeys ( \
ID CHARACTER(35) PRIMARY KEY, \
PubKey BLOB \
);"
);",
"CREATE TABLE AccountTransactions ( \
TransID CHARACTER(64), \
Account CHARACTER(64), \
LedgerSeq BIGINT UNSIGNED \
);",
"CREATE INDEX AcctTxindex ON \
AccountTransactions(Account, LedgerSeq, TransID);"
};
int TxnDBCount = sizeof(TxnDBInit) / sizeof(const char *);
const char *AcctTxnDBInit[] = {
"CREATE TABLE AccountTransactions ( \
TransID CHARACTER964) PRIMARY KEY \
Account CHARACTER(64), \
LedgerSeq BIGINT UNSIGNED, \
);",
"CREATE INDEX AcctTxindex ON \
AccountTransactions(Account), \
AccountTransactions(LedgerSeq), \
AccountTransactions(TransID);"
};
int AcctTxnDBCount = sizeof(AcctTxnDBInit) / sizeof(const char *);
// Ledger database holds ledgers and ledger confirmations
const char *LedgerDBInit[] = {
"CREATE TABLE Ledgers ( \

View File

@@ -16,6 +16,7 @@
#include "Wallet.h"
#include "BinaryFormats.h"
#include "LedgerTiming.h"
#include "Log.h"
Ledger::Ledger(const NewcoinAddress& masterID, uint64 startAmount) : mTotCoins(startAmount),
mCloseTime(0), mLedgerSeq(0), mLedgerInterval(LEDGER_INTERVAL), mClosed(false), mValidHash(false),
@@ -261,6 +262,41 @@ void Ledger::saveAcceptedLedger(Ledger::pointer ledger)
while(ledger->mAccountStateMap->flushDirty(64, ACCOUNT_NODE, ledger->mLedgerSeq))
{ ; }
SHAMap& txSet = *ledger->peekTransactionMap();
Database *db = theApp->getTxnDB()->getDB();
ScopedLock dbLock = theApp->getTxnDB()->getDBLock();
db->executeSQL("BEGIN TRANSACTION;");
for (SHAMapItem::pointer item = txSet.peekFirstItem(); !!item; item = txSet.peekNextItem(item->getTag()))
{
SerializerIterator sit(item->peekSerializer());
SerializedTransaction txn(sit);
std::vector<NewcoinAddress> accts = txn.getAffectedAccounts();
std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES ";
bool first = true;
for (std::vector<NewcoinAddress>::iterator it = accts.begin(), end = accts.end(); it != end; ++it)
{
if (!first)
sql += ", ('";
else
{
sql += "('";
first = false;
}
sql += txn.getTransactionID().GetHex();
sql += "','";
sql += it->humanAccountID();
sql += "',";
sql += boost::lexical_cast<std::string>(ledger->getLedgerSeq());
sql += ")";
}
sql += ";";
Log(lsTRACE) << "ActTx: " << sql;
db->executeSQL(sql);
db->executeSQL(txn.getSQLInsertHeader() + txn.getSQL(ledger->getLedgerSeq(), TXN_SQL_VALIDATED) + ";");
// FIXME: If above updates no rows, modify seq/status
}
db->executeSQL("COMMIT TRANSACTION;");
}
Ledger::pointer Ledger::getSQL(const std::string& sql)
@@ -365,7 +401,8 @@ void Ledger::addJson(Json::Value& ret, int options)
SerializedLedgerEntry sle(sit, item->getTag());
state.append(sle.getJson(0));
}
else state.append(item->getTag().GetHex());
else
state.append(item->getTag().GetHex());
}
ledger["AccountState"] = state;
}

View File

@@ -654,7 +654,6 @@ void LedgerConsensus::accept(SHAMap::pointer set)
Log(lsDEBUG) << "Previous LCL " << mPreviousLedger->getHash().GetHex();
Ledger::pointer newLCL = boost::make_shared<Ledger>(false, boost::ref(*mPreviousLedger));
uint32 newLedgerSeq = newLCL->getLedgerSeq();
#ifdef DEBUG
Json::StyledStreamWriter ssw;
@@ -727,34 +726,6 @@ void LedgerConsensus::accept(SHAMap::pointer set)
theApp->getConnectionPool().relayMessage(NULL, boost::make_shared<PackedMessage>(val, newcoin::mtVALIDATION));
Log(lsINFO) << "Validation sent " << newLCL->getHash().GetHex();
statusChange(newcoin::neACCEPTED_LEDGER, newOL);
// Insert the transactions in set into the AcctTxn database
Database *db = theApp->getAcctTxnDB()->getDB();
ScopedLock dbLock = theApp->getAcctTxnDB()->getDBLock();
db->executeSQL("BEGIN TRANSACTION");
for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag()))
{
SerializerIterator sit(item->peekSerializer());
SerializedTransaction txn(sit);
std::vector<NewcoinAddress> accts = txn.getAffectedAccounts();
std::string sql = "INSERT INTO AccountTransactions (TransID,Account,LedgerSeq) VALUES ";
bool first = true;
for (std::vector<NewcoinAddress>::iterator it = accts.begin(), end = accts.end(); it != end; ++it)
{
if (!first) sql += ", (";
else sql += "(";
sql += txn.getTransactionID().GetHex();
sql += ",";
sql += it->humanAccountID();
sql += ",";
sql += boost::lexical_cast<std::string>(newLedgerSeq);
sql += ")";
}
sql += ";";
db->executeSQL(sql);
}
db->executeSQL("COMMIT TRANSACTION");
}
void LedgerConsensus::endConsensus()

View File

@@ -18,16 +18,16 @@ enum LedgerEntryType
// Used as a prefix for computing ledger indexes (keys).
enum LedgerNameSpace
{
spaceAccount,
spaceGenerator,
spaceNickname,
spaceRipple,
spaceRippleDir,
spaceOffer,
spaceOfferDir,
spaceBond,
spaceInvoice,
spaceMultiSig,
spaceAccount = 0,
spaceGenerator = 1,
spaceNickname = 2,
spaceRipple = 3,
spaceRippleDir = 4,
spaceOffer = 5,
spaceOfferDir = 6,
spaceBond = 7,
spaceInvoice = 8,
spaceMultiSig = 9,
};
enum LedgerSpecificFlags

View File

@@ -2,6 +2,7 @@
#include <string>
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include "LedgerHistory.h"
#include "Config.h"
@@ -32,7 +33,8 @@ void LedgerHistory::addAcceptedLedger(Ledger::pointer ledger)
boost::recursive_mutex::scoped_lock sl(mLedgersByHash.peekMutex());
mLedgersByHash.canonicalize(h, ledger);
mLedgersByIndex.insert(std::make_pair(ledger->getLedgerSeq(), ledger));
theApp->getIOService().post(boost::bind(&Ledger::saveAcceptedLedger, ledger));
boost::thread thread(boost::bind(&Ledger::saveAcceptedLedger, ledger));
thread.detach();
}
Ledger::pointer LedgerHistory::getLedgerBySeq(uint32 index)

View File

@@ -528,4 +528,31 @@ void NetworkOPs::setMode(OperatingMode om)
mMode = om;
}
#define SQL_FOREACH(_db, _strQuery) \
if ((_db)->executeSQL(_strQuery)) \
for (bool _bMore = (db)->startIterRows(); _bMore; _bMore = (_db)->getNextRow())
std::vector< std::pair<uint32, uint256> >
NetworkOPs::getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger)
{
std::vector< std::pair<uint32, uint256> > affectedAccounts;
std::string sql =
str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex "
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ORDER BY LedgerSeq LIMIT 1000")
% account.humanAccountID() % maxLedger % minLedger);
Database *db = theApp->getTxnDB()->getDB();
ScopedLock dbLock = theApp->getTxnDB()->getDBLock();
SQL_FOREACH(db, sql)
{
std::string txID;
db->getStr("TransID", txID);
affectedAccounts.push_back(std::make_pair<uint32, uint256>(db->getInt("LedgerSeq"), uint256(txID)));
}
return affectedAccounts;
}
// vim:ts=4

View File

@@ -125,6 +125,10 @@ public:
int beginConsensus(Ledger::pointer closingLedger);
void endConsensus();
void setStateTimer(int seconds);
// client information retrieval functions
std::vector< std::pair<uint32, uint256> >
getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,65 @@
class RPCServer : public boost::enable_shared_from_this<RPCServer>
{
public:
enum {
rpcSUCCESS,
// Networking
rpcNO_CLOSED,
rpcNO_CURRENT,
rpcNO_NETWORK,
// Ledger state
rpcACT_EXISTS,
rpcACT_NOT_FOUND,
rpcINSUF_FUNDS,
rpcLGR_NOT_FOUND,
rpcMUST_SEND_XNS,
rpcNICKNAME_MISSING,
rpcPASSWD_CHANGED,
rpcSRC_MISSING,
rpcSRC_UNCLAIMED,
rpcTXN_NOT_FOUND,
rpcWRONG_PASSWORD,
rpcWRONG_SEED,
// Malformed command
rpcINVALID_PARAMS,
rpcUNKNOWN_COMMAND,
// Bad paramater
rpcACT_MALFORMED,
rpcBAD_SEED,
rpcDST_ACT_MALFORMED,
rpcDST_AMT_MALFORMED,
rpcHOST_IP_MALFORMED,
rpcLGR_IDXS_INVALID,
rpcLGR_IDX_MALFORMED,
rpcNICKNAME_MALFORMED,
rpcNICKNAME_PERM,
rpcPORT_MALFORMED,
rpcPUBLIC_MALFORMED,
rpcSRC_ACT_MALFORMED,
rpcSRC_AMT_MALFORMED,
// Internal error (should never happen)
rpcINTERNAL, // Generic internal error.
rpcFAIL_GEN_DECRPYT,
rpcNOT_IMPL,
rpcNO_GEN_DECRPYT,
};
Json::Value RPCError(int iError);
private:
typedef Json::Value (RPCServer::*doFuncPtr)(Json::Value &params);
enum {
optNetwork = 1, // Need network
optCurrent = 2+optNetwork, // Need current ledger
optClosed = 4+optNetwork, // Need closed ledger
};
NetworkOPs* mNetOps;
boost::asio::ip::tcp::socket mSocket;
@@ -52,6 +110,7 @@ private:
Json::Value doAccountInfo(Json::Value& params);
Json::Value doAccountLines(Json::Value &params);
Json::Value doAccountMessageSet(Json::Value &params);
Json::Value doAccountTransactions(Json::Value& params);
Json::Value doAccountWalletSet(Json::Value &params);
Json::Value doConnect(Json::Value& params);
Json::Value doCreditSet(Json::Value& params);

View File

@@ -1,5 +1,6 @@
#include "SerializedTransaction.h"
#include "Application.h"
#include "Log.h"
@@ -85,8 +86,22 @@ std::vector<NewcoinAddress> SerializedTransaction::getAffectedAccounts() const
end = mInnerTxn.peekData().end(); it != end ; ++it)
{
const STAccount* sa = dynamic_cast<const STAccount*>(&*it);
if (sa != NULL) // FIXME: Should we check for duplicates?
accounts.push_back(sa->getValueNCA());
if (sa != NULL)
{
bool found = false;
NewcoinAddress na = sa->getValueNCA();
for (std::vector<NewcoinAddress>::iterator it = accounts.begin(), end = accounts.end();
it != end; ++it)
{
if (*it == na)
{
found = true;
break;
}
}
if (!found)
accounts.push_back(na);
}
}
return accounts;
}
@@ -283,4 +298,33 @@ Json::Value SerializedTransaction::getJson(int options) const
ret["Inner"] = mInnerTxn.getJson(options);
return ret;
}
std::string SerializedTransaction::getSQLValueHeader()
{
return "(TransID, TransType, FromAcct, FromSeq, CommitSeq, Status, RawTxn)";
}
std::string SerializedTransaction::getSQLInsertHeader()
{
return "INSERT INTO Transactions " + getSQLValueHeader() + " VALUES ";
}
std::string SerializedTransaction::getSQL(uint32 inLedger, char status) const
{
Serializer s;
add(s);
return getSQL(s, inLedger, status);
}
std::string SerializedTransaction::getSQL(Serializer rawTxn, uint32 inLedger, char status) const
{
std::string rTxn;
theApp->getTxnDB()->getDB()->escape(
reinterpret_cast<const unsigned char *>(rawTxn.getDataPtr()), rawTxn.getLength(), rTxn);
return str(boost::format("('%s', '%s', '%s', %d, %d, %c, '%s')")
% getTransactionID().GetHex() % getTransactionType() % getSourceAccount().humanAccountID()
% getSequence() % inLedger % status % rTxn);
}
// vim:ts=4

View File

@@ -10,6 +10,11 @@
#include "TransactionFormats.h"
#include "NewcoinAddress.h"
#define TXN_SQL_NEW 'N'
#define TXN_SQL_CONFLICT 'C'
#define TXN_SQL_HELD 'H'
#define TXN_SQL_VALIDATED 'V'
class SerializedTransaction : public SerializedType
{
public:
@@ -116,6 +121,14 @@ public:
bool sign(const NewcoinAddress& naAccountPrivate);
bool checkSign(const NewcoinAddress& naAccountPublic) const;
// SQL Functions
static std::string getSQLValueHeader();
static std::string getSQLInsertHeader();
std::string getSQL(std::string& sql, uint32 inLedger, char status) const;
std::string getSQL(uint32 inLedger, char status) const;
std::string getSQL(Serializer rawTxn, uint32 inLedger, char status) const;
};
#endif

View File

@@ -510,6 +510,7 @@ void Transaction::saveTransaction(Transaction::pointer txn)
bool Transaction::save() const
{ // This code needs to be fixed to support new-style transactions - FIXME
// This code is going away. It will be handled from SerializedTransaction
#if 0
// Identify minimums fields to write for now.
// Also maybe write effected accounts for use later.

View File

@@ -9,7 +9,8 @@
#include "types.h"
#define nothing() do {} while (0)
#define fallthru() do {} while (0)
#define fallthru() do {} while (0)
#define NUMBER(x) (sizeof(x)/sizeof((x)[0]))
#ifndef MAX
#define MAX(x,y) ((x) < (y) ? (y) : (x))