From 1cbcc7be215d5f9933e5b771aa5d401e4c5d0297 Mon Sep 17 00:00:00 2001 From: Tom Ritchford Date: Mon, 1 Dec 2014 19:20:30 -0500 Subject: [PATCH] Allow the Ledger to generically output to both Json models. --- src/ripple/app/consensus/LedgerConsensus.cpp | 4 +- src/ripple/app/ledger/Ledger.cpp | 131 +----------- src/ripple/app/ledger/Ledger.h | 8 +- src/ripple/app/ledger/LedgerToJson.h | 203 +++++++++++++++++++ src/ripple/app/misc/NetworkOPs.cpp | 5 +- src/ripple/protocol/JsonFields.h | 3 + src/ripple/rpc/handlers/LedgerHeader.cpp | 2 +- src/ripple/rpc/handlers/LedgerRequest.cpp | 2 +- 8 files changed, 224 insertions(+), 134 deletions(-) create mode 100644 src/ripple/app/ledger/LedgerToJson.h diff --git a/src/ripple/app/consensus/LedgerConsensus.cpp b/src/ripple/app/consensus/LedgerConsensus.cpp index f25f60f97..929ae1e40 100644 --- a/src/ripple/app/consensus/LedgerConsensus.cpp +++ b/src/ripple/app/consensus/LedgerConsensus.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,6 @@ #include #include - namespace ripple { /** @@ -559,7 +559,7 @@ public: WriteLog (lsWARNING, LedgerConsensus) << mPrevLedgerHash << " to " << netLgr; WriteLog (lsWARNING, LedgerConsensus) - << mPreviousLedger->getJson (0); + << ripple::getJson (*mPreviousLedger, 0); if (ShouldLog (lsDEBUG, LedgerConsensus)) { diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 4d362edee..0d9eed63e 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -17,10 +17,10 @@ */ //============================================================================== +#include #include #include #include -#include #include #include #include @@ -28,7 +28,6 @@ #include #include #include -#include namespace ripple { @@ -643,7 +642,8 @@ bool Ledger::saveValidatedLedger (bool current) if (!getAccountHash ().isNonZero ()) { - WriteLog (lsFATAL, Ledger) << "AH is zero: " << getJson (0); + WriteLog (lsFATAL, Ledger) << "AH is zero: " + << getJson (*this, 0); assert (false); } @@ -920,7 +920,7 @@ Ledger::pointer Ledger::getSQL (std::string const& sql) { WriteLog (lsERROR, Ledger) << "Failed on ledger"; Json::Value p; - ret->addJson (p, LEDGER_JSON_FULL); + addJson (*ret, p, LEDGER_JSON_FULL); WriteLog (lsERROR, Ledger) << p; } @@ -1119,127 +1119,6 @@ Ledger::pointer Ledger::getLastFullLedger () } } -void Ledger::addJson (Json::Value& ret, int options) -{ - ret[jss::ledger] = getJson (options); -} - -static void stateItemTagAppender(Json::Value& value, SHAMapItem::ref smi) -{ - value.append (to_string (smi->getTag ())); -} - -static void stateItemFullAppender(Json::Value& value, SLE::ref sle) -{ - value.append (sle->getJson (0)); -} - -Json::Value Ledger::getJson (int options) const -{ - Json::Value ledger (Json::objectValue); - - bool const bFull (options & LEDGER_JSON_FULL); - bool const bExpand (options & LEDGER_JSON_EXPAND); - - // DEPRECATED - ledger[jss::seqNum] - = beast::lexicalCastThrow (mLedgerSeq); - ledger[jss::parent_hash] = to_string (mParentHash); - ledger[jss::ledger_index] - = beast::lexicalCastThrow (mLedgerSeq); - - if (mClosed || bFull) - { - if (mClosed) - ledger[jss::closed] = true; - - // DEPRECATED - ledger[jss::hash] = to_string (mHash); - - // DEPRECATED - ledger[jss::totalCoins] - = beast::lexicalCastThrow (mTotCoins); - ledger[jss::ledger_hash] = to_string (mHash); - ledger[jss::transaction_hash] = to_string (mTransHash); - ledger[jss::account_hash] = to_string (mAccountHash); - ledger[jss::accepted] = mAccepted; - ledger[jss::total_coins] - = beast::lexicalCastThrow (mTotCoins); - - if (mCloseTime != 0) - { - ledger[jss::close_time] = mCloseTime; - ledger[jss::close_time_human] - = boost::posix_time::to_simple_string ( - ptFromSeconds (mCloseTime)); - ledger[jss::close_time_resolution] = mCloseResolution; - - if ((mCloseFlags & sLCF_NoConsensusTime) != 0) - ledger[jss::close_time_estimated] = true; - } - } - else - { - ledger[jss::closed] = false; - } - - if (mTransactionMap && (bFull || options & LEDGER_JSON_DUMP_TXRP)) - { - Json::Value& txns = (ledger[jss::transactions] = Json::arrayValue); - SHAMapTreeNode::TNType type; - - for (auto item = mTransactionMap->peekFirstItem (type); item; - item = mTransactionMap->peekNextItem (item->getTag (), type)) - { - if (bFull || bExpand) - { - if (type == SHAMapTreeNode::tnTRANSACTION_NM) - { - SerializerIterator sit (item->peekSerializer ()); - STTx txn (sit); - txns.append (txn.getJson (0)); - } - else if (type == SHAMapTreeNode::tnTRANSACTION_MD) - { - SerializerIterator sit (item->peekSerializer ()); - Serializer sTxn (sit.getVL ()); - - SerializerIterator tsit (sTxn); - STTx txn (tsit); - - TransactionMetaSet meta ( - item->getTag (), mLedgerSeq, sit.getVL ()); - Json::Value txJson = txn.getJson (0); - txJson[jss::metaData] = meta.getJson (0); - txns.append (txJson); - } - else - { - Json::Value error = Json::objectValue; - error[to_string (item->getTag ())] = type; - txns.append (error); - } - } - else txns.append (to_string (item->getTag ())); - } - - } - - if (mAccountStateMap && (bFull || options & LEDGER_JSON_DUMP_STATE)) - { - Json::Value& state = (ledger[jss::accountState] = Json::arrayValue); - if (bFull || bExpand) - visitStateItems(std::bind(stateItemFullAppender, std::ref(state), - std::placeholders::_1)); - else - mAccountStateMap->visitLeaves( - std::bind(stateItemTagAppender, std::ref(state), - std::placeholders::_1)); - } - - return ledger; -} - void Ledger::setAcquiring (void) { if (!mTransactionMap || !mAccountStateMap) @@ -1769,7 +1648,7 @@ bool Ledger::assertSane () const WriteLog (lsFATAL, Ledger) << "ledger is not sane"; - Json::Value j = getJson (0); + Json::Value j = getJson (*this, 0); j [jss::accountTreeHash] = to_string (mAccountHash); j [jss::transTreeHash] = to_string (mTransHash); diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 11f9f8a48..cf377adfb 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -429,8 +429,12 @@ public: static std::set getPendingSaves(); - Json::Value getJson (int options) const; - void addJson (Json::Value&, int options); + /** Const version of getHash() which gets the current value without calling + updateHash(). */ + uint256 const& getRawHash () const + { + return mHash; + } bool walkLedger () const; bool assertSane () const; diff --git a/src/ripple/app/ledger/LedgerToJson.h b/src/ripple/app/ledger/LedgerToJson.h new file mode 100644 index 000000000..c6745a4c4 --- /dev/null +++ b/src/ripple/app/ledger/LedgerToJson.h @@ -0,0 +1,203 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2012, 2013 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLED_RIPPLE_APP_LEDGER_LEDGERTOJSON_H +#define RIPPLED_RIPPLE_APP_LEDGER_LEDGERTOJSON_H + +#include +#include +#include +#include +#include +#include +#include + +namespace ripple { + +/** Given a Ledger, options, and a generic Object that has Json semantics, + fill the Object with a description of the ledger. +*/ +template +void fillJson (Ledger const&, Object&, int options, + RPC::Yield const& yield = {}); + +/** Add Json to an existing generic Object. */ +template +void addJson (Ledger const&, Object&, int options, + RPC::Yield const& yield = {}); + +/** Return a new Json::Value representing the ledger with given options.*/ +Json::Value getJson (Ledger const&, int options, + RPC::Yield const& yield = {}); + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// Implementations. + +auto const accountYieldCount = 0; +auto const transactionYieldCount = 0; + +template +void fillJson ( + Ledger const& ledger, Object& json, int options, RPC::Yield const& yield) +{ + bool const bFull (options & LEDGER_JSON_FULL); + bool const bExpand (options & LEDGER_JSON_EXPAND); + + // DEPRECATED + json[jss::seqNum] = to_string (ledger.getLedgerSeq()); + json[jss::parent_hash] = to_string (ledger.getParentHash()); + json[jss::ledger_index] = to_string (ledger.getLedgerSeq()); + + if (ledger.isClosed() || bFull) + { + if (ledger.isClosed()) + json[jss::closed] = true; + + // DEPRECATED + json[jss::hash] = to_string (ledger.getRawHash()); + + // DEPRECATED + json[jss::totalCoins] = to_string (ledger.getTotalCoins()); + json[jss::ledger_hash] = to_string (ledger.getRawHash()); + json[jss::transaction_hash] = to_string (ledger.getTransHash()); + json[jss::account_hash] = to_string (ledger.getAccountHash()); + json[jss::accepted] = ledger.isAccepted(); + json[jss::total_coins] = to_string (ledger.getTotalCoins()); + + auto closeTime = ledger.getCloseTimeNC(); + if (closeTime != 0) + { + json[jss::close_time] = closeTime; + json[jss::close_time_human] + = boost::posix_time::to_simple_string ( + ptFromSeconds (closeTime)); + json[jss::close_time_resolution] = ledger.getCloseResolution(); + + if (!ledger.getCloseAgree()) + json[jss::close_time_estimated] = true; + } + } + else + { + json[jss::closed] = false; + } + + auto &transactionMap = ledger.peekTransactionMap(); + if (transactionMap && (bFull || options & LEDGER_JSON_DUMP_TXRP)) + { + auto&& txns = RPC::addArray (json, jss::transactions); + SHAMapTreeNode::TNType type; + + int count = 0; + for (auto item = transactionMap->peekFirstItem (type); item; + item = transactionMap->peekNextItem (item->getTag (), type)) + { + if (transactionYieldCount && ++count >= transactionYieldCount) + { + yield(); + count = 0; + } + if (bFull || bExpand) + { + if (type == SHAMapTreeNode::tnTRANSACTION_NM) + { + SerializerIterator sit (item->peekSerializer ()); + STTx txn (sit); + txns.append (txn.getJson (0)); + } + else if (type == SHAMapTreeNode::tnTRANSACTION_MD) + { + SerializerIterator sit (item->peekSerializer ()); + Serializer sTxn (sit.getVL ()); + + SerializerIterator tsit (sTxn); + STTx txn (tsit); + + TransactionMetaSet meta ( + item->getTag (), ledger.getLedgerSeq(), sit.getVL ()); + Json::Value txJson = txn.getJson (0); + txJson[jss::metaData] = meta.getJson (0); + txns.append (txJson); + } + else + { + Json::Value error = Json::objectValue; + error[to_string (item->getTag ())] = type; + txns.append (error); + } + } + else txns.append (to_string (item->getTag ())); + } + } + + auto& accountStateMap = ledger.peekAccountStateMap(); + if (accountStateMap && (bFull || options & LEDGER_JSON_DUMP_STATE)) + { + auto&& array = RPC::addArray (json, jss::accountState); + auto count = 0; + if (bFull || bExpand) + { + ledger.visitStateItems ( + [&array, &count, &yield] (SLE::ref sle) + { + if (accountYieldCount && ++count >= accountYieldCount) + { + yield(); + count = 0; + } + array.append (sle->getJson(0)); + }); + } + else + { + accountStateMap->visitLeaves( + [&array, &count, &yield] (SHAMapItem::ref smi) + { + if (accountYieldCount && ++count >= accountYieldCount) + { + yield(); + count = 0; + } + array.append (to_string(smi->getTag ())); + }); + } + } +} + +/** Add Json to an existing generic Object. */ +template +void addJson ( + Ledger const& ledger, Object& json, int options, RPC::Yield const& yield) +{ + auto&& object = RPC::addObject (json, jss::ledger); + fillJson (ledger, object, options, yield); +} + +inline +Json::Value getJson (Ledger const& ledger, int options, RPC::Yield const& yield) +{ + Json::Value json; + fillJson (ledger, json, options, yield); + return json; +} + +} // ripple + +#endif diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 95bca10bb..bd11451a2 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -590,7 +591,7 @@ NetworkOPsImp::getHostId (bool forAdmin) // (this could be cached instead of recalculated every time) Blob const& addr (getApp ().getLocalCredentials ().getNodePublic (). getNodePublic ()); - + return RFC1751::getWordFromBlob (addr.data (), addr.size ()); } @@ -1408,7 +1409,7 @@ bool NetworkOPsImp::checkLastClosedLedger ( } m_journal.warning << "We are not running on the consensus ledger"; - m_journal.info << "Our LCL: " << ourClosed->getJson (0); + m_journal.info << "Our LCL: " << getJson (*ourClosed, 0); m_journal.info << "Net LCL " << closedLedger; if ((mMode == omTRACKING) || (mMode == omFULL)) diff --git a/src/ripple/protocol/JsonFields.h b/src/ripple/protocol/JsonFields.h index bcdb2b522..e0cbc4216 100644 --- a/src/ripple/protocol/JsonFields.h +++ b/src/ripple/protocol/JsonFields.h @@ -73,12 +73,14 @@ JSS ( error ); JSS ( error_code ); JSS ( error_exception ); JSS ( error_message ); +JSS ( expand ); JSS ( fee_base ); JSS ( fee_ref ); JSS ( fetch_pack ); JSS ( flags ); JSS ( freeze ); JSS ( freeze_peer ); +JSS ( full ); JSS ( hash ); JSS ( hostid ); JSS ( id ); @@ -114,6 +116,7 @@ JSS ( none ); JSS ( no_ripple ); JSS ( no_ripple_peer ); JSS ( offers ); +JSS ( open ); JSS ( owner_funds ); JSS ( params ); JSS ( parent_hash ); diff --git a/src/ripple/rpc/handlers/LedgerHeader.cpp b/src/ripple/rpc/handlers/LedgerHeader.cpp index 482ec9f39..9e0704469 100644 --- a/src/ripple/rpc/handlers/LedgerHeader.cpp +++ b/src/ripple/rpc/handlers/LedgerHeader.cpp @@ -41,7 +41,7 @@ Json::Value doLedgerHeader (RPC::Context& context) // This information isn't verified: they should only use it if they trust // us. - lpLedger->addJson (jvResult, 0); + addJson (*lpLedger, jvResult, 0); return jvResult; } diff --git a/src/ripple/rpc/handlers/LedgerRequest.cpp b/src/ripple/rpc/handlers/LedgerRequest.cpp index 247987e76..dab527313 100644 --- a/src/ripple/rpc/handlers/LedgerRequest.cpp +++ b/src/ripple/rpc/handlers/LedgerRequest.cpp @@ -93,7 +93,7 @@ Json::Value doLedgerRequest (RPC::Context& context) // We already have the ledger they want Json::Value jvResult; jvResult[jss::ledger_index] = ledger->getLedgerSeq(); - ledger->addJson (jvResult, 0); + addJson (*ledger, jvResult, 0); return jvResult; } else