Refactor treatment of Ledger:

All handling of Ledger in shared_ptr is modified to
use a const managed object when the context requires
immutable semantics.
This commit is contained in:
Nik Bougalis
2016-02-21 16:56:18 -05:00
parent 77a4218a9e
commit 34e85ccb62
50 changed files with 788 additions and 782 deletions

View File

@@ -41,7 +41,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (
, accountCache_ (accountCache)
, logs_ (logs)
{
assert (! ledger->info().open);
assert (! ledger->open());
mResult = mMeta->getResultTER ();
@@ -65,7 +65,7 @@ AcceptedLedgerTx::AcceptedLedgerTx (
, accountCache_ (accountCache)
, logs_ (logs)
{
assert (ledger->info().open);
assert (ledger->open());
buildJson ();
}

View File

@@ -77,7 +77,7 @@ public:
startRound (
LedgerConsensus& consensus,
LedgerHash const &prevLCLHash,
Ledger::ref previousLedger,
std::shared_ptr<Ledger const> const& previousLedger,
NetClock::time_point closeTime) = 0;
/** Specified the network time when the last ledger closed */

View File

@@ -66,7 +66,8 @@ public:
{
return mHaveHeader;
}
Ledger::ref getLedger () const
std::shared_ptr<Ledger> const&
getLedger() const
{
return mLedger;
}
@@ -131,7 +132,7 @@ private:
bool takeAsRootNode (Blob const& data, SHAMapAddNode&);
private:
Ledger::pointer mLedger;
std::shared_ptr<Ledger> mLedger;
bool mHaveHeader;
bool mHaveState;
bool mHaveTransactions;

View File

@@ -40,7 +40,9 @@ public:
// VFALCO TODO Should this be called findOrAdd ?
//
virtual Ledger::pointer acquire (uint256 const& hash,
virtual
std::shared_ptr<Ledger>
acquire (uint256 const& hash,
std::uint32_t seq, InboundLedger::fcReason) = 0;
virtual std::shared_ptr<InboundLedger> find (LedgerHash const& hash) = 0;

View File

@@ -179,6 +179,7 @@ Ledger::Ledger (create_genesis_t, Config const& config, Family& family)
info_.seq = 1;
info_.drops = SYSTEM_CURRENCY_START;
info_.closeTimeResolution = ledgerDefaultTimeResolution;
static auto const id = calcAccountID(
generateKeyPair(KeyType::secp256k1,
generateSeed("masterpassphrase")).first);
@@ -189,7 +190,6 @@ Ledger::Ledger (create_genesis_t, Config const& config, Family& family)
rawInsert(sle);
stateMap_->flushDirty (hotACCOUNT_NODE, info_.seq);
updateHash();
setClosed();
setImmutable(config);
setup(config);
}
@@ -210,8 +210,8 @@ Ledger::Ledger (uint256 const& parentHash,
: mImmutable (true)
, txMap_ (std::make_shared <SHAMap> (
SHAMapType::TRANSACTION, transHash, family))
, stateMap_ (std::make_shared <SHAMap> (SHAMapType::STATE, accountHash,
family))
, stateMap_ (std::make_shared <SHAMap> (
SHAMapType::STATE, accountHash, family))
{
info_.seq = ledgerSeq;
info_.parentCloseTime = parentCloseTime;
@@ -222,6 +222,7 @@ Ledger::Ledger (uint256 const& parentHash,
info_.parentHash = parentHash;
info_.closeTimeResolution = closeResolution;
info_.closeFlags = closeFlags;
loaded = true;
if (info_.txHash.isNonZero () &&
@@ -251,20 +252,8 @@ Ledger::Ledger (uint256 const& parentHash,
}
}
// Create a new ledger that's a snapshot of this one
Ledger::Ledger (Ledger const& ledger,
bool isMutable)
: mImmutable (!isMutable)
, txMap_ (ledger.txMap_->snapShot (isMutable))
, stateMap_ (ledger.stateMap_->snapShot (isMutable))
, fees_ (ledger.fees_)
, info_ (ledger.info_)
{
updateHash ();
}
// Create a new open ledger that follows this one
Ledger::Ledger (open_ledger_t, Ledger const& prevLedger,
// Create a new ledger that follows this one
Ledger::Ledger (Ledger const& prevLedger,
NetClock::time_point closeTime)
: mImmutable (false)
, txMap_ (std::make_shared <SHAMap> (SHAMapType::TRANSACTION,
@@ -273,14 +262,13 @@ Ledger::Ledger (open_ledger_t, Ledger const& prevLedger,
, fees_(prevLedger.fees_)
, rules_(prevLedger.rules_)
{
info_.open = true;
info_.seq = prevLedger.info_.seq + 1;
info_.parentCloseTime =
prevLedger.info_.closeTime;
info_.hash = prevLedger.info().hash + uint256(1);
info_.drops = prevLedger.info().drops;
info_.closeTimeResolution = prevLedger.info_.closeTimeResolution;
info_.parentHash = prevLedger.getHash ();
info_.parentHash = prevLedger.info().hash;
info_.closeTimeResolution = getNextLedgerTimeResolution(
prevLedger.info_.closeTimeResolution,
getCloseAgree(prevLedger.info()), info_.seq);
@@ -374,39 +362,13 @@ void Ledger::updateHash()
mValidHash = true;
}
void Ledger::setRaw (SerialIter& sit, bool hasPrefix, Family& family)
{
if (hasPrefix)
sit.get32 ();
info_.seq = sit.get32 ();
info_.drops = sit.get64 ();
info_.parentHash = sit.get256 ();
info_.txHash = sit.get256 ();
info_.accountHash = sit.get256 ();
info_.parentCloseTime = NetClock::time_point{NetClock::duration{sit.get32()}};
info_.closeTime = NetClock::time_point{NetClock::duration{sit.get32()}};
info_.closeTimeResolution = NetClock::duration{sit.get8()};
info_.closeFlags = sit.get8 ();
updateHash ();
txMap_ = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, info_.txHash,
family);
stateMap_ = std::make_shared<SHAMap> (SHAMapType::STATE, info_.accountHash,
family);
}
void Ledger::addRaw (Serializer& s) const
{
ripple::addRaw(info_, s);
}
void
Ledger::setAccepted(NetClock::time_point closeTime,
NetClock::duration closeResolution,
bool correctCloseTime, Config const& config)
{
// Used when we witnessed the consensus.
assert (closed());
assert (!open());
info_.closeTime = closeTime;
info_.closeTimeResolution = closeResolution;
@@ -453,7 +415,7 @@ deserializeTxPlusMeta (SHAMapItem const& item)
return result;
}
void Ledger::setAcquiring (void)
void Ledger::setAcquiring ()
{
if (!txMap_ || !stateMap_)
Throw<std::runtime_error> ("invalid map");
@@ -462,21 +424,6 @@ void Ledger::setAcquiring (void)
stateMap_->setSynching ();
}
bool Ledger::isAcquiring (void) const
{
return isAcquiringTx () || isAcquiringAS ();
}
bool Ledger::isAcquiringTx (void) const
{
return txMap_->isSynching ();
}
bool Ledger::isAcquiringAS (void) const
{
return stateMap_->isSynching ();
}
//------------------------------------------------------------------------------
bool
@@ -555,18 +502,16 @@ auto
Ledger::txsBegin() const ->
std::unique_ptr<txs_type::iter_base>
{
return std::make_unique<
txs_iter_impl>(closed(),
txMap_->begin(), *this);
return std::make_unique<txs_iter_impl>(
!open(), txMap_->begin(), *this);
}
auto
Ledger::txsEnd() const ->
std::unique_ptr<txs_type::iter_base>
{
return std::make_unique<
txs_iter_impl>(closed(),
txMap_->end(), *this);
return std::make_unique<txs_iter_impl>(
!open(), txMap_->end(), *this);
}
bool
@@ -584,7 +529,7 @@ Ledger::txRead(
txMap_->peekItem(key);
if (! item)
return {};
if (closed())
if (!open())
{
auto result =
deserializeTxPlusMeta(*item);
@@ -649,30 +594,18 @@ Ledger::rawTxInsert (uint256 const& key,
> const& txn, std::shared_ptr<
Serializer const> const& metaData)
{
assert (static_cast<bool>(metaData) != info_.open);
assert (metaData);
if (metaData)
{
// low-level - just add to table
Serializer s(txn->getDataLength () +
metaData->getDataLength () + 16);
s.addVL (txn->peekData ());
s.addVL (metaData->peekData ());
auto item = std::make_shared<
SHAMapItem const> (key, std::move(s));
if (! txMap().addGiveItem
(std::move(item), true, true))
LogicError("duplicate_tx: " + to_string(key));
}
else
{
// low-level - just add to table
auto item = std::make_shared<
SHAMapItem const>(key, txn->peekData());
if (! txMap().addGiveItem(
std::move(item), true, false))
LogicError("duplicate_tx: " + to_string(key));
}
// low-level - just add to table
Serializer s(txn->getDataLength () +
metaData->getDataLength () + 16);
s.addVL (txn->peekData ());
s.addVL (metaData->peekData ());
auto item = std::make_shared<
SHAMapItem const> (key, std::move(s));
if (! txMap().addGiveItem
(std::move(item), true, true))
LogicError("duplicate_tx: " + to_string(key));
}
bool
@@ -910,8 +843,31 @@ void Ledger::updateSkipList ()
rawReplace(sle);
}
void Ledger::setRaw (SerialIter& sit, bool hasPrefix, Family& family)
{
if (hasPrefix)
sit.get32 ();
info_.seq = sit.get32 ();
info_.drops = sit.get64 ();
info_.parentHash = sit.get256 ();
info_.txHash = sit.get256 ();
info_.accountHash = sit.get256 ();
info_.parentCloseTime = NetClock::time_point{NetClock::duration{sit.get32()}};
info_.closeTime = NetClock::time_point{NetClock::duration{sit.get32()}};
info_.closeTimeResolution = NetClock::duration{sit.get8()};
info_.closeFlags = sit.get8 ();
updateHash ();
txMap_ = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, info_.txHash,
family);
stateMap_ = std::make_shared<SHAMap> (SHAMapType::STATE, info_.accountHash,
family);
}
static bool saveValidatedLedger (
Application& app, std::shared_ptr<Ledger> const& ledger, bool current)
Application& app,
std::shared_ptr<Ledger const> const& ledger,
bool current)
{
auto j = app.journal ("Ledger");
@@ -969,7 +925,7 @@ static bool saveValidatedLedger (
{
Serializer s (128);
s.add32 (HashPrefix::ledgerMaster);
ledger->addRaw (s);
addRaw(ledger->info(), s);
app.getNodeStore ().store (
hotLEDGER, std::move (s.modData ()), ledger->info().hash);
}
@@ -1099,8 +1055,11 @@ static bool saveValidatedLedger (
/** Save, or arrange to save, a fully-validated ledger
Returns false on error
*/
bool pendSaveValidated (Application& app,
std::shared_ptr<Ledger> const& ledger, bool isSynchronous, bool isCurrent)
bool pendSaveValidated (
Application& app,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent)
{
if (! app.getHashRouter ().setFlags (ledger->info().hash, SF_SAVED))
{
@@ -1221,10 +1180,9 @@ Ledger::getNeededAccountStateHashes (
* (typically a where clause).
* @return The ledger, ledger sequence, and ledger hash.
*/
std::tuple<Ledger::pointer, std::uint32_t, uint256>
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
loadLedgerHelper(std::string const& sqlSuffix, Application& app)
{
Ledger::pointer ledger;
uint256 ledgerHash{};
std::uint32_t ledgerSeq{0};
@@ -1258,7 +1216,10 @@ loadLedgerHelper(std::string const& sqlSuffix, Application& app)
if (!db->got_data ())
{
JLOG (app.journal("Ledger").debug) << "Ledger not found: " << sqlSuffix;
return std::make_tuple (Ledger::pointer (), ledgerSeq, ledgerHash);
return std::make_tuple (
std::shared_ptr<Ledger>(),
ledgerSeq,
ledgerHash);
}
ledgerSeq =
@@ -1277,45 +1238,49 @@ loadLedgerHelper(std::string const& sqlSuffix, Application& app)
using time_point = NetClock::time_point;
using duration = NetClock::duration;
bool loaded = false;
ledger = std::make_shared<Ledger>(prevHash,
transHash,
accountHash,
totDrops.value_or(0),
time_point{duration{closingTime.value_or(0)}},
time_point{duration{prevClosingTime.value_or(0)}},
closeFlags.value_or(0),
duration{closeResolution.value_or(0)},
ledgerSeq,
loaded,
app.config(),
app.family(),
app.journal("Ledger"));
auto ledger = std::make_shared<Ledger>(
prevHash,
transHash,
accountHash,
totDrops.value_or(0),
time_point{duration{closingTime.value_or(0)}},
time_point{duration{prevClosingTime.value_or(0)}},
closeFlags.value_or(0),
duration{closeResolution.value_or(0)},
ledgerSeq,
loaded,
app.config(),
app.family(),
app.journal("Ledger"));
if (!loaded)
return std::make_tuple (Ledger::pointer (), ledgerSeq, ledgerHash);
ledger.reset();
return std::make_tuple (ledger, ledgerSeq, ledgerHash);
}
static
void finishLoadByIndexOrHash(Ledger::pointer& ledger, Config const& config, beast::Journal j)
void finishLoadByIndexOrHash(
std::shared_ptr<Ledger> const& ledger,
Config const& config,
beast::Journal j)
{
if (!ledger)
return;
ledger->setClosed ();
ledger->setImmutable (config);
JLOG (j.trace)
<< "Loaded ledger: " << to_string (ledger->getHash ());
<< "Loaded ledger: " << to_string (ledger->info().hash);
ledger->setFull ();
}
Ledger::pointer
std::shared_ptr<Ledger>
loadByIndex (std::uint32_t ledgerIndex, Application& app)
{
Ledger::pointer ledger;
std::shared_ptr<Ledger> ledger;
{
std::ostringstream s;
s << "WHERE LedgerSeq = " << ledgerIndex;
@@ -1323,14 +1288,15 @@ loadByIndex (std::uint32_t ledgerIndex, Application& app)
loadLedgerHelper (s.str (), app);
}
finishLoadByIndexOrHash (ledger, app.config(), app.journal ("Ledger"));
finishLoadByIndexOrHash (ledger, app.config(),
app.journal ("Ledger"));
return ledger;
}
Ledger::pointer
std::shared_ptr<Ledger>
loadByHash (uint256 const& ledgerHash, Application& app)
{
Ledger::pointer ledger;
std::shared_ptr<Ledger> ledger;
{
std::ostringstream s;
s << "WHERE LedgerHash = '" << ledgerHash << "'";
@@ -1338,9 +1304,10 @@ loadByHash (uint256 const& ledgerHash, Application& app)
loadLedgerHelper (s.str (), app);
}
finishLoadByIndexOrHash (ledger, app.config(), app.journal ("Ledger"));
finishLoadByIndexOrHash (ledger, app.config(),
app.journal ("Ledger"));
assert (!ledger || ledger->getHash () == ledgerHash);
assert (!ledger || ledger->info().hash == ledgerHash);
return ledger;
}

View File

@@ -80,9 +80,6 @@ class Ledger final
public:
static char const* getCountedObjectName () { return "Ledger"; }
using pointer = std::shared_ptr<Ledger>;
using ref = const std::shared_ptr<Ledger>&;
Ledger (Ledger const&) = delete;
Ledger& operator= (Ledger const&) = delete;
@@ -110,16 +107,13 @@ public:
Family& family,
beast::Journal j);
// Create a new ledger that's a snapshot of this one
Ledger (Ledger const& target, bool isMutable);
/** Create a new open ledger
/** Create a new ledger following a previous ledger
The ledger will have the sequence number that
follows previous, and have
parentCloseTime == previous.closeTime.
*/
Ledger (open_ledger_t, Ledger const& previous,
Ledger (Ledger const& previous,
NetClock::time_point closeTime);
Ledger (void const* data,
@@ -137,6 +131,12 @@ public:
// ReadView
//
bool
open() const override
{
return false;
}
LedgerInfo const&
info() const override
{
@@ -227,12 +227,7 @@ public:
//--------------------------------------------------------------------------
void setClosed()
{
info_.open = false;
}
void setValidated()
void setValidated() const
{
info_.validated = true;
}
@@ -248,27 +243,23 @@ public:
return mImmutable;
}
// Indicates that all ledger entries
// are available locally. For example,
// all in the NodeStore and memory.
void setFull ()
/* Mark this ledger as "should be full".
"Full" is metadata property of the ledger, it indicates
that the local server wants all the corresponding nodes
in durable storage.
This is marked `const` because it reflects metadata
and not data that is in common with other nodes on the
network.
*/
void
setFull() const
{
txMap_->setLedgerSeq (info_.seq);
stateMap_->setLedgerSeq (info_.seq);
}
// ledger signature operations
void addRaw (Serializer& s) const;
void setRaw (SerialIter& sit, bool hasPrefix, Family& family);
// DEPRECATED
// Remove contract.h include
uint256 const&
getHash() const
{
return info_.hash;
}
void setTotalDrops (std::uint64_t totDrops)
{
info_.drops = totDrops;
@@ -302,10 +293,7 @@ public:
bool addSLE (SLE const& sle);
// ledger sync functions
void setAcquiring (void);
bool isAcquiring (void) const;
bool isAcquiringTx (void) const;
bool isAcquiringAS (void) const;
void setAcquiring ();
//--------------------------------------------------------------------------
@@ -328,7 +316,7 @@ private:
class sles_iter_impl;
class txs_iter_impl;
bool saveValidatedLedger (bool current);
void setRaw (SerialIter& sit, bool hasPrefix, Family& family);
bool
setup (Config const& config);
@@ -339,8 +327,6 @@ private:
void
updateHash();
// The basic Ledger structure, can be opened, closed, or synching
bool mValidHash = false;
bool mImmutable;
@@ -368,22 +354,22 @@ extern
bool
pendSaveValidated(
Application& app,
std::shared_ptr<Ledger> const& ledger,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent);
extern
Ledger::pointer
std::shared_ptr<Ledger>
loadByIndex (std::uint32_t ledgerIndex,
Application& app);
extern
std::tuple<Ledger::pointer, std::uint32_t, uint256>
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
loadLedgerHelper(std::string const& sqlSuffix,
Application& app);
extern
Ledger::pointer
std::shared_ptr<Ledger>
loadByHash (uint256 const& ledgerHash, Application& app);
extern

View File

@@ -56,7 +56,7 @@ public:
virtual void startRound (
LedgerHash const& prevLCLHash,
Ledger::ref prevLedger,
std::shared_ptr<Ledger const> const& prevLedger,
NetClock::time_point closeTime,
int previousProposers,
std::chrono::milliseconds previousConvergeTime) = 0;
@@ -90,7 +90,7 @@ void applyTransactions (
Application& app,
SHAMap const* set,
OpenView& view,
Ledger::ref checkLedger,
ReadView const& checkLedger,
CanonicalTXSet& retriableTransactions,
ApplyFlags flags);

View File

@@ -22,6 +22,7 @@
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/contract.h>
#include <ripple/json/to_string.h>
namespace ripple {
@@ -52,17 +53,22 @@ LedgerHistory::LedgerHistory (
{
}
bool LedgerHistory::addLedger (Ledger::pointer ledger, bool validated)
bool
LedgerHistory::insert(
std::shared_ptr<Ledger const> ledger,
bool validated)
{
assert (ledger && ledger->isImmutable ());
if(! ledger->isImmutable())
LogicError("mutable Ledger in insert");
assert (ledger->stateMap().getHash ().isNonZero ());
LedgersByHash::ScopedLockType sl (m_ledgers_by_hash.peekMutex ());
const bool alreadyHad = m_ledgers_by_hash.canonicalize (
ledger->getHash(), ledger, true);
ledger->info().hash, ledger, true);
if (validated)
mLedgersByIndex[ledger->info().seq] = ledger->getHash();
mLedgersByIndex[ledger->info().seq] = ledger->info().hash;
return alreadyHad;
}
@@ -78,7 +84,8 @@ LedgerHash LedgerHistory::getLedgerHash (LedgerIndex index)
return uint256 ();
}
Ledger::pointer LedgerHistory::getLedgerBySeq (LedgerIndex index)
std::shared_ptr<Ledger const>
LedgerHistory::getLedgerBySeq (LedgerIndex index)
{
{
LedgersByHash::ScopedLockType sl (m_ledgers_by_hash.peekMutex ());
@@ -92,7 +99,7 @@ Ledger::pointer LedgerHistory::getLedgerBySeq (LedgerIndex index)
}
}
Ledger::pointer ret = loadByIndex (index, app_);
std::shared_ptr<Ledger const> ret = loadByIndex (index, app_);
if (!ret)
return ret;
@@ -104,20 +111,21 @@ Ledger::pointer LedgerHistory::getLedgerBySeq (LedgerIndex index)
LedgersByHash::ScopedLockType sl (m_ledgers_by_hash.peekMutex ());
assert (ret->isImmutable ());
m_ledgers_by_hash.canonicalize (ret->getHash (), ret);
mLedgersByIndex[ret->info().seq] = ret->getHash ();
return (ret->info().seq == index) ? ret : Ledger::pointer ();
m_ledgers_by_hash.canonicalize (ret->info().hash, ret);
mLedgersByIndex[ret->info().seq] = ret->info().hash;
return (ret->info().seq == index) ? ret : nullptr;
}
}
Ledger::pointer LedgerHistory::getLedgerByHash (LedgerHash const& hash)
std::shared_ptr<Ledger const>
LedgerHistory::getLedgerByHash (LedgerHash const& hash)
{
Ledger::pointer ret = m_ledgers_by_hash.fetch (hash);
auto ret = m_ledgers_by_hash.fetch (hash);
if (ret)
{
assert (ret->isImmutable ());
assert (ret->getHash () == hash);
assert (ret->info().hash == hash);
return ret;
}
@@ -127,19 +135,22 @@ Ledger::pointer LedgerHistory::getLedgerByHash (LedgerHash const& hash)
return ret;
assert (ret->isImmutable ());
assert (ret->getHash () == hash);
m_ledgers_by_hash.canonicalize (ret->getHash (), ret);
assert (ret->getHash () == hash);
assert (ret->info().hash == hash);
m_ledgers_by_hash.canonicalize (ret->info().hash, ret);
assert (ret->info().hash == hash);
return ret;
}
static
void
log_one(Ledger::pointer ledger, uint256 const& tx, char const* msg,
log_one(
ReadView const& ledger,
uint256 const& tx,
char const* msg,
beast::Journal& j)
{
auto metaData = ledger->txRead(tx).second;
auto metaData = ledger.txRead(tx).second;
if (metaData != nullptr)
{
@@ -157,10 +168,12 @@ log_one(Ledger::pointer ledger, uint256 const& tx, char const* msg,
static
void
log_metadata_difference(
Ledger::pointer builtLedger, Ledger::pointer validLedger, uint256 const& tx,
ReadView const& builtLedger,
ReadView const& validLedger,
uint256 const& tx,
beast::Journal j)
{
auto getMeta = [j](Ledger const& ledger,
auto getMeta = [j](ReadView const& ledger,
uint256 const& txID) -> std::shared_ptr<TxMeta>
{
auto meta = ledger.txRead(txID).second;
@@ -169,8 +182,8 @@ log_metadata_difference(
return std::make_shared<TxMeta> (txID, ledger.seq(), *meta, j);
};
auto validMetaData = getMeta (*validLedger, tx);
auto builtMetaData = getMeta (*builtLedger, tx);
auto validMetaData = getMeta (validLedger, tx);
auto builtMetaData = getMeta (builtLedger, tx);
assert(validMetaData != nullptr || builtMetaData != nullptr);
if (validMetaData != nullptr && builtMetaData != nullptr)
@@ -299,15 +312,16 @@ leaves (SHAMap const& sm)
return v;
}
void LedgerHistory::handleMismatch (
LedgerHash const& built, LedgerHash const& valid, Json::Value const& consensus)
LedgerHash const& built,
LedgerHash const& valid,
Json::Value const& consensus)
{
assert (built != valid);
++mismatch_counter_;
Ledger::pointer builtLedger = getLedgerByHash (built);
Ledger::pointer validLedger = getLedgerByHash (valid);
auto builtLedger = getLedgerByHash (built);
auto validLedger = getLedgerByHash (valid);
if (!builtLedger || !validLedger)
{
@@ -326,19 +340,19 @@ void LedgerHistory::handleMismatch (
j_.debug << "Consensus: " << consensus;
}
// Determine the mismatch reason
// Distinguish Byzantine failure from transaction processing difference
// Determine the mismatch reason, distinguishing Byzantine
// failure from transaction processing difference
// Disagreement over prior ledger indicates sync issue
if (builtLedger->info().parentHash != validLedger->info().parentHash)
{
// Disagreement over prior ledger indicates sync issue
JLOG (j_.error) << "MISMATCH on prior ledger";
return;
}
// Disagreement over close time indicates Byzantine failure
if (builtLedger->info().closeTime != validLedger->info().closeTime)
{
// Disagreement over close time indicates Byzantine failure
JLOG (j_.error) << "MISMATCH on close time";
return;
}
@@ -346,18 +360,18 @@ void LedgerHistory::handleMismatch (
// Find differences between built and valid ledgers
auto const builtTx = leaves(builtLedger->txMap());
auto const validTx = leaves(validLedger->txMap());
if (builtTx == validTx)
JLOG (j_.error) <<
"MISMATCH with same " << builtTx.size() << " transactions";
"MISMATCH with same " << builtTx.size() <<
" transactions";
else
JLOG (j_.error) << "MISMATCH with " <<
builtTx.size() << " built and " <<
validTx.size() << " valid transactions.";
JLOG (j_.error) << "built\n" <<
getJson(*builtLedger);
JLOG (j_.error) << "valid\n" <<
getJson(*validLedger);
JLOG (j_.error) << "built\n" << getJson(*builtLedger);
JLOG (j_.error) << "valid\n" << getJson(*validLedger);
// Log all differences between built and valid ledgers
auto b = builtTx.begin();
@@ -366,12 +380,12 @@ void LedgerHistory::handleMismatch (
{
if ((*b)->key() < (*v)->key())
{
log_one (builtLedger, (*b)->key(), "valid", j_);
log_one (*builtLedger, (*b)->key(), "valid", j_);
++b;
}
else if ((*b)->key() > (*v)->key())
{
log_one(validLedger, (*v)->key(), "built", j_);
log_one(*validLedger, (*v)->key(), "built", j_);
++v;
}
else
@@ -379,23 +393,28 @@ void LedgerHistory::handleMismatch (
if ((*b)->peekData() != (*v)->peekData())
{
// Same transaction with different metadata
log_metadata_difference(builtLedger, validLedger, (*b)->key(), j_);
log_metadata_difference(
*builtLedger,
*validLedger, (*b)->key(), j_);
}
++b;
++v;
}
}
for (; b != builtTx.end(); ++b)
log_one (builtLedger, (*b)->key(), "valid", j_);
log_one (*builtLedger, (*b)->key(), "valid", j_);
for (; v != validTx.end(); ++v)
log_one (validLedger, (*v)->key(), "built", j_);
log_one (*validLedger, (*v)->key(), "built", j_);
}
void LedgerHistory::builtLedger (Ledger::ref ledger, Json::Value consensus)
void LedgerHistory::builtLedger (
std::shared_ptr<Ledger const> const& ledger,
Json::Value consensus)
{
LedgerIndex index = ledger->info().seq;
LedgerHash hash = ledger->getHash();
LedgerHash hash = ledger->info().hash;
assert (!hash.isZero());
ConsensusValidated::ScopedLockType sl (
m_consensus_validated.peekMutex());
@@ -422,11 +441,13 @@ void LedgerHistory::builtLedger (Ledger::ref ledger, Json::Value consensus)
entry->consensus.emplace (std::move (consensus));
}
void LedgerHistory::validatedLedger (Ledger::ref ledger)
void LedgerHistory::validatedLedger (
std::shared_ptr<Ledger const> const& ledger)
{
LedgerIndex index = ledger->info().seq;
LedgerHash hash = ledger->getHash();
LedgerHash hash = ledger->info().hash;
assert (!hash.isZero());
ConsensusValidated::ScopedLockType sl (
m_consensus_validated.peekMutex());

View File

@@ -40,7 +40,8 @@ public:
/** Track a ledger
@return `true` if the ledger was already tracked
*/
bool addLedger (Ledger::pointer ledger, bool validated);
bool insert (std::shared_ptr<Ledger const> ledger,
bool validated);
/** Get the ledgers_by_hash cache hit rate
@return the hit rate
@@ -50,10 +51,13 @@ public:
return m_ledgers_by_hash.getHitRate ();
}
/** Get a ledger given its squence number
@param ledgerIndex The sequence number of the desired ledger
*/
Ledger::pointer getLedgerBySeq (LedgerIndex ledgerIndex);
/** Get a ledger given its squence number */
std::shared_ptr<Ledger const>
getLedgerBySeq (LedgerIndex ledgerIndex);
/** Retrieve a ledger given its hash */
std::shared_ptr<Ledger const>
getLedgerByHash (LedgerHash const& ledgerHash);
/** Get a ledger's hash given its sequence number
@param ledgerIndex The sequence number of the desired ledger
@@ -61,12 +65,6 @@ public:
*/
LedgerHash getLedgerHash (LedgerIndex ledgerIndex);
/** Retrieve a ledger given its hash
@param ledgerHash The hash of the requested ledger
@return The ledger requested
*/
Ledger::pointer getLedgerByHash (LedgerHash const& ledgerHash);
/** Set the history cache's paramters
@param size The target size of the cache
@param age The target age of the cache, in seconds
@@ -81,13 +79,14 @@ public:
m_consensus_validated.sweep ();
}
/** Report that we have locally built a particular ledger
*/
void builtLedger (Ledger::ref, Json::Value);
/** Report that we have locally built a particular ledger */
void builtLedger (
std::shared_ptr<Ledger const> const&,
Json::Value);
/** Report that we have validated a particular ledger
*/
void validatedLedger (Ledger::ref);
/** Report that we have validated a particular ledger */
void validatedLedger (
std::shared_ptr<Ledger const> const&);
/** Repair a hash to index mapping
@param ledgerIndex The index whose mapping is to be repaired
@@ -113,7 +112,7 @@ private:
beast::insight::Collector::ptr collector_;
beast::insight::Counter mismatch_counter_;
using LedgersByHash = TaggedCache <LedgerHash, Ledger>;
using LedgersByHash = TaggedCache <LedgerHash, Ledger const>;
LedgersByHash m_ledgers_by_hash;

View File

@@ -20,44 +20,42 @@
#ifndef RIPPLE_APP_LEDGER_LEDGERHOLDER_H_INCLUDED
#define RIPPLE_APP_LEDGER_LEDGERHOLDER_H_INCLUDED
#include <ripple/basics/contract.h>
#include <mutex>
namespace ripple {
// Can std::atomic<std::shared_ptr>> make this lock free?
// VFALCO NOTE This class can be replaced with atomic<shared_ptr<...>>
/** Hold a ledger in a thread-safe way.
VFALCO TODO The constructor should require a valid ledger, this
way the object always holds a value. We can use the
genesis ledger in all cases.
*/
class LedgerHolder
{
public:
// Update the held ledger
void set (Ledger::pointer ledger)
void set (std::shared_ptr<Ledger const> ledger)
{
// The held ledger must always be immutable
if (ledger && !ledger->isImmutable ())
ledger = std::make_shared <Ledger> (*ledger, false);
{
std::lock_guard <std::mutex> sl (m_lock);
m_heldLedger = ledger;
}
if(! ledger)
LogicError("LedgerHolder::set with nullptr");
if(! ledger->isImmutable())
LogicError("LedgerHolder::set with mutable Ledger");
std::lock_guard <std::mutex> sl (m_lock);
m_heldLedger = std::move(ledger);
}
// Return the (immutable) held ledger
Ledger::pointer get ()
std::shared_ptr<Ledger const> get ()
{
std::lock_guard <std::mutex> sl (m_lock);
return m_heldLedger;
}
// Return a mutable snapshot of the held ledger
Ledger::pointer getMutable ()
{
Ledger::pointer ret = get ();
return ret ? std::make_shared <Ledger> (*ret, true) : ret;
}
bool empty ()
{
std::lock_guard <std::mutex> sl (m_lock);
@@ -66,7 +64,7 @@ public:
private:
std::mutex m_lock;
Ledger::pointer m_heldLedger;
std::shared_ptr<Ledger const> m_heldLedger;
};
} // ripple

View File

@@ -49,7 +49,7 @@ struct LedgerReplay
std::map< int, std::shared_ptr<STTx const> > txns_;
NetClock::time_point closeTime_;
int closeFlags_;
Ledger::pointer prevLedger_;
std::shared_ptr<Ledger const> prevLedger_;
};
// Tracks the current ledger and any ledgers in the process of closing
@@ -69,37 +69,43 @@ public:
beast::insight::Collector::ptr const& collector,
beast::Journal journal);
public:
using callback = std::function <void (Ledger::ref)>;
public:
virtual ~LedgerMaster () = default;
LedgerIndex getCurrentLedgerIndex ();
LedgerIndex getValidLedgerIndex ();
bool isCompatible (Ledger::pointer,
beast::Journal::Stream, const char* reason);
bool isCompatible (
ReadView const&,
beast::Journal::Stream,
char const* reason);
std::recursive_mutex& peekMutex ();
// The current ledger is the ledger we believe new transactions should go in
std::shared_ptr<ReadView const> getCurrentLedger ();
std::shared_ptr<ReadView const>
getCurrentLedger();
// The finalized ledger is the last closed/accepted ledger
Ledger::pointer getClosedLedger ();
std::shared_ptr<Ledger const>
getClosedLedger()
{
return mClosedLedger.get();
}
// The validated ledger is the last fully validated ledger
Ledger::pointer getValidatedLedger ();
std::shared_ptr<Ledger const>
getValidatedLedger ()
{
return mValidLedger.get();
}
// The Rules are in the last fully validated ledger if there is one.
Rules getValidatedRules();
// This is the last ledger we published to clients and can lag the validated
// ledger
Ledger::pointer getPublishedLedger ();
bool isValidLedger(LedgerInfo const&);
std::shared_ptr<ReadView const>
getPublishedLedger();
std::chrono::seconds getPublishedLedgerAge ();
std::chrono::seconds getValidatedLedgerAge ();
@@ -111,13 +117,13 @@ public:
std::uint32_t getEarliestFetch ();
bool storeLedger (Ledger::pointer);
void forceValid (Ledger::pointer);
bool storeLedger (std::shared_ptr<Ledger const> ledger);
void setFullLedger (
Ledger::pointer ledger, bool isSynchronous, bool isCurrent);
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous, bool isCurrent);
void switchLCL (Ledger::pointer lastClosed);
void switchLCL (std::shared_ptr<Ledger const> const& lastClosed);
void failedSave(std::uint32_t seq, uint256 const& hash);
@@ -144,9 +150,9 @@ public:
*/
uint256 getHashBySeq (std::uint32_t index);
/** Walk to a ledger's hash using the skip list
*/
/** Walk to a ledger's hash using the skip list */
boost::optional<LedgerHash> walkHashBySeq (std::uint32_t index);
/** Walk the chain of ledger hashes to determine the hash of the
ledger with the specified index. The referenceLedger is used as
the base of the chain and should be fully validated and must not
@@ -155,17 +161,21 @@ public:
in the node store.
*/
boost::optional<LedgerHash> walkHashBySeq (
std::uint32_t index, Ledger::ref referenceLedger);
std::uint32_t index,
std::shared_ptr<ReadView const> const& referenceLedger);
Ledger::pointer getLedgerBySeq (std::uint32_t index);
std::shared_ptr<Ledger const>
getLedgerBySeq (std::uint32_t index);
Ledger::pointer getLedgerByHash (uint256 const& hash);
std::shared_ptr<Ledger const>
getLedgerByHash (uint256 const& hash);
void setLedgerRangePresent (
std::uint32_t minV, std::uint32_t maxV);
boost::optional<LedgerHash> getLedgerHash(
std::uint32_t desiredSeq, Ledger::ref knownGoodLedger);
std::uint32_t desiredSeq,
std::shared_ptr<ReadView const> const& knownGoodLedger);
boost::optional <NetClock::time_point> getCloseTimeBySeq (
LedgerIndex ledgerIndex);
@@ -174,7 +184,7 @@ public:
LedgerHash const& ledgerHash);
void addHeldTransaction (std::shared_ptr<Transaction> const& trans);
void fixMismatch (Ledger::ref ledger);
void fixMismatch (ReadView const& ledger);
bool haveLedger (std::uint32_t seq);
void clearLedger (std::uint32_t seq);
@@ -187,9 +197,9 @@ public:
void sweep ();
float getCacheHitRate ();
void checkAccept (Ledger::ref ledger);
void checkAccept (std::shared_ptr<Ledger const> const& ledger);
void checkAccept (uint256 const& hash, std::uint32_t seq);
void consensusBuilt (Ledger::ref ledger, Json::Value consensus);
void consensusBuilt (std::shared_ptr<Ledger const> const& ledger, Json::Value consensus);
LedgerIndex getBuildingLedger ();
void setBuildingLedger (LedgerIndex index);
@@ -235,9 +245,15 @@ public:
std::size_t getFetchPackCacheSize () const;
private:
void setValidLedger(Ledger::ref l);
void setPubLedger(Ledger::ref l);
void tryFill(Job& job, Ledger::pointer ledger);
void setValidLedger(
std::shared_ptr<Ledger const> const& l);
void setPubLedger(
std::shared_ptr<Ledger const> const& l);
void tryFill(
Job& job,
std::shared_ptr<Ledger const> ledger);
void getFetchPack(LedgerHash missingHash, LedgerIndex missingIndex);
boost::optional<LedgerHash> getLedgerHashForHistory(LedgerIndex index);
int getNeededValidations();
@@ -250,7 +266,10 @@ private:
std::uint32_t const ledgerHistory,
std::uint32_t const ledgerHistoryIndex,
std::uint32_t const candidateLedger) const;
std::vector<Ledger::pointer> findNewLedgersToPublish();
std::vector<std::shared_ptr<Ledger const>>
findNewLedgersToPublish();
void updatePaths(Job& job);
void newPFWork(const char *name);
@@ -270,13 +289,13 @@ private:
LedgerHolder mValidLedger;
// The last ledger we have published.
Ledger::pointer mPubLedger;
std::shared_ptr<Ledger const> mPubLedger;
// The last ledger we did pathfinding against.
Ledger::pointer mPathLedger;
std::shared_ptr<Ledger const> mPathLedger;
// The last ledger we handled fetching history
Ledger::pointer mHistLedger;
std::shared_ptr<Ledger const> mHistLedger;
// Fully validated ledger, whether or not we have the ledger resident.
std::pair <uint256, LedgerIndex> mLastValidLedger;

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_APP_LEDGER_LOCALTXS_H_INCLUDED
#define RIPPLE_APP_LEDGER_LOCALTXS_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/ledger/ReadView.h>
#include <memory>
namespace ripple {
@@ -42,7 +42,7 @@ public:
virtual CanonicalTXSet getTxSet () = 0;
// Remove obsolete transactions based on a new fully-valid ledger
virtual void sweep (Ledger::ref validLedger) = 0;
virtual void sweep (ReadView const& view) = 0;
virtual std::size_t size () = 0;
};

View File

@@ -78,7 +78,7 @@ void
ConsensusImp::startRound (
LedgerConsensus& consensus,
LedgerHash const &prevLCLHash,
Ledger::ref previousLedger,
std::shared_ptr<Ledger const> const& previousLedger,
NetClock::time_point closeTime)
{
consensus.startRound (

View File

@@ -63,7 +63,7 @@ public:
startRound (
LedgerConsensus& ledgerConsensus,
LedgerHash const& prevLCLHash,
Ledger::ref previousLedger,
std::shared_ptr<Ledger const> const& previousLedger,
NetClock::time_point closeTime) override;
void

View File

@@ -142,7 +142,6 @@ void InboundLedger::init (ScopedLockType& collectionLock)
{
JLOG (m_journal.debug) <<
"Acquiring ledger we already have locally: " << getHash ();
mLedger->setClosed ();
mLedger->setImmutable (app_.config());
if (mReason != fcHISTORY)
@@ -192,7 +191,7 @@ bool InboundLedger::tryLocal ()
true, app_.config(), app_.family());
}
if (mLedger->getHash () != mHash)
if (mLedger->info().hash != mHash)
{
// We know for a fact the ledger can never be acquired
JLOG (m_journal.warning) <<
@@ -264,7 +263,6 @@ bool InboundLedger::tryLocal ()
JLOG (m_journal.debug) <<
"Had everything locally";
mComplete = true;
mLedger->setClosed ();
mLedger->setImmutable (app_.config());
}
@@ -357,7 +355,6 @@ void InboundLedger::done ()
if (isComplete () && !isFailed () && mLedger)
{
mLedger->setClosed ();
mLedger->setImmutable (app_.config());
if (mReason != fcHISTORY)
app_.getLedgerMaster ().storeLedger (mLedger);
@@ -735,10 +732,10 @@ bool InboundLedger::takeHeader (std::string const& data)
data.data(), data.size(), false,
app_.config(), app_.family());
if (mLedger->getHash () != mHash)
if (mLedger->info().hash != mHash)
{
JLOG (m_journal.warning) <<
"Acquire hash mismatch: " << mLedger->getHash () <<
"Acquire hash mismatch: " << mLedger->info().hash <<
"!=" << mHash;
mLedger.reset ();
return false;

View File

@@ -64,8 +64,11 @@ public:
{
}
Ledger::pointer acquire (
uint256 const& hash, std::uint32_t seq, InboundLedger::fcReason reason)
std::shared_ptr<Ledger>
acquire (
uint256 const& hash,
std::uint32_t seq,
InboundLedger::fcReason reason)
{
assert (hash.isNonZero ());
bool isNew = true;

View File

@@ -269,7 +269,9 @@ private:
}
// VFALCO TODO This should return boost::optional<uint256>
LedgerHash getLedgerHash(Ledger::pointer ledger, LedgerIndex index)
LedgerHash getLedgerHash(
std::shared_ptr<ReadView const>& ledger,
LedgerIndex index)
{
boost::optional<LedgerHash> hash;
try
@@ -281,7 +283,7 @@ private:
JLOG (j_.warning) <<
"Node missing from ledger " << ledger->info().seq;
app_.getInboundLedgers().acquire (
ledger->getHash(), ledger->info().seq,
ledger->info().hash, ledger->info().seq,
InboundLedger::fcGENERIC);
}
return hash ? *hash : zero; // kludge
@@ -300,9 +302,8 @@ private:
bool doNodes,
bool doTxns)
{
Ledger::pointer nodeLedger =
app_.getInboundLedgers().acquire (
ledgerHash, ledgerIndex, InboundLedger::fcGENERIC);
auto nodeLedger = app_.getInboundLedgers().acquire (
ledgerHash, ledgerIndex, InboundLedger::fcGENERIC);
if (!nodeLedger)
{
JLOG (j_.debug) << "Ledger " << ledgerIndex << " not available";
@@ -312,9 +313,9 @@ private:
return false;
}
Ledger::pointer dbLedger = loadByIndex(ledgerIndex, app_);
auto dbLedger = loadByIndex(ledgerIndex, app_);
if (! dbLedger ||
(dbLedger->getHash() != ledgerHash) ||
(dbLedger->info().hash != ledgerHash) ||
(dbLedger->info().parentHash != nodeLedger->info().parentHash))
{
// Ideally we'd also check for more than one ledger with that index
@@ -355,7 +356,7 @@ private:
*/
LedgerHash getHash(
LedgerIndex const& ledgerIndex,
Ledger::pointer& referenceLedger)
std::shared_ptr<ReadView const>& referenceLedger)
{
LedgerHash ledgerHash;
@@ -411,7 +412,7 @@ private:
return shouldExit_;
};
Ledger::pointer goodLedger;
std::shared_ptr<ReadView const> goodLedger;
while (! shouldExit())
{

View File

@@ -569,14 +569,14 @@ void LedgerConsensusImp::checkLCL ()
handleLCL (netLgr);
}
else if (mPreviousLedger->getHash () != mPrevLedgerHash)
else if (mPreviousLedger->info().hash != mPrevLedgerHash)
handleLCL (netLgr);
}
void LedgerConsensusImp::handleLCL (uint256 const& lclHash)
{
assert (lclHash != mPrevLedgerHash ||
mPreviousLedger->getHash () != lclHash);
mPreviousLedger->info().hash != lclHash);
if (mPrevLedgerHash != lclHash)
{
@@ -601,12 +601,12 @@ void LedgerConsensusImp::handleLCL (uint256 const& lclHash)
playbackProposals ();
}
if (mPreviousLedger->getHash () == mPrevLedgerHash)
if (mPreviousLedger->info().hash == mPrevLedgerHash)
return;
// we need to switch the ledger we're working from
auto newLCL = ledgerMaster_.getLedgerByHash (mPrevLedgerHash);
if (!newLCL)
auto buildLCL = ledgerMaster_.getLedgerByHash (mPrevLedgerHash);
if (! buildLCL)
{
if (mAcquiringLedger != lclHash)
{
@@ -631,13 +631,13 @@ void LedgerConsensusImp::handleLCL (uint256 const& lclHash)
return;
}
assert (!newLCL->info().open && newLCL->isImmutable ());
assert (newLCL->getHash () == lclHash);
assert (!buildLCL->open() && buildLCL->isImmutable ());
assert (buildLCL->info().hash == lclHash);
JLOG (j_.info) <<
"Have the consensus ledger " << mPrevLedgerHash;
startRound (
lclHash,
newLCL,
buildLCL,
mCloseTime,
mPreviousProposers,
mPreviousMSeconds);
@@ -975,80 +975,83 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
// Put transactions into a deterministic, but unpredictable, order
CanonicalTXSet retriableTxs (set->getHash ().as_uint256());
// Build the new last closed ledger
auto newLCL = std::make_shared<Ledger>(
open_ledger, *mPreviousLedger,
app_.timeKeeper().closeTime());
newLCL->setClosed (); // so applyTransactions sees a closed ledger
// Set up to write SHAMap changes to our database,
// perform updates, extract changes
JLOG (j_.debug)
<< "Applying consensus set transactions to the"
<< " last closed ledger";
std::shared_ptr<Ledger const> sharedLCL;
{
OpenView accum(&*newLCL);
assert(accum.closed());
if (replay)
// Build the new last closed ledger
auto buildLCL = std::make_shared<Ledger>(
*mPreviousLedger,
app_.timeKeeper().closeTime());
// Set up to write SHAMap changes to our database,
// perform updates, extract changes
JLOG (j_.debug)
<< "Applying consensus set transactions to the"
<< " last closed ledger";
{
// Special case, we are replaying a ledger close
for (auto& tx : replay->txns_)
applyTransaction (app_, accum, tx.second, false, tapNO_CHECK_SIGN, j_);
OpenView accum(&*buildLCL);
assert(!accum.open());
if (replay)
{
// Special case, we are replaying a ledger close
for (auto& tx : replay->txns_)
applyTransaction (app_, accum, tx.second, false, tapNO_CHECK_SIGN, j_);
}
else
{
// Normal case, we are not replaying a ledger close
applyTransactions (app_, set.get(), accum,
*buildLCL, retriableTxs, tapNONE);
}
// Update fee computations.
app_.getTxQ().processValidatedLedger(app_, accum,
mCurrentMSeconds > 5s);
accum.apply(*buildLCL);
}
// retriableTxs will include any transactions that
// made it into the consensus set but failed during application
// to the ledger.
buildLCL->updateSkipList ();
{
int asf = buildLCL->stateMap().flushDirty (
hotACCOUNT_NODE, buildLCL->info().seq);
int tmf = buildLCL->txMap().flushDirty (
hotTRANSACTION_NODE, buildLCL->info().seq);
JLOG (j_.debug) << "Flushed " <<
asf << " accounts and " <<
tmf << " transaction nodes";
}
// Accept ledger
buildLCL->setAccepted(closeTime, mCloseResolution,
closeTimeCorrect, app_.config());
// And stash the ledger in the ledger master
if (ledgerMaster_.storeLedger (buildLCL))
JLOG (j_.debug)
<< "Consensus built ledger we already had";
else if (app_.getInboundLedgers().find (buildLCL->info().hash))
JLOG (j_.debug)
<< "Consensus built ledger we were acquiring";
else
{
// Normal case, we are not replaying a ledger close
applyTransactions (app_, set.get(), accum,
newLCL, retriableTxs, tapNONE);
}
// Update fee computations.
app_.getTxQ().processValidatedLedger(app_, accum,
mCurrentMSeconds > 5s);
accum.apply(*newLCL);
JLOG (j_.debug)
<< "Consensus built new ledger";
sharedLCL = std::move(buildLCL);
}
// retriableTxs will include any transactions that
// made it into the consensus set but failed during application
// to the ledger.
newLCL->updateSkipList ();
{
int asf = newLCL->stateMap().flushDirty (
hotACCOUNT_NODE, newLCL->info().seq);
int tmf = newLCL->txMap().flushDirty (
hotTRANSACTION_NODE, newLCL->info().seq);
JLOG (j_.debug) << "Flushed " <<
asf << " accounts and " <<
tmf << " transaction nodes";
}
// Accept ledger
newLCL->setAccepted(closeTime, mCloseResolution,
closeTimeCorrect, app_.config());
// And stash the ledger in the ledger master
if (ledgerMaster_.storeLedger (newLCL))
JLOG (j_.debug)
<< "Consensus built ledger we already had";
else if (app_.getInboundLedgers().find (newLCL->getHash()))
JLOG (j_.debug)
<< "Consensus built ledger we were acquiring";
else
JLOG (j_.debug)
<< "Consensus built new ledger";
uint256 const newLCLHash = newLCL->getHash ();
uint256 const newLCLHash = sharedLCL->info().hash;
JLOG (j_.debug)
<< "Report: NewL = " << newLCL->getHash ()
<< ":" << newLCL->info().seq;
<< "Report: NewL = " << newLCLHash
<< ":" << sharedLCL->info().seq;
// Tell directly connected peers that we have a new LCL
statusChange (protocol::neACCEPTED_LEDGER, *newLCL);
statusChange (protocol::neACCEPTED_LEDGER, *sharedLCL);
if (mValidating &&
! ledgerMaster_.isCompatible (newLCL,
! ledgerMaster_.isCompatible (*sharedLCL,
app_.journal("LedgerConsensus").warning,
"Not validating"))
{
@@ -1061,15 +1064,15 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
auto v = std::make_shared<STValidation> (newLCLHash,
consensus_.validationTimestamp(app_.timeKeeper().now()),
mValPublic, mProposing);
v->setFieldU32 (sfLedgerSequence, newLCL->info().seq);
v->setFieldU32 (sfLedgerSequence, sharedLCL->info().seq);
addLoad(v); // Our network load
if (((newLCL->info().seq + 1) % 256) == 0)
if (((sharedLCL->info().seq + 1) % 256) == 0)
// next ledger is flag ledger
{
// Suggest fee changes and new features
m_feeVote.doValidation (newLCL, *v);
app_.getAmendmentTable ().doValidation (newLCL, *v);
m_feeVote.doValidation (sharedLCL, *v);
app_.getAmendmentTable ().doValidation (sharedLCL, *v);
}
auto const signingHash = v->sign (mValSecret);
@@ -1088,10 +1091,10 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
}
else
JLOG (j_.info)
<< "CNF newLCL " << newLCLHash;
<< "CNF buildLCL " << newLCLHash;
// See if we can accept a ledger as fully-validated
ledgerMaster_.consensusBuilt (newLCL, getJson (true));
ledgerMaster_.consensusBuilt (sharedLCL, getJson (true));
{
// Apply disputed transactions that didn't get in
@@ -1150,7 +1153,7 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
else
rules.emplace();
app_.openLedger().accept(app_, *rules,
newLCL, localTx, anyDisputes, retriableTxs, tapNONE,
sharedLCL, localTx, anyDisputes, retriableTxs, tapNONE,
"consensus",
[&](OpenView& view, beast::Journal j)
{
@@ -1159,10 +1162,10 @@ void LedgerConsensusImp::accept (std::shared_ptr<SHAMap> set)
});
}
ledgerMaster_.switchLCL (newLCL);
ledgerMaster_.switchLCL (sharedLCL);
assert (ledgerMaster_.getClosedLedger()->getHash() == newLCL->getHash());
assert (app_.openLedger().current()->info().parentHash == newLCL->getHash());
assert (ledgerMaster_.getClosedLedger()->info().hash == sharedLCL->info().hash);
assert (app_.openLedger().current()->info().parentHash == sharedLCL->info().hash);
if (mValidating)
{
@@ -1363,7 +1366,7 @@ void LedgerConsensusImp::sendHaveTxSet (uint256 const& hash, bool direct)
}
void LedgerConsensusImp::statusChange (
protocol::NodeEvent event, Ledger& ledger)
protocol::NodeEvent event, ReadView const& ledger)
{
protocol::TMStatusChange s;
@@ -1376,8 +1379,8 @@ void LedgerConsensusImp::statusChange (
s.set_networktime (app_.timeKeeper().now().time_since_epoch().count());
s.set_ledgerhashprevious(ledger.info().parentHash.begin (),
std::decay_t<decltype(ledger.info().parentHash)>::bytes);
s.set_ledgerhash (ledger.getHash ().begin (),
std::decay_t<decltype(ledger.getHash ())>::bytes);
s.set_ledgerhash (ledger.info().hash.begin (),
std::decay_t<decltype(ledger.info().hash)>::bytes);
std::uint32_t uMin, uMax;
if (!ledgerMaster_.getFullValidatedRange (uMin, uMax))
@@ -1757,7 +1760,7 @@ void LedgerConsensusImp::checkOurValidation ()
return;
}
auto v = std::make_shared<STValidation> (mPreviousLedger->getHash (),
auto v = std::make_shared<STValidation> (mPreviousLedger->info().hash,
consensus_.validationTimestamp(app_.timeKeeper().now()),
mValPublic, false);
addLoad(v);
@@ -1803,7 +1806,7 @@ void LedgerConsensusImp::endConsensus (bool correctLCL)
void LedgerConsensusImp::startRound (
LedgerHash const& prevLCLHash,
Ledger::ref prevLedger,
std::shared_ptr<Ledger const> const& prevLedger,
NetClock::time_point closeTime,
int previousProposers,
std::chrono::milliseconds previousConvergeTime)
@@ -1861,7 +1864,7 @@ void LedgerConsensusImp::startRound (
mProposing = mValidating = false;
}
mHaveCorrectLCL = (mPreviousLedger->getHash () == mPrevLedgerHash);
mHaveCorrectLCL = (mPreviousLedger->info().hash == mPrevLedgerHash);
if (!mHaveCorrectLCL)
{
@@ -1874,7 +1877,7 @@ void LedgerConsensusImp::startRound (
{
JLOG (j_.info)
<< "Entering consensus with: "
<< mPreviousLedger->getHash ();
<< mPreviousLedger->info().hash;
JLOG (j_.info)
<< "Correct LCL is: " << prevLCLHash;
}
@@ -1981,7 +1984,7 @@ void applyTransactions (
Application& app,
SHAMap const* set,
OpenView& view,
Ledger::ref checkLedger,
ReadView const& checkLedger,
CanonicalTXSet& retriableTxs,
ApplyFlags flags)
{
@@ -1991,7 +1994,7 @@ void applyTransactions (
{
for (auto const& item : *set)
{
if (checkLedger->txExists (item.key()))
if (checkLedger.txExists (item.key()))
continue;
// The transaction isn't in the check ledger, try to apply it

View File

@@ -105,7 +105,7 @@ public:
*/
void startRound (
LedgerHash const& prevLCLHash,
Ledger::ref prevLedger,
std::shared_ptr<Ledger const> const& prevLedger,
NetClock::time_point closeTime,
int previousProposers,
std::chrono::milliseconds previousConvergeTime) override;
@@ -256,7 +256,7 @@ private:
typically neACCEPTED_LEDGER or neCLOSING_LEDGER.
@param ledger The ledger associated with the event.
*/
void statusChange (protocol::NodeEvent event, Ledger& ledger);
void statusChange (protocol::NodeEvent event, ReadView const& ledger);
/** Take an initial position on what we think the consensus should be
based on the transactions that made it into our open ledger
@@ -316,7 +316,7 @@ private:
uint256 mPrevLedgerHash;
uint256 mAcquiringLedger;
Ledger::pointer mPreviousLedger;
std::shared_ptr<Ledger const> mPreviousLedger;
LedgerProposal::pointer mOurPosition;
PublicKey mValPublic;
SecretKey mValSecret;

View File

@@ -33,6 +33,7 @@
#include <ripple/app/misc/TxQ.h>
#include <ripple/app/misc/Validations.h>
#include <ripple/app/paths/PathRequests.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/TaggedCache.h>
#include <ripple/basics/UptimeTimer.h>
@@ -109,8 +110,10 @@ LedgerMaster::getValidLedgerIndex ()
}
bool
LedgerMaster::isCompatible (Ledger::pointer ledger,
beast::Journal::Stream s, const char* reason)
LedgerMaster::isCompatible (
ReadView const& view,
beast::Journal::Stream s,
char const* reason)
{
if (mStrictValCount)
{
@@ -122,7 +125,7 @@ LedgerMaster::isCompatible (Ledger::pointer ledger,
auto validLedger = getValidatedLedger();
if (validLedger &&
! areCompatible (*validLedger, *ledger, s, reason))
! areCompatible (*validLedger, view, s, reason))
{
return false;
}
@@ -132,7 +135,7 @@ LedgerMaster::isCompatible (Ledger::pointer ledger,
if ((mLastValidLedger.second != 0) &&
! areCompatible (mLastValidLedger.first,
mLastValidLedger.second, *ledger, s, reason))
mLastValidLedger.second, view, s, reason))
{
return false;
}
@@ -201,13 +204,19 @@ LedgerMaster::isCaughtUp(std::string& reason)
}
void
LedgerMaster::setValidLedger(Ledger::ref l)
LedgerMaster::setValidLedger(
std::shared_ptr<Ledger const> const& l)
{
std::vector <NetClock::time_point> times;
NetClock::time_point signTime;
if (! app_.config().RUN_STANDALONE)
{
times = app_.getValidations().getValidationTimes(
l->getHash());
l->info().hash);
}
NetClock::time_point signTime;
if (! times.empty () && times.size() >= mMinValidations)
{
// Calculate the sample median
@@ -224,14 +233,16 @@ LedgerMaster::setValidLedger(Ledger::ref l)
mValidLedger.set (l);
mValidLedgerSign = signTime.time_since_epoch().count();
mValidLedgerSeq = l->info().seq;
app_.getOPs().updateLocalTx (l);
app_.getOPs().updateLocalTx (*l);
app_.getSHAMapStore().onLedgerClosed (getValidatedLedger());
mLedgerHistory.validatedLedger (l);
app_.getAmendmentTable().doValidatedLedger (l);
}
void
LedgerMaster::setPubLedger(Ledger::ref l)
LedgerMaster::setPubLedger(
std::shared_ptr<Ledger const> const& l)
{
mPubLedger = l;
mPubLedgerClose = l->info().closeTime.time_since_epoch().count();
@@ -242,21 +253,22 @@ void
LedgerMaster::addHeldTransaction (
std::shared_ptr<Transaction> const& transaction)
{
// returns true if transaction was added
ScopedLockType ml (m_mutex);
mHeldTransactions.insert (transaction->getSTransaction ());
}
void
LedgerMaster::switchLCL (Ledger::pointer lastClosed)
LedgerMaster::switchLCL(std::shared_ptr<Ledger const> const& lastClosed)
{
assert (lastClosed);
if(! lastClosed->isImmutable())
LogicError("mutable ledger in switchLCL");
lastClosed->setClosed ();
if (lastClosed->open())
LogicError ("The new last closed ledger is open!");
{
ScopedLockType ml (m_mutex);
mClosedLedger.set (lastClosed);
}
@@ -278,17 +290,10 @@ LedgerMaster::fixIndex (LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
}
bool
LedgerMaster::storeLedger (Ledger::pointer ledger)
LedgerMaster::storeLedger (std::shared_ptr<Ledger const> ledger)
{
// Returns true if we already had the ledger
return mLedgerHistory.addLedger (ledger, false);
}
void
LedgerMaster::forceValid (Ledger::pointer ledger)
{
ledger->setValidated();
setFullLedger(ledger, true, false);
return mLedgerHistory.insert(std::move(ledger), false);
}
/** Apply held transactions to the open ledger
@@ -442,7 +447,7 @@ LedgerMaster::getValidatedRange (std::uint32_t& minVal, std::uint32_t& maxVal)
// Get the earliest ledger we will let peers fetch
std::uint32_t
LedgerMaster::getEarliestFetch ()
LedgerMaster::getEarliestFetch()
{
// The earliest ledger we will let people fetch is ledger zero,
// unless that creates a larger range than allowed
@@ -456,7 +461,9 @@ LedgerMaster::getEarliestFetch ()
}
void
LedgerMaster::tryFill (Job& job, Ledger::pointer ledger)
LedgerMaster::tryFill (
Job& job,
std::shared_ptr<Ledger const> ledger)
{
std::uint32_t seq = ledger->info().seq;
uint256 prevHash = ledger->info().parentHash;
@@ -567,18 +574,18 @@ LedgerMaster::getFetchPack (LedgerHash missingHash, LedgerIndex missingIndex)
}
void
LedgerMaster::fixMismatch (Ledger::ref ledger)
LedgerMaster::fixMismatch (ReadView const& ledger)
{
int invalidate = 0;
boost::optional<uint256> hash;
for (std::uint32_t lSeq = ledger->info().seq - 1; lSeq > 0; --lSeq)
for (std::uint32_t lSeq = ledger.info().seq - 1; lSeq > 0; --lSeq)
{
if (haveLedger (lSeq))
{
try
{
hash = hashOfSeq(*ledger, lSeq, m_journal);
hash = hashOfSeq(ledger, lSeq, m_journal);
}
catch (std::exception const&)
{
@@ -591,9 +598,9 @@ LedgerMaster::fixMismatch (Ledger::ref ledger)
if (hash)
{
// try to close the seam
Ledger::pointer otherLedger = getLedgerBySeq (lSeq);
auto otherLedger = getLedgerBySeq (lSeq);
if (otherLedger && (otherLedger->getHash () == *hash))
if (otherLedger && (otherLedger->info().hash == *hash))
{
// we closed the seam
if (invalidate != 0)
@@ -623,18 +630,20 @@ LedgerMaster::fixMismatch (Ledger::ref ledger)
void
LedgerMaster::setFullLedger (
Ledger::pointer ledger, bool isSynchronous, bool isCurrent)
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous, bool isCurrent)
{
// A new ledger has been accepted as part of the trusted chain
JLOG (m_journal.debug) << "Ledger " << ledger->info().seq
<< " accepted :" << ledger->getHash ();
JLOG (m_journal.debug) <<
"Ledger " << ledger->info().seq <<
" accepted :" << ledger->info().hash;
assert (ledger->stateMap().getHash ().isNonZero ());
ledger->setValidated();
ledger->setFull();
if (isCurrent)
mLedgerHistory.addLedger(ledger, true);
mLedgerHistory.insert(ledger, true);
{
// Check the SQL database's entry for the sequence before this
@@ -648,12 +657,11 @@ LedgerMaster::setFullLedger (
pendSaveValidated (app_, ledger, isSynchronous, isCurrent);
{
ScopedLockType ml (mCompleteLock);
mCompleteLedgers.setValue (ledger->info().seq);
}
{
ScopedLockType ml (mCompleteLock);
mCompleteLedgers.setValue (ledger->info().seq);
}
{
ScopedLockType ml (m_mutex);
if (ledger->info().seq > mValidLedgerSeq)
@@ -670,12 +678,12 @@ LedgerMaster::setFullLedger (
auto prevLedger = getLedgerBySeq (ledger->info().seq - 1);
if (!prevLedger ||
(prevLedger->getHash () != ledger->info().parentHash))
(prevLedger->info().hash != ledger->info().parentHash))
{
JLOG (m_journal.warning)
<< "Acquired ledger invalidates previous ledger: "
<< (prevLedger ? "hashMismatch" : "missingLedger");
fixMismatch (ledger);
<< "Acquired ledger invalidates previous ledger: "
<< (prevLedger ? "hashMismatch" : "missingLedger");
fixMismatch (*ledger);
}
}
}
@@ -694,8 +702,7 @@ LedgerMaster::failedSave(std::uint32_t seq, uint256 const& hash)
void
LedgerMaster::checkAccept (uint256 const& hash, std::uint32_t seq)
{
int valCount;
int valCount = 0;
if (seq != 0)
{
@@ -728,7 +735,7 @@ LedgerMaster::checkAccept (uint256 const& hash, std::uint32_t seq)
return;
}
Ledger::pointer ledger = mLedgerHistory.getLedgerByHash (hash);
auto ledger = mLedgerHistory.getLedgerByHash (hash);
if (!ledger)
{
@@ -777,7 +784,8 @@ LedgerMaster::getNeededValidations ()
}
void
LedgerMaster::checkAccept (Ledger::ref ledger)
LedgerMaster::checkAccept (
std::shared_ptr<Ledger const> const& ledger)
{
if (ledger->info().seq <= mValidLedgerSeq)
return;
@@ -789,13 +797,14 @@ LedgerMaster::checkAccept (Ledger::ref ledger)
if (ledger->info().seq <= mValidLedgerSeq)
return;
int minVal = getNeededValidations();
int tvc = app_.getValidations().getTrustedValidationCount(
ledger->getHash());
auto const minVal = getNeededValidations();
auto const tvc = app_.getValidations().getTrustedValidationCount(
ledger->info().hash);
if (tvc < minVal) // nothing we can do
{
JLOG (m_journal.trace)
<< "Only " << tvc << " validations for " << ledger->getHash();
JLOG (m_journal.trace) <<
"Only " << tvc <<
" validations for " << ledger->info().hash;
return;
}
@@ -803,7 +812,7 @@ LedgerMaster::checkAccept (Ledger::ref ledger)
<< "Advancing accepted ledger to " << ledger->info().seq
<< " with >= " << minVal << " validations";
mLastValidateHash = ledger->getHash();
mLastValidateHash = ledger->info().hash;
mLastValidateSeq = ledger->info().seq;
ledger->setValidated();
@@ -817,7 +826,7 @@ LedgerMaster::checkAccept (Ledger::ref ledger)
}
std::uint64_t const base = app_.getFeeTrack().getLoadBase();
auto fees = app_.getValidations().fees (ledger->getHash(), base);
auto fees = app_.getValidations().fees (ledger->info().hash, base);
{
auto fees2 = app_.getValidations().fees (
ledger->info(). parentHash, base);
@@ -842,7 +851,8 @@ LedgerMaster::checkAccept (Ledger::ref ledger)
/** Report that the consensus process built a particular ledger */
void
LedgerMaster::consensusBuilt (Ledger::ref ledger, Json::Value consensus)
LedgerMaster::consensusBuilt(
std::shared_ptr<Ledger const> const& ledger, Json::Value consensus)
{
// Because we just built a ledger, we are no longer building one
@@ -906,7 +916,7 @@ LedgerMaster::consensusBuilt (Ledger::ref ledger, Json::Value consensus)
auto neededValidations = getNeededValidations ();
auto maxSeq = mValidLedgerSeq.load();
auto maxLedger = ledger->getHash();
auto maxLedger = ledger->info().hash;
// Of the ledgers with sufficient validations,
// find the one with the highest sequence
@@ -916,8 +926,7 @@ LedgerMaster::consensusBuilt (Ledger::ref ledger, Json::Value consensus)
// If we still don't know the sequence, get it
if (v.second.ledgerSeq_ == 0)
{
Ledger::pointer ledger = getLedgerByHash (v.first);
if (ledger)
if (auto ledger = getLedgerByHash (v.first))
v.second.ledgerSeq_ = ledger->info().seq;
}
@@ -984,96 +993,110 @@ LedgerMaster::shouldFetchPack (std::uint32_t seq) const
return (fetch_seq_ != seq);
}
std::vector<Ledger::pointer>
std::vector<std::shared_ptr<Ledger const>>
LedgerMaster::findNewLedgersToPublish ()
{
std::vector<Ledger::pointer> ret;
std::vector<std::shared_ptr<Ledger const>> ret;
JLOG (m_journal.trace) << "findNewLedgersToPublish<";
// No valid ledger, nothing to do
if (mValidLedger.empty ())
{
// No valid ledger, nothing to do
JLOG(m_journal.trace) <<
"No valid journal, nothing to publish.";
return {};
}
else if (! mPubLedger)
if (! mPubLedger)
{
JLOG (m_journal.info) << "First published ledger will be "
<< mValidLedgerSeq;
ret.push_back (mValidLedger.get ());
JLOG(m_journal.info) <<
"First published ledger will be " << mValidLedgerSeq;
return { mValidLedger.get () };
}
else if (mValidLedgerSeq > (mPubLedgerSeq + MAX_LEDGER_GAP))
if (mValidLedgerSeq > (mPubLedgerSeq + MAX_LEDGER_GAP))
{
JLOG (m_journal.warning)
<< "Gap in validated ledger stream " << mPubLedgerSeq
<< " - " << mValidLedgerSeq - 1;
Ledger::pointer valLedger = mValidLedger.get ();
JLOG(m_journal.warning) <<
"Gap in validated ledger stream " << mPubLedgerSeq <<
" - " << mValidLedgerSeq - 1;
auto valLedger = mValidLedger.get ();
ret.push_back (valLedger);
setPubLedger (valLedger);
app_.getOrderBookDB().setup(valLedger);
return { valLedger };
}
else if (mValidLedgerSeq > mPubLedgerSeq)
if (mValidLedgerSeq <= mPubLedgerSeq)
{
int acqCount = 0;
(m_journal.trace) <<
"No valid journal, nothing to publish.";
return {};
}
auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
Ledger::pointer valLedger = mValidLedger.get ();
std::uint32_t valSeq = valLedger->info().seq;
int acqCount = 0;
ScopedUnlockType sul(m_mutex);
try
auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
auto valLedger = mValidLedger.get ();
std::uint32_t valSeq = valLedger->info().seq;
ScopedUnlockType sul(m_mutex);
try
{
for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
{
for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
JLOG(m_journal.trace)
<< "Trying to fetch/publish valid ledger " << seq;
std::shared_ptr<Ledger const> ledger;
// This can throw
auto hash = hashOfSeq(*valLedger, seq, m_journal);
// VFALCO TODO Restructure this code so that zero is not
// used.
if (! hash)
hash = zero; // kludge
if (seq == valSeq)
{
JLOG (m_journal.trace)
<< "Trying to fetch/publish valid ledger " << seq;
// We need to publish the ledger we just fully validated
ledger = valLedger;
}
else if (hash->isZero())
{
JLOG (m_journal.fatal)
<< "Ledger: " << valSeq
<< " does not have hash for " << seq;
assert (false);
}
else
{
ledger = mLedgerHistory.getLedgerByHash (*hash);
}
Ledger::pointer ledger;
// This can throw
auto hash = hashOfSeq(*valLedger, seq, m_journal);
// VFALCO TODO Restructure this code so that zero is not
// used.
if (! hash)
hash = zero; // kludge
if (seq == valSeq)
{
// We need to publish the ledger we just fully validated
ledger = valLedger;
}
else if (hash->isZero())
{
JLOG (m_journal.fatal)
<< "Ledger: " << valSeq
<< " does not have hash for " << seq;
assert (false);
}
else
{
ledger = mLedgerHistory.getLedgerByHash (*hash);
}
// Can we try to acquire the ledger we need?
if (! ledger && (++acqCount < 4))
ledger = app_.getInboundLedgers ().acquire(
*hash, seq, InboundLedger::fcGENERIC);
// Did we acquire the next ledger we need to publish?
if (ledger && (ledger->info().seq == pubSeq))
{
ledger->setValidated();
ret.push_back (ledger);
++pubSeq;
}
// Can we try to acquire the ledger we need?
if (! ledger && (++acqCount < 4))
ledger = app_.getInboundLedgers ().acquire(
*hash, seq, InboundLedger::fcGENERIC);
// Did we acquire the next ledger we need to publish?
if (ledger && (ledger->info().seq == pubSeq))
{
ledger->setValidated();
ret.push_back (ledger);
++pubSeq;
}
}
catch (std::exception const&)
{
JLOG (m_journal.error)
<< "findNewLedgersToPublish catches an exception";
}
JLOG(m_journal.trace) <<
"ready to publish " << ret.size() << " ledgers.";
}
catch (std::exception const&)
{
JLOG(m_journal.error) <<
"Exception while trying to find ledgers to publish.";
}
JLOG (m_journal.trace)
<< "findNewLedgersToPublish> " << ret.size();
return ret;
}
@@ -1096,7 +1119,9 @@ LedgerMaster::tryAdvance()
// Return the hash of the valid ledger with a particular sequence, given a
// subsequent ledger known valid.
boost::optional<LedgerHash>
LedgerMaster::getLedgerHash(std::uint32_t desiredSeq, Ledger::ref knownGoodLedger)
LedgerMaster::getLedgerHash(
std::uint32_t desiredSeq,
std::shared_ptr<ReadView const> const& knownGoodLedger)
{
assert(desiredSeq < knownGoodLedger->info().seq);
@@ -1111,8 +1136,7 @@ LedgerMaster::getLedgerHash(std::uint32_t desiredSeq, Ledger::ref knownGoodLedge
hash = hashOfSeq(*knownGoodLedger, seq, m_journal);
if (hash)
{
auto l = getLedgerByHash(*hash);
if (l)
if (auto l = getLedgerByHash(*hash))
{
hash = hashOfSeq(*l, desiredSeq, m_journal);
assert (hash);
@@ -1172,7 +1196,7 @@ LedgerMaster::updatePaths (Job& job)
if (age > 1min)
{
JLOG (m_journal.debug)
<< "Published ledger too old for updating paths";
<< "Published ledger too old for updating paths";
--mPathFindThread;
return;
}
@@ -1186,21 +1210,23 @@ LedgerMaster::updatePaths (Job& job)
catch (SHAMapMissingNode&)
{
JLOG (m_journal.info)
<< "Missing node detected during pathfinding";
if (lastLedger->info().open)
<< "Missing node detected during pathfinding";
if (lastLedger->open())
{
// our parent is the problem
app_.getInboundLedgers().acquire(
lastLedger->info().parentHash, lastLedger->info().seq - 1,
lastLedger->info().parentHash,
lastLedger->info().seq - 1,
InboundLedger::fcGENERIC);
}
else
{
// this ledger is the problem
app_.getInboundLedgers().acquire(
lastLedger->info().hash, lastLedger->info().seq,
lastLedger->info().hash,
lastLedger->info().seq,
InboundLedger::fcGENERIC);
}
}
}
}
}
@@ -1262,20 +1288,6 @@ LedgerMaster::getCurrentLedger ()
return app_.openLedger().current();
}
// The finalized ledger is the last closed/accepted ledger
Ledger::pointer
LedgerMaster::getClosedLedger ()
{
return mClosedLedger.get ();
}
// The validated ledger is the last fully validated ledger
Ledger::pointer
LedgerMaster::getValidatedLedger ()
{
return mValidLedger.get ();
}
Rules
LedgerMaster::getValidatedRules ()
{
@@ -1291,44 +1303,13 @@ LedgerMaster::getValidatedRules ()
// This is the last ledger we published to clients and can lag the validated
// ledger.
Ledger::pointer
std::shared_ptr<ReadView const>
LedgerMaster::getPublishedLedger ()
{
ScopedLockType lock(m_mutex);
return mPubLedger;
}
bool
LedgerMaster::isValidLedger(LedgerInfo const& info)
{
if (info.validated)
return true;
if (info.open)
return false;
auto seq = info.seq;
try
{
// Use the skip list in the last validated ledger to see if ledger
// comes before the last validated ledger (and thus has been
// validated).
auto hash = walkHashBySeq (seq);
if (info.hash != hash)
return false;
}
catch (SHAMapMissingNode const&)
{
JLOG (app_.journal ("RPCHandler").warning)
<< "Missing SHANode " << std::to_string (seq);
return false;
}
// Mark ledger as validated to save time if we see it again.
info.validated = true;
return true;
}
int
LedgerMaster::getMinValidations ()
{
@@ -1393,16 +1374,17 @@ boost::optional<LedgerHash>
LedgerMaster::walkHashBySeq (std::uint32_t index)
{
boost::optional<LedgerHash> ledgerHash;
Ledger::pointer referenceLedger;
referenceLedger = mValidLedger.get ();
if (referenceLedger)
if (auto referenceLedger = mValidLedger.get ())
ledgerHash = walkHashBySeq (index, referenceLedger);
return ledgerHash;
}
boost::optional<LedgerHash>
LedgerMaster::walkHashBySeq (std::uint32_t index, Ledger::ref referenceLedger)
LedgerMaster::walkHashBySeq (
std::uint32_t index,
std::shared_ptr<ReadView const> const& referenceLedger)
{
if (!referenceLedger || (referenceLedger->info().seq < index))
{
@@ -1452,14 +1434,13 @@ LedgerMaster::walkHashBySeq (std::uint32_t index, Ledger::ref referenceLedger)
return ledgerHash;
}
Ledger::pointer
std::shared_ptr<Ledger const>
LedgerMaster::getLedgerBySeq (std::uint32_t index)
{
if (index <= mValidLedgerSeq)
{
// Always prefer a validated ledger
auto valid = mValidLedger.get ();
if (valid)
if (auto valid = mValidLedger.get ())
{
if (valid->info().seq == index)
return valid;
@@ -1467,6 +1448,7 @@ LedgerMaster::getLedgerBySeq (std::uint32_t index)
try
{
auto const hash = hashOfSeq(*valid, index, m_journal);
if (hash)
return mLedgerHistory.getLedgerByHash (*hash);
}
@@ -1477,30 +1459,28 @@ LedgerMaster::getLedgerBySeq (std::uint32_t index)
}
}
Ledger::pointer ret = mLedgerHistory.getLedgerBySeq (index);
if (ret)
if (auto ret = mLedgerHistory.getLedgerBySeq (index))
return ret;
ret = mClosedLedger.get ();
auto ret = mClosedLedger.get ();
if (ret && (ret->info().seq == index))
return ret;
clearLedger (index);
return Ledger::pointer();
return {};
}
Ledger::pointer
std::shared_ptr<Ledger const>
LedgerMaster::getLedgerByHash (uint256 const& hash)
{
Ledger::pointer ret = mLedgerHistory.getLedgerByHash (hash);
if (ret)
if (auto ret = mLedgerHistory.getLedgerByHash (hash))
return ret;
ret = mClosedLedger.get ();
if (ret && (ret->getHash () == hash))
auto ret = mClosedLedger.get ();
if (ret && (ret->info().hash == hash))
return ret;
return Ledger::pointer ();
return {};
}
void
@@ -1628,7 +1608,7 @@ void LedgerMaster::doAdvance ()
if (hash)
{
assert(hash->isNonZero());
Ledger::pointer ledger = getLedgerByHash (*hash);
auto ledger = getLedgerByHash (*hash);
if (!ledger)
{
if (!app_.getInboundLedgers().isFailure (
@@ -1663,8 +1643,11 @@ void LedgerMaster::doAdvance ()
JLOG (m_journal.trace)
<< "tryAdvance acquired "
<< ledger->info().seq;
setFullLedger(ledger, false, false);
auto& parent = ledger->info().parentHash;
setFullLedger(
ledger,
false,
false);
auto const& parent = ledger->info().parentHash;
int fillInProgress;
{
@@ -1756,7 +1739,10 @@ void LedgerMaster::doAdvance ()
JLOG (m_journal.debug) <<
"tryAdvance publishing seq " << ledger->info().seq;
setFullLedger(ledger, true, true);
setFullLedger(
ledger,
true,
true);
}
setPubLedger(ledger);
@@ -1847,7 +1833,7 @@ LedgerMaster::makeFetchPack (
return;
}
if (haveLedger->info().open)
if (haveLedger->open())
{
m_journal.warning
<< "Peer requests fetch pack from open ledger: "
@@ -1912,10 +1898,11 @@ LedgerMaster::makeFetchPack (
std::uint32_t lSeq = wantLedger->info().seq;
protocol::TMIndexedObject& newObj = *reply.add_objects ();
newObj.set_hash (wantLedger->getHash ().begin (), 256 / 8);
newObj.set_hash (
wantLedger->info().hash.data(), 256 / 8);
Serializer s (256);
s.add32 (HashPrefix::ledgerMaster);
wantLedger->addRaw (s);
addRaw(wantLedger->info(), s);
newObj.set_data (s.getDataPtr (), s.getLength ());
newObj.set_ledgerseq (lSeq);

View File

@@ -40,13 +40,13 @@ bool isBinary(LedgerFill const& fill)
}
template <class Object>
void fillJson(Object& json, LedgerInfo const& info, bool bFull)
void fillJson(Object& json, bool closed, LedgerInfo const& info, bool bFull)
{
json[jss::parent_hash] = to_string (info.parentHash);
json[jss::ledger_index] = to_string (info.seq);
json[jss::seqNum] = to_string (info.seq); // DEPRECATED
if (! info.open)
if (closed)
{
json[jss::closed] = true;
}
@@ -64,7 +64,7 @@ void fillJson(Object& json, LedgerInfo const& info, bool bFull)
// These next three are DEPRECATED.
json[jss::hash] = to_string (info.hash);
json[jss::totalCoins] = to_string (info.drops);
json[jss::accepted] = ! info.open;
json[jss::accepted] = closed;
json[jss::close_flags] = info.closeFlags;
// Always show fields that contribute to the ledger hash
@@ -165,7 +165,7 @@ void fillJson (Object& json, LedgerFill const& fill)
// TODO: what happens if bBinary and bExtracted are both set?
// Is there a way to report this back?
auto bFull = isFull(fill);
fillJson(json, fill.ledger.info(), bFull);
fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
if (bFull || fill.options & LedgerFill::dumpTxrp)
fillJsonTx(json, fill);

View File

@@ -18,6 +18,7 @@
//==============================================================================
#include <BeastConfig.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/LocalTxs.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/Indexes.h>
@@ -120,21 +121,6 @@ public:
m_txns.emplace_back (index, txn);
}
bool can_remove (LocalTx& txn, Ledger::ref ledger)
{
if (txn.isExpired (ledger->info().seq))
return true;
if (ledger->txExists(txn.getID()))
return true;
auto const sle = cachedRead(*ledger,
keylet::account(txn.getAccount()).key, ltACCOUNT_ROOT);
if (! sle)
return false;
if (sle->getFieldU32 (sfSequence) > txn.getSeq ())
return true;
return false;
}
CanonicalTXSet
getTxSet () override
{
@@ -152,19 +138,25 @@ public:
return tset;
}
// Remove transactions that have either been accepted into a fully-validated
// ledger, are (now) impossible, or have expired
void sweep (Ledger::ref validLedger) override
// Remove transactions that have either been accepted
// into a fully-validated ledger, are (now) impossible,
// or have expired
void sweep (ReadView const& view) override
{
std::lock_guard <std::mutex> lock (m_lock);
for (auto it = m_txns.begin (); it != m_txns.end (); )
m_txns.remove_if ([&view](auto const& txn)
{
if (can_remove (*it, validLedger))
it = m_txns.erase (it);
else
++it;
}
if (txn.isExpired (view.info().seq))
return true;
if (view.txExists(txn.getID()))
return true;
auto const sle = cachedRead(view,
keylet::account(txn.getAccount()).key, ltACCOUNT_ROOT);
if (! sle)
return false;
return sle->getFieldU32 (sfSequence) > txn.getSeq ();
});
}
std::size_t size () override

View File

@@ -925,7 +925,10 @@ private:
void addTxnSeqField();
void updateTables ();
void startGenesisLedger ();
Ledger::pointer getLastFullLedger();
std::shared_ptr<Ledger>
getLastFullLedger();
bool loadOldLedger (
std::string const& ledgerID, bool replay, bool isFilename);
};
@@ -1207,9 +1210,8 @@ ApplicationImp::startGenesisLedger()
m_ledgerMaster->storeLedger (genesis);
auto const next = std::make_shared<Ledger>(
open_ledger, *genesis, timeKeeper().closeTime());
*genesis, timeKeeper().closeTime());
next->updateSkipList ();
next->setClosed ();
next->setImmutable (*config_);
m_networkOPs->setLastCloseTime (next->info().closeTime);
openLedger_.emplace(next, cachedSLEs_,
@@ -1218,49 +1220,50 @@ ApplicationImp::startGenesisLedger()
m_ledgerMaster->switchLCL (next);
}
Ledger::pointer
std::shared_ptr<Ledger>
ApplicationImp::getLastFullLedger()
{
auto j = journal ("Ledger");
try
{
Ledger::pointer ledger;
std::uint32_t ledgerSeq;
uint256 ledgerHash;
std::tie (ledger, ledgerSeq, ledgerHash) =
loadLedgerHelper ("order by LedgerSeq desc limit 1", *this);
std::shared_ptr<Ledger> ledger;
std::uint32_t seq;
uint256 hash;
std::tie (ledger, seq, hash) =
loadLedgerHelper (
"order by LedgerSeq desc limit 1", *this);
if (!ledger)
return ledger;
ledger->setClosed ();
ledger->setImmutable(*config_);
if (getLedgerMaster ().haveLedger (ledgerSeq))
if (getLedgerMaster ().haveLedger (seq))
ledger->setValidated ();
if (ledger->getHash () != ledgerHash)
if (ledger->info().hash == hash)
{
auto j = journal ("Ledger");
if (j.error)
{
j.error << "Failed on ledger";
Json::Value p;
addJson (p, {*ledger, LedgerFill::full});
j.error << p;
}
assert (false);
return Ledger::pointer ();
JLOG (j.trace) << "Loaded ledger: " << hash;
return ledger;
}
JLOG (journal ("Ledger").trace) << "Loaded ledger: " << ledgerHash;
return ledger;
if (j.error)
{
j.error << "Failed on ledger";
Json::Value p;
addJson (p, {*ledger, LedgerFill::full});
j.error << p;
}
return {};
}
catch (SHAMapMissingNode& sn)
{
JLOG (journal ("Ledger").warning)
<< "Database contains ledger with missing nodes: " << sn;
return Ledger::pointer ();
JLOG (j.warning) <<
"Ledger with missing nodes in database: " << sn;
return {};
}
}
@@ -1269,7 +1272,7 @@ bool ApplicationImp::loadOldLedger (
{
try
{
Ledger::pointer loadLedger, replayLedger;
std::shared_ptr<Ledger> loadLedger, replayLedger;
if (isFileName)
{
@@ -1374,7 +1377,6 @@ bool ApplicationImp::loadOldLedger (
}
}
loadLedger->setClosed ();
loadLedger->stateMap().flushDirty
(hotACCOUNT_NODE, loadLedger->info().seq);
loadLedger->setAccepted (closeTime,
@@ -1446,9 +1448,9 @@ bool ApplicationImp::loadOldLedger (
}
}
loadLedger->setClosed ();
JLOG(m_journal.info) << "Loading ledger " << loadLedger->getHash () << " seq:" << loadLedger->info().seq;
JLOG(m_journal.info) <<
"Loading ledger " << loadLedger->info().hash <<
" seq:" << loadLedger->info().seq;
if (loadLedger->info().accountHash.isZero ())
{
@@ -1471,12 +1473,13 @@ bool ApplicationImp::loadOldLedger (
return false;
}
m_ledgerMaster->setLedgerRangePresent (loadLedger->info().seq, loadLedger->info().seq);
m_ledgerMaster->setLedgerRangePresent (
loadLedger->info().seq,
loadLedger->info().seq);
auto const openLedger =
std::make_shared<Ledger>(open_ledger, *loadLedger, timeKeeper().closeTime());
m_ledgerMaster->switchLCL (loadLedger);
m_ledgerMaster->forceValid(loadLedger);
loadLedger->setValidated();
m_ledgerMaster->setFullLedger(loadLedger, true, false);
m_networkOPs->setLastCloseTime (loadLedger->info().closeTime);
openLedger_.emplace(loadLedger, cachedSLEs_,
logs_->journal("OpenLedger"));

View File

@@ -20,7 +20,8 @@
#ifndef RIPPLE_APP_MISC_FEEVOTE_H_INCLUDED
#define RIPPLE_APP_MISC_FEEVOTE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/shamap/SHAMap.h>
#include <ripple/app/misc/Validations.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/protocol/SystemParameters.h>
@@ -60,7 +61,7 @@ public:
*/
virtual
void
doValidation (Ledger::ref lastClosedLedger,
doValidation (std::shared_ptr<ReadView const> const& lastClosedLedger,
STObject& baseValidation) = 0;
/** Cast our local vote on the fee.
@@ -70,8 +71,9 @@ public:
*/
virtual
void
doVoting (Ledger::ref lastClosedLedger, ValidationSet const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition) = 0;
doVoting (std::shared_ptr<ReadView const> const& lastClosedLedger,
ValidationSet const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition) = 0;
};
/** Build FeeVote::Setup from a config section. */

View File

@@ -98,11 +98,11 @@ public:
FeeVoteImpl (Setup const& setup, beast::Journal journal);
void
doValidation (Ledger::ref lastClosedLedger,
doValidation (std::shared_ptr<ReadView const> const& lastClosedLedger,
STObject& baseValidation) override;
void
doVoting (Ledger::ref lastClosedLedger,
doVoting (std::shared_ptr<ReadView const> const& lastClosedLedger,
ValidationSet const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition) override;
};
@@ -116,8 +116,9 @@ FeeVoteImpl::FeeVoteImpl (Setup const& setup, beast::Journal journal)
}
void
FeeVoteImpl::doValidation (Ledger::ref lastClosedLedger,
STObject& baseValidation)
FeeVoteImpl::doValidation(
std::shared_ptr<ReadView const> const& lastClosedLedger,
STObject& baseValidation)
{
if (lastClosedLedger->fees().base != target_.reference_fee)
{
@@ -146,9 +147,10 @@ FeeVoteImpl::doValidation (Ledger::ref lastClosedLedger,
}
void
FeeVoteImpl::doVoting (Ledger::ref lastClosedLedger,
ValidationSet const& set,
std::shared_ptr<SHAMap> const& initialPosition)
FeeVoteImpl::doVoting(
std::shared_ptr<ReadView const> const& lastClosedLedger,
ValidationSet const& set,
std::shared_ptr<SHAMap> const& initialPosition)
{
// LCL must be flag ledger
assert ((lastClosedLedger->info().seq % 256) == 0);

View File

@@ -303,7 +303,7 @@ public:
// Used for the "jump" case.
private:
void switchLastClosedLedger (
Ledger::pointer newLedger, bool duringConsensus);
std::shared_ptr<Ledger const> const& newLCL);
bool checkLastClosedLedger (
const Overlay::PeerSequence&, uint256& networkClosed);
void tryStartConsensus ();
@@ -356,9 +356,9 @@ public:
uint256 getConsensusLCL () override;
void reportFeeChange () override;
void updateLocalTx (Ledger::ref newValidLedger) override
void updateLocalTx (ReadView const& view) override
{
m_localTX->sweep (newValidLedger);
m_localTX->sweep (view);
}
std::size_t getLocalTxCount () override
{
@@ -402,7 +402,8 @@ public:
//
// Monitoring: publisher side.
//
void pubLedger (Ledger::ref lpAccepted) override;
void pubLedger (
std::shared_ptr<ReadView const> const& lpAccepted) override;
void pubProposedTransaction (
std::shared_ptr<ReadView const> const& lpCurrent,
std::shared_ptr<STTx const> const& stTxn, TER terResult) override;
@@ -484,9 +485,11 @@ private:
std::shared_ptr<ReadView const> const& lpCurrent);
void pubValidatedTransaction (
Ledger::ref alAccepted, const AcceptedLedgerTx& alTransaction);
std::shared_ptr<ReadView const> const& alAccepted,
const AcceptedLedgerTx& alTransaction);
void pubAccountTransaction (
std::shared_ptr<ReadView const> const& lpCurrent, const AcceptedLedgerTx& alTransaction,
std::shared_ptr<ReadView const> const& lpCurrent,
const AcceptedLedgerTx& alTransaction,
bool isAccepted);
void pubServer ();
@@ -1233,12 +1236,12 @@ bool NetworkOPsImp::checkLastClosedLedger (
JLOG(m_journal.trace) << "NetworkOPsImp::checkLastClosedLedger";
Ledger::pointer ourClosed = m_ledgerMaster.getClosedLedger ();
auto const ourClosed = m_ledgerMaster.getClosedLedger ();
if (!ourClosed)
return false;
uint256 closedLedger = ourClosed->getHash ();
uint256 closedLedger = ourClosed->info().hash;
uint256 prevClosedLedger = ourClosed->info().parentHash;
JLOG(m_journal.trace) << "OurClosed: " << closedLedger;
JLOG(m_journal.trace) << "PrevClosed: " << prevClosedLedger;
@@ -1331,7 +1334,7 @@ bool NetworkOPsImp::checkLastClosedLedger (
{
// don't switch to our own previous ledger
JLOG(m_journal.info) << "We won't switch to our own previous ledger";
networkClosed = ourClosed->getHash ();
networkClosed = ourClosed->info().hash;
switchLedgers = false;
}
else
@@ -1340,18 +1343,18 @@ bool NetworkOPsImp::checkLastClosedLedger (
if (!switchLedgers)
return false;
Ledger::pointer consensus = m_ledgerMaster.getLedgerByHash (closedLedger);
auto consensus = m_ledgerMaster.getLedgerByHash (closedLedger);
if (!consensus)
consensus = app_.getInboundLedgers().acquire (
closedLedger, 0, InboundLedger::fcCONSENSUS);
if (consensus &&
! m_ledgerMaster.isCompatible (consensus, m_journal.debug,
! m_ledgerMaster.isCompatible (*consensus, m_journal.debug,
"Not switching"))
{
// Don't switch to a ledger not on the validated chain
networkClosed = ourClosed->getHash ();
networkClosed = ourClosed->info().hash;
return false;
}
@@ -1369,23 +1372,20 @@ bool NetworkOPsImp::checkLastClosedLedger (
// FIXME: If this rewinds the ledger sequence, or has the same sequence, we
// should update the status on any stored transactions in the invalidated
// ledgers.
switchLastClosedLedger (consensus, false);
switchLastClosedLedger (consensus);
}
return true;
}
void NetworkOPsImp::switchLastClosedLedger (
Ledger::pointer newLCL, bool duringConsensus)
std::shared_ptr<Ledger const> const& newLCL)
{
// set the newLCL as our last closed ledger -- this is abnormal code
auto msg = duringConsensus ? "JUMPdc" : "JUMP";
JLOG(m_journal.error)
<< msg << " last closed ledger to " << newLCL->getHash ();
JLOG(m_journal.error) <<
"JUMP last closed ledger to " << newLCL->info().hash;
clearNeedNetworkLedger ();
newLCL->setClosed ();
// Update fee computations.
// TODO: Needs an open ledger
@@ -1420,10 +1420,12 @@ void NetworkOPsImp::switchLastClosedLedger (
s.set_newevent (protocol::neSWITCHED_LEDGER);
s.set_ledgerseq (newLCL->info().seq);
s.set_networktime (app_.timeKeeper().now().time_since_epoch().count());
uint256 hash = newLCL->info().parentHash;
s.set_ledgerhashprevious (hash.begin (), hash.size ());
hash = newLCL->getHash ();
s.set_ledgerhash (hash.begin (), hash.size ());
s.set_ledgerhashprevious (
newLCL->info().parentHash.begin (),
newLCL->info().parentHash.size ());
s.set_ledgerhash (
newLCL->info().hash.begin (),
newLCL->info().hash.size ());
app_.overlay ().foreach (send_always (
std::make_shared<Message> (s, protocol::mtSTATUS_CHANGE)));
@@ -1439,10 +1441,10 @@ bool NetworkOPsImp::beginConsensus (uint256 const& networkClosed)
"Consensus time for #" << closingInfo.seq <<
" with LCL " << closingInfo.parentHash;
auto prevLedger = m_ledgerMaster.getLedgerByHash (
auto prevLedger = m_ledgerMaster.getLedgerByHash(
closingInfo.parentHash);
if (!prevLedger)
if(! prevLedger)
{
// this shouldn't happen unless we jump ledgers
if (mMode == omFULL)
@@ -1454,11 +1456,9 @@ bool NetworkOPsImp::beginConsensus (uint256 const& networkClosed)
return false;
}
assert (prevLedger->getHash () == closingInfo.parentHash);
assert (prevLedger->info().hash == closingInfo.parentHash);
assert (closingInfo.parentHash ==
m_ledgerMaster.getClosedLedger ()->getHash ());
prevLedger->setImmutable (app_.config());
m_ledgerMaster.getClosedLedger()->info().hash);
mConsensus->startRound (
*mLedgerConsensus,
@@ -1820,11 +1820,13 @@ NetworkOPs::AccountTxs NetworkOPsImp::getAccountTxs (
{ // Work around a bug that could leave the metadata missing
auto const seq = rangeCheckedCast<std::uint32_t>(
ledgerSeq.value_or (0));
JLOG(m_journal.warning) << "Recovering ledger " << seq
<< ", txn " << txn->getID();
Ledger::pointer ledger = m_ledgerMaster.getLedgerBySeq(seq);
if (ledger)
pendSaveValidated(app_, ledger, false, false);
JLOG(m_journal.warning) <<
"Recovering ledger " << seq <<
", txn " << txn->getID();
if (auto l = m_ledgerMaster.getLedgerBySeq(seq))
pendSaveValidated(app_, l, false, false);
}
if (txn)
@@ -2059,12 +2061,12 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
}
bool valid = false;
Ledger::pointer lpClosed = m_ledgerMaster.getValidatedLedger ();
auto lpClosed = m_ledgerMaster.getValidatedLedger ();
if (lpClosed)
valid = true;
else
lpClosed = m_ledgerMaster.getClosedLedger ();
lpClosed = m_ledgerMaster.getClosedLedger ();
if (lpClosed)
{
@@ -2072,7 +2074,7 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
std::uint64_t baseRef = lpClosed->fees().units;
Json::Value l (Json::objectValue);
l[jss::seq] = Json::UInt (lpClosed->info().seq);
l[jss::hash] = to_string (lpClosed->getHash ());
l[jss::hash] = to_string (lpClosed->info().hash);
if (!human)
{
@@ -2121,8 +2123,8 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
else
info[jss::closed_ledger] = l;
Ledger::pointer lpPublished = m_ledgerMaster.getPublishedLedger ();
if (!lpPublished)
auto lpPublished = m_ledgerMaster.getPublishedLedger ();
if (! lpPublished)
info[jss::published_ledger] = "none";
else if (lpPublished->info().seq != lpClosed->info().seq)
info[jss::published_ledger] = lpPublished->info().seq;
@@ -2175,7 +2177,8 @@ void NetworkOPsImp::pubProposedTransaction (
pubAccountTransaction (lpCurrent, alt, false);
}
void NetworkOPsImp::pubLedger (Ledger::ref lpAccepted)
void NetworkOPsImp::pubLedger (
std::shared_ptr<ReadView const> const& lpAccepted)
{
// Ledgers are published only when they acquire sufficient validations
// Holes are filled across connection loss or other catastrophe
@@ -2199,7 +2202,7 @@ void NetworkOPsImp::pubLedger (Ledger::ref lpAccepted)
jvObj[jss::type] = "ledgerClosed";
jvObj[jss::ledger_index] = lpAccepted->info().seq;
jvObj[jss::ledger_hash] = to_string (lpAccepted->getHash ());
jvObj[jss::ledger_hash] = to_string (lpAccepted->info().hash);
jvObj[jss::ledger_time]
= Json::Value::UInt (lpAccepted->info().closeTime.time_since_epoch().count());
@@ -2306,7 +2309,8 @@ Json::Value NetworkOPsImp::transJson(
}
void NetworkOPsImp::pubValidatedTransaction (
Ledger::ref alAccepted, const AcceptedLedgerTx& alTx)
std::shared_ptr<ReadView const> const& alAccepted,
const AcceptedLedgerTx& alTx)
{
Json::Value jvObj = transJson (
*alTx.getTxn (), alTx.getResult (), true, alAccepted);
@@ -2546,7 +2550,7 @@ std::uint32_t NetworkOPsImp::acceptLedger (
// FIXME Could we improve on this and remove the need for a specialized
// API in LedgerConsensus?
beginConsensus (m_ledgerMaster.getClosedLedger ()->getHash ());
beginConsensus (m_ledgerMaster.getClosedLedger()->info().hash);
mLedgerConsensus->simulate (consensusDelay);
return m_ledgerMaster.getCurrentLedger ()->info().seq;
}
@@ -2554,12 +2558,10 @@ std::uint32_t NetworkOPsImp::acceptLedger (
// <-- bool: true=added, false=already there
bool NetworkOPsImp::subLedger (InfoSub::ref isrListener, Json::Value& jvResult)
{
Ledger::pointer lpClosed = m_ledgerMaster.getValidatedLedger ();
if (lpClosed)
if (auto lpClosed = m_ledgerMaster.getValidatedLedger ())
{
jvResult[jss::ledger_index] = lpClosed->info().seq;
jvResult[jss::ledger_hash] = to_string (lpClosed->getHash ());
jvResult[jss::ledger_hash] = to_string (lpClosed->info().hash);
jvResult[jss::ledger_time]
= Json::Value::UInt(lpClosed->info().closeTime.time_since_epoch().count());
jvResult[jss::fee_ref]

View File

@@ -24,6 +24,7 @@
#include <ripple/protocol/STValidation.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/ledger/LedgerProposal.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/net/InfoSub.h>
#include <memory>
#include <beast/threads/Stoppable.h>
@@ -197,7 +198,7 @@ public:
virtual void reportFeeChange () = 0;
virtual void updateLocalTx (Ledger::ref newValidLedger) = 0;
virtual void updateLocalTx (ReadView const& newValidLedger) = 0;
virtual std::size_t getLocalTxCount () = 0;
// client information retrieval functions
@@ -229,7 +230,8 @@ public:
//
// Monitoring: publisher side
//
virtual void pubLedger (Ledger::ref lpAccepted) = 0;
virtual void pubLedger (
std::shared_ptr<ReadView const> const& lpAccepted) = 0;
virtual void pubProposedTransaction (
std::shared_ptr<ReadView const> const& lpCurrent,
std::shared_ptr<STTx const> const& stTxn, TER terResult) = 0;

View File

@@ -54,7 +54,7 @@ public:
SHAMapStore (Stoppable& parent) : Stoppable ("SHAMapStore", parent) {}
/** Called by LedgerMaster every time a ledger validates. */
virtual void onLedgerClosed (Ledger::pointer validatedLedger) = 0;
virtual void onLedgerClosed(std::shared_ptr<Ledger const> const& ledger) = 0;
virtual std::uint32_t clampFetchDepth (std::uint32_t fetch_depth) const = 0;

View File

@@ -241,11 +241,12 @@ SHAMapStoreImp::makeDatabase (std::string const& name,
}
void
SHAMapStoreImp::onLedgerClosed (Ledger::pointer validatedLedger)
SHAMapStoreImp::onLedgerClosed(
std::shared_ptr<Ledger const> const& ledger)
{
{
std::lock_guard <std::mutex> lock (mutex_);
newLedger_ = validatedLedger;
newLedger_ = ledger;
}
cond_.notify_one();
}

View File

@@ -93,8 +93,8 @@ private:
bool healthy_ = true;
mutable std::condition_variable cond_;
mutable std::mutex mutex_;
Ledger::pointer newLedger_;
Ledger::pointer validatedLedger_;
std::shared_ptr<Ledger const> newLedger_;
std::shared_ptr<Ledger const> validatedLedger_;
TransactionMaster& transactionMaster_;
std::atomic <LedgerIndex> canDelete_;
// these do not exist upon SHAMapStore creation, but do exist
@@ -158,7 +158,7 @@ public:
return canDelete_;
}
void onLedgerClosed (Ledger::pointer validatedLedger) override;
void onLedgerClosed (std::shared_ptr<Ledger const> const& ledger) override;
private:
// callback for visitNodes

View File

@@ -57,9 +57,8 @@ convertBlobsToTxResult (
void
saveLedgerAsync (Application& app, std::uint32_t seq)
{
Ledger::pointer ledger = app.getLedgerMaster().getLedgerBySeq(seq);
if (ledger)
pendSaveValidated(app, ledger, false, false);
if (auto l = app.getLedgerMaster().getLedgerBySeq(seq))
pendSaveValidated(app, l, false, false);
}
void

View File

@@ -58,9 +58,8 @@ struct Regression_test : public beast::unit_test::suite
auto const aliceAmount = XRP(aliceXRP);
auto next = std::make_shared<Ledger>(
open_ledger, *closed,
*closed,
env.app().timeKeeper().closeTime());
next->setClosed();
{
// Fund alice
auto const jt = env.jt(pay(env.master, "alice", aliceAmount));

View File

@@ -683,7 +683,7 @@ Transactor::operator()()
// Transaction succeeded fully or (retries are
// not allowed and the transaction could claim a fee)
if(view().closed())
if(!view().open())
{
// Charge whatever fee they specified.

View File

@@ -65,6 +65,12 @@ public:
std::shared_ptr<SLE const>
read (Keylet const& k) const override;
bool
open() const override
{
return base_.open();
}
LedgerInfo const&
info() const override
{

View File

@@ -66,6 +66,7 @@ private:
ReadView const* base_;
detail::RawStateTable items_;
std::shared_ptr<void const> hold_;
bool open_ = true;
public:
OpenView() = delete;
@@ -134,6 +135,13 @@ public:
OpenView (ReadView const* base,
std::shared_ptr<void const> hold = nullptr);
/** Returns true if this reflects an open ledger. */
bool
open() const override
{
return open_;
}
/** Return the number of tx inserted since creation.
This is used to set the "apply ordinal"

View File

@@ -75,7 +75,6 @@ struct LedgerInfo
// For all ledgers
//
bool open = true;
LedgerIndex seq = 0;
NetClock::time_point parentCloseTime = {};
@@ -233,18 +232,9 @@ public:
info() const = 0;
/** Returns true if this reflects an open ledger. */
virtual
bool
open() const
{
return info().open;
}
/** Returns true if this reflects a closed ledger. */
bool
closed() const
{
return ! info().open;
}
open() const = 0;
/** Returns the close time of the previous ledger. */
NetClock::time_point

View File

@@ -46,6 +46,8 @@ public:
ReadView const* base, ApplyFlags flags);
// ReadView
bool
open() const override;
LedgerInfo const&
info() const override;

View File

@@ -116,7 +116,7 @@ ApplyStateTable::apply (OpenView& to,
std::make_shared<Serializer>();
tx.add(*sTx);
std::shared_ptr<Serializer> sMeta;
if (to.closed())
if (!to.open())
{
TxMeta meta(j);
// VFALCO Shouldn't TxMeta ctor do this?

View File

@@ -33,6 +33,12 @@ ApplyViewBase::ApplyViewBase(
//---
bool
ApplyViewBase::open() const
{
return base_->open();
}
LedgerInfo const&
ApplyViewBase::info() const
{

View File

@@ -94,7 +94,6 @@ OpenView::OpenView (open_ledger_t,
, base_ (base)
, hold_ (std::move(hold))
{
info_.open = true;
info_.validated = false;
info_.accepted = false;
info_.seq = base_->info().seq + 1;
@@ -108,6 +107,7 @@ OpenView::OpenView (ReadView const* base,
, info_ (base->info())
, base_ (base)
, hold_ (std::move(hold))
, open_ (base->open())
{
}
@@ -192,18 +192,16 @@ auto
OpenView::txsBegin() const ->
std::unique_ptr<txs_type::iter_base>
{
return std::make_unique<
txs_iter_impl>(
closed(), txs_.cbegin());
return std::make_unique<txs_iter_impl>(
!open(), txs_.cbegin());
}
auto
OpenView::txsEnd() const ->
std::unique_ptr<txs_type::iter_base>
{
return std::make_unique<
txs_iter_impl>(
closed(), txs_.cend());
return std::make_unique<txs_iter_impl>(
!open(), txs_.cend());
}
bool

View File

@@ -43,10 +43,9 @@ class SkipList_test : public beast::unit_test::suite
for (auto i = 0; i < 1023; ++i)
{
auto next = std::make_shared<Ledger>(
open_ledger, *prev,
*prev,
env.app().timeKeeper().closeTime());
next->updateSkipList();
next->setClosed();
history.push_back(next);
prev = next;
}

View File

@@ -155,7 +155,7 @@ class View_test
create_genesis, config, env.app().family());
auto const ledger =
std::make_shared<Ledger>(
open_ledger, *genesis,
*genesis,
env.app().timeKeeper().closeTime());
wipe(*ledger);
ReadView& v = *ledger;
@@ -419,7 +419,7 @@ class View_test
std::make_shared<Ledger> (
create_genesis, config, env.app().family());
auto const ledger = std::make_shared<Ledger>(
open_ledger, *genesis,
*genesis,
env.app().timeKeeper().closeTime());
auto setup123 = [&ledger, this]()
{
@@ -761,7 +761,7 @@ class View_test
create_genesis, config, env.app().family());
auto const ledger =
std::make_shared<Ledger>(
open_ledger, *genesis,
*genesis,
env.app().timeKeeper().closeTime());
wipe(*ledger);
ledger->rawInsert(sle(1));

View File

@@ -2111,7 +2111,7 @@ PeerImp::getLedger (std::shared_ptr<protocol::TMGetLedger> const& m)
// Figure out what ledger they want
JLOG(p_journal_.trace) << "GetLedger: Received";
Ledger::pointer ledger;
std::shared_ptr<Ledger const> ledger;
if (packet.has_ledgerhash ())
{
@@ -2176,10 +2176,14 @@ PeerImp::getLedger (std::shared_ptr<protocol::TMGetLedger> const& m)
else if (packet.has_ltype () && (packet.ltype () == protocol::ltCLOSED) )
{
ledger = app_.getLedgerMaster ().getClosedLedger ();
assert(! ledger->open());
// VFALCO ledger should never be null!
// VFALCO How can the closed ledger be open?
#if 0
if (ledger && ledger->info().open)
ledger = app_.getLedgerMaster ().getLedgerBySeq (
ledger->info().seq - 1);
#endif
}
else
{
@@ -2208,7 +2212,7 @@ PeerImp::getLedger (std::shared_ptr<protocol::TMGetLedger> const& m)
}
// Fill out the reply
uint256 lHash = ledger->getHash ();
auto const lHash = ledger->info().hash;
reply.set_ledgerhash (lHash.begin (), lHash.size ());
reply.set_ledgerseq (ledger->info().seq);
reply.set_type (packet.itype ());
@@ -2218,7 +2222,7 @@ PeerImp::getLedger (std::shared_ptr<protocol::TMGetLedger> const& m)
// they want the ledger base data
JLOG(p_journal_.trace) << "GetLedger: Base data";
Serializer nData (128);
ledger->addRaw (nData);
addRaw(ledger->info(), nData);
reply.add_nodes ()->set_nodedata (
nData.getDataPtr (), nData.getLength ());

View File

@@ -140,9 +140,11 @@ buildHello (
auto const closedLedger = app.getLedgerMaster().getClosedLedger();
if (closedLedger && !closedLedger->info().open)
assert(! closedLedger->open());
// VFALCO There should ALWAYS be a closed ledger
if (closedLedger)
{
uint256 hash = closedLedger->getHash ();
uint256 hash = closedLedger->info().hash;
h.set_ledgerclosed (hash.begin (), hash.size ());
hash = closedLedger->info().parentHash;
h.set_ledgerprevious (hash.begin (), hash.size ());

View File

@@ -33,7 +33,7 @@ Json::Value doLedgerClosed (RPC::Context& context)
Json::Value jvResult;
jvResult[jss::ledger_index] = ledger->info().seq;
jvResult[jss::ledger_hash] = to_string (ledger->getHash ());
jvResult[jss::ledger_hash] = to_string (ledger->info().hash);
return jvResult;
}

View File

@@ -138,7 +138,7 @@ Json::Value doTx (RPC::Context& context)
if (okay)
ret[jss::validated] = isValidated (
context, lgr->info().seq, lgr->getHash ());
context, lgr->info().seq, lgr->info().hash);
}
return ret;

View File

@@ -111,19 +111,19 @@ Status ledgerFromRequest (T& ledger, Context& context)
if (ledger == nullptr)
return {rpcNO_NETWORK, "InsufficientNetworkMode"};
assert (! ledger->info().open);
assert (! ledger->open());
}
else
{
if (index.empty () || index == "current")
{
ledger = ledgerMaster.getCurrentLedger ();
assert (ledger->info().open);
assert (ledger->open());
}
else if (index == "closed")
{
ledger = ledgerMaster.getClosedLedger ();
assert (! ledger->info().open);
assert (! ledger->open());
}
else
{
@@ -148,7 +148,7 @@ Status ledgerFromRequest (T& ledger, Context& context)
bool isValidated (LedgerMaster& ledgerMaster, ReadView const& ledger,
Application& app)
{
if (ledger.info().open)
if (ledger.open())
return false;
if (ledger.info().validated)
@@ -220,7 +220,7 @@ Status lookupLedger (
auto& info = ledger->info();
if (!info.open)
if (!ledger->open())
{
result[jss::ledger_hash] = to_string (info.hash);
result[jss::ledger_index] = info.seq;

View File

@@ -82,7 +82,7 @@ private:
Family& f_;
beast::Journal journal_;
std::uint32_t seq_;
std::uint32_t ledgerSeq_; // sequence number of ledger this is part of
std::uint32_t ledgerSeq_ = 0; // sequence number of ledger this is part of
std::shared_ptr<SHAMapAbstractNode> root_;
SHAMapState state_;
SHAMapType type_;
@@ -131,7 +131,14 @@ public:
// Returns a new map that's a snapshot of this one.
// Handles copy on write for mutable snapshots.
std::shared_ptr<SHAMap> snapShot (bool isMutable) const;
/* Sets metadata associated with the SHAMap
Marked `const` because the data is not part of
the map contents.
*/
void setLedgerSeq (std::uint32_t lseq);
bool fetchRoot (SHAMapHash const& hash, SHAMapSyncFilter * filter);
// normal hash access functions
@@ -198,7 +205,7 @@ public:
using fetchPackEntry_t = std::pair <uint256, Blob>;
void getFetchPack (SHAMap * have, bool includeLeaves, int max,
void getFetchPack (SHAMap const* have, bool includeLeaves, int max,
std::function<void (SHAMapHash const&, const Blob&)>) const;
void setUnbacked ();
@@ -211,7 +218,7 @@ private:
using DeltaRef = std::pair<std::shared_ptr<SHAMapItem const> const&,
std::shared_ptr<SHAMapItem const> const&>;
void visitDifferences(SHAMap* have, std::function<bool(SHAMapAbstractNode&)>) const;
void visitDifferences(SHAMap const* have, std::function<bool(SHAMapAbstractNode&)>) const;
int unshare ();
// tree node cache operations

View File

@@ -31,7 +31,6 @@ SHAMap::SHAMap (
: f_ (f)
, journal_(f.journal())
, seq_ (seq)
, ledgerSeq_ (0)
, state_ (SHAMapState::Modifying)
, type_ (t)
{
@@ -47,7 +46,6 @@ SHAMap::SHAMap (
: f_ (f)
, journal_(f.journal())
, seq_ (1)
, ledgerSeq_ (0)
, state_ (SHAMapState::Synching)
, type_ (t)
{

View File

@@ -671,7 +671,7 @@ SHAMap::hasLeafNode (uint256 const& tag, SHAMapHash const& targetNodeHash) const
Note: a caller should set includeLeaves to false for transaction trees.
There's no point in including the leaves of transaction trees.
*/
void SHAMap::getFetchPack (SHAMap* have, bool includeLeaves, int max,
void SHAMap::getFetchPack (SHAMap const* have, bool includeLeaves, int max,
std::function<void (SHAMapHash const&, const Blob&)> func) const
{
visitDifferences (have,
@@ -691,7 +691,7 @@ void SHAMap::getFetchPack (SHAMap* have, bool includeLeaves, int max,
}
void
SHAMap::visitDifferences(SHAMap* have,
SHAMap::visitDifferences(SHAMap const* have,
std::function<bool (SHAMapAbstractNode&)> func) const
{
// Visit every node in this SHAMap that is not present