diff --git a/src/cpp/ripple/Ledger.cpp b/src/cpp/ripple/Ledger.cpp index 273d765150..9745e7ba85 100644 --- a/src/cpp/ripple/Ledger.cpp +++ b/src/cpp/ripple/Ledger.cpp @@ -403,17 +403,19 @@ void Ledger::saveAcceptedLedger(bool fromConsensus, LoadEvent::pointer event) assert(type == SHAMapTreeNode::tnTRANSACTION_MD); SerializerIterator sit(item->peekSerializer()); Serializer rawTxn(sit.getVL()); - std::string escMeta(sqlEscape(sit.getVL())); + Serializer rawMeta(sit.getVL()); + std::string escMeta(sqlEscape(rawMeta.peekData())); SerializerIterator txnIt(rawTxn); SerializedTransaction txn(txnIt); assert(txn.getTransactionID() == item->getTag()); + TransactionMetaSet meta(item->getTag(), mLedgerSeq, rawMeta.peekData()); // Make sure transaction is in AccountTransactions. if (!SQL_EXISTS(db, boost::str(AcctTransExists % item->getTag().GetHex()))) { // Transaction not in AccountTransactions - std::vector accts = txn.getAffectedAccounts(); + std::vector accts = meta.getAffectedAccounts(); std::string sql = "INSERT INTO AccountTransactions (TransID, Account, LedgerSeq) VALUES "; bool first = true; @@ -620,10 +622,13 @@ Json::Value Ledger::getJson(int options) { Json::Value ledger(Json::objectValue); - boost::recursive_mutex::scoped_lock sl(mLock); - ledger["parentHash"] = mParentHash.GetHex(); - bool full = (options & LEDGER_JSON_FULL) != 0; + + boost::recursive_mutex::scoped_lock sl(mLock); + + ledger["parentHash"] = mParentHash.GetHex(); + ledger["seqNum"] = boost::lexical_cast(mLedgerSeq); + if(mClosed || full) { if (mClosed) @@ -646,6 +651,7 @@ Json::Value Ledger::getJson(int options) } else ledger["closed"] = false; + if (mTransactionMap && (full || ((options & LEDGER_JSON_DUMP_TXRP) != 0))) { Json::Value txns(Json::arrayValue); @@ -685,6 +691,7 @@ Json::Value Ledger::getJson(int options) } ledger["transactions"] = txns; } + if (mAccountStateMap && (full || ((options & LEDGER_JSON_DUMP_STATE) != 0))) { Json::Value state(Json::arrayValue); @@ -702,7 +709,6 @@ Json::Value Ledger::getJson(int options) } ledger["accountState"] = state; } - ledger["seqNum"] = boost::lexical_cast(mLedgerSeq); return ledger; } diff --git a/src/cpp/ripple/SHAMap.cpp b/src/cpp/ripple/SHAMap.cpp index e549b9325b..15355ed1d5 100644 --- a/src/cpp/ripple/SHAMap.cpp +++ b/src/cpp/ripple/SHAMap.cpp @@ -717,7 +717,7 @@ SHAMapTreeNode::pointer SHAMap::fetchNodeExternal(const SHAMapNode& id, const ui try { SHAMapTreeNode::pointer ret = - boost::make_shared(id, obj->getData(), mSeq - 1, snfPREFIX, hash); + boost::make_shared(id, obj->getData(), mSeq, snfPREFIX, hash); if (id != *ret) { cLog(lsFATAL) << "id:" << id << ", got:" << *ret; diff --git a/src/cpp/ripple/SerializedTransaction.cpp b/src/cpp/ripple/SerializedTransaction.cpp index 8d05b85a8e..e7b1ef7e59 100644 --- a/src/cpp/ripple/SerializedTransaction.cpp +++ b/src/cpp/ripple/SerializedTransaction.cpp @@ -78,8 +78,8 @@ std::string SerializedTransaction::getText() const return STObject::getText(); } -std::vector SerializedTransaction::getAffectedAccounts() const -{ // FIXME: This needs to be thought out better +std::vector SerializedTransaction::getMentionedAccounts() const +{ std::vector accounts; BOOST_FOREACH(const SerializedType& it, peekData()) diff --git a/src/cpp/ripple/SerializedTransaction.h b/src/cpp/ripple/SerializedTransaction.h index c026d0220d..5294532f69 100644 --- a/src/cpp/ripple/SerializedTransaction.h +++ b/src/cpp/ripple/SerializedTransaction.h @@ -60,7 +60,7 @@ public: uint32 getSequence() const { return getFieldU32(sfSequence); } void setSequence(uint32 seq) { return setFieldU32(sfSequence, seq); } - std::vector getAffectedAccounts() const; + std::vector getMentionedAccounts() const; uint256 getTransactionID() const; diff --git a/src/cpp/ripple/TransactionMeta.cpp b/src/cpp/ripple/TransactionMeta.cpp index 6fc6e85bc9..77886c163e 100644 --- a/src/cpp/ripple/TransactionMeta.cpp +++ b/src/cpp/ripple/TransactionMeta.cpp @@ -7,6 +7,9 @@ #include #include "Log.h" +#include "SerializedObject.h" + +SETUP_LOG(); TransactionMetaSet::TransactionMetaSet(const uint256& txid, uint32 ledger, const std::vector& vec) : mTransactionID(txid), mLedger(ledger), mNodes(sfAffectedNodes, 32) @@ -52,33 +55,58 @@ void TransactionMetaSet::setAffectedNode(const uint256& node, SField::ref type, obj.setFieldU16(sfLedgerEntryType, nodeType); } -/* +static void addIfUnique(std::vector& vector, const RippleAddress& address) +{ + BOOST_FOREACH(const RippleAddress& a, vector) + if (a == address) + return; + vector.push_back(address); +} + std::vector TransactionMetaSet::getAffectedAccounts() { std::vector accounts; + accounts.reserve(10); - BOOST_FOREACH(STObject& object, mNodes.getValue() ) + BOOST_FOREACH(const STObject& it, mNodes) { - const STAccount* sa = dynamic_cast(&it); - if (sa != NULL) + int index = it.getFieldIndex((it.getFName() == sfCreatedNode) ? sfNewFields : sfFinalFields); + if (index != -1) { - bool found = false; - RippleAddress na = sa->getValueNCA(); - BOOST_FOREACH(const RippleAddress& it, accounts) + const STObject *inner = dynamic_cast(&it.peekAtIndex(index)); + if (inner) { - if (it == na) + BOOST_FOREACH(const SerializedType& field, inner->peekData()) { - found = true; - break; + const STAccount* sa = dynamic_cast(&it); + if (sa) + addIfUnique(accounts, sa->getValueNCA()); + else if ((field.getFName() == sfLowLimit) || (field.getFName() == sfHighLimit)) + { + const STAmount* lim = dynamic_cast(&field); + if (lim != NULL) + { + uint160 issuer = lim->getIssuer(); + if (issuer.isNonZero()) + { + RippleAddress na; + na.setAccountID(issuer); + addIfUnique(accounts, na); + } + } + else + { + cLog(lsFATAL) << "limit is not amount " << field.getJson(0); + } + } } } - if (!found) - accounts.push_back(na); + else assert(false); } } + return accounts; } -*/ STObject& TransactionMetaSet::getAffectedNode(SLE::ref node, SField::ref type) { diff --git a/src/cpp/ripple/TransactionMeta.h b/src/cpp/ripple/TransactionMeta.h index 3b8ae25e3f..5386b96b87 100644 --- a/src/cpp/ripple/TransactionMeta.h +++ b/src/cpp/ripple/TransactionMeta.h @@ -49,7 +49,7 @@ public: STObject& getAffectedNode(SLE::ref node, SField::ref type); // create if needed STObject& getAffectedNode(const uint256&); const STObject& peekAffectedNode(const uint256&) const; - //std::vector getAffectedAccounts(); + std::vector getAffectedAccounts(); Json::Value getJson(int p) const { return getAsObject().getJson(p); }