From 380902536f54a23652d1efb8d8e6f2188d969999 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 16:58:04 -0700 Subject: [PATCH 1/8] Framework for account_tx command. --- src/NetworkOPs.cpp | 8 ++++++ src/NetworkOPs.h | 4 +++ src/RPCServer.cpp | 65 +++++++++++++++++++++++++++++++++++++++++----- src/RPCServer.h | 2 ++ 4 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 85508664fe..624145d92a 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -528,4 +528,12 @@ void NetworkOPs::setMode(OperatingMode om) mMode = om; } +std::vector< std::pair > + NetworkOPs::getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger) +{ + // WRITEME + std::vector< std::pair > affectedAccounts; + return affectedAccounts; +} + // vim:ts=4 diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 005ef02a97..1dddca15e4 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -125,6 +125,10 @@ public: int beginConsensus(Ledger::pointer closingLedger); void endConsensus(); void setStateTimer(int seconds); + + // client information retrieval functions + std::vector< std::pair > + getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger); }; #endif diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 6ba9ad38d4..b09f4d987f 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -319,7 +319,7 @@ Json::Value RPCServer::accountFromString(const uint256& uLedger, NewcoinAddress& naRegular0Public.setAccountPublic(naGenerator, 0); naRegular0Private.setAccountPrivate(naGenerator, naSeed, 0); - uint160 uGeneratorID = naRegular0Public.getAccountID(); +// uint160 uGeneratorID = naRegular0Public.getAccountID(); SLE::pointer sleGen = mNetOps->getGenerator(uLedger, naRegular0Public.getAccountID()); if (!sleGen) { @@ -1145,7 +1145,7 @@ Json::Value RPCServer::doPasswordSet(Json::Value& params) naRegular0Private.setAccountPrivate(naRegularGenerator, naRegularSeed, 0); // Hash of regular account #0 public key. - uint160 uGeneratorID = naRegular0Public.getAccountID(); +// uint160 uGeneratorID = naRegular0Public.getAccountID(); std::vector vucGeneratorCipher = naRegular0Private.accountPrivateEncrypt(naRegular0Public, naMasterGenerator.getFamilyGenerator()); std::vector vucGeneratorSig; @@ -1418,7 +1418,7 @@ Json::Value RPCServer::doLedger(Json::Value& params) { return "invalid params"; } - else if (!mNetOps->available()) + if (!mNetOps->available()) { return JSONRPCError(503, "network not available"); } @@ -1464,6 +1464,59 @@ Json::Value RPCServer::doLedger(Json::Value& params) return ret; } +// account_tx +// account_tx +Json::Value RPCServer::doAccountTransactions(Json::Value& params) +{ + std::string param; + uint32 minLedger, maxLedger; + + if ((params.size() < 2) || (params.size() > 3) || !extractString(param, params, 0)) + return "invalid params"; + + if (!mNetOps->available()) + { + return JSONRPCError(503, "network not available"); + } + + NewcoinAddress account; + if (!account.setAccountID(param)) + return JSONRPCError(500, "invalid account"); + + if (!extractString(param, params, 1)) + minLedger = boost::lexical_cast(param); + + if ((params.size() == 3) && extractString(param, params, 2)) + maxLedger = boost::lexical_cast(param); + else + maxLedger = minLedger; + + if ((maxLedger < minLedger) || (minLedger == 0) || (maxLedger == 0)) + return JSONRPCError(500, "invalid ledger indexes"); + + try + { + std::vector< std::pair > txns = + mNetOps->getAffectedAccounts(account, minLedger, maxLedger); + Json::Value ret(Json::objectValue); + ret["Account"] = account.humanAccountID(); + Json::Value jtxns(Json::arrayValue); + for (std::vector< std::pair >::iterator it = txns.begin(), + end = txns.end(); it != end; ++it) + { + Json::Value txn = it->second->getJson(0); + txn["InLedger"] = it->first; + jtxns.append(txn); + } + ret["Transactions"] = jtxns; + return ret; + } + catch (...) + { + return JSONRPCError(500, "internal error"); + } +} + // unl_add | [] Json::Value RPCServer::doUnlAdd(Json::Value& params) { @@ -2143,13 +2196,13 @@ Json::Value RPCServer::doCommand(const std::string& command, Json::Value& params if (command == "wallet_propose") return doWalletPropose(params); if (command == "wallet_seed") return doWalletSeed(params); - if (command=="ledger") return doLedger(params); - + if (command == "ledger") return doLedger(params); + if (command == "account_tx") return doAccountTransactions(params); // // Obsolete or need rewrite: // - if (command=="tx") return doTx(params); + if (command == "tx") return doTx(params); return "unknown command"; } diff --git a/src/RPCServer.h b/src/RPCServer.h index 4af47f84d4..5a2af47d8c 100644 --- a/src/RPCServer.h +++ b/src/RPCServer.h @@ -91,6 +91,8 @@ private: Json::Value doWalletUnlock(Json::Value& params); Json::Value doWalletVerify(Json::Value& params); + Json::Value doAccountTransactions(Json::Value& params); + void validatorsResponse(const boost::system::error_code& err, std::string strResponse); public: From e2288acfd1100211d3867a32a16b2e8798d474ec Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 17:59:24 -0700 Subject: [PATCH 2/8] More work on account_tx command. --- src/NetworkOPs.cpp | 25 ++++++++++++++++++++++--- src/NetworkOPs.h | 2 +- src/RPCServer.cpp | 33 ++++++++++++++++++++++++++------- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 624145d92a..0e7c6c5ff2 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -528,11 +528,30 @@ void NetworkOPs::setMode(OperatingMode om) mMode = om; } -std::vector< std::pair > +#define SQL_FOREACH(_db, _strQuery) \ + if ((_db)->executeSQL(_strQuery)) \ + for (bool _bMore = (db)->startIterRows(); _bMore; _bMore = (_db)->getNextRow()) + +std::vector< std::pair > NetworkOPs::getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger) { - // WRITEME - std::vector< std::pair > affectedAccounts; + std::vector< std::pair > affectedAccounts; + + std::string sql = + str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex " + " WHERE Account = % AND LedgerSeq <= % AND LedgerSeq >= % ORDER BY LedgerSeq LIMIT 1000") + % account.humanAccountID() % minLedger % maxLedger); + + Database *db = theApp->getAcctTxnDB()->getDB(); + ScopedLock dbLock = theApp->getAcctTxnDB()->getDBLock(); + + SQL_FOREACH(db, sql) + { + std::string txID; + db->getStr("TransID", txID); + affectedAccounts.push_back(std::make_pair(db->getInt("LedgerSeq"), uint256(txID))); + } + return affectedAccounts; } diff --git a/src/NetworkOPs.h b/src/NetworkOPs.h index 1dddca15e4..0514a0902a 100644 --- a/src/NetworkOPs.h +++ b/src/NetworkOPs.h @@ -127,7 +127,7 @@ public: void setStateTimer(int seconds); // client information retrieval functions - std::vector< std::pair > + std::vector< std::pair > getAffectedAccounts(const NewcoinAddress& account, uint32 minLedger, uint32 maxLedger); }; diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index b09f4d987f..49812e0e72 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1496,19 +1496,38 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) try { - std::vector< std::pair > txns = + std::vector< std::pair > txns = mNetOps->getAffectedAccounts(account, minLedger, maxLedger); Json::Value ret(Json::objectValue); ret["Account"] = account.humanAccountID(); - Json::Value jtxns(Json::arrayValue); - for (std::vector< std::pair >::iterator it = txns.begin(), + Json::Value ledgers(Json::arrayValue); + + uint32 currentLedger = 0; + Json::Value ledger, jtxns; + for (std::vector< std::pair >::iterator it = txns.begin(), end = txns.end(); it != end; ++it) { - Json::Value txn = it->second->getJson(0); - txn["InLedger"] = it->first; - jtxns.append(txn); + if (it->first != currentLedger) + { // new ledger + if (currentLedger != 0) // add old ledger + { + ledger["Transactions"] = jtxns; + ledgers.append(ledger); + ledger = Json::objectValue; + } + currentLedger = it->first; + ledger["ID"] = currentLedger; + jtxns = Json::arrayValue; + } + jtxns.append(it->second.GetHex()); } - ret["Transactions"] = jtxns; + if (currentLedger != 0) + { + ledger["Transactions"] = jtxns; + ledgers.append(ledger); + } + + ret["Ledgers"] = ledgers; return ret; } catch (...) From 20499106f045f3963f87a235651989f1ff6e6c73 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:04:44 -0700 Subject: [PATCH 3/8] Bugfixes. --- src/NetworkOPs.cpp | 2 +- src/RPCServer.cpp | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 0e7c6c5ff2..d2e93f926f 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -539,7 +539,7 @@ std::vector< std::pair > std::string sql = str(boost::format("SELECT LedgerSeq,TransID FROM AccountTransactions INDEXED BY AcctTxIndex " - " WHERE Account = % AND LedgerSeq <= % AND LedgerSeq >= % ORDER BY LedgerSeq LIMIT 1000") + " WHERE Account = %s AND LedgerSeq <= %d AND LedgerSeq >= %d ORDER BY LedgerSeq LIMIT 1000") % account.humanAccountID() % minLedger % maxLedger); Database *db = theApp->getAcctTxnDB()->getDB(); diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 49812e0e72..d674254985 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1484,7 +1484,8 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) return JSONRPCError(500, "invalid account"); if (!extractString(param, params, 1)) - minLedger = boost::lexical_cast(param); + return JSONRPCError(500, "invalid ledger index"); + minLedger = boost::lexical_cast(param); if ((params.size() == 3) && extractString(param, params, 2)) maxLedger = boost::lexical_cast(param); @@ -1492,10 +1493,15 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) maxLedger = minLedger; if ((maxLedger < minLedger) || (minLedger == 0) || (maxLedger == 0)) + { + std::cerr << "minL=" << minLedger << ", maxL=" << maxLedger << std::endl; return JSONRPCError(500, "invalid ledger indexes"); + } +#ifndef DEBUG try { +#endif std::vector< std::pair > txns = mNetOps->getAffectedAccounts(account, minLedger, maxLedger); Json::Value ret(Json::objectValue); @@ -1529,11 +1535,13 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) ret["Ledgers"] = ledgers; return ret; +#ifndef DEBUG } catch (...) { return JSONRPCError(500, "internal error"); } +#endif } // unl_add | [] From 9739eea860effcc26178eba1c332f45495045742 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:08:16 -0700 Subject: [PATCH 4/8] More sensible name --- src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Application.cpp b/src/Application.cpp index 5b27580c97..97e0f47d8c 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -61,7 +61,7 @@ void Application::run() // Construct databases. // mTxnDB = new DatabaseCon("transaction.db", TxnDBInit, TxnDBCount); - mAcctTxnDB = new DatabaseCon("transacct.db", AcctTxnDBInit, AcctTxnDBCount); + mAcctTxnDB = new DatabaseCon("accttx.db", AcctTxnDBInit, AcctTxnDBCount); mLedgerDB = new DatabaseCon("ledger.db", LedgerDBInit, LedgerDBCount); mWalletDB = new DatabaseCon("wallet.db", WalletDBInit, WalletDBCount); mHashNodeDB = new DatabaseCon("hashnode.db", HashNodeDBInit, HashNodeDBCount); From 8d8d2c6691ad0ef4d1d96b263179ecb8d53ab5ee Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:14:32 -0700 Subject: [PATCH 5/8] Bugfixes. --- src/LedgerConsensus.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index bd15efe5f9..ea148163e4 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -731,7 +731,7 @@ void LedgerConsensus::accept(SHAMap::pointer set) // Insert the transactions in set into the AcctTxn database Database *db = theApp->getAcctTxnDB()->getDB(); ScopedLock dbLock = theApp->getAcctTxnDB()->getDBLock(); - db->executeSQL("BEGIN TRANSACTION"); + db->executeSQL("BEGIN TRANSACTION;"); for (SHAMapItem::pointer item = set->peekFirstItem(); !!item; item = set->peekNextItem(item->getTag())) { SerializerIterator sit(item->peekSerializer()); @@ -742,19 +742,25 @@ void LedgerConsensus::accept(SHAMap::pointer set) bool first = true; for (std::vector::iterator it = accts.begin(), end = accts.end(); it != end; ++it) { - if (!first) sql += ", ("; - else sql += "("; + if (!first) + sql += ", ("; + else + { + sql += "('"; + first = false; + } sql += txn.getTransactionID().GetHex(); - sql += ","; + sql += "','"; sql += it->humanAccountID(); - sql += ","; + sql += "','"; sql += boost::lexical_cast(newLedgerSeq); - sql += ")"; + sql += "')"; } sql += ";"; + Log(lsTRACE) << "ActTx: " << sql; db->executeSQL(sql); } - db->executeSQL("COMMIT TRANSACTION"); + db->executeSQL("COMMIT TRANSACTION;"); } void LedgerConsensus::endConsensus() From d888cc2da8dbbf267457308b0a053a2e82d3456d Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:28:34 -0700 Subject: [PATCH 6/8] Bugfixes. --- src/DBInit.cpp | 8 +++----- src/LedgerConsensus.cpp | 8 ++++---- src/NetworkOPs.cpp | 4 ++-- src/RPCServer.cpp | 10 ++++------ 4 files changed, 13 insertions(+), 17 deletions(-) diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 470d28fb31..0c9e45ff81 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -24,14 +24,12 @@ int TxnDBCount = sizeof(TxnDBInit) / sizeof(const char *); const char *AcctTxnDBInit[] = { "CREATE TABLE AccountTransactions ( \ - TransID CHARACTER964) PRIMARY KEY \ + TransID CHARACTER(64) PRIMARY KEY, \ Account CHARACTER(64), \ - LedgerSeq BIGINT UNSIGNED, \ + LedgerSeq BIGINT UNSIGNED \ );", "CREATE INDEX AcctTxindex ON \ - AccountTransactions(Account), \ - AccountTransactions(LedgerSeq), \ - AccountTransactions(TransID);" + AccountTransactions(Account, LedgerSeq, TransID);" }; int AcctTxnDBCount = sizeof(AcctTxnDBInit) / sizeof(const char *); diff --git a/src/LedgerConsensus.cpp b/src/LedgerConsensus.cpp index ea148163e4..fa2ecb1896 100644 --- a/src/LedgerConsensus.cpp +++ b/src/LedgerConsensus.cpp @@ -738,12 +738,12 @@ void LedgerConsensus::accept(SHAMap::pointer set) SerializedTransaction txn(sit); std::vector accts = txn.getAffectedAccounts(); - std::string sql = "INSERT INTO AccountTransactions (TransID,Account,LedgerSeq) VALUES "; + std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES "; bool first = true; for (std::vector::iterator it = accts.begin(), end = accts.end(); it != end; ++it) { if (!first) - sql += ", ("; + sql += ", ('"; else { sql += "('"; @@ -752,9 +752,9 @@ void LedgerConsensus::accept(SHAMap::pointer set) sql += txn.getTransactionID().GetHex(); sql += "','"; sql += it->humanAccountID(); - sql += "','"; + sql += "',"; sql += boost::lexical_cast(newLedgerSeq); - sql += "')"; + sql += ")"; } sql += ";"; Log(lsTRACE) << "ActTx: " << sql; diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index d2e93f926f..0efcc2b30b 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -539,8 +539,8 @@ std::vector< std::pair > 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() % minLedger % maxLedger); + " WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' ORDER BY LedgerSeq LIMIT 1000") + % account.humanAccountID() % maxLedger % minLedger); Database *db = theApp->getAcctTxnDB()->getDB(); ScopedLock dbLock = theApp->getAcctTxnDB()->getDBLock(); diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index d674254985..3320ace8c3 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1502,19 +1502,17 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) try { #endif - std::vector< std::pair > txns = - mNetOps->getAffectedAccounts(account, minLedger, maxLedger); + std::vector< std::pair > txns = mNetOps->getAffectedAccounts(account, minLedger, maxLedger); Json::Value ret(Json::objectValue); ret["Account"] = account.humanAccountID(); Json::Value ledgers(Json::arrayValue); uint32 currentLedger = 0; Json::Value ledger, jtxns; - for (std::vector< std::pair >::iterator it = txns.begin(), - end = txns.end(); it != end; ++it) + for (std::vector< std::pair >::iterator it = txns.begin(), end = txns.end(); it != end; ++it) { - if (it->first != currentLedger) - { // new ledger + if (it->first != currentLedger) // different/new ledger + { if (currentLedger != 0) // add old ledger { ledger["Transactions"] = jtxns; From c1c64fe1c733d5cbe3e90df0c9e6993d799ff171 Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:30:01 -0700 Subject: [PATCH 7/8] Fix. --- src/DBInit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DBInit.cpp b/src/DBInit.cpp index 0c9e45ff81..0c4826e943 100644 --- a/src/DBInit.cpp +++ b/src/DBInit.cpp @@ -24,7 +24,7 @@ int TxnDBCount = sizeof(TxnDBInit) / sizeof(const char *); const char *AcctTxnDBInit[] = { "CREATE TABLE AccountTransactions ( \ - TransID CHARACTER(64) PRIMARY KEY, \ + TransID CHARACTER(64), \ Account CHARACTER(64), \ LedgerSeq BIGINT UNSIGNED \ );", From 43d0e8bdb714ca3479675e5ea207347f84c3975f Mon Sep 17 00:00:00 2001 From: JoelKatz Date: Sat, 9 Jun 2012 18:31:15 -0700 Subject: [PATCH 8/8] Cleanup. --- src/RPCServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RPCServer.cpp b/src/RPCServer.cpp index 3320ace8c3..778550827c 100644 --- a/src/RPCServer.cpp +++ b/src/RPCServer.cpp @@ -1520,7 +1520,7 @@ Json::Value RPCServer::doAccountTransactions(Json::Value& params) ledger = Json::objectValue; } currentLedger = it->first; - ledger["ID"] = currentLedger; + ledger["LedgerSeq"] = currentLedger; jtxns = Json::arrayValue; } jtxns.append(it->second.GetHex());