diff --git a/Builds/VisualStudio2013/RippleD.vcxproj b/Builds/VisualStudio2013/RippleD.vcxproj index b3cbfa7dd..4dd0314d4 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj +++ b/Builds/VisualStudio2013/RippleD.vcxproj @@ -1413,10 +1413,6 @@ True True - - True - True - @@ -1475,8 +1471,6 @@ - - True True @@ -2337,6 +2331,10 @@ True True + + True + True + True True @@ -2361,6 +2359,8 @@ True True + + diff --git a/Builds/VisualStudio2013/RippleD.vcxproj.filters b/Builds/VisualStudio2013/RippleD.vcxproj.filters index 7313be427..a1b9facb2 100644 --- a/Builds/VisualStudio2013/RippleD.vcxproj.filters +++ b/Builds/VisualStudio2013/RippleD.vcxproj.filters @@ -2160,9 +2160,6 @@ ripple\app\ledger\impl - - ripple\app\ledger\impl - ripple\app\ledger @@ -2229,9 +2226,6 @@ ripple\app\ledger - - ripple\app\ledger - ripple\app\main @@ -3066,6 +3060,9 @@ ripple\ledger\impl + + ripple\ledger\impl + ripple\ledger\impl @@ -3093,6 +3090,9 @@ ripple\ledger\tests + + ripple\ledger + ripple\ledger diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index d00644e8a..606a65bf1 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -400,115 +400,6 @@ bool Ledger::addSLE (SLE const& sle) return stateMap_->addItem(item, false, false); } -Transaction::pointer -getTransaction (Ledger const& ledger, - uint256 const& transID, TransactionMaster& cache) -{ - SHAMapTreeNode::TNType type; - auto const item = - ledger.txMap().peekItem (transID, type); - - if (!item) - return Transaction::pointer (); - - auto txn = cache.fetch (transID, false); - - if (txn) - return txn; - - if (type == SHAMapTreeNode::tnTRANSACTION_NM) - { - txn = Transaction::sharedTransaction (item->peekData (), Validate::YES); - } - else if (type == SHAMapTreeNode::tnTRANSACTION_MD) - { - auto sit = SerialIter{item->data(), item->size()}; - txn = Transaction::sharedTransaction(sit.getVL(), Validate::NO); - } - else - { - assert (false); - return Transaction::pointer (); - } - - if (txn->getStatus () == NEW) - { - txn->setStatus ( - ledger.info().open ? INCLUDED : COMMITTED, ledger.info().seq); - } - - cache.canonicalize (&txn); - return txn; -} - -bool -getTransaction (Ledger const& ledger, - uint256 const& txID, Transaction::pointer& txn, - TxMeta::pointer& meta, - TransactionMaster& cache) -{ - SHAMapTreeNode::TNType type; - auto const item = - ledger.txMap().peekItem (txID, type); - if (!item) - return false; - - if (type == SHAMapTreeNode::tnTRANSACTION_NM) - { - // in tree with no metadata - txn = cache.fetch (txID, false); - meta.reset (); - - if (!txn) - { - txn = Transaction::sharedTransaction ( - item->peekData (), Validate::YES); - } - } - else if (type == SHAMapTreeNode::tnTRANSACTION_MD) - { - // in tree with metadata - SerialIter it (item->slice()); - txn = getApp().getMasterTransaction ().fetch (txID, false); - - if (!txn) - txn = Transaction::sharedTransaction (it.getVL (), Validate::YES); - else - it.getVL (); // skip transaction - - meta = std::make_shared ( - txID, ledger.seq(), it.getVL ()); - } - else - return false; - - if (txn->getStatus () == NEW) - txn->setStatus (ledger.info().open ? INCLUDED : COMMITTED, ledger.seq()); - - cache.canonicalize (&txn); - return true; -} - -bool getTransactionMeta (Ledger const& ledger, - uint256 const& txID, TxMeta::pointer& meta) -{ - SHAMapTreeNode::TNType type; - auto const item = - ledger.txMap().peekItem (txID, type); - - if (!item) - return false; - - if (type != SHAMapTreeNode::tnTRANSACTION_MD) - return false; - - SerialIter it (item->slice()); - it.getVL (); // skip transaction - meta = std::make_shared (txID, ledger.seq(), it.getVL ()); - - return true; -} - uint256 const& Ledger::getHash() { @@ -1447,7 +1338,8 @@ void Ledger::deprecatedUpdateCachedFees() const } } -std::vector Ledger::getNeededTransactionHashes ( +std::vector +Ledger::getNeededTransactionHashes ( int max, SHAMapSyncFilter* filter) const { std::vector ret; @@ -1463,7 +1355,8 @@ std::vector Ledger::getNeededTransactionHashes ( return ret; } -std::vector Ledger::getNeededAccountStateHashes ( +std::vector +Ledger::getNeededAccountStateHashes ( int max, SHAMapSyncFilter* filter) const { std::vector ret; @@ -1479,121 +1372,104 @@ std::vector Ledger::getNeededAccountStateHashes ( return ret; } -//------------------------------------------------------------------------------ -// -// API -// //------------------------------------------------------------------------------ -boost::optional -hashOfSeq (Ledger& ledger, LedgerIndex seq, - beast::Journal journal) -{ - // Easy cases... - if (seq > ledger.seq()) - { - if (journal.warning) journal.warning << - "Can't get seq " << seq << - " from " << ledger.seq() << " future"; - return boost::none; - } - if (seq == ledger.seq()) - return ledger.getHash(); - if (seq == (ledger.seq() - 1)) - return ledger.info().parentHash; - - // Within 256... - { - int diff = ledger.seq() - seq; - if (diff <= 256) - { - auto const hashIndex = cachedRead( - ledger, getLedgerHashIndex()); - if (hashIndex) - { - assert (hashIndex->getFieldU32 (sfLastLedgerSequence) == - (ledger.seq() - 1)); - STVector256 vec = hashIndex->getFieldV256 (sfHashes); - if (vec.size () >= diff) - return vec[vec.size () - diff]; - if (journal.warning) journal.warning << - "Ledger " << ledger.seq() << - " missing hash for " << seq << - " (" << vec.size () << "," << diff << ")"; - } - else - { - if (journal.warning) journal.warning << - "Ledger " << ledger.seq() << - ":" << ledger.getHash () << " missing normal list"; - } - } - if ((seq & 0xff) != 0) - { - if (journal.debug) journal.debug << - "Can't get seq " << seq << - " from " << ledger.seq() << " past"; - return boost::none; - } - } - - // in skiplist - auto const hashIndex = cachedRead(ledger, - getLedgerHashIndex(seq)); - if (hashIndex) - { - auto const lastSeq = - hashIndex->getFieldU32 (sfLastLedgerSequence); - assert (lastSeq >= seq); - assert ((lastSeq & 0xff) == 0); - auto const diff = (lastSeq - seq) >> 8; - STVector256 vec = hashIndex->getFieldV256 (sfHashes); - if (vec.size () > diff) - return vec[vec.size () - diff - 1]; - } - if (journal.warning) journal.warning << - "Can't get seq " << seq << - " from " << ledger.seq() << " error"; - return boost::none; -} - -void -injectSLE (Json::Value& jv, - SLE const& sle) -{ - jv = sle.getJson(0); - if (sle.getType() == ltACCOUNT_ROOT) - { - if (sle.isFieldPresent(sfEmailHash)) - { - auto const& hash = - sle.getFieldH128(sfEmailHash); - Blob const b (hash.begin(), hash.end()); - std::string md5 = strHex(b); - boost::to_lower(md5); - // VFALCO TODO Give a name and move this constant - // to a more visible location. Also - // shouldn't this be https? - jv[jss::urlgravatar] = str(boost::format( - "http://www.gravatar.com/avatar/%s") % md5); - } - } - else - { - jv[jss::Invalid] = true; - } -} - -//------------------------------------------------------------------------------ - -bool -getMetaHex (Ledger const& ledger, - uint256 const& transID, std::string& hex) +Transaction::pointer +getTransaction (Ledger const& ledger, + uint256 const& transID, TransactionMaster& cache) { SHAMapTreeNode::TNType type; auto const item = ledger.txMap().peekItem (transID, type); + if (!item) + return Transaction::pointer (); + + auto txn = cache.fetch (transID, false); + + if (txn) + return txn; + + if (type == SHAMapTreeNode::tnTRANSACTION_NM) + { + txn = Transaction::sharedTransaction (item->peekData (), Validate::YES); + } + else if (type == SHAMapTreeNode::tnTRANSACTION_MD) + { + auto sit = SerialIter{item->data(), item->size()}; + txn = Transaction::sharedTransaction(sit.getVL(), Validate::NO); + } + else + { + assert (false); + return Transaction::pointer (); + } + + if (txn->getStatus () == NEW) + { + txn->setStatus ( + ledger.info().open ? INCLUDED : COMMITTED, ledger.info().seq); + } + + cache.canonicalize (&txn); + return txn; +} + +bool +getTransaction (Ledger const& ledger, + uint256 const& txID, Transaction::pointer& txn, + TxMeta::pointer& meta, + TransactionMaster& cache) +{ + SHAMapTreeNode::TNType type; + auto const item = + ledger.txMap().peekItem (txID, type); + if (!item) + return false; + + if (type == SHAMapTreeNode::tnTRANSACTION_NM) + { + // in tree with no metadata + txn = cache.fetch (txID, false); + meta.reset (); + + if (!txn) + { + txn = Transaction::sharedTransaction ( + item->peekData (), Validate::YES); + } + } + else if (type == SHAMapTreeNode::tnTRANSACTION_MD) + { + // in tree with metadata + SerialIter it (item->slice()); + txn = getApp().getMasterTransaction ().fetch (txID, false); + + if (!txn) + txn = Transaction::sharedTransaction (it.getVL (), Validate::YES); + else + it.getVL (); // skip transaction + + meta = std::make_shared ( + txID, ledger.seq(), it.getVL ()); + } + else + return false; + + if (txn->getStatus () == NEW) + txn->setStatus (ledger.info().open ? INCLUDED : COMMITTED, ledger.seq()); + + cache.canonicalize (&txn); + return true; +} + +bool getTransactionMeta (Ledger const& ledger, + uint256 const& txID, TxMeta::pointer& meta) +{ + SHAMapTreeNode::TNType type; + auto const item = + ledger.txMap().peekItem (txID, type); + if (!item) return false; @@ -1602,7 +1478,8 @@ getMetaHex (Ledger const& ledger, SerialIter it (item->slice()); it.getVL (); // skip transaction - hex = strHex (it.getVL ()); + meta = std::make_shared (txID, ledger.seq(), it.getVL ()); + return true; } diff --git a/src/ripple/app/ledger/Ledger.h b/src/ripple/app/ledger/Ledger.h index 5a68e3461..8b2269f09 100644 --- a/src/ripple/app/ledger/Ledger.h +++ b/src/ripple/app/ledger/Ledger.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED #define RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED -#include +#include #include #include #include @@ -447,50 +447,6 @@ cachedRead (ReadView const& ledger, uint256 const& key, return ledger.read(keylet::unchecked(key)); } -/** Return the hash of a ledger by sequence. - The hash is retrieved by looking up the "skip list" - in the passed ledger. As the skip list is limited - in size, if the requested ledger sequence number is - out of the range of ledgers represented in the skip - list, then boost::none is returned. - @return The hash of the ledger with the - given sequence number or boost::none. -*/ -boost::optional -hashOfSeq (Ledger& ledger, LedgerIndex seq, - beast::Journal journal); - -/** Find a ledger index from which we could easily get the requested ledger - - The index that we return should meet two requirements: - 1) It must be the index of a ledger that has the hash of the ledger - we are looking for. This means that its sequence must be equal to - greater than the sequence that we want but not more than 256 greater - since each ledger contains the hashes of the 256 previous ledgers. - - 2) Its hash must be easy for us to find. This means it must be 0 mod 256 - because every such ledger is permanently enshrined in a LedgerHashes - page which we can easily retrieve via the skip list. -*/ -inline -LedgerIndex -getCandidateLedger (LedgerIndex requested) -{ - return (requested + 255) & (~255); -} - -/** Inject JSON describing ledger entry - - Effects: - Adds the JSON description of `sle` to `jv`. - - If `sle` holds an account root, also adds the - urlgravatar field JSON if sfEmailHash is present. -*/ -void -injectSLE (Json::Value& jv, - SLE const& sle); - //------------------------------------------------------------------------------ // VFALCO NOTE This is called from only one place @@ -510,11 +466,6 @@ getTransactionMeta (Ledger const&, uint256 const& transID, TxMeta::pointer & txMeta); -// VFALCO NOTE This is called from only one place -bool -getMetaHex (Ledger const& ledger, - uint256 const& transID, std::string & hex); - void ownerDirDescriber (SLE::ref, bool, AccountID const& owner); diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index b75566f7e..82ba42643 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -310,18 +310,6 @@ public: digest (key_type const& key) const = 0; }; -/** Run a functor on each SLE in a ReadView starting from the key start, - as long as the functor returns true. - */ -template -void forEachSLE(ReadView const& view, Functor func, uint256 const& start = {}) -{ - for (auto k = view.succ(start); k; k = view.succ(*k)) - if (auto sle = view.read(keylet::unchecked(*k))) - if (! func(*sle)) - break; -} - } // ripple #include diff --git a/src/ripple/app/ledger/TxMeta.h b/src/ripple/ledger/TxMeta.h similarity index 100% rename from src/ripple/app/ledger/TxMeta.h rename to src/ripple/ledger/TxMeta.h diff --git a/src/ripple/ledger/View.h b/src/ripple/ledger/View.h index ce6089136..8923e6724 100644 --- a/src/ripple/ledger/View.h +++ b/src/ripple/ledger/View.h @@ -41,6 +41,7 @@ #include namespace ripple { + //------------------------------------------------------------------------------ // // Observers @@ -140,6 +141,50 @@ using majorityAmendments_t = std::map ; majorityAmendments_t getMajorityAmendments (ReadView const& view); +/** Return the hash of a ledger by sequence. + The hash is retrieved by looking up the "skip list" + in the passed ledger. As the skip list is limited + in size, if the requested ledger sequence number is + out of the range of ledgers represented in the skip + list, then boost::none is returned. + @return The hash of the ledger with the + given sequence number or boost::none. +*/ +boost::optional +hashOfSeq (ReadView const& ledger, LedgerIndex seq, + beast::Journal journal); + +/** Find a ledger index from which we could easily get the requested ledger + + The index that we return should meet two requirements: + 1) It must be the index of a ledger that has the hash of the ledger + we are looking for. This means that its sequence must be equal to + greater than the sequence that we want but not more than 256 greater + since each ledger contains the hashes of the 256 previous ledgers. + + 2) Its hash must be easy for us to find. This means it must be 0 mod 256 + because every such ledger is permanently enshrined in a LedgerHashes + page which we can easily retrieve via the skip list. +*/ +inline +LedgerIndex +getCandidateLedger (LedgerIndex requested) +{ + return (requested + 255) & (~255); +} + +/** Run a functor on each SLE in a ReadView starting from the key start, + as long as the functor returns true. + */ +template +void forEachSLE(ReadView const& view, Functor func, uint256 const& start = {}) +{ + for (auto k = view.succ(start); k; k = view.succ(*k)) + if (auto sle = view.read(keylet::unchecked(*k))) + if (! func(*sle)) + break; +} + //------------------------------------------------------------------------------ // // Modifiers diff --git a/src/ripple/ledger/detail/ApplyStateTable.h b/src/ripple/ledger/detail/ApplyStateTable.h index 21d2260e1..a8e934c2f 100644 --- a/src/ripple/ledger/detail/ApplyStateTable.h +++ b/src/ripple/ledger/detail/ApplyStateTable.h @@ -27,7 +27,7 @@ #include #include // VFALCO TODO Move TxMeta to ripple/ledger/ -#include +#include namespace ripple { namespace detail { diff --git a/src/ripple/app/ledger/impl/TxMeta.cpp b/src/ripple/ledger/impl/TxMeta.cpp similarity index 99% rename from src/ripple/app/ledger/impl/TxMeta.cpp rename to src/ripple/ledger/impl/TxMeta.cpp index 094982b2f..dc7ed243f 100644 --- a/src/ripple/app/ledger/impl/TxMeta.cpp +++ b/src/ripple/ledger/impl/TxMeta.cpp @@ -18,7 +18,7 @@ //============================================================================== #include -#include +#include #include #include #include diff --git a/src/ripple/ledger/impl/View.cpp b/src/ripple/ledger/impl/View.cpp index 372e5904b..3305053cb 100644 --- a/src/ripple/ledger/impl/View.cpp +++ b/src/ripple/ledger/impl/View.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include namespace ripple { @@ -434,6 +436,78 @@ getMajorityAmendments (ReadView const& view) return majorities; } +boost::optional +hashOfSeq (ReadView const& ledger, LedgerIndex seq, + beast::Journal journal) +{ + // Easy cases... + if (seq > ledger.seq()) + { + if (journal.warning) journal.warning << + "Can't get seq " << seq << + " from " << ledger.seq() << " future"; + return boost::none; + } + if (seq == ledger.seq()) + return ledger.info().hash; + if (seq == (ledger.seq() - 1)) + return ledger.info().parentHash; + + // Within 256... + { + int diff = ledger.seq() - seq; + if (diff <= 256) + { + auto const hashIndex = + ledger.read(keylet::skip()); + if (hashIndex) + { + assert (hashIndex->getFieldU32 (sfLastLedgerSequence) == + (ledger.seq() - 1)); + STVector256 vec = hashIndex->getFieldV256 (sfHashes); + if (vec.size () >= diff) + return vec[vec.size () - diff]; + if (journal.warning) journal.warning << + "Ledger " << ledger.seq() << + " missing hash for " << seq << + " (" << vec.size () << "," << diff << ")"; + } + else + { + if (journal.warning) journal.warning << + "Ledger " << ledger.seq() << + ":" << ledger.info().hash << " missing normal list"; + } + } + if ((seq & 0xff) != 0) + { + if (journal.debug) journal.debug << + "Can't get seq " << seq << + " from " << ledger.seq() << " past"; + return boost::none; + } + } + + // in skiplist + auto const hashIndex = + ledger.read(keylet::skip(seq)); + if (hashIndex) + { + auto const lastSeq = + hashIndex->getFieldU32 (sfLastLedgerSequence); + assert (lastSeq >= seq); + assert ((lastSeq & 0xff) == 0); + auto const diff = (lastSeq - seq) >> 8; + STVector256 vec = hashIndex->getFieldV256 (sfHashes); + if (vec.size () > diff) + return vec[vec.size () - diff - 1]; + } + if (journal.warning) journal.warning << + "Can't get seq " << seq << + " from " << ledger.seq() << " error"; + return boost::none; +} + //------------------------------------------------------------------------------ // // Modifiers diff --git a/src/ripple/rpc/handlers/AccountInfo.cpp b/src/ripple/rpc/handlers/AccountInfo.cpp index e35730eb8..15c0293c3 100644 --- a/src/ripple/rpc/handlers/AccountInfo.cpp +++ b/src/ripple/rpc/handlers/AccountInfo.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,7 @@ Json::Value doAccountInfo (RPC::Context& context) auto const sleAccepted = ledger->read(keylet::account(accountID)); if (sleAccepted) { - injectSLE(jvAccepted, *sleAccepted); + RPC::injectSLE(jvAccepted, *sleAccepted); // See if there's a SignerEntries for this account. auto const signerList = ledger->read (keylet::signers(accountID)); diff --git a/src/ripple/rpc/handlers/Tx.cpp b/src/ripple/rpc/handlers/Tx.cpp index a5d08db9f..d979393ec 100644 --- a/src/ripple/rpc/handlers/Tx.cpp +++ b/src/ripple/rpc/handlers/Tx.cpp @@ -63,6 +63,26 @@ isValidated (RPC::Context& context, std::uint32_t seq, uint256 const& hash) return context.ledgerMaster.getHashBySeq (seq) == hash; } +bool +getMetaHex (Ledger const& ledger, + uint256 const& transID, std::string& hex) +{ + SHAMapTreeNode::TNType type; + auto const item = + ledger.txMap().peekItem (transID, type); + + if (!item) + return false; + + if (type != SHAMapTreeNode::tnTRANSACTION_MD) + return false; + + SerialIter it (item->slice()); + it.getVL (); // skip transaction + hex = strHex (makeSlice(it.getVL ())); + return true; +} + Json::Value doTx (RPC::Context& context) { if (!context.params.isMember (jss::transaction)) diff --git a/src/ripple/rpc/impl/Accounts.cpp b/src/ripple/rpc/impl/Accounts.cpp index b0b183b0f..abf77b9b8 100644 --- a/src/ripple/rpc/impl/Accounts.cpp +++ b/src/ripple/rpc/impl/Accounts.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include diff --git a/src/ripple/rpc/impl/Utilities.cpp b/src/ripple/rpc/impl/Utilities.cpp index 262267ed2..0942436e5 100644 --- a/src/ripple/rpc/impl/Utilities.cpp +++ b/src/ripple/rpc/impl/Utilities.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include namespace ripple { namespace RPC { @@ -65,5 +67,32 @@ addPaymentDeliveredAmount ( meta[jss::delivered_amount] = Json::Value ("unavailable"); } +void +injectSLE (Json::Value& jv, + SLE const& sle) +{ + jv = sle.getJson(0); + if (sle.getType() == ltACCOUNT_ROOT) + { + if (sle.isFieldPresent(sfEmailHash)) + { + auto const& hash = + sle.getFieldH128(sfEmailHash); + Blob const b (hash.begin(), hash.end()); + std::string md5 = strHex(makeSlice(b)); + boost::to_lower(md5); + // VFALCO TODO Give a name and move this constant + // to a more visible location. Also + // shouldn't this be https? + jv[jss::urlgravatar] = str(boost::format( + "http://www.gravatar.com/avatar/%s") % md5); + } + } + else + { + jv[jss::Invalid] = true; + } +} + } // ripple } // RPC diff --git a/src/ripple/rpc/impl/Utilities.h b/src/ripple/rpc/impl/Utilities.h index 5e554e37c..144c9ba11 100644 --- a/src/ripple/rpc/impl/Utilities.h +++ b/src/ripple/rpc/impl/Utilities.h @@ -20,7 +20,7 @@ #ifndef RIPPLE_RPC_IMPL_UTILITIES_H_INCLUDED #define RIPPLE_RPC_IMPL_UTILITIES_H_INCLUDED -#include +#include #include namespace Json { @@ -40,6 +40,18 @@ addPaymentDeliveredAmount ( Transaction::pointer, TxMeta::pointer); +/** Inject JSON describing ledger entry + + Effects: + Adds the JSON description of `sle` to `jv`. + + If `sle` holds an account root, also adds the + urlgravatar field JSON if sfEmailHash is present. +*/ +void +injectSLE (Json::Value& jv, + SLE const& sle); + } // RPC } // ripple diff --git a/src/ripple/unity/app_ledger.cpp b/src/ripple/unity/app_ledger.cpp index 8291de5eb..4b07ce883 100644 --- a/src/ripple/unity/app_ledger.cpp +++ b/src/ripple/unity/app_ledger.cpp @@ -40,7 +40,6 @@ #include #include #include -#include #include #include diff --git a/src/ripple/unity/ledger.cpp b/src/ripple/unity/ledger.cpp index 2ee8bfaaa..4711aa44f 100644 --- a/src/ripple/unity/ledger.cpp +++ b/src/ripple/unity/ledger.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include