mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Refactor Ledger and LedgerEntrySet:
Member functions and free functions on Ledger and LedgerEntrySet are rewritten in terms of new abstract interfaces `BasicView` and `View`, representing the set of non-decomposable primitives necessary to read and write state map items in a ledger, and to overlay a discardable view onto a Ledger that can calculate metadata during transaction processing. const-correctness is enforced through the parameter and return types. The MetaView now supports multi-level stacking: A MetaView can be stacked on top of either a Ledger or another MetaView, up to any number of levels. The getSLEi member function is removed. The CachedView wrapper replaces it, wrapping a View such that any function called with a CachedView will go through the SLECache. * Add BasicView, View, CachedView * Rename LedgerEntrySet to MetaView * Factor out free functions * Consolidate free functions in ViewAPI * Remove unused class members and free functions
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <beast/unit_test/suite.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <cassert>
|
||||
#include <utility>
|
||||
|
||||
namespace ripple {
|
||||
|
||||
@@ -57,7 +58,7 @@ namespace ripple {
|
||||
@param drops The number of drops to start with
|
||||
*/
|
||||
static
|
||||
std::shared_ptr<SLE const>
|
||||
std::shared_ptr<SLE>
|
||||
makeGenesisAccount (AccountID const& id,
|
||||
std::uint64_t drops)
|
||||
{
|
||||
@@ -70,6 +71,11 @@ makeGenesisAccount (AccountID const& id,
|
||||
return sle;
|
||||
}
|
||||
|
||||
// VFALCO This constructor could be eliminating by providing
|
||||
// a free function createGenesisLedger, call the
|
||||
// other constructor with appropriate parameters, and
|
||||
// then create the master account / flush dirty.
|
||||
//
|
||||
Ledger::Ledger (RippleAddress const& masterID, std::uint64_t startAmount)
|
||||
: mTotCoins (startAmount)
|
||||
, seq_ (1) // First Ledger
|
||||
@@ -78,17 +84,17 @@ Ledger::Ledger (RippleAddress const& masterID, std::uint64_t startAmount)
|
||||
, mCloseResolution (ledgerDefaultTimeResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
, mTransactionMap (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
|
||||
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap")))
|
||||
, mAccountStateMap (std::make_shared <SHAMap> (SHAMapType::STATE,
|
||||
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap")))
|
||||
{
|
||||
auto const sle = makeGenesisAccount(
|
||||
auto sle = makeGenesisAccount(
|
||||
masterID.getAccountID(), startAmount);
|
||||
WriteLog (lsTRACE, Ledger)
|
||||
<< "root account: " << sle->getJson(0);
|
||||
insert(*sle);
|
||||
mAccountStateMap->flushDirty (hotACCOUNT_NODE, seq_);
|
||||
unchecked_insert(std::move(sle));
|
||||
stateMap_->flushDirty (hotACCOUNT_NODE, seq_);
|
||||
}
|
||||
|
||||
Ledger::Ledger (uint256 const& parentHash,
|
||||
@@ -111,31 +117,31 @@ Ledger::Ledger (uint256 const& parentHash,
|
||||
, mCloseResolution (closeResolution)
|
||||
, mCloseFlags (closeFlags)
|
||||
, mImmutable (true)
|
||||
, mTransactionMap (std::make_shared <SHAMap> (
|
||||
, txMap_ (std::make_shared <SHAMap> (
|
||||
SHAMapType::TRANSACTION, transHash, getApp().family(),
|
||||
deprecatedLogs().journal("SHAMap")))
|
||||
, mAccountStateMap (std::make_shared <SHAMap> (SHAMapType::STATE, accountHash,
|
||||
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE, accountHash,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap")))
|
||||
{
|
||||
updateHash ();
|
||||
loaded = true;
|
||||
|
||||
if (mTransHash.isNonZero () &&
|
||||
!mTransactionMap->fetchRoot (mTransHash, nullptr))
|
||||
!txMap_->fetchRoot (mTransHash, nullptr))
|
||||
{
|
||||
loaded = false;
|
||||
WriteLog (lsWARNING, Ledger) << "Don't have TX root for ledger";
|
||||
}
|
||||
|
||||
if (mAccountHash.isNonZero () &&
|
||||
!mAccountStateMap->fetchRoot (mAccountHash, nullptr))
|
||||
!stateMap_->fetchRoot (mAccountHash, nullptr))
|
||||
{
|
||||
loaded = false;
|
||||
WriteLog (lsWARNING, Ledger) << "Don't have AS root for ledger";
|
||||
}
|
||||
|
||||
mTransactionMap->setImmutable ();
|
||||
mAccountStateMap->setImmutable ();
|
||||
txMap_->setImmutable ();
|
||||
stateMap_->setImmutable ();
|
||||
}
|
||||
|
||||
// Create a new ledger that's a snapshot of this one
|
||||
@@ -152,8 +158,8 @@ Ledger::Ledger (Ledger const& ledger,
|
||||
, mValidated (ledger.mValidated)
|
||||
, mAccepted (ledger.mAccepted)
|
||||
, mImmutable (!isMutable)
|
||||
, mTransactionMap (ledger.mTransactionMap->snapShot (isMutable))
|
||||
, mAccountStateMap (ledger.mAccountStateMap->snapShot (isMutable))
|
||||
, txMap_ (ledger.txMap_->snapShot (isMutable))
|
||||
, stateMap_ (ledger.stateMap_->snapShot (isMutable))
|
||||
{
|
||||
updateHash ();
|
||||
}
|
||||
@@ -167,9 +173,9 @@ Ledger::Ledger (bool /* dummy */,
|
||||
, mCloseResolution (prevLedger.mCloseResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
, mTransactionMap (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
|
||||
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap")))
|
||||
, mAccountStateMap (prevLedger.mAccountStateMap->snapShot (true))
|
||||
, stateMap_ (prevLedger.stateMap_->snapShot (true))
|
||||
{
|
||||
prevLedger.updateHash ();
|
||||
|
||||
@@ -207,10 +213,10 @@ Ledger::Ledger (std::uint32_t ledgerSeq, std::uint32_t closeTime)
|
||||
, mCloseResolution (ledgerDefaultTimeResolution)
|
||||
, mCloseFlags (0)
|
||||
, mImmutable (false)
|
||||
, mTransactionMap (std::make_shared <SHAMap> (
|
||||
, txMap_ (std::make_shared <SHAMap> (
|
||||
SHAMapType::TRANSACTION, getApp().family(),
|
||||
deprecatedLogs().journal("SHAMap")))
|
||||
, mAccountStateMap (std::make_shared <SHAMap> (
|
||||
, stateMap_ (std::make_shared <SHAMap> (
|
||||
SHAMapType::STATE, getApp().family(),
|
||||
deprecatedLogs().journal("SHAMap")))
|
||||
{
|
||||
@@ -229,24 +235,24 @@ void Ledger::setImmutable ()
|
||||
updateHash ();
|
||||
mImmutable = true;
|
||||
|
||||
if (mTransactionMap)
|
||||
mTransactionMap->setImmutable ();
|
||||
if (txMap_)
|
||||
txMap_->setImmutable ();
|
||||
|
||||
if (mAccountStateMap)
|
||||
mAccountStateMap->setImmutable ();
|
||||
if (stateMap_)
|
||||
stateMap_->setImmutable ();
|
||||
}
|
||||
|
||||
void Ledger::updateHash()
|
||||
{
|
||||
if (! mImmutable)
|
||||
{
|
||||
if (mTransactionMap)
|
||||
mTransHash = mTransactionMap->getHash ();
|
||||
if (txMap_)
|
||||
mTransHash = txMap_->getHash ();
|
||||
else
|
||||
mTransHash.zero ();
|
||||
|
||||
if (mAccountStateMap)
|
||||
mAccountHash = mAccountStateMap->getHash ();
|
||||
if (stateMap_)
|
||||
mAccountHash = stateMap_->getHash ();
|
||||
else
|
||||
mAccountHash.zero ();
|
||||
}
|
||||
@@ -281,9 +287,9 @@ void Ledger::setRaw (SerialIter& sit, bool hasPrefix)
|
||||
mCloseResolution = sit.get8 ();
|
||||
mCloseFlags = sit.get8 ();
|
||||
updateHash ();
|
||||
mTransactionMap = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, mTransHash,
|
||||
txMap_ = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, mTransHash,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap"));
|
||||
mAccountStateMap = std::make_shared<SHAMap> (SHAMapType::STATE, mAccountHash,
|
||||
stateMap_ = std::make_shared<SHAMap> (SHAMapType::STATE, mAccountHash,
|
||||
getApp().family(), deprecatedLogs().journal("SHAMap"));
|
||||
}
|
||||
|
||||
@@ -328,26 +334,29 @@ void Ledger::setAccepted ()
|
||||
bool Ledger::addSLE (SLE const& sle)
|
||||
{
|
||||
SHAMapItem item (sle.getIndex(), sle.getSerializer());
|
||||
return mAccountStateMap->addItem(item, false, false);
|
||||
return stateMap_->addItem(item, false, false);
|
||||
}
|
||||
|
||||
bool Ledger::addTransaction (uint256 const& txID, const Serializer& txn)
|
||||
bool
|
||||
addTransaction (Ledger& ledger,
|
||||
uint256 const& txID, const Serializer& txn)
|
||||
{
|
||||
// low-level - just add to table
|
||||
auto item = std::make_shared<SHAMapItem> (txID, txn.peekData ());
|
||||
|
||||
if (!mTransactionMap->addGiveItem (item, true, false))
|
||||
if (! ledger.txMap().addGiveItem (item, true, false))
|
||||
{
|
||||
WriteLog (lsWARNING, Ledger)
|
||||
<< "Attempt to add transaction to ledger that already had it";
|
||||
return false;
|
||||
}
|
||||
|
||||
mValidHash = false;
|
||||
// VFALCO TODO We could touch only the txMap
|
||||
ledger.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ledger::addTransaction (
|
||||
bool addTransaction (Ledger& ledger,
|
||||
uint256 const& txID, const Serializer& txn, const Serializer& md)
|
||||
{
|
||||
// low-level - just add to table
|
||||
@@ -356,26 +365,30 @@ bool Ledger::addTransaction (
|
||||
s.addVL (md.peekData ());
|
||||
auto item = std::make_shared<SHAMapItem> (txID, s.peekData ());
|
||||
|
||||
if (!mTransactionMap->addGiveItem (item, true, true))
|
||||
if (! ledger.txMap().addGiveItem (item, true, true))
|
||||
{
|
||||
WriteLog (lsFATAL, Ledger)
|
||||
<< "Attempt to add transaction+MD to ledger that already had it";
|
||||
return false;
|
||||
}
|
||||
|
||||
mValidHash = false;
|
||||
// VFALCO TODO We could touch only the txMap
|
||||
ledger.touch();
|
||||
return true;
|
||||
}
|
||||
|
||||
Transaction::pointer Ledger::getTransaction (uint256 const& transID) const
|
||||
Transaction::pointer
|
||||
getTransaction (Ledger const& ledger,
|
||||
uint256 const& transID, TransactionMaster& cache)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
std::shared_ptr<SHAMapItem> item = mTransactionMap->peekItem (transID, type);
|
||||
auto const item =
|
||||
ledger.txMap().peekItem (transID, type);
|
||||
|
||||
if (!item)
|
||||
return Transaction::pointer ();
|
||||
|
||||
auto txn = getApp().getMasterTransaction ().fetch (transID, false);
|
||||
auto txn = cache.fetch (transID, false);
|
||||
|
||||
if (txn)
|
||||
return txn;
|
||||
@@ -399,71 +412,28 @@ Transaction::pointer Ledger::getTransaction (uint256 const& transID) const
|
||||
}
|
||||
|
||||
if (txn->getStatus () == NEW)
|
||||
txn->setStatus (mClosed ? COMMITTED : INCLUDED, seq_);
|
||||
txn->setStatus (ledger.isClosed() ? COMMITTED : INCLUDED, ledger.getLedgerSeq());
|
||||
|
||||
getApp().getMasterTransaction ().canonicalize (&txn);
|
||||
cache.canonicalize (&txn);
|
||||
return txn;
|
||||
}
|
||||
|
||||
STTx::pointer Ledger::getSTransaction (
|
||||
std::shared_ptr<SHAMapItem> const& item, SHAMapTreeNode::TNType type)
|
||||
{
|
||||
SerialIter sit (item->slice());
|
||||
|
||||
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
|
||||
return std::make_shared<STTx> (sit);
|
||||
|
||||
if (type == SHAMapTreeNode::tnTRANSACTION_MD)
|
||||
{
|
||||
// VFALCO This is making a needless copy
|
||||
auto const vl = sit.getVL();
|
||||
SerialIter tSit (make_Slice(vl));
|
||||
return std::make_shared<STTx> (tSit);
|
||||
}
|
||||
|
||||
return STTx::pointer ();
|
||||
}
|
||||
|
||||
STTx::pointer Ledger::getSMTransaction (
|
||||
std::shared_ptr<SHAMapItem> const& item, SHAMapTreeNode::TNType type,
|
||||
TransactionMetaSet::pointer& txMeta) const
|
||||
{
|
||||
SerialIter sit (item->slice());
|
||||
|
||||
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
|
||||
{
|
||||
txMeta.reset ();
|
||||
return std::make_shared<STTx> (sit);
|
||||
}
|
||||
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
|
||||
{
|
||||
// VFALCO This is making a needless copy
|
||||
auto const vl = sit.getVL();
|
||||
SerialIter tSit (make_Slice(vl));
|
||||
|
||||
txMeta = std::make_shared<TransactionMetaSet> (
|
||||
item->key(), seq_, sit.getVL ());
|
||||
return std::make_shared<STTx> (tSit);
|
||||
}
|
||||
|
||||
txMeta.reset ();
|
||||
return STTx::pointer ();
|
||||
}
|
||||
|
||||
bool Ledger::getTransaction (
|
||||
bool
|
||||
getTransaction (Ledger const& ledger,
|
||||
uint256 const& txID, Transaction::pointer& txn,
|
||||
TransactionMetaSet::pointer& meta) const
|
||||
TransactionMetaSet::pointer& meta,
|
||||
TransactionMaster& cache)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
std::shared_ptr<SHAMapItem> item = mTransactionMap->peekItem (txID, type);
|
||||
|
||||
auto const item =
|
||||
ledger.txMap().peekItem (txID, type);
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
|
||||
{
|
||||
// in tree with no metadata
|
||||
txn = getApp().getMasterTransaction ().fetch (txID, false);
|
||||
txn = cache.fetch (txID, false);
|
||||
meta.reset ();
|
||||
|
||||
if (!txn)
|
||||
@@ -484,23 +454,24 @@ bool Ledger::getTransaction (
|
||||
it.getVL (); // skip transaction
|
||||
|
||||
meta = std::make_shared<TransactionMetaSet> (
|
||||
txID, seq_, it.getVL ());
|
||||
txID, ledger.seq(), it.getVL ());
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
if (txn->getStatus () == NEW)
|
||||
txn->setStatus (mClosed ? COMMITTED : INCLUDED, seq_);
|
||||
txn->setStatus (ledger.isClosed() ? COMMITTED : INCLUDED, ledger.seq());
|
||||
|
||||
getApp().getMasterTransaction ().canonicalize (&txn);
|
||||
cache.canonicalize (&txn);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ledger::getTransactionMeta (
|
||||
uint256 const& txID, TransactionMetaSet::pointer& meta) const
|
||||
bool getTransactionMeta (Ledger const& ledger,
|
||||
uint256 const& txID, TransactionMetaSet::pointer& meta)
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
std::shared_ptr<SHAMapItem> item = mTransactionMap->peekItem (txID, type);
|
||||
auto const item =
|
||||
ledger.txMap().peekItem (txID, type);
|
||||
|
||||
if (!item)
|
||||
return false;
|
||||
@@ -510,28 +481,11 @@ bool Ledger::getTransactionMeta (
|
||||
|
||||
SerialIter it (item->slice());
|
||||
it.getVL (); // skip transaction
|
||||
meta = std::make_shared<TransactionMetaSet> (txID, seq_, it.getVL ());
|
||||
meta = std::make_shared<TransactionMetaSet> (txID, ledger.seq(), it.getVL ());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ledger::getMetaHex (uint256 const& transID, std::string& hex) const
|
||||
{
|
||||
SHAMapTreeNode::TNType type;
|
||||
std::shared_ptr<SHAMapItem> item = mTransactionMap->peekItem (transID, type);
|
||||
|
||||
if (!item)
|
||||
return false;
|
||||
|
||||
if (type != SHAMapTreeNode::tnTRANSACTION_MD)
|
||||
return false;
|
||||
|
||||
SerialIter it (item->slice());
|
||||
it.getVL (); // skip transaction
|
||||
hex = strHex (it.getVL ());
|
||||
return true;
|
||||
}
|
||||
|
||||
uint256 const&
|
||||
Ledger::getHash()
|
||||
{
|
||||
@@ -572,16 +526,16 @@ bool Ledger::saveValidatedLedger (bool current)
|
||||
assert (false);
|
||||
}
|
||||
|
||||
if (getAccountHash () != mAccountStateMap->getHash ())
|
||||
if (getAccountHash () != stateMap_->getHash ())
|
||||
{
|
||||
WriteLog (lsFATAL, Ledger) << "sAL: " << getAccountHash ()
|
||||
<< " != " << mAccountStateMap->getHash ();
|
||||
<< " != " << stateMap_->getHash ();
|
||||
WriteLog (lsFATAL, Ledger) << "saveAcceptedLedger: seq="
|
||||
<< seq_ << ", current=" << current;
|
||||
assert (false);
|
||||
}
|
||||
|
||||
assert (getTransHash () == mTransactionMap->getHash ());
|
||||
assert (getTransHash () == txMap_->getHash ());
|
||||
|
||||
// Save the ledger header in the hashed object store
|
||||
{
|
||||
@@ -923,11 +877,11 @@ Ledger::getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq)
|
||||
|
||||
void Ledger::setAcquiring (void)
|
||||
{
|
||||
if (!mTransactionMap || !mAccountStateMap)
|
||||
if (!txMap_ || !stateMap_)
|
||||
throw std::runtime_error ("invalid map");
|
||||
|
||||
mTransactionMap->setSynching ();
|
||||
mAccountStateMap->setSynching ();
|
||||
txMap_->setSynching ();
|
||||
stateMap_->setSynching ();
|
||||
}
|
||||
|
||||
bool Ledger::isAcquiring (void) const
|
||||
@@ -937,12 +891,12 @@ bool Ledger::isAcquiring (void) const
|
||||
|
||||
bool Ledger::isAcquiringTx (void) const
|
||||
{
|
||||
return mTransactionMap->isSynching ();
|
||||
return txMap_->isSynching ();
|
||||
}
|
||||
|
||||
bool Ledger::isAcquiringAS (void) const
|
||||
{
|
||||
return mAccountStateMap->isSynching ();
|
||||
return stateMap_->isSynching ();
|
||||
}
|
||||
|
||||
boost::posix_time::ptime Ledger::getCloseTime () const
|
||||
@@ -959,90 +913,108 @@ void Ledger::setCloseTime (boost::posix_time::ptime ptm)
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
Ledger::exists (uint256 const& key) const
|
||||
Ledger::exists (Keylet const& k) const
|
||||
{
|
||||
return mAccountStateMap->hasItem(key);
|
||||
// VFALCO NOTE Perhaps check the type for debug builds?
|
||||
return stateMap_->hasItem(k.key);
|
||||
}
|
||||
|
||||
std::shared_ptr<SHAMapItem const>
|
||||
Ledger::find (uint256 const& key) const
|
||||
boost::optional<uint256>
|
||||
Ledger::succ (uint256 const& key,
|
||||
boost::optional<uint256> last) const
|
||||
{
|
||||
return mAccountStateMap->peekItem(key);
|
||||
auto const item =
|
||||
stateMap_->peekNextItem(key);
|
||||
if (! item)
|
||||
return boost::none;
|
||||
if (last && item->key() >= last)
|
||||
return boost::none;
|
||||
return item->key();
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
Ledger::read (Keylet const& k) const
|
||||
{
|
||||
auto const& value =
|
||||
stateMap_->peekItem(k.key);
|
||||
if (! value)
|
||||
return nullptr;
|
||||
auto sle = std::make_shared<SLE>(
|
||||
value->peekSerializer(), value->key());
|
||||
if (! k.check(*sle))
|
||||
return nullptr;
|
||||
// VFALCO TODO Eliminate "immutable" runtime property
|
||||
sle->setImmutable();
|
||||
// need move otherwise makes a copy
|
||||
// because return type is different
|
||||
return std::move(sle);
|
||||
}
|
||||
|
||||
bool
|
||||
Ledger::unchecked_erase(
|
||||
uint256 const& key)
|
||||
{
|
||||
return stateMap_->delItem(key);
|
||||
}
|
||||
|
||||
void
|
||||
Ledger::insert (SLE const& sle)
|
||||
Ledger::unchecked_insert(
|
||||
std::shared_ptr<SLE>&& sle)
|
||||
{
|
||||
assert(! mAccountStateMap->hasItem(sle.getIndex()));
|
||||
auto item = std::make_shared<SHAMapItem>(
|
||||
sle.getIndex());
|
||||
sle.add(item->peekSerializer());
|
||||
assert(! stateMap_->hasItem(sle->getIndex()));
|
||||
Serializer ss;
|
||||
sle->add(ss);
|
||||
auto item = std::make_shared<
|
||||
SHAMapItem>(sle->key(),
|
||||
std::move(ss));
|
||||
// VFALCO NOTE addGiveItem should take ownership
|
||||
auto const success =
|
||||
mAccountStateMap->addGiveItem(
|
||||
item, false, false);
|
||||
stateMap_->addGiveItem(
|
||||
std::move(item), false, false);
|
||||
(void)success;
|
||||
assert(success);
|
||||
auto const ours = std::move(sle);
|
||||
}
|
||||
|
||||
void
|
||||
Ledger::unchecked_replace(
|
||||
std::shared_ptr<SLE>&& sle)
|
||||
{
|
||||
assert(stateMap_->hasItem(sle->getIndex()));
|
||||
Serializer ss;
|
||||
sle->add(ss);
|
||||
auto item = std::make_shared<
|
||||
SHAMapItem>(sle->key(),
|
||||
std::move(ss));
|
||||
// VFALCO NOTE updateGiveItem should take ownership
|
||||
auto const success =
|
||||
stateMap_->updateGiveItem(
|
||||
std::move(item), false, false);
|
||||
(void)success;
|
||||
assert(success);
|
||||
auto const ours = std::move(sle);
|
||||
}
|
||||
|
||||
std::shared_ptr<SLE>
|
||||
Ledger::fetch (uint256 const& key,
|
||||
boost::optional<LedgerEntryType> type) const
|
||||
Ledger::peek (Keylet const& k) const
|
||||
{
|
||||
auto const item =
|
||||
mAccountStateMap->peekItem(key);
|
||||
if (! item)
|
||||
auto const& value =
|
||||
stateMap_->peekItem(k.key);
|
||||
if (! value)
|
||||
return nullptr;
|
||||
auto const sle = std::make_shared<SLE>(
|
||||
item->peekSerializer(), item->getTag());
|
||||
if (type && sle->getType() != type)
|
||||
auto sle = std::make_shared<SLE>(
|
||||
value->peekSerializer(), value->key());
|
||||
if (! k.check(*sle))
|
||||
return nullptr;
|
||||
return sle;
|
||||
}
|
||||
|
||||
void
|
||||
Ledger::replace (SLE const& sle)
|
||||
{
|
||||
assert(mAccountStateMap->hasItem(sle.getIndex()));
|
||||
auto item = std::make_shared<SHAMapItem>(
|
||||
sle.getIndex());
|
||||
sle.add(item->peekSerializer());
|
||||
auto const success =
|
||||
mAccountStateMap->updateGiveItem(
|
||||
item, false, false);
|
||||
(void)success;
|
||||
assert(success);
|
||||
}
|
||||
|
||||
void
|
||||
Ledger::erase (uint256 const& key)
|
||||
{
|
||||
assert(mAccountStateMap->hasItem(key));
|
||||
mAccountStateMap->delItem(key);
|
||||
// VFALCO TODO Eliminate "immutable" runtime property
|
||||
sle->setImmutable();
|
||||
// need move otherwise makes a copy
|
||||
// because return type is different
|
||||
return std::move(sle);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
SLE::pointer Ledger::getSLEi (uint256 const& uId) const
|
||||
{
|
||||
uint256 hash;
|
||||
|
||||
std::shared_ptr<SHAMapItem> node = mAccountStateMap->peekItem (uId, hash);
|
||||
|
||||
if (!node)
|
||||
return SLE::pointer ();
|
||||
|
||||
SLE::pointer ret = getApp().getSLECache ().fetch (hash);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
ret = std::make_shared<SLE> (node->peekSerializer (), node->key());
|
||||
ret->setImmutable ();
|
||||
getApp().getSLECache ().canonicalize (hash, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void visitHelper (
|
||||
std::function<void (SLE::ref)>& function, std::shared_ptr<SHAMapItem> const& item)
|
||||
{
|
||||
@@ -1053,9 +1025,9 @@ void Ledger::visitStateItems (std::function<void (SLE::ref)> function) const
|
||||
{
|
||||
try
|
||||
{
|
||||
if (mAccountStateMap)
|
||||
if (stateMap_)
|
||||
{
|
||||
mAccountStateMap->visitLeaves(
|
||||
stateMap_->visitLeaves(
|
||||
std::bind(&visitHelper, std::ref(function),
|
||||
std::placeholders::_1));
|
||||
}
|
||||
@@ -1075,7 +1047,7 @@ uint256 Ledger::getNextLedgerIndex (uint256 const& hash,
|
||||
boost::optional<uint256> const& last) const
|
||||
{
|
||||
auto const node =
|
||||
mAccountStateMap->peekNextItem(hash);
|
||||
stateMap_->peekNextItem(hash);
|
||||
if ((! node) || (last && node->key() >= *last))
|
||||
return {};
|
||||
return node->key();
|
||||
@@ -1086,15 +1058,15 @@ bool Ledger::walkLedger () const
|
||||
std::vector <SHAMapMissingNode> missingNodes1;
|
||||
std::vector <SHAMapMissingNode> missingNodes2;
|
||||
|
||||
if (mAccountStateMap->getHash().isZero() &&
|
||||
if (stateMap_->getHash().isZero() &&
|
||||
! mAccountHash.isZero() &&
|
||||
! mAccountStateMap->fetchRoot (mAccountHash, nullptr))
|
||||
! stateMap_->fetchRoot (mAccountHash, nullptr))
|
||||
{
|
||||
missingNodes1.emplace_back (SHAMapType::STATE, mAccountHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
mAccountStateMap->walkMap (missingNodes1, 32);
|
||||
stateMap_->walkMap (missingNodes1, 32);
|
||||
}
|
||||
|
||||
if (ShouldLog (lsINFO, Ledger) && !missingNodes1.empty ())
|
||||
@@ -1105,15 +1077,15 @@ bool Ledger::walkLedger () const
|
||||
<< "First: " << missingNodes1[0];
|
||||
}
|
||||
|
||||
if (mTransactionMap->getHash().isZero() &&
|
||||
if (txMap_->getHash().isZero() &&
|
||||
mTransHash.isNonZero() &&
|
||||
! mTransactionMap->fetchRoot (mTransHash, nullptr))
|
||||
! txMap_->fetchRoot (mTransHash, nullptr))
|
||||
{
|
||||
missingNodes2.emplace_back (SHAMapType::TRANSACTION, mTransHash);
|
||||
}
|
||||
else
|
||||
{
|
||||
mTransactionMap->walkMap (missingNodes2, 32);
|
||||
txMap_->walkMap (missingNodes2, 32);
|
||||
}
|
||||
|
||||
if (ShouldLog (lsINFO, Ledger) && !missingNodes2.empty ())
|
||||
@@ -1131,10 +1103,10 @@ bool Ledger::assertSane ()
|
||||
{
|
||||
if (mHash.isNonZero () &&
|
||||
mAccountHash.isNonZero () &&
|
||||
mAccountStateMap &&
|
||||
mTransactionMap &&
|
||||
(mAccountHash == mAccountStateMap->getHash ()) &&
|
||||
(mTransHash == mTransactionMap->getHash ()))
|
||||
stateMap_ &&
|
||||
txMap_ &&
|
||||
(mAccountHash == stateMap_->getHash ()) &&
|
||||
(mTransHash == txMap_->getHash ()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -1163,15 +1135,14 @@ void Ledger::updateSkipList ()
|
||||
// update record of every 256th ledger
|
||||
if ((prevIndex & 0xff) == 0)
|
||||
{
|
||||
auto const key = getLedgerHashIndex(prevIndex);
|
||||
auto sle = fetch(key, ltLEDGER_HASHES);
|
||||
auto const k = keylet::skip(prevIndex);
|
||||
auto sle = peek(k);
|
||||
std::vector<uint256> hashes;
|
||||
|
||||
bool created;
|
||||
if (! sle)
|
||||
{
|
||||
sle = std::make_shared<SLE>(
|
||||
ltLEDGER_HASHES, key);
|
||||
sle = std::make_shared<SLE>(k);
|
||||
created = true;
|
||||
}
|
||||
else
|
||||
@@ -1186,20 +1157,19 @@ void Ledger::updateSkipList ()
|
||||
sle->setFieldV256 (sfHashes, STVector256 (hashes));
|
||||
sle->setFieldU32 (sfLastLedgerSequence, prevIndex);
|
||||
if (created)
|
||||
insert(*sle);
|
||||
unchecked_insert(std::move(sle));
|
||||
else
|
||||
replace(*sle);
|
||||
unchecked_replace(std::move(sle));
|
||||
}
|
||||
|
||||
// update record of past 256 ledger
|
||||
auto const key = getLedgerHashIndex();
|
||||
auto sle = fetch(key, ltLEDGER_HASHES);
|
||||
auto const k = keylet::skip();
|
||||
auto sle = peek(k);
|
||||
std::vector <uint256> hashes;
|
||||
bool created;
|
||||
if (! sle)
|
||||
{
|
||||
sle = std::make_shared<SLE>(
|
||||
ltLEDGER_HASHES, key);
|
||||
sle = std::make_shared<SLE>(k);
|
||||
created = true;
|
||||
}
|
||||
else
|
||||
@@ -1215,9 +1185,9 @@ void Ledger::updateSkipList ()
|
||||
sle->setFieldV256 (sfHashes, STVector256 (hashes));
|
||||
sle->setFieldU32 (sfLastLedgerSequence, prevIndex);
|
||||
if (created)
|
||||
insert(*sle);
|
||||
unchecked_insert(std::move(sle));
|
||||
else
|
||||
replace(*sle);
|
||||
unchecked_replace(std::move(sle));
|
||||
}
|
||||
|
||||
/** Save, or arrange to save, a fully-validated ledger
|
||||
@@ -1260,12 +1230,14 @@ bool Ledger::pendSaveValidated (bool isSynchronous, bool isCurrent)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Ledger::ownerDirDescriber (SLE::ref sle, bool, AccountID const& owner)
|
||||
void
|
||||
ownerDirDescriber (SLE::ref sle, bool, AccountID const& owner)
|
||||
{
|
||||
sle->setFieldAccount (sfOwner, owner);
|
||||
}
|
||||
|
||||
void Ledger::qualityDirDescriber (
|
||||
void
|
||||
qualityDirDescriber (
|
||||
SLE::ref sle, bool isNew,
|
||||
Currency const& uTakerPaysCurrency, AccountID const& uTakerPaysIssuer,
|
||||
Currency const& uTakerGetsCurrency, AccountID const& uTakerGetsIssuer,
|
||||
@@ -1294,8 +1266,7 @@ void Ledger::deprecatedUpdateCachedFees() const
|
||||
std::int64_t reserveIncrement = getConfig ().FEE_OWNER_RESERVE;
|
||||
|
||||
// VFALCO NOTE this doesn't go through the SLECache
|
||||
auto const sle = this->fetch(
|
||||
getLedgerFeeIndex(), ltFEE_SETTINGS);
|
||||
auto const sle = this->read(keylet::fees());
|
||||
if (sle)
|
||||
{
|
||||
if (sle->getFieldIndex (sfBaseFee) != -1)
|
||||
@@ -1332,10 +1303,10 @@ std::vector<uint256> Ledger::getNeededTransactionHashes (
|
||||
|
||||
if (mTransHash.isNonZero ())
|
||||
{
|
||||
if (mTransactionMap->getHash ().isZero ())
|
||||
if (txMap_->getHash ().isZero ())
|
||||
ret.push_back (mTransHash);
|
||||
else
|
||||
ret = mTransactionMap->getNeededHashes (max, filter);
|
||||
ret = txMap_->getNeededHashes (max, filter);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1348,10 +1319,10 @@ std::vector<uint256> Ledger::getNeededAccountStateHashes (
|
||||
|
||||
if (mAccountHash.isNonZero ())
|
||||
{
|
||||
if (mAccountStateMap->getHash ().isZero ())
|
||||
if (stateMap_->getHash ().isZero ())
|
||||
ret.push_back (mAccountHash);
|
||||
else
|
||||
ret = mAccountStateMap->getNeededHashes (max, filter);
|
||||
ret = stateMap_->getNeededHashes (max, filter);
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -1364,12 +1335,12 @@ std::vector<uint256> Ledger::getNeededAccountStateHashes (
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
std::shared_ptr<SLE const>
|
||||
fetch (Ledger const& ledger, uint256 const& key,
|
||||
cachedRead (Ledger const& ledger, uint256 const& key,
|
||||
SLECache& cache, boost::optional<LedgerEntryType> type)
|
||||
{
|
||||
uint256 hash;
|
||||
auto const item =
|
||||
ledger.peekAccountStateMap()->peekItem(key, hash);
|
||||
ledger.stateMap().peekItem(key, hash);
|
||||
if (! item)
|
||||
return {};
|
||||
if (auto const sle = cache.fetch(hash))
|
||||
@@ -1388,105 +1359,12 @@ fetch (Ledger const& ledger, uint256 const& key,
|
||||
return sle;
|
||||
}
|
||||
|
||||
void
|
||||
forEachItem (Ledger const& ledger, AccountID const& id, SLECache& cache,
|
||||
std::function<void(std::shared_ptr<SLE const> const&)> f)
|
||||
{
|
||||
auto rootIndex = getOwnerDirIndex (id);
|
||||
auto currentIndex = rootIndex;
|
||||
for(;;)
|
||||
{
|
||||
auto ownerDir = fetch(
|
||||
ledger, currentIndex, cache, ltDIR_NODE);
|
||||
if (! ownerDir)
|
||||
return;
|
||||
for (auto const& key : ownerDir->getFieldV256 (sfIndexes))
|
||||
f(fetch(ledger, key, cache));
|
||||
auto uNodeNext =
|
||||
ownerDir->getFieldU64 (sfIndexNext);
|
||||
if (! uNodeNext)
|
||||
return;
|
||||
currentIndex = getDirNodeIndex (rootIndex, uNodeNext);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
forEachItemAfter (Ledger const& ledger, AccountID const& id, SLECache& cache,
|
||||
uint256 const& after, std::uint64_t const hint, unsigned int limit,
|
||||
std::function <bool (std::shared_ptr<SLE const> const&)> f)
|
||||
{
|
||||
auto const rootIndex = getOwnerDirIndex(id);
|
||||
auto currentIndex = rootIndex;
|
||||
|
||||
// If startAfter is not zero try jumping to that page using the hint
|
||||
if (after.isNonZero ())
|
||||
{
|
||||
auto const hintIndex = getDirNodeIndex (rootIndex, hint);
|
||||
auto hintDir = fetch(ledger, hintIndex, cache);
|
||||
if (hintDir)
|
||||
{
|
||||
for (auto const& key : hintDir->getFieldV256 (sfIndexes))
|
||||
{
|
||||
if (key == after)
|
||||
{
|
||||
// We found the hint, we can start here
|
||||
currentIndex = hintIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (;;)
|
||||
{
|
||||
auto const ownerDir = fetch(ledger, currentIndex, cache);
|
||||
if (! ownerDir || ownerDir->getType () != ltDIR_NODE)
|
||||
return found;
|
||||
for (auto const& key : ownerDir->getFieldV256 (sfIndexes))
|
||||
{
|
||||
if (! found)
|
||||
{
|
||||
if (key == after)
|
||||
found = true;
|
||||
}
|
||||
else if (f (fetch (ledger, key, cache)) && limit-- <= 1)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
auto const uNodeNext =
|
||||
ownerDir->getFieldU64(sfIndexNext);
|
||||
if (uNodeNext == 0)
|
||||
return found;
|
||||
currentIndex = getDirNodeIndex (rootIndex, uNodeNext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
auto const ownerDir = fetch(ledger, currentIndex, cache);
|
||||
if (! ownerDir || ownerDir->getType () != ltDIR_NODE)
|
||||
return true;
|
||||
for (auto const& key : ownerDir->getFieldV256 (sfIndexes))
|
||||
if (f (fetch(ledger, key, cache)) && limit-- <= 1)
|
||||
return true;
|
||||
auto const uNodeNext =
|
||||
ownerDir->getFieldU64 (sfIndexNext);
|
||||
if (uNodeNext == 0)
|
||||
return true;
|
||||
currentIndex = getDirNodeIndex (rootIndex, uNodeNext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AccountState::pointer
|
||||
getAccountState (Ledger const& ledger,
|
||||
RippleAddress const& accountID,
|
||||
SLECache& cache)
|
||||
{
|
||||
auto const sle = fetch (ledger,
|
||||
auto const sle = cachedRead (ledger,
|
||||
getAccountRootIndex(accountID.getAccountID()),
|
||||
cache);
|
||||
if (!sle)
|
||||
@@ -1528,7 +1406,7 @@ hashOfSeq (Ledger& ledger, LedgerIndex seq,
|
||||
int diff = ledger.seq() - seq;
|
||||
if (diff <= 256)
|
||||
{
|
||||
auto const hashIndex = fetch(
|
||||
auto const hashIndex = cachedRead(
|
||||
ledger, getLedgerHashIndex(), cache);
|
||||
if (hashIndex)
|
||||
{
|
||||
@@ -1559,7 +1437,7 @@ hashOfSeq (Ledger& ledger, LedgerIndex seq,
|
||||
}
|
||||
|
||||
// in skiplist
|
||||
auto const hashIndex = fetch(ledger,
|
||||
auto const hashIndex = cachedRead(ledger,
|
||||
getLedgerHashIndex(seq), cache);
|
||||
if (hashIndex)
|
||||
{
|
||||
@@ -1578,4 +1456,51 @@ hashOfSeq (Ledger& ledger, LedgerIndex seq,
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
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 (it.getVL ());
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
Ledger const*
|
||||
ledgerFromView(BasicView const* view)
|
||||
{
|
||||
do
|
||||
{
|
||||
auto const ledger =
|
||||
dynamic_cast<Ledger const*>(view);
|
||||
if (ledger)
|
||||
return ledger;
|
||||
view = view->parent();
|
||||
}
|
||||
while (view != nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This hack traverses the View chain until
|
||||
// it finds the underlying ledger then extracts
|
||||
// the parent close time.
|
||||
//
|
||||
std::uint32_t
|
||||
getParentCloseTimeNC (BasicView const& view)
|
||||
{
|
||||
auto const& ledger = *ledgerFromView(&view);
|
||||
return ledger.getParentCloseTimeNC();
|
||||
}
|
||||
|
||||
} // ripple
|
||||
|
||||
Reference in New Issue
Block a user