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

This commit is contained in:
Arthur Britto
2013-02-25 22:32:19 -08:00
12 changed files with 174 additions and 41 deletions

View File

@@ -100,19 +100,29 @@ Json::Value RPCParser::parseAccountInfo(const Json::Value& jvParams)
// account_tx <account> <minledger> <maxledger> // account_tx <account> <minledger> <maxledger>
// account_tx <account> <ledger> // account_tx <account> <ledger>
// account_tx <account> binary
// account_tx <account> <minledger> <maxledger> binary
Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams) Json::Value RPCParser::parseAccountTransactions(const Json::Value& jvParams)
{ {
Json::Value jvRequest(Json::objectValue); Json::Value jvRequest(Json::objectValue);
RippleAddress raAccount; RippleAddress raAccount;
if (jvParams.size() < 2 || jvParams.size() > 3) unsigned size = jvParams.size();
if ((size > 1) && (jvParams[size - 1].asString() == "binary"))
{
jvRequest["binary"] = true;
--size;
}
if (size < 2 || size > 3)
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
if (!raAccount.setAccountID(jvParams[0u].asString())) if (!raAccount.setAccountID(jvParams[0u].asString()))
return rpcError(rpcACT_MALFORMED); return rpcError(rpcACT_MALFORMED);
// YYY This could be more strict and report casting errors. // YYY This could be more strict and report casting errors.
if (jvParams.size() == 2) if (size == 2)
{ {
jvRequest["ledger"] = jvParams[1u].asUInt(); jvRequest["ledger"] = jvParams[1u].asUInt();
} }
@@ -365,8 +375,14 @@ Json::Value RPCParser::parseTx(const Json::Value& jvParams)
{ {
Json::Value jvRequest; Json::Value jvRequest;
if (jvParams.size() > 1)
{
if (jvParams[1u].asString() == "binary")
jvRequest["binary"] = true;
}
jvRequest["transaction"] = jvParams[0u].asString(); jvRequest["transaction"] = jvParams[0u].asString();
return jvRequest; return jvRequest;
} }
// tx_history <index> // tx_history <index>
@@ -497,7 +513,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{ "account_info", &RPCParser::parseAccountInfo, 1, 2 }, { "account_info", &RPCParser::parseAccountInfo, 1, 2 },
{ "account_lines", &RPCParser::parseAccountItems, 1, 2 }, { "account_lines", &RPCParser::parseAccountItems, 1, 2 },
{ "account_offers", &RPCParser::parseAccountItems, 1, 2 }, { "account_offers", &RPCParser::parseAccountItems, 1, 2 },
{ "account_tx", &RPCParser::parseAccountTransactions, 2, 3 }, { "account_tx", &RPCParser::parseAccountTransactions, 2, 4 },
{ "connect", &RPCParser::parseConnect, 1, 2 }, { "connect", &RPCParser::parseConnect, 1, 2 },
{ "consensus_info", &RPCParser::parseAsIs, 0, 0 }, { "consensus_info", &RPCParser::parseAsIs, 0, 0 },
{ "get_counts", &RPCParser::parseGetCounts, 0, 1 }, { "get_counts", &RPCParser::parseGetCounts, 0, 1 },
@@ -522,7 +538,7 @@ Json::Value RPCParser::parseCommand(std::string strMethod, Json::Value jvParams)
{ "server_state", &RPCParser::parseAsIs, 0, 0 }, { "server_state", &RPCParser::parseAsIs, 0, 0 },
{ "stop", &RPCParser::parseAsIs, 0, 0 }, { "stop", &RPCParser::parseAsIs, 0, 0 },
// { "transaction_entry", &RPCParser::parseTransactionEntry, -1, -1 }, // { "transaction_entry", &RPCParser::parseTransactionEntry, -1, -1 },
{ "tx", &RPCParser::parseTx, 1, 1 }, { "tx", &RPCParser::parseTx, 1, 2 },
{ "tx_history", &RPCParser::parseTxHistory, 1, 1 }, { "tx_history", &RPCParser::parseTxHistory, 1, 1 },
{ "unl_add", &RPCParser::parseUnlAdd, 1, 2 }, { "unl_add", &RPCParser::parseUnlAdd, 1, 2 },

View File

@@ -377,6 +377,22 @@ bool Ledger::getTransactionMeta(const uint256& txID, TransactionMetaSet::pointer
return true; return true;
} }
bool Ledger::getMetaHex(const uint256& transID, std::string& hex)
{
SHAMapTreeNode::TNType type;
SHAMapItem::pointer item = mTransactionMap->peekItem(transID, type);
if (!item)
return false;
if (type != SHAMapTreeNode::tnTRANSACTION_MD)
return false;
SerializerIterator it(item->peekSerializer());
it.getVL(); // skip transaction
hex = strHex(it.getVL());
return true;
}
uint256 Ledger::getHash() uint256 Ledger::getHash()
{ {
if (!mValidHash) if (!mValidHash)

View File

@@ -184,6 +184,7 @@ public:
Transaction::pointer getTransaction(const uint256& transID) const; Transaction::pointer getTransaction(const uint256& transID) const;
bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta); bool getTransaction(const uint256& transID, Transaction::pointer& txn, TransactionMetaSet::pointer& txMeta);
bool getTransactionMeta(const uint256& transID, TransactionMetaSet::pointer& txMeta); bool getTransactionMeta(const uint256& transID, TransactionMetaSet::pointer& txMeta);
bool getMetaHex(const uint256& transID, std::string& hex);
static SerializedTransaction::pointer getSTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType); static SerializedTransaction::pointer getSTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType);
SerializedTransaction::pointer getSMTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType, SerializedTransaction::pointer getSMTransaction(SHAMapItem::ref, SHAMapTreeNode::TNType,

View File

@@ -728,7 +728,7 @@ void LedgerConsensus::updateOurPositions()
cLog(lsWARNING) << "Removing stale proposal from " << peerID; cLog(lsWARNING) << "Removing stale proposal from " << peerID;
BOOST_FOREACH(u256_lct_pair& it, mDisputes) BOOST_FOREACH(u256_lct_pair& it, mDisputes)
it.second->unVote(peerID); it.second->unVote(peerID);
mPeerPositions.erase(it++); it = mPeerPositions.erase(it);
} }
else else
{ // proposal is still fresh { // proposal is still fresh

View File

@@ -1085,6 +1085,52 @@ std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
return ret; return ret;
} }
std::vector<NetworkOPs::txnMetaLedgerType> NetworkOPs::getAccountTxsB(
const RippleAddress& account, uint32 minLedger, uint32 maxLedger)
{ // can be called with no locks
std::vector< txnMetaLedgerType> ret;
std::string sql =
str(boost::format("SELECT LedgerSeq, RawTxn,TxnMeta FROM Transactions where TransID in (SELECT TransID from AccountTransactions "
" WHERE Account = '%s' AND LedgerSeq <= '%d' AND LedgerSeq >= '%d' LIMIT 500) ORDER BY LedgerSeq DESC;")
% account.humanAccountID() % maxLedger % minLedger);
{
Database* db = theApp->getTxnDB()->getDB();
ScopedLock sl(theApp->getTxnDB()->getDBLock());
SQL_FOREACH(db, sql)
{
int txnSize = 2048;
std::vector<unsigned char> rawTxn(txnSize);
txnSize = db->getBinary("RawTxn", &rawTxn[0], rawTxn.size());
if (txnSize > rawTxn.size())
{
rawTxn.resize(txnSize);
db->getBinary("RawTxn", &*rawTxn.begin(), rawTxn.size());
}
else
rawTxn.resize(txnSize);
int metaSize = 2048;
std::vector<unsigned char> rawMeta(2048);
metaSize = db->getBinary("TxnMeta", &rawMeta[0], rawMeta.size());
if (metaSize > rawMeta.size())
{
rawMeta.resize(metaSize);
db->getBinary("TxnMeta", &*rawMeta.begin(), rawMeta.size());
}
else
rawMeta.resize(metaSize);
ret.push_back(boost::make_tuple(strHex(rawTxn), strHex(rawMeta), db->getInt("LedgerSeq")));
}
}
return ret;
}
std::vector<RippleAddress> std::vector<RippleAddress>
NetworkOPs::getLedgerAffectedAccounts(uint32 ledgerSeq) NetworkOPs::getLedgerAffectedAccounts(uint32 ledgerSeq)
{ {

View File

@@ -4,6 +4,7 @@
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/recursive_mutex.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <boost/unordered_set.hpp> #include <boost/unordered_set.hpp>
#include <boost/tuple/tuple.hpp>
#include "AccountState.h" #include "AccountState.h"
#include "LedgerMaster.h" #include "LedgerMaster.h"
@@ -273,6 +274,11 @@ public:
// client information retrieval functions // client information retrieval functions
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >
getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger); getAccountTxs(const RippleAddress& account, uint32 minLedger, uint32 maxLedger);
typedef boost::tuple<std::string, std::string, uint32> txnMetaLedgerType;
std::vector<txnMetaLedgerType>
getAccountTxsB(const RippleAddress& account, uint32 minL, uint32 maxL);
std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq); std::vector<RippleAddress> getLedgerAffectedAccounts(uint32 ledgerSeq);
std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq); std::vector<SerializedTransaction> getLedgerTransactions(uint32 ledgerSeq);

View File

@@ -1433,6 +1433,8 @@ Json::Value RPCHandler::doTx(Json::Value jvRequest)
if (!jvRequest.isMember("transaction")) if (!jvRequest.isMember("transaction"))
return rpcError(rpcINVALID_PARAMS); return rpcError(rpcINVALID_PARAMS);
bool binary = jvRequest.isMember("binary") && jvRequest["binary"].asBool();
std::string strTransaction = jvRequest["transaction"].asString(); std::string strTransaction = jvRequest["transaction"].asString();
if (Transaction::isHexTxID(strTransaction)) if (Transaction::isHexTxID(strTransaction))
@@ -1441,21 +1443,42 @@ Json::Value RPCHandler::doTx(Json::Value jvRequest)
Transaction::pointer txn = theApp->getMasterTransaction().fetch(txid, true); Transaction::pointer txn = theApp->getMasterTransaction().fetch(txid, true);
if (!txn) return rpcError(rpcTXN_NOT_FOUND); if (!txn)
return rpcError(rpcTXN_NOT_FOUND);
Json::Value ret = txn->getJson(0); #ifdef READY_FOR_NEW_TX_FORMAT
Json::Value ret;
ret["transaction"] = txn->getJson(0, binary);
#else
Json::Value ret = txn->getJson(0, binary);
#endif
if (txn->getLedger() != 0) if (txn->getLedger() != 0)
{ {
Ledger::pointer lgr = theApp->getLedgerMaster().getLedgerBySeq(txn->getLedger()); Ledger::pointer lgr = theApp->getLedgerMaster().getLedgerBySeq(txn->getLedger());
if (lgr) if (lgr)
{ {
TransactionMetaSet::pointer set; bool okay = false;
if (lgr->getTransactionMeta(txid, set)) if (binary)
{ {
ret["meta"] = set->getJson(0); std::string meta;
ret["validated"] = theApp->getOPs().isValidated(lgr); if (lgr->getMetaHex(txid, meta))
{
ret["meta"] = meta;
okay = true;
}
} }
else
{
TransactionMetaSet::pointer set;
if (lgr->getTransactionMeta(txid, set))
{
okay = true;
ret["meta"] = set->getJson(0);
}
}
if (okay)
ret["validated"] = theApp->getOPs().isValidated(lgr);
} }
} }
@@ -1576,29 +1599,49 @@ Json::Value RPCHandler::doAccountTransactions(Json::Value jvRequest)
int vl = theApp->getOPs().getValidatedSeq(); int vl = theApp->getOPs().getValidatedSeq();
ScopedUnlock su(theApp->getMasterLock()); ScopedUnlock su(theApp->getMasterLock());
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs(raAccount, minLedger, maxLedger);
Json::Value ret(Json::objectValue); Json::Value ret(Json::objectValue);
ret["account"] = raAccount.humanAccountID(); ret["account"] = raAccount.humanAccountID();
Json::Value ledgers(Json::arrayValue);
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin(), end = txns.end(); it != end; ++it) if (jvRequest.isMember("binary") && jvRequest["binary"].asBool())
{ {
Json::Value obj(Json::objectValue); std::vector<NetworkOPs::txnMetaLedgerType> txns =
mNetOps->getAccountTxsB(raAccount, minLedger, maxLedger);
if (it->first) for (std::vector<NetworkOPs::txnMetaLedgerType>::const_iterator it = txns.begin(), end = txns.end();
obj["tx"] = it->first->getJson(1); it != end; ++it)
if (it->second)
{ {
obj["meta"] = it->second->getJson(0); Json::Value obj(Json::objectValue);
obj["transaction"] = it->get<0>();
uint32 s = it->second->getLgrSeq(); obj["meta"] = it->get<1>();
if (s > vl) obj["inLedger"] = it->get<2>();
if (it->get<2>() > vl)
obj["validated"] = false; obj["validated"] = false;
else if (theApp->getOPs().haveLedger(s)) else if (theApp->getOPs().haveLedger(it->get<2>()))
obj["validated"] = true; obj["validated"] = true;
ret["transactions"].append(obj);
} }
}
else
{
std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> > txns = mNetOps->getAccountTxs(raAccount, minLedger, maxLedger);
for (std::vector< std::pair<Transaction::pointer, TransactionMetaSet::pointer> >::iterator it = txns.begin(), end = txns.end(); it != end; ++it)
{
Json::Value obj(Json::objectValue);
ret["transactions"].append(obj); if (it->first)
obj["tx"] = it->first->getJson(1);
if (it->second)
{
obj["meta"] = it->second->getJson(0);
uint32 s = it->second->getLgrSeq();
if (s > vl)
obj["validated"] = false;
else if (theApp->getOPs().haveLedger(s))
obj["validated"] = true;
}
ret["transactions"].append(obj);
}
} }
return ret; return ret;
#ifndef DEBUG #ifndef DEBUG

View File

@@ -190,12 +190,19 @@ void SerializedTransaction::setSourceAccount(const RippleAddress& naSource)
setFieldAccount(sfAccount, naSource); setFieldAccount(sfAccount, naSource);
} }
Json::Value SerializedTransaction::getJson(int options) const Json::Value SerializedTransaction::getJson(int options, bool binary) const
{ {
if (binary)
{
Json::Value ret;
Serializer s = STObject::getSerializer();
ret["tx"] = strHex(s.peekData());
ret["hash"] = getTransactionID().GetHex();
return ret;
}
Json::Value ret = STObject::getJson(0); Json::Value ret = STObject::getJson(0);
ret["hash"] = getTransactionID().GetHex(); ret["hash"] = getTransactionID().GetHex();
return ret; return ret;
} }

View File

@@ -64,7 +64,7 @@ public:
uint256 getTransactionID() const; uint256 getTransactionID() const;
virtual Json::Value getJson(int options) const; virtual Json::Value getJson(int options, bool binary = false) const;
void sign(const RippleAddress& naAccountPrivate); void sign(const RippleAddress& naAccountPrivate);
bool checkSign(const RippleAddress& naAccountPublic) const; bool checkSign(const RippleAddress& naAccountPublic) const;

View File

@@ -56,7 +56,7 @@ protected:
mutable boost::recursive_mutex mLock; mutable boost::recursive_mutex mLock;
std::string mName; // Used for logging std::string mName; // Used for logging
int mTargetSize; // Desired number of cache entries (0 = ignore) int mTargetSize; // Desired number of cache entries (0 = ignore)
int mTargetAge; // Desired maximum cache age int mTargetAge; // Desired maximum cache age
int mCacheCount; // Number of items cached int mCacheCount; // Number of items cached
@@ -152,7 +152,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
if (cit->second.isExpired()) if (cit->second.isExpired())
{ {
++mapRemovals; ++mapRemovals;
mCache.erase(cit++); cit = mCache.erase(cit);
} }
else else
++cit; ++cit;
@@ -165,7 +165,7 @@ template<typename c_Key, typename c_Data> void TaggedCache<c_Key, c_Data>::sweep
if (cit->second.isExpired()) if (cit->second.isExpired())
{ {
++mapRemovals; ++mapRemovals;
mCache.erase(cit++); cit = mCache.erase(cit);
} }
else // remains weakly cached else // remains weakly cached
++cit; ++cit;

View File

@@ -299,22 +299,20 @@ bool Transaction::convertToTransactions(uint32 firstLedgerSeq, uint32 secondLedg
} }
// options 1 to include the date of the transaction // options 1 to include the date of the transaction
Json::Value Transaction::getJson(int options) const Json::Value Transaction::getJson(int options, bool binary) const
{ {
Json::Value ret(mTransaction->getJson(0)); Json::Value ret(mTransaction->getJson(0, binary));
if (mInLedger) if (mInLedger)
{ {
ret["inLedger"]=mInLedger; ret["inLedger"] = mInLedger;
if(options==1) if(options == 1)
{ {
Ledger::pointer ledger=theApp->getLedgerMaster().getLedgerBySeq(mInLedger); Ledger::pointer ledger=theApp->getLedgerMaster().getLedgerBySeq(mInLedger);
if(ledger) if(ledger)
{ ret["date"] = ledger->getCloseTimeNC();
ret["date"]=ledger->getCloseTimeNC();
}
} }
} }

View File

@@ -113,7 +113,7 @@ public:
bool operator<=(const Transaction&) const; bool operator<=(const Transaction&) const;
bool operator>=(const Transaction&) const; bool operator>=(const Transaction&) const;
Json::Value getJson(int options) const; Json::Value getJson(int options, bool binary = false) const;
static bool isHexTxID(const std::string&); static bool isHexTxID(const std::string&);