Format first-party source according to .clang-format

This commit is contained in:
Pretty Printer
2020-04-17 09:56:34 -05:00
committed by manojsdoshi
parent 65dfc5d19e
commit 50760c6935
1076 changed files with 86161 additions and 77449 deletions

View File

@@ -37,25 +37,28 @@ public:
TxID txid;
Sequence seq;
TxIDSeq (TxID const& txid_, Sequence const& seq_)
: txid (txid_)
, seq (seq_)
{ }
TxIDSeq(TxID const& txid_, Sequence const& seq_)
: txid(txid_), seq(seq_)
{
}
};
friend bool operator< (TxIDSeq const& lhs, TxIDSeq const& rhs)
friend bool
operator<(TxIDSeq const& lhs, TxIDSeq const& rhs)
{
if (lhs.txid != rhs.txid)
return lhs.txid < rhs.txid;
return lhs.seq < rhs.seq;
}
friend bool operator< (TxIDSeq const& lhs, TxID const& rhs)
friend bool
operator<(TxIDSeq const& lhs, TxID const& rhs)
{
return lhs.txid < rhs;
}
friend bool operator< (TxID const& lhs, TxIDSeq const& rhs)
friend bool
operator<(TxID const& lhs, TxIDSeq const& rhs)
{
return lhs < rhs.txid;
}
@@ -73,17 +76,21 @@ public:
@param proposed The set of transactions that we are initially proposing
for this round.
*/
void propose(TxIDSeqVec proposed)
void
propose(TxIDSeqVec proposed)
{
// We want to remove any entries that we proposed in a previous round
// that did not make it in yet if we are no longer proposing them.
// And we also want to preserve the Sequence of entries that we proposed
// in the last round and want to propose again.
std::sort(proposed.begin(), proposed.end());
generalized_set_intersection(proposed.begin(), proposed.end(),
tracker_.cbegin(), tracker_.cend(),
[](auto& x, auto const& y) {x.seq = y.seq;},
[](auto const& x, auto const& y) {return x.txid < y.txid;});
generalized_set_intersection(
proposed.begin(),
proposed.end(),
tracker_.cbegin(),
tracker_.cend(),
[](auto& x, auto const& y) { x.seq = y.seq; },
[](auto const& x, auto const& y) { return x.txid < y.txid; });
tracker_ = std::move(proposed);
}
@@ -101,9 +108,8 @@ public:
It must return true for entries that should be removed.
*/
template <class Predicate>
void check(
std::vector<TxID> accepted,
Predicate&& pred)
void
check(std::vector<TxID> accepted, Predicate&& pred)
{
auto acceptTxid = accepted.begin();
auto const ae = accepted.end();
@@ -112,10 +118,13 @@ public:
// We want to remove all tracking entries for transactions that were
// accepted as well as those which match the predicate.
auto i = remove_if_intersect_or_match(tracker_.begin(), tracker_.end(),
accepted.begin(), accepted.end(),
[&pred](auto const& x) {return pred(x.txid, x.seq);},
std::less<void>{});
auto i = remove_if_intersect_or_match(
tracker_.begin(),
tracker_.end(),
accepted.begin(),
accepted.end(),
[&pred](auto const& x) { return pred(x.txid, x.seq); },
std::less<void>{});
tracker_.erase(i, tracker_.end());
}
@@ -124,12 +133,13 @@ public:
Typically, this function might be called after we reconnect to the
network following an outage, or after we start tracking the network.
*/
void reset()
void
reset()
{
tracker_.clear();
}
};
}
} // namespace ripple
#endif

View File

@@ -77,14 +77,14 @@ RCLConsensus::Adaptor::Adaptor(
ValidatorKeys const& validatorKeys,
beast::Journal journal)
: app_(app)
, feeVote_(std::move(feeVote))
, ledgerMaster_(ledgerMaster)
, localTxs_(localTxs)
, inboundTransactions_{inboundTransactions}
, j_(journal)
, nodeID_{validatorKeys.nodeID}
, valPublic_{validatorKeys.publicKey}
, valSecret_{validatorKeys.secretKey}
, feeVote_(std::move(feeVote))
, ledgerMaster_(ledgerMaster)
, localTxs_(localTxs)
, inboundTransactions_{inboundTransactions}
, j_(journal)
, nodeID_{validatorKeys.nodeID}
, valPublic_{validatorKeys.publicKey}
, valSecret_{validatorKeys.secretKey}
{
}
@@ -103,11 +103,12 @@ RCLConsensus::Adaptor::acquireLedger(LedgerHash const& hash)
// Tell the ledger acquire system that we need the consensus ledger
acquiringLedger_ = hash;
app_.getJobQueue().addJob(jtADVANCE, "getConsensusLedger",
[id = hash, &app = app_](Job&)
{
app.getInboundLedgers().acquire(id, 0,
InboundLedger::Reason::CONSENSUS);
app_.getJobQueue().addJob(
jtADVANCE,
"getConsensusLedger",
[id = hash, &app = app_](Job&) {
app.getInboundLedgers().acquire(
id, 0, InboundLedger::Reason::CONSENSUS);
});
}
return boost::none;
@@ -205,7 +206,7 @@ RCLConsensus::Adaptor::propose(RCLCxPeerPos::Proposal const& proposal)
valPublic_,
sig);
app_.getHashRouter ().addSuppression (suppression);
app_.getHashRouter().addSuppression(suppression);
app_.overlay().send(prop);
}
@@ -264,7 +265,7 @@ RCLConsensus::Adaptor::getPrevLedger(
if (mode != ConsensusMode::wrongLedger)
app_.getOPs().consensusViewChange();
JLOG(j_.debug())<< Json::Compact(app_.getValidations().getJsonTrie());
JLOG(j_.debug()) << Json::Compact(app_.getValidations().getJsonTrie());
}
return netLgr;
@@ -289,15 +290,15 @@ RCLConsensus::Adaptor::onClose(
auto initialLedger = app_.openLedger().current();
auto initialSet = std::make_shared<SHAMap>(
SHAMapType::TRANSACTION, app_.family());
auto initialSet =
std::make_shared<SHAMap>(SHAMapType::TRANSACTION, app_.family());
initialSet->setUnbacked();
// Build SHAMap containing all transactions in our open ledger
for (auto const& tx : initialLedger->txs)
{
JLOG(j_.trace()) << "Adding open ledger TX " <<
tx.first->getTransactionID();
JLOG(j_.trace()) << "Adding open ledger TX "
<< tx.first->getTransactionID();
Serializer s(2048);
tx.first->add(s);
initialSet->addItem(
@@ -311,11 +312,10 @@ RCLConsensus::Adaptor::onClose(
((prevLedger->info().seq % 256) == 0))
{
// previous ledger was flag ledger, add pseudo-transactions
auto const validations =
app_.getValidations().getTrustedForLedger (
prevLedger->info().parentHash);
auto const validations = app_.getValidations().getTrustedForLedger(
prevLedger->info().parentHash);
if (validations.size() >= app_.validators ().quorum ())
if (validations.size() >= app_.validators().quorum())
{
feeVote_->doVoting(prevLedger, validations, initialSet);
app_.getAmendmentTable().doVoting(
@@ -332,8 +332,7 @@ RCLConsensus::Adaptor::onClose(
RCLCensorshipDetector<TxID, LedgerIndex>::TxIDSeqVec proposed;
initialSet->visitLeaves(
[&proposed, seq](std::shared_ptr<SHAMapItem const> const& item)
{
[&proposed, seq](std::shared_ptr<SHAMapItem const> const& item) {
proposed.emplace_back(item->key(), seq);
});
@@ -361,7 +360,7 @@ RCLConsensus::Adaptor::onForceAccept(
NetClock::duration const& closeResolution,
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value && consensusJson)
Json::Value&& consensusJson)
{
doAccept(
result,
@@ -379,12 +378,12 @@ RCLConsensus::Adaptor::onAccept(
NetClock::duration const& closeResolution,
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value && consensusJson)
Json::Value&& consensusJson)
{
app_.getJobQueue().addJob(
jtACCEPT,
"acceptLedger",
[=, cj = std::move(consensusJson) ](auto&) mutable {
[=, cj = std::move(consensusJson)](auto&) mutable {
// Note that no lock is held or acquired during this job.
// This is because generic Consensus guarantees that once a ledger
// is accepted, the consensus results and capture by reference state
@@ -408,7 +407,7 @@ RCLConsensus::Adaptor::doAccept(
NetClock::duration closeResolution,
ConsensusCloseTimes const& rawCloseTimes,
ConsensusMode const& mode,
Json::Value && consensusJson)
Json::Value&& consensusJson)
{
prevProposers_ = result.proposers;
prevRoundTime_ = result.roundTime.read();
@@ -450,7 +449,7 @@ RCLConsensus::Adaptor::doAccept(
// we use the hash of the set.
//
// FIXME: Use a std::vector and a custom sorter instead of CanonicalTXSet?
CanonicalTXSet retriableTxs{ result.txns.map_->getHash().as_uint256() };
CanonicalTXSet retriableTxs{result.txns.map_->getHash().as_uint256()};
JLOG(j_.debug()) << "Building canonical tx set: " << retriableTxs.key();
@@ -458,7 +457,8 @@ RCLConsensus::Adaptor::doAccept(
{
try
{
retriableTxs.insert(std::make_shared<STTx const>(SerialIter{item.slice()}));
retriableTxs.insert(
std::make_shared<STTx const>(SerialIter{item.slice()}));
JLOG(j_.debug()) << " Tx: " << item.key();
}
catch (std::exception const&)
@@ -468,8 +468,14 @@ RCLConsensus::Adaptor::doAccept(
}
}
auto built = buildLCL(prevLedger, retriableTxs, consensusCloseTime,
closeTimeCorrect, closeResolution, result.roundTime.read(), failed);
auto built = buildLCL(
prevLedger,
retriableTxs,
consensusCloseTime,
closeTimeCorrect,
closeResolution,
result.roundTime.read(),
failed);
auto const newLCLHash = built.id();
JLOG(j_.debug()) << "Built ledger #" << built.seq() << ": " << newLCLHash;
@@ -484,20 +490,20 @@ RCLConsensus::Adaptor::doAccept(
{
std::vector<TxID> accepted;
result.txns.map_->visitLeaves (
[&accepted](std::shared_ptr<SHAMapItem const> const& item)
{
result.txns.map_->visitLeaves(
[&accepted](std::shared_ptr<SHAMapItem const> const& item) {
accepted.push_back(item->key());
});
// Track all the transactions which failed or were marked as retriable
for (auto const& r : retriableTxs)
failed.insert (r.first.getTXID());
failed.insert(r.first.getTXID());
censorshipDetector_.check(std::move(accepted),
[curr = built.seq(), j = app_.journal("CensorshipDetector"), &failed]
(uint256 const& id, LedgerIndex seq)
{
censorshipDetector_.check(
std::move(accepted),
[curr = built.seq(),
j = app_.journal("CensorshipDetector"),
&failed](uint256 const& id, LedgerIndex seq) {
if (failed.count(id))
return true;
@@ -508,8 +514,7 @@ RCLConsensus::Adaptor::doAccept(
std::ostringstream ss;
ss << "Potential Censorship: Eligible tx " << id
<< ", which we are tracking since ledger " << seq
<< " has not been included as of ledger " << curr
<< ".";
<< " has not been included as of ledger " << curr << ".";
JLOG(j.warn()) << ss.str();
}
@@ -617,15 +622,16 @@ RCLConsensus::Adaptor::doAccept(
// Do these need to exist?
assert(ledgerMaster_.getClosedLedger()->info().hash == built.id());
assert(
app_.openLedger().current()->info().parentHash == built.id());
assert(app_.openLedger().current()->info().parentHash == built.id());
}
//-------------------------------------------------------------------------
// we entered the round with the network,
// see how close our close time is to other node's
// close time reports, and update our clock.
if ((mode == ConsensusMode::proposing || mode == ConsensusMode::observing) && !consensusFail)
if ((mode == ConsensusMode::proposing ||
mode == ConsensusMode::observing) &&
!consensusFail)
{
auto closeTime = rawCloseTimes.self;
@@ -638,9 +644,8 @@ RCLConsensus::Adaptor::doAccept(
for (auto const& [t, v] : rawCloseTimes.peers)
{
JLOG(j_.info())
<< std::to_string(v) << " time votes for "
<< std::to_string(t.time_since_epoch().count());
JLOG(j_.info()) << std::to_string(v) << " time votes for "
<< std::to_string(t.time_since_epoch().count());
closeCount += v;
closeTotal +=
std::chrono::duration_cast<usec64_t>(t.time_since_epoch()) * v;
@@ -695,10 +700,9 @@ RCLConsensus::Adaptor::notify(
}
s.set_firstseq(uMin);
s.set_lastseq(uMax);
app_.overlay ().foreach (send_always (
std::make_shared <Message> (
s, protocol::mtSTATUS_CHANGE)));
JLOG (j_.trace()) << "send status change to peer";
app_.overlay().foreach (
send_always(std::make_shared<Message>(s, protocol::mtSTATUS_CHANGE)));
JLOG(j_.trace()) << "send status change to peer";
}
RCLCxLedger
@@ -711,15 +715,21 @@ RCLConsensus::Adaptor::buildLCL(
std::chrono::milliseconds roundTime,
std::set<TxID>& failedTxs)
{
std::shared_ptr<Ledger> built = [&]()
{
std::shared_ptr<Ledger> built = [&]() {
if (auto const replayData = ledgerMaster_.releaseReplay())
{
assert(replayData->parent()->info().hash == previousLedger.id());
return buildLedger(*replayData, tapNONE, app_, j_);
}
return buildLedger(previousLedger.ledger_, closeTime, closeTimeCorrect,
closeResolution, app_, retriableTxs, failedTxs, j_);
return buildLedger(
previousLedger.ledger_,
closeTime,
closeTimeCorrect,
closeResolution,
app_,
retriableTxs,
failedTxs,
j_);
}();
// Update fee computations based on accepted txs
@@ -737,7 +747,8 @@ RCLConsensus::Adaptor::buildLCL(
}
void
RCLConsensus::Adaptor::validate(RCLCxLedger const& ledger,
RCLConsensus::Adaptor::validate(
RCLCxLedger const& ledger,
RCLTxSet const& txns,
bool proposing)
{
@@ -762,7 +773,8 @@ RCLConsensus::Adaptor::validate(RCLCxLedger const& ledger,
{
// Suggest fee changes and new features
feeVote_->doValidation(ledger.ledger_, fees);
amendments = app_.getAmendmentTable().doValidation (getEnabledAmendments(*ledger.ledger_));
amendments = app_.getAmendmentTable().doValidation(
getEnabledAmendments(*ledger.ledger_));
}
auto v = std::make_shared<STValidation>(
@@ -789,16 +801,16 @@ RCLConsensus::Adaptor::validate(RCLCxLedger const& ledger,
}
void
RCLConsensus::Adaptor::onModeChange(
ConsensusMode before,
ConsensusMode after)
RCLConsensus::Adaptor::onModeChange(ConsensusMode before, ConsensusMode after)
{
JLOG(j_.info()) << "Consensus mode change before=" << to_string(before)
<< ", after=" << to_string(after);
// If we were proposing but aren't any longer, we need to reset the
// censorship tracking to avoid bogus warnings.
if ((before == ConsensusMode::proposing || before == ConsensusMode::observing) && before != after)
if ((before == ConsensusMode::proposing ||
before == ConsensusMode::observing) &&
before != after)
censorshipDetector_.reset();
mode_ = after;
@@ -809,8 +821,8 @@ RCLConsensus::getJson(bool full) const
{
Json::Value ret;
{
std::lock_guard _{mutex_};
ret = consensus_.getJson(full);
std::lock_guard _{mutex_};
ret = consensus_.getJson(full);
}
ret["validating"] = adaptor_.validating();
return ret;
@@ -848,7 +860,6 @@ RCLConsensus::gotTxSet(NetClock::time_point const& now, RCLTxSet const& txSet)
}
}
//! @see Consensus::simulate
void
@@ -870,13 +881,13 @@ RCLConsensus::peerProposal(
}
bool
RCLConsensus::Adaptor::preStartRound(RCLCxLedger const & prevLgr)
RCLConsensus::Adaptor::preStartRound(RCLCxLedger const& prevLgr)
{
// We have a key, we do not want out of sync validations after a restart
// and are not amendment blocked.
validating_ = valPublic_.size() != 0 &&
prevLgr.seq() >= app_.getMaxDisallowedLedger() &&
!app_.getOPs().isAmendmentBlocked();
prevLgr.seq() >= app_.getMaxDisallowedLedger() &&
!app_.getOPs().isAmendmentBlocked();
// If we are not running in standalone mode and there's a configured UNL,
// check to make sure that it's not expired.
@@ -892,8 +903,7 @@ RCLConsensus::Adaptor::preStartRound(RCLCxLedger const & prevLgr)
}
}
const bool synced = app_.getOPs().getOperatingMode() ==
OperatingMode::FULL;
const bool synced = app_.getOPs().getOperatingMode() == OperatingMode::FULL;
if (validating_)
{
@@ -933,7 +943,8 @@ RCLConsensus::Adaptor::getQuorumKeys() const
}
std::size_t
RCLConsensus::Adaptor::laggards(Ledger_t::Seq const seq,
RCLConsensus::Adaptor::laggards(
Ledger_t::Seq const seq,
hash_set<RCLConsensus::Adaptor::NodeKey_t>& trustedKeys) const
{
return app_.getValidations().laggards(seq, trustedKeys);
@@ -948,7 +959,7 @@ RCLConsensus::Adaptor::validator() const
void
RCLConsensus::Adaptor::updateOperatingMode(std::size_t const positions) const
{
if (! positions && app_.getOPs().isFull())
if (!positions && app_.getOPs().isFull())
app_.getOPs().setMode(OperatingMode::CONNECTED);
}
@@ -963,4 +974,4 @@ RCLConsensus::startRound(
consensus_.startRound(
now, prevLgrId, prevLgr, nowUntrusted, adaptor_.preStartRound(prevLgr));
}
}
} // namespace ripple

View File

@@ -20,10 +20,10 @@
#ifndef RIPPLE_APP_CONSENSUS_RCLCONSENSUS_H_INCLUDED
#define RIPPLE_APP_CONSENSUS_RCLCONSENSUS_H_INCLUDED
#include <ripple/app/consensus/RCLCensorshipDetector.h>
#include <ripple/app/consensus/RCLCxLedger.h>
#include <ripple/app/consensus/RCLCxPeerPos.h>
#include <ripple/app/consensus/RCLCxTx.h>
#include <ripple/app/consensus/RCLCensorshipDetector.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/Log.h>
@@ -45,10 +45,11 @@ class LedgerMaster;
class ValidatorKeys;
/** Manages the generic consensus algorithm for use by the RCL.
*/
*/
class RCLConsensus
{
/** Warn for transactions that haven't been included every so many ledgers. */
/** Warn for transactions that haven't been included every so many ledgers.
*/
constexpr static unsigned int censorshipWarnInternal = 15;
// Implements the Adaptor template interface required by Consensus.
@@ -97,7 +98,7 @@ class RCLConsensus
LedgerMaster& ledgerMaster,
LocalTxs& localTxs,
InboundTransactions& inboundTransactions,
ValidatorKeys const & validatorKeys,
ValidatorKeys const& validatorKeys,
beast::Journal journal);
bool
@@ -130,7 +131,7 @@ class RCLConsensus
@return Whether we enter the round proposing
*/
bool
preStartRound(RCLCxLedger const & prevLedger);
preStartRound(RCLCxLedger const& prevLedger);
bool
haveValidated() const;
@@ -142,8 +143,8 @@ class RCLConsensus
getQuorumKeys() const;
std::size_t
laggards(Ledger_t::Seq const seq,
hash_set<NodeKey_t >& trustedKeys) const;
laggards(Ledger_t::Seq const seq, hash_set<NodeKey_t>& trustedKeys)
const;
/** Whether I am a validator.
*
@@ -159,7 +160,8 @@ class RCLConsensus
*
* @param positions Number of current peer positions.
*/
void updateOperatingMode(std::size_t const positions) const;
void
updateOperatingMode(std::size_t const positions) const;
/** Consensus simulation parameters
*/
@@ -173,9 +175,9 @@ class RCLConsensus
//---------------------------------------------------------------------
// The following members implement the generic Consensus requirements
// and are marked private to indicate ONLY Consensus<Adaptor> will call
// them (via friendship). Since they are called only from Consensus<Adaptor>
// methods and since RCLConsensus::consensus_ should only be accessed
// under lock, these will only be called under lock.
// them (via friendship). Since they are called only from
// Consensus<Adaptor> methods and since RCLConsensus::consensus_ should
// only be accessed under lock, these will only be called under lock.
//
// In general, the idea is that there is only ONE thread that is running
// consensus code at anytime. The only special case is the dispatched
@@ -242,7 +244,7 @@ class RCLConsensus
descended from the preferred working ledger.
*/
std::size_t
proposersFinished(RCLCxLedger const & ledger, LedgerHash const& h) const;
proposersFinished(RCLCxLedger const& ledger, LedgerHash const& h) const;
/** Propose the given position to my peers.
@@ -281,9 +283,7 @@ class RCLConsensus
@param after The new consensus mode
*/
void
onModeChange(
ConsensusMode before,
ConsensusMode after);
onModeChange(ConsensusMode before, ConsensusMode after);
/** Close the open ledger and return initial consensus position.
@@ -400,7 +400,10 @@ class RCLConsensus
but are still around and trying to catch up.
*/
void
validate(RCLCxLedger const& ledger, RCLTxSet const& txns, bool proposing);
validate(
RCLCxLedger const& ledger,
RCLTxSet const& txns,
bool proposing);
};
public:
@@ -412,7 +415,7 @@ public:
LocalTxs& localTxs,
InboundTransactions& inboundTransactions,
Consensus<Adaptor>::clock_type const& clock,
ValidatorKeys const & validatorKeys,
ValidatorKeys const& validatorKeys,
beast::Journal journal);
RCLConsensus(RCLConsensus const&) = delete;
@@ -501,7 +504,7 @@ public:
NetClock::time_point const& now,
RCLCxPeerPos const& newProposal);
ConsensusParms const &
ConsensusParms const&
parms() const
{
return adaptor_.parms();
@@ -517,6 +520,6 @@ private:
Consensus<Adaptor> consensus_;
beast::Journal const j_;
};
}
} // namespace ripple
#endif

View File

@@ -119,5 +119,5 @@ public:
*/
std::shared_ptr<Ledger const> ledger_;
};
}
} // namespace ripple
#endif

View File

@@ -20,9 +20,9 @@
#include <ripple/app/consensus/RCLCxPeerPos.h>
#include <ripple/core/Config.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/jss.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/digest.h>
#include <ripple/protocol/jss.h>
namespace ripple {
@@ -54,11 +54,9 @@ RCLCxPeerPos::signingHash() const
bool
RCLCxPeerPos::checkSign() const
{
return verifyDigest(
publicKey(), signingHash(), signature(), false);
return verifyDigest(publicKey(), signingHash(), signature(), false);
}
Json::Value
RCLCxPeerPos::getJson() const
{
@@ -102,4 +100,4 @@ RCLCxPeerPos::Data::Data(
{
}
} // ripple
} // namespace ripple

View File

@@ -90,7 +90,7 @@ public:
return data_->suppression_;
}
Proposal const &
Proposal const&
proposal() const
{
return data_->proposal_;
@@ -101,7 +101,6 @@ public:
getJson() const;
private:
struct Data : public CountedObject<Data>
{
PublicKey publicKey_;
@@ -135,7 +134,6 @@ private:
hash_append(h, proposal().prevLedger());
hash_append(h, proposal().position());
}
};
/** Calculate a unique identifier for a signed proposal.
@@ -163,6 +161,6 @@ proposalUniqueId(
Slice const& publicKey,
Slice const& signature);
} // ripple
} // namespace ripple
#endif

View File

@@ -178,9 +178,7 @@ public:
std::map<uint256, bool> ret;
for (auto const& [k, v] : delta)
{
assert(
(v.first && !v.second) ||
(v.second && !v.first));
assert((v.first && !v.second) || (v.second && !v.first));
ret[k] = static_cast<bool>(v.first);
}
@@ -190,5 +188,5 @@ public:
//! The SHAMap representing the transactions.
std::shared_ptr<SHAMap> map_;
};
}
} // namespace ripple
#endif

View File

@@ -75,7 +75,8 @@ RCLValidatedLedger::id() const -> ID
return ledgerID_;
}
auto RCLValidatedLedger::operator[](Seq const& s) const -> ID
auto
RCLValidatedLedger::operator[](Seq const& s) const -> ID
{
if (s >= minSeq() && s <= seq())
{
@@ -112,7 +113,7 @@ mismatch(RCLValidatedLedger const& a, RCLValidatedLedger const& b)
}
RCLValidationsAdaptor::RCLValidationsAdaptor(Application& app, beast::Journal j)
: app_(app), j_(j)
: app_(app), j_(j)
{
}
@@ -123,7 +124,7 @@ RCLValidationsAdaptor::now() const
}
boost::optional<RCLValidatedLedger>
RCLValidationsAdaptor::acquire(LedgerHash const & hash)
RCLValidationsAdaptor::acquire(LedgerHash const& hash)
{
auto ledger = app_.getLedgerMaster().getLedgerByHash(hash);
if (!ledger)
@@ -131,11 +132,11 @@ RCLValidationsAdaptor::acquire(LedgerHash const & hash)
JLOG(j_.debug())
<< "Need validated ledger for preferred ledger analysis " << hash;
Application * pApp = &app_;
Application* pApp = &app_;
app_.getJobQueue().addJob(
jtADVANCE, "getConsensusLedger", [pApp, hash](Job&) {
pApp ->getInboundLedgers().acquire(
pApp->getInboundLedgers().acquire(
hash, 0, InboundLedger::Reason::CONSENSUS);
});
return boost::none;
@@ -148,7 +149,8 @@ RCLValidationsAdaptor::acquire(LedgerHash const & hash)
}
bool
handleNewValidation(Application& app,
handleNewValidation(
Application& app,
STValidation::ref val,
std::string const& source)
{
@@ -175,14 +177,13 @@ handleNewValidation(Application& app,
<< (val->isFull() ? "full" : "partial") << " from "
<< (masterKey ? toBase58(TokenType::NodePublic, *masterKey)
: "unknown")
<< " signing key "
<< toBase58(TokenType::NodePublic, signingKey) << " " << msg
<< " src=" << source;
<< " signing key " << toBase58(TokenType::NodePublic, signingKey)
<< " " << msg << " src=" << source;
};
if(!val->isFieldPresent(sfLedgerSequence))
if (!val->isFieldPresent(sfLedgerSequence))
{
if(j.error())
if (j.error())
dmp(j.error(), "missing ledger sequence field");
return false;
}
@@ -191,7 +192,7 @@ handleNewValidation(Application& app,
if (masterKey)
{
ValStatus const outcome = validations.add(calcNodeID(*masterKey), val);
if(j.debug())
if (j.debug())
dmp(j.debug(), to_string(outcome));
if (outcome == ValStatus::badSeq && j.warn())
@@ -211,8 +212,8 @@ handleNewValidation(Application& app,
else
{
JLOG(j.debug()) << "Val for " << hash << " from "
<< toBase58(TokenType::NodePublic, signingKey)
<< " not added UNlisted";
<< toBase58(TokenType::NodePublic, signingKey)
<< " not added UNlisted";
}
// This currently never forwards untrusted validations, though we may
@@ -226,5 +227,4 @@ handleNewValidation(Application& app,
return shouldRelay;
}
} // namespace ripple

View File

@@ -39,6 +39,7 @@ class Application;
class RCLValidation
{
STValidation::pointer val_;
public:
using NodeKey = ripple::PublicKey;
using NodeID = ripple::NodeID;
@@ -132,7 +133,6 @@ public:
{
return val_;
}
};
/** Wraps a ledger instance for use in generic Validations LedgerTrie.
@@ -174,7 +174,8 @@ public:
@return The ID of this ledger's ancestor with that sequence number or
ID{0} if one was not determined
*/
ID operator[](Seq const& s) const;
ID
operator[](Seq const& s) const;
/// Find the sequence number of the earliest mismatching ancestor
friend Seq
@@ -212,7 +213,7 @@ public:
/** Attempt to acquire the ledger with given id from the network */
boost::optional<RCLValidatedLedger>
acquire(LedgerHash const & id);
acquire(LedgerHash const& id);
beast::Journal
journal() const
@@ -228,7 +229,6 @@ private:
/// Alias for RCL-specific instantiation of generic Validations
using RCLValidations = Validations<RCLValidationsAdaptor>;
/** Handle a new validation
Also sets the trust status of a validation based on the validating node's

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_APP_LEDGER_ABSTRACTFETCHPACKCONTAINER_H_INCLUDED
#define RIPPLE_APP_LEDGER_ABSTRACTFETCHPACKCONTAINER_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/basics/Blob.h>
#include <ripple/basics/base_uint.h>
#include <boost/optional.hpp>
namespace ripple {
@@ -40,9 +40,10 @@ public:
@return `boost::none` if the hash isn't cached,
otherwise, the hash associated data.
*/
virtual boost::optional<Blob> getFetchPack(uint256 const& nodeHash) = 0;
virtual boost::optional<Blob>
getFetchPack(uint256 const& nodeHash) = 0;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -23,32 +23,35 @@
namespace ripple {
AcceptedLedger::AcceptedLedger (
AcceptedLedger::AcceptedLedger(
std::shared_ptr<ReadView const> const& ledger,
AccountIDCache const& accountCache, Logs& logs)
: mLedger (ledger)
AccountIDCache const& accountCache,
Logs& logs)
: mLedger(ledger)
{
for (auto const& item : ledger->txs)
{
insert (std::make_shared<AcceptedLedgerTx>(
insert(std::make_shared<AcceptedLedgerTx>(
ledger, item.first, item.second, accountCache, logs));
}
}
void AcceptedLedger::insert (AcceptedLedgerTx::ref at)
void
AcceptedLedger::insert(AcceptedLedgerTx::ref at)
{
assert (mMap.find (at->getIndex ()) == mMap.end ());
mMap.insert (std::make_pair (at->getIndex (), at));
assert(mMap.find(at->getIndex()) == mMap.end());
mMap.insert(std::make_pair(at->getIndex(), at));
}
AcceptedLedgerTx::pointer AcceptedLedger::getTxn (int i) const
AcceptedLedgerTx::pointer
AcceptedLedger::getTxn(int i) const
{
map_t::const_iterator it = mMap.find (i);
map_t::const_iterator it = mMap.find(i);
if (it == mMap.end ())
return AcceptedLedgerTx::pointer ();
if (it == mMap.end())
return AcceptedLedgerTx::pointer();
return it->second;
}
} // ripple
} // namespace ripple

View File

@@ -44,41 +44,46 @@ namespace ripple {
class AcceptedLedger
{
public:
using pointer = std::shared_ptr<AcceptedLedger>;
using ret = const pointer&;
using map_t = std::map<int, AcceptedLedgerTx::pointer>;
using pointer = std::shared_ptr<AcceptedLedger>;
using ret = const pointer&;
using map_t = std::map<int, AcceptedLedgerTx::pointer>;
// mapt_t must be an ordered map!
using value_type = map_t::value_type;
using value_type = map_t::value_type;
using const_iterator = map_t::const_iterator;
public:
std::shared_ptr<ReadView const> const& getLedger () const
std::shared_ptr<ReadView const> const&
getLedger() const
{
return mLedger;
}
const map_t& getMap () const
const map_t&
getMap() const
{
return mMap;
}
int getTxnCount () const
int
getTxnCount() const
{
return mMap.size ();
return mMap.size();
}
AcceptedLedgerTx::pointer getTxn (int) const;
AcceptedLedgerTx::pointer
getTxn(int) const;
AcceptedLedger (
AcceptedLedger(
std::shared_ptr<ReadView const> const& ledger,
AccountIDCache const& accountCache, Logs& logs);
AccountIDCache const& accountCache,
Logs& logs);
private:
void insert (AcceptedLedgerTx::ref);
void insert(AcceptedLedgerTx::ref);
std::shared_ptr<ReadView const> mLedger;
map_t mMap;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -17,96 +17,104 @@
*/
//==============================================================================
#include <ripple/app/main/Application.h>
#include <ripple/app/ledger/AcceptedLedgerTx.h>
#include <ripple/app/main/Application.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/protocol/jss.h>
#include <ripple/protocol/UintTypes.h>
#include <ripple/protocol/jss.h>
namespace ripple {
AcceptedLedgerTx::AcceptedLedgerTx (
AcceptedLedgerTx::AcceptedLedgerTx(
std::shared_ptr<ReadView const> const& ledger,
std::shared_ptr<STTx const> const& txn,
std::shared_ptr<STObject const> const& met,
AccountIDCache const& accountCache,
Logs& logs)
: mLedger (ledger)
, mTxn (txn)
, mMeta (std::make_shared<TxMeta> (
txn->getTransactionID(), ledger->seq(), *met))
, mAffected (mMeta->getAffectedAccounts (logs.journal("View")))
, accountCache_ (accountCache)
, logs_ (logs)
: mLedger(ledger)
, mTxn(txn)
, mMeta(std::make_shared<TxMeta>(
txn->getTransactionID(),
ledger->seq(),
*met))
, mAffected(mMeta->getAffectedAccounts(logs.journal("View")))
, accountCache_(accountCache)
, logs_(logs)
{
assert (! ledger->open());
assert(!ledger->open());
mResult = mMeta->getResultTER ();
mResult = mMeta->getResultTER();
Serializer s;
met->add(s);
mRawMeta = std::move (s.modData());
mRawMeta = std::move(s.modData());
buildJson ();
buildJson();
}
AcceptedLedgerTx::AcceptedLedgerTx (
AcceptedLedgerTx::AcceptedLedgerTx(
std::shared_ptr<ReadView const> const& ledger,
std::shared_ptr<STTx const> const& txn,
TER result,
AccountIDCache const& accountCache,
Logs& logs)
: mLedger (ledger)
, mTxn (txn)
, mResult (result)
, mAffected (txn->getMentionedAccounts ())
, accountCache_ (accountCache)
, logs_ (logs)
: mLedger(ledger)
, mTxn(txn)
, mResult(result)
, mAffected(txn->getMentionedAccounts())
, accountCache_(accountCache)
, logs_(logs)
{
assert (ledger->open());
buildJson ();
assert(ledger->open());
buildJson();
}
std::string AcceptedLedgerTx::getEscMeta () const
std::string
AcceptedLedgerTx::getEscMeta() const
{
assert (!mRawMeta.empty ());
return sqlEscape (mRawMeta);
assert(!mRawMeta.empty());
return sqlEscape(mRawMeta);
}
void AcceptedLedgerTx::buildJson ()
void
AcceptedLedgerTx::buildJson()
{
mJson = Json::objectValue;
mJson[jss::transaction] = mTxn->getJson (JsonOptions::none);
mJson[jss::transaction] = mTxn->getJson(JsonOptions::none);
if (mMeta)
{
mJson[jss::meta] = mMeta->getJson (JsonOptions::none);
mJson[jss::raw_meta] = strHex (mRawMeta);
mJson[jss::meta] = mMeta->getJson(JsonOptions::none);
mJson[jss::raw_meta] = strHex(mRawMeta);
}
mJson[jss::result] = transHuman (mResult);
mJson[jss::result] = transHuman(mResult);
if (! mAffected.empty ())
if (!mAffected.empty())
{
Json::Value& affected = (mJson[jss::affected] = Json::arrayValue);
for (auto const& account: mAffected)
affected.append (accountCache_.toBase58(account));
for (auto const& account : mAffected)
affected.append(accountCache_.toBase58(account));
}
if (mTxn->getTxnType () == ttOFFER_CREATE)
if (mTxn->getTxnType() == ttOFFER_CREATE)
{
auto const& account = mTxn->getAccountID(sfAccount);
auto const amount = mTxn->getFieldAmount (sfTakerGets);
auto const amount = mTxn->getFieldAmount(sfTakerGets);
// If the offer create is not self funded then add the owner balance
if (account != amount.issue ().account)
if (account != amount.issue().account)
{
auto const ownerFunds = accountFunds(*mLedger,
account, amount, fhIGNORE_FREEZE, logs_.journal ("View"));
mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText ();
auto const ownerFunds = accountFunds(
*mLedger,
account,
amount,
fhIGNORE_FREEZE,
logs_.journal("View"));
mJson[jss::transaction][jss::owner_funds] = ownerFunds.getText();
}
}
}
} // ripple
} // namespace ripple

View File

@@ -50,28 +50,30 @@ class Logs;
class AcceptedLedgerTx
{
public:
using pointer = std::shared_ptr <AcceptedLedgerTx>;
using pointer = std::shared_ptr<AcceptedLedgerTx>;
using ref = const pointer&;
public:
AcceptedLedgerTx (
AcceptedLedgerTx(
std::shared_ptr<ReadView const> const& ledger,
std::shared_ptr<STTx const> const&,
std::shared_ptr<STObject const> const&,
AccountIDCache const&,
Logs&);
AcceptedLedgerTx (
AcceptedLedgerTx(
std::shared_ptr<ReadView const> const&,
std::shared_ptr<STTx const> const&,
TER,
AccountIDCache const&,
Logs&);
std::shared_ptr <STTx const> const& getTxn () const
std::shared_ptr<STTx const> const&
getTxn() const
{
return mTxn;
}
std::shared_ptr <TxMeta> const& getMeta () const
std::shared_ptr<TxMeta> const&
getMeta() const
{
return mMeta;
}
@@ -82,33 +84,41 @@ public:
return mAffected;
}
TxID getTransactionID () const
TxID
getTransactionID() const
{
return mTxn->getTransactionID ();
return mTxn->getTransactionID();
}
TxType getTxnType () const
TxType
getTxnType() const
{
return mTxn->getTxnType ();
return mTxn->getTxnType();
}
TER getResult () const
TER
getResult() const
{
return mResult;
}
std::uint32_t getTxnSeq () const
std::uint32_t
getTxnSeq() const
{
return mMeta->getIndex ();
return mMeta->getIndex();
}
bool isApplied () const
bool
isApplied() const
{
return bool(mMeta);
}
int getIndex () const
int
getIndex() const
{
return mMeta ? mMeta->getIndex () : 0;
return mMeta ? mMeta->getIndex() : 0;
}
std::string getEscMeta () const;
Json::Value getJson () const
std::string
getEscMeta() const;
Json::Value
getJson() const
{
return mJson;
}
@@ -117,16 +127,17 @@ private:
std::shared_ptr<ReadView const> mLedger;
std::shared_ptr<STTx const> mTxn;
std::shared_ptr<TxMeta> mMeta;
TER mResult;
TER mResult;
boost::container::flat_set<AccountID> mAffected;
Blob mRawMeta;
Json::Value mJson;
Blob mRawMeta;
Json::Value mJson;
AccountIDCache const& accountCache_;
Logs& logs_;
void buildJson ();
void
buildJson();
};
} // ripple
} // namespace ripple
#endif

View File

@@ -22,12 +22,15 @@
namespace ripple {
void
AccountStateSF::gotNode(bool, SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq, Blob&& nodeData,
AccountStateSF::gotNode(
bool,
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType) const
{
db_.store(hotACCOUNT_NODE, std::move(nodeData),
nodeHash.as_uint256(), ledgerSeq);
db_.store(
hotACCOUNT_NODE, std::move(nodeData), nodeHash.as_uint256(), ledgerSeq);
}
boost::optional<Blob>
@@ -36,4 +39,4 @@ AccountStateSF::getNode(SHAMapHash const& nodeHash) const
return fp_.getFetchPack(nodeHash.as_uint256());
}
} // ripple
} // namespace ripple

View File

@@ -32,14 +32,17 @@ class AccountStateSF : public SHAMapSyncFilter
{
public:
AccountStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp)
: db_(db)
, fp_(fp)
{}
: db_(db), fp_(fp)
{
}
void
gotNode(bool fromFilter, SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq, Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
gotNode(
bool fromFilter,
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
boost::optional<Blob>
getNode(SHAMapHash const& nodeHash) const override;
@@ -49,6 +52,6 @@ private:
AbstractFetchPackContainer& fp_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -52,7 +52,7 @@ BookListeners::publish(
if (p)
{
// Only publish jvObj if this is the first occurence
if(havePublished.emplace(p->getSeq()).second)
if (havePublished.emplace(p->getSeq()).second)
{
p->send(jvObj, true);
}

View File

@@ -37,12 +37,12 @@ public:
}
/** Add a new subscription for this book
*/
*/
void
addSubscriber(InfoSub::ref sub);
/** Stop publishing to a subscriber
*/
*/
void
removeSubscriber(std::uint64_t sub);

View File

@@ -20,9 +20,9 @@
#ifndef RIPPLE_APP_LEDGER_BUILD_LEDGER_H_INCLUDED
#define RIPPLE_APP_LEDGER_BUILD_LEDGER_H_INCLUDED
#include <ripple/ledger/ApplyView.h>
#include <ripple/basics/chrono.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/ledger/ApplyView.h>
#include <chrono>
#include <memory>
@@ -34,7 +34,6 @@ class Ledger;
class LedgerReplay;
class SHAMap;
/** Build a new ledger by applying consensus transactions
Build a new ledger by applying a set of transactions accepted as part of

View File

@@ -23,80 +23,80 @@
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/basics/Log.h>
#include <ripple/protocol/digest.h>
#include <ripple/core/JobQueue.h>
#include <ripple/nodestore/Database.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/digest.h>
namespace ripple {
ConsensusTransSetSF::ConsensusTransSetSF (Application& app, NodeCache& nodeCache)
: app_ (app)
, m_nodeCache (nodeCache)
, j_ (app.journal ("TransactionAcquire"))
ConsensusTransSetSF::ConsensusTransSetSF(Application& app, NodeCache& nodeCache)
: app_(app), m_nodeCache(nodeCache), j_(app.journal("TransactionAcquire"))
{
}
void
ConsensusTransSetSF::gotNode(bool fromFilter, SHAMapHash const& nodeHash,
std::uint32_t, Blob&& nodeData, SHAMapTreeNode::TNType type) const
ConsensusTransSetSF::gotNode(
bool fromFilter,
SHAMapHash const& nodeHash,
std::uint32_t,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const
{
if (fromFilter)
return;
m_nodeCache.insert (nodeHash, nodeData);
m_nodeCache.insert(nodeHash, nodeData);
if ((type == SHAMapTreeNode::tnTRANSACTION_NM) && (nodeData.size () > 16))
if ((type == SHAMapTreeNode::tnTRANSACTION_NM) && (nodeData.size() > 16))
{
// this is a transaction, and we didn't have it
JLOG (j_.debug())
<< "Node on our acquiring TX set is TXN we may not have";
JLOG(j_.debug())
<< "Node on our acquiring TX set is TXN we may not have";
try
{
// skip prefix
Serializer s (nodeData.data() + 4, nodeData.size() - 4);
SerialIter sit (s.slice());
auto stx = std::make_shared<STTx const> (std::ref (sit));
assert (stx->getTransactionID () == nodeHash.as_uint256());
Serializer s(nodeData.data() + 4, nodeData.size() - 4);
SerialIter sit(s.slice());
auto stx = std::make_shared<STTx const>(std::ref(sit));
assert(stx->getTransactionID() == nodeHash.as_uint256());
auto const pap = &app_;
app_.getJobQueue ().addJob (
jtTRANSACTION, "TXS->TXN",
[pap, stx] (Job&) {
app_.getJobQueue().addJob(
jtTRANSACTION, "TXS->TXN", [pap, stx](Job&) {
pap->getOPs().submitTransaction(stx);
});
}
catch (std::exception const&)
{
JLOG (j_.warn())
<< "Fetched invalid transaction in proposed set";
JLOG(j_.warn()) << "Fetched invalid transaction in proposed set";
}
}
}
boost::optional<Blob>
ConsensusTransSetSF::getNode (SHAMapHash const& nodeHash) const
ConsensusTransSetSF::getNode(SHAMapHash const& nodeHash) const
{
Blob nodeData;
if (m_nodeCache.retrieve (nodeHash, nodeData))
if (m_nodeCache.retrieve(nodeHash, nodeData))
return nodeData;
auto txn = app_.getMasterTransaction().fetch_from_cache (nodeHash.as_uint256());
auto txn =
app_.getMasterTransaction().fetch_from_cache(nodeHash.as_uint256());
if (txn)
{
// this is a transaction, and we have it
JLOG (j_.trace())
<< "Node in our acquiring TX set is TXN we have";
JLOG(j_.trace()) << "Node in our acquiring TX set is TXN we have";
Serializer s;
s.add32 (HashPrefix::transactionID);
txn->getSTransaction ()->add (s);
s.add32(HashPrefix::transactionID);
txn->getSTransaction()->add(s);
assert(sha512Half(s.slice()) == nodeHash.as_uint256());
nodeData = s.peekData ();
nodeData = s.peekData();
return nodeData;
}
return boost::none;
}
} // ripple
} // namespace ripple

View File

@@ -21,8 +21,8 @@
#define RIPPLE_APP_LEDGER_CONSENSUSTRANSSETSF_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/shamap/SHAMapSyncFilter.h>
#include <ripple/basics/TaggedCache.h>
#include <ripple/shamap/SHAMapSyncFilter.h>
namespace ripple {
@@ -34,18 +34,21 @@ namespace ripple {
class ConsensusTransSetSF : public SHAMapSyncFilter
{
public:
using NodeCache = TaggedCache <SHAMapHash, Blob>;
using NodeCache = TaggedCache<SHAMapHash, Blob>;
ConsensusTransSetSF (Application& app, NodeCache& nodeCache);
ConsensusTransSetSF(Application& app, NodeCache& nodeCache);
// Note that the nodeData is overwritten by this call
void
gotNode(bool fromFilter, SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq, Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
gotNode(
bool fromFilter,
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
boost::optional<Blob>
getNode (SHAMapHash const& nodeHash) const override;
getNode(SHAMapHash const& nodeHash) const override;
private:
Application& app_;
@@ -53,6 +56,6 @@ private:
beast::Journal const j_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -20,10 +20,10 @@
#ifndef RIPPLE_APP_LEDGER_INBOUNDLEDGER_H_INCLUDED
#define RIPPLE_APP_LEDGER_INBOUNDLEDGER_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/overlay/PeerSet.h>
#include <ripple/app/main/Application.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/overlay/PeerSet.h>
#include <mutex>
#include <set>
#include <utility>
@@ -31,37 +31,44 @@
namespace ripple {
// A ledger we are trying to acquire
class InboundLedger
: public PeerSet
, public std::enable_shared_from_this <InboundLedger>
, public CountedObject <InboundLedger>
class InboundLedger : public PeerSet,
public std::enable_shared_from_this<InboundLedger>,
public CountedObject<InboundLedger>
{
public:
static char const* getCountedObjectName () { return "InboundLedger"; }
static char const*
getCountedObjectName()
{
return "InboundLedger";
}
using PeerDataPairType = std::pair<
std::weak_ptr<Peer>,
std::shared_ptr<protocol::TMLedgerData>>;
using PeerDataPairType =
std::pair<std::weak_ptr<Peer>, std::shared_ptr<protocol::TMLedgerData>>;
// These are the reasons we might acquire a ledger
enum class Reason
{
HISTORY, // Acquiring past ledger
SHARD, // Acquiring for shard
GENERIC, // Generic other reasons
CONSENSUS // We believe the consensus round requires this ledger
enum class Reason {
HISTORY, // Acquiring past ledger
SHARD, // Acquiring for shard
GENERIC, // Generic other reasons
CONSENSUS // We believe the consensus round requires this ledger
};
InboundLedger(Application& app, uint256 const& hash,
std::uint32_t seq, Reason reason, clock_type&);
InboundLedger(
Application& app,
uint256 const& hash,
std::uint32_t seq,
Reason reason,
clock_type&);
~InboundLedger ();
~InboundLedger();
// Called when the PeerSet timer expires
void execute () override;
void
execute() override;
// Called when another attempt is made to fetch this same ledger
void update (std::uint32_t seq);
void
update(std::uint32_t seq);
std::shared_ptr<Ledger const>
getLedger() const
@@ -69,7 +76,8 @@ public:
return mLedger;
}
std::uint32_t getSeq () const
std::uint32_t
getSeq() const
{
return mSeq;
}
@@ -80,82 +88,96 @@ public:
return mReason;
}
bool checkLocal ();
void init (ScopedLockType& collectionLock);
bool
checkLocal();
void
init(ScopedLockType& collectionLock);
bool
gotData(std::weak_ptr<Peer>,
gotData(
std::weak_ptr<Peer>,
std::shared_ptr<protocol::TMLedgerData> const&);
using neededHash_t =
std::pair <protocol::TMGetObjectByHash::ObjectType, uint256>;
std::pair<protocol::TMGetObjectByHash::ObjectType, uint256>;
/** Return a Json::objectValue. */
Json::Value getJson (int);
Json::Value
getJson(int);
void runData ();
void
runData();
static
LedgerInfo
static LedgerInfo
deserializeHeader(Slice data, bool hasPrefix);
private:
enum class TriggerReason
{
added,
reply,
timeout
};
enum class TriggerReason { added, reply, timeout };
void filterNodes (
void
filterNodes(
std::vector<std::pair<SHAMapNodeID, uint256>>& nodes,
TriggerReason reason);
void trigger (std::shared_ptr<Peer> const&, TriggerReason);
void
trigger(std::shared_ptr<Peer> const&, TriggerReason);
std::vector<neededHash_t> getNeededHashes ();
std::vector<neededHash_t>
getNeededHashes();
void addPeers ();
void tryDB (Family& f);
void
addPeers();
void
tryDB(Family& f);
void done ();
void
done();
void onTimer (bool progress, ScopedLockType& peerSetLock) override;
void
onTimer(bool progress, ScopedLockType& peerSetLock) override;
void newPeer (std::shared_ptr<Peer> const& peer) override
void
newPeer(std::shared_ptr<Peer> const& peer) override
{
// For historical nodes, do not trigger too soon
// since a fetch pack is probably coming
if (mReason != Reason::HISTORY)
trigger (peer, TriggerReason::added);
trigger(peer, TriggerReason::added);
}
std::weak_ptr <PeerSet> pmDowncast () override;
std::weak_ptr<PeerSet>
pmDowncast() override;
int processData (std::shared_ptr<Peer> peer, protocol::TMLedgerData& data);
int
processData(std::shared_ptr<Peer> peer, protocol::TMLedgerData& data);
bool takeHeader (std::string const& data);
bool takeTxNode (const std::vector<SHAMapNodeID>& IDs,
const std::vector<Blob>& data,
SHAMapAddNode&);
bool takeTxRootNode (Slice const& data, SHAMapAddNode&);
bool
takeHeader(std::string const& data);
bool
takeTxNode(
const std::vector<SHAMapNodeID>& IDs,
const std::vector<Blob>& data,
SHAMapAddNode&);
bool
takeTxRootNode(Slice const& data, SHAMapAddNode&);
// VFALCO TODO Rename to receiveAccountStateNode
// Don't use acronyms, but if we are going to use them at least
// capitalize them correctly.
//
bool takeAsNode (const std::vector<SHAMapNodeID>& IDs,
const std::vector<Blob>& data,
SHAMapAddNode&);
bool takeAsRootNode (Slice const& data, SHAMapAddNode&);
bool
takeAsNode(
const std::vector<SHAMapNodeID>& IDs,
const std::vector<Blob>& data,
SHAMapAddNode&);
bool
takeAsRootNode(Slice const& data, SHAMapAddNode&);
std::vector<uint256>
neededTxHashes (
int max, SHAMapSyncFilter* filter) const;
neededTxHashes(int max, SHAMapSyncFilter* filter) const;
std::vector<uint256>
neededStateHashes (
int max, SHAMapSyncFilter* filter) const;
neededStateHashes(int max, SHAMapSyncFilter* filter) const;
std::shared_ptr<Ledger> mLedger;
bool mHaveHeader;
@@ -166,16 +188,16 @@ private:
std::uint32_t mSeq;
Reason const mReason;
std::set <uint256> mRecentNodes;
std::set<uint256> mRecentNodes;
SHAMapAddNode mStats;
// Data we have received from peers
std::mutex mReceivedDataLock;
std::vector <PeerDataPairType> mReceivedData;
std::vector<PeerDataPairType> mReceivedData;
bool mReceiveDispatched;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -21,8 +21,8 @@
#define RIPPLE_APP_LEDGER_INBOUNDLEDGERS_H_INCLUDED
#include <ripple/app/ledger/InboundLedger.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <ripple/core/Stoppable.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <memory>
namespace ripple {
@@ -34,58 +34,71 @@ namespace ripple {
class InboundLedgers
{
public:
using clock_type = beast::abstract_clock <std::chrono::steady_clock>;
using clock_type = beast::abstract_clock<std::chrono::steady_clock>;
virtual ~InboundLedgers() = 0;
// VFALCO TODO Should this be called findOrAdd ?
//
virtual
std::shared_ptr<Ledger const>
acquire (uint256 const& hash,
std::uint32_t seq, InboundLedger::Reason) = 0;
virtual std::shared_ptr<Ledger const>
acquire(uint256 const& hash, std::uint32_t seq, InboundLedger::Reason) = 0;
virtual std::shared_ptr<InboundLedger> find (LedgerHash const& hash) = 0;
virtual std::shared_ptr<InboundLedger>
find(LedgerHash const& hash) = 0;
// VFALCO TODO Remove the dependency on the Peer object.
//
virtual bool gotLedgerData (LedgerHash const& ledgerHash,
virtual bool
gotLedgerData(
LedgerHash const& ledgerHash,
std::shared_ptr<Peer>,
std::shared_ptr <protocol::TMLedgerData>) = 0;
std::shared_ptr<protocol::TMLedgerData>) = 0;
virtual void doLedgerData (LedgerHash hash) = 0;
virtual void
doLedgerData(LedgerHash hash) = 0;
virtual void gotStaleData (
std::shared_ptr <protocol::TMLedgerData> packet) = 0;
virtual void
gotStaleData(std::shared_ptr<protocol::TMLedgerData> packet) = 0;
virtual int getFetchCount (int& timeoutCount) = 0;
virtual int
getFetchCount(int& timeoutCount) = 0;
virtual void logFailure (uint256 const& h, std::uint32_t seq) = 0;
virtual void
logFailure(uint256 const& h, std::uint32_t seq) = 0;
virtual bool isFailure (uint256 const& h) = 0;
virtual bool
isFailure(uint256 const& h) = 0;
virtual void clearFailures() = 0;
virtual void
clearFailures() = 0;
virtual Json::Value getInfo() = 0;
virtual Json::Value
getInfo() = 0;
/** Returns the rate of historical ledger fetches per minute. */
virtual std::size_t fetchRate() = 0;
virtual std::size_t
fetchRate() = 0;
/** Called when a complete ledger is obtained. */
virtual void onLedgerFetched() = 0;
virtual void
onLedgerFetched() = 0;
virtual void gotFetchPack () = 0;
virtual void sweep () = 0;
virtual void
gotFetchPack() = 0;
virtual void
sweep() = 0;
virtual void onStop() = 0;
virtual void
onStop() = 0;
};
std::unique_ptr<InboundLedgers>
make_InboundLedgers (Application& app,
InboundLedgers::clock_type& clock, Stoppable& parent,
make_InboundLedgers(
Application& app,
InboundLedgers::clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector);
} // ripple
} // namespace ripple
#endif

View File

@@ -20,10 +20,10 @@
#ifndef RIPPLE_APP_LEDGER_INBOUNDTRANSACTIONS_H_INCLUDED
#define RIPPLE_APP_LEDGER_INBOUNDTRANSACTIONS_H_INCLUDED
#include <ripple/overlay/Peer.h>
#include <ripple/shamap/SHAMap.h>
#include <ripple/beast/clock/abstract_clock.h>
#include <ripple/core/Stoppable.h>
#include <ripple/overlay/Peer.h>
#include <ripple/shamap/SHAMap.h>
#include <memory>
namespace ripple {
@@ -31,57 +31,61 @@ namespace ripple {
class Application;
/** Manages the acquisition and lifetime of transaction sets.
*/
*/
class InboundTransactions
{
public:
using clock_type = beast::abstract_clock <std::chrono::steady_clock>;
using clock_type = beast::abstract_clock<std::chrono::steady_clock>;
InboundTransactions() = default;
InboundTransactions(InboundTransactions const&) = delete;
InboundTransactions& operator=(InboundTransactions const&) = delete;
InboundTransactions&
operator=(InboundTransactions const&) = delete;
virtual ~InboundTransactions() = 0;
/** Retrieves a transaction set by hash
*/
virtual std::shared_ptr <SHAMap> getSet (
uint256 const& setHash,
bool acquire) = 0;
*/
virtual std::shared_ptr<SHAMap>
getSet(uint256 const& setHash, bool acquire) = 0;
/** Gives data to an inbound transaction set
*/
virtual void gotData (uint256 const& setHash,
std::shared_ptr <Peer>,
std::shared_ptr <protocol::TMLedgerData>) = 0;
*/
virtual void
gotData(
uint256 const& setHash,
std::shared_ptr<Peer>,
std::shared_ptr<protocol::TMLedgerData>) = 0;
/** Gives set to the container
*/
virtual void giveSet (uint256 const& setHash,
std::shared_ptr <SHAMap> const& set,
*/
virtual void
giveSet(
uint256 const& setHash,
std::shared_ptr<SHAMap> const& set,
bool acquired) = 0;
/** Informs the container if a new consensus round
*/
virtual void newRound (std::uint32_t seq) = 0;
*/
virtual void
newRound(std::uint32_t seq) = 0;
virtual Json::Value getInfo() = 0;
virtual Json::Value
getInfo() = 0;
virtual void onStop() = 0;
virtual void
onStop() = 0;
};
std::unique_ptr <InboundTransactions>
make_InboundTransactions (
std::unique_ptr<InboundTransactions>
make_InboundTransactions(
Application& app,
InboundTransactions::clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector,
std::function
<void (std::shared_ptr <SHAMap> const&,
bool)> gotSet);
std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet);
} // ripple
} // namespace ripple
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -20,17 +20,17 @@
#ifndef RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
#define RIPPLE_APP_LEDGER_LEDGER_H_INCLUDED
#include <ripple/basics/CountedObject.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/ledger/CachedView.h>
#include <ripple/ledger/TxMeta.h>
#include <ripple/ledger/View.h>
#include <ripple/ledger/CachedView.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/protocol/Book.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/STLedgerEntry.h>
#include <ripple/protocol/Serializer.h>
#include <ripple/protocol/Book.h>
#include <ripple/shamap/SHAMap.h>
#include <ripple/beast/utility/Journal.h>
#include <boost/optional.hpp>
#include <mutex>
@@ -74,17 +74,21 @@ extern create_genesis_t const create_genesis;
@note Presented to clients as ReadView
@note Calls virtuals in the constructor, so marked as final
*/
class Ledger final
: public std::enable_shared_from_this <Ledger>
, public DigestAwareReadView
, public TxsRawView
, public CountedObject <Ledger>
class Ledger final : public std::enable_shared_from_this<Ledger>,
public DigestAwareReadView,
public TxsRawView,
public CountedObject<Ledger>
{
public:
static char const* getCountedObjectName () { return "Ledger"; }
static char const*
getCountedObjectName()
{
return "Ledger";
}
Ledger (Ledger const&) = delete;
Ledger& operator= (Ledger const&) = delete;
Ledger(Ledger const&) = delete;
Ledger&
operator=(Ledger const&) = delete;
/** Create the Genesis ledger.
@@ -100,22 +104,19 @@ public:
Amendments specified are enabled in the genesis ledger
*/
Ledger (
Ledger(
create_genesis_t,
Config const& config,
std::vector<uint256> const& amendments,
Family& family);
Ledger (
LedgerInfo const& info,
Config const& config,
Family& family);
Ledger(LedgerInfo const& info, Config const& config, Family& family);
/** Used for ledgers loaded from JSON files
@param acquire If true, acquires the ledger if not found locally
*/
Ledger (
Ledger(
LedgerInfo const& info,
bool& loaded,
bool acquire,
@@ -129,13 +130,14 @@ public:
follows previous, and have
parentCloseTime == previous.closeTime.
*/
Ledger (Ledger const& previous,
NetClock::time_point closeTime);
Ledger(Ledger const& previous, NetClock::time_point closeTime);
// used for database ledgers
Ledger (std::uint32_t ledgerSeq,
NetClock::time_point closeTime, Config const& config,
Family& family);
Ledger(
std::uint32_t ledgerSeq,
NetClock::time_point closeTime,
Config const& config,
Family& family);
~Ledger() = default;
@@ -168,14 +170,14 @@ public:
}
bool
exists (Keylet const& k) const override;
exists(Keylet const& k) const override;
boost::optional<uint256>
succ (uint256 const& key, boost::optional<
uint256> const& last = boost::none) const override;
succ(uint256 const& key, boost::optional<uint256> const& last = boost::none)
const override;
std::shared_ptr<SLE const>
read (Keylet const& k) const override;
read(Keylet const& k) const override;
std::unique_ptr<sles_type::iter_base>
slesBegin() const override;
@@ -193,36 +195,33 @@ public:
txsEnd() const override;
bool
txExists (uint256 const& key) const override;
txExists(uint256 const& key) const override;
tx_type
txRead (key_type const& key) const override;
txRead(key_type const& key) const override;
//
// DigestAwareReadView
//
boost::optional<digest_type>
digest (key_type const& key) const override;
digest(key_type const& key) const override;
//
// RawView
//
void
rawErase (std::shared_ptr<
SLE> const& sle) override;
rawErase(std::shared_ptr<SLE> const& sle) override;
void
rawInsert (std::shared_ptr<
SLE> const& sle) override;
rawInsert(std::shared_ptr<SLE> const& sle) override;
void
rawReplace (std::shared_ptr<
SLE> const& sle) override;
rawReplace(std::shared_ptr<SLE> const& sle) override;
void
rawDestroyXRP (XRPAmount const& fee) override
rawDestroyXRP(XRPAmount const& fee) override
{
info_.drops -= fee;
}
@@ -232,25 +231,31 @@ public:
//
void
rawTxInsert (uint256 const& key,
std::shared_ptr<Serializer const
> const& txn, std::shared_ptr<
Serializer const> const& metaData) override;
rawTxInsert(
uint256 const& key,
std::shared_ptr<Serializer const> const& txn,
std::shared_ptr<Serializer const> const& metaData) override;
//--------------------------------------------------------------------------
void setValidated() const
void
setValidated() const
{
info_.validated = true;
}
void setAccepted (NetClock::time_point closeTime,
NetClock::duration closeResolution, bool correctCloseTime,
Config const& config);
void
setAccepted(
NetClock::time_point closeTime,
NetClock::duration closeResolution,
bool correctCloseTime,
Config const& config);
void setImmutable (Config const& config);
void
setImmutable(Config const& config);
bool isImmutable () const
bool
isImmutable() const
{
return mImmutable;
}
@@ -274,7 +279,8 @@ public:
stateMap_->setLedgerSeq(info_.seq);
}
void setTotalDrops (std::uint64_t totDrops)
void
setTotalDrops(std::uint64_t totDrops)
{
info_.drops = totDrops;
}
@@ -304,27 +310,34 @@ public:
}
// returns false on error
bool addSLE (SLE const& sle);
bool
addSLE(SLE const& sle);
//--------------------------------------------------------------------------
void updateSkipList ();
void
updateSkipList();
bool walkLedger (beast::Journal j) const;
bool
walkLedger(beast::Journal j) const;
bool assertSane (beast::Journal ledgerJ) const;
bool
assertSane(beast::Journal ledgerJ) const;
void
invariants() const;
void
unshare() const;
void invariants() const;
void unshare() const;
private:
class sles_iter_impl;
class txs_iter_impl;
bool
setup (Config const& config);
setup(Config const& config);
std::shared_ptr<SLE>
peek (Keylet const& k) const;
peek(Keylet const& k) const;
bool mImmutable;
@@ -348,44 +361,38 @@ using CachedLedger = CachedView<Ledger>;
//
//------------------------------------------------------------------------------
extern
bool
extern bool
pendSaveValidated(
Application& app,
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous,
bool isCurrent);
extern
std::shared_ptr<Ledger>
loadByIndex (std::uint32_t ledgerIndex,
Application& app, bool acquire = true);
extern std::shared_ptr<Ledger>
loadByIndex(std::uint32_t ledgerIndex, Application& app, bool acquire = true);
extern
std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
loadLedgerHelper(std::string const& sqlSuffix,
Application& app, bool acquire = true);
extern std::tuple<std::shared_ptr<Ledger>, std::uint32_t, uint256>
loadLedgerHelper(
std::string const& sqlSuffix,
Application& app,
bool acquire = true);
extern
std::shared_ptr<Ledger>
loadByHash (uint256 const& ledgerHash,
Application& app, bool acquire = true);
extern std::shared_ptr<Ledger>
loadByHash(uint256 const& ledgerHash, Application& app, bool acquire = true);
extern
uint256
extern uint256
getHashByIndex(std::uint32_t index, Application& app);
extern
bool
getHashesByIndex(std::uint32_t index,
uint256 &ledgerHash, uint256& parentHash,
Application& app);
extern
std::map< std::uint32_t, std::pair<uint256, uint256>>
getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq,
extern bool
getHashesByIndex(
std::uint32_t index,
uint256& ledgerHash,
uint256& parentHash,
Application& app);
extern std::map<std::uint32_t, std::pair<uint256, uint256>>
getHashesByIndex(std::uint32_t minSeq, std::uint32_t maxSeq, Application& app);
/** Deserialize a SHAMapItem containing a single STTx
Throw:
@@ -393,7 +400,7 @@ getHashesByIndex (std::uint32_t minSeq, std::uint32_t maxSeq,
May throw on deserializaton error
*/
std::shared_ptr<STTx const>
deserializeTx (SHAMapItem const& item);
deserializeTx(SHAMapItem const& item);
/** Deserialize a SHAMapItem containing STTx + STObject metadata
@@ -404,11 +411,9 @@ deserializeTx (SHAMapItem const& item);
May throw on deserializaton error
*/
std::pair<std::shared_ptr<
STTx const>, std::shared_ptr<
STObject const>>
deserializeTxPlusMeta (SHAMapItem const& item);
std::pair<std::shared_ptr<STTx const>, std::shared_ptr<STObject const>>
deserializeTxPlusMeta(SHAMapItem const& item);
} // ripple
} // namespace ripple
#endif

View File

@@ -21,26 +21,24 @@
#define RIPPLE_APP_LEDGER_LEDGERCLEANER_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/json/json_value.h>
#include <ripple/core/Stoppable.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/core/Stoppable.h>
#include <ripple/json/json_value.h>
#include <memory>
namespace ripple {
namespace detail {
/** Check the ledger/transaction databases to make sure they have continuity */
class LedgerCleaner
: public Stoppable
, public beast::PropertyStream::Source
class LedgerCleaner : public Stoppable, public beast::PropertyStream::Source
{
protected:
explicit LedgerCleaner (Stoppable& parent);
explicit LedgerCleaner(Stoppable& parent);
public:
/** Destroy the object. */
virtual ~LedgerCleaner () = 0;
virtual ~LedgerCleaner() = 0;
/** Start a long running task to clean the ledger.
The ledger is cleaned asynchronously, on an implementation defined
@@ -52,14 +50,14 @@ public:
@param parameters A Json object with configurable parameters.
*/
virtual void doClean (Json::Value const& parameters) = 0;
virtual void
doClean(Json::Value const& parameters) = 0;
};
std::unique_ptr<LedgerCleaner>
make_LedgerCleaner (Application& app,
Stoppable& parent, beast::Journal journal);
make_LedgerCleaner(Application& app, Stoppable& parent, beast::Journal journal);
} // detail
} // ripple
} // namespace detail
} // namespace ripple
#endif

View File

@@ -36,31 +36,37 @@ std::chrono::seconds constexpr CachedLedgerAge = std::chrono::minutes{2};
// FIXME: Need to clean up ledgers by index at some point
LedgerHistory::LedgerHistory (
LedgerHistory::LedgerHistory(
beast::insight::Collector::ptr const& collector,
Application& app)
: app_ (app)
, collector_ (collector)
, mismatch_counter_ (collector->make_counter ("ledger.history", "mismatch"))
, m_ledgers_by_hash ("LedgerCache", CACHED_LEDGER_NUM, CachedLedgerAge,
stopwatch(), app_.journal("TaggedCache"))
, m_consensus_validated ("ConsensusValidated", 64, std::chrono::minutes {5},
stopwatch(), app_.journal("TaggedCache"))
, j_ (app.journal ("LedgerHistory"))
Application& app)
: app_(app)
, collector_(collector)
, mismatch_counter_(collector->make_counter("ledger.history", "mismatch"))
, m_ledgers_by_hash(
"LedgerCache",
CACHED_LEDGER_NUM,
CachedLedgerAge,
stopwatch(),
app_.journal("TaggedCache"))
, m_consensus_validated(
"ConsensusValidated",
64,
std::chrono::minutes{5},
stopwatch(),
app_.journal("TaggedCache"))
, j_(app.journal("LedgerHistory"))
{
}
bool
LedgerHistory::insert(
std::shared_ptr<Ledger const> ledger,
bool validated)
LedgerHistory::insert(std::shared_ptr<Ledger const> ledger, bool validated)
{
if(! ledger->isImmutable())
if (!ledger->isImmutable())
LogicError("mutable Ledger in insert");
assert (ledger->stateMap().getHash ().isNonZero ());
assert(ledger->stateMap().getHash().isNonZero());
std::unique_lock sl (m_ledgers_by_hash.peekMutex ());
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
const bool alreadyHad = m_ledgers_by_hash.canonicalize_replace_cache(
ledger->info().hash, ledger);
@@ -70,44 +76,45 @@ LedgerHistory::insert(
return alreadyHad;
}
LedgerHash LedgerHistory::getLedgerHash (LedgerIndex index)
LedgerHash
LedgerHistory::getLedgerHash(LedgerIndex index)
{
std::unique_lock sl (m_ledgers_by_hash.peekMutex ());
auto it = mLedgersByIndex.find (index);
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
auto it = mLedgersByIndex.find(index);
if (it != mLedgersByIndex.end ())
if (it != mLedgersByIndex.end())
return it->second;
return uint256 ();
return uint256();
}
std::shared_ptr<Ledger const>
LedgerHistory::getLedgerBySeq (LedgerIndex index)
LedgerHistory::getLedgerBySeq(LedgerIndex index)
{
{
std::unique_lock sl (m_ledgers_by_hash.peekMutex ());
auto it = mLedgersByIndex.find (index);
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
auto it = mLedgersByIndex.find(index);
if (it != mLedgersByIndex.end ())
if (it != mLedgersByIndex.end())
{
uint256 hash = it->second;
sl.unlock ();
return getLedgerByHash (hash);
sl.unlock();
return getLedgerByHash(hash);
}
}
std::shared_ptr<Ledger const> ret = loadByIndex (index, app_);
std::shared_ptr<Ledger const> ret = loadByIndex(index, app_);
if (!ret)
return ret;
assert (ret->info().seq == index);
assert(ret->info().seq == index);
{
// Add this ledger to the local tracking by index
std::unique_lock sl (m_ledgers_by_hash.peekMutex ());
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
assert (ret->isImmutable ());
assert(ret->isImmutable());
m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret);
mLedgersByIndex[ret->info().seq] = ret->info().hash;
return (ret->info().seq == index) ? ret : nullptr;
@@ -115,32 +122,31 @@ LedgerHistory::getLedgerBySeq (LedgerIndex index)
}
std::shared_ptr<Ledger const>
LedgerHistory::getLedgerByHash (LedgerHash const& hash)
LedgerHistory::getLedgerByHash(LedgerHash const& hash)
{
auto ret = m_ledgers_by_hash.fetch (hash);
auto ret = m_ledgers_by_hash.fetch(hash);
if (ret)
{
assert (ret->isImmutable ());
assert (ret->info().hash == hash);
assert(ret->isImmutable());
assert(ret->info().hash == hash);
return ret;
}
ret = loadByHash (hash, app_);
ret = loadByHash(hash, app_);
if (!ret)
return ret;
assert (ret->isImmutable ());
assert (ret->info().hash == hash);
assert(ret->isImmutable());
assert(ret->info().hash == hash);
m_ledgers_by_hash.canonicalize_replace_client(ret->info().hash, ret);
assert (ret->info().hash == hash);
assert(ret->info().hash == hash);
return ret;
}
static
void
static void
log_one(
ReadView const& ledger,
uint256 const& tx,
@@ -151,19 +157,18 @@ log_one(
if (metaData != nullptr)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": " << msg << " is missing this transaction:\n" <<
metaData->getJson (JsonOptions::none);
JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg
<< " is missing this transaction:\n"
<< metaData->getJson(JsonOptions::none);
}
else
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": " << msg << " is missing this transaction.";
JLOG(j.debug()) << "MISMATCH on TX " << tx << ": " << msg
<< " is missing this transaction.";
}
}
static
void
static void
log_metadata_difference(
ReadView const& builtLedger,
ReadView const& validLedger,
@@ -171,35 +176,34 @@ log_metadata_difference(
beast::Journal j)
{
auto getMeta = [](ReadView const& ledger,
uint256 const& txID) -> std::shared_ptr<TxMeta>
{
uint256 const& txID) -> std::shared_ptr<TxMeta> {
auto meta = ledger.txRead(txID).second;
if (!meta)
return {};
return std::make_shared<TxMeta> (txID, ledger.seq(), *meta);
return std::make_shared<TxMeta>(txID, ledger.seq(), *meta);
};
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)
{
auto const& validNodes = validMetaData->getNodes ();
auto const& builtNodes = builtMetaData->getNodes ();
auto const& validNodes = validMetaData->getNodes();
auto const& builtNodes = builtMetaData->getNodes();
bool const result_diff =
validMetaData->getResultTER () != builtMetaData->getResultTER ();
validMetaData->getResultTER() != builtMetaData->getResultTER();
bool const index_diff =
validMetaData->getIndex() != builtMetaData->getIndex ();
validMetaData->getIndex() != builtMetaData->getIndex();
bool const nodes_diff = validNodes != builtNodes;
if (!result_diff && !index_diff && !nodes_diff)
{
JLOG (j.error()) << "MISMATCH on TX " << tx <<
": No apparent mismatches detected!";
JLOG(j.error()) << "MISMATCH on TX " << tx
<< ": No apparent mismatches detected!";
return;
}
@@ -207,105 +211,111 @@ log_metadata_difference(
{
if (result_diff && index_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different result and index!";
JLOG (j.debug()) << " Built:" <<
" Result: " << builtMetaData->getResult () <<
" Index: " << builtMetaData->getIndex ();
JLOG (j.debug()) << " Valid:" <<
" Result: " << validMetaData->getResult () <<
" Index: " << validMetaData->getIndex ();
JLOG(j.debug()) << "MISMATCH on TX " << tx
<< ": Different result and index!";
JLOG(j.debug()) << " Built:"
<< " Result: " << builtMetaData->getResult()
<< " Index: " << builtMetaData->getIndex();
JLOG(j.debug()) << " Valid:"
<< " Result: " << validMetaData->getResult()
<< " Index: " << validMetaData->getIndex();
}
else if (result_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different result!";
JLOG (j.debug()) << " Built:" <<
" Result: " << builtMetaData->getResult ();
JLOG (j.debug()) << " Valid:" <<
" Result: " << validMetaData->getResult ();
JLOG(j.debug())
<< "MISMATCH on TX " << tx << ": Different result!";
JLOG(j.debug()) << " Built:"
<< " Result: " << builtMetaData->getResult();
JLOG(j.debug()) << " Valid:"
<< " Result: " << validMetaData->getResult();
}
else if (index_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different index!";
JLOG (j.debug()) << " Built:" <<
" Index: " << builtMetaData->getIndex ();
JLOG (j.debug()) << " Valid:" <<
" Index: " << validMetaData->getIndex ();
JLOG(j.debug())
<< "MISMATCH on TX " << tx << ": Different index!";
JLOG(j.debug()) << " Built:"
<< " Index: " << builtMetaData->getIndex();
JLOG(j.debug()) << " Valid:"
<< " Index: " << validMetaData->getIndex();
}
}
else
{
if (result_diff && index_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different result, index and nodes!";
JLOG (j.debug()) << " Built:\n" <<
builtMetaData->getJson (JsonOptions::none);
JLOG (j.debug()) << " Valid:\n" <<
validMetaData->getJson (JsonOptions::none);
JLOG(j.debug()) << "MISMATCH on TX " << tx
<< ": Different result, index and nodes!";
JLOG(j.debug()) << " Built:\n"
<< builtMetaData->getJson(JsonOptions::none);
JLOG(j.debug()) << " Valid:\n"
<< validMetaData->getJson(JsonOptions::none);
}
else if (result_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different result and nodes!";
JLOG (j.debug()) << " Built:" <<
" Result: " << builtMetaData->getResult () <<
" Nodes:\n" << builtNodes.getJson (JsonOptions::none);
JLOG (j.debug()) << " Valid:" <<
" Result: " << validMetaData->getResult () <<
" Nodes:\n" << validNodes.getJson (JsonOptions::none);
JLOG(j.debug()) << "MISMATCH on TX " << tx
<< ": Different result and nodes!";
JLOG(j.debug())
<< " Built:"
<< " Result: " << builtMetaData->getResult() << " Nodes:\n"
<< builtNodes.getJson(JsonOptions::none);
JLOG(j.debug())
<< " Valid:"
<< " Result: " << validMetaData->getResult() << " Nodes:\n"
<< validNodes.getJson(JsonOptions::none);
}
else if (index_diff)
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different index and nodes!";
JLOG (j.debug()) << " Built:" <<
" Index: " << builtMetaData->getIndex () <<
" Nodes:\n" << builtNodes.getJson (JsonOptions::none);
JLOG (j.debug()) << " Valid:" <<
" Index: " << validMetaData->getIndex () <<
" Nodes:\n" << validNodes.getJson (JsonOptions::none);
JLOG(j.debug()) << "MISMATCH on TX " << tx
<< ": Different index and nodes!";
JLOG(j.debug())
<< " Built:"
<< " Index: " << builtMetaData->getIndex() << " Nodes:\n"
<< builtNodes.getJson(JsonOptions::none);
JLOG(j.debug())
<< " Valid:"
<< " Index: " << validMetaData->getIndex() << " Nodes:\n"
<< validNodes.getJson(JsonOptions::none);
}
else // nodes_diff
else // nodes_diff
{
JLOG (j.debug()) << "MISMATCH on TX " << tx <<
": Different nodes!";
JLOG (j.debug()) << " Built:" <<
" Nodes:\n" << builtNodes.getJson (JsonOptions::none);
JLOG (j.debug()) << " Valid:" <<
" Nodes:\n" << validNodes.getJson (JsonOptions::none);
JLOG(j.debug())
<< "MISMATCH on TX " << tx << ": Different nodes!";
JLOG(j.debug()) << " Built:"
<< " Nodes:\n"
<< builtNodes.getJson(JsonOptions::none);
JLOG(j.debug()) << " Valid:"
<< " Nodes:\n"
<< validNodes.getJson(JsonOptions::none);
}
}
}
else if (validMetaData != nullptr)
{
JLOG (j.error()) << "MISMATCH on TX " << tx <<
": Metadata Difference (built has none)\n" <<
validMetaData->getJson (JsonOptions::none);
JLOG(j.error()) << "MISMATCH on TX " << tx
<< ": Metadata Difference (built has none)\n"
<< validMetaData->getJson(JsonOptions::none);
}
else // builtMetaData != nullptr
else // builtMetaData != nullptr
{
JLOG (j.error()) << "MISMATCH on TX " << tx <<
": Metadata Difference (valid has none)\n" <<
builtMetaData->getJson (JsonOptions::none);
JLOG(j.error()) << "MISMATCH on TX " << tx
<< ": Metadata Difference (valid has none)\n"
<< builtMetaData->getJson(JsonOptions::none);
}
}
//------------------------------------------------------------------------------
// Return list of leaves sorted by key
static
std::vector<SHAMapItem const*>
leaves (SHAMap const& sm)
static std::vector<SHAMapItem const*>
leaves(SHAMap const& sm)
{
std::vector<SHAMapItem const*> v;
for (auto const& item : sm)
v.push_back(&item);
std::sort(v.begin(), v.end(),
[](SHAMapItem const* lhs, SHAMapItem const* rhs)
{ return lhs->key() < rhs->key(); });
std::sort(
v.begin(), v.end(), [](SHAMapItem const* lhs, SHAMapItem const* rhs) {
return lhs->key() < rhs->key();
});
return v;
}
@@ -317,26 +327,27 @@ LedgerHistory::handleMismatch(
boost::optional<uint256> const& validatedConsensusHash,
Json::Value const& consensus)
{
assert (built != valid);
assert(built != valid);
++mismatch_counter_;
auto builtLedger = getLedgerByHash (built);
auto validLedger = getLedgerByHash (valid);
auto builtLedger = getLedgerByHash(built);
auto validLedger = getLedgerByHash(valid);
if (!builtLedger || !validLedger)
{
JLOG (j_.error()) << "MISMATCH cannot be analyzed:" <<
" builtLedger: " << to_string (built) << " -> " << builtLedger <<
" validLedger: " << to_string (valid) << " -> " << validLedger;
JLOG(j_.error()) << "MISMATCH cannot be analyzed:"
<< " builtLedger: " << to_string(built) << " -> "
<< builtLedger << " validLedger: " << to_string(valid)
<< " -> " << validLedger;
return;
}
assert (builtLedger->info().seq == validLedger->info().seq);
assert(builtLedger->info().seq == validLedger->info().seq);
if (auto stream = j_.debug())
{
stream << "Built: " << getJson (*builtLedger);
stream << "Valid: " << getJson (*validLedger);
stream << "Built: " << getJson(*builtLedger);
stream << "Valid: " << getJson(*validLedger);
stream << "Consensus: " << consensus;
}
@@ -346,14 +357,14 @@ LedgerHistory::handleMismatch(
// Disagreement over prior ledger indicates sync issue
if (builtLedger->info().parentHash != validLedger->info().parentHash)
{
JLOG (j_.error()) << "MISMATCH on prior ledger";
JLOG(j_.error()) << "MISMATCH on prior ledger";
return;
}
// Disagreement over close time indicates Byzantine failure
if (builtLedger->info().closeTime != validLedger->info().closeTime)
{
JLOG (j_.error()) << "MISMATCH on close time";
JLOG(j_.error()) << "MISMATCH on close time";
return;
}
@@ -374,25 +385,23 @@ LedgerHistory::handleMismatch(
auto const validTx = leaves(validLedger->txMap());
if (builtTx == validTx)
JLOG (j_.error()) <<
"MISMATCH with same " << builtTx.size() <<
" transactions";
JLOG(j_.error()) << "MISMATCH with same " << builtTx.size()
<< " transactions";
else
JLOG (j_.error()) << "MISMATCH with " <<
builtTx.size() << " built and " <<
validTx.size() << " valid transactions.";
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();
auto v = validTx.begin();
while(b != builtTx.end() && v != validTx.end())
while (b != builtTx.end() && v != validTx.end())
{
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())
@@ -406,41 +415,40 @@ LedgerHistory::handleMismatch(
{
// Same transaction with different metadata
log_metadata_difference(
*builtLedger,
*validLedger, (*b)->key(), j_);
*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 (
void
LedgerHistory::builtLedger(
std::shared_ptr<Ledger const> const& ledger,
uint256 const& consensusHash,
Json::Value consensus)
{
LedgerIndex index = ledger->info().seq;
LedgerHash hash = ledger->info().hash;
assert (!hash.isZero());
assert(!hash.isZero());
std::unique_lock sl (
m_consensus_validated.peekMutex());
std::unique_lock sl(m_consensus_validated.peekMutex());
auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry);
if (entry->validated && ! entry->built)
if (entry->validated && !entry->built)
{
if (entry->validated.get() != hash)
{
JLOG (j_.error()) << "MISMATCH: seq=" << index
<< " validated:" << entry->validated.get()
<< " then:" << hash;
JLOG(j_.error())
<< "MISMATCH: seq=" << index
<< " validated:" << entry->validated.get() << " then:" << hash;
handleMismatch(
hash,
entry->validated.get(),
@@ -451,35 +459,35 @@ void LedgerHistory::builtLedger (
else
{
// We validated a ledger and then built it locally
JLOG (j_.debug()) << "MATCH: seq=" << index << " late";
JLOG(j_.debug()) << "MATCH: seq=" << index << " late";
}
}
entry->built.emplace (hash);
entry->built.emplace(hash);
entry->builtConsensusHash.emplace(consensusHash);
entry->consensus.emplace (std::move (consensus));
entry->consensus.emplace(std::move(consensus));
}
void LedgerHistory::validatedLedger (
void
LedgerHistory::validatedLedger(
std::shared_ptr<Ledger const> const& ledger,
boost::optional<uint256> const& consensusHash)
{
LedgerIndex index = ledger->info().seq;
LedgerHash hash = ledger->info().hash;
assert (!hash.isZero());
assert(!hash.isZero());
std::unique_lock sl (
m_consensus_validated.peekMutex());
std::unique_lock sl(m_consensus_validated.peekMutex());
auto entry = std::make_shared<cv_entry>();
m_consensus_validated.canonicalize_replace_client(index, entry);
if (entry->built && ! entry->validated)
if (entry->built && !entry->validated)
{
if (entry->built.get() != hash)
{
JLOG (j_.error()) << "MISMATCH: seq=" << index
<< " built:" << entry->built.get()
JLOG(j_.error())
<< "MISMATCH: seq=" << index << " built:" << entry->built.get()
<< " then:" << hash;
handleMismatch(
entry->built.get(),
@@ -491,23 +499,23 @@ void LedgerHistory::validatedLedger (
else
{
// We built a ledger locally and then validated it
JLOG (j_.debug()) << "MATCH: seq=" << index;
JLOG(j_.debug()) << "MATCH: seq=" << index;
}
}
entry->validated.emplace (hash);
entry->validated.emplace(hash);
entry->validatedConsensusHash = consensusHash;
}
/** Ensure m_ledgers_by_hash doesn't have the wrong hash for a particular index
*/
bool LedgerHistory::fixIndex (
LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
*/
bool
LedgerHistory::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
{
std::unique_lock sl (m_ledgers_by_hash.peekMutex ());
auto it = mLedgersByIndex.find (ledgerIndex);
std::unique_lock sl(m_ledgers_by_hash.peekMutex());
auto it = mLedgersByIndex.find(ledgerIndex);
if ((it != mLedgersByIndex.end ()) && (it->second != ledgerHash) )
if ((it != mLedgersByIndex.end()) && (it->second != ledgerHash))
{
it->second = ledgerHash;
return false;
@@ -515,20 +523,22 @@ bool LedgerHistory::fixIndex (
return true;
}
void LedgerHistory::tune (int size, std::chrono::seconds age)
void
LedgerHistory::tune(int size, std::chrono::seconds age)
{
m_ledgers_by_hash.setTargetSize (size);
m_ledgers_by_hash.setTargetAge (age);
m_ledgers_by_hash.setTargetSize(size);
m_ledgers_by_hash.setTargetAge(age);
}
void LedgerHistory::clearLedgerCachePrior (LedgerIndex seq)
void
LedgerHistory::clearLedgerCachePrior(LedgerIndex seq)
{
for (LedgerHash it: m_ledgers_by_hash.getKeys())
for (LedgerHash it : m_ledgers_by_hash.getKeys())
{
auto const ledger = getLedgerByHash (it);
auto const ledger = getLedgerByHash(it);
if (!ledger || ledger->info().seq < seq)
m_ledgers_by_hash.del (it, false);
m_ledgers_by_hash.del(it, false);
}
}
} // ripple
} // namespace ripple

View File

@@ -22,9 +22,9 @@
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <ripple/beast/insight/Collector.h>
#include <ripple/beast/insight/Event.h>
#include <ripple/protocol/RippleLedgerHash.h>
namespace ripple {
@@ -34,59 +34,66 @@ namespace ripple {
class LedgerHistory
{
public:
LedgerHistory (beast::insight::Collector::ptr const& collector,
LedgerHistory(
beast::insight::Collector::ptr const& collector,
Application& app);
/** Track a ledger
@return `true` if the ledger was already tracked
*/
bool insert (std::shared_ptr<Ledger const> 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
*/
float getCacheHitRate ()
float
getCacheHitRate()
{
return m_ledgers_by_hash.getHitRate ();
return m_ledgers_by_hash.getHitRate();
}
/** Get a ledger given its sequence number */
std::shared_ptr<Ledger const>
getLedgerBySeq (LedgerIndex ledgerIndex);
getLedgerBySeq(LedgerIndex ledgerIndex);
/** Retrieve a ledger given its hash */
std::shared_ptr<Ledger const>
getLedgerByHash (LedgerHash const& ledgerHash);
getLedgerByHash(LedgerHash const& ledgerHash);
/** Get a ledger's hash given its sequence number
@param ledgerIndex The sequence number of the desired ledger
@return The hash of the specified ledger
*/
LedgerHash getLedgerHash (LedgerIndex ledgerIndex);
LedgerHash
getLedgerHash(LedgerIndex ledgerIndex);
/** Set the history cache's parameters
@param size The target size of the cache
@param age The target age of the cache, in seconds
*/
void tune (int size, std::chrono::seconds age);
void
tune(int size, std::chrono::seconds age);
/** Remove stale cache entries
*/
void sweep ()
*/
void
sweep()
{
m_ledgers_by_hash.sweep ();
m_consensus_validated.sweep ();
m_ledgers_by_hash.sweep();
m_consensus_validated.sweep();
}
/** Report that we have locally built a particular ledger */
void builtLedger (
void
builtLedger(
std::shared_ptr<Ledger const> const&,
uint256 const& consensusHash,
Json::Value);
/** Report that we have validated a particular ledger */
void validatedLedger (
void
validatedLedger(
std::shared_ptr<Ledger const> const&,
boost::optional<uint256> const& consensusHash);
@@ -95,12 +102,13 @@ public:
@param ledgerHash The hash it is to be mapped to
@return `true` if the mapping was repaired
*/
bool fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash);
bool
fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash);
void clearLedgerCachePrior (LedgerIndex seq);
void
clearLedgerCachePrior(LedgerIndex seq);
private:
/** Log details in the case where we build one ledger but
validate a different one.
@param built The hash of the ledger we built
@@ -123,7 +131,7 @@ private:
beast::insight::Collector::ptr collector_;
beast::insight::Counter mismatch_counter_;
using LedgersByHash = TaggedCache <LedgerHash, Ledger const>;
using LedgersByHash = TaggedCache<LedgerHash, Ledger const>;
LedgersByHash m_ledgers_by_hash;
@@ -142,16 +150,15 @@ private:
// Consensus metadata of built ledger
boost::optional<Json::Value> consensus;
};
using ConsensusValidated = TaggedCache <LedgerIndex, cv_entry>;
using ConsensusValidated = TaggedCache<LedgerIndex, cv_entry>;
ConsensusValidated m_consensus_validated;
// Maps ledger indexes to the corresponding hash.
std::map <LedgerIndex, LedgerHash> mLedgersByIndex; // validated ledgers
std::map<LedgerIndex, LedgerHash> mLedgersByIndex; // validated ledgers
beast::Journal j_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -39,26 +39,29 @@ class LedgerHolder
{
public:
// Update the held ledger
void set (std::shared_ptr<Ledger const> ledger)
void
set(std::shared_ptr<Ledger const> ledger)
{
if(! ledger)
if (!ledger)
LogicError("LedgerHolder::set with nullptr");
if(! ledger->isImmutable())
if (!ledger->isImmutable())
LogicError("LedgerHolder::set with mutable Ledger");
std::lock_guard sl (m_lock);
std::lock_guard sl(m_lock);
m_heldLedger = std::move(ledger);
}
// Return the (immutable) held ledger
std::shared_ptr<Ledger const> get ()
std::shared_ptr<Ledger const>
get()
{
std::lock_guard sl (m_lock);
std::lock_guard sl(m_lock);
return m_heldLedger;
}
bool empty ()
bool
empty()
{
std::lock_guard sl (m_lock);
std::lock_guard sl(m_lock);
return m_heldLedger == nullptr;
}
@@ -67,6 +70,6 @@ private:
std::shared_ptr<Ledger const> m_heldLedger;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -20,7 +20,6 @@
#ifndef RIPPLE_APP_LEDGER_LEDGERMASTER_H_INCLUDED
#define RIPPLE_APP_LEDGER_LEDGERMASTER_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/app/ledger/AbstractFetchPackContainer.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/Ledger.h>
@@ -28,17 +27,18 @@
#include <ripple/app/ledger/LedgerHistory.h>
#include <ripple/app/ledger/LedgerHolder.h>
#include <ripple/app/ledger/LedgerReplay.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/RangeSet.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/chrono.h>
#include <ripple/beast/insight/Collector.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/core/Stoppable.h>
#include <ripple/protocol/messages.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/RippleLedgerHash.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/messages.h>
#include <boost/optional.hpp>
#include <mutex>
@@ -48,8 +48,6 @@ namespace ripple {
class Peer;
class Transaction;
// Tracks the current ledger and any ledgers in the process of closing
// Tracks ledger history
// Tracks held transactions
@@ -57,28 +55,28 @@ class Transaction;
// VFALCO TODO Rename to Ledgers
// It sounds like this holds all the ledgers...
//
class LedgerMaster
: public Stoppable
, public AbstractFetchPackContainer
class LedgerMaster : public Stoppable, public AbstractFetchPackContainer
{
public:
explicit
LedgerMaster(Application& app, Stopwatch& stopwatch,
explicit LedgerMaster(
Application& app,
Stopwatch& stopwatch,
Stoppable& parent,
beast::insight::Collector::ptr const& collector,
beast::Journal journal);
beast::insight::Collector::ptr const& collector,
beast::Journal journal);
virtual ~LedgerMaster () = default;
virtual ~LedgerMaster() = default;
LedgerIndex getCurrentLedgerIndex ();
LedgerIndex getValidLedgerIndex ();
LedgerIndex
getCurrentLedgerIndex();
LedgerIndex
getValidLedgerIndex();
bool isCompatible (
ReadView const&,
beast::Journal::Stream,
char const* reason);
bool
isCompatible(ReadView const&, beast::Journal::Stream, char const* reason);
std::recursive_mutex& peekMutex ();
std::recursive_mutex&
peekMutex();
// The current ledger is the ledger we believe new transactions should go in
std::shared_ptr<ReadView const>
@@ -93,49 +91,62 @@ public:
// The validated ledger is the last fully validated ledger
std::shared_ptr<Ledger const>
getValidatedLedger ()
getValidatedLedger()
{
return mValidLedger.get();
}
// The Rules are in the last fully validated ledger if there is one.
Rules getValidatedRules();
Rules
getValidatedRules();
// This is the last ledger we published to clients and can lag the validated
// ledger
std::shared_ptr<ReadView const>
getPublishedLedger();
std::chrono::seconds getPublishedLedgerAge ();
std::chrono::seconds getValidatedLedgerAge ();
bool isCaughtUp(std::string& reason);
std::chrono::seconds
getPublishedLedgerAge();
std::chrono::seconds
getValidatedLedgerAge();
bool
isCaughtUp(std::string& reason);
std::uint32_t getEarliestFetch ();
std::uint32_t
getEarliestFetch();
bool storeLedger (std::shared_ptr<Ledger const> ledger);
bool
storeLedger(std::shared_ptr<Ledger const> ledger);
void setFullLedger (
void
setFullLedger(
std::shared_ptr<Ledger const> const& ledger,
bool isSynchronous, bool isCurrent);
bool isSynchronous,
bool isCurrent);
/** Check the sequence number and parent close time of a
ledger against our clock and last validated ledger to
see if it can be the network's current ledger
*/
bool canBeCurrent (std::shared_ptr<Ledger const> const& ledger);
bool
canBeCurrent(std::shared_ptr<Ledger const> const& ledger);
void switchLCL (std::shared_ptr<Ledger const> const& lastClosed);
void
switchLCL(std::shared_ptr<Ledger const> const& lastClosed);
void failedSave(std::uint32_t seq, uint256 const& hash);
void
failedSave(std::uint32_t seq, uint256 const& hash);
std::string getCompleteLedgers ();
std::string
getCompleteLedgers();
/** Apply held transactions to the open ledger
This is normally called as we close the ledger.
The open ledger remains open to handle new transactions
until a new open ledger is built.
*/
void applyHeldTransactions ();
void
applyHeldTransactions();
/** Get all the transactions held for a particular account.
This is normally called when a transaction for that
@@ -144,15 +155,16 @@ public:
waiting for ledger close.
*/
std::vector<std::shared_ptr<STTx const>>
pruneHeldTransactions(AccountID const& account,
std::uint32_t const seq);
pruneHeldTransactions(AccountID const& account, std::uint32_t const seq);
/** Get a ledger's hash by sequence number using the cache
*/
uint256 getHashBySeq (std::uint32_t index);
*/
uint256
getHashBySeq(std::uint32_t index);
/** Walk to a ledger's hash using the skip list */
boost::optional<LedgerHash> walkHashBySeq (std::uint32_t index);
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
@@ -161,92 +173,115 @@ public:
from the reference ledger or any prior ledger are not present
in the node store.
*/
boost::optional<LedgerHash> walkHashBySeq (
boost::optional<LedgerHash>
walkHashBySeq(
std::uint32_t index,
std::shared_ptr<ReadView const> const& referenceLedger);
std::shared_ptr<Ledger const>
getLedgerBySeq (std::uint32_t index);
getLedgerBySeq(std::uint32_t index);
std::shared_ptr<Ledger const>
getLedgerByHash (uint256 const& hash);
getLedgerByHash(uint256 const& hash);
void setLedgerRangePresent (
std::uint32_t minV, std::uint32_t maxV);
void
setLedgerRangePresent(std::uint32_t minV, std::uint32_t maxV);
boost::optional<LedgerHash> getLedgerHash(
boost::optional<LedgerHash>
getLedgerHash(
std::uint32_t desiredSeq,
std::shared_ptr<ReadView const> const& knownGoodLedger);
boost::optional <NetClock::time_point> getCloseTimeBySeq (
LedgerIndex ledgerIndex);
boost::optional<NetClock::time_point>
getCloseTimeBySeq(LedgerIndex ledgerIndex);
boost::optional <NetClock::time_point> getCloseTimeByHash (
LedgerHash const& ledgerHash, LedgerIndex ledgerIndex);
boost::optional<NetClock::time_point>
getCloseTimeByHash(LedgerHash const& ledgerHash, LedgerIndex ledgerIndex);
void addHeldTransaction (std::shared_ptr<Transaction> const& trans);
void fixMismatch (ReadView const& ledger);
void
addHeldTransaction(std::shared_ptr<Transaction> const& trans);
void
fixMismatch(ReadView const& ledger);
bool haveLedger (std::uint32_t seq);
void clearLedger (std::uint32_t seq);
bool getValidatedRange (
std::uint32_t& minVal, std::uint32_t& maxVal);
bool getFullValidatedRange (
std::uint32_t& minVal, std::uint32_t& maxVal);
bool
haveLedger(std::uint32_t seq);
void
clearLedger(std::uint32_t seq);
bool
getValidatedRange(std::uint32_t& minVal, std::uint32_t& maxVal);
bool
getFullValidatedRange(std::uint32_t& minVal, std::uint32_t& maxVal);
void tune (int size, std::chrono::seconds age);
void sweep ();
float getCacheHitRate ();
void
tune(int size, std::chrono::seconds age);
void
sweep();
float
getCacheHitRate();
void checkAccept (std::shared_ptr<Ledger const> const& ledger);
void checkAccept (uint256 const& hash, std::uint32_t seq);
void
checkAccept(std::shared_ptr<Ledger const> const& ledger);
void
checkAccept(uint256 const& hash, std::uint32_t seq);
void
consensusBuilt(
std::shared_ptr<Ledger const> const& ledger,
uint256 const& consensusHash,
Json::Value consensus);
LedgerIndex getBuildingLedger ();
void setBuildingLedger (LedgerIndex index);
LedgerIndex
getBuildingLedger();
void
setBuildingLedger(LedgerIndex index);
void tryAdvance ();
bool newPathRequest (); // Returns true if path request successfully placed.
bool isNewPathRequest ();
bool newOrderBookDB (); // Returns true if able to fulfill request.
void
tryAdvance();
bool
newPathRequest(); // Returns true if path request successfully placed.
bool
isNewPathRequest();
bool
newOrderBookDB(); // Returns true if able to fulfill request.
bool fixIndex (
LedgerIndex ledgerIndex, LedgerHash const& ledgerHash);
void doLedgerCleaner(Json::Value const& parameters);
bool
fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash);
void
doLedgerCleaner(Json::Value const& parameters);
beast::PropertyStream::Source& getPropertySource ();
beast::PropertyStream::Source&
getPropertySource();
void clearPriorLedgers (LedgerIndex seq);
void
clearPriorLedgers(LedgerIndex seq);
void clearLedgerCachePrior (LedgerIndex seq);
void
clearLedgerCachePrior(LedgerIndex seq);
// ledger replay
void takeReplay (std::unique_ptr<LedgerReplay> replay);
std::unique_ptr<LedgerReplay> releaseReplay ();
void
takeReplay(std::unique_ptr<LedgerReplay> replay);
std::unique_ptr<LedgerReplay>
releaseReplay();
// Fetch Packs
void gotFetchPack (
bool progress,
std::uint32_t seq);
void
gotFetchPack(bool progress, std::uint32_t seq);
void addFetchPack (
uint256 const& hash,
std::shared_ptr<Blob>& data);
void
addFetchPack(uint256 const& hash, std::shared_ptr<Blob>& data);
boost::optional<Blob>
getFetchPack (uint256 const& hash) override;
getFetchPack(uint256 const& hash) override;
void makeFetchPack (
void
makeFetchPack(
std::weak_ptr<Peer> const& wPeer,
std::shared_ptr<protocol::TMGetObjectByHash> const& request,
uint256 haveLedgerHash,
UptimeClock::time_point uptime);
std::size_t getFetchPackCacheSize () const;
std::size_t
getFetchPackCacheSize() const;
//! Whether we have ever fully validated a ledger.
bool
@@ -256,40 +291,45 @@ public:
}
private:
void setValidLedger(
std::shared_ptr<Ledger const> const& l);
void setPubLedger(
std::shared_ptr<Ledger const> const& l);
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
tryFill(Job& job, std::shared_ptr<Ledger const> ledger);
void getFetchPack(
LedgerIndex missing, InboundLedger::Reason reason);
void
getFetchPack(LedgerIndex missing, InboundLedger::Reason reason);
boost::optional<LedgerHash> getLedgerHashForHistory(
LedgerIndex index, InboundLedger::Reason reason);
boost::optional<LedgerHash>
getLedgerHashForHistory(LedgerIndex index, InboundLedger::Reason reason);
std::size_t getNeededValidations();
void advanceThread();
void fetchForHistory(
std::size_t
getNeededValidations();
void
advanceThread();
void
fetchForHistory(
std::uint32_t missing,
bool& progress,
InboundLedger::Reason reason,
std::unique_lock<std::recursive_mutex>&);
// Try to publish ledgers, acquire missing ledgers. Always called with
// m_mutex locked. The passed lock is a reminder to callers.
void doAdvance(std::unique_lock<std::recursive_mutex>&);
void
doAdvance(std::unique_lock<std::recursive_mutex>&);
std::vector<std::shared_ptr<Ledger const>>
findNewLedgersToPublish(std::unique_lock<std::recursive_mutex>&);
void updatePaths(Job& job);
void
updatePaths(Job& job);
// Returns true if work started. Always called with m_mutex locked.
// The passed lock is a reminder to callers.
bool newPFWork(const char *name, std::unique_lock<std::recursive_mutex>&);
bool
newPFWork(const char* name, std::unique_lock<std::recursive_mutex>&);
Application& app_;
beast::Journal m_journal;
@@ -315,11 +355,11 @@ private:
std::shared_ptr<Ledger const> mShardLedger;
// Fully validated ledger, whether or not we have the ledger resident.
std::pair <uint256, LedgerIndex> mLastValidLedger {uint256(), 0};
std::pair<uint256, LedgerIndex> mLastValidLedger{uint256(), 0};
LedgerHistory mLedgerHistory;
CanonicalTXSet mHeldTransactions {uint256()};
CanonicalTXSet mHeldTransactions{uint256()};
// A set of transactions to replay during the next close
std::unique_ptr<LedgerReplay> replayData;
@@ -327,25 +367,26 @@ private:
std::recursive_mutex mCompleteLock;
RangeSet<std::uint32_t> mCompleteLedgers;
std::unique_ptr <detail::LedgerCleaner> mLedgerCleaner;
std::unique_ptr<detail::LedgerCleaner> mLedgerCleaner;
// Publish thread is running.
bool mAdvanceThread {false};
bool mAdvanceThread{false};
// Publish thread has work to do.
bool mAdvanceWork {false};
int mFillInProgress {0};
bool mAdvanceWork{false};
int mFillInProgress{0};
int mPathFindThread {0}; // Pathfinder jobs dispatched
bool mPathFindNewRequest {false};
int mPathFindThread{0}; // Pathfinder jobs dispatched
bool mPathFindNewRequest{false};
std::atomic_flag mGotFetchPackThread = ATOMIC_FLAG_INIT; // GotFetchPack jobs dispatched
std::atomic_flag mGotFetchPackThread =
ATOMIC_FLAG_INIT; // GotFetchPack jobs dispatched
std::atomic <std::uint32_t> mPubLedgerClose {0};
std::atomic <LedgerIndex> mPubLedgerSeq {0};
std::atomic <std::uint32_t> mValidLedgerSign {0};
std::atomic <LedgerIndex> mValidLedgerSeq {0};
std::atomic <LedgerIndex> mBuildingLedgerSeq {0};
std::atomic<std::uint32_t> mPubLedgerClose{0};
std::atomic<LedgerIndex> mPubLedgerSeq{0};
std::atomic<std::uint32_t> mValidLedgerSign{0};
std::atomic<LedgerIndex> mValidLedgerSeq{0};
std::atomic<LedgerIndex> mBuildingLedgerSeq{0};
// The server is in standalone mode
bool const standalone_;
@@ -360,21 +401,26 @@ private:
TaggedCache<uint256, Blob> fetch_packs_;
std::uint32_t fetch_seq_ {0};
std::uint32_t fetch_seq_{0};
// Try to keep a validator from switching from test to live network
// without first wiping the database.
LedgerIndex const max_ledger_difference_ {1000000};
LedgerIndex const max_ledger_difference_{1000000};
private:
struct Stats
{
template <class Handler>
Stats (Handler const& handler, beast::insight::Collector::ptr const& collector)
: hook (collector->make_hook (handler))
, validatedLedgerAge (collector->make_gauge ("LedgerMaster", "Validated_Ledger_Age"))
, publishedLedgerAge (collector->make_gauge ("LedgerMaster", "Published_Ledger_Age"))
{ }
Stats(
Handler const& handler,
beast::insight::Collector::ptr const& collector)
: hook(collector->make_hook(handler))
, validatedLedgerAge(
collector->make_gauge("LedgerMaster", "Validated_Ledger_Age"))
, publishedLedgerAge(
collector->make_gauge("LedgerMaster", "Published_Ledger_Age"))
{
}
beast::insight::Hook hook;
beast::insight::Gauge validatedLedgerAge;
@@ -384,19 +430,15 @@ private:
Stats m_stats;
private:
void collect_metrics()
void
collect_metrics()
{
std::lock_guard lock (m_mutex);
std::lock_guard lock(m_mutex);
m_stats.validatedLedgerAge.set(getValidatedLedgerAge().count());
m_stats.publishedLedgerAge.set(getPublishedLedgerAge().count());
}
};
} // ripple
} // namespace ripple
#endif

View File

@@ -41,7 +41,7 @@ public:
std::shared_ptr<Ledger const> replay);
/** @return The parent of the ledger to replay
*/
*/
std::shared_ptr<Ledger const> const&
parent() const
{
@@ -49,7 +49,7 @@ public:
}
/** @return The ledger to replay
*/
*/
std::shared_ptr<Ledger const> const&
replay() const
{
@@ -57,7 +57,7 @@ public:
}
/** @return Transactions in the order they should be replayed
*/
*/
std::map<std::uint32_t, std::shared_ptr<STTx const>> const&
orderedTxns() const
{

View File

@@ -23,20 +23,20 @@
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/misc/TxQ.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/protocol/jss.h>
#include <ripple/protocol/STTx.h>
#include <ripple/json/Object.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/jss.h>
namespace ripple {
struct LedgerFill
{
LedgerFill (ReadView const& l, int o = 0, std::vector<TxQ::TxDetails> q = {},
LedgerEntryType t = ltINVALID)
: ledger (l)
, options (o)
, txQueue(std::move(q))
, type (t)
LedgerFill(
ReadView const& l,
int o = 0,
std::vector<TxQ::TxDetails> q = {},
LedgerEntryType t = ltINVALID)
: ledger(l), options(o), txQueue(std::move(q)), type(t)
{
}
@@ -60,14 +60,17 @@ struct LedgerFill
description of the ledger.
*/
void addJson(Json::Value&, LedgerFill const&);
void
addJson(Json::Value&, LedgerFill const&);
/** Return a new Json::Value representing the ledger with given options.*/
Json::Value getJson (LedgerFill const&);
Json::Value
getJson(LedgerFill const&);
/** Serialize an object to a blob. */
template <class Object>
Blob serializeBlob(Object const& o)
Blob
serializeBlob(Object const& o)
{
Serializer s;
o.add(s);
@@ -75,11 +78,11 @@ Blob serializeBlob(Object const& o)
}
/** Serialize an object to a hex string. */
inline
std::string serializeHex(STObject const& o)
inline std::string
serializeHex(STObject const& o)
{
return strHex(serializeBlob(o));
}
} // ripple
} // namespace ripple
#endif

View File

@@ -33,23 +33,27 @@ namespace ripple {
class LocalTxs
{
public:
virtual ~LocalTxs () = default;
virtual ~LocalTxs() = default;
// Add a new local transaction
virtual void push_back (LedgerIndex index, std::shared_ptr<STTx const> const& txn) = 0;
virtual void
push_back(LedgerIndex index, std::shared_ptr<STTx const> const& txn) = 0;
// Return the set of local transactions to a new open ledger
virtual CanonicalTXSet getTxSet () = 0;
virtual CanonicalTXSet
getTxSet() = 0;
// Remove obsolete transactions based on a new fully-valid ledger
virtual void sweep (ReadView const& view) = 0;
virtual void
sweep(ReadView const& view) = 0;
virtual std::size_t size () = 0;
virtual std::size_t
size() = 0;
};
std::unique_ptr<LocalTxs>
make_LocalTxs ();
make_LocalTxs();
} // ripple
} // namespace ripple
#endif

View File

@@ -21,13 +21,13 @@
#define RIPPLE_APP_LEDGER_OPENLEDGER_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/ledger/CachedSLEs.h>
#include <ripple/ledger/OpenView.h>
#include <ripple/app/misc/CanonicalTXSet.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/core/Config.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/core/Config.h>
#include <ripple/ledger/CachedSLEs.h>
#include <ripple/ledger/OpenView.h>
#include <cassert>
#include <mutex>
@@ -67,22 +67,21 @@ public:
`true` won't cause harm, but it may be
sub-optimal.
*/
using modify_type = std::function<
bool(OpenView&, beast::Journal)>;
using modify_type = std::function<bool(OpenView&, beast::Journal)>;
OpenLedger() = delete;
OpenLedger (OpenLedger const&) = delete;
OpenLedger& operator= (OpenLedger const&) = delete;
OpenLedger(OpenLedger const&) = delete;
OpenLedger&
operator=(OpenLedger const&) = delete;
/** Create a new open ledger object.
@param ledger A closed ledger
*/
explicit
OpenLedger(std::shared_ptr<
Ledger const> const& ledger,
CachedSLEs& cache,
beast::Journal journal);
explicit OpenLedger(
std::shared_ptr<Ledger const> const& ledger,
CachedSLEs& cache,
beast::Journal journal);
/** Returns `true` if there are no transactions.
@@ -124,7 +123,7 @@ public:
@return `true` if the open view was changed
*/
bool
modify (modify_type const& f);
modify(modify_type const& f);
/** Accept a new ledger.
@@ -160,12 +159,16 @@ public:
@param ledger A new closed ledger
*/
void
accept (Application& app, Rules const& rules,
accept(
Application& app,
Rules const& rules,
std::shared_ptr<Ledger const> const& ledger,
OrderedTxs const& locals, bool retriesFirst,
OrderedTxs& retries, ApplyFlags flags,
std::string const& suffix = "",
modify_type const& f = {});
OrderedTxs const& locals,
bool retriesFirst,
OrderedTxs& retries,
ApplyFlags flags,
std::string const& suffix = "",
modify_type const& f = {});
private:
/** Algorithm for applying transactions.
@@ -174,45 +177,48 @@ private:
used for consensus and building the open ledger.
*/
template <class FwdRange>
static
void
apply (Application& app, OpenView& view,
ReadView const& check, FwdRange const& txs,
OrderedTxs& retries, ApplyFlags flags,
std::map<uint256, bool>& shouldRecover,
beast::Journal j);
static void
apply(
Application& app,
OpenView& view,
ReadView const& check,
FwdRange const& txs,
OrderedTxs& retries,
ApplyFlags flags,
std::map<uint256, bool>& shouldRecover,
beast::Journal j);
enum Result
{
success,
failure,
retry
};
enum Result { success, failure, retry };
std::shared_ptr<OpenView>
create (Rules const& rules,
std::shared_ptr<Ledger const> const& ledger);
create(Rules const& rules, std::shared_ptr<Ledger const> const& ledger);
static
Result
apply_one (Application& app, OpenView& view,
std::shared_ptr< STTx const> const& tx,
bool retry, ApplyFlags flags,
bool shouldRecover, beast::Journal j);
static Result
apply_one(
Application& app,
OpenView& view,
std::shared_ptr<STTx const> const& tx,
bool retry,
ApplyFlags flags,
bool shouldRecover,
beast::Journal j);
};
//------------------------------------------------------------------------------
template <class FwdRange>
void
OpenLedger::apply (Application& app, OpenView& view,
ReadView const& check, FwdRange const& txs,
OrderedTxs& retries, ApplyFlags flags,
std::map<uint256, bool>& shouldRecover,
beast::Journal j)
OpenLedger::apply(
Application& app,
OpenView& view,
ReadView const& check,
FwdRange const& txs,
OrderedTxs& retries,
ApplyFlags flags,
std::map<uint256, bool>& shouldRecover,
beast::Journal j)
{
for (auto iter = txs.begin();
iter != txs.end(); ++iter)
for (auto iter = txs.begin(); iter != txs.end(); ++iter)
{
try
{
@@ -222,51 +228,53 @@ OpenLedger::apply (Application& app, OpenView& view,
auto const txId = tx->getTransactionID();
if (check.txExists(txId))
continue;
auto const result = apply_one(app, view,
tx, true, flags, shouldRecover[txId], j);
auto const result =
apply_one(app, view, tx, true, flags, shouldRecover[txId], j);
if (result == Result::retry)
retries.insert(tx);
}
catch(std::exception const&)
catch (std::exception const&)
{
JLOG(j.error()) <<
"Caught exception";
JLOG(j.error()) << "Caught exception";
}
}
bool retry = true;
for (int pass = 0;
pass < LEDGER_TOTAL_PASSES;
++pass)
for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
{
int changes = 0;
auto iter = retries.begin();
while (iter != retries.end())
{
switch (apply_one(app, view,
iter->second, retry, flags,
shouldRecover[iter->second->getTransactionID()], j))
switch (apply_one(
app,
view,
iter->second,
retry,
flags,
shouldRecover[iter->second->getTransactionID()],
j))
{
case Result::success:
++changes;
[[fallthrough]];
case Result::failure:
iter = retries.erase (iter);
break;
case Result::retry:
++iter;
case Result::success:
++changes;
[[fallthrough]];
case Result::failure:
iter = retries.erase(iter);
break;
case Result::retry:
++iter;
}
}
// A non-retry pass made no changes
if (! changes && ! retry)
if (!changes && !retry)
return;
// Stop retriable passes
if (! changes || (pass >= LEDGER_RETRY_PASSES))
if (!changes || (pass >= LEDGER_RETRY_PASSES))
retry = false;
}
// If there are any transactions left, we must have
// tried them in at least one final pass
assert (retries.empty() || ! retry);
assert(retries.empty() || !retry);
}
//------------------------------------------------------------------------------
@@ -274,17 +282,17 @@ OpenLedger::apply (Application& app, OpenView& view,
// For debug logging
std::string
debugTxstr (std::shared_ptr<STTx const> const& tx);
debugTxstr(std::shared_ptr<STTx const> const& tx);
std::string
debugTostr (OrderedTxs const& set);
debugTostr(OrderedTxs const& set);
std::string
debugTostr (SHAMap const& set);
debugTostr(SHAMap const& set);
std::string
debugTostr (std::shared_ptr<ReadView const> const& view);
debugTostr(std::shared_ptr<ReadView const> const& view);
} // ripple
} // namespace ripple
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#include <ripple/app/ledger/OrderBookDB.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/OrderBookDB.h>
#include <ripple/app/main/Application.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h>
@@ -27,25 +27,26 @@
namespace ripple {
OrderBookDB::OrderBookDB (Application& app, Stoppable& parent)
: Stoppable ("OrderBookDB", parent)
, app_ (app)
, mSeq (0)
, j_ (app.journal ("OrderBookDB"))
OrderBookDB::OrderBookDB(Application& app, Stoppable& parent)
: Stoppable("OrderBookDB", parent)
, app_(app)
, mSeq(0)
, j_(app.journal("OrderBookDB"))
{
}
void OrderBookDB::invalidate ()
void
OrderBookDB::invalidate()
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
mSeq = 0;
}
void OrderBookDB::setup(
std::shared_ptr<ReadView const> const& ledger)
void
OrderBookDB::setup(std::shared_ptr<ReadView const> const& ledger)
{
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
auto seq = ledger->info().seq;
// Do a full update every 256 ledgers
@@ -59,8 +60,7 @@ void OrderBookDB::setup(
return;
}
JLOG (j_.debug())
<< "Advancing from " << mSeq << " to " << seq;
JLOG(j_.debug()) << "Advancing from " << mSeq << " to " << seq;
mSeq = seq;
}
@@ -73,19 +73,20 @@ void OrderBookDB::setup(
update(ledger);
else
app_.getJobQueue().addJob(
jtUPDATE_PF, "OrderBookDB::update",
[this, ledger] (Job&) { update(ledger); });
jtUPDATE_PF, "OrderBookDB::update", [this, ledger](Job&) {
update(ledger);
});
}
void OrderBookDB::update(
std::shared_ptr<ReadView const> const& ledger)
void
OrderBookDB::update(std::shared_ptr<ReadView const> const& ledger)
{
hash_set< uint256 > seen;
hash_set<uint256> seen;
OrderBookDB::IssueToOrderBook destMap;
OrderBookDB::IssueToOrderBook sourceMap;
hash_set< Issue > XRPBooks;
hash_set<Issue> XRPBooks;
JLOG (j_.debug()) << "OrderBookDB::update>";
JLOG(j_.debug()) << "OrderBookDB::update>";
if (app_.config().PATH_SEARCH_MAX == 0)
{
@@ -98,20 +99,20 @@ void OrderBookDB::update(
try
{
for(auto& sle : ledger->sles)
for (auto& sle : ledger->sles)
{
if (isStopping())
{
JLOG (j_.info())
JLOG(j_.info())
<< "OrderBookDB::update exiting due to isStopping";
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
mSeq = 0;
return;
}
if (sle->getType () == ltDIR_NODE &&
sle->isFieldPresent (sfExchangeRate) &&
sle->getFieldH256 (sfRootIndex) == sle->key())
if (sle->getType() == ltDIR_NODE &&
sle->isFieldPresent(sfExchangeRate) &&
sle->getFieldH256(sfRootIndex) == sle->key())
{
Book book;
book.in.currency = sle->getFieldH160(sfTakerPaysCurrency);
@@ -119,12 +120,12 @@ void OrderBookDB::update(
book.out.account = sle->getFieldH160(sfTakerGetsIssuer);
book.out.currency = sle->getFieldH160(sfTakerGetsCurrency);
uint256 index = getBookBase (book);
if (seen.insert (index).second)
uint256 index = getBookBase(book);
if (seen.insert(index).second)
{
auto orderBook = std::make_shared<OrderBook> (index, book);
sourceMap[book.in].push_back (orderBook);
destMap[book.out].push_back (orderBook);
auto orderBook = std::make_shared<OrderBook>(index, book);
sourceMap[book.in].push_back(orderBook);
destMap[book.out].push_back(orderBook);
if (isXRP(book.out))
XRPBooks.insert(book.in);
++books;
@@ -134,17 +135,15 @@ void OrderBookDB::update(
}
catch (SHAMapMissingNode const& mn)
{
JLOG (j_.info())
<< "OrderBookDB::update: " << mn.what();
std::lock_guard sl (mLock);
JLOG(j_.info()) << "OrderBookDB::update: " << mn.what();
std::lock_guard sl(mLock);
mSeq = 0;
return;
}
JLOG (j_.debug())
<< "OrderBookDB::update< " << books << " books found";
JLOG(j_.debug()) << "OrderBookDB::update< " << books << " books found";
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
mXRPBooks.swap(XRPBooks);
mSourceMap.swap(sourceMap);
@@ -153,24 +152,25 @@ void OrderBookDB::update(
app_.getLedgerMaster().newOrderBookDB();
}
void OrderBookDB::addOrderBook(Book const& book)
void
OrderBookDB::addOrderBook(Book const& book)
{
bool toXRP = isXRP (book.out);
std::lock_guard sl (mLock);
bool toXRP = isXRP(book.out);
std::lock_guard sl(mLock);
if (toXRP)
{
// We don't want to search through all the to-XRP or from-XRP order
// books!
for (auto ob: mSourceMap[book.in])
for (auto ob : mSourceMap[book.in])
{
if (isXRP (ob->getCurrencyOut ())) // also to XRP
if (isXRP(ob->getCurrencyOut())) // also to XRP
return;
}
}
else
{
for (auto ob: mDestMap[book.out])
for (auto ob : mDestMap[book.out])
{
if (ob->getCurrencyIn() == book.in.currency &&
ob->getIssuerIn() == book.in.account)
@@ -180,57 +180,63 @@ void OrderBookDB::addOrderBook(Book const& book)
}
}
uint256 index = getBookBase(book);
auto orderBook = std::make_shared<OrderBook> (index, book);
auto orderBook = std::make_shared<OrderBook>(index, book);
mSourceMap[book.in].push_back (orderBook);
mDestMap[book.out].push_back (orderBook);
mSourceMap[book.in].push_back(orderBook);
mDestMap[book.out].push_back(orderBook);
if (toXRP)
mXRPBooks.insert(book.in);
}
// return list of all orderbooks that want this issuerID and currencyID
OrderBook::List OrderBookDB::getBooksByTakerPays (Issue const& issue)
OrderBook::List
OrderBookDB::getBooksByTakerPays(Issue const& issue)
{
std::lock_guard sl (mLock);
auto it = mSourceMap.find (issue);
return it == mSourceMap.end () ? OrderBook::List() : it->second;
std::lock_guard sl(mLock);
auto it = mSourceMap.find(issue);
return it == mSourceMap.end() ? OrderBook::List() : it->second;
}
int OrderBookDB::getBookSize(Issue const& issue) {
std::lock_guard sl (mLock);
auto it = mSourceMap.find (issue);
return it == mSourceMap.end () ? 0 : it->second.size();
int
OrderBookDB::getBookSize(Issue const& issue)
{
std::lock_guard sl(mLock);
auto it = mSourceMap.find(issue);
return it == mSourceMap.end() ? 0 : it->second.size();
}
bool OrderBookDB::isBookToXRP(Issue const& issue)
bool
OrderBookDB::isBookToXRP(Issue const& issue)
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
return mXRPBooks.count(issue) > 0;
}
BookListeners::pointer OrderBookDB::makeBookListeners (Book const& book)
BookListeners::pointer
OrderBookDB::makeBookListeners(Book const& book)
{
std::lock_guard sl (mLock);
auto ret = getBookListeners (book);
std::lock_guard sl(mLock);
auto ret = getBookListeners(book);
if (!ret)
{
ret = std::make_shared<BookListeners> ();
ret = std::make_shared<BookListeners>();
mListeners [book] = ret;
assert (getBookListeners (book) == ret);
mListeners[book] = ret;
assert(getBookListeners(book) == ret);
}
return ret;
}
BookListeners::pointer OrderBookDB::getBookListeners (Book const& book)
BookListeners::pointer
OrderBookDB::getBookListeners(Book const& book)
{
BookListeners::pointer ret;
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
auto it0 = mListeners.find (book);
if (it0 != mListeners.end ())
auto it0 = mListeners.find(book);
if (it0 != mListeners.end())
ret = it0->second;
return ret;
@@ -238,12 +244,14 @@ BookListeners::pointer OrderBookDB::getBookListeners (Book const& book)
// Based on the meta, send the meta to the streams that are listening.
// We need to determine which streams a given meta effects.
void OrderBookDB::processTxn (
void
OrderBookDB::processTxn(
std::shared_ptr<ReadView const> const& ledger,
const AcceptedLedgerTx& alTx, Json::Value const& jvObj)
const AcceptedLedgerTx& alTx,
Json::Value const& jvObj)
{
std::lock_guard sl (mLock);
if (alTx.getResult () == tesSUCCESS)
std::lock_guard sl(mLock);
if (alTx.getResult() == tesSUCCESS)
{
// For this particular transaction, maintain the set of unique
// subscriptions that have already published it. This prevents sending
@@ -255,34 +263,34 @@ void OrderBookDB::processTxn (
// Check if this is an offer or an offer cancel or a payment that
// consumes an offer.
// Check to see what the meta looks like.
for (auto& node : alTx.getMeta ()->getNodes ())
for (auto& node : alTx.getMeta()->getNodes())
{
try
{
if (node.getFieldU16 (sfLedgerEntryType) == ltOFFER)
if (node.getFieldU16(sfLedgerEntryType) == ltOFFER)
{
SField const* field = nullptr;
// We need a field that contains the TakerGets and TakerPays
// parameters.
if (node.getFName () == sfModifiedNode)
if (node.getFName() == sfModifiedNode)
field = &sfPreviousFields;
else if (node.getFName () == sfCreatedNode)
else if (node.getFName() == sfCreatedNode)
field = &sfNewFields;
else if (node.getFName () == sfDeletedNode)
else if (node.getFName() == sfDeletedNode)
field = &sfFinalFields;
if (field)
{
auto data = dynamic_cast<const STObject*> (
node.peekAtPField (*field));
auto data = dynamic_cast<const STObject*>(
node.peekAtPField(*field));
if (data &&
data->isFieldPresent (sfTakerPays) &&
data->isFieldPresent (sfTakerGets))
if (data && data->isFieldPresent(sfTakerPays) &&
data->isFieldPresent(sfTakerGets))
{
// determine the OrderBook
Book b{data->getFieldAmount(sfTakerGets).issue(),
Book b{
data->getFieldAmount(sfTakerGets).issue(),
data->getFieldAmount(sfTakerPays).issue()};
auto listeners = getBookListeners(b);
@@ -296,11 +304,11 @@ void OrderBookDB::processTxn (
}
catch (std::exception const&)
{
JLOG (j_.info())
JLOG(j_.info())
<< "Fields not found in OrderBookDB::processTxn";
}
}
}
}
} // ripple
} // namespace ripple

View File

@@ -28,40 +28,51 @@
namespace ripple {
class OrderBookDB
: public Stoppable
class OrderBookDB : public Stoppable
{
public:
OrderBookDB (Application& app, Stoppable& parent);
OrderBookDB(Application& app, Stoppable& parent);
void setup (std::shared_ptr<ReadView const> const& ledger);
void update (std::shared_ptr<ReadView const> const& ledger);
void invalidate ();
void
setup(std::shared_ptr<ReadView const> const& ledger);
void
update(std::shared_ptr<ReadView const> const& ledger);
void
invalidate();
void addOrderBook(Book const&);
void
addOrderBook(Book const&);
/** @return a list of all orderbooks that want this issuerID and currencyID.
*/
OrderBook::List getBooksByTakerPays (Issue const&);
OrderBook::List
getBooksByTakerPays(Issue const&);
/** @return a count of all orderbooks that want this issuerID and
currencyID. */
int getBookSize(Issue const&);
int
getBookSize(Issue const&);
bool isBookToXRP (Issue const&);
bool
isBookToXRP(Issue const&);
BookListeners::pointer getBookListeners (Book const&);
BookListeners::pointer makeBookListeners (Book const&);
BookListeners::pointer
getBookListeners(Book const&);
BookListeners::pointer
makeBookListeners(Book const&);
// see if this txn effects any orderbook
void processTxn (
void
processTxn(
std::shared_ptr<ReadView const> const& ledger,
const AcceptedLedgerTx& alTx, Json::Value const& jvObj);
const AcceptedLedgerTx& alTx,
Json::Value const& jvObj);
using IssueToOrderBook = hash_map <Issue, OrderBook::List>;
using IssueToOrderBook = hash_map<Issue, OrderBook::List>;
private:
void rawAddBook(Book const&);
void
rawAddBook(Book const&);
Application& app_;
@@ -72,11 +83,11 @@ private:
IssueToOrderBook mDestMap;
// does an order book to XRP exist
hash_set <Issue> mXRPBooks;
hash_set<Issue> mXRPBooks;
std::recursive_mutex mLock;
using BookToListenersMap = hash_map <Book, BookListeners::pointer>;
using BookToListenersMap = hash_map<Book, BookListeners::pointer>;
BookToListenersMap mListeners;
@@ -85,6 +96,6 @@ private:
beast::Journal const j_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -21,9 +21,9 @@
#define RIPPLE_APP_PENDINGSAVES_H_INCLUDED
#include <ripple/protocol/Protocol.h>
#include <condition_variable>
#include <map>
#include <mutex>
#include <condition_variable>
namespace ripple {
@@ -37,11 +37,10 @@ class PendingSaves
{
private:
std::mutex mutable mutex_;
std::map <LedgerIndex, bool> map_;
std::map<LedgerIndex, bool> map_;
std::condition_variable await_;
public:
/** Start working on a ledger
This is called prior to updating the SQLite indexes.
@@ -49,11 +48,11 @@ public:
@return 'true' if work should be done
*/
bool
startWork (LedgerIndex seq)
startWork(LedgerIndex seq)
{
std::lock_guard lock(mutex_);
auto it = map_.find (seq);
auto it = map_.find(seq);
if ((it == map_.end()) || it->second)
{
@@ -72,17 +71,17 @@ public:
threads awaiting completion are notified.
*/
void
finishWork (LedgerIndex seq)
finishWork(LedgerIndex seq)
{
std::lock_guard lock(mutex_);
map_.erase (seq);
map_.erase(seq);
await_.notify_all();
}
/** Return `true` if a ledger is in the progress of being saved. */
bool
pending (LedgerIndex seq)
pending(LedgerIndex seq)
{
std::lock_guard lock(mutex_);
return map_.find(seq) != map_.end();
@@ -97,12 +96,12 @@ public:
@return 'true' if work should be done or dispatched
*/
bool
shouldWork (LedgerIndex seq, bool isSynchronous)
shouldWork(LedgerIndex seq, bool isSynchronous)
{
std::unique_lock <std::mutex> lock(mutex_);
std::unique_lock<std::mutex> lock(mutex_);
do
{
auto it = map_.find (seq);
auto it = map_.find(seq);
if (it == map_.end())
{
@@ -110,20 +109,20 @@ public:
return true;
}
if (! isSynchronous)
if (!isSynchronous)
{
// Already dispatched
return false;
}
if (! it->second)
if (!it->second)
{
// Scheduled, but not dispatched
return true;
}
// Already in progress, just need to wait
await_.wait (lock);
await_.wait(lock);
} while (true);
}
@@ -134,16 +133,15 @@ public:
that is in progress or dispatched. The boolean indicates
whether work is currently in progress.
*/
std::map <LedgerIndex, bool>
getSnapshot () const
std::map<LedgerIndex, bool>
getSnapshot() const
{
std::lock_guard lock(mutex_);
return map_;
}
};
}
} // namespace ripple
#endif

View File

@@ -20,11 +20,11 @@
#ifndef RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED
#define RIPPLE_APP_LEDGER_TRANSACTIONMASTER_H_INCLUDED
#include <ripple/app/misc/Transaction.h>
#include <ripple/basics/RangeSet.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/shamap/SHAMapItem.h>
#include <ripple/shamap/SHAMapTreeNode.h>
#include <ripple/basics/RangeSet.h>
#include <ripple/app/misc/Transaction.h>
namespace ripple {
@@ -36,15 +36,16 @@ class STTx;
class TransactionMaster
{
public:
TransactionMaster (Application& app);
TransactionMaster (TransactionMaster const&) = delete;
TransactionMaster& operator= (TransactionMaster const&) = delete;
TransactionMaster(Application& app);
TransactionMaster(TransactionMaster const&) = delete;
TransactionMaster&
operator=(TransactionMaster const&) = delete;
std::shared_ptr<Transaction>
fetch_from_cache (uint256 const&);
fetch_from_cache(uint256 const&);
std::shared_ptr<Transaction>
fetch (uint256 const& , error_code_i& ec);
fetch(uint256 const&, error_code_i& ec);
/**
* Fetch transaction from the cache or database.
@@ -56,27 +57,35 @@ public:
* while the search was conducted.
*/
boost::variant<Transaction::pointer, bool>
fetch (uint256 const& , ClosedInterval<uint32_t> const& range, error_code_i& ec);
fetch(
uint256 const&,
ClosedInterval<uint32_t> const& range,
error_code_i& ec);
std::shared_ptr<STTx const>
fetch (std::shared_ptr<SHAMapItem> const& item,
SHAMapTreeNode::TNType type, std::uint32_t uCommitLedger);
fetch(
std::shared_ptr<SHAMapItem> const& item,
SHAMapTreeNode::TNType type,
std::uint32_t uCommitLedger);
// return value: true = we had the transaction already
bool inLedger (uint256 const& hash, std::uint32_t ledger);
bool
inLedger(uint256 const& hash, std::uint32_t ledger);
void canonicalize (std::shared_ptr<Transaction>* pTransaction);
void
canonicalize(std::shared_ptr<Transaction>* pTransaction);
void sweep (void);
void
sweep(void);
TaggedCache <uint256, Transaction>&
TaggedCache<uint256, Transaction>&
getCache();
private:
Application& mApp;
TaggedCache <uint256, Transaction> mCache;
TaggedCache<uint256, Transaction> mCache;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -22,13 +22,20 @@
namespace ripple {
void
TransactionStateSF::gotNode(bool, SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq, Blob&& nodeData, SHAMapTreeNode::TNType type) const
TransactionStateSF::gotNode(
bool,
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const
{
assert(type != SHAMapTreeNode::tnTRANSACTION_NM);
db_.store(hotTRANSACTION_NODE, std::move(nodeData),
nodeHash.as_uint256(), ledgerSeq);
db_.store(
hotTRANSACTION_NODE,
std::move(nodeData),
nodeHash.as_uint256(),
ledgerSeq);
}
boost::optional<Blob>
@@ -37,4 +44,4 @@ TransactionStateSF::getNode(SHAMapHash const& nodeHash) const
return fp_.getFetchPack(nodeHash.as_uint256());
}
} // ripple
} // namespace ripple

View File

@@ -32,14 +32,17 @@ class TransactionStateSF : public SHAMapSyncFilter
{
public:
TransactionStateSF(NodeStore::Database& db, AbstractFetchPackContainer& fp)
: db_(db)
, fp_(fp)
{}
: db_(db), fp_(fp)
{
}
void
gotNode(bool fromFilter, SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq, Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
gotNode(
bool fromFilter,
SHAMapHash const& nodeHash,
std::uint32_t ledgerSeq,
Blob&& nodeData,
SHAMapTreeNode::TNType type) const override;
boost::optional<Blob>
getNode(SHAMapHash const& nodeHash) const override;
@@ -49,6 +52,6 @@ private:
AbstractFetchPackContainer& fp_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -62,10 +62,10 @@ buildLedgerImpl(
// Write the final version of all modified SHAMap
// nodes to the node store to preserve the new LCL
int const asf = built->stateMap().flushDirty(
hotACCOUNT_NODE, built->info().seq);
int const tmf = built->txMap().flushDirty(
hotTRANSACTION_NODE, built->info().seq);
int const asf =
built->stateMap().flushDirty(hotACCOUNT_NODE, built->info().seq);
int const tmf =
built->txMap().flushDirty(hotTRANSACTION_NODE, built->info().seq);
JLOG(j.debug()) << "Flushed " << asf << " accounts and " << tmf
<< " transaction nodes";
}
@@ -103,9 +103,8 @@ applyTransactions(
// Attempt to apply all of the retriable transactions
for (int pass = 0; pass < LEDGER_TOTAL_PASSES; ++pass)
{
JLOG(j.debug())
<< (certainRetry ? "Pass: " : "Final pass: ") << pass
<< " begins (" << txns.size() << " transactions)";
JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
<< " begins (" << txns.size() << " transactions)";
int changes = 0;
auto it = txns.begin();
@@ -147,9 +146,8 @@ applyTransactions(
}
}
JLOG(j.debug())
<< (certainRetry ? "Pass: " : "Final pass: ") << pass
<< " completed (" << changes << " changes)";
JLOG(j.debug()) << (certainRetry ? "Pass: " : "Final pass: ") << pass
<< " completed (" << changes << " changes)";
// Accumulate changes.
count += changes;
@@ -181,30 +179,30 @@ buildLedger(
std::set<TxID>& failedTxns,
beast::Journal j)
{
JLOG(j.debug()) << "Report: Transaction Set = " << txns.key()
<< ", close " << closeTime.time_since_epoch().count()
JLOG(j.debug()) << "Report: Transaction Set = " << txns.key() << ", close "
<< closeTime.time_since_epoch().count()
<< (closeTimeCorrect ? "" : " (incorrect)");
return buildLedgerImpl(parent, closeTime, closeTimeCorrect,
closeResolution, app, j,
[&](OpenView& accum, std::shared_ptr<Ledger> const& built)
{
return buildLedgerImpl(
parent,
closeTime,
closeTimeCorrect,
closeResolution,
app,
j,
[&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
JLOG(j.debug())
<< "Attempting to apply " << txns.size()
<< " transactions";
<< "Attempting to apply " << txns.size() << " transactions";
auto const applied = applyTransactions(app, built, txns,
failedTxns, accum, j);
auto const applied =
applyTransactions(app, built, txns, failedTxns, accum, j);
if (!txns.empty() || !failedTxns.empty())
JLOG(j.debug())
<< "Applied " << applied << " transactions; "
<< failedTxns.size() << " failed and "
<< txns.size() << " will be retried.";
JLOG(j.debug()) << "Applied " << applied << " transactions; "
<< failedTxns.size() << " failed and "
<< txns.size() << " will be retried.";
else
JLOG(j.debug())
<< "Applied " << applied
<< " transactions.";
JLOG(j.debug()) << "Applied " << applied << " transactions.";
});
}
@@ -227,8 +225,7 @@ buildLedger(
replayLedger->info().closeTimeResolution,
app,
j,
[&](OpenView& accum, std::shared_ptr<Ledger> const& built)
{
[&](OpenView& accum, std::shared_ptr<Ledger> const& built) {
for (auto& tx : replayData.orderedTxns())
applyTransaction(app, accum, *tx.second, false, applyFlags, j);
});

File diff suppressed because it is too large Load Diff

View File

@@ -23,19 +23,17 @@
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/basics/DecayingSample.h>
#include <ripple/basics/Log.h>
#include <ripple/beast/container/aged_map.h>
#include <ripple/beast/core/LexicalCast.h>
#include <ripple/core/JobQueue.h>
#include <ripple/nodestore/DatabaseShard.h>
#include <ripple/protocol/jss.h>
#include <ripple/beast/core/LexicalCast.h>
#include <ripple/beast/container/aged_map.h>
#include <memory>
#include <mutex>
namespace ripple {
class InboundLedgersImp
: public InboundLedgers
, public Stoppable
class InboundLedgersImp : public InboundLedgers, public Stoppable
{
private:
Application& app_;
@@ -45,32 +43,36 @@ private:
beast::Journal const j_;
public:
using u256_acq_pair = std::pair<
uint256,
std::shared_ptr <InboundLedger>>;
using u256_acq_pair = std::pair<uint256, std::shared_ptr<InboundLedger>>;
// How long before we try again to acquire the same ledger
static const std::chrono::minutes kReacquireInterval;
InboundLedgersImp (Application& app, clock_type& clock, Stoppable& parent,
beast::insight::Collector::ptr const& collector)
: Stoppable ("InboundLedgers", parent)
, app_ (app)
InboundLedgersImp(
Application& app,
clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector)
: Stoppable("InboundLedgers", parent)
, app_(app)
, fetchRate_(clock.now())
, j_ (app.journal ("InboundLedger"))
, m_clock (clock)
, mRecentFailures (clock)
, j_(app.journal("InboundLedger"))
, m_clock(clock)
, mRecentFailures(clock)
, mCounter(collector->make_counter("ledger_fetches"))
{
}
/** @callgraph */
std::shared_ptr<Ledger const>
acquire(uint256 const& hash, std::uint32_t seq,
acquire(
uint256 const& hash,
std::uint32_t seq,
InboundLedger::Reason reason) override
{
assert(hash.isNonZero());
assert(reason != InboundLedger::Reason::SHARD ||
assert(
reason != InboundLedger::Reason::SHARD ||
(seq != 0 && app_.getShardStore()));
if (isStopping())
return {};
@@ -87,7 +89,7 @@ public:
}
else
{
inbound = std::make_shared <InboundLedger>(
inbound = std::make_shared<InboundLedger>(
app_, hash, seq, reason, std::ref(m_clock));
mLedgers.emplace(hash, inbound);
inbound->init(sl);
@@ -98,10 +100,10 @@ public:
if (inbound->isFailed())
return {};
if (! isNew)
if (!isNew)
inbound->update(seq);
if (! inbound->isComplete())
if (!inbound->isComplete())
return {};
if (reason == InboundLedger::Reason::HISTORY)
@@ -114,8 +116,8 @@ public:
auto shardStore = app_.getShardStore();
if (!shardStore)
{
JLOG(j_.error()) <<
"Acquiring shard with no shard store available";
JLOG(j_.error())
<< "Acquiring shard with no shard store available";
return {};
}
if (inbound->getLedger()->stateMap().family().isShardBacked())
@@ -126,17 +128,18 @@ public:
return inbound->getLedger();
}
std::shared_ptr<InboundLedger> find (uint256 const& hash) override
std::shared_ptr<InboundLedger>
find(uint256 const& hash) override
{
assert (hash.isNonZero ());
assert(hash.isNonZero());
std::shared_ptr<InboundLedger> ret;
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
auto it = mLedgers.find (hash);
if (it != mLedgers.end ())
auto it = mLedgers.find(hash);
if (it != mLedgers.end())
{
ret = it->second;
}
@@ -158,31 +161,32 @@ public:
// VFALCO TODO Remove the dependency on the Peer object.
/** We received a TMLedgerData from a peer.
*/
bool gotLedgerData (LedgerHash const& hash,
std::shared_ptr<Peer> peer,
std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
*/
bool
gotLedgerData(
LedgerHash const& hash,
std::shared_ptr<Peer> peer,
std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
{
protocol::TMLedgerData& packet = *packet_ptr;
JLOG (j_.trace())
<< "Got data (" << packet.nodes ().size ()
<< ") for acquiring ledger: " << hash;
JLOG(j_.trace()) << "Got data (" << packet.nodes().size()
<< ") for acquiring ledger: " << hash;
auto ledger = find (hash);
auto ledger = find(hash);
if (!ledger)
{
JLOG (j_.trace())
<< "Got data for ledger we're no longer acquiring";
JLOG(j_.trace()) << "Got data for ledger we're no longer acquiring";
// If it's state node data, stash it because it still might be
// useful.
if (packet.type () == protocol::liAS_NODE)
if (packet.type() == protocol::liAS_NODE)
{
app_.getJobQueue().addJob(
jtLEDGER_DATA, "gotStaleData",
[this, packet_ptr] (Job&) { gotStaleData(packet_ptr); });
jtLEDGER_DATA, "gotStaleData", [this, packet_ptr](Job&) {
gotStaleData(packet_ptr);
});
}
return false;
@@ -190,14 +194,16 @@ public:
// Stash the data for later processing and see if we need to dispatch
if (ledger->gotData(std::weak_ptr<Peer>(peer), packet_ptr))
app_.getJobQueue().addJob (
jtLEDGER_DATA, "processLedgerData",
[this, hash] (Job&) { doLedgerData(hash); });
app_.getJobQueue().addJob(
jtLEDGER_DATA, "processLedgerData", [this, hash](Job&) {
doLedgerData(hash);
});
return true;
}
int getFetchCount (int& timeoutCount) override
int
getFetchCount(int& timeoutCount) override
{
timeoutCount = 0;
int ret = 0;
@@ -205,7 +211,7 @@ public:
std::vector<u256_acq_pair> inboundLedgers;
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
inboundLedgers.reserve(mLedgers.size());
for (auto const& it : mLedgers)
@@ -216,34 +222,37 @@ public:
for (auto const& it : inboundLedgers)
{
if (it.second->isActive ())
if (it.second->isActive())
{
++ret;
timeoutCount += it.second->getTimeouts ();
timeoutCount += it.second->getTimeouts();
}
}
return ret;
}
void logFailure (uint256 const& h, std::uint32_t seq) override
void
logFailure(uint256 const& h, std::uint32_t seq) override
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
mRecentFailures.emplace(h, seq);
}
bool isFailure (uint256 const& h) override
bool
isFailure(uint256 const& h) override
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
beast::expire (mRecentFailures, kReacquireInterval);
return mRecentFailures.find (h) != mRecentFailures.end();
beast::expire(mRecentFailures, kReacquireInterval);
return mRecentFailures.find(h) != mRecentFailures.end();
}
void doLedgerData (LedgerHash hash) override
void
doLedgerData(LedgerHash hash) override
{
if (auto ledger = find (hash))
ledger->runData ();
if (auto ledger = find(hash))
ledger->runData();
}
/** We got some data for a ledger we are no longer acquiring Since we paid
@@ -252,23 +261,28 @@ public:
Nodes are received in wire format and must be stashed/hashed in prefix
format
*/
void gotStaleData (std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
void
gotStaleData(std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
{
const uint256 uZero;
Serializer s;
try
{
for (int i = 0; i < packet_ptr->nodes ().size (); ++i)
for (int i = 0; i < packet_ptr->nodes().size(); ++i)
{
auto const& node = packet_ptr->nodes (i);
auto const& node = packet_ptr->nodes(i);
if (!node.has_nodeid () || !node.has_nodedata ())
if (!node.has_nodeid() || !node.has_nodedata())
return;
auto id_string = node.nodeid();
auto newNode = SHAMapAbstractNode::make(
makeSlice(node.nodedata()),
0, snfWIRE, SHAMapHash{uZero}, false, app_.journal ("SHAMapNodeID"),
0,
snfWIRE,
SHAMapHash{uZero},
false,
app_.journal("SHAMapNodeID"),
SHAMapNodeID(id_string.data(), id_string.size()));
if (!newNode)
@@ -277,7 +291,7 @@ public:
s.erase();
newNode->addRaw(s, snfPREFIX);
auto blob = std::make_shared<Blob> (s.begin(), s.end());
auto blob = std::make_shared<Blob>(s.begin(), s.end());
app_.getLedgerMaster().addFetchPack(
newNode->getNodeHash().as_uint256(), blob);
@@ -288,50 +302,53 @@ public:
}
}
void clearFailures () override
void
clearFailures() override
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
mRecentFailures.clear();
mLedgers.clear();
}
std::size_t fetchRate() override
std::size_t
fetchRate() override
{
std::lock_guard lock(fetchRateMutex_);
return 60 * fetchRate_.value(
m_clock.now());
return 60 * fetchRate_.value(m_clock.now());
}
// Should only be called with an inboundledger that has
// a reason of history or shard
void onLedgerFetched() override
void
onLedgerFetched() override
{
std::lock_guard lock(fetchRateMutex_);
fetchRate_.add(1, m_clock.now());
}
Json::Value getInfo() override
Json::Value
getInfo() override
{
Json::Value ret(Json::objectValue);
std::vector<u256_acq_pair> acquires;
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
acquires.reserve (mLedgers.size ());
acquires.reserve(mLedgers.size());
for (auto const& it : mLedgers)
{
assert (it.second);
acquires.push_back (it);
assert(it.second);
acquires.push_back(it);
}
for (auto const& it : mRecentFailures)
{
if (it.second > 1)
ret[beast::lexicalCastThrow <std::string>(
it.second)][jss::failed] = true;
ret[beast::lexicalCastThrow<std::string>(it.second)]
[jss::failed] = true;
else
ret[to_string (it.first)][jss::failed] = true;
ret[to_string(it.first)][jss::failed] = true;
}
}
@@ -342,59 +359,62 @@ public:
if (seq > 1)
ret[std::to_string(seq)] = it.second->getJson(0);
else
ret[to_string (it.first)] = it.second->getJson(0);
ret[to_string(it.first)] = it.second->getJson(0);
}
return ret;
}
void gotFetchPack () override
void
gotFetchPack() override
{
std::vector<std::shared_ptr<InboundLedger>> acquires;
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
acquires.reserve (mLedgers.size ());
acquires.reserve(mLedgers.size());
for (auto const& it : mLedgers)
{
assert (it.second);
acquires.push_back (it.second);
assert(it.second);
acquires.push_back(it.second);
}
}
for (auto const& acquire : acquires)
{
acquire->checkLocal ();
acquire->checkLocal();
}
}
void sweep () override
void
sweep() override
{
clock_type::time_point const now (m_clock.now());
clock_type::time_point const now(m_clock.now());
// Make a list of things to sweep, while holding the lock
std::vector <MapType::mapped_type> stuffToSweep;
std::vector<MapType::mapped_type> stuffToSweep;
std::size_t total;
{
ScopedLockType sl (mLock);
MapType::iterator it (mLedgers.begin ());
total = mLedgers.size ();
stuffToSweep.reserve (total);
ScopedLockType sl(mLock);
MapType::iterator it(mLedgers.begin());
total = mLedgers.size();
stuffToSweep.reserve(total);
while (it != mLedgers.end ())
while (it != mLedgers.end())
{
if (it->second->getLastAction () > now)
if (it->second->getLastAction() > now)
{
it->second->touch ();
it->second->touch();
++it;
}
else if ((it->second->getLastAction () +
std::chrono::minutes (1)) < now)
else if (
(it->second->getLastAction() + std::chrono::minutes(1)) <
now)
{
stuffToSweep.push_back (it->second);
stuffToSweep.push_back(it->second);
// shouldn't cause the actual final delete
// since we are holding a reference in the vector.
it = mLedgers.erase (it);
it = mLedgers.erase(it);
}
else
{
@@ -402,18 +422,17 @@ public:
}
}
beast::expire (mRecentFailures, kReacquireInterval);
beast::expire(mRecentFailures, kReacquireInterval);
}
JLOG (j_.debug()) <<
"Swept " << stuffToSweep.size () <<
" out of " << total << " inbound ledgers.";
JLOG(j_.debug()) << "Swept " << stuffToSweep.size() << " out of "
<< total << " inbound ledgers.";
}
void onStop () override
void
onStop() override
{
ScopedLockType lock (mLock);
ScopedLockType lock(mLock);
mLedgers.clear();
mRecentFailures.clear();
@@ -424,13 +443,13 @@ public:
private:
clock_type& m_clock;
using ScopedLockType = std::unique_lock <std::recursive_mutex>;
using ScopedLockType = std::unique_lock<std::recursive_mutex>;
std::recursive_mutex mLock;
using MapType = hash_map <uint256, std::shared_ptr<InboundLedger>>;
using MapType = hash_map<uint256, std::shared_ptr<InboundLedger>>;
MapType mLedgers;
beast::aged_map <uint256, std::uint32_t> mRecentFailures;
beast::aged_map<uint256, std::uint32_t> mRecentFailures;
beast::insight::Counter mCounter;
};
@@ -438,16 +457,18 @@ private:
//------------------------------------------------------------------------------
decltype(InboundLedgersImp::kReacquireInterval)
InboundLedgersImp::kReacquireInterval{5};
InboundLedgersImp::kReacquireInterval{5};
InboundLedgers::~InboundLedgers() = default;
std::unique_ptr<InboundLedgers>
make_InboundLedgers (Application& app,
InboundLedgers::clock_type& clock, Stoppable& parent,
make_InboundLedgers(
Application& app,
InboundLedgers::clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector)
{
return std::make_unique<InboundLedgersImp> (app, clock, parent, collector);
return std::make_unique<InboundLedgersImp>(app, clock, parent, collector);
}
} // ripple
} // namespace ripple

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#include <ripple/app/ledger/InboundTransactions.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/InboundTransactions.h>
#include <ripple/app/ledger/impl/TransactionAcquire.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h>
@@ -31,8 +31,7 @@
namespace ripple {
enum
{
enum {
// Ideal number of peers to start with
startPeers = 2,
@@ -42,152 +41,155 @@ enum
class InboundTransactionSet
{
// A transaction set we generated, acquired, or are acquiring
// A transaction set we generated, acquired, or are acquiring
public:
std::uint32_t mSeq;
std::uint32_t mSeq;
TransactionAcquire::pointer mAcquire;
std::shared_ptr <SHAMap> mSet;
std::shared_ptr<SHAMap> mSet;
InboundTransactionSet (
std::uint32_t seq,
std::shared_ptr <SHAMap> const& set) :
mSeq (seq), mSet (set)
{ ; }
InboundTransactionSet () : mSeq (0)
{ ; }
InboundTransactionSet(std::uint32_t seq, std::shared_ptr<SHAMap> const& set)
: mSeq(seq), mSet(set)
{
;
}
InboundTransactionSet() : mSeq(0)
{
;
}
};
class InboundTransactionsImp
: public InboundTransactions
, public Stoppable
class InboundTransactionsImp : public InboundTransactions, public Stoppable
{
public:
Application& app_;
InboundTransactionsImp (
Application& app,
clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector,
std::function <void (std::shared_ptr <SHAMap> const&,
bool)> gotSet)
: Stoppable ("InboundTransactions", parent)
, app_ (app)
, m_clock (clock)
, m_seq (0)
, m_zeroSet (m_map[uint256()])
, m_gotSet (std::move (gotSet))
InboundTransactionsImp(
Application& app,
clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector,
std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
: Stoppable("InboundTransactions", parent)
, app_(app)
, m_clock(clock)
, m_seq(0)
, m_zeroSet(m_map[uint256()])
, m_gotSet(std::move(gotSet))
{
m_zeroSet.mSet = std::make_shared<SHAMap> (
SHAMapType::TRANSACTION, uint256(),
app_.family());
m_zeroSet.mSet = std::make_shared<SHAMap>(
SHAMapType::TRANSACTION, uint256(), app_.family());
m_zeroSet.mSet->setUnbacked();
}
TransactionAcquire::pointer getAcquire (uint256 const& hash)
TransactionAcquire::pointer
getAcquire(uint256 const& hash)
{
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
auto it = m_map.find (hash);
auto it = m_map.find(hash);
if (it != m_map.end ())
if (it != m_map.end())
return it->second.mAcquire;
}
return {};
}
std::shared_ptr <SHAMap> getSet (
uint256 const& hash,
bool acquire) override
std::shared_ptr<SHAMap>
getSet(uint256 const& hash, bool acquire) override
{
TransactionAcquire::pointer ta;
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
auto it = m_map.find (hash);
auto it = m_map.find(hash);
if (it != m_map.end ())
if (it != m_map.end())
{
if (acquire)
{
it->second.mSeq = m_seq;
if (it->second.mAcquire)
{
it->second.mAcquire->stillNeed ();
it->second.mAcquire->stillNeed();
}
}
return it->second.mSet;
}
if (!acquire || isStopping ())
return std::shared_ptr <SHAMap> ();
if (!acquire || isStopping())
return std::shared_ptr<SHAMap>();
ta = std::make_shared <TransactionAcquire> (app_, hash, m_clock);
ta = std::make_shared<TransactionAcquire>(app_, hash, m_clock);
auto &obj = m_map[hash];
auto& obj = m_map[hash];
obj.mAcquire = ta;
obj.mSeq = m_seq;
}
ta->init (startPeers);
ta->init(startPeers);
return {};
}
/** We received a TMLedgerData from a peer.
*/
void gotData (LedgerHash const& hash,
std::shared_ptr<Peer> peer,
std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
*/
void
gotData(
LedgerHash const& hash,
std::shared_ptr<Peer> peer,
std::shared_ptr<protocol::TMLedgerData> packet_ptr) override
{
protocol::TMLedgerData& packet = *packet_ptr;
JLOG (app_.journal("InboundLedger").trace()) <<
"Got data (" << packet.nodes ().size () << ") "
"for acquiring ledger: " << hash;
JLOG(app_.journal("InboundLedger").trace())
<< "Got data (" << packet.nodes().size()
<< ") "
"for acquiring ledger: "
<< hash;
TransactionAcquire::pointer ta = getAcquire (hash);
TransactionAcquire::pointer ta = getAcquire(hash);
if (ta == nullptr)
{
peer->charge (Resource::feeUnwantedData);
peer->charge(Resource::feeUnwantedData);
return;
}
std::list<SHAMapNodeID> nodeIDs;
std::list< Blob > nodeData;
for (auto const &node : packet.nodes())
std::list<Blob> nodeData;
for (auto const& node : packet.nodes())
{
if (!node.has_nodeid () || !node.has_nodedata () || (
node.nodeid ().size () != 33))
if (!node.has_nodeid() || !node.has_nodedata() ||
(node.nodeid().size() != 33))
{
peer->charge (Resource::feeInvalidRequest);
peer->charge(Resource::feeInvalidRequest);
return;
}
nodeIDs.emplace_back (node.nodeid ().data (),
static_cast<int>(node.nodeid ().size ()));
nodeData.emplace_back (node.nodedata ().begin (),
node.nodedata ().end ());
nodeIDs.emplace_back(
node.nodeid().data(), static_cast<int>(node.nodeid().size()));
nodeData.emplace_back(
node.nodedata().begin(), node.nodedata().end());
}
if (! ta->takeNodes (nodeIDs, nodeData, peer).isUseful ())
peer->charge (Resource::feeUnwantedData);
if (!ta->takeNodes(nodeIDs, nodeData, peer).isUseful())
peer->charge(Resource::feeUnwantedData);
}
void giveSet (uint256 const& hash,
std::shared_ptr <SHAMap> const& set,
void
giveSet(
uint256 const& hash,
std::shared_ptr<SHAMap> const& set,
bool fromAcquire) override
{
bool isNew = true;
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
auto& inboundSet = m_map [hash];
auto& inboundSet = m_map[hash];
if (inboundSet.mSeq < m_seq)
inboundSet.mSeq = m_seq;
@@ -197,28 +199,28 @@ public:
else
inboundSet.mSet = set;
inboundSet.mAcquire.reset ();
inboundSet.mAcquire.reset();
}
if (isNew)
m_gotSet (set, fromAcquire);
m_gotSet(set, fromAcquire);
}
Json::Value getInfo() override
Json::Value
getInfo() override
{
Json::Value ret (Json::objectValue);
Json::Value ret(Json::objectValue);
Json::Value& sets = (ret["sets"] = Json::arrayValue);
{
std::lock_guard sl (mLock);
std::lock_guard sl(mLock);
ret["seq"] = m_seq;
for (auto const& it : m_map)
{
Json::Value& set = sets [to_string (it.first)];
Json::Value& set = sets[to_string(it.first)];
set["seq"] = it.second.mSeq;
if (it.second.mSet)
set["state"] = "complete";
@@ -227,45 +229,45 @@ public:
else
set["state"] = "dead";
}
}
return ret;
}
void newRound (std::uint32_t seq) override
void
newRound(std::uint32_t seq) override
{
std::lock_guard lock (mLock);
std::lock_guard lock(mLock);
// Protect zero set from expiration
m_zeroSet.mSeq = seq;
if (m_seq != seq)
{
m_seq = seq;
auto it = m_map.begin ();
auto it = m_map.begin();
std::uint32_t const minSeq =
(seq < setKeepRounds) ? 0 : (seq - setKeepRounds);
std::uint32_t maxSeq = seq + setKeepRounds;
while (it != m_map.end ())
while (it != m_map.end())
{
if (it->second.mSeq < minSeq || it->second.mSeq > maxSeq)
it = m_map.erase (it);
it = m_map.erase(it);
else
++it;
}
}
}
void onStop () override
void
onStop() override
{
std::lock_guard lock (mLock);
std::lock_guard lock(mLock);
m_map.clear ();
m_map.clear();
stopped();
}
@@ -273,7 +275,7 @@ public:
private:
clock_type& m_clock;
using MapType = hash_map <uint256, InboundTransactionSet>;
using MapType = hash_map<uint256, InboundTransactionSet>;
std::recursive_mutex mLock;
@@ -283,24 +285,23 @@ private:
// The empty transaction set whose hash is zero
InboundTransactionSet& m_zeroSet;
std::function <void (std::shared_ptr <SHAMap> const&, bool)> m_gotSet;
std::function<void(std::shared_ptr<SHAMap> const&, bool)> m_gotSet;
};
//------------------------------------------------------------------------------
InboundTransactions::~InboundTransactions() = default;
std::unique_ptr <InboundTransactions>
make_InboundTransactions (
std::unique_ptr<InboundTransactions>
make_InboundTransactions(
Application& app,
InboundLedgers::clock_type& clock,
Stoppable& parent,
beast::insight::Collector::ptr const& collector,
std::function <void (std::shared_ptr <SHAMap> const&,
bool)> gotSet)
std::function<void(std::shared_ptr<SHAMap> const&, bool)> gotSet)
{
return std::make_unique <InboundTransactionsImp>
(app, clock, parent, collector, std::move (gotSet));
return std::make_unique<InboundTransactionsImp>(
app, clock, parent, collector, std::move(gotSet));
}
} // ripple
} // namespace ripple

View File

@@ -17,12 +17,12 @@
*/
//==============================================================================
#include <ripple/app/ledger/LedgerCleaner.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/LedgerCleaner.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/protocol/jss.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/protocol/jss.h>
namespace ripple {
namespace detail {
@@ -51,19 +51,15 @@ class LedgerCleanerImp : public LedgerCleaner
std::thread thread_;
enum class State : char {
readyToClean = 0,
startCleaning,
cleaning
};
enum class State : char { readyToClean = 0, startCleaning, cleaning };
State state_ = State::readyToClean;
bool shouldExit_ = false;
// The lowest ledger in the range we're checking.
LedgerIndex minRange_ = 0;
LedgerIndex minRange_ = 0;
// The highest ledger in the range we're checking
LedgerIndex maxRange_ = 0;
LedgerIndex maxRange_ = 0;
// Check all state/transaction nodes
bool checkNodes_ = false;
@@ -76,20 +72,18 @@ class LedgerCleanerImp : public LedgerCleaner
//--------------------------------------------------------------------------
public:
LedgerCleanerImp (
LedgerCleanerImp(
Application& app,
Stoppable& stoppable,
beast::Journal journal)
: LedgerCleaner (stoppable)
, app_ (app)
, j_ (journal)
: LedgerCleaner(stoppable), app_(app), j_(journal)
{
}
~LedgerCleanerImp () override
~LedgerCleanerImp() override
{
if (thread_.joinable())
LogicError ("LedgerCleanerImp::onStop not called.");
LogicError("LedgerCleanerImp::onStop not called.");
}
//--------------------------------------------------------------------------
@@ -98,20 +92,23 @@ public:
//
//--------------------------------------------------------------------------
void onPrepare () override
void
onPrepare() override
{
}
void onStart () override
void
onStart() override
{
thread_ = std::thread {&LedgerCleanerImp::run, this};
thread_ = std::thread{&LedgerCleanerImp::run, this};
}
void onStop () override
void
onStop() override
{
JLOG (j_.info()) << "Stopping";
JLOG(j_.info()) << "Stopping";
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
shouldExit_ = true;
wakeup_.notify_one();
}
@@ -124,9 +121,10 @@ public:
//
//--------------------------------------------------------------------------
void onWrite (beast::PropertyStream::Map& map) override
void
onWrite(beast::PropertyStream::Map& map) override
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
if (maxRange_ == 0)
map["status"] = "idle";
@@ -148,14 +146,15 @@ public:
//
//--------------------------------------------------------------------------
void doClean (Json::Value const& params) override
void
doClean(Json::Value const& params) override
{
LedgerIndex minRange = 0;
LedgerIndex maxRange = 0;
app_.getLedgerMaster().getFullValidatedRange (minRange, maxRange);
app_.getLedgerMaster().getFullValidatedRange(minRange, maxRange);
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
maxRange_ = maxRange;
minRange_ = minRange;
@@ -203,7 +202,7 @@ public:
}
if (params.isMember(jss::max_ledger))
maxRange_ = params[jss::max_ledger].asUInt();
maxRange_ = params[jss::max_ledger].asUInt();
if (params.isMember(jss::min_ledger))
minRange_ = params[jss::min_ledger].asUInt();
@@ -234,28 +233,27 @@ public:
//
//--------------------------------------------------------------------------
private:
void init ()
void
init()
{
JLOG (j_.debug()) << "Initializing";
JLOG(j_.debug()) << "Initializing";
}
void run ()
void
run()
{
beast::setCurrentThreadName ("LedgerCleaner");
JLOG (j_.debug()) << "Started";
beast::setCurrentThreadName("LedgerCleaner");
JLOG(j_.debug()) << "Started";
init();
while (true)
{
{
std::unique_lock<std::mutex> lock (mutex_);
wakeup_.wait(lock, [this]()
{
return (
shouldExit_ ||
state_ == State::startCleaning);
});
std::unique_lock<std::mutex> lock(mutex_);
wakeup_.wait(lock, [this]() {
return (shouldExit_ || state_ == State::startCleaning);
});
if (shouldExit_)
break;
@@ -268,9 +266,8 @@ private:
}
// VFALCO TODO This should return boost::optional<uint256>
LedgerHash getLedgerHash(
std::shared_ptr<ReadView const>& ledger,
LedgerIndex index)
LedgerHash
getLedgerHash(std::shared_ptr<ReadView const>& ledger, LedgerIndex index)
{
boost::optional<LedgerHash> hash;
try
@@ -279,13 +276,14 @@ private:
}
catch (SHAMapMissingNode const& mn)
{
JLOG (j_.warn()) <<
"Ledger #" << ledger->info().seq << ": " << mn.what();
app_.getInboundLedgers().acquire (
ledger->info().hash, ledger->info().seq,
JLOG(j_.warn())
<< "Ledger #" << ledger->info().seq << ": " << mn.what();
app_.getInboundLedgers().acquire(
ledger->info().hash,
ledger->info().seq,
InboundLedger::Reason::GENERIC);
}
return hash ? *hash : beast::zero; // kludge
return hash ? *hash : beast::zero; // kludge
}
/** Process a single ledger
@@ -295,45 +293,45 @@ private:
@param doTxns Reprocess (account) transactions to SQL databases.
@return `true` if the ledger was cleaned.
*/
bool doLedger(
bool
doLedger(
LedgerIndex const& ledgerIndex,
LedgerHash const& ledgerHash,
bool doNodes,
bool doTxns)
{
auto nodeLedger = app_.getInboundLedgers().acquire (
auto nodeLedger = app_.getInboundLedgers().acquire(
ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
if (!nodeLedger)
{
JLOG (j_.debug()) << "Ledger " << ledgerIndex << " not available";
app_.getLedgerMaster().clearLedger (ledgerIndex);
JLOG(j_.debug()) << "Ledger " << ledgerIndex << " not available";
app_.getLedgerMaster().clearLedger(ledgerIndex);
app_.getInboundLedgers().acquire(
ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
return false;
}
auto dbLedger = loadByIndex(ledgerIndex, app_);
if (! dbLedger ||
(dbLedger->info().hash != ledgerHash) ||
if (!dbLedger || (dbLedger->info().hash != ledgerHash) ||
(dbLedger->info().parentHash != nodeLedger->info().parentHash))
{
// Ideally we'd also check for more than one ledger with that index
JLOG (j_.debug()) <<
"Ledger " << ledgerIndex << " mismatches SQL DB";
JLOG(j_.debug())
<< "Ledger " << ledgerIndex << " mismatches SQL DB";
doTxns = true;
}
if(! app_.getLedgerMaster().fixIndex(ledgerIndex, ledgerHash))
if (!app_.getLedgerMaster().fixIndex(ledgerIndex, ledgerHash))
{
JLOG (j_.debug()) << "ledger " << ledgerIndex
<< " had wrong entry in history";
JLOG(j_.debug())
<< "ledger " << ledgerIndex << " had wrong entry in history";
doTxns = true;
}
if (doNodes && !nodeLedger->walkLedger(app_.journal ("Ledger")))
if (doNodes && !nodeLedger->walkLedger(app_.journal("Ledger")))
{
JLOG (j_.debug()) << "Ledger " << ledgerIndex << " is missing nodes";
app_.getLedgerMaster().clearLedger (ledgerIndex);
JLOG(j_.debug()) << "Ledger " << ledgerIndex << " is missing nodes";
app_.getLedgerMaster().clearLedger(ledgerIndex);
app_.getInboundLedgers().acquire(
ledgerHash, ledgerIndex, InboundLedger::Reason::GENERIC);
return false;
@@ -341,7 +339,7 @@ private:
if (doTxns && !pendSaveValidated(app_, nodeLedger, true, false))
{
JLOG (j_.debug()) << "Failed to save ledger " << ledgerIndex;
JLOG(j_.debug()) << "Failed to save ledger " << ledgerIndex;
return false;
}
@@ -353,7 +351,8 @@ private:
@param referenceLedger [out] An optional known good subsequent ledger.
@return The hash of the ledger. This will be all-bits-zero if not found.
*/
LedgerHash getHash(
LedgerHash
getHash(
LedgerIndex const& ledgerIndex,
std::shared_ptr<ReadView const>& referenceLedger)
{
@@ -364,8 +363,8 @@ private:
referenceLedger = app_.getLedgerMaster().getValidatedLedger();
if (!referenceLedger)
{
JLOG (j_.warn()) << "No validated ledger";
return ledgerHash; // Nothing we can do. No validated ledger.
JLOG(j_.warn()) << "No validated ledger";
return ledgerHash; // Nothing we can do. No validated ledger.
}
}
@@ -378,42 +377,41 @@ private:
// No. Try to get another ledger that might have the hash we
// need: compute the index and hash of a ledger that will have
// the hash we need.
LedgerIndex refIndex = getCandidateLedger (ledgerIndex);
LedgerHash refHash = getLedgerHash (referenceLedger, refIndex);
LedgerIndex refIndex = getCandidateLedger(ledgerIndex);
LedgerHash refHash = getLedgerHash(referenceLedger, refIndex);
bool const nonzero (refHash.isNonZero ());
assert (nonzero);
bool const nonzero(refHash.isNonZero());
assert(nonzero);
if (nonzero)
{
// We found the hash and sequence of a better reference
// ledger.
referenceLedger =
app_.getInboundLedgers().acquire(
refHash, refIndex, InboundLedger::Reason::GENERIC);
referenceLedger = app_.getInboundLedgers().acquire(
refHash, refIndex, InboundLedger::Reason::GENERIC);
if (referenceLedger)
ledgerHash = getLedgerHash(
referenceLedger, ledgerIndex);
ledgerHash =
getLedgerHash(referenceLedger, ledgerIndex);
}
}
}
else
JLOG (j_.warn()) << "Validated ledger is prior to target ledger";
JLOG(j_.warn()) << "Validated ledger is prior to target ledger";
return ledgerHash;
}
/** Run the ledger cleaner. */
void doLedgerCleaner()
void
doLedgerCleaner()
{
auto shouldExit = [this]()
{
auto shouldExit = [this]() {
std::lock_guard lock(mutex_);
return shouldExit_;
};
std::shared_ptr<ReadView const> goodLedger;
while (! shouldExit())
while (!shouldExit())
{
LedgerIndex ledgerIndex;
LedgerHash ledgerHash;
@@ -422,16 +420,16 @@ private:
while (app_.getFeeTrack().isLoadedLocal())
{
JLOG (j_.debug()) << "Waiting for load to subside";
JLOG(j_.debug()) << "Waiting for load to subside";
std::this_thread::sleep_for(std::chrono::seconds(5));
if (shouldExit())
return;
}
{
std::lock_guard lock (mutex_);
if ((minRange_ > maxRange_) ||
(maxRange_ == 0) || (minRange_ == 0))
std::lock_guard lock(mutex_);
if ((minRange_ > maxRange_) || (maxRange_ == 0) ||
(minRange_ == 0))
{
minRange_ = maxRange_ = 0;
state_ = State::readyToClean;
@@ -447,20 +445,20 @@ private:
bool fail = false;
if (ledgerHash.isZero())
{
JLOG (j_.info()) << "Unable to get hash for ledger "
<< ledgerIndex;
JLOG(j_.info())
<< "Unable to get hash for ledger " << ledgerIndex;
fail = true;
}
else if (!doLedger(ledgerIndex, ledgerHash, doNodes, doTxns))
{
JLOG (j_.info()) << "Failed to process ledger " << ledgerIndex;
JLOG(j_.info()) << "Failed to process ledger " << ledgerIndex;
fail = true;
}
if (fail)
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
++failures_;
}
// Wait for acquiring to catch up to us
@@ -469,7 +467,7 @@ private:
else
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
if (ledgerIndex == minRange_)
++minRange_;
if (ledgerIndex == maxRange_)
@@ -479,27 +477,25 @@ private:
// Reduce I/O pressure and wait for acquiring to catch up to us
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
}
};
//------------------------------------------------------------------------------
LedgerCleaner::LedgerCleaner (Stoppable& parent)
: Stoppable ("LedgerCleaner", parent)
, beast::PropertyStream::Source ("ledgercleaner")
LedgerCleaner::LedgerCleaner(Stoppable& parent)
: Stoppable("LedgerCleaner", parent)
, beast::PropertyStream::Source("ledgercleaner")
{
}
LedgerCleaner::~LedgerCleaner() = default;
std::unique_ptr<LedgerCleaner>
make_LedgerCleaner (Application& app,
Stoppable& parent, beast::Journal journal)
make_LedgerCleaner(Application& app, Stoppable& parent, beast::Journal journal)
{
return std::make_unique<LedgerCleanerImp>(app, parent, journal);
}
} // detail
} // ripple
} // namespace detail
} // namespace ripple

File diff suppressed because it is too large Load Diff

View File

@@ -29,74 +29,80 @@ namespace ripple {
namespace {
bool isFull(LedgerFill const& fill)
bool
isFull(LedgerFill const& fill)
{
return fill.options & LedgerFill::full;
}
bool isExpanded(LedgerFill const& fill)
bool
isExpanded(LedgerFill const& fill)
{
return isFull(fill) || (fill.options & LedgerFill::expand);
}
bool isBinary(LedgerFill const& fill)
bool
isBinary(LedgerFill const& fill)
{
return fill.options & LedgerFill::binary;
}
template <class Object>
void fillJson(Object& json, bool closed, 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
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 (closed)
{
json[jss::closed] = true;
}
else if (! bFull)
else if (!bFull)
{
json[jss::closed] = false;
return;
}
json[jss::ledger_hash] = to_string (info.hash);
json[jss::transaction_hash] = to_string (info.txHash);
json[jss::account_hash] = to_string (info.accountHash);
json[jss::total_coins] = to_string (info.drops);
json[jss::ledger_hash] = to_string(info.hash);
json[jss::transaction_hash] = to_string(info.txHash);
json[jss::account_hash] = to_string(info.accountHash);
json[jss::total_coins] = to_string(info.drops);
// These next three are DEPRECATED.
json[jss::hash] = to_string (info.hash);
json[jss::totalCoins] = to_string (info.drops);
json[jss::hash] = to_string(info.hash);
json[jss::totalCoins] = to_string(info.drops);
json[jss::accepted] = closed;
json[jss::close_flags] = info.closeFlags;
// Always show fields that contribute to the ledger hash
json[jss::parent_close_time] = info.parentCloseTime.time_since_epoch().count();
json[jss::parent_close_time] =
info.parentCloseTime.time_since_epoch().count();
json[jss::close_time] = info.closeTime.time_since_epoch().count();
json[jss::close_time_resolution] = info.closeTimeResolution.count();
if (info.closeTime != NetClock::time_point{})
{
json[jss::close_time_human] = to_string(info.closeTime);
if (! getCloseAgree(info))
if (!getCloseAgree(info))
json[jss::close_time_estimated] = true;
}
}
template <class Object>
void fillJsonBinary(Object& json, bool closed, LedgerInfo const& info)
void
fillJsonBinary(Object& json, bool closed, LedgerInfo const& info)
{
if (! closed)
if (!closed)
json[jss::closed] = false;
else
{
json[jss::closed] = true;
Serializer s;
addRaw (info, s);
json[jss::ledger_data] = strHex (s.peekData ());
addRaw(info, s);
json[jss::ledger_data] = strHex(s.peekData());
}
}
@@ -160,17 +166,19 @@ fillJsonTx(
}
template <class Object>
void fillJsonTx (Object& json, LedgerFill const& fill)
void
fillJsonTx(Object& json, LedgerFill const& fill)
{
auto&& txns = setArray (json, jss::transactions);
auto&& txns = setArray(json, jss::transactions);
auto bBinary = isBinary(fill);
auto bExpanded = isExpanded(fill);
try
{
for (auto& i: fill.ledger.txs)
for (auto& i : fill.ledger.txs)
{
txns.append(fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
txns.append(
fillJsonTx(fill, bBinary, bExpanded, i.first, i.second));
}
}
catch (std::exception const&)
@@ -180,16 +188,17 @@ void fillJsonTx (Object& json, LedgerFill const& fill)
}
template <class Object>
void fillJsonState(Object& json, LedgerFill const& fill)
void
fillJsonState(Object& json, LedgerFill const& fill)
{
auto& ledger = fill.ledger;
auto&& array = Json::setArray (json, jss::accountState);
auto&& array = Json::setArray(json, jss::accountState);
auto expanded = isExpanded(fill);
auto binary = isBinary(fill);
for(auto const& sle : ledger.sles)
for (auto const& sle : ledger.sles)
{
if (fill.type == ltINVALID || sle->getType () == fill.type)
if (fill.type == ltINVALID || sle->getType() == fill.type)
{
if (binary)
{
@@ -206,7 +215,8 @@ void fillJsonState(Object& json, LedgerFill const& fill)
}
template <class Object>
void fillJsonQueue(Object& json, LedgerFill const& fill)
void
fillJsonQueue(Object& json, LedgerFill const& fill)
{
auto&& queueData = Json::setArray(json, jss::queue_data);
auto bBinary = isBinary(fill);
@@ -220,13 +230,11 @@ void fillJsonQueue(Object& json, LedgerFill const& fill)
txJson[jss::LastLedgerSequence] = *tx.lastValid;
if (tx.consequences)
{
txJson[jss::fee] = to_string(
tx.consequences->fee);
auto spend = tx.consequences->potentialSpend +
tx.consequences->fee;
txJson[jss::fee] = to_string(tx.consequences->fee);
auto spend = tx.consequences->potentialSpend + tx.consequences->fee;
txJson[jss::max_spend_drops] = to_string(spend);
auto authChanged = tx.consequences->category ==
TxConsequences::blocker;
auto authChanged =
tx.consequences->category == TxConsequences::blocker;
txJson[jss::auth_change] = authChanged;
}
@@ -241,15 +249,16 @@ void fillJsonQueue(Object& json, LedgerFill const& fill)
}
template <class Object>
void fillJson (Object& json, LedgerFill const& fill)
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);
if (isBinary(fill))
fillJsonBinary(json, ! fill.ledger.open(), fill.ledger.info());
fillJsonBinary(json, !fill.ledger.open(), fill.ledger.info());
else
fillJson(json, ! fill.ledger.open(), fill.ledger.info(), bFull);
fillJson(json, !fill.ledger.open(), fill.ledger.info(), bFull);
if (bFull || fill.options & LedgerFill::dumpTxrp)
fillJsonTx(json, fill);
@@ -258,22 +267,24 @@ void fillJson (Object& json, LedgerFill const& fill)
fillJsonState(json, fill);
}
} // namespace
} // namespace
void addJson (Json::Value& json, LedgerFill const& fill)
void
addJson(Json::Value& json, LedgerFill const& fill)
{
auto&& object = Json::addObject (json, jss::ledger);
fillJson (object, fill);
auto&& object = Json::addObject(json, jss::ledger);
fillJson(object, fill);
if ((fill.options & LedgerFill::dumpQueue) && !fill.txQueue.empty())
fillJsonQueue(json, fill);
}
Json::Value getJson (LedgerFill const& fill)
Json::Value
getJson(LedgerFill const& fill)
{
Json::Value json;
fillJson (json, fill);
fillJson(json, fill);
return json;
}
} // ripple
} // namespace ripple

View File

@@ -53,85 +53,90 @@ namespace ripple {
class LocalTx
{
public:
// The number of ledgers to hold a transaction is essentially
// arbitrary. It should be sufficient to allow the transaction to
// get into a fully-validated ledger.
static int const holdLedgers = 5;
LocalTx (LedgerIndex index, std::shared_ptr<STTx const> const& txn)
: m_txn (txn)
, m_expire (index + holdLedgers)
, m_id (txn->getTransactionID ())
, m_account (txn->getAccountID(sfAccount))
, m_seq (txn->getSequence())
LocalTx(LedgerIndex index, std::shared_ptr<STTx const> const& txn)
: m_txn(txn)
, m_expire(index + holdLedgers)
, m_id(txn->getTransactionID())
, m_account(txn->getAccountID(sfAccount))
, m_seq(txn->getSequence())
{
if (txn->isFieldPresent (sfLastLedgerSequence))
m_expire = std::min (m_expire, txn->getFieldU32 (sfLastLedgerSequence) + 1);
if (txn->isFieldPresent(sfLastLedgerSequence))
m_expire =
std::min(m_expire, txn->getFieldU32(sfLastLedgerSequence) + 1);
}
uint256 const& getID () const
uint256 const&
getID() const
{
return m_id;
}
std::uint32_t getSeq () const
std::uint32_t
getSeq() const
{
return m_seq;
}
bool isExpired (LedgerIndex i) const
bool
isExpired(LedgerIndex i) const
{
return i > m_expire;
}
std::shared_ptr<STTx const> const& getTX () const
std::shared_ptr<STTx const> const&
getTX() const
{
return m_txn;
}
AccountID const& getAccount () const
AccountID const&
getAccount() const
{
return m_account;
}
private:
std::shared_ptr<STTx const> m_txn;
LedgerIndex m_expire;
uint256 m_id;
AccountID m_account;
std::uint32_t m_seq;
LedgerIndex m_expire;
uint256 m_id;
AccountID m_account;
std::uint32_t m_seq;
};
//------------------------------------------------------------------------------
class LocalTxsImp
: public LocalTxs
class LocalTxsImp : public LocalTxs
{
public:
LocalTxsImp() = default;
// Add a new transaction to the set of local transactions
void push_back (LedgerIndex index, std::shared_ptr<STTx const> const& txn) override
void
push_back(LedgerIndex index, std::shared_ptr<STTx const> const& txn)
override
{
std::lock_guard lock (m_lock);
std::lock_guard lock(m_lock);
m_txns.emplace_back (index, txn);
m_txns.emplace_back(index, txn);
}
CanonicalTXSet
getTxSet () override
getTxSet() override
{
CanonicalTXSet tset (uint256 {});
CanonicalTXSet tset(uint256{});
// Get the set of local transactions as a canonical
// set (so they apply in a valid order)
{
std::lock_guard lock (m_lock);
std::lock_guard lock(m_lock);
for (auto const& it : m_txns)
tset.insert (it.getTX());
tset.insert(it.getTX());
}
return tset;
@@ -140,41 +145,42 @@ public:
// Remove transactions that have either been accepted
// into a fully-validated ledger, are (now) impossible,
// or have expired
void sweep (ReadView const& view) override
void
sweep(ReadView const& view) override
{
std::lock_guard lock (m_lock);
std::lock_guard lock(m_lock);
m_txns.remove_if ([&view](auto const& txn)
{
if (txn.isExpired (view.info().seq))
m_txns.remove_if([&view](auto const& txn) {
if (txn.isExpired(view.info().seq))
return true;
if (view.txExists(txn.getID()))
return true;
std::shared_ptr<SLE const> sle = view.read(
keylet::account(txn.getAccount()));
if (! sle)
std::shared_ptr<SLE const> sle =
view.read(keylet::account(txn.getAccount()));
if (!sle)
return false;
return sle->getFieldU32 (sfSequence) > txn.getSeq ();
return sle->getFieldU32(sfSequence) > txn.getSeq();
});
}
std::size_t size () override
std::size_t
size() override
{
std::lock_guard lock (m_lock);
std::lock_guard lock(m_lock);
return m_txns.size ();
return m_txns.size();
}
private:
std::mutex m_lock;
std::list <LocalTx> m_txns;
std::list<LocalTx> m_txns;
};
std::unique_ptr<LocalTxs>
make_LocalTxs ()
make_LocalTxs()
{
return std::make_unique<LocalTxsImp> ();
return std::make_unique<LocalTxsImp>();
}
} // ripple
} // namespace ripple

View File

@@ -31,13 +31,11 @@
namespace ripple {
OpenLedger::OpenLedger(std::shared_ptr<
Ledger const> const& ledger,
CachedSLEs& cache,
beast::Journal journal)
: j_ (journal)
, cache_ (cache)
, current_ (create(ledger->rules(), ledger))
OpenLedger::OpenLedger(
std::shared_ptr<Ledger const> const& ledger,
CachedSLEs& cache,
beast::Journal journal)
: j_(journal), cache_(cache), current_(create(ledger->rules(), ledger))
{
}
@@ -56,11 +54,10 @@ OpenLedger::current() const
}
bool
OpenLedger::modify (modify_type const& f)
OpenLedger::modify(modify_type const& f)
{
std::lock_guard lock1(modify_mutex_);
auto next = std::make_shared<
OpenView>(*current_);
auto next = std::make_shared<OpenView>(*current_);
auto const changed = f(*next, j_);
if (changed)
{
@@ -71,15 +68,18 @@ OpenLedger::modify (modify_type const& f)
}
void
OpenLedger::accept(Application& app, Rules const& rules,
OpenLedger::accept(
Application& app,
Rules const& rules,
std::shared_ptr<Ledger const> const& ledger,
OrderedTxs const& locals, bool retriesFirst,
OrderedTxs& retries, ApplyFlags flags,
std::string const& suffix,
modify_type const& f)
OrderedTxs const& locals,
bool retriesFirst,
OrderedTxs& retries,
ApplyFlags flags,
std::string const& suffix,
modify_type const& f)
{
JLOG(j_.trace()) <<
"accept ledger " << ledger->seq() << " " << suffix;
JLOG(j_.trace()) << "accept ledger " << ledger->seq() << " " << suffix;
auto next = create(rules, ledger);
std::map<uint256, bool> shouldRecover;
if (retriesFirst)
@@ -90,49 +90,49 @@ OpenLedger::accept(Application& app, Rules const& rules,
shouldRecover[txID] = app.getHashRouter().shouldRecover(txID);
}
// Handle disputed tx, outside lock
using empty =
std::vector<std::shared_ptr<
STTx const>>;
apply (app, *next, *ledger, empty{},
retries, flags, shouldRecover, j_);
using empty = std::vector<std::shared_ptr<STTx const>>;
apply(app, *next, *ledger, empty{}, retries, flags, shouldRecover, j_);
}
// Block calls to modify, otherwise
// new tx going into the open ledger
// would get lost.
std::lock_guard lock1(modify_mutex_);
// Apply tx from the current open view
if (! current_->txs.empty())
if (!current_->txs.empty())
{
for (auto const& tx : current_->txs)
{
auto const txID = tx.first->getTransactionID();
auto iter = shouldRecover.lower_bound(txID);
if (iter != shouldRecover.end()
&& iter->first == txID)
if (iter != shouldRecover.end() && iter->first == txID)
// already had a chance via disputes
iter->second = false;
else
shouldRecover.emplace_hint(iter, txID,
app.getHashRouter().shouldRecover(txID));
shouldRecover.emplace_hint(
iter, txID, app.getHashRouter().shouldRecover(txID));
}
apply (app, *next, *ledger,
apply(
app,
*next,
*ledger,
boost::adaptors::transform(
current_->txs,
[](std::pair<std::shared_ptr<
STTx const>, std::shared_ptr<
STObject const>> const& p)
{
return p.first;
}),
retries, flags, shouldRecover, j_);
[](std::pair<
std::shared_ptr<STTx const>,
std::shared_ptr<STObject const>> const& p) {
return p.first;
}),
retries,
flags,
shouldRecover,
j_);
}
// Call the modifier
if (f)
f(*next, j_);
// Apply local tx
for (auto const& item : locals)
app.getTxQ().apply(app, *next,
item.second, flags, j_);
app.getTxQ().apply(app, *next, item.second, flags, j_);
// If we didn't relay this transaction recently, relay it to all peers
for (auto const& txpair : next->txs)
@@ -150,7 +150,7 @@ OpenLedger::accept(Application& app, Rules const& rules,
msg.set_status(protocol::tsNEW);
msg.set_receivetimestamp(
app.timeKeeper().now().time_since_epoch().count());
app.overlay().foreach(send_if_not(
app.overlay().foreach (send_if_not(
std::make_shared<Message>(msg, protocol::mtTRANSACTION),
peer_in_set(*toSkip)));
}
@@ -164,27 +164,31 @@ OpenLedger::accept(Application& app, Rules const& rules,
//------------------------------------------------------------------------------
std::shared_ptr<OpenView>
OpenLedger::create (Rules const& rules,
OpenLedger::create(
Rules const& rules,
std::shared_ptr<Ledger const> const& ledger)
{
return std::make_shared<OpenView>(
open_ledger, rules, std::make_shared<
CachedLedger const>(ledger,
cache_));
open_ledger,
rules,
std::make_shared<CachedLedger const>(ledger, cache_));
}
auto
OpenLedger::apply_one (Application& app, OpenView& view,
OpenLedger::apply_one(
Application& app,
OpenView& view,
std::shared_ptr<STTx const> const& tx,
bool retry, ApplyFlags flags, bool shouldRecover,
beast::Journal j) -> Result
bool retry,
ApplyFlags flags,
bool shouldRecover,
beast::Journal j) -> Result
{
if (retry)
flags = flags | tapRETRY;
auto const result = [&]
{
auto const queueResult = app.getTxQ().apply(
app, view, tx, flags | tapPREFER_QUEUE, j);
auto const result = [&] {
auto const queueResult =
app.getTxQ().apply(app, view, tx, flags | tapPREFER_QUEUE, j);
// If the transaction can't get into the queue for intrinsic
// reasons, and it can still be recovered, try to put it
// directly into the open ledger, else drop it.
@@ -192,12 +196,10 @@ OpenLedger::apply_one (Application& app, OpenView& view,
return ripple::apply(app, view, *tx, flags, j);
return queueResult;
}();
if (result.second ||
result.first == terQUEUED)
if (result.second || result.first == terQUEUED)
return Result::success;
if (isTefFailure (result.first) ||
isTemMalformed (result.first) ||
isTelLocal (result.first))
if (isTefFailure(result.first) || isTemMalformed(result.first) ||
isTelLocal(result.first))
return Result::failure;
return Result::retry;
}
@@ -205,7 +207,7 @@ OpenLedger::apply_one (Application& app, OpenView& view,
//------------------------------------------------------------------------------
std::string
debugTxstr (std::shared_ptr<STTx const> const& tx)
debugTxstr(std::shared_ptr<STTx const> const& tx)
{
std::stringstream ss;
ss << tx->getTransactionID();
@@ -213,16 +215,16 @@ debugTxstr (std::shared_ptr<STTx const> const& tx)
}
std::string
debugTostr (OrderedTxs const& set)
debugTostr(OrderedTxs const& set)
{
std::stringstream ss;
for(auto const& item : set)
for (auto const& item : set)
ss << debugTxstr(item.second) << ", ";
return ss.str();
}
std::string
debugTostr (SHAMap const& set)
debugTostr(SHAMap const& set)
{
std::stringstream ss;
for (auto const& item : set)
@@ -230,11 +232,10 @@ debugTostr (SHAMap const& set)
try
{
SerialIter sit(item.slice());
auto const tx = std::make_shared<
STTx const>(sit);
auto const tx = std::make_shared<STTx const>(sit);
ss << debugTxstr(tx) << ", ";
}
catch(std::exception const&)
catch (std::exception const&)
{
ss << "THRO, ";
}
@@ -243,12 +244,12 @@ debugTostr (SHAMap const& set)
}
std::string
debugTostr (std::shared_ptr<ReadView const> const& view)
debugTostr(std::shared_ptr<ReadView const> const& view)
{
std::stringstream ss;
for(auto const& item : view->txs)
for (auto const& item : view->txs)
ss << debugTxstr(item.first) << ", ";
return ss.str();
}
} // ripple
} // namespace ripple

View File

@@ -17,10 +17,10 @@
*/
//==============================================================================
#include <ripple/app/ledger/impl/TransactionAcquire.h>
#include <ripple/app/ledger/ConsensusTransSetSF.h>
#include <ripple/app/ledger/InboundLedgers.h>
#include <ripple/app/ledger/InboundTransactions.h>
#include <ripple/app/ledger/impl/TransactionAcquire.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/overlay/Overlay.h>
@@ -34,235 +34,253 @@ using namespace std::chrono_literals;
// Timeout interval in milliseconds
auto constexpr TX_ACQUIRE_TIMEOUT = 250ms;
enum
{
enum {
NORM_TIMEOUTS = 4,
MAX_TIMEOUTS = 20,
};
TransactionAcquire::TransactionAcquire (Application& app, uint256 const& hash, clock_type& clock)
: PeerSet (app, hash, TX_ACQUIRE_TIMEOUT, clock,
app.journal("TransactionAcquire"))
, mHaveRoot (false)
TransactionAcquire::TransactionAcquire(
Application& app,
uint256 const& hash,
clock_type& clock)
: PeerSet(
app,
hash,
TX_ACQUIRE_TIMEOUT,
clock,
app.journal("TransactionAcquire"))
, mHaveRoot(false)
, j_(app.journal("TransactionAcquire"))
{
mMap = std::make_shared<SHAMap> (SHAMapType::TRANSACTION, hash,
app_.family());
mMap->setUnbacked ();
mMap =
std::make_shared<SHAMap>(SHAMapType::TRANSACTION, hash, app_.family());
mMap->setUnbacked();
}
void TransactionAcquire::execute ()
void
TransactionAcquire::execute()
{
app_.getJobQueue ().addJob (
jtTXN_DATA, "TransactionAcquire",
[ptr = shared_from_this()](Job&)
{
ptr->invokeOnTimer ();
app_.getJobQueue().addJob(
jtTXN_DATA, "TransactionAcquire", [ptr = shared_from_this()](Job&) {
ptr->invokeOnTimer();
});
}
void TransactionAcquire::done ()
void
TransactionAcquire::done()
{
// We hold a PeerSet lock and so cannot do real work here
if (mFailed)
{
JLOG (j_.warn()) << "Failed to acquire TX set " << mHash;
JLOG(j_.warn()) << "Failed to acquire TX set " << mHash;
}
else
{
JLOG (j_.debug()) << "Acquired TX set " << mHash;
mMap->setImmutable ();
JLOG(j_.debug()) << "Acquired TX set " << mHash;
mMap->setImmutable();
uint256 const& hash (mHash);
std::shared_ptr <SHAMap> const& map (mMap);
uint256 const& hash(mHash);
std::shared_ptr<SHAMap> const& map(mMap);
auto const pap = &app_;
// Note that, when we're in the process of shutting down, addJob()
// may reject the request. If that happens then giveSet() will
// not be called. That's fine. According to David the giveSet() call
// just updates the consensus and related structures when we acquire
// a transaction set. No need to update them if we're shutting down.
app_.getJobQueue().addJob (jtTXN_DATA, "completeAcquire",
[pap, hash, map](Job&)
{
pap->getInboundTransactions().giveSet (
hash, map, true);
app_.getJobQueue().addJob(
jtTXN_DATA, "completeAcquire", [pap, hash, map](Job&) {
pap->getInboundTransactions().giveSet(hash, map, true);
});
}
}
void TransactionAcquire::onTimer (bool progress, ScopedLockType& psl)
void
TransactionAcquire::onTimer(bool progress, ScopedLockType& psl)
{
bool aggressive = false;
if (getTimeouts () >= NORM_TIMEOUTS)
if (getTimeouts() >= NORM_TIMEOUTS)
{
aggressive = true;
if (getTimeouts () > MAX_TIMEOUTS)
if (getTimeouts() > MAX_TIMEOUTS)
{
mFailed = true;
done ();
done();
return;
}
}
if (aggressive)
trigger (nullptr);
trigger(nullptr);
addPeers (1);
addPeers(1);
}
std::weak_ptr<PeerSet> TransactionAcquire::pmDowncast ()
std::weak_ptr<PeerSet>
TransactionAcquire::pmDowncast()
{
return std::dynamic_pointer_cast<PeerSet> (shared_from_this ());
return std::dynamic_pointer_cast<PeerSet>(shared_from_this());
}
void TransactionAcquire::trigger (std::shared_ptr<Peer> const& peer)
void
TransactionAcquire::trigger(std::shared_ptr<Peer> const& peer)
{
if (mComplete)
{
JLOG (j_.info()) << "trigger after complete";
JLOG(j_.info()) << "trigger after complete";
return;
}
if (mFailed)
{
JLOG (j_.info()) << "trigger after fail";
JLOG(j_.info()) << "trigger after fail";
return;
}
if (!mHaveRoot)
{
JLOG (j_.trace()) << "TransactionAcquire::trigger " << (peer ? "havePeer" : "noPeer") << " no root";
JLOG(j_.trace()) << "TransactionAcquire::trigger "
<< (peer ? "havePeer" : "noPeer") << " no root";
protocol::TMGetLedger tmGL;
tmGL.set_ledgerhash (mHash.begin (), mHash.size ());
tmGL.set_itype (protocol::liTS_CANDIDATE);
tmGL.set_querydepth (3); // We probably need the whole thing
tmGL.set_ledgerhash(mHash.begin(), mHash.size());
tmGL.set_itype(protocol::liTS_CANDIDATE);
tmGL.set_querydepth(3); // We probably need the whole thing
if (getTimeouts () != 0)
tmGL.set_querytype (protocol::qtINDIRECT);
if (getTimeouts() != 0)
tmGL.set_querytype(protocol::qtINDIRECT);
* (tmGL.add_nodeids ()) = SHAMapNodeID ().getRawString ();
sendRequest (tmGL, peer);
*(tmGL.add_nodeids()) = SHAMapNodeID().getRawString();
sendRequest(tmGL, peer);
}
else if (!mMap->isValid ())
else if (!mMap->isValid())
{
mFailed = true;
done ();
done();
}
else
{
ConsensusTransSetSF sf (app_, app_.getTempNodeCache ());
auto nodes = mMap->getMissingNodes (256, &sf);
ConsensusTransSetSF sf(app_, app_.getTempNodeCache());
auto nodes = mMap->getMissingNodes(256, &sf);
if (nodes.empty ())
if (nodes.empty())
{
if (mMap->isValid ())
if (mMap->isValid())
mComplete = true;
else
mFailed = true;
done ();
done();
return;
}
protocol::TMGetLedger tmGL;
tmGL.set_ledgerhash (mHash.begin (), mHash.size ());
tmGL.set_itype (protocol::liTS_CANDIDATE);
tmGL.set_ledgerhash(mHash.begin(), mHash.size());
tmGL.set_itype(protocol::liTS_CANDIDATE);
if (getTimeouts () != 0)
tmGL.set_querytype (protocol::qtINDIRECT);
if (getTimeouts() != 0)
tmGL.set_querytype(protocol::qtINDIRECT);
for (auto const& node : nodes)
{
*tmGL.add_nodeids () = node.first.getRawString ();
*tmGL.add_nodeids() = node.first.getRawString();
}
sendRequest (tmGL, peer);
sendRequest(tmGL, peer);
}
}
SHAMapAddNode TransactionAcquire::takeNodes (const std::list<SHAMapNodeID>& nodeIDs,
const std::list< Blob >& data, std::shared_ptr<Peer> const& peer)
SHAMapAddNode
TransactionAcquire::takeNodes(
const std::list<SHAMapNodeID>& nodeIDs,
const std::list<Blob>& data,
std::shared_ptr<Peer> const& peer)
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
if (mComplete)
{
JLOG (j_.trace()) << "TX set complete";
return SHAMapAddNode ();
JLOG(j_.trace()) << "TX set complete";
return SHAMapAddNode();
}
if (mFailed)
{
JLOG (j_.trace()) << "TX set failed";
return SHAMapAddNode ();
JLOG(j_.trace()) << "TX set failed";
return SHAMapAddNode();
}
try
{
if (nodeIDs.empty ())
return SHAMapAddNode::invalid ();
if (nodeIDs.empty())
return SHAMapAddNode::invalid();
std::list<SHAMapNodeID>::const_iterator nodeIDit = nodeIDs.begin ();
std::list< Blob >::const_iterator nodeDatait = data.begin ();
ConsensusTransSetSF sf (app_, app_.getTempNodeCache ());
std::list<SHAMapNodeID>::const_iterator nodeIDit = nodeIDs.begin();
std::list<Blob>::const_iterator nodeDatait = data.begin();
ConsensusTransSetSF sf(app_, app_.getTempNodeCache());
while (nodeIDit != nodeIDs.end ())
while (nodeIDit != nodeIDs.end())
{
if (nodeIDit->isRoot ())
if (nodeIDit->isRoot())
{
if (mHaveRoot)
JLOG (j_.debug()) << "Got root TXS node, already have it";
else if (!mMap->addRootNode (SHAMapHash{getHash ()},
makeSlice(*nodeDatait), snfWIRE, nullptr).isGood())
JLOG(j_.debug()) << "Got root TXS node, already have it";
else if (!mMap->addRootNode(
SHAMapHash{getHash()},
makeSlice(*nodeDatait),
snfWIRE,
nullptr)
.isGood())
{
JLOG (j_.warn()) << "TX acquire got bad root node";
JLOG(j_.warn()) << "TX acquire got bad root node";
}
else
mHaveRoot = true;
}
else if (!mMap->addKnownNode (*nodeIDit, makeSlice(*nodeDatait), &sf).isGood())
else if (!mMap->addKnownNode(*nodeIDit, makeSlice(*nodeDatait), &sf)
.isGood())
{
JLOG (j_.warn()) << "TX acquire got bad non-root node";
return SHAMapAddNode::invalid ();
JLOG(j_.warn()) << "TX acquire got bad non-root node";
return SHAMapAddNode::invalid();
}
++nodeIDit;
++nodeDatait;
}
trigger (peer);
progress ();
return SHAMapAddNode::useful ();
trigger(peer);
progress();
return SHAMapAddNode::useful();
}
catch (std::exception const&)
{
JLOG (j_.error()) << "Peer sends us junky transaction node data";
return SHAMapAddNode::invalid ();
JLOG(j_.error()) << "Peer sends us junky transaction node data";
return SHAMapAddNode::invalid();
}
}
void TransactionAcquire::addPeers (int numPeers)
void
TransactionAcquire::addPeers(int numPeers)
{
app_.overlay().selectPeers (*this, numPeers, ScoreHasTxSet (getHash()));
app_.overlay().selectPeers(*this, numPeers, ScoreHasTxSet(getHash()));
}
void TransactionAcquire::init (int numPeers)
void
TransactionAcquire::init(int numPeers)
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
addPeers (numPeers);
addPeers(numPeers);
setTimer ();
setTimer();
}
void TransactionAcquire::stillNeed ()
void
TransactionAcquire::stillNeed()
{
ScopedLockType sl (mLock);
ScopedLockType sl(mLock);
if (mTimeouts > NORM_TIMEOUTS)
mTimeouts = NORM_TIMEOUTS;
}
} // ripple
} // namespace ripple

View File

@@ -29,56 +29,74 @@ namespace ripple {
// VFALCO TODO rename to PeerTxRequest
// A transaction set we are trying to acquire
class TransactionAcquire
: public PeerSet
, public std::enable_shared_from_this <TransactionAcquire>
, public CountedObject <TransactionAcquire>
: public PeerSet,
public std::enable_shared_from_this<TransactionAcquire>,
public CountedObject<TransactionAcquire>
{
public:
static char const* getCountedObjectName () { return "TransactionAcquire"; }
static char const*
getCountedObjectName()
{
return "TransactionAcquire";
}
using pointer = std::shared_ptr<TransactionAcquire>;
public:
TransactionAcquire (Application& app, uint256 const& hash, clock_type& clock);
~TransactionAcquire () = default;
TransactionAcquire(
Application& app,
uint256 const& hash,
clock_type& clock);
~TransactionAcquire() = default;
std::shared_ptr<SHAMap> const& getMap ()
std::shared_ptr<SHAMap> const&
getMap()
{
return mMap;
}
SHAMapAddNode takeNodes (const std::list<SHAMapNodeID>& IDs,
const std::list< Blob >& data, std::shared_ptr<Peer> const&);
SHAMapAddNode
takeNodes(
const std::list<SHAMapNodeID>& IDs,
const std::list<Blob>& data,
std::shared_ptr<Peer> const&);
void init (int startPeers);
void
init(int startPeers);
void stillNeed ();
void
stillNeed();
private:
std::shared_ptr<SHAMap> mMap;
bool mHaveRoot;
beast::Journal j_;
bool mHaveRoot;
beast::Journal j_;
void execute () override;
void
execute() override;
void onTimer (bool progress, ScopedLockType& peerSetLock) override;
void
onTimer(bool progress, ScopedLockType& peerSetLock) override;
void newPeer (std::shared_ptr<Peer> const& peer) override
void
newPeer(std::shared_ptr<Peer> const& peer) override
{
trigger (peer);
trigger(peer);
}
void done ();
void
done();
// Tries to add the specified number of peers
void addPeers (int num);
void
addPeers(int num);
void trigger (std::shared_ptr<Peer> const&);
std::weak_ptr<PeerSet> pmDowncast () override;
void
trigger(std::shared_ptr<Peer> const&);
std::weak_ptr<PeerSet>
pmDowncast() override;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -18,46 +18,51 @@
//==============================================================================
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/STTx.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/basics/chrono.h>
#include <ripple/protocol/STTx.h>
namespace ripple {
TransactionMaster::TransactionMaster (Application& app)
: mApp (app)
, mCache ("TransactionCache", 65536, std::chrono::minutes {30}, stopwatch(),
mApp.journal("TaggedCache"))
TransactionMaster::TransactionMaster(Application& app)
: mApp(app)
, mCache(
"TransactionCache",
65536,
std::chrono::minutes{30},
stopwatch(),
mApp.journal("TaggedCache"))
{
}
bool TransactionMaster::inLedger (uint256 const& hash, std::uint32_t ledger)
bool
TransactionMaster::inLedger(uint256 const& hash, std::uint32_t ledger)
{
auto txn = mCache.fetch (hash);
auto txn = mCache.fetch(hash);
if (!txn)
return false;
txn->setStatus (COMMITTED, ledger);
txn->setStatus(COMMITTED, ledger);
return true;
}
std::shared_ptr<Transaction>
TransactionMaster::fetch_from_cache (uint256 const& txnID)
TransactionMaster::fetch_from_cache(uint256 const& txnID)
{
return mCache.fetch (txnID);
return mCache.fetch(txnID);
}
std::shared_ptr<Transaction>
TransactionMaster::fetch (uint256 const& txnID, error_code_i& ec)
TransactionMaster::fetch(uint256 const& txnID, error_code_i& ec)
{
auto txn = fetch_from_cache (txnID);
auto txn = fetch_from_cache(txnID);
if (txn)
return txn;
txn = Transaction::load (txnID, mApp, ec);
txn = Transaction::load(txnID, mApp, ec);
if (!txn)
return txn;
@@ -68,52 +73,56 @@ TransactionMaster::fetch (uint256 const& txnID, error_code_i& ec)
}
boost::variant<Transaction::pointer, bool>
TransactionMaster::fetch (uint256 const& txnID, ClosedInterval<uint32_t> const& range,
TransactionMaster::fetch(
uint256 const& txnID,
ClosedInterval<uint32_t> const& range,
error_code_i& ec)
{
using pointer = Transaction::pointer;
auto txn = mCache.fetch (txnID);
auto txn = mCache.fetch(txnID);
if (txn)
return txn;
boost::variant<Transaction::pointer, bool> v = Transaction::load (
txnID, mApp, range, ec);
boost::variant<Transaction::pointer, bool> v =
Transaction::load(txnID, mApp, range, ec);
if (v.which () == 0 && boost::get<pointer> (v))
mCache.canonicalize_replace_client(txnID, boost::get<pointer> (v));
if (v.which() == 0 && boost::get<pointer>(v))
mCache.canonicalize_replace_client(txnID, boost::get<pointer>(v));
return v;
}
std::shared_ptr<STTx const>
TransactionMaster::fetch (std::shared_ptr<SHAMapItem> const& item,
SHAMapTreeNode::TNType type, std::uint32_t uCommitLedger)
TransactionMaster::fetch(
std::shared_ptr<SHAMapItem> const& item,
SHAMapTreeNode::TNType type,
std::uint32_t uCommitLedger)
{
std::shared_ptr<STTx const> txn;
auto iTx = fetch_from_cache (item->key());
std::shared_ptr<STTx const> txn;
auto iTx = fetch_from_cache(item->key());
if (!iTx)
{
if (type == SHAMapTreeNode::tnTRANSACTION_NM)
{
SerialIter sit (item->slice());
txn = std::make_shared<STTx const> (std::ref (sit));
SerialIter sit(item->slice());
txn = std::make_shared<STTx const>(std::ref(sit));
}
else if (type == SHAMapTreeNode::tnTRANSACTION_MD)
{
auto blob = SerialIter{item->data(), item->size()}.getVL();
txn = std::make_shared<STTx const>(SerialIter{blob.data(), blob.size()});
txn = std::make_shared<STTx const>(
SerialIter{blob.data(), blob.size()});
}
}
else
{
if (uCommitLedger)
iTx->setStatus (COMMITTED, uCommitLedger);
iTx->setStatus(COMMITTED, uCommitLedger);
txn = iTx->getSTransaction ();
txn = iTx->getSTransaction();
}
return txn;
@@ -132,14 +141,16 @@ TransactionMaster::canonicalize(std::shared_ptr<Transaction>* pTransaction)
}
}
void TransactionMaster::sweep (void)
void
TransactionMaster::sweep(void)
{
mCache.sweep ();
mCache.sweep();
}
TaggedCache <uint256, Transaction>& TransactionMaster::getCache()
TaggedCache<uint256, Transaction>&
TransactionMaster::getCache()
{
return mCache;
}
} // ripple
} // namespace ripple

File diff suppressed because it is too large Load Diff

View File

@@ -20,23 +20,32 @@
#ifndef RIPPLE_APP_MAIN_APPLICATION_H_INCLUDED
#define RIPPLE_APP_MAIN_APPLICATION_H_INCLUDED
#include <ripple/basics/TaggedCache.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/core/Config.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/shamap/FullBelowCache.h>
#include <ripple/shamap/TreeNodeCache.h>
#include <ripple/basics/TaggedCache.h>
#include <ripple/core/Config.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/beast/utility/PropertyStream.h>
#include <ripple/overlay/PeerReservationTable.h>
#include <boost/asio.hpp>
#include <memory>
#include <mutex>
namespace ripple {
namespace unl { class Manager; }
namespace Resource { class Manager; }
namespace NodeStore { class Database; class DatabaseShard; }
namespace perf { class PerfLog; }
namespace unl {
class Manager;
}
namespace Resource {
class Manager;
}
namespace NodeStore {
class Database;
class DatabaseShard;
} // namespace NodeStore
namespace perf {
class PerfLog;
}
// VFALCO TODO Fix forward declares required for header dependency loops
class AmendmentTable;
@@ -75,7 +84,7 @@ class Cluster;
class DatabaseCon;
class SHAMapStore;
using NodeCache = TaggedCache <SHAMapHash, Blob>;
using NodeCache = TaggedCache<SHAMapHash, Blob>;
template <class Adaptor>
class Validations;
@@ -97,110 +106,158 @@ public:
other things
*/
using MutexType = std::recursive_mutex;
virtual MutexType& getMasterMutex () = 0;
virtual MutexType&
getMasterMutex() = 0;
public:
Application ();
Application();
virtual ~Application () = default;
virtual ~Application() = default;
virtual bool setup() = 0;
virtual void doStart(bool withTimers) = 0;
virtual void run() = 0;
virtual bool isShutdown () = 0;
virtual void signalStop () = 0;
virtual bool checkSigs() const = 0;
virtual void checkSigs(bool) = 0;
virtual bool
setup() = 0;
virtual void
doStart(bool withTimers) = 0;
virtual void
run() = 0;
virtual bool
isShutdown() = 0;
virtual void
signalStop() = 0;
virtual bool
checkSigs() const = 0;
virtual void
checkSigs(bool) = 0;
//
// ---
//
virtual Logs& logs() = 0;
virtual Config& config() = 0;
virtual Logs&
logs() = 0;
virtual Config&
config() = 0;
virtual
boost::asio::io_service&
getIOService () = 0;
virtual boost::asio::io_service&
getIOService() = 0;
virtual CollectorManager& getCollectorManager () = 0;
virtual Family& family() = 0;
virtual Family* shardFamily() = 0;
virtual TimeKeeper& timeKeeper() = 0;
virtual JobQueue& getJobQueue () = 0;
virtual NodeCache& getTempNodeCache () = 0;
virtual CachedSLEs& cachedSLEs() = 0;
virtual AmendmentTable& getAmendmentTable() = 0;
virtual HashRouter& getHashRouter () = 0;
virtual LoadFeeTrack& getFeeTrack () = 0;
virtual LoadManager& getLoadManager () = 0;
virtual Overlay& overlay () = 0;
virtual TxQ& getTxQ() = 0;
virtual ValidatorList& validators () = 0;
virtual ValidatorSite& validatorSites () = 0;
virtual ManifestCache& validatorManifests () = 0;
virtual ManifestCache& publisherManifests () = 0;
virtual Cluster& cluster () = 0;
virtual PeerReservationTable& peerReservations () = 0;
virtual RCLValidations& getValidations () = 0;
virtual NodeStore::Database& getNodeStore () = 0;
virtual NodeStore::DatabaseShard* getShardStore() = 0;
virtual InboundLedgers& getInboundLedgers () = 0;
virtual InboundTransactions& getInboundTransactions () = 0;
virtual CollectorManager&
getCollectorManager() = 0;
virtual Family&
family() = 0;
virtual Family*
shardFamily() = 0;
virtual TimeKeeper&
timeKeeper() = 0;
virtual JobQueue&
getJobQueue() = 0;
virtual NodeCache&
getTempNodeCache() = 0;
virtual CachedSLEs&
cachedSLEs() = 0;
virtual AmendmentTable&
getAmendmentTable() = 0;
virtual HashRouter&
getHashRouter() = 0;
virtual LoadFeeTrack&
getFeeTrack() = 0;
virtual LoadManager&
getLoadManager() = 0;
virtual Overlay&
overlay() = 0;
virtual TxQ&
getTxQ() = 0;
virtual ValidatorList&
validators() = 0;
virtual ValidatorSite&
validatorSites() = 0;
virtual ManifestCache&
validatorManifests() = 0;
virtual ManifestCache&
publisherManifests() = 0;
virtual Cluster&
cluster() = 0;
virtual PeerReservationTable&
peerReservations() = 0;
virtual RCLValidations&
getValidations() = 0;
virtual NodeStore::Database&
getNodeStore() = 0;
virtual NodeStore::DatabaseShard*
getShardStore() = 0;
virtual InboundLedgers&
getInboundLedgers() = 0;
virtual InboundTransactions&
getInboundTransactions() = 0;
virtual
TaggedCache <uint256, AcceptedLedger>&
getAcceptedLedgerCache () = 0;
virtual TaggedCache<uint256, AcceptedLedger>&
getAcceptedLedgerCache() = 0;
virtual LedgerMaster& getLedgerMaster () = 0;
virtual NetworkOPs& getOPs () = 0;
virtual OrderBookDB& getOrderBookDB () = 0;
virtual TransactionMaster& getMasterTransaction () = 0;
virtual perf::PerfLog& getPerfLog () = 0;
virtual LedgerMaster&
getLedgerMaster() = 0;
virtual NetworkOPs&
getOPs() = 0;
virtual OrderBookDB&
getOrderBookDB() = 0;
virtual TransactionMaster&
getMasterTransaction() = 0;
virtual perf::PerfLog&
getPerfLog() = 0;
virtual
std::pair<PublicKey, SecretKey> const&
nodeIdentity () = 0;
virtual std::pair<PublicKey, SecretKey> const&
nodeIdentity() = 0;
virtual
PublicKey const &
getValidationPublicKey() const = 0;
virtual PublicKey const&
getValidationPublicKey() const = 0;
virtual Resource::Manager& getResourceManager () = 0;
virtual PathRequests& getPathRequests () = 0;
virtual SHAMapStore& getSHAMapStore () = 0;
virtual PendingSaves& pendingSaves() = 0;
virtual AccountIDCache const& accountIDCache() const = 0;
virtual OpenLedger& openLedger() = 0;
virtual OpenLedger const& openLedger() const = 0;
virtual DatabaseCon& getTxnDB () = 0;
virtual DatabaseCon& getLedgerDB () = 0;
virtual Resource::Manager&
getResourceManager() = 0;
virtual PathRequests&
getPathRequests() = 0;
virtual SHAMapStore&
getSHAMapStore() = 0;
virtual PendingSaves&
pendingSaves() = 0;
virtual AccountIDCache const&
accountIDCache() const = 0;
virtual OpenLedger&
openLedger() = 0;
virtual OpenLedger const&
openLedger() const = 0;
virtual DatabaseCon&
getTxnDB() = 0;
virtual DatabaseCon&
getLedgerDB() = 0;
virtual
std::chrono::milliseconds
getIOLatency () = 0;
virtual std::chrono::milliseconds
getIOLatency() = 0;
virtual bool serverOkay (std::string& reason) = 0;
virtual bool
serverOkay(std::string& reason) = 0;
virtual beast::Journal journal (std::string const& name) = 0;
virtual beast::Journal
journal(std::string const& name) = 0;
/* Returns the number of file descriptors the application needs */
virtual int fdRequired() const = 0;
virtual int
fdRequired() const = 0;
/** Retrieve the "wallet database" */
virtual DatabaseCon& getWalletDB () = 0;
virtual DatabaseCon&
getWalletDB() = 0;
/** Ensure that a newly-started validator does not sign proposals older
* than the last ledger it persisted. */
virtual LedgerIndex getMaxDisallowedLedger() = 0;
virtual LedgerIndex
getMaxDisallowedLedger() = 0;
};
std::unique_ptr <Application>
std::unique_ptr<Application>
make_Application(
std::unique_ptr<Config> config,
std::unique_ptr<Logs> logs,
std::unique_ptr<TimeKeeper> timeKeeper);
}
} // namespace ripple
#endif

View File

@@ -22,17 +22,16 @@
BasicApp::BasicApp(std::size_t numberOfThreads)
{
work_.emplace (io_service_);
work_.emplace(io_service_);
threads_.reserve(numberOfThreads);
while(numberOfThreads--)
while (numberOfThreads--)
{
threads_.emplace_back([this, numberOfThreads]()
{
beast::setCurrentThreadName("io svc #" +
std::to_string(numberOfThreads));
this->io_service_.run();
});
threads_.emplace_back([this, numberOfThreads]() {
beast::setCurrentThreadName(
"io svc #" + std::to_string(numberOfThreads));
this->io_service_.run();
});
}
}

View File

@@ -22,46 +22,47 @@
namespace ripple {
class CollectorManagerImp
: public CollectorManager
class CollectorManagerImp : public CollectorManager
{
public:
beast::Journal m_journal;
beast::insight::Collector::ptr m_collector;
std::unique_ptr <beast::insight::Groups> m_groups;
std::unique_ptr<beast::insight::Groups> m_groups;
CollectorManagerImp (Section const& params,
beast::Journal journal)
: m_journal (journal)
CollectorManagerImp(Section const& params, beast::Journal journal)
: m_journal(journal)
{
std::string const& server = get<std::string> (params, "server");
std::string const& server = get<std::string>(params, "server");
if (server == "statsd")
{
beast::IP::Endpoint const address (beast::IP::Endpoint::from_string (
get<std::string> (params, "address")));
std::string const& prefix (get<std::string> (params, "prefix"));
beast::IP::Endpoint const address(beast::IP::Endpoint::from_string(
get<std::string>(params, "address")));
std::string const& prefix(get<std::string>(params, "prefix"));
m_collector = beast::insight::StatsDCollector::New (address, prefix, journal);
m_collector =
beast::insight::StatsDCollector::New(address, prefix, journal);
}
else
{
m_collector = beast::insight::NullCollector::New ();
m_collector = beast::insight::NullCollector::New();
}
m_groups = beast::insight::make_Groups (m_collector);
m_groups = beast::insight::make_Groups(m_collector);
}
~CollectorManagerImp() = default;
beast::insight::Collector::ptr const& collector () override
beast::insight::Collector::ptr const&
collector() override
{
return m_collector;
}
beast::insight::Group::ptr const& group (std::string const& name) override
beast::insight::Group::ptr const&
group(std::string const& name) override
{
return m_groups->get (name);
return m_groups->get(name);
}
};
@@ -69,10 +70,10 @@ public:
CollectorManager::~CollectorManager() = default;
std::unique_ptr<CollectorManager> CollectorManager::New(Section const& params,
beast::Journal journal)
std::unique_ptr<CollectorManager>
CollectorManager::New(Section const& params, beast::Journal journal)
{
return std::make_unique<CollectorManagerImp>(params, journal);
}
}
} // namespace ripple

View File

@@ -29,15 +29,16 @@ namespace ripple {
class CollectorManager
{
public:
static std::unique_ptr<CollectorManager> New (
Section const& params, beast::Journal journal);
static std::unique_ptr<CollectorManager>
New(Section const& params, beast::Journal journal);
virtual ~CollectorManager () = 0;
virtual beast::insight::Collector::ptr const& collector () = 0;
virtual beast::insight::Group::ptr const& group (
std::string const& name) = 0;
virtual ~CollectorManager() = 0;
virtual beast::insight::Collector::ptr const&
collector() = 0;
virtual beast::insight::Group::ptr const&
group(std::string const& name) = 0;
};
}
} // namespace ripple
#endif

View File

@@ -27,20 +27,17 @@ namespace ripple {
////////////////////////////////////////////////////////////////////////////////
// Ledger database holds ledgers and ledger confirmations
inline constexpr auto LgrDBName {"ledger.db"};
inline constexpr auto LgrDBName{"ledger.db"};
inline constexpr
std::array<char const*, 3> LgrDBPragma {{
"PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;",
"PRAGMA journal_size_limit=1582080;"
}};
inline constexpr std::array<char const*, 3> LgrDBPragma{
{"PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;",
"PRAGMA journal_size_limit=1582080;"}};
inline constexpr
std::array<char const*, 5> LgrDBInit {{
"BEGIN TRANSACTION;",
inline constexpr std::array<char const*, 5> LgrDBInit{
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS Ledgers ( \
"CREATE TABLE IF NOT EXISTS Ledgers ( \
LedgerHash CHARACTER(64) PRIMARY KEY, \
LedgerSeq BIGINT UNSIGNED, \
PrevHash CHARACTER(64), \
@@ -52,40 +49,40 @@ std::array<char const*, 5> LgrDBInit {{
AccountSetHash CHARACTER(64), \
TransSetHash CHARACTER(64) \
);",
"CREATE INDEX IF NOT EXISTS SeqLedger ON Ledgers(LedgerSeq);",
"CREATE INDEX IF NOT EXISTS SeqLedger ON Ledgers(LedgerSeq);",
// Old table and indexes no longer needed
"DROP TABLE IF EXISTS Validations;",
// Old table and indexes no longer needed
"DROP TABLE IF EXISTS Validations;",
"END TRANSACTION;"
}};
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////
// Transaction database holds transactions and public keys
inline constexpr auto TxDBName {"transaction.db"};
inline constexpr auto TxDBName{"transaction.db"};
inline constexpr
#if (ULONG_MAX > UINT_MAX) && !defined (NO_SQLITE_MMAP)
std::array<char const*, 6> TxDBPragma {{
#if (ULONG_MAX > UINT_MAX) && !defined(NO_SQLITE_MMAP)
std::array<char const*, 6>
TxDBPragma
{
{
#else
std::array<char const*, 5> TxDBPragma {{
#endif
"PRAGMA page_size=4096;",
"PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;",
"PRAGMA journal_size_limit=1582080;",
"PRAGMA max_page_count=2147483646;",
#if (ULONG_MAX > UINT_MAX) && !defined (NO_SQLITE_MMAP)
"PRAGMA mmap_size=17179869184;"
"PRAGMA page_size=4096;", "PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;", "PRAGMA journal_size_limit=1582080;",
"PRAGMA max_page_count=2147483646;",
#if (ULONG_MAX > UINT_MAX) && !defined(NO_SQLITE_MMAP)
"PRAGMA mmap_size=17179869184;"
#endif
}};
}
};
inline constexpr
std::array<char const*, 8> TxDBInit {{
"BEGIN TRANSACTION;",
inline constexpr std::array<char const*, 8> TxDBInit{
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS Transactions ( \
"CREATE TABLE IF NOT EXISTS Transactions ( \
TransID CHARACTER(64) PRIMARY KEY, \
TransType CHARACTER(24), \
FromAcct CHARACTER(35), \
@@ -95,131 +92,111 @@ std::array<char const*, 8> TxDBInit {{
RawTxn BLOB, \
TxnMeta BLOB \
);",
"CREATE INDEX IF NOT EXISTS TxLgrIndex ON \
"CREATE INDEX IF NOT EXISTS TxLgrIndex ON \
Transactions(LedgerSeq);",
"CREATE TABLE IF NOT EXISTS AccountTransactions ( \
"CREATE TABLE IF NOT EXISTS AccountTransactions ( \
TransID CHARACTER(64), \
Account CHARACTER(64), \
LedgerSeq BIGINT UNSIGNED, \
TxnSeq INTEGER \
);",
"CREATE INDEX IF NOT EXISTS AcctTxIDIndex ON \
"CREATE INDEX IF NOT EXISTS AcctTxIDIndex ON \
AccountTransactions(TransID);",
"CREATE INDEX IF NOT EXISTS AcctTxIndex ON \
"CREATE INDEX IF NOT EXISTS AcctTxIndex ON \
AccountTransactions(Account, LedgerSeq, TxnSeq, TransID);",
"CREATE INDEX IF NOT EXISTS AcctLgrIndex ON \
"CREATE INDEX IF NOT EXISTS AcctLgrIndex ON \
AccountTransactions(LedgerSeq, Account, TransID);",
"END TRANSACTION;"
}};
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////
// Temporary database used with an incomplete shard that is being acquired
inline constexpr auto AcquireShardDBName {"acquire.db"};
inline constexpr auto AcquireShardDBName{"acquire.db"};
inline constexpr
std::array<char const*, 3> AcquireShardDBPragma {{
"PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;",
"PRAGMA journal_size_limit=1582080;"
}};
inline constexpr std::array<char const*, 3> AcquireShardDBPragma{
{"PRAGMA synchronous=NORMAL;",
"PRAGMA journal_mode=WAL;",
"PRAGMA journal_size_limit=1582080;"}};
inline constexpr
std::array<char const*, 1> AcquireShardDBInit {{
"CREATE TABLE IF NOT EXISTS Shard ( \
inline constexpr std::array<char const*, 1> AcquireShardDBInit{
{"CREATE TABLE IF NOT EXISTS Shard ( \
ShardIndex INTEGER PRIMARY KEY, \
LastLedgerHash CHARACTER(64), \
StoredLedgerSeqs BLOB \
);"
}};
);"}};
////////////////////////////////////////////////////////////////////////////////
// Pragma for Ledger and Transaction databases with complete shards
inline constexpr
std::array<char const*, 2> CompleteShardDBPragma{{
"PRAGMA synchronous=OFF;",
"PRAGMA journal_mode=OFF;"
}};
inline constexpr std::array<char const*, 2> CompleteShardDBPragma{
{"PRAGMA synchronous=OFF;", "PRAGMA journal_mode=OFF;"}};
////////////////////////////////////////////////////////////////////////////////
inline constexpr auto WalletDBName {"wallet.db"};
inline constexpr auto WalletDBName{"wallet.db"};
inline constexpr
std::array<char const*, 6> WalletDBInit {{
"BEGIN TRANSACTION;",
inline constexpr std::array<char const*, 6> WalletDBInit{
{"BEGIN TRANSACTION;",
// A node's identity must be persisted, including
// for clustering purposes. This table holds one
// entry: the server's unique identity, but the
// value can be overriden by specifying a node
// identity in the config file using a [node_seed]
// entry.
"CREATE TABLE IF NOT EXISTS NodeIdentity ( \
// A node's identity must be persisted, including
// for clustering purposes. This table holds one
// entry: the server's unique identity, but the
// value can be overriden by specifying a node
// identity in the config file using a [node_seed]
// entry.
"CREATE TABLE IF NOT EXISTS NodeIdentity ( \
PublicKey CHARACTER(53), \
PrivateKey CHARACTER(52) \
);",
// Peer reservations
"CREATE TABLE IF NOT EXISTS PeerReservations ( \
// Peer reservations
"CREATE TABLE IF NOT EXISTS PeerReservations ( \
PublicKey CHARACTER(53) UNIQUE NOT NULL, \
Description CHARACTER(64) NOT NULL \
);",
// Validator Manifests
"CREATE TABLE IF NOT EXISTS ValidatorManifests ( \
// Validator Manifests
"CREATE TABLE IF NOT EXISTS ValidatorManifests ( \
RawData BLOB NOT NULL \
);",
"CREATE TABLE IF NOT EXISTS PublisherManifests ( \
"CREATE TABLE IF NOT EXISTS PublisherManifests ( \
RawData BLOB NOT NULL \
);",
"END TRANSACTION;"
}};
"END TRANSACTION;"}};
////////////////////////////////////////////////////////////////////////////////
static constexpr auto stateDBName {"state.db"};
static constexpr auto stateDBName{"state.db"};
static constexpr
std::array<char const*, 2> DownloaderDBPragma
{{
"PRAGMA synchronous=FULL;",
"PRAGMA journal_mode=DELETE;"
}};
static constexpr std::array<char const*, 2> DownloaderDBPragma{
{"PRAGMA synchronous=FULL;", "PRAGMA journal_mode=DELETE;"}};
static constexpr
std::array<char const*, 3> ShardArchiveHandlerDBInit
{{
"BEGIN TRANSACTION;",
static constexpr std::array<char const*, 3> ShardArchiveHandlerDBInit{
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS State ( \
"CREATE TABLE IF NOT EXISTS State ( \
ShardIndex INTEGER PRIMARY KEY, \
URL TEXT \
);",
"END TRANSACTION;"
}};
"END TRANSACTION;"}};
static constexpr
std::array<char const*, 3> DatabaseBodyDBInit
{{
"BEGIN TRANSACTION;",
static constexpr std::array<char const*, 3> DatabaseBodyDBInit{
{"BEGIN TRANSACTION;",
"CREATE TABLE IF NOT EXISTS download ( \
"CREATE TABLE IF NOT EXISTS download ( \
Path TEXT, \
Data BLOB, \
Size BIGINT UNSIGNED, \
Part BIGINT UNSIGNED PRIMARY KEY \
);",
"END TRANSACTION;"
}};
"END TRANSACTION;"}};
} // ripple
} // namespace ripple
#endif

View File

@@ -100,15 +100,14 @@ GRPCServerImpl::CallData<Request, Response>::process()
JobType::jtRPC,
"gRPC-Client",
[thisShared](std::shared_ptr<JobQueue::Coro> coro) {
thisShared->process(coro);
});
// If coro is null, then the JobQueue has already been shutdown
if (!coro)
{
grpc::Status status{grpc::StatusCode::INTERNAL,
"Job Queue is already stopped"};
grpc::Status status{
grpc::StatusCode::INTERNAL, "Job Queue is already stopped"};
responder_.FinishWithError(status, this);
}
}
@@ -123,8 +122,9 @@ GRPCServerImpl::CallData<Request, Response>::process(
auto usage = getUsage();
if (usage.disconnect())
{
grpc::Status status{grpc::StatusCode::RESOURCE_EXHAUSTED,
"usage balance exceeds threshhold"};
grpc::Status status{
grpc::StatusCode::RESOURCE_EXHAUSTED,
"usage balance exceeds threshhold"};
responder_.FinishWithError(status, this);
}
else
@@ -133,16 +133,17 @@ GRPCServerImpl::CallData<Request, Response>::process(
usage.charge(loadType);
auto role = getRole();
RPC::GRPCContext<Request> context{{app_.journal("gRPCServer"),
app_,
loadType,
app_.getOPs(),
app_.getLedgerMaster(),
usage,
role,
coro,
InfoSub::pointer()},
request_};
RPC::GRPCContext<Request> context{
{app_.journal("gRPCServer"),
app_,
loadType,
app_.getOPs(),
app_.getLedgerMaster(),
usage,
role,
coro,
InfoSub::pointer()},
request_};
// Make sure we can currently handle the rpc
error_code_i conditionMetRes =
@@ -151,8 +152,9 @@ GRPCServerImpl::CallData<Request, Response>::process(
if (conditionMetRes != rpcSUCCESS)
{
RPC::ErrorInfo errorInfo = RPC::get_error_info(conditionMetRes);
grpc::Status status{grpc::StatusCode::FAILED_PRECONDITION,
errorInfo.message.c_str()};
grpc::Status status{
grpc::StatusCode::FAILED_PRECONDITION,
errorInfo.message.c_str()};
responder_.FinishWithError(status, this);
}
else
@@ -234,13 +236,13 @@ GRPCServerImpl::shutdown()
{
JLOG(journal_.debug()) << "Shutting down";
//The below call cancels all "listeners" (CallData objects that are waiting
//for a request, as opposed to processing a request), and blocks until all
//requests being processed are completed. CallData objects in the midst of
//processing requests need to actually send data back to the client, via
//responder_.Finish(...) or responder_.FinishWithError(...), for this call
//to unblock. Each cancelled listener is returned via cq_.Next(...) with ok
//set to false
// The below call cancels all "listeners" (CallData objects that are waiting
// for a request, as opposed to processing a request), and blocks until all
// requests being processed are completed. CallData objects in the midst of
// processing requests need to actually send data back to the client, via
// responder_.Finish(...) or responder_.FinishWithError(...), for this call
// to unblock. Each cancelled listener is returned via cq_.Next(...) with ok
// set to false
server_->Shutdown();
JLOG(journal_.debug()) << "Server has been shutdown";
@@ -249,7 +251,6 @@ GRPCServerImpl::shutdown()
// queue have been processed. See handleRpcs() for more details.
cq_->Shutdown();
JLOG(journal_.debug()) << "Completion Queue has been shutdown";
}
void
@@ -292,13 +293,12 @@ GRPCServerImpl::handleRpcs()
{
auto ptr = static_cast<Processor*>(tag);
JLOG(journal_.trace()) << "Processing CallData object."
<< " ptr = " << ptr
<< " ok = " << ok;
<< " ptr = " << ptr << " ok = " << ok;
if (!ok)
{
JLOG(journal_.debug()) << "Request listener cancelled. "
<< "Destroying object";
<< "Destroying object";
erase(ptr);
}
else
@@ -315,7 +315,6 @@ GRPCServerImpl::handleRpcs()
}
else
{
JLOG(journal_.debug()) << "Sent response. Destroying object";
erase(ptr);
}
@@ -335,13 +334,16 @@ GRPCServerImpl::setupListeners()
};
{
using cd = CallData<org::xrpl::rpc::v1::GetFeeRequest, org::xrpl::rpc::v1::GetFeeResponse>;
using cd = CallData<
org::xrpl::rpc::v1::GetFeeRequest,
org::xrpl::rpc::v1::GetFeeResponse>;
addToRequests(std::make_shared<cd>(
service_,
*cq_,
app_,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetFee,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
RequestGetFee,
doFeeGrpc,
RPC::NEEDS_CURRENT_LEDGER,
Resource::feeReferenceRPC));
@@ -355,7 +357,8 @@ GRPCServerImpl::setupListeners()
service_,
*cq_,
app_,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetAccountInfo,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
RequestGetAccountInfo,
doAccountInfoGrpc,
RPC::NO_CONDITION,
Resource::feeReferenceRPC));
@@ -369,7 +372,8 @@ GRPCServerImpl::setupListeners()
service_,
*cq_,
app_,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::RequestGetTransaction,
&org::xrpl::rpc::v1::XRPLedgerAPIService::AsyncService::
RequestGetTransaction,
doTxGrpc,
RPC::NEEDS_CURRENT_LEDGER,
Resource::feeReferenceRPC));

View File

@@ -17,93 +17,101 @@
*/
//==============================================================================
#include <ripple/app/main/LoadManager.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/main/LoadManager.h>
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/basics/UptimeClock.h>
#include <ripple/json/to_string.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/json/to_string.h>
#include <memory>
#include <mutex>
#include <thread>
namespace ripple {
LoadManager::LoadManager (
Application& app, Stoppable& parent, beast::Journal journal)
: Stoppable ("LoadManager", parent)
, app_ (app)
, journal_ (journal)
, deadLock_ ()
, armed_ (false)
, stop_ (false)
LoadManager::LoadManager(
Application& app,
Stoppable& parent,
beast::Journal journal)
: Stoppable("LoadManager", parent)
, app_(app)
, journal_(journal)
, deadLock_()
, armed_(false)
, stop_(false)
{
}
LoadManager::~LoadManager ()
LoadManager::~LoadManager()
{
try
{
onStop ();
onStop();
}
catch (std::exception const& ex)
{
// Swallow the exception in a destructor.
JLOG(journal_.warn()) << "std::exception in ~LoadManager. "
<< ex.what();
JLOG(journal_.warn())
<< "std::exception in ~LoadManager. " << ex.what();
}
}
//------------------------------------------------------------------------------
void LoadManager::activateDeadlockDetector ()
void
LoadManager::activateDeadlockDetector()
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
armed_ = true;
deadLock_ = std::chrono::steady_clock::now();
}
void LoadManager::resetDeadlockDetector ()
void
LoadManager::resetDeadlockDetector()
{
auto const detector_start = std::chrono::steady_clock::now();
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
deadLock_ = detector_start;
}
//------------------------------------------------------------------------------
void LoadManager::onPrepare ()
void
LoadManager::onPrepare()
{
}
void LoadManager::onStart ()
void
LoadManager::onStart()
{
JLOG(journal_.debug()) << "Starting";
assert (! thread_.joinable());
assert(!thread_.joinable());
thread_ = std::thread {&LoadManager::run, this};
thread_ = std::thread{&LoadManager::run, this};
}
void LoadManager::onStop ()
void
LoadManager::onStop()
{
if (thread_.joinable())
{
JLOG(journal_.debug()) << "Stopping";
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
stop_ = true;
}
thread_.join();
}
stopped ();
stopped();
}
//------------------------------------------------------------------------------
void LoadManager::run ()
void
LoadManager::run()
{
beast::setCurrentThreadName ("LoadManager");
beast::setCurrentThreadName("LoadManager");
using namespace std::chrono_literals;
using clock_type = std::chrono::system_clock;
@@ -111,11 +119,11 @@ void LoadManager::run ()
auto t = clock_type::now();
bool stop = false;
while (! (stop || isStopping ()))
while (!(stop || isStopping()))
{
{
// Copy out shared data under a lock. Use copies outside lock.
std::unique_lock<std::mutex> sl (mutex_);
std::unique_lock<std::mutex> sl(mutex_);
auto const deadLock = deadLock_;
auto const armed = armed_;
stop = stop_;
@@ -131,8 +139,8 @@ void LoadManager::run ()
constexpr auto deadlockLogicErrorTimeLimit = 600s;
if (armed && (timeSpentDeadlocked >= reportingIntervalSeconds))
{
// Report the deadlocked condition every reportingIntervalSeconds
// Report the deadlocked condition every
// reportingIntervalSeconds
if ((timeSpentDeadlocked % reportingIntervalSeconds) == 0s)
{
if (timeSpentDeadlocked < deadlockFatalLogMessageTimeLimit)
@@ -154,9 +162,9 @@ void LoadManager::run ()
}
}
// If we go over the deadlockTimeLimit spent deadlocked, it means that
// the deadlock resolution code has failed, which qualifies
// as undefined behavior.
// If we go over the deadlockTimeLimit spent deadlocked, it
// means that the deadlock resolution code has failed, which
// qualifies as undefined behavior.
//
if (timeSpentDeadlocked >= deadlockLogicErrorTimeLimit)
{
@@ -173,21 +181,21 @@ void LoadManager::run ()
}
bool change = false;
if (app_.getJobQueue ().isOverloaded ())
if (app_.getJobQueue().isOverloaded())
{
JLOG(journal_.info()) << app_.getJobQueue ().getJson (0);
change = app_.getFeeTrack ().raiseLocalFee ();
JLOG(journal_.info()) << app_.getJobQueue().getJson(0);
change = app_.getFeeTrack().raiseLocalFee();
}
else
{
change = app_.getFeeTrack ().lowerLocalFee ();
change = app_.getFeeTrack().lowerLocalFee();
}
if (change)
{
// VFALCO TODO replace this with a Listener / observer and
// subscribe in NetworkOPs or Application.
app_.getOPs ().reportFeeChange ();
app_.getOPs().reportFeeChange();
}
t += 1s;
@@ -204,16 +212,15 @@ void LoadManager::run ()
}
}
stopped ();
stopped();
}
//------------------------------------------------------------------------------
std::unique_ptr<LoadManager>
make_LoadManager (Application& app,
Stoppable& parent, beast::Journal journal)
make_LoadManager(Application& app, Stoppable& parent, beast::Journal journal)
{
return std::unique_ptr<LoadManager>{new LoadManager{app, parent, journal}};
}
} // ripple
} // namespace ripple

View File

@@ -42,18 +42,19 @@ class Application;
*/
class LoadManager : public Stoppable
{
LoadManager (Application& app, Stoppable& parent, beast::Journal journal);
LoadManager(Application& app, Stoppable& parent, beast::Journal journal);
public:
LoadManager () = delete;
LoadManager (LoadManager const&) = delete;
LoadManager& operator=(LoadManager const&) = delete;
LoadManager() = delete;
LoadManager(LoadManager const&) = delete;
LoadManager&
operator=(LoadManager const&) = delete;
/** Destroy the manager.
The destructor returns only after the thread has stopped.
*/
~LoadManager ();
~LoadManager();
/** Turn on deadlock detection.
@@ -67,47 +68,55 @@ public:
// to prevent it from going off during program startup if
// there's a lengthy initialization operation taking place?
//
void activateDeadlockDetector ();
void
activateDeadlockDetector();
/** Reset the deadlock detection timer.
A dedicated thread monitors the deadlock timer, and if too much
time passes it will produce log warnings.
*/
void resetDeadlockDetector ();
void
resetDeadlockDetector();
//--------------------------------------------------------------------------
// Stoppable members
void onPrepare () override;
void
onPrepare() override;
void onStart () override;
void
onStart() override;
void onStop () override;
void
onStop() override;
private:
void run ();
void
run();
private:
Application& app_;
beast::Journal const journal_;
std::thread thread_;
std::mutex mutex_; // Guards deadLock_, armed_, and stop_.
std::mutex mutex_; // Guards deadLock_, armed_, and stop_.
std::chrono::steady_clock::time_point deadLock_; // Detect server deadlocks.
std::chrono::steady_clock::time_point
deadLock_; // Detect server deadlocks.
bool armed_;
bool stop_;
friend
std::unique_ptr<LoadManager>
make_LoadManager(Application& app, Stoppable& parent, beast::Journal journal);
friend std::unique_ptr<LoadManager>
make_LoadManager(
Application& app,
Stoppable& parent,
beast::Journal journal);
};
std::unique_ptr<LoadManager>
make_LoadManager (
Application& app, Stoppable& parent, beast::Journal journal);
make_LoadManager(Application& app, Stoppable& parent, beast::Journal journal);
} // ripple
} // namespace ripple
#endif

View File

@@ -17,25 +17,24 @@
*/
//==============================================================================
#include <ripple/basics/Log.h>
#include <ripple/protocol/digest.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/main/DBInit.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/Sustain.h>
#include <ripple/basics/contract.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <ripple/core/Config.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/TimeKeeper.h>
#include <ripple/json/to_string.h>
#include <ripple/net/RPCCall.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/protocol/digest.h>
#include <ripple/resource/Fees.h>
#include <ripple/rpc/RPCHandler.h>
#include <ripple/protocol/BuildInfo.h>
#include <ripple/beast/clock/basic_seconds_clock.h>
#include <ripple/beast/core/CurrentThreadName.h>
#include <beast/unit_test/match.hpp>
#include <test/unit_test/multi_runner.h>
@@ -43,18 +42,18 @@
#include <google/protobuf/stubs/common.h>
#include <boost/filesystem.hpp>
#include <boost/predef.h>
#include <boost/process.hpp>
#include <boost/program_options.hpp>
#include <boost/predef.h>
#include <cstdlib>
#include <iostream>
#include <utility>
#include <stdexcept>
#include <utility>
#if BOOST_OS_WINDOWS
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/types.h>
#endif
// Do we know the plaform we're compiling on? If you're adding new platforms
@@ -64,9 +63,9 @@
#endif
// Ensure that precisely one platform is detected.
#if (BOOST_OS_LINUX && (BOOST_OS_WINDOWS || BOOST_OS_MACOS)) || \
(BOOST_OS_MACOS && (BOOST_OS_WINDOWS || BOOST_OS_LINUX)) || \
(BOOST_OS_WINDOWS && (BOOST_OS_LINUX || BOOST_OS_MACOS))
#if (BOOST_OS_LINUX && (BOOST_OS_WINDOWS || BOOST_OS_MACOS)) || \
(BOOST_OS_MACOS && (BOOST_OS_WINDOWS || BOOST_OS_LINUX)) || \
(BOOST_OS_WINDOWS && (BOOST_OS_LINUX || BOOST_OS_MACOS))
#error Multiple supported platforms appear active at once
#endif
@@ -105,15 +104,12 @@ adjustDescriptorLimit(int needed, beast::Journal j)
if (needed > available)
{
j.fatal() <<
"Insufficient number of file descriptors: " <<
needed << " are needed, but only " <<
available << " are available.";
j.fatal() << "Insufficient number of file descriptors: " << needed
<< " are needed, but only " << available << " are available.";
std::cerr <<
"Insufficient number of file descriptors: " <<
needed << " are needed, but only " <<
available << " are available.\n";
std::cerr << "Insufficient number of file descriptors: " << needed
<< " are needed, but only " << available
<< " are available.\n";
return false;
}
@@ -122,30 +118,37 @@ adjustDescriptorLimit(int needed, beast::Journal j)
return true;
}
void printHelp (const po::options_description& desc)
void
printHelp(const po::options_description& desc)
{
std::cerr
<< systemName () << "d [options] <command> <params>\n"
<< systemName() << "d [options] <command> <params>\n"
<< desc << std::endl
<< "Commands: \n"
" account_currencies <account> [<ledger>] [strict]\n"
" account_info <account>|<seed>|<pass_phrase>|<key> [<ledger>] [strict]\n"
" account_info <account>|<seed>|<pass_phrase>|<key> [<ledger>] "
"[strict]\n"
" account_lines <account> <account>|\"\" [<ledger>]\n"
" account_channels <account> <account>|\"\" [<ledger>]\n"
" account_objects <account> [<ledger>] [strict]\n"
" account_offers <account>|<account_public_key> [<ledger>] [strict]\n"
" account_tx accountID [ledger_min [ledger_max [limit [offset]]]] [binary] [count] [descending]\n"
" book_offers <taker_pays> <taker_gets> [<taker [<ledger> [<limit> [<proof> [<marker>]]]]]\n"
" account_offers <account>|<account_public_key> [<ledger>] "
"[strict]\n"
" account_tx accountID [ledger_min [ledger_max [limit "
"[offset]]]] [binary] [count] [descending]\n"
" book_offers <taker_pays> <taker_gets> [<taker [<ledger> "
"[<limit> [<proof> [<marker>]]]]]\n"
" can_delete [<ledgerid>|<ledgerhash>|now|always|never]\n"
" channel_authorize <private_key> <channel_id> <drops>\n"
" channel_verify <public_key> <channel_id> <drops> <signature>\n"
" connect <ip> [<port>]\n"
" consensus_info\n"
" deposit_authorized <source_account> <destination_account> [<ledger>]\n"
" deposit_authorized <source_account> <destination_account> "
"[<ledger>]\n"
" download_shard [[<index> <url>]]\n"
" feature [<feature> [accept|reject]]\n"
" fetch_info [clear]\n"
" gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ <hotwallet> ]]\n"
" gateway_balances [<ledger>] <issuer_account> [ <hotwallet> [ "
"<hotwallet> ]]\n"
" get_counts\n"
" json <method> <json>\n"
" ledger [<id>|current|closed|validated] [full]\n"
@@ -167,7 +170,8 @@ void printHelp (const po::options_description& desc)
" server_info [counters]\n"
" server_state [counters]\n"
" sign <private_key> <tx_json> [offline]\n"
" sign_for <signer_address> <signer_private_key> <tx_json> [offline]\n"
" sign_for <signer_address> <signer_private_key> <tx_json> "
"[offline]\n"
" stop\n"
" submit <tx_blob>|[<private_key> <tx_json>]\n"
" submit_multisigned <tx_json>\n"
@@ -188,21 +192,19 @@ class multi_selector
{
private:
std::vector<beast::unit_test::selector> selectors_;
public:
explicit
multi_selector(std::string const& patterns = "")
explicit multi_selector(std::string const& patterns = "")
{
std::vector<std::string> v;
boost::split (v, patterns, boost::algorithm::is_any_of (","));
boost::split(v, patterns, boost::algorithm::is_any_of(","));
selectors_.reserve(v.size());
std::for_each(v.begin(), v.end(),
[this](std::string s)
{
boost::trim (s);
if (selectors_.empty() || !s.empty())
selectors_.emplace_back(
beast::unit_test::selector::automatch, s);
});
std::for_each(v.begin(), v.end(), [this](std::string s) {
boost::trim(s);
if (selectors_.empty() || !s.empty())
selectors_.emplace_back(
beast::unit_test::selector::automatch, s);
});
}
bool
@@ -215,9 +217,12 @@ public:
}
};
namespace test{ extern std::atomic<bool> envUseIPv4; }
namespace test {
extern std::atomic<bool> envUseIPv4;
}
static int runUnitTests(
static int
runUnitTests(
std::string const& pattern,
std::string const& argument,
bool quiet,
@@ -231,7 +236,7 @@ static int runUnitTests(
using namespace beast::unit_test;
using namespace ripple::test;
ripple::test::envUseIPv4 = (! ipv6);
ripple::test::envUseIPv4 = (!ipv6);
if (!child && num_jobs == 1)
{
@@ -264,7 +269,7 @@ static int runUnitTests(
boost::process::exe = exe_name, boost::process::args = args);
int bad_child_exits = 0;
for(auto& c : children)
for (auto& c : children)
{
try
{
@@ -298,21 +303,22 @@ static int runUnitTests(
//------------------------------------------------------------------------------
int run (int argc, char** argv)
int
run(int argc, char** argv)
{
using namespace std;
beast::setCurrentThreadName ("rippled: main");
beast::setCurrentThreadName("rippled: main");
po::variables_map vm;
std::string importText;
{
importText += "Import an existing node database (specified in the [";
importText += ConfigSection::importNodeDatabase ();
importText += ConfigSection::importNodeDatabase();
importText += "] configuration file section) into the current ";
importText += "node database (specified in the [";
importText += ConfigSection::nodeDatabase ();
importText += ConfigSection::nodeDatabase();
importText += "] configuration file section).";
}
std::string shardsText;
@@ -324,90 +330,97 @@ int run (int argc, char** argv)
// Set up option parsing.
//
po::options_description gen ("General Options");
gen.add_options ()
("conf", po::value<std::string> (), "Specify the configuration file.")
("debug", "Enable normally suppressed debug logging")
("fg", "Run in the foreground.")
("help,h", "Display this message.")
("quorum", po::value <std::size_t> (),
"Override the minimum validation quorum.")
("silent", "No output to the console after startup.")
("standalone,a", "Run with no peers.")
("verbose,v", "Verbose logging.")
("version", "Display the build version.")
;
po::options_description gen("General Options");
gen.add_options()(
"conf", po::value<std::string>(), "Specify the configuration file.")(
"debug", "Enable normally suppressed debug logging")(
"fg", "Run in the foreground.")("help,h", "Display this message.")(
"quorum",
po::value<std::size_t>(),
"Override the minimum validation quorum.")(
"silent", "No output to the console after startup.")(
"standalone,a", "Run with no peers.")("verbose,v", "Verbose logging.")(
"version", "Display the build version.");
po::options_description data ("Ledger/Data Options");
data.add_options ()
("import", importText.c_str ())
("ledger", po::value<std::string> (),
"Load the specified ledger and start from the value given.")
("ledgerfile", po::value<std::string> (), "Load the specified ledger file.")
("load", "Load the current ledger from the local DB.")
("net", "Get the initial ledger from the network.")
("nodetoshard", "Import node store into shards")
("replay","Replay a ledger close.")
("start", "Start from a fresh Ledger.")
("vacuum", po::value<std::string>(),
po::options_description data("Ledger/Data Options");
data.add_options()("import", importText.c_str())(
"ledger",
po::value<std::string>(),
"Load the specified ledger and start from the value given.")(
"ledgerfile",
po::value<std::string>(),
"Load the specified ledger file.")(
"load", "Load the current ledger from the local DB.")(
"net", "Get the initial ledger from the network.")(
"nodetoshard", "Import node store into shards")(
"replay", "Replay a ledger close.")(
"start", "Start from a fresh Ledger.")(
"vacuum",
po::value<std::string>(),
"VACUUM the transaction db. Mandatory string argument specifies "
"temporary directory path.")
("valid", "Consider the initial ledger a valid network ledger.")
("validateShards", shardsText.c_str ())
;
"temporary directory path.")(
"valid", "Consider the initial ledger a valid network ledger.")(
"validateShards", shardsText.c_str());
po::options_description rpc ("RPC Client Options");
rpc.add_options()
("rpc",
po::options_description rpc("RPC Client Options");
rpc.add_options()(
"rpc",
"Perform rpc command - see below for available commands. "
"This is assumed if any positional parameters are provided.")
("rpc_ip", po::value <std::string> (),
"This is assumed if any positional parameters are provided.")(
"rpc_ip",
po::value<std::string>(),
"Specify the IP address for RPC command. "
"Format: <ip-address>[':'<port-number>]")
("rpc_port", po::value <std::uint16_t> (),
"Format: <ip-address>[':'<port-number>]")(
"rpc_port",
po::value<std::uint16_t>(),
"DEPRECATED: include with rpc_ip instead. "
"Specify the port number for RPC command.")
;
"Specify the port number for RPC command.");
po::options_description test ("Unit Test Options");
test.add_options()
("quiet,q",
po::options_description test("Unit Test Options");
test.add_options()(
"quiet,q",
"Suppress test suite messages, "
"including suite/case name (at start) and test log messages.")
("unittest,u", po::value <std::string> ()->implicit_value (""),
"including suite/case name (at start) and test log messages.")(
"unittest,u",
po::value<std::string>()->implicit_value(""),
"Perform unit tests. The optional argument specifies one or "
"more comma-separated selectors. Each selector specifies a suite name, "
"full-name (lib.module.suite), module, or library "
"(checked in that ""order).")
("unittest-arg", po::value <std::string> ()->implicit_value (""),
"(checked in that "
"order).")(
"unittest-arg",
po::value<std::string>()->implicit_value(""),
"Supplies an argument string to unit tests. If provided, this argument "
"is made available to each suite that runs. Interpretation of the "
"argument is handled individually by any suite that accesses it -- "
"as such, it typically only make sense to provide this when running "
"a single suite.")
("unittest-ipv6", "Use IPv6 localhost when running unittests (default is IPv4).")
("unittest-log",
"a single suite.")(
"unittest-ipv6",
"Use IPv6 localhost when running unittests (default is IPv4).")(
"unittest-log",
"Force unit test log message output. Only useful in combination with "
"--quiet, in which case log messages will print but suite/case names "
"will not.")
("unittest-jobs", po::value <std::size_t> (),
"Number of unittest jobs to run in parallel (child processes).")
;
"will not.")(
"unittest-jobs",
po::value<std::size_t>(),
"Number of unittest jobs to run in parallel (child processes).");
// These are hidden options, not intended to be shown in the usage/help message
po::options_description hidden ("Hidden Options");
hidden.add_options()
("parameters", po::value< vector<string> > (),
// These are hidden options, not intended to be shown in the usage/help
// message
po::options_description hidden("Hidden Options");
hidden.add_options()(
"parameters",
po::value<vector<string>>(),
"Specify rpc command and parameters. This option must be repeated "
"for each command/param. Positional parameters also serve this purpose, "
"so this option is not needed for users")
("unittest-child",
"For internal use only when spawning child unit test processes.")
;
"for each command/param. Positional parameters also serve this "
"purpose, "
"so this option is not needed for users")(
"unittest-child",
"For internal use only when spawning child unit test processes.");
// Interpret positional arguments as --parameters.
po::positional_options_description p;
p.add ("parameters", -1);
p.add("parameters", -1);
po::options_description all;
all.add(gen).add(rpc).add(data).add(test).add(hidden);
@@ -418,12 +431,13 @@ int run (int argc, char** argv)
// Parse options, if no error.
try
{
po::store (po::command_line_parser (argc, argv)
.options (all) // Parse options.
.positional (p) // Remainder as --parameters.
.run (),
po::store(
po::command_line_parser(argc, argv)
.options(all) // Parse options.
.positional(p) // Remainder as --parameters.
.run(),
vm);
po::notify (vm); // Invoke option notify functions.
po::notify(vm); // Invoke option notify functions.
}
catch (std::exception const&)
{
@@ -432,23 +446,23 @@ int run (int argc, char** argv)
return 1;
}
if (vm.count ("help"))
if (vm.count("help"))
{
printHelp (desc);
printHelp(desc);
return 0;
}
if (vm.count ("version"))
if (vm.count("version"))
{
std::cout << "rippled version " <<
BuildInfo::getVersionString () << std::endl;
std::cout << "rippled version " << BuildInfo::getVersionString()
<< std::endl;
return 0;
}
// Run the unit tests if requested.
// The unit tests will exit the application with an appropriate return code.
//
if (vm.count ("unittest"))
if (vm.count("unittest"))
{
std::string argument;
@@ -459,14 +473,15 @@ int run (int argc, char** argv)
bool unittestChild = false;
if (vm.count("unittest-jobs"))
numJobs = std::max(numJobs, vm["unittest-jobs"].as<std::size_t>());
unittestChild = bool (vm.count("unittest-child"));
unittestChild = bool(vm.count("unittest-child"));
return runUnitTests(
vm["unittest"].as<std::string>(), argument,
bool (vm.count ("quiet")),
bool (vm.count ("unittest-log")),
vm["unittest"].as<std::string>(),
argument,
bool(vm.count("quiet")),
bool(vm.count("unittest-log")),
unittestChild,
bool (vm.count ("unittest-ipv6")),
bool(vm.count("unittest-ipv6")),
numJobs,
argc,
argv);
@@ -476,20 +491,25 @@ int run (int argc, char** argv)
if (vm.count("unittest-jobs"))
{
// unittest jobs only makes sense with `unittest`
std::cerr << "rippled: '--unittest-jobs' specified without '--unittest'.\n";
std::cerr << "To run the unit tests the '--unittest' option must be present.\n";
std::cerr << "rippled: '--unittest-jobs' specified without "
"'--unittest'.\n";
std::cerr << "To run the unit tests the '--unittest' option must "
"be present.\n";
return 1;
}
}
auto config = std::make_unique<Config>();
auto configFile = vm.count ("conf") ?
vm["conf"].as<std::string> () : std::string();
auto configFile =
vm.count("conf") ? vm["conf"].as<std::string>() : std::string();
// config file, quiet flag.
config->setup (configFile, bool (vm.count ("quiet")),
bool(vm.count("silent")), bool(vm.count("standalone")));
config->setup(
configFile,
bool(vm.count("quiet")),
bool(vm.count("silent")),
bool(vm.count("standalone")));
if (vm.count("vacuum"))
{
@@ -516,8 +536,7 @@ int run (int argc, char** argv)
"as much free space as the size of "
<< dbPath.string() << ", which is " << dbSize
<< " bytes. The filesystem for " << tmpPath.string()
<< " only has "
<< space(tmpPath).available
<< " only has " << space(tmpPath).available
<< " bytes.\n";
return -1;
}
@@ -529,71 +548,71 @@ int run (int argc, char** argv)
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM beginning. page_size: " <<
pageSize << std::endl;
std::cout << "VACUUM beginning. page_size: " << pageSize
<< std::endl;
session << "PRAGMA journal_mode=OFF;";
session << "PRAGMA temp_store_directory=\"" <<
tmpPath.string() << "\";";
session << "PRAGMA temp_store_directory=\"" << tmpPath.string()
<< "\";";
session << "VACUUM;";
session << "PRAGMA journal_mode=WAL;";
session << "PRAGMA page_size;", soci::into(pageSize);
std::cout << "VACUUM finished. page_size: " <<
pageSize << std::endl;
std::cout << "VACUUM finished. page_size: " << pageSize
<< std::endl;
}
catch (std::exception const& e)
{
std::cerr << "exception " << e.what() <<
" in function " << __func__ << std::endl;
std::cerr << "exception " << e.what() << " in function " << __func__
<< std::endl;
return -1;
}
return 0;
}
if (vm.count ("start"))
if (vm.count("start"))
config->START_UP = Config::FRESH;
if (vm.count ("import"))
if (vm.count("import"))
config->doImport = true;
if (vm.count("nodetoshard"))
config->nodeToShard = true;
if (vm.count ("validateShards"))
if (vm.count("validateShards"))
config->validateShards = true;
if (vm.count ("ledger"))
if (vm.count("ledger"))
{
config->START_LEDGER = vm["ledger"].as<std::string> ();
config->START_LEDGER = vm["ledger"].as<std::string>();
if (vm.count("replay"))
config->START_UP = Config::REPLAY;
else
config->START_UP = Config::LOAD;
}
else if (vm.count ("ledgerfile"))
else if (vm.count("ledgerfile"))
{
config->START_LEDGER = vm["ledgerfile"].as<std::string> ();
config->START_LEDGER = vm["ledgerfile"].as<std::string>();
config->START_UP = Config::LOAD_FILE;
}
else if (vm.count ("load"))
else if (vm.count("load"))
{
config->START_UP = Config::LOAD;
}
if (vm.count ("valid"))
if (vm.count("valid"))
{
config->START_VALID = true;
}
if (vm.count ("net"))
if (vm.count("net"))
{
if ((config->START_UP == Config::LOAD) ||
(config->START_UP == Config::REPLAY))
{
std::cerr <<
"Net and load/reply options are incompatible" << std::endl;
std::cerr << "Net and load/reply options are incompatible"
<< std::endl;
return -1;
}
@@ -602,31 +621,31 @@ int run (int argc, char** argv)
// Override the RPC destination IP address. This must
// happen after the config file is loaded.
if (vm.count ("rpc_ip"))
if (vm.count("rpc_ip"))
{
auto endpoint = beast::IP::Endpoint::from_string_checked(
vm["rpc_ip"].as<std::string>());
if (! endpoint)
if (!endpoint)
{
std::cerr << "Invalid rpc_ip = " <<
vm["rpc_ip"].as<std::string>() << "\n";
std::cerr << "Invalid rpc_ip = " << vm["rpc_ip"].as<std::string>()
<< "\n";
return -1;
}
if (endpoint->port() == 0)
{
std::cerr << "No port specified in rpc_ip.\n";
if (vm.count ("rpc_port"))
if (vm.count("rpc_port"))
{
std::cerr << "WARNING: using deprecated rpc_port param.\n";
try
{
endpoint = endpoint->at_port(
vm["rpc_port"].as<std::uint16_t>());
endpoint =
endpoint->at_port(vm["rpc_port"].as<std::uint16_t>());
if (endpoint->port() == 0)
throw std::domain_error("0");
}
catch(std::exception const& e)
catch (std::exception const& e)
{
std::cerr << "Invalid rpc_port = " << e.what() << "\n";
return -1;
@@ -639,20 +658,20 @@ int run (int argc, char** argv)
config->rpc_ip = std::move(*endpoint);
}
if (vm.count ("quorum"))
if (vm.count("quorum"))
{
try
{
config->VALIDATION_QUORUM = vm["quorum"].as <std::size_t> ();
config->VALIDATION_QUORUM = vm["quorum"].as<std::size_t>();
if (config->VALIDATION_QUORUM == std::size_t{})
{
throw std::domain_error("0");
}
}
catch(std::exception const& e)
catch (std::exception const& e)
{
std::cerr << "Invalid value specified for --quorum ("
<< e.what() << ")\n";
std::cerr << "Invalid value specified for --quorum (" << e.what()
<< ")\n";
return -1;
}
}
@@ -661,25 +680,27 @@ int run (int argc, char** argv)
using namespace beast::severities;
Severity thresh = kInfo;
if (vm.count ("quiet"))
if (vm.count("quiet"))
thresh = kFatal;
else if (vm.count ("verbose"))
else if (vm.count("verbose"))
thresh = kTrace;
auto logs = std::make_unique<Logs>(thresh);
// No arguments. Run server.
if (!vm.count ("parameters"))
if (!vm.count("parameters"))
{
// TODO: this comment can be removed in a future release -
// say 1.7 or higher
if (config->had_trailing_comments())
{
JLOG(logs->journal("Application").warn()) <<
"Trailing comments were seen in your config file. " <<
"The treatment of inline/trailing comments has changed recently. " <<
"Any `#` characters NOT intended to delimit comments should be " <<
"preceded by a \\";
JLOG(logs->journal("Application").warn())
<< "Trailing comments were seen in your config file. "
<< "The treatment of inline/trailing comments has changed "
"recently. "
<< "Any `#` characters NOT intended to delimit comments should "
"be "
<< "preceded by a \\";
}
// We want at least 1024 file descriptors. We'll
@@ -687,29 +708,25 @@ int run (int argc, char** argv)
if (!adjustDescriptorLimit(1024, logs->journal("Application")))
return -1;
if (HaveSustain() && !vm.count ("fg") && !config->standalone())
if (HaveSustain() && !vm.count("fg") && !config->standalone())
{
auto const ret = DoSustain ();
auto const ret = DoSustain();
if (!ret.empty ())
if (!ret.empty())
std::cerr << "Watchdog: " << ret << std::endl;
}
if (vm.count ("debug"))
if (vm.count("debug"))
{
setDebugLogSink (logs->makeSink (
"Debug", beast::severities::kTrace));
setDebugLogSink(logs->makeSink("Debug", beast::severities::kTrace));
}
auto timeKeeper = make_TimeKeeper(
logs->journal("TimeKeeper"));
auto timeKeeper = make_TimeKeeper(logs->journal("TimeKeeper"));
auto app = make_Application(
std::move(config),
std::move(logs),
std::move(timeKeeper));
std::move(config), std::move(logs), std::move(timeKeeper));
if (!app->setup ())
if (!app->setup())
{
StopSustain();
return -1;
@@ -718,8 +735,7 @@ int run (int argc, char** argv)
// With our configuration parsed, ensure we have
// enough file descriptors available:
if (!adjustDescriptorLimit(
app->fdRequired(),
app->logs().journal("Application")))
app->fdRequired(), app->logs().journal("Application")))
{
StopSustain();
return -1;
@@ -735,18 +751,17 @@ int run (int argc, char** argv)
}
// We have an RPC command to process:
beast::setCurrentThreadName ("rippled: rpc");
return RPCCall::fromCommandLine (
*config,
vm["parameters"].as<std::vector<std::string>>(),
*logs);
beast::setCurrentThreadName("rippled: rpc");
return RPCCall::fromCommandLine(
*config, vm["parameters"].as<std::vector<std::string>>(), *logs);
}
} // ripple
} // namespace ripple
// Must be outside the namespace for obvious reasons
//
int main (int argc, char** argv)
int
main(int argc, char** argv)
{
#if BOOST_OS_WINDOWS
{
@@ -758,18 +773,18 @@ int main (int argc, char** argv)
// coroutines. At the time of this writing the _ftime call is
// used to initialize the timezone information.
struct _timeb t;
#ifdef _INC_TIME_INL
_ftime_s (&t);
#else
_ftime (&t);
#endif
#ifdef _INC_TIME_INL
_ftime_s(&t);
#else
_ftime(&t);
#endif
}
ripple::sha512_deprecatedMSVCWorkaround();
#endif
atexit(&google::protobuf::ShutdownProtobufLibrary);
auto const result (ripple::run (argc, argv));
auto const result(ripple::run(argc, argv));
beast::basic_seconds_clock_main_hook();

View File

@@ -17,19 +17,19 @@
*/
//==============================================================================
#include <ripple/core/DatabaseCon.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/main/NodeIdentity.h>
#include <ripple/basics/Log.h>
#include <ripple/core/Config.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/core/DatabaseCon.h>
#include <boost/format.hpp>
#include <boost/optional.hpp>
namespace ripple {
std::pair<PublicKey, SecretKey>
loadNodeIdentity (Application& app)
loadNodeIdentity(Application& app)
{
// If a seed is specified in the configuration file use that directly.
if (app.config().exists(SECTION_NODE_SEED))
@@ -38,31 +38,29 @@ loadNodeIdentity (Application& app)
app.config().section(SECTION_NODE_SEED).lines().front());
if (!seed)
Throw<std::runtime_error>(
"NodeIdentity: Bad [" SECTION_NODE_SEED "] specified");
Throw<std::runtime_error>("NodeIdentity: Bad [" SECTION_NODE_SEED
"] specified");
auto secretKey =
generateSecretKey (KeyType::secp256k1, *seed);
auto publicKey =
derivePublicKey (KeyType::secp256k1, secretKey);
auto secretKey = generateSecretKey(KeyType::secp256k1, *seed);
auto publicKey = derivePublicKey(KeyType::secp256k1, secretKey);
return { publicKey, secretKey };
return {publicKey, secretKey};
}
// Try to load a node identity from the database:
boost::optional<PublicKey> publicKey;
boost::optional<SecretKey> secretKey;
auto db = app.getWalletDB ().checkoutDb ();
auto db = app.getWalletDB().checkoutDb();
{
boost::optional<std::string> pubKO, priKO;
soci::statement st = (db->prepare <<
"SELECT PublicKey, PrivateKey FROM NodeIdentity;",
soci::into(pubKO),
soci::into(priKO));
st.execute ();
while (st.fetch ())
soci::statement st =
(db->prepare << "SELECT PublicKey, PrivateKey FROM NodeIdentity;",
soci::into(pubKO),
soci::into(priKO));
st.execute();
while (st.fetch())
{
auto const sk = parseBase58<SecretKey>(
TokenType::NodePrivate, priKO.value_or(""));
@@ -70,7 +68,7 @@ loadNodeIdentity (Application& app)
TokenType::NodePublic, pubKO.value_or(""));
// Only use if the public and secret keys are a pair
if (sk && pk && (*pk == derivePublicKey (KeyType::secp256k1, *sk)))
if (sk && pk && (*pk == derivePublicKey(KeyType::secp256k1, *sk)))
{
secretKey = sk;
publicKey = pk;
@@ -83,13 +81,14 @@ loadNodeIdentity (Application& app)
{
std::tie(publicKey, secretKey) = randomKeyPair(KeyType::secp256k1);
*db << str (boost::format (
"INSERT INTO NodeIdentity (PublicKey,PrivateKey) VALUES ('%s','%s');")
% toBase58 (TokenType::NodePublic, *publicKey)
% toBase58 (TokenType::NodePrivate, *secretKey));
*db << str(
boost::format("INSERT INTO NodeIdentity (PublicKey,PrivateKey) "
"VALUES ('%s','%s');") %
toBase58(TokenType::NodePublic, *publicKey) %
toBase58(TokenType::NodePrivate, *secretKey));
}
return { *publicKey, *secretKey };
return {*publicKey, *secretKey};
}
} // ripple
} // namespace ripple

View File

@@ -29,8 +29,8 @@ namespace ripple {
/** The cryptographic credentials identifying this server instance. */
std::pair<PublicKey, SecretKey>
loadNodeIdentity (Application& app);
loadNodeIdentity(Application& app);
} // ripple
} // namespace ripple
#endif

View File

@@ -22,43 +22,47 @@
namespace ripple {
NodeStoreScheduler::NodeStoreScheduler (Stoppable& parent)
: Stoppable ("NodeStoreScheduler", parent)
NodeStoreScheduler::NodeStoreScheduler(Stoppable& parent)
: Stoppable("NodeStoreScheduler", parent)
{
}
void NodeStoreScheduler::setJobQueue (JobQueue& jobQueue)
void
NodeStoreScheduler::setJobQueue(JobQueue& jobQueue)
{
m_jobQueue = &jobQueue;
}
void NodeStoreScheduler::onStop ()
void
NodeStoreScheduler::onStop()
{
}
void NodeStoreScheduler::onChildrenStopped ()
void
NodeStoreScheduler::onChildrenStopped()
{
assert (m_taskCount == 0);
stopped ();
assert(m_taskCount == 0);
stopped();
}
void NodeStoreScheduler::scheduleTask (NodeStore::Task& task)
void
NodeStoreScheduler::scheduleTask(NodeStore::Task& task)
{
++m_taskCount;
if (!m_jobQueue->addJob (
jtWRITE,
"NodeObject::store",
[this, &task] (Job&) { doTask(task); }))
if (!m_jobQueue->addJob(jtWRITE, "NodeObject::store", [this, &task](Job&) {
doTask(task);
}))
{
// Job not added, presumably because we're shutting down.
// Recover by executing the task synchronously.
doTask (task);
doTask(task);
}
}
void NodeStoreScheduler::doTask (NodeStore::Task& task)
void
NodeStoreScheduler::doTask(NodeStore::Task& task)
{
task.performScheduledTask ();
task.performScheduledTask();
// NOTE: It feels a bit off that there are two different methods that
// call stopped(): onChildrenStopped() and doTask(). There's a
@@ -71,18 +75,20 @@ void NodeStoreScheduler::doTask (NodeStore::Task& task)
stopped();
}
void NodeStoreScheduler::onFetch (NodeStore::FetchReport const& report)
void
NodeStoreScheduler::onFetch(NodeStore::FetchReport const& report)
{
if (report.wentToDisk)
m_jobQueue->addLoadEvents (
m_jobQueue->addLoadEvents(
report.isAsync ? jtNS_ASYNC_READ : jtNS_SYNC_READ,
1, report.elapsed);
1,
report.elapsed);
}
void NodeStoreScheduler::onBatchWrite (NodeStore::BatchWriteReport const& report)
void
NodeStoreScheduler::onBatchWrite(NodeStore::BatchWriteReport const& report)
{
m_jobQueue->addLoadEvents (jtNS_WRITE,
report.writeCount, report.elapsed);
m_jobQueue->addLoadEvents(jtNS_WRITE, report.writeCount, report.elapsed);
}
} // ripple
} // namespace ripple

View File

@@ -20,39 +20,45 @@
#ifndef RIPPLE_APP_MAIN_NODESTORESCHEDULER_H_INCLUDED
#define RIPPLE_APP_MAIN_NODESTORESCHEDULER_H_INCLUDED
#include <ripple/nodestore/Scheduler.h>
#include <ripple/core/JobQueue.h>
#include <ripple/core/Stoppable.h>
#include <ripple/nodestore/Scheduler.h>
#include <atomic>
namespace ripple {
/** A NodeStore::Scheduler which uses the JobQueue and implements the Stoppable API. */
class NodeStoreScheduler
: public NodeStore::Scheduler
, public Stoppable
/** A NodeStore::Scheduler which uses the JobQueue and implements the Stoppable
* API. */
class NodeStoreScheduler : public NodeStore::Scheduler, public Stoppable
{
public:
NodeStoreScheduler (Stoppable& parent);
NodeStoreScheduler(Stoppable& parent);
// VFALCO NOTE This is a temporary hack to solve the problem
// of circular dependency.
//
void setJobQueue (JobQueue& jobQueue);
void
setJobQueue(JobQueue& jobQueue);
void onStop () override;
void onChildrenStopped () override;
void scheduleTask (NodeStore::Task& task) override;
void onFetch (NodeStore::FetchReport const& report) override;
void onBatchWrite (NodeStore::BatchWriteReport const& report) override;
void
onStop() override;
void
onChildrenStopped() override;
void
scheduleTask(NodeStore::Task& task) override;
void
onFetch(NodeStore::FetchReport const& report) override;
void
onBatchWrite(NodeStore::BatchWriteReport const& report) override;
private:
void doTask (NodeStore::Task& task);
void
doTask(NodeStore::Task& task);
JobQueue* m_jobQueue {nullptr};
std::atomic <int> m_taskCount {0};
JobQueue* m_jobQueue{nullptr};
std::atomic<int> m_taskCount{0};
};
} // ripple
} // namespace ripple
#endif

View File

@@ -25,6 +25,6 @@ namespace ripple {
constexpr std::size_t fullBelowTargetSize = 524288;
constexpr std::chrono::seconds fullBelowExpiration = std::chrono::minutes{10};
}
} // namespace ripple
#endif

View File

@@ -21,9 +21,9 @@
#define RIPPLE_APP_MISC_AMENDMENTTABLE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/STValidation.h>
namespace ripple {
@@ -36,16 +36,23 @@ class AmendmentTable
public:
virtual ~AmendmentTable() = default;
virtual uint256 find (std::string const& name) = 0;
virtual uint256
find(std::string const& name) = 0;
virtual bool veto (uint256 const& amendment) = 0;
virtual bool unVeto (uint256 const& amendment) = 0;
virtual bool
veto(uint256 const& amendment) = 0;
virtual bool
unVeto(uint256 const& amendment) = 0;
virtual bool enable (uint256 const& amendment) = 0;
virtual bool disable (uint256 const& amendment) = 0;
virtual bool
enable(uint256 const& amendment) = 0;
virtual bool
disable(uint256 const& amendment) = 0;
virtual bool isEnabled (uint256 const& amendment) = 0;
virtual bool isSupported (uint256 const& amendment) = 0;
virtual bool
isEnabled(uint256 const& amendment) = 0;
virtual bool
isSupported(uint256 const& amendment) = 0;
/**
* @brief returns true if one or more amendments on the network
@@ -53,14 +60,17 @@ public:
*
* @return true if an unsupported feature is enabled on the network
*/
virtual bool hasUnsupportedEnabled () = 0;
virtual bool
hasUnsupportedEnabled() = 0;
virtual boost::optional<NetClock::time_point>
firstUnsupportedExpected() = 0;
virtual Json::Value getJson (int) = 0;
virtual Json::Value
getJson(int) = 0;
/** Returns a Json::objectValue. */
virtual Json::Value getJson (uint256 const& ) = 0;
virtual Json::Value
getJson(uint256 const&) = 0;
/** Called when a new fully-validated ledger is accepted. */
void
@@ -78,34 +88,34 @@ public:
a new validated ledger. (If it could have changed things.)
*/
virtual bool
needValidatedLedger (LedgerIndex seq) = 0;
needValidatedLedger(LedgerIndex seq) = 0;
virtual void
doValidatedLedger (
doValidatedLedger(
LedgerIndex ledgerSeq,
std::set <uint256> const& enabled,
std::set<uint256> const& enabled,
majorityAmendments_t const& majority) = 0;
// Called by the consensus code when we need to
// inject pseudo-transactions
virtual std::map <uint256, std::uint32_t>
doVoting (
virtual std::map<uint256, std::uint32_t>
doVoting(
NetClock::time_point closeTime,
std::set <uint256> const& enabledAmendments,
std::set<uint256> const& enabledAmendments,
majorityAmendments_t const& majorityAmendments,
std::vector<STValidation::pointer> const& valSet) = 0;
// Called by the consensus code when we need to
// add feature entries to a validation
virtual std::vector <uint256>
doValidation (std::set <uint256> const& enabled) = 0;
virtual std::vector<uint256>
doValidation(std::set<uint256> const& enabled) = 0;
// The set of amendments to enable in the genesis ledger
// This will return all known, non-vetoed amendments.
// If we ever have two amendments that should not both be
// enabled at the same time, we should ensure one is vetoed.
virtual std::vector <uint256>
getDesired () = 0;
virtual std::vector<uint256>
getDesired() = 0;
// The function below adapts the API callers expect to the
// internal amendment table API. This allows the amendment
@@ -114,13 +124,13 @@ public:
// supports a full ledger API
void
doVoting (
std::shared_ptr <ReadView const> const& lastClosedLedger,
doVoting(
std::shared_ptr<ReadView const> const& lastClosedLedger,
std::vector<STValidation::pointer> const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition)
{
// Ask implementation what to do
auto actions = doVoting (
auto actions = doVoting(
lastClosedLedger->parentCloseTime(),
getEnabledAmendments(*lastClosedLedger),
getMajorityAmendments(*lastClosedLedger),
@@ -129,32 +139,31 @@ public:
// Inject appropriate pseudo-transactions
for (auto const& it : actions)
{
STTx amendTx (ttAMENDMENT,
[&it, seq = lastClosedLedger->seq() + 1](auto& obj)
{
obj.setAccountID (sfAccount, AccountID());
obj.setFieldH256 (sfAmendment, it.first);
obj.setFieldU32 (sfLedgerSequence, seq);
STTx amendTx(
ttAMENDMENT,
[&it, seq = lastClosedLedger->seq() + 1](auto& obj) {
obj.setAccountID(sfAccount, AccountID());
obj.setFieldH256(sfAmendment, it.first);
obj.setFieldU32(sfLedgerSequence, seq);
if (it.second != 0)
obj.setFieldU32 (sfFlags, it.second);
obj.setFieldU32(sfFlags, it.second);
});
Serializer s;
amendTx.add (s);
amendTx.add(s);
initialPosition->addGiveItem (
std::make_shared <SHAMapItem> (
amendTx.getTransactionID(),
s.peekData()),
initialPosition->addGiveItem(
std::make_shared<SHAMapItem>(
amendTx.getTransactionID(), s.peekData()),
true,
false);
}
}
};
std::unique_ptr<AmendmentTable> make_AmendmentTable (
std::unique_ptr<AmendmentTable>
make_AmendmentTable(
std::chrono::seconds majorityTime,
int majorityFraction,
Section const& supported,
@@ -162,6 +171,6 @@ std::unique_ptr<AmendmentTable> make_AmendmentTable (
Section const& vetoed,
beast::Journal journal);
} // ripple
} // namespace ripple
#endif

View File

@@ -22,94 +22,109 @@
namespace ripple {
bool CanonicalTXSet::Key::operator< (Key const& rhs) const
bool
CanonicalTXSet::Key::operator<(Key const& rhs) const
{
if (mAccount < rhs.mAccount) return true;
if (mAccount < rhs.mAccount)
return true;
if (mAccount > rhs.mAccount) return false;
if (mAccount > rhs.mAccount)
return false;
if (mSeq < rhs.mSeq) return true;
if (mSeq < rhs.mSeq)
return true;
if (mSeq > rhs.mSeq) return false;
if (mSeq > rhs.mSeq)
return false;
return mTXid < rhs.mTXid;
}
bool CanonicalTXSet::Key::operator> (Key const& rhs) const
bool
CanonicalTXSet::Key::operator>(Key const& rhs) const
{
if (mAccount > rhs.mAccount) return true;
if (mAccount > rhs.mAccount)
return true;
if (mAccount < rhs.mAccount) return false;
if (mAccount < rhs.mAccount)
return false;
if (mSeq > rhs.mSeq) return true;
if (mSeq > rhs.mSeq)
return true;
if (mSeq < rhs.mSeq) return false;
if (mSeq < rhs.mSeq)
return false;
return mTXid > rhs.mTXid;
}
bool CanonicalTXSet::Key::operator<= (Key const& rhs) const
bool
CanonicalTXSet::Key::operator<=(Key const& rhs) const
{
if (mAccount < rhs.mAccount) return true;
if (mAccount < rhs.mAccount)
return true;
if (mAccount > rhs.mAccount) return false;
if (mAccount > rhs.mAccount)
return false;
if (mSeq < rhs.mSeq) return true;
if (mSeq < rhs.mSeq)
return true;
if (mSeq > rhs.mSeq) return false;
if (mSeq > rhs.mSeq)
return false;
return mTXid <= rhs.mTXid;
}
bool CanonicalTXSet::Key::operator>= (Key const& rhs)const
bool
CanonicalTXSet::Key::operator>=(Key const& rhs) const
{
if (mAccount > rhs.mAccount) return true;
if (mAccount > rhs.mAccount)
return true;
if (mAccount < rhs.mAccount) return false;
if (mAccount < rhs.mAccount)
return false;
if (mSeq > rhs.mSeq) return true;
if (mSeq > rhs.mSeq)
return true;
if (mSeq < rhs.mSeq) return false;
if (mSeq < rhs.mSeq)
return false;
return mTXid >= rhs.mTXid;
}
uint256 CanonicalTXSet::accountKey (AccountID const& account)
uint256
CanonicalTXSet::accountKey(AccountID const& account)
{
uint256 ret = beast::zero;
memcpy (
ret.begin (),
account.begin (),
account.size ());
memcpy(ret.begin(), account.begin(), account.size());
ret ^= salt_;
return ret;
}
void CanonicalTXSet::insert (std::shared_ptr<STTx const> const& txn)
void
CanonicalTXSet::insert(std::shared_ptr<STTx const> const& txn)
{
map_.insert (
std::make_pair (
Key (
accountKey (txn->getAccountID(sfAccount)),
txn->getSequence (),
txn->getTransactionID ()),
txn));
map_.insert(std::make_pair(
Key(accountKey(txn->getAccountID(sfAccount)),
txn->getSequence(),
txn->getTransactionID()),
txn));
}
std::vector<std::shared_ptr<STTx const>>
CanonicalTXSet::prune(AccountID const& account,
std::uint32_t const seq)
CanonicalTXSet::prune(AccountID const& account, std::uint32_t const seq)
{
auto effectiveAccount = accountKey (account);
auto effectiveAccount = accountKey(account);
Key keyLow(effectiveAccount, seq, beast::zero);
Key keyHigh(effectiveAccount, seq+1, beast::zero);
Key keyHigh(effectiveAccount, seq + 1, beast::zero);
auto range = boost::make_iterator_range(
map_.lower_bound(keyLow),
map_.lower_bound(keyHigh));
auto txRange = boost::adaptors::transform(range,
[](auto const& p) { return p.second; });
map_.lower_bound(keyLow), map_.lower_bound(keyHigh));
auto txRange = boost::adaptors::transform(
range, [](auto const& p) { return p.second; });
std::vector<std::shared_ptr<STTx const>> result(
txRange.begin(), txRange.end());
@@ -118,4 +133,4 @@ CanonicalTXSet::prune(AccountID const& account,
return result;
}
} // ripple
} // namespace ripple

View File

@@ -39,28 +39,33 @@ private:
class Key
{
public:
Key (uint256 const& account, std::uint32_t seq, uint256 const& id)
: mAccount (account)
, mTXid (id)
, mSeq (seq)
Key(uint256 const& account, std::uint32_t seq, uint256 const& id)
: mAccount(account), mTXid(id), mSeq(seq)
{
}
bool operator< (Key const& rhs) const;
bool operator> (Key const& rhs) const;
bool operator<= (Key const& rhs) const;
bool operator>= (Key const& rhs) const;
bool
operator<(Key const& rhs) const;
bool
operator>(Key const& rhs) const;
bool
operator<=(Key const& rhs) const;
bool
operator>=(Key const& rhs) const;
bool operator== (Key const& rhs) const
bool
operator==(Key const& rhs) const
{
return mTXid == rhs.mTXid;
}
bool operator!= (Key const& rhs) const
bool
operator!=(Key const& rhs) const
{
return mTXid != rhs.mTXid;
}
uint256 const& getTXID () const
uint256 const&
getTXID() const
{
return mTXid;
}
@@ -72,65 +77,74 @@ private:
};
// Calculate the salted key for the given account
uint256 accountKey (AccountID const& account);
uint256
accountKey(AccountID const& account);
public:
using const_iterator = std::map <Key, std::shared_ptr<STTx const>>::const_iterator;
using const_iterator =
std::map<Key, std::shared_ptr<STTx const>>::const_iterator;
public:
explicit CanonicalTXSet (LedgerHash const& saltHash)
: salt_ (saltHash)
explicit CanonicalTXSet(LedgerHash const& saltHash) : salt_(saltHash)
{
}
void insert (std::shared_ptr<STTx const> const& txn);
void
insert(std::shared_ptr<STTx const> const& txn);
std::vector<std::shared_ptr<STTx const>>
prune(AccountID const& account, std::uint32_t const seq);
// VFALCO TODO remove this function
void reset (LedgerHash const& salt)
void
reset(LedgerHash const& salt)
{
salt_ = salt;
map_.clear ();
map_.clear();
}
const_iterator erase (const_iterator const& it)
const_iterator
erase(const_iterator const& it)
{
return map_.erase(it);
}
const_iterator begin () const
const_iterator
begin() const
{
return map_.begin();
}
const_iterator end() const
const_iterator
end() const
{
return map_.end();
}
size_t size () const
size_t
size() const
{
return map_.size ();
return map_.size();
}
bool empty () const
bool
empty() const
{
return map_.empty ();
return map_.empty();
}
uint256 const& key() const
uint256 const&
key() const
{
return salt_;
}
private:
std::map <Key, std::shared_ptr<STTx const>> map_;
std::map<Key, std::shared_ptr<STTx const>> map_;
// Used to salt the accounts so people can't mine for low account numbers
uint256 salt_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -20,11 +20,11 @@
#ifndef RIPPLE_APP_MISC_FEEVOTE_H_INCLUDED
#define RIPPLE_APP_MISC_FEEVOTE_H_INCLUDED
#include <ripple/ledger/ReadView.h>
#include <ripple/shamap/SHAMap.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/SystemParameters.h>
#include <ripple/shamap/SHAMap.h>
namespace ripple {
@@ -40,53 +40,53 @@ public:
struct Setup
{
/** The cost of a reference transaction in drops. */
XRPAmount reference_fee{ 10 };
XRPAmount reference_fee{10};
/** The cost of a reference transaction in fee units. */
static constexpr FeeUnit32 reference_fee_units{ 10 };
static constexpr FeeUnit32 reference_fee_units{10};
/** The account reserve requirement in drops. */
XRPAmount account_reserve{ 20 * DROPS_PER_XRP };
XRPAmount account_reserve{20 * DROPS_PER_XRP};
/** The per-owned item reserve requirement in drops. */
XRPAmount owner_reserve{ 5 * DROPS_PER_XRP };
XRPAmount owner_reserve{5 * DROPS_PER_XRP};
};
virtual ~FeeVote () = default;
virtual ~FeeVote() = default;
/** Add local fee preference to validation.
@param lastClosedLedger
@param baseValidation
*/
virtual
void
doValidation (std::shared_ptr<ReadView const> const& lastClosedLedger,
STValidation::FeeSettings & fees) = 0;
virtual void
doValidation(
std::shared_ptr<ReadView const> const& lastClosedLedger,
STValidation::FeeSettings& fees) = 0;
/** Cast our local vote on the fee.
@param lastClosedLedger
@param initialPosition
*/
virtual
void
doVoting (std::shared_ptr<ReadView const> const& lastClosedLedger,
virtual void
doVoting(
std::shared_ptr<ReadView const> const& lastClosedLedger,
std::vector<STValidation::pointer> const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition) = 0;
std::shared_ptr<SHAMap> const& initialPosition) = 0;
};
/** Build FeeVote::Setup from a config section. */
FeeVote::Setup
setup_FeeVote (Section const& section);
setup_FeeVote(Section const& section);
/** Create an instance of the FeeVote logic.
@param setup The fee schedule to vote for.
@param journal Where to log.
*/
std::unique_ptr <FeeVote>
make_FeeVote (FeeVote::Setup const& setup, beast::Journal journal);
std::unique_ptr<FeeVote>
make_FeeVote(FeeVote::Setup const& setup, beast::Journal journal);
} // ripple
} // namespace ripple
#endif

View File

@@ -17,12 +17,12 @@
*/
//==============================================================================
#include <ripple/protocol/st.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/app/main/Application.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/app/misc/FeeVote.h>
#include <ripple/basics/BasicConfig.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/st.h>
namespace ripple {
@@ -32,14 +32,13 @@ class VotableValue
{
private:
using value_type = XRPAmount;
value_type const mCurrent; // The current setting
value_type const mTarget; // The setting we want
std::map <value_type, int> mVoteMap;
value_type const mCurrent; // The current setting
value_type const mTarget; // The setting we want
std::map<value_type, int> mVoteMap;
public:
VotableValue (value_type current, value_type target)
: mCurrent (current)
, mTarget (target)
VotableValue(value_type current, value_type target)
: mCurrent(current), mTarget(target)
{
// Add our vote
++mVoteMap[mTarget];
@@ -54,7 +53,7 @@ public:
void
noVote()
{
addVote (mCurrent);
addVote(mCurrent);
}
value_type
@@ -62,17 +61,15 @@ public:
};
auto
VotableValue::getVotes() const
-> value_type
VotableValue::getVotes() const -> value_type
{
value_type ourVote = mCurrent;
int weight = 0;
for (auto const& [key, val] : mVoteMap)
{
// Take most voted value between current and target, inclusive
if ((key <= std::max (mTarget, mCurrent)) &&
(key >= std::min (mTarget, mCurrent)) &&
(val > weight))
if ((key <= std::max(mTarget, mCurrent)) &&
(key >= std::min(mTarget, mCurrent)) && (val > weight))
{
ourVote = key;
weight = val;
@@ -82,7 +79,7 @@ VotableValue::getVotes() const
return ourVote;
}
}
} // namespace detail
//------------------------------------------------------------------------------
@@ -93,51 +90,52 @@ private:
beast::Journal const journal_;
public:
FeeVoteImpl (Setup const& setup, beast::Journal journal);
FeeVoteImpl(Setup const& setup, beast::Journal journal);
void
doValidation (std::shared_ptr<ReadView const> const& lastClosedLedger,
doValidation(
std::shared_ptr<ReadView const> const& lastClosedLedger,
STValidation::FeeSettings& fees) override;
void
doVoting (std::shared_ptr<ReadView const> const& lastClosedLedger,
doVoting(
std::shared_ptr<ReadView const> const& lastClosedLedger,
std::vector<STValidation::pointer> const& parentValidations,
std::shared_ptr<SHAMap> const& initialPosition) override;
};
//--------------------------------------------------------------------------
FeeVoteImpl::FeeVoteImpl (Setup const& setup, beast::Journal journal)
: target_ (setup)
, journal_ (journal)
FeeVoteImpl::FeeVoteImpl(Setup const& setup, beast::Journal journal)
: target_(setup), journal_(journal)
{
}
void
FeeVoteImpl::doValidation(
std::shared_ptr<ReadView const> const& lastClosedLedger,
STValidation::FeeSettings& fees)
STValidation::FeeSettings& fees)
{
if (lastClosedLedger->fees().base != target_.reference_fee)
{
JLOG(journal_.info()) <<
"Voting for base fee of " << target_.reference_fee;
JLOG(journal_.info())
<< "Voting for base fee of " << target_.reference_fee;
fees.baseFee = target_.reference_fee;
}
if (lastClosedLedger->fees().accountReserve(0) != target_.account_reserve)
{
JLOG(journal_.info()) <<
"Voting for base reserve of " << target_.account_reserve;
JLOG(journal_.info())
<< "Voting for base reserve of " << target_.account_reserve;
fees.reserveBase = target_.account_reserve;
}
if (lastClosedLedger->fees().increment != target_.owner_reserve)
{
JLOG(journal_.info()) <<
"Voting for reserve increment of " << target_.owner_reserve;
JLOG(journal_.info())
<< "Voting for reserve increment of " << target_.owner_reserve;
fees.reserveIncrement = target_.owner_reserve;
}
@@ -150,32 +148,29 @@ FeeVoteImpl::doVoting(
std::shared_ptr<SHAMap> const& initialPosition)
{
// LCL must be flag ledger
assert ((lastClosedLedger->info().seq % 256) == 0);
assert((lastClosedLedger->info().seq % 256) == 0);
detail::VotableValue baseFeeVote (
lastClosedLedger->fees().base,
target_.reference_fee);
detail::VotableValue baseFeeVote(
lastClosedLedger->fees().base, target_.reference_fee);
detail::VotableValue baseReserveVote(
lastClosedLedger->fees().accountReserve(0),
target_.account_reserve);
lastClosedLedger->fees().accountReserve(0), target_.account_reserve);
detail::VotableValue incReserveVote (
lastClosedLedger->fees().increment,
target_.owner_reserve);
detail::VotableValue incReserveVote(
lastClosedLedger->fees().increment, target_.owner_reserve);
for (auto const& val : set)
{
if (val->isTrusted ())
if (val->isTrusted())
{
if (val->isFieldPresent (sfBaseFee))
if (val->isFieldPresent(sfBaseFee))
{
using xrptype = XRPAmount::value_type;
auto const vote = val->getFieldU64 (sfBaseFee);
auto const vote = val->getFieldU64(sfBaseFee);
if (vote <= std::numeric_limits<xrptype>::max() &&
isLegalAmount(XRPAmount{unsafe_cast<xrptype>(vote)}))
baseFeeVote.addVote(XRPAmount{
unsafe_cast<XRPAmount::value_type>(vote)});
baseFeeVote.addVote(
XRPAmount{unsafe_cast<XRPAmount::value_type>(vote)});
else
// Invalid amounts will be treated as if they're
// not provided. Don't throw because this value is
@@ -184,38 +179,38 @@ FeeVoteImpl::doVoting(
}
else
{
baseFeeVote.noVote ();
baseFeeVote.noVote();
}
if (val->isFieldPresent (sfReserveBase))
if (val->isFieldPresent(sfReserveBase))
{
baseReserveVote.addVote(XRPAmount{
val->getFieldU32(sfReserveBase)});
baseReserveVote.addVote(
XRPAmount{val->getFieldU32(sfReserveBase)});
}
else
{
baseReserveVote.noVote ();
baseReserveVote.noVote();
}
if (val->isFieldPresent (sfReserveIncrement))
if (val->isFieldPresent(sfReserveIncrement))
{
incReserveVote.addVote (XRPAmount{
val->getFieldU32 (sfReserveIncrement)});
incReserveVote.addVote(
XRPAmount{val->getFieldU32(sfReserveIncrement)});
}
else
{
incReserveVote.noVote ();
incReserveVote.noVote();
}
}
}
// choose our positions
// If any of the values are invalid, send the current values.
auto const baseFee = baseFeeVote.getVotes ().dropsAs<std::uint64_t>(
auto const baseFee = baseFeeVote.getVotes().dropsAs<std::uint64_t>(
lastClosedLedger->fees().base);
auto const baseReserve = baseReserveVote.getVotes ().dropsAs<std::uint32_t>(
auto const baseReserve = baseReserveVote.getVotes().dropsAs<std::uint32_t>(
lastClosedLedger->fees().accountReserve(0));
auto const incReserve = incReserveVote.getVotes ().dropsAs<std::uint32_t>(
auto const incReserve = incReserveVote.getVotes().dropsAs<std::uint32_t>(
lastClosedLedger->fees().increment);
constexpr FeeUnit32 feeUnits = Setup::reference_fee_units;
auto const seq = lastClosedLedger->info().seq + 1;
@@ -223,16 +218,14 @@ FeeVoteImpl::doVoting(
// add transactions to our position
if ((baseFee != lastClosedLedger->fees().base) ||
(baseReserve != lastClosedLedger->fees().accountReserve(0)) ||
(incReserve != lastClosedLedger->fees().increment))
(incReserve != lastClosedLedger->fees().increment))
{
JLOG(journal_.warn()) <<
"We are voting for a fee change: " << baseFee <<
"/" << baseReserve <<
"/" << incReserve;
JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee
<< "/" << baseReserve << "/" << incReserve;
STTx feeTx (ttFEE,
[seq,baseFee,baseReserve,incReserve,feeUnits](auto& obj)
{
STTx feeTx(
ttFEE,
[seq, baseFee, baseReserve, incReserve, feeUnits](auto& obj) {
obj[sfAccount] = AccountID();
obj[sfLedgerSequence] = seq;
obj[sfBaseFee] = baseFee;
@@ -241,20 +234,18 @@ FeeVoteImpl::doVoting(
obj[sfReferenceFeeUnits] = feeUnits.fee();
});
uint256 txID = feeTx.getTransactionID ();
uint256 txID = feeTx.getTransactionID();
JLOG(journal_.warn()) <<
"Vote: " << txID;
JLOG(journal_.warn()) << "Vote: " << txID;
Serializer s;
feeTx.add (s);
feeTx.add(s);
auto tItem = std::make_shared<SHAMapItem> (txID, s.peekData ());
auto tItem = std::make_shared<SHAMapItem>(txID, s.peekData());
if (!initialPosition->addGiveItem (tItem, true, false))
if (!initialPosition->addGiveItem(tItem, true, false))
{
JLOG(journal_.warn()) <<
"Ledger already had fee change";
JLOG(journal_.warn()) << "Ledger already had fee change";
}
}
}
@@ -262,7 +253,7 @@ FeeVoteImpl::doVoting(
//------------------------------------------------------------------------------
FeeVote::Setup
setup_FeeVote (Section const& section)
setup_FeeVote(Section const& section)
{
FeeVote::Setup setup;
{
@@ -282,9 +273,9 @@ setup_FeeVote (Section const& section)
}
std::unique_ptr<FeeVote>
make_FeeVote (FeeVote::Setup const& setup, beast::Journal journal)
make_FeeVote(FeeVote::Setup const& setup, beast::Journal journal)
{
return std::make_unique<FeeVoteImpl> (setup, journal);
return std::make_unique<FeeVoteImpl>(setup, journal);
}
} // ripple
} // namespace ripple

View File

@@ -22,92 +22,97 @@
namespace ripple {
auto
HashRouter::emplace (uint256 const& key)
-> std::pair<Entry&, bool>
HashRouter::emplace(uint256 const& key) -> std::pair<Entry&, bool>
{
auto iter = suppressionMap_.find (key);
auto iter = suppressionMap_.find(key);
if (iter != suppressionMap_.end ())
if (iter != suppressionMap_.end())
{
suppressionMap_.touch(iter);
return std::make_pair(
std::ref(iter->second), false);
return std::make_pair(std::ref(iter->second), false);
}
// See if any supressions need to be expired
expire(suppressionMap_, holdTime_);
return std::make_pair(std::ref(
suppressionMap_.emplace (
key, Entry ()).first->second),
true);
return std::make_pair(
std::ref(suppressionMap_.emplace(key, Entry()).first->second), true);
}
void HashRouter::addSuppression (uint256 const& key)
void
HashRouter::addSuppression(uint256 const& key)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
emplace (key);
emplace(key);
}
bool HashRouter::addSuppressionPeer (uint256 const& key, PeerShortID peer)
bool
HashRouter::addSuppressionPeer(uint256 const& key, PeerShortID peer)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
auto result = emplace(key);
result.first.addPeer(peer);
return result.second;
}
bool HashRouter::addSuppressionPeer (uint256 const& key, PeerShortID peer, int& flags)
bool
HashRouter::addSuppressionPeer(uint256 const& key, PeerShortID peer, int& flags)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
auto [s, created] = emplace(key);
s.addPeer (peer);
flags = s.getFlags ();
s.addPeer(peer);
flags = s.getFlags();
return created;
}
bool HashRouter::shouldProcess (uint256 const& key, PeerShortID peer,
int& flags, std::chrono::seconds tx_interval)
bool
HashRouter::shouldProcess(
uint256 const& key,
PeerShortID peer,
int& flags,
std::chrono::seconds tx_interval)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
auto result = emplace(key);
auto& s = result.first;
s.addPeer (peer);
flags = s.getFlags ();
return s.shouldProcess (suppressionMap_.clock().now(), tx_interval);
s.addPeer(peer);
flags = s.getFlags();
return s.shouldProcess(suppressionMap_.clock().now(), tx_interval);
}
int HashRouter::getFlags (uint256 const& key)
int
HashRouter::getFlags(uint256 const& key)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
return emplace(key).first.getFlags ();
return emplace(key).first.getFlags();
}
bool HashRouter::setFlags (uint256 const& key, int flags)
bool
HashRouter::setFlags(uint256 const& key, int flags)
{
assert (flags != 0);
assert(flags != 0);
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
auto& s = emplace(key).first;
if ((s.getFlags () & flags) == flags)
if ((s.getFlags() & flags) == flags)
return false;
s.setFlags (flags);
s.setFlags(flags);
return true;
}
auto
HashRouter::shouldRelay (uint256 const& key)
HashRouter::shouldRelay(uint256 const& key)
-> boost::optional<std::set<PeerShortID>>
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
auto& s = emplace(key).first;
@@ -127,4 +132,4 @@ HashRouter::shouldRecover(uint256 const& key)
return s.shouldRecover(recoverLimit_);
}
} // ripple
} // namespace ripple

View File

@@ -20,10 +20,10 @@
#ifndef RIPPLE_APP_MISC_HASHROUTER_H_INCLUDED
#define RIPPLE_APP_MISC_HASHROUTER_H_INCLUDED
#include <ripple/basics/base_uint.h>
#include <ripple/basics/chrono.h>
#include <ripple/basics/CountedObject.h>
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/basics/base_uint.h>
#include <ripple/basics/chrono.h>
#include <ripple/beast/container/aged_unordered_map.h>
#include <boost/optional.hpp>
@@ -32,17 +32,17 @@ namespace ripple {
// VFALCO NOTE Are these the flags?? Why aren't we using a packed struct?
// VFALCO TODO convert these macros to int constants
// VFALCO NOTE How can both bad and good be set on a hash?
#define SF_BAD 0x02 // Temporarily bad
#define SF_SAVED 0x04
#define SF_TRUSTED 0x10 // comes from trusted source
#define SF_BAD 0x02 // Temporarily bad
#define SF_SAVED 0x04
#define SF_TRUSTED 0x10 // comes from trusted source
// Private flags, used internally in apply.cpp.
// Do not attempt to read, set, or reuse.
#define SF_PRIVATE1 0x0100
#define SF_PRIVATE2 0x0200
#define SF_PRIVATE3 0x0400
#define SF_PRIVATE4 0x0800
#define SF_PRIVATE5 0x1000
#define SF_PRIVATE6 0x2000
#define SF_PRIVATE1 0x0100
#define SF_PRIVATE2 0x0200
#define SF_PRIVATE3 0x0400
#define SF_PRIVATE4 0x0800
#define SF_PRIVATE5 0x1000
#define SF_PRIVATE6 0x2000
/** Routing table for objects identified by hash.
@@ -58,34 +58,42 @@ public:
private:
/** An entry in the routing table.
*/
class Entry : public CountedObject <Entry>
*/
class Entry : public CountedObject<Entry>
{
public:
static char const* getCountedObjectName () { return "HashRouterEntry"; }
static char const*
getCountedObjectName()
{
return "HashRouterEntry";
}
Entry ()
Entry()
{
}
void addPeer (PeerShortID peer)
void
addPeer(PeerShortID peer)
{
if (peer != 0)
peers_.insert (peer);
peers_.insert(peer);
}
int getFlags (void) const
int
getFlags(void) const
{
return flags_;
}
void setFlags (int flagsToSet)
void
setFlags(int flagsToSet)
{
flags_ |= flagsToSet;
}
/** Return set of peers we've relayed to and reset tracking */
std::set<PeerShortID> releasePeerSet()
std::set<PeerShortID>
releasePeerSet()
{
return std::move(peers_);
}
@@ -96,7 +104,9 @@ private:
If it has, return false. If it has not, update the
last relay timestamp and return true.
*/
bool shouldRelay (Stopwatch::time_point const& now,
bool
shouldRelay(
Stopwatch::time_point const& now,
std::chrono::seconds holdTime)
{
if (relayed_ && *relayed_ + holdTime > now)
@@ -113,22 +123,24 @@ private:
@note The limit must be > 0
*/
bool shouldRecover(std::uint32_t limit)
bool
shouldRecover(std::uint32_t limit)
{
return ++recoveries_ % limit != 0;
}
bool shouldProcess(Stopwatch::time_point now, std::chrono::seconds interval)
bool
shouldProcess(Stopwatch::time_point now, std::chrono::seconds interval)
{
if (processed_ && ((*processed_ + interval) > now))
return false;
processed_.emplace (now);
return true;
if (processed_ && ((*processed_ + interval) > now))
return false;
processed_.emplace(now);
return true;
}
private:
int flags_ = 0;
std::set <PeerShortID> peers_;
std::set<PeerShortID> peers_;
// This could be generalized to a map, if more
// than one flag needs to expire independently.
boost::optional<Stopwatch::time_point> relayed_;
@@ -137,50 +149,63 @@ private:
};
public:
static inline std::chrono::seconds getDefaultHoldTime ()
static inline std::chrono::seconds
getDefaultHoldTime()
{
using namespace std::chrono;
return 300s;
}
static inline std::uint32_t getDefaultRecoverLimit()
static inline std::uint32_t
getDefaultRecoverLimit()
{
return 1;
}
HashRouter (Stopwatch& clock, std::chrono::seconds entryHoldTimeInSeconds,
HashRouter(
Stopwatch& clock,
std::chrono::seconds entryHoldTimeInSeconds,
std::uint32_t recoverLimit)
: suppressionMap_(clock)
, holdTime_ (entryHoldTimeInSeconds)
, recoverLimit_ (recoverLimit + 1u)
, holdTime_(entryHoldTimeInSeconds)
, recoverLimit_(recoverLimit + 1u)
{
}
HashRouter& operator= (HashRouter const&) = delete;
HashRouter&
operator=(HashRouter const&) = delete;
virtual ~HashRouter() = default;
// VFALCO TODO Replace "Supression" terminology with something more
// semantically meaningful.
void addSuppression(uint256 const& key);
void
addSuppression(uint256 const& key);
bool addSuppressionPeer (uint256 const& key, PeerShortID peer);
bool
addSuppressionPeer(uint256 const& key, PeerShortID peer);
bool addSuppressionPeer (uint256 const& key, PeerShortID peer,
int& flags);
bool
addSuppressionPeer(uint256 const& key, PeerShortID peer, int& flags);
// Add a peer suppression and return whether the entry should be processed
bool shouldProcess (uint256 const& key, PeerShortID peer, int& flags,
bool
shouldProcess(
uint256 const& key,
PeerShortID peer,
int& flags,
std::chrono::seconds tx_interval);
/** Set the flags on a hash.
@return `true` if the flags were changed. `false` if unchanged.
*/
bool setFlags (uint256 const& key, int flags);
bool
setFlags(uint256 const& key, int flags);
int getFlags (uint256 const& key);
int
getFlags(uint256 const& key);
/** Determines whether the hashed item should be relayed.
@@ -194,7 +219,8 @@ public:
relayed to. If the result is uninitialized, the item should
_not_ be relayed.
*/
boost::optional<std::set<PeerShortID>> shouldRelay(uint256 const& key);
boost::optional<std::set<PeerShortID>>
shouldRelay(uint256 const& key);
/** Determines whether the hashed item should be recovered
from the open ledger into the next open ledger or the transaction
@@ -202,23 +228,29 @@ public:
@return `bool` indicates whether the item should be recovered
*/
bool shouldRecover(uint256 const& key);
bool
shouldRecover(uint256 const& key);
private:
// pair.second indicates whether the entry was created
std::pair<Entry&, bool> emplace (uint256 const&);
std::pair<Entry&, bool>
emplace(uint256 const&);
std::mutex mutable mutex_;
// Stores all suppressed hashes and their expiration time
beast::aged_unordered_map<uint256, Entry, Stopwatch::clock_type,
hardened_hash<strong_hash>> suppressionMap_;
beast::aged_unordered_map<
uint256,
Entry,
Stopwatch::clock_type,
hardened_hash<strong_hash>>
suppressionMap_;
std::chrono::seconds const holdTime_;
std::uint32_t const recoverLimit_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -21,8 +21,8 @@
#define RIPPLE_CORE_LOADFEETRACK_H_INCLUDED
#include <ripple/basics/FeeUnits.h>
#include <ripple/json/json_value.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/json/json_value.h>
#include <algorithm>
#include <cstdint>
#include <mutex>
@@ -43,51 +43,58 @@ struct Fees;
class LoadFeeTrack final
{
public:
explicit LoadFeeTrack (beast::Journal journal =
beast::Journal(beast::Journal::getNullSink()))
: j_ (journal)
, localTxnLoadFee_ (lftNormalFee)
, remoteTxnLoadFee_ (lftNormalFee)
, clusterTxnLoadFee_ (lftNormalFee)
, raiseCount_ (0)
explicit LoadFeeTrack(
beast::Journal journal = beast::Journal(beast::Journal::getNullSink()))
: j_(journal)
, localTxnLoadFee_(lftNormalFee)
, remoteTxnLoadFee_(lftNormalFee)
, clusterTxnLoadFee_(lftNormalFee)
, raiseCount_(0)
{
}
~LoadFeeTrack() = default;
void setRemoteFee (std::uint32_t f)
void
setRemoteFee(std::uint32_t f)
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
remoteTxnLoadFee_ = f;
}
std::uint32_t getRemoteFee () const
std::uint32_t
getRemoteFee() const
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
return remoteTxnLoadFee_;
}
std::uint32_t getLocalFee () const
std::uint32_t
getLocalFee() const
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
return localTxnLoadFee_;
}
std::uint32_t getClusterFee () const
std::uint32_t
getClusterFee() const
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
return clusterTxnLoadFee_;
}
std::uint32_t getLoadBase () const
std::uint32_t
getLoadBase() const
{
return lftNormalFee;
}
std::uint32_t getLoadFactor () const
std::uint32_t
getLoadFactor() const
{
std::lock_guard sl (lock_);
return std::max({ clusterTxnLoadFee_, localTxnLoadFee_, remoteTxnLoadFee_ });
std::lock_guard sl(lock_);
return std::max(
{clusterTxnLoadFee_, localTxnLoadFee_, remoteTxnLoadFee_});
}
std::pair<std::uint32_t, std::uint32_t>
@@ -100,41 +107,49 @@ public:
std::max(remoteTxnLoadFee_, clusterTxnLoadFee_));
}
void setClusterFee (std::uint32_t fee)
void
setClusterFee(std::uint32_t fee)
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
clusterTxnLoadFee_ = fee;
}
bool raiseLocalFee ();
bool lowerLocalFee ();
bool
raiseLocalFee();
bool
lowerLocalFee();
bool isLoadedLocal () const
bool
isLoadedLocal() const
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee);
}
bool isLoadedCluster () const
bool
isLoadedCluster() const
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
return (raiseCount_ != 0) || (localTxnLoadFee_ != lftNormalFee) ||
(clusterTxnLoadFee_ != lftNormalFee);
}
private:
static std::uint32_t constexpr lftNormalFee = 256; // 256 is the minimum/normal load factor
static std::uint32_t constexpr lftFeeIncFraction = 4; // increase fee by 1/4
static std::uint32_t constexpr lftFeeDecFraction = 4; // decrease fee by 1/4
static std::uint32_t constexpr lftNormalFee =
256; // 256 is the minimum/normal load factor
static std::uint32_t constexpr lftFeeIncFraction =
4; // increase fee by 1/4
static std::uint32_t constexpr lftFeeDecFraction =
4; // decrease fee by 1/4
static std::uint32_t constexpr lftFeeMax = lftNormalFee * 1000000;
beast::Journal const j_;
std::mutex mutable lock_;
std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t localTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t remoteTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t
clusterTxnLoadFee_; // Scale factor, lftNormalFee = normal fee
std::uint32_t raiseCount_;
};
@@ -142,9 +157,12 @@ private:
// Scale using load as well as base rate
XRPAmount
scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const& feeTrack,
Fees const& fees, bool bUnlimited);
scaleFeeLoad(
FeeUnit64 fee,
LoadFeeTrack const& feeTrack,
Fees const& fees,
bool bUnlimited);
} // ripple
} // namespace ripple
#endif

View File

@@ -21,9 +21,9 @@
#define RIPPLE_APP_MISC_MANIFEST_H_INCLUDED
#include <ripple/basics/UnorderedContainers.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/protocol/PublicKey.h>
#include <ripple/protocol/SecretKey.h>
#include <ripple/beast/utility/Journal.h>
#include <boost/optional.hpp>
#include <string>
@@ -33,7 +33,7 @@ namespace ripple {
Validator key manifests
-----------------------
Suppose the secret keys installed on a Ripple validator are compromised. Not
Suppose the secret keys installed on a Ripple validator are compromised. Not
only do you have to generate and install new key pairs on each validator,
EVERY rippled needs to have its config updated with the new public keys, and
is vulnerable to forged validation signatures until this is done. The
@@ -94,24 +94,31 @@ struct Manifest
Manifest() = default;
Manifest(Manifest const& other) = delete;
Manifest& operator=(Manifest const& other) = delete;
Manifest&
operator=(Manifest const& other) = delete;
Manifest(Manifest&& other) = default;
Manifest& operator=(Manifest&& other) = default;
Manifest&
operator=(Manifest&& other) = default;
/// Returns `true` if manifest signature is valid
bool verify () const;
bool
verify() const;
/// Returns hash of serialized manifest data
uint256 hash () const;
uint256
hash() const;
/// Returns `true` if manifest revokes master key
bool revoked () const;
bool
revoked() const;
/// Returns manifest signature
boost::optional<Blob> getSignature () const;
boost::optional<Blob>
getSignature() const;
/// Returns manifest master key signature
Blob getMasterSignature () const;
Blob
getMasterSignature() const;
};
/** Constructs Manifest from serialized string
@@ -127,15 +134,16 @@ struct Manifest
boost::optional<Manifest>
deserializeManifest(Slice s);
inline
boost::optional<Manifest>
inline boost::optional<Manifest>
deserializeManifest(std::string const& s)
{
return deserializeManifest(makeSlice(s));
}
template <class T, class = std::enable_if_t<
std::is_same<T, char>::value || std::is_same<T, unsigned char>::value>>
template <
class T,
class = std::enable_if_t<
std::is_same<T, char>::value || std::is_same<T, unsigned char>::value>>
boost::optional<Manifest>
deserializeManifest(std::vector<T> const& v)
{
@@ -143,21 +151,17 @@ deserializeManifest(std::vector<T> const& v)
}
/** @} */
inline
bool
inline bool
operator==(Manifest const& lhs, Manifest const& rhs)
{
// In theory, comparing the two serialized strings should be
// sufficient.
return lhs.sequence == rhs.sequence &&
lhs.masterKey == rhs.masterKey &&
lhs.signingKey == rhs.signingKey &&
lhs.domain == rhs.domain &&
return lhs.sequence == rhs.sequence && lhs.masterKey == rhs.masterKey &&
lhs.signingKey == rhs.signingKey && lhs.domain == rhs.domain &&
lhs.serialized == rhs.serialized;
}
inline
bool
inline bool
operator!=(Manifest const& lhs, Manifest const& rhs)
{
return !(lhs == rhs);
@@ -179,8 +183,7 @@ public:
make_ValidatorToken(std::vector<std::string> const& tokenBlob);
};
enum class ManifestDisposition
{
enum class ManifestDisposition {
/// Manifest is valid
accepted = 0,
@@ -218,16 +221,15 @@ private:
std::mutex mutable read_mutex_;
/** Active manifests stored by master public key. */
hash_map <PublicKey, Manifest> map_;
hash_map<PublicKey, Manifest> map_;
/** Master public keys stored by current ephemeral public key. */
hash_map <PublicKey, PublicKey> signingToMasterKeys_;
hash_map<PublicKey, PublicKey> signingToMasterKeys_;
public:
explicit
ManifestCache (beast::Journal j =
beast::Journal(beast::Journal::getNullSink()))
: j_ (j)
explicit ManifestCache(
beast::Journal j = beast::Journal(beast::Journal::getNullSink()))
: j_(j)
{
}
@@ -242,7 +244,7 @@ public:
May be called concurrently
*/
PublicKey
getSigningKey (PublicKey const& pk) const;
getSigningKey(PublicKey const& pk) const;
/** Returns ephemeral signing key's master public key.
@@ -255,7 +257,7 @@ public:
May be called concurrently
*/
PublicKey
getMasterKey (PublicKey const& pk) const;
getMasterKey(PublicKey const& pk) const;
/** Returns master key's current manifest sequence.
@@ -263,7 +265,7 @@ public:
if configured or boost::none otherwise
*/
boost::optional<std::uint32_t>
getSequence (PublicKey const& pk) const;
getSequence(PublicKey const& pk) const;
/** Returns domain claimed by a given public key
@@ -271,7 +273,7 @@ public:
if present, otherwise boost::none
*/
boost::optional<std::string>
getDomain (PublicKey const& pk) const;
getDomain(PublicKey const& pk) const;
/** Returns mainfest corresponding to a given public key
@@ -279,7 +281,7 @@ public:
if present, otherwise boost::none
*/
boost::optional<std::string>
getManifest (PublicKey const& pk) const;
getManifest(PublicKey const& pk) const;
/** Returns `true` if master key has been revoked in a manifest.
@@ -290,7 +292,7 @@ public:
May be called concurrently
*/
bool
revoked (PublicKey const& pk) const;
revoked(PublicKey const& pk) const;
/** Add manifest to cache.
@@ -304,8 +306,7 @@ public:
May be called concurrently
*/
ManifestDisposition
applyManifest (
Manifest m);
applyManifest(Manifest m);
/** Populate manifest cache with manifests in database and config.
@@ -323,8 +324,10 @@ public:
May be called concurrently
*/
bool load (
DatabaseCon& dbCon, std::string const& dbTable,
bool
load(
DatabaseCon& dbCon,
std::string const& dbTable,
std::string const& configManifest,
std::vector<std::string> const& configRevocation);
@@ -338,8 +341,8 @@ public:
May be called concurrently
*/
void load (
DatabaseCon& dbCon, std::string const& dbTable);
void
load(DatabaseCon& dbCon, std::string const& dbTable);
/** Save cached manifests to database.
@@ -351,9 +354,11 @@ public:
May be called concurrently
*/
void save (
DatabaseCon& dbCon, std::string const& dbTable,
std::function <bool (PublicKey const&)> isTrusted);
void
save(
DatabaseCon& dbCon,
std::string const& dbTable,
std::function<bool(PublicKey const&)> isTrusted);
/** Invokes the callback once for every populated manifest.
@@ -397,7 +402,7 @@ public:
for_each_manifest(PreFun&& pf, EachFun&& f) const
{
std::lock_guard lock{read_mutex_};
pf(map_.size ());
pf(map_.size());
for (auto const& [_, manifest] : map_)
{
(void)_;
@@ -406,6 +411,6 @@ public:
}
};
} // ripple
} // namespace ripple
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -20,16 +20,16 @@
#ifndef RIPPLE_APP_MISC_NETWORKOPS_H_INCLUDED
#define RIPPLE_APP_MISC_NETWORKOPS_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/app/consensus/RCLCxPeerPos.h>
#include <ripple/app/ledger/Ledger.h>
#include <ripple/core/JobQueue.h>
#include <ripple/core/Stoppable.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/net/InfoSub.h>
#include <ripple/protocol/STValidation.h>
#include <boost/asio.hpp>
#include <memory>
#include <deque>
#include <memory>
#include <tuple>
#include <ripple/protocol/messages.h>
@@ -65,13 +65,12 @@ class ValidatorKeys;
not change them without verifying each use and ensuring that it is
not a breaking change.
*/
enum class OperatingMode
{
DISCONNECTED = 0, //!< not ready to process requests
CONNECTED = 1, //!< convinced we are talking to the network
SYNCING = 2, //!< fallen slightly behind
TRACKING = 3, //!< convinced we agree with the network
FULL = 4 //!< we have the ledger and can even validate
enum class OperatingMode {
DISCONNECTED = 0, //!< not ready to process requests
CONNECTED = 1, //!< convinced we are talking to the network
SYNCING = 2, //!< fallen slightly behind
TRACKING = 3, //!< convinced we agree with the network
FULL = 4 //!< we have the ledger and can even validate
};
/** Provides server functionality for clients.
@@ -86,37 +85,36 @@ enum class OperatingMode
instances of rippled will need to be hardened to protect against hostile
or unreliable servers.
*/
class NetworkOPs
: public InfoSub::Source
class NetworkOPs : public InfoSub::Source
{
protected:
explicit NetworkOPs (Stoppable& parent);
explicit NetworkOPs(Stoppable& parent);
public:
using clock_type = beast::abstract_clock <std::chrono::steady_clock>;
using clock_type = beast::abstract_clock<std::chrono::steady_clock>;
enum class FailHard : unsigned char
{
no,
yes
};
static inline FailHard doFailHard (bool noMeansDont)
enum class FailHard : unsigned char { no, yes };
static inline FailHard
doFailHard(bool noMeansDont)
{
return noMeansDont ? FailHard::yes : FailHard::no;
}
public:
~NetworkOPs () override = default;
~NetworkOPs() override = default;
//--------------------------------------------------------------------------
//
// Network information
//
virtual OperatingMode getOperatingMode () const = 0;
virtual std::string strOperatingMode (
OperatingMode const mode, bool const admin = false) const = 0;
virtual std::string strOperatingMode (bool const admin = false) const = 0;
virtual OperatingMode
getOperatingMode() const = 0;
virtual std::string
strOperatingMode(OperatingMode const mode, bool const admin = false)
const = 0;
virtual std::string
strOperatingMode(bool const admin = false) const = 0;
//--------------------------------------------------------------------------
//
@@ -124,7 +122,8 @@ public:
//
// must complete immediately
virtual void submitTransaction (std::shared_ptr<STTx const> const&) = 0;
virtual void
submitTransaction(std::shared_ptr<STTx const> const&) = 0;
/**
* Process transactions as they arrive from the network or which are
@@ -135,15 +134,21 @@ public:
* @param bLocal Client submission.
* @param failType fail_hard setting from transaction submission.
*/
virtual void processTransaction (std::shared_ptr<Transaction>& transaction,
bool bUnlimited, bool bLocal, FailHard failType) = 0;
virtual void
processTransaction(
std::shared_ptr<Transaction>& transaction,
bool bUnlimited,
bool bLocal,
FailHard failType) = 0;
//--------------------------------------------------------------------------
//
// Owner functions
//
virtual Json::Value getOwnerInfo (std::shared_ptr<ReadView const> lpLedger,
virtual Json::Value
getOwnerInfo(
std::shared_ptr<ReadView const> lpLedger,
AccountID const& account) = 0;
//--------------------------------------------------------------------------
@@ -151,7 +156,8 @@ public:
// Book functions
//
virtual void getBookPage (
virtual void
getBookPage(
std::shared_ptr<ReadView const>& lpLedger,
Book const& book,
AccountID const& uTakerID,
@@ -163,38 +169,58 @@ public:
//--------------------------------------------------------------------------
// ledger proposal/close functions
virtual void processTrustedProposal (RCLCxPeerPos peerPos,
virtual void
processTrustedProposal(
RCLCxPeerPos peerPos,
std::shared_ptr<protocol::TMProposeSet> set) = 0;
virtual bool recvValidation (STValidation::ref val,
std::string const& source) = 0;
virtual bool
recvValidation(STValidation::ref val, std::string const& source) = 0;
virtual void mapComplete (std::shared_ptr<SHAMap> const& map,
bool fromAcquire) = 0;
virtual void
mapComplete(std::shared_ptr<SHAMap> const& map, bool fromAcquire) = 0;
// network state machine
virtual bool beginConsensus (uint256 const& netLCL) = 0;
virtual void endConsensus () = 0;
virtual void setStandAlone () = 0;
virtual void setStateTimer () = 0;
virtual bool
beginConsensus(uint256 const& netLCL) = 0;
virtual void
endConsensus() = 0;
virtual void
setStandAlone() = 0;
virtual void
setStateTimer() = 0;
virtual void setNeedNetworkLedger () = 0;
virtual void clearNeedNetworkLedger () = 0;
virtual bool isNeedNetworkLedger () = 0;
virtual bool isFull () = 0;
virtual void setMode(OperatingMode om) = 0;
virtual bool isAmendmentBlocked () = 0;
virtual void setAmendmentBlocked () = 0;
virtual bool isAmendmentWarned() = 0;
virtual void setAmendmentWarned() = 0;
virtual void clearAmendmentWarned() = 0;
virtual void consensusViewChange () = 0;
virtual void
setNeedNetworkLedger() = 0;
virtual void
clearNeedNetworkLedger() = 0;
virtual bool
isNeedNetworkLedger() = 0;
virtual bool
isFull() = 0;
virtual void
setMode(OperatingMode om) = 0;
virtual bool
isAmendmentBlocked() = 0;
virtual void
setAmendmentBlocked() = 0;
virtual bool
isAmendmentWarned() = 0;
virtual void
setAmendmentWarned() = 0;
virtual void
clearAmendmentWarned() = 0;
virtual void
consensusViewChange() = 0;
virtual Json::Value getConsensusInfo () = 0;
virtual Json::Value getServerInfo (
bool human, bool admin, bool counters) = 0;
virtual void clearLedgerFetch () = 0;
virtual Json::Value getLedgerFetchInfo () = 0;
virtual Json::Value
getConsensusInfo() = 0;
virtual Json::Value
getServerInfo(bool human, bool admin, bool counters) = 0;
virtual void
clearLedgerFetch() = 0;
virtual Json::Value
getLedgerFetchInfo() = 0;
/** Accepts the current transaction tree, return the new ledger's sequence
@@ -202,15 +228,21 @@ public:
performs a virtual consensus round, with all the transactions we are
proposing being accepted.
*/
virtual std::uint32_t acceptLedger (
boost::optional<std::chrono::milliseconds> consensusDelay = boost::none) = 0;
virtual std::uint32_t
acceptLedger(
boost::optional<std::chrono::milliseconds> consensusDelay =
boost::none) = 0;
virtual uint256 getConsensusLCL () = 0;
virtual uint256
getConsensusLCL() = 0;
virtual void reportFeeChange () = 0;
virtual void
reportFeeChange() = 0;
virtual void updateLocalTx (ReadView const& newValidLedger) = 0;
virtual std::size_t getLocalTxCount () = 0;
virtual void
updateLocalTx(ReadView const& newValidLedger) = 0;
virtual std::size_t
getLocalTxCount() = 0;
struct AccountTxMarker
{
@@ -219,13 +251,18 @@ public:
};
// client information retrieval functions
using AccountTx = std::pair<std::shared_ptr<Transaction>, TxMeta::pointer>;
using AccountTx = std::pair<std::shared_ptr<Transaction>, TxMeta::pointer>;
using AccountTxs = std::vector<AccountTx>;
virtual AccountTxs getAccountTxs (
virtual AccountTxs
getAccountTxs(
AccountID const& account,
std::int32_t minLedger, std::int32_t maxLedger, bool descending,
std::uint32_t offset, int limit, bool bUnlimited) = 0;
std::int32_t minLedger,
std::int32_t maxLedger,
bool descending,
std::uint32_t offset,
int limit,
bool bUnlimited) = 0;
virtual AccountTxs
getTxsAccount(
@@ -238,11 +275,17 @@ public:
bool bUnlimited) = 0;
using txnMetaLedgerType = std::tuple<Blob, Blob, std::uint32_t>;
using MetaTxsList = std::vector<txnMetaLedgerType>;
using MetaTxsList = std::vector<txnMetaLedgerType>;
virtual MetaTxsList getAccountTxsB (AccountID const& account,
std::int32_t minLedger, std::int32_t maxLedger, bool descending,
std::uint32_t offset, int limit, bool bUnlimited) = 0;
virtual MetaTxsList
getAccountTxsB(
AccountID const& account,
std::int32_t minLedger,
std::int32_t maxLedger,
bool descending,
std::uint32_t offset,
int limit,
bool bUnlimited) = 0;
virtual MetaTxsList
getTxsAccountB(
@@ -258,26 +301,34 @@ public:
//
// Monitoring: publisher side
//
virtual void pubLedger (
std::shared_ptr<ReadView const> const& lpAccepted) = 0;
virtual void pubProposedTransaction (
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;
virtual void pubValidation (STValidation::ref val) = 0;
std::shared_ptr<STTx const> const& stTxn,
TER terResult) = 0;
virtual void
pubValidation(STValidation::ref val) = 0;
};
//------------------------------------------------------------------------------
std::unique_ptr<NetworkOPs>
make_NetworkOPs (Application& app, NetworkOPs::clock_type& clock,
bool standalone, std::size_t minPeerCount, bool start_valid,
JobQueue& job_queue, LedgerMaster& ledgerMaster, Stoppable& parent,
ValidatorKeys const & validatorKeys, boost::asio::io_service& io_svc,
beast::Journal journal, beast::insight::Collector::ptr const& collector);
make_NetworkOPs(
Application& app,
NetworkOPs::clock_type& clock,
bool standalone,
std::size_t minPeerCount,
bool start_valid,
JobQueue& job_queue,
LedgerMaster& ledgerMaster,
Stoppable& parent,
ValidatorKeys const& validatorKeys,
boost::asio::io_service& io_svc,
beast::Journal journal,
beast::insight::Collector::ptr const& collector);
} // ripple
} // namespace ripple
#endif

View File

@@ -26,8 +26,8 @@ namespace ripple {
class OrderBook
{
public:
using pointer = std::shared_ptr <OrderBook>;
using ref = std::shared_ptr <OrderBook> const&;
using pointer = std::shared_ptr<OrderBook>;
using ref = std::shared_ptr<OrderBook> const&;
using List = std::vector<pointer>;
/** Construct from a currency specification.
@@ -36,37 +36,43 @@ public:
@param book in and out currency/issuer pairs.
*/
// VFALCO NOTE what is the meaning of the index parameter?
OrderBook (uint256 const& base, Book const& book)
: mBookBase(base), mBook(book)
OrderBook(uint256 const& base, Book const& book)
: mBookBase(base), mBook(book)
{
}
uint256 const& getBookBase () const
uint256 const&
getBookBase() const
{
return mBookBase;
}
Book const& book() const
Book const&
book() const
{
return mBook;
}
Currency const& getCurrencyIn () const
Currency const&
getCurrencyIn() const
{
return mBook.in.currency;
}
Currency const& getCurrencyOut () const
Currency const&
getCurrencyOut() const
{
return mBook.out.currency;
}
AccountID const& getIssuerIn () const
AccountID const&
getIssuerIn() const
{
return mBook.in.account;
}
AccountID const& getIssuerOut () const
AccountID const&
getIssuerOut() const
{
return mBook.out.account;
}
@@ -76,6 +82,6 @@ private:
Book const mBook;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -21,9 +21,9 @@
#define RIPPLE_APP_MISC_SHAMAPSTORE_H_INCLUDED
#include <ripple/app/ledger/Ledger.h>
#include <ripple/core/Stoppable.h>
#include <ripple/nodestore/Manager.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/core/Stoppable.h>
namespace ripple {
@@ -33,39 +33,47 @@ class TransactionMaster;
* class to create database, launch online delete thread, and
* related SQLite database
*/
class SHAMapStore
: public Stoppable
class SHAMapStore : public Stoppable
{
public:
SHAMapStore (Stoppable& parent) : Stoppable ("SHAMapStore", parent) {}
SHAMapStore(Stoppable& parent) : Stoppable("SHAMapStore", parent)
{
}
/** Called by LedgerMaster every time a ledger validates. */
virtual void onLedgerClosed(std::shared_ptr<Ledger const> const& ledger) = 0;
virtual void
onLedgerClosed(std::shared_ptr<Ledger const> const& ledger) = 0;
virtual void rendezvous() const = 0;
virtual void
rendezvous() const = 0;
virtual std::uint32_t clampFetchDepth (std::uint32_t fetch_depth) const = 0;
virtual std::uint32_t
clampFetchDepth(std::uint32_t fetch_depth) const = 0;
virtual
std::unique_ptr <NodeStore::Database>
virtual std::unique_ptr<NodeStore::Database>
makeNodeStore(std::string const& name, std::int32_t readThreads) = 0;
/** Highest ledger that may be deleted. */
virtual LedgerIndex setCanDelete (LedgerIndex canDelete) = 0;
virtual LedgerIndex
setCanDelete(LedgerIndex canDelete) = 0;
/** Whether advisory delete is enabled. */
virtual bool advisoryDelete() const = 0;
virtual bool
advisoryDelete() const = 0;
/** Maximum ledger that has been deleted, or will be deleted if
* currently in the act of online deletion.
*/
virtual LedgerIndex getLastRotated() = 0;
virtual LedgerIndex
getLastRotated() = 0;
/** Highest ledger that may be deleted. */
virtual LedgerIndex getCanDelete() = 0;
virtual LedgerIndex
getCanDelete() = 0;
/** Returns the number of file descriptors that are needed. */
virtual int fdRequired() const = 0;
virtual int
fdRequired() const = 0;
};
//------------------------------------------------------------------------------
@@ -76,6 +84,6 @@ make_SHAMapStore(
Stoppable& parent,
NodeStore::Scheduler& scheduler,
beast::Journal journal);
}
} // namespace ripple
#endif

View File

@@ -17,7 +17,6 @@
*/
//==============================================================================
#include <ripple/app/ledger/TransactionMaster.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/app/misc/SHAMapStoreImp.h>
@@ -28,63 +27,58 @@
#include <boost/algorithm/string/predicate.hpp>
namespace ripple {
void SHAMapStoreImp::SavedStateDB::init (BasicConfig const& config,
std::string const& dbName)
void
SHAMapStoreImp::SavedStateDB::init(
BasicConfig const& config,
std::string const& dbName)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
open(session_, config, dbName);
session_ << "PRAGMA synchronous=FULL;";
session_ <<
"CREATE TABLE IF NOT EXISTS DbState ("
" Key INTEGER PRIMARY KEY,"
" WritableDb TEXT,"
" ArchiveDb TEXT,"
" LastRotatedLedger INTEGER"
");"
;
session_ << "CREATE TABLE IF NOT EXISTS DbState ("
" Key INTEGER PRIMARY KEY,"
" WritableDb TEXT,"
" ArchiveDb TEXT,"
" LastRotatedLedger INTEGER"
");";
session_ <<
"CREATE TABLE IF NOT EXISTS CanDelete ("
" Key INTEGER PRIMARY KEY,"
" CanDeleteSeq INTEGER"
");"
;
session_ << "CREATE TABLE IF NOT EXISTS CanDelete ("
" Key INTEGER PRIMARY KEY,"
" CanDeleteSeq INTEGER"
");";
std::int64_t count = 0;
{
boost::optional<std::int64_t> countO;
session_ <<
"SELECT COUNT(Key) FROM DbState WHERE Key = 1;"
, soci::into (countO);
session_ << "SELECT COUNT(Key) FROM DbState WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error> ("Failed to fetch Key Count from DbState.");
Throw<std::runtime_error>(
"Failed to fetch Key Count from DbState.");
count = *countO;
}
if (!count)
{
session_ <<
"INSERT INTO DbState VALUES (1, '', '', 0);";
session_ << "INSERT INTO DbState VALUES (1, '', '', 0);";
}
{
boost::optional<std::int64_t> countO;
session_ <<
"SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;"
, soci::into (countO);
session_ << "SELECT COUNT(Key) FROM CanDelete WHERE Key = 1;",
soci::into(countO);
if (!countO)
Throw<std::runtime_error> ("Failed to fetch Key Count from CanDelete.");
Throw<std::runtime_error>(
"Failed to fetch Key Count from CanDelete.");
count = *countO;
}
if (!count)
{
session_ <<
"INSERT INTO CanDelete VALUES (1, 0);";
session_ << "INSERT INTO CanDelete VALUES (1, 0);";
}
}
@@ -92,25 +86,22 @@ LedgerIndex
SHAMapStoreImp::SavedStateDB::getCanDelete()
{
LedgerIndex seq;
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
session_ <<
"SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;"
, soci::into (seq);
session_ << "SELECT CanDeleteSeq FROM CanDelete WHERE Key = 1;",
soci::into(seq);
;
return seq;
}
LedgerIndex
SHAMapStoreImp::SavedStateDB::setCanDelete (LedgerIndex canDelete)
SHAMapStoreImp::SavedStateDB::setCanDelete(LedgerIndex canDelete)
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
session_ <<
"UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;"
, soci::use (canDelete)
;
session_ << "UPDATE CanDelete SET CanDeleteSeq = :canDelete WHERE Key = 1;",
soci::use(canDelete);
return canDelete;
}
@@ -120,43 +111,36 @@ SHAMapStoreImp::SavedStateDB::getState()
{
SavedState state;
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
session_ <<
"SELECT WritableDb, ArchiveDb, LastRotatedLedger"
" FROM DbState WHERE Key = 1;"
, soci::into (state.writableDb), soci::into (state.archiveDb)
, soci::into (state.lastRotated)
;
session_ << "SELECT WritableDb, ArchiveDb, LastRotatedLedger"
" FROM DbState WHERE Key = 1;",
soci::into(state.writableDb), soci::into(state.archiveDb),
soci::into(state.lastRotated);
return state;
}
void
SHAMapStoreImp::SavedStateDB::setState (SavedState const& state)
SHAMapStoreImp::SavedStateDB::setState(SavedState const& state)
{
std::lock_guard lock (mutex_);
session_ <<
"UPDATE DbState"
" SET WritableDb = :writableDb,"
" ArchiveDb = :archiveDb,"
" LastRotatedLedger = :lastRotated"
" WHERE Key = 1;"
, soci::use (state.writableDb)
, soci::use (state.archiveDb)
, soci::use (state.lastRotated)
;
std::lock_guard lock(mutex_);
session_ << "UPDATE DbState"
" SET WritableDb = :writableDb,"
" ArchiveDb = :archiveDb,"
" LastRotatedLedger = :lastRotated"
" WHERE Key = 1;",
soci::use(state.writableDb), soci::use(state.archiveDb),
soci::use(state.lastRotated);
}
void
SHAMapStoreImp::SavedStateDB::setLastRotated (LedgerIndex seq)
SHAMapStoreImp::SavedStateDB::setLastRotated(LedgerIndex seq)
{
std::lock_guard lock (mutex_);
session_ <<
"UPDATE DbState SET LastRotatedLedger = :seq"
" WHERE Key = 1;"
, soci::use (seq)
;
std::lock_guard lock(mutex_);
session_ << "UPDATE DbState SET LastRotatedLedger = :seq"
" WHERE Key = 1;",
soci::use(seq);
}
//------------------------------------------------------------------------------
@@ -166,31 +150,30 @@ SHAMapStoreImp::SHAMapStoreImp(
Stoppable& parent,
NodeStore::Scheduler& scheduler,
beast::Journal journal)
: SHAMapStore (parent)
, app_ (app)
, scheduler_ (scheduler)
, journal_ (journal)
: SHAMapStore(parent)
, app_(app)
, scheduler_(scheduler)
, journal_(journal)
, working_(true)
, canDelete_ (std::numeric_limits <LedgerIndex>::max())
, canDelete_(std::numeric_limits<LedgerIndex>::max())
{
Config& config {app.config()};
Section& section {config.section(ConfigSection::nodeDatabase())};
Config& config{app.config()};
Section& section{config.section(ConfigSection::nodeDatabase())};
if (section.empty())
{
Throw<std::runtime_error>(
"Missing [" + ConfigSection::nodeDatabase() +
"] entry in configuration file");
}
// RocksDB only. Use sensible defaults if no values specified.
if (boost::iequals(
get<std::string>(section, "type"), "RocksDB"))
if (boost::iequals(get<std::string>(section, "type"), "RocksDB"))
{
if (!section.exists("cache_mb"))
{
section.set("cache_mb", std::to_string(
config.getValueFor(SizedItem::hashNodeDBCache)));
section.set(
"cache_mb",
std::to_string(config.getValueFor(SizedItem::hashNodeDBCache)));
}
if (!section.exists("filter_bits") && (config.NODE_SIZE >= 2))
@@ -206,19 +189,22 @@ SHAMapStoreImp::SHAMapStoreImp(
{
get_if_exists(section, "advisory_delete", advisoryDelete_);
auto const minInterval = config.standalone() ?
minimumDeletionIntervalSA_ : minimumDeletionInterval_;
auto const minInterval = config.standalone()
? minimumDeletionIntervalSA_
: minimumDeletionInterval_;
if (deleteInterval_ < minInterval)
{
Throw<std::runtime_error>("online_delete must be at least " +
std::to_string (minInterval));
Throw<std::runtime_error>(
"online_delete must be at least " +
std::to_string(minInterval));
}
if (config.LEDGER_HISTORY > deleteInterval_)
{
Throw<std::runtime_error>(
"online_delete must not be less than ledger_history (currently " +
std::to_string (config.LEDGER_HISTORY) + ")");
"online_delete must not be less than ledger_history "
"(currently " +
std::to_string(config.LEDGER_HISTORY) + ")");
}
state_db_.init(config, dbName_);
@@ -226,22 +212,22 @@ SHAMapStoreImp::SHAMapStoreImp(
}
}
std::unique_ptr <NodeStore::Database>
std::unique_ptr<NodeStore::Database>
SHAMapStoreImp::makeNodeStore(std::string const& name, std::int32_t readThreads)
{
// Anything which calls addJob must be a descendant of the JobQueue.
// Therefore Database objects use the JobQueue as Stoppable parent.
std::unique_ptr <NodeStore::Database> db;
std::unique_ptr<NodeStore::Database> db;
if (deleteInterval_)
{
SavedState state = state_db_.getState();
auto writableBackend = makeBackendRotating(state.writableDb);
auto archiveBackend = makeBackendRotating(state.archiveDb);
if (! state.writableDb.size())
if (!state.writableDb.size())
{
state.writableDb = writableBackend->getName();
state.archiveDb = archiveBackend->getName();
state_db_.setState (state);
state_db_.setState(state);
}
// Create NodeStore with two backends to allow online deletion of data
@@ -273,11 +259,10 @@ SHAMapStoreImp::makeNodeStore(std::string const& name, std::int32_t readThreads)
}
void
SHAMapStoreImp::onLedgerClosed(
std::shared_ptr<Ledger const> const& ledger)
SHAMapStoreImp::onLedgerClosed(std::shared_ptr<Ledger const> const& ledger)
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
newLedger_ = ledger;
working_ = true;
}
@@ -290,11 +275,8 @@ SHAMapStoreImp::rendezvous() const
if (!working_)
return;
std::unique_lock <std::mutex> lock(mutex_);
rendezvous_.wait(lock, [&]
{
return !working_;
});
std::unique_lock<std::mutex> lock(mutex_);
rendezvous_.wait(lock, [&] { return !working_; });
}
int
@@ -304,12 +286,13 @@ SHAMapStoreImp::fdRequired() const
}
bool
SHAMapStoreImp::copyNode (std::uint64_t& nodeCount,
SHAMapAbstractNode const& node)
SHAMapStoreImp::copyNode(
std::uint64_t& nodeCount,
SHAMapAbstractNode const& node)
{
// Copy a single record from node to dbRotating_
dbRotating_->fetch(node.getNodeHash().as_uint256(), node.getSeq());
if (! (++nodeCount % checkHealthInterval_))
if (!(++nodeCount % checkHealthInterval_))
{
if (health())
return false;
@@ -321,7 +304,7 @@ SHAMapStoreImp::copyNode (std::uint64_t& nodeCount,
void
SHAMapStoreImp::run()
{
beast::setCurrentThreadName ("SHAMapStore");
beast::setCurrentThreadName("SHAMapStore");
lastRotated_ = state_db_.getState().lastRotated;
netOPs_ = &app_.getOPs();
ledgerMaster_ = &app_.getLedgerMaster();
@@ -331,7 +314,7 @@ SHAMapStoreImp::run()
ledgerDb_ = &app_.getLedgerDB();
if (advisoryDelete_)
canDelete_ = state_db_.getCanDelete ();
canDelete_ = state_db_.getCanDelete();
while (true)
{
@@ -339,7 +322,7 @@ SHAMapStoreImp::run()
std::shared_ptr<Ledger const> validatedLedger;
{
std::unique_lock <std::mutex> lock (mutex_);
std::unique_lock<std::mutex> lock(mutex_);
working_ = false;
rendezvous_.notify_all();
if (stop_)
@@ -347,7 +330,7 @@ SHAMapStoreImp::run()
stopped();
return;
}
cond_.wait (lock);
cond_.wait(lock);
if (newLedger_)
{
validatedLedger = std::move(newLedger_);
@@ -360,16 +343,17 @@ SHAMapStoreImp::run()
if (!lastRotated_)
{
lastRotated_ = validatedSeq;
state_db_.setLastRotated (lastRotated_);
state_db_.setLastRotated(lastRotated_);
}
// will delete up to (not including) lastRotated_
if (validatedSeq >= lastRotated_ + deleteInterval_
&& canDelete_ >= lastRotated_ - 1)
if (validatedSeq >= lastRotated_ + deleteInterval_ &&
canDelete_ >= lastRotated_ - 1)
{
JLOG(journal_.warn()) << "rotating validatedSeq " << validatedSeq
<< " lastRotated_ " << lastRotated_ << " deleteInterval "
<< deleteInterval_ << " canDelete_ " << canDelete_;
JLOG(journal_.warn())
<< "rotating validatedSeq " << validatedSeq << " lastRotated_ "
<< lastRotated_ << " deleteInterval " << deleteInterval_
<< " canDelete_ " << canDelete_;
switch (health())
{
@@ -379,11 +363,10 @@ SHAMapStoreImp::run()
case Health::unhealthy:
continue;
case Health::ok:
default:
;
default:;
}
clearPrior (lastRotated_);
clearPrior(lastRotated_);
switch (health())
{
case Health::stopping:
@@ -392,17 +375,17 @@ SHAMapStoreImp::run()
case Health::unhealthy:
continue;
case Health::ok:
default:
;
default:;
}
std::uint64_t nodeCount = 0;
validatedLedger->stateMap().snapShot (
false)->visitNodes (
std::bind (&SHAMapStoreImp::copyNode, this,
std::ref(nodeCount), std::placeholders::_1));
validatedLedger->stateMap().snapShot(false)->visitNodes(std::bind(
&SHAMapStoreImp::copyNode,
this,
std::ref(nodeCount),
std::placeholders::_1));
JLOG(journal_.debug()) << "copied ledger " << validatedSeq
<< " nodecount " << nodeCount;
<< " nodecount " << nodeCount;
switch (health())
{
case Health::stopping:
@@ -411,8 +394,7 @@ SHAMapStoreImp::run()
case Health::unhealthy:
continue;
case Health::ok:
default:
;
default:;
}
freshenCaches();
@@ -425,15 +407,14 @@ SHAMapStoreImp::run()
case Health::unhealthy:
continue;
case Health::ok:
default:
;
default:;
}
auto newBackend = makeBackendRotating();
JLOG(journal_.debug()) << validatedSeq << " new backend "
<< newBackend->getName();
JLOG(journal_.debug())
<< validatedSeq << " new backend " << newBackend->getName();
clearCaches (validatedSeq);
clearCaches(validatedSeq);
switch (health())
{
case Health::stopping:
@@ -442,8 +423,7 @@ SHAMapStoreImp::run()
case Health::unhealthy:
continue;
case Health::ok:
default:
;
default:;
}
std::string nextArchiveDir =
@@ -451,14 +431,13 @@ SHAMapStoreImp::run()
lastRotated_ = validatedSeq;
std::shared_ptr<NodeStore::Backend> oldBackend;
{
std::lock_guard lock (dbRotating_->peekMutex());
std::lock_guard lock(dbRotating_->peekMutex());
state_db_.setState (SavedState {newBackend->getName(),
nextArchiveDir, lastRotated_});
clearCaches (validatedSeq);
oldBackend = dbRotating_->rotateBackends(
std::move(newBackend),
lock);
state_db_.setState(SavedState{
newBackend->getName(), nextArchiveDir, lastRotated_});
clearCaches(validatedSeq);
oldBackend =
dbRotating_->rotateBackends(std::move(newBackend), lock);
}
JLOG(journal_.warn()) << "finished rotation " << validatedSeq;
@@ -470,35 +449,33 @@ SHAMapStoreImp::run()
void
SHAMapStoreImp::dbPaths()
{
Section section {app_.config().section(ConfigSection::nodeDatabase())};
Section section{app_.config().section(ConfigSection::nodeDatabase())};
boost::filesystem::path dbPath = get<std::string>(section, "path");
if (boost::filesystem::exists (dbPath))
if (boost::filesystem::exists(dbPath))
{
if (! boost::filesystem::is_directory (dbPath))
if (!boost::filesystem::is_directory(dbPath))
{
journal_.error() << "node db path must be a directory. "
<< dbPath.string();
Throw<std::runtime_error> (
"node db path must be a directory.");
journal_.error()
<< "node db path must be a directory. " << dbPath.string();
Throw<std::runtime_error>("node db path must be a directory.");
}
}
else
{
boost::filesystem::create_directories (dbPath);
boost::filesystem::create_directories(dbPath);
}
SavedState state = state_db_.getState();
{
auto update = [&dbPath](std::string& sPath)
{
auto update = [&dbPath](std::string& sPath) {
if (sPath.empty())
return false;
// Check if configured "path" matches stored directory path
using namespace boost::filesystem;
auto const stored {path(sPath)};
auto const stored{path(sPath)};
if (stored.parent_path() == dbPath)
return false;
@@ -516,50 +493,51 @@ SHAMapStoreImp::dbPaths()
bool writableDbExists = false;
bool archiveDbExists = false;
for (boost::filesystem::directory_iterator it (dbPath);
it != boost::filesystem::directory_iterator(); ++it)
for (boost::filesystem::directory_iterator it(dbPath);
it != boost::filesystem::directory_iterator();
++it)
{
if (! state.writableDb.compare (it->path().string()))
if (!state.writableDb.compare(it->path().string()))
writableDbExists = true;
else if (! state.archiveDb.compare (it->path().string()))
else if (!state.archiveDb.compare(it->path().string()))
archiveDbExists = true;
else if (! dbPrefix_.compare (it->path().stem().string()))
boost::filesystem::remove_all (it->path());
else if (!dbPrefix_.compare(it->path().stem().string()))
boost::filesystem::remove_all(it->path());
}
if ((!writableDbExists && state.writableDb.size()) ||
(!archiveDbExists && state.archiveDb.size()) ||
(writableDbExists != archiveDbExists) ||
state.writableDb.empty() != state.archiveDb.empty())
(!archiveDbExists && state.archiveDb.size()) ||
(writableDbExists != archiveDbExists) ||
state.writableDb.empty() != state.archiveDb.empty())
{
boost::filesystem::path stateDbPathName =
app_.config().legacy("database_path");
stateDbPathName /= dbName_;
stateDbPathName += "*";
journal_.error() << "state db error:\n"
<< " writableDbExists " << writableDbExists
<< " archiveDbExists " << archiveDbExists << '\n'
<< " writableDb '" << state.writableDb
<< "' archiveDb '" << state.archiveDb << "\n\n"
<< "The existing data is in a corrupted state.\n"
<< "To resume operation, remove the files matching "
<< stateDbPathName.string()
<< " and contents of the directory "
<< get<std::string>(section, "path") << '\n'
<< "Optionally, you can move those files to another\n"
<< "location if you wish to analyze or back up the data.\n"
<< "However, there is no guarantee that the data in its\n"
<< "existing form is usable.";
journal_.error()
<< "state db error:\n"
<< " writableDbExists " << writableDbExists << " archiveDbExists "
<< archiveDbExists << '\n'
<< " writableDb '" << state.writableDb << "' archiveDb '"
<< state.archiveDb << "\n\n"
<< "The existing data is in a corrupted state.\n"
<< "To resume operation, remove the files matching "
<< stateDbPathName.string() << " and contents of the directory "
<< get<std::string>(section, "path") << '\n'
<< "Optionally, you can move those files to another\n"
<< "location if you wish to analyze or back up the data.\n"
<< "However, there is no guarantee that the data in its\n"
<< "existing form is usable.";
Throw<std::runtime_error> ("state db error");
Throw<std::runtime_error>("state db error");
}
}
std::unique_ptr <NodeStore::Backend>
SHAMapStoreImp::makeBackendRotating (std::string path)
std::unique_ptr<NodeStore::Backend>
SHAMapStoreImp::makeBackendRotating(std::string path)
{
Section section {app_.config().section(ConfigSection::nodeDatabase())};
Section section{app_.config().section(ConfigSection::nodeDatabase())};
boost::filesystem::path newPath;
if (path.size())
@@ -571,26 +549,27 @@ SHAMapStoreImp::makeBackendRotating (std::string path)
boost::filesystem::path p = get<std::string>(section, "path");
p /= dbPrefix_;
p += ".%%%%";
newPath = boost::filesystem::unique_path (p);
newPath = boost::filesystem::unique_path(p);
}
section.set("path", newPath.string());
auto backend {NodeStore::Manager::instance().make_Backend(
auto backend{NodeStore::Manager::instance().make_Backend(
section, scheduler_, app_.logs().journal(nodeStoreName_))};
backend->open();
return backend;
}
bool
SHAMapStoreImp::clearSql (DatabaseCon& database,
LedgerIndex lastRotated,
std::string const& minQuery,
std::string const& deleteQuery)
SHAMapStoreImp::clearSql(
DatabaseCon& database,
LedgerIndex lastRotated,
std::string const& minQuery,
std::string const& deleteQuery)
{
LedgerIndex min = std::numeric_limits <LedgerIndex>::max();
LedgerIndex min = std::numeric_limits<LedgerIndex>::max();
{
auto db = database.checkoutDb ();
auto db = database.checkoutDb();
boost::optional<std::uint64_t> m;
*db << minQuery, soci::into(m);
if (!m)
@@ -598,71 +577,76 @@ SHAMapStoreImp::clearSql (DatabaseCon& database,
min = *m;
}
if(min > lastRotated || health() != Health::ok)
if (min > lastRotated || health() != Health::ok)
return false;
boost::format formattedDeleteQuery (deleteQuery);
boost::format formattedDeleteQuery(deleteQuery);
JLOG(journal_.debug()) <<
"start: " << deleteQuery << " from " << min << " to " << lastRotated;
JLOG(journal_.debug()) << "start: " << deleteQuery << " from " << min
<< " to " << lastRotated;
while (min < lastRotated)
{
min = std::min(lastRotated, min + deleteBatch_);
{
auto db = database.checkoutDb ();
*db << boost::str (formattedDeleteQuery % min);
auto db = database.checkoutDb();
*db << boost::str(formattedDeleteQuery % min);
}
if (health())
return true;
if (min < lastRotated)
std::this_thread::sleep_for (
std::chrono::milliseconds (backOff_));
std::this_thread::sleep_for(std::chrono::milliseconds(backOff_));
}
JLOG(journal_.debug()) << "finished: " << deleteQuery;
return true;
}
void
SHAMapStoreImp::clearCaches (LedgerIndex validatedSeq)
SHAMapStoreImp::clearCaches(LedgerIndex validatedSeq)
{
ledgerMaster_->clearLedgerCachePrior (validatedSeq);
ledgerMaster_->clearLedgerCachePrior(validatedSeq);
fullBelowCache_->clear();
}
void
SHAMapStoreImp::freshenCaches()
{
if (freshenCache (dbRotating_->getPositiveCache()))
if (freshenCache(dbRotating_->getPositiveCache()))
return;
if (freshenCache (*treeNodeCache_))
if (freshenCache(*treeNodeCache_))
return;
if (freshenCache (app_.getMasterTransaction().getCache()))
if (freshenCache(app_.getMasterTransaction().getCache()))
return;
}
void
SHAMapStoreImp::clearPrior (LedgerIndex lastRotated)
SHAMapStoreImp::clearPrior(LedgerIndex lastRotated)
{
if (health())
return;
ledgerMaster_->clearPriorLedgers (lastRotated);
ledgerMaster_->clearPriorLedgers(lastRotated);
if (health())
return;
clearSql (*ledgerDb_, lastRotated,
clearSql(
*ledgerDb_,
lastRotated,
"SELECT MIN(LedgerSeq) FROM Ledgers;",
"DELETE FROM Ledgers WHERE LedgerSeq < %u;");
if (health())
return;
clearSql (*transactionDb_, lastRotated,
clearSql(
*transactionDb_,
lastRotated,
"SELECT MIN(LedgerSeq) FROM Transactions;",
"DELETE FROM Transactions WHERE LedgerSeq < %u;");
if (health())
return;
clearSql (*transactionDb_, lastRotated,
clearSql(
*transactionDb_,
lastRotated,
"SELECT MIN(LedgerSeq) FROM AccountTransactions;",
"DELETE FROM AccountTransactions WHERE LedgerSeq < %u;");
if (health())
@@ -673,11 +657,11 @@ SHAMapStoreImp::Health
SHAMapStoreImp::health()
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
if (stop_)
return Health::stopping;
}
if (! netOPs_)
if (!netOPs_)
return Health::ok;
constexpr static std::chrono::seconds age_threshold(60);
@@ -703,7 +687,7 @@ SHAMapStoreImp::onStop()
if (deleteInterval_)
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
stop_ = true;
}
cond_.notify_one();
@@ -720,7 +704,7 @@ SHAMapStoreImp::onChildrenStopped()
if (deleteInterval_)
{
{
std::lock_guard lock (mutex_);
std::lock_guard lock(mutex_);
stop_ = true;
}
cond_.notify_one();
@@ -743,4 +727,4 @@ make_SHAMapStore(
return std::make_unique<SHAMapStoreImp>(app, parent, scheduler, journal);
}
}
} // namespace ripple

View File

@@ -20,8 +20,8 @@
#ifndef RIPPLE_APP_MISC_SHAMAPSTOREIMP_H_INCLUDED
#define RIPPLE_APP_MISC_SHAMAPSTOREIMP_H_INCLUDED
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/misc/SHAMapStore.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/nodestore/DatabaseRotating.h>
@@ -43,12 +43,7 @@ private:
LedgerIndex lastRotated;
};
enum Health : std::uint8_t
{
ok = 0,
stopping,
unhealthy
};
enum Health : std::uint8_t { ok = 0, stopping, unhealthy };
class SavedStateDB
{
@@ -59,18 +54,24 @@ private:
// Just instantiate without any logic in case online delete is not
// configured
explicit SavedStateDB()
: journal_ {beast::Journal::getNullSink()}
{ }
explicit SavedStateDB() : journal_{beast::Journal::getNullSink()}
{
}
// opens database and, if necessary, creates & initializes its tables.
void init (BasicConfig const& config, std::string const& dbName);
void
init(BasicConfig const& config, std::string const& dbName);
// get/set the ledger index that we can delete up to and including
LedgerIndex getCanDelete();
LedgerIndex setCanDelete (LedgerIndex canDelete);
SavedState getState();
void setState (SavedState const& state);
void setLastRotated (LedgerIndex seq);
LedgerIndex
getCanDelete();
LedgerIndex
setCanDelete(LedgerIndex canDelete);
SavedState
getState();
void
setState(SavedState const& state);
void
setLastRotated(LedgerIndex seq);
};
Application& app_;
@@ -91,7 +92,7 @@ private:
// not including) this value. All ledgers past this value are accumulated
// until the next online deletion. This value is persisted to SQLite
// nearly immediately after modification.
std::atomic<LedgerIndex> lastRotated_ {};
std::atomic<LedgerIndex> lastRotated_{};
NodeStore::Scheduler& scheduler_;
beast::Journal const journal_;
@@ -105,7 +106,7 @@ private:
mutable std::mutex mutex_;
std::shared_ptr<Ledger const> newLedger_;
std::atomic<bool> working_;
std::atomic <LedgerIndex> canDelete_;
std::atomic<LedgerIndex> canDelete_;
int fdRequired_ = 0;
std::uint32_t deleteInterval_ = 0;
@@ -139,21 +140,21 @@ public:
}
std::uint32_t
clampFetchDepth (std::uint32_t fetch_depth) const override
clampFetchDepth(std::uint32_t fetch_depth) const override
{
return deleteInterval_ ? std::min (fetch_depth,
deleteInterval_) : fetch_depth;
return deleteInterval_ ? std::min(fetch_depth, deleteInterval_)
: fetch_depth;
}
std::unique_ptr <NodeStore::Database>
std::unique_ptr<NodeStore::Database>
makeNodeStore(std::string const& name, std::int32_t readThreads) override;
LedgerIndex
setCanDelete (LedgerIndex seq) override
setCanDelete(LedgerIndex seq) override
{
if (advisoryDelete_)
canDelete_ = seq;
return state_db_.setCanDelete (seq);
return state_db_.setCanDelete(seq);
}
bool
@@ -178,30 +179,36 @@ public:
return canDelete_;
}
void onLedgerClosed (std::shared_ptr<Ledger const> const& ledger) override;
void
onLedgerClosed(std::shared_ptr<Ledger const> const& ledger) override;
void rendezvous() const override;
int fdRequired() const override;
void
rendezvous() const override;
int
fdRequired() const override;
private:
// callback for visitNodes
bool copyNode (std::uint64_t& nodeCount, SHAMapAbstractNode const &node);
void run();
void dbPaths();
bool
copyNode(std::uint64_t& nodeCount, SHAMapAbstractNode const& node);
void
run();
void
dbPaths();
std::unique_ptr<NodeStore::Backend>
makeBackendRotating (std::string path = std::string());
makeBackendRotating(std::string path = std::string());
template <class CacheInstance>
bool
freshenCache (CacheInstance& cache)
freshenCache(CacheInstance& cache)
{
std::uint64_t check = 0;
for (auto const& key: cache.getKeys())
for (auto const& key : cache.getKeys())
{
dbRotating_->fetch(key, 0);
if (! (++check % checkHealthInterval_) && health())
if (!(++check % checkHealthInterval_) && health())
return true;
}
@@ -214,18 +221,26 @@ private:
* @return true if any deletable rows were found (though not
* necessarily deleted.
*/
bool clearSql (DatabaseCon& database, LedgerIndex lastRotated,
std::string const& minQuery, std::string const& deleteQuery);
void clearCaches (LedgerIndex validatedSeq);
void freshenCaches();
void clearPrior (LedgerIndex lastRotated);
bool
clearSql(
DatabaseCon& database,
LedgerIndex lastRotated,
std::string const& minQuery,
std::string const& deleteQuery);
void
clearCaches(LedgerIndex validatedSeq);
void
freshenCaches();
void
clearPrior(LedgerIndex lastRotated);
// If rippled is not healthy, defer rotate-delete.
// If already unhealthy, do not change state on further check.
// Assume that, once unhealthy, a necessary step has been
// aborted, so the online-delete process needs to restart
// at next ledger.
Health health();
Health
health();
//
// Stoppable
//
@@ -238,16 +253,17 @@ private:
onStart() override
{
if (deleteInterval_)
thread_ = std::thread (&SHAMapStoreImp::run, this);
thread_ = std::thread(&SHAMapStoreImp::run, this);
}
// Called when the application begins shutdown
void onStop() override;
void
onStop() override;
// Called when all child Stoppable objects have stoped
void onChildrenStopped() override;
void
onChildrenStopped() override;
};
}
} // namespace ripple
#endif

View File

@@ -20,12 +20,12 @@
#ifndef RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED
#define RIPPLE_APP_MISC_TRANSACTION_H_INCLUDED
#include <ripple/basics/RangeSet.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Protocol.h>
#include <ripple/protocol/STTx.h>
#include <ripple/protocol/TER.h>
#include <ripple/beast/utility/Journal.h>
#include <ripple/basics/RangeSet.h>
#include <boost/optional.hpp>
#include <boost/variant.hpp>
@@ -40,84 +40,95 @@ class Application;
class Database;
class Rules;
enum TransStatus
{
NEW = 0, // just received / generated
INVALID = 1, // no valid signature, insufficient funds
INCLUDED = 2, // added to the current ledger
CONFLICTED = 3, // losing to a conflicting transaction
COMMITTED = 4, // known to be in a ledger
HELD = 5, // not valid now, maybe later
REMOVED = 6, // taken out of a ledger
OBSOLETE = 7, // a compatible transaction has taken precedence
INCOMPLETE = 8 // needs more signatures
enum TransStatus {
NEW = 0, // just received / generated
INVALID = 1, // no valid signature, insufficient funds
INCLUDED = 2, // added to the current ledger
CONFLICTED = 3, // losing to a conflicting transaction
COMMITTED = 4, // known to be in a ledger
HELD = 5, // not valid now, maybe later
REMOVED = 6, // taken out of a ledger
OBSOLETE = 7, // a compatible transaction has taken precedence
INCOMPLETE = 8 // needs more signatures
};
// This class is for constructing and examining transactions.
// Transactions are static so manipulation functions are unnecessary.
class Transaction
: public std::enable_shared_from_this<Transaction>
, public CountedObject <Transaction>
class Transaction : public std::enable_shared_from_this<Transaction>,
public CountedObject<Transaction>
{
public:
static char const* getCountedObjectName () { return "Transaction"; }
static char const*
getCountedObjectName()
{
return "Transaction";
}
using pointer = std::shared_ptr<Transaction>;
using ref = const pointer&;
Transaction (
std::shared_ptr<STTx const> const&, std::string&, Application&) noexcept;
Transaction(
std::shared_ptr<STTx const> const&,
std::string&,
Application&) noexcept;
static
Transaction::pointer
transactionFromSQL (
static Transaction::pointer
transactionFromSQL(
boost::optional<std::uint64_t> const& ledgerSeq,
boost::optional<std::string> const& status,
Blob const& rawTxn,
Application& app);
static
TransStatus
static TransStatus
sqlTransactionStatus(boost::optional<std::string> const& status);
std::shared_ptr<STTx const> const& getSTransaction ()
std::shared_ptr<STTx const> const&
getSTransaction()
{
return mTransaction;
}
uint256 const& getID () const
uint256 const&
getID() const
{
return mTransactionID;
}
LedgerIndex getLedger () const
LedgerIndex
getLedger() const
{
return mInLedger;
}
TransStatus getStatus () const
TransStatus
getStatus() const
{
return mStatus;
}
TER getResult ()
TER
getResult()
{
return mResult;
}
void setResult (TER terResult)
void
setResult(TER terResult)
{
mResult = terResult;
}
void setStatus (TransStatus status, std::uint32_t ledgerSeq);
void
setStatus(TransStatus status, std::uint32_t ledgerSeq);
void setStatus (TransStatus status)
void
setStatus(TransStatus status)
{
mStatus = status;
}
void setLedger (LedgerIndex ledger)
void
setLedger(LedgerIndex ledger)
{
mInLedger = ledger;
}
@@ -125,7 +136,8 @@ public:
/**
* Set this flag once added to a batch.
*/
void setApplying()
void
setApplying()
{
mApplying = true;
}
@@ -135,7 +147,8 @@ public:
*
* @return Whether transaction is being applied within a batch.
*/
bool getApplying()
bool
getApplying()
{
return mApplying;
}
@@ -143,7 +156,8 @@ public:
/**
* Indicate that transaction application has been attempted.
*/
void clearApplying()
void
clearApplying()
{
mApplying = false;
}
@@ -153,7 +167,8 @@ public:
/**
* @brief clear Clear all states
*/
void clear()
void
clear()
{
applied = false;
broadcast = false;
@@ -165,7 +180,8 @@ public:
* @brief any Get true of any state is true
* @return True if any state if true
*/
bool any() const
bool
any() const
{
return applied || broadcast || queued || kept;
}
@@ -180,7 +196,8 @@ public:
* @brief getSubmitResult Return submit result
* @return SubmitResult struct
*/
SubmitResult getSubmitResult() const
SubmitResult
getSubmitResult() const
{
return submitResult_;
}
@@ -188,7 +205,8 @@ public:
/**
* @brief clearSubmitResult Clear all flags in SubmitResult
*/
void clearSubmitResult()
void
clearSubmitResult()
{
submitResult_.clear();
}
@@ -196,7 +214,8 @@ public:
/**
* @brief setApplied Set this flag once was applied to open ledger
*/
void setApplied()
void
setApplied()
{
submitResult_.applied = true;
}
@@ -204,7 +223,8 @@ public:
/**
* @brief setQueued Set this flag once was put into heldtxns queue
*/
void setQueued()
void
setQueued()
{
submitResult_.queued = true;
}
@@ -212,7 +232,8 @@ public:
/**
* @brief setBroadcast Set this flag once was broadcasted via network
*/
void setBroadcast()
void
setBroadcast()
{
submitResult_.broadcast = true;
}
@@ -220,7 +241,8 @@ public:
/**
* @brief setKept Set this flag once was put to localtxns queue
*/
void setKept()
void
setKept()
{
submitResult_.kept = true;
}
@@ -275,37 +297,44 @@ public:
validatedLedger, fee, accountSeq, availableSeq);
}
Json::Value getJson (JsonOptions options, bool binary = false) const;
Json::Value
getJson(JsonOptions options, bool binary = false) const;
static pointer
load (uint256 const& id, Application& app, error_code_i& ec);
load(uint256 const& id, Application& app, error_code_i& ec);
static boost::variant<Transaction::pointer, bool>
load (uint256 const& id, Application& app, ClosedInterval<uint32_t> const& range, error_code_i& ec);
private:
static boost::variant<Transaction::pointer, bool>
load (uint256 const& id, Application& app, boost::optional<ClosedInterval<uint32_t>> const& range,
load(
uint256 const& id,
Application& app,
ClosedInterval<uint32_t> const& range,
error_code_i& ec);
uint256 mTransactionID;
private:
static boost::variant<Transaction::pointer, bool>
load(
uint256 const& id,
Application& app,
boost::optional<ClosedInterval<uint32_t>> const& range,
error_code_i& ec);
LedgerIndex mInLedger = 0;
TransStatus mStatus = INVALID;
TER mResult = temUNCERTAIN;
bool mApplying = false;
uint256 mTransactionID;
LedgerIndex mInLedger = 0;
TransStatus mStatus = INVALID;
TER mResult = temUNCERTAIN;
bool mApplying = false;
/** different ways for transaction to be accepted */
SubmitResult submitResult_;
SubmitResult submitResult_;
boost::optional<CurrentLedgerState> currentLedgerState_;
std::shared_ptr<STTx const> mTransaction;
Application& mApp;
beast::Journal j_;
std::shared_ptr<STTx const> mTransaction;
Application& mApp;
beast::Journal j_;
};
} // ripple
} // namespace ripple
#endif

View File

@@ -21,12 +21,12 @@
#define RIPPLE_TXQ_H_INCLUDED
#include <ripple/app/tx/applySteps.h>
#include <ripple/ledger/OpenView.h>
#include <ripple/ledger/ApplyView.h>
#include <ripple/protocol/TER.h>
#include <ripple/ledger/OpenView.h>
#include <ripple/protocol/STTx.h>
#include <boost/intrusive/set.hpp>
#include <ripple/protocol/TER.h>
#include <boost/circular_buffer.hpp>
#include <boost/intrusive/set.hpp>
namespace ripple {
@@ -55,7 +55,7 @@ class TxQ
{
public:
/// Fee level for single-signed reference transaction.
static constexpr FeeLevel64 baseLevel{ 256 };
static constexpr FeeLevel64 baseLevel{256};
/**
Structure used to customize @ref TxQ behavior.
@@ -168,7 +168,7 @@ public:
we can make this more complicated. But avoid
bikeshedding for now.
*/
FeeLevel64 zeroBaseFeeTransactionFeeLevel{ 256000 };
FeeLevel64 zeroBaseFeeTransactionFeeLevel{256000};
/// Use standalone mode behavior.
bool standAlone = false;
};
@@ -264,8 +264,7 @@ public:
};
/// Constructor
TxQ(Setup const& setup,
beast::Journal j);
TxQ(Setup const& setup, beast::Journal j);
/// Destructor
virtual ~TxQ();
@@ -280,9 +279,12 @@ public:
will return `{ terQUEUED, false }`.
*/
std::pair<TER, bool>
apply(Application& app, OpenView& view,
apply(
Application& app,
OpenView& view,
std::shared_ptr<STTx const> const& tx,
ApplyFlags flags, beast::Journal j);
ApplyFlags flags,
beast::Journal j);
/**
Fill the new open ledger with transactions from the queue.
@@ -311,11 +313,10 @@ public:
that have no candidates under them are removed.
*/
void
processClosedLedger(Application& app,
ReadView const& view, bool timeLeap);
processClosedLedger(Application& app, ReadView const& view, bool timeLeap);
/** Returns fee metrics in reference fee level units.
*/
*/
Metrics
getMetrics(OpenView const& view) const;
@@ -336,7 +337,8 @@ public:
* and first available sequence
*/
FeeAndSeq
getTxRequiredFeeAndSeq(OpenView const& view,
getTxRequiredFeeAndSeq(
OpenView const& view,
std::shared_ptr<STTx const> const& tx) const;
/** Returns information about the transactions currently
@@ -396,15 +398,19 @@ private:
public:
/// Constructor
FeeMetrics(Setup const& setup, beast::Journal j)
: minimumTxnCount_(setup.standAlone ?
setup.minimumTxnInLedgerSA :
setup.minimumTxnInLedger)
, targetTxnCount_(setup.targetTxnInLedger < minimumTxnCount_ ?
minimumTxnCount_ : setup.targetTxnInLedger)
, maximumTxnCount_(setup.maximumTxnInLedger ?
*setup.maximumTxnInLedger < targetTxnCount_ ?
targetTxnCount_ : *setup.maximumTxnInLedger :
boost::optional<std::size_t>(boost::none))
: minimumTxnCount_(
setup.standAlone ? setup.minimumTxnInLedgerSA
: setup.minimumTxnInLedger)
, targetTxnCount_(
setup.targetTxnInLedger < minimumTxnCount_
? minimumTxnCount_
: setup.targetTxnInLedger)
, maximumTxnCount_(
setup.maximumTxnInLedger
? *setup.maximumTxnInLedger < targetTxnCount_
? targetTxnCount_
: *setup.maximumTxnInLedger
: boost::optional<std::size_t>(boost::none))
, txnsExpected_(minimumTxnCount_)
, recentTxnCounts_(setup.ledgersInQueue)
, escalationMultiplier_(setup.minimumEscalationMultiplier)
@@ -423,8 +429,10 @@ private:
@param setup Customization params.
*/
std::size_t
update(Application& app,
ReadView const& view, bool timeLeap,
update(
Application& app,
ReadView const& view,
bool timeLeap,
TxQ::Setup const& setup);
/// Snapshot of the externally relevant FeeMetrics
@@ -444,10 +452,7 @@ private:
Snapshot
getSnapshot() const
{
return {
txnsExpected_,
escalationMultiplier_
};
return {txnsExpected_, escalationMultiplier_};
}
/** Use the number of transactions in the current open ledger
@@ -458,8 +463,7 @@ private:
@return A fee level value.
*/
static
FeeLevel64
static FeeLevel64
scaleFeeLevel(Snapshot const& snapshot, OpenView const& view);
/**
@@ -492,10 +496,12 @@ private:
@return A `std::pair` as returned from @ref `mulDiv` indicating
whether the calculation result overflows.
*/
static
std::pair<bool, FeeLevel64>
escalatedSeriesFeeLevel(Snapshot const& snapshot, OpenView const& view,
std::size_t extraCount, std::size_t seriesSize);
static std::pair<bool, FeeLevel64>
escalatedSeriesFeeLevel(
Snapshot const& snapshot,
OpenView const& view,
std::size_t extraCount,
std::size_t seriesSize);
};
/**
@@ -578,10 +584,12 @@ private:
public:
/// Constructor
MaybeTx(std::shared_ptr<STTx const> const&,
TxID const& txID, FeeLevel64 feeLevel,
ApplyFlags const flags,
PreflightResult const& pfresult);
MaybeTx(
std::shared_ptr<STTx const> const&,
TxID const& txID,
FeeLevel64 feeLevel,
ApplyFlags const flags,
PreflightResult const& pfresult);
/// Attempt to apply the queued transaction to the open ledger.
std::pair<TER, bool>
@@ -596,7 +604,8 @@ private:
explicit GreaterFee() = default;
/// Is the fee level of `lhs` greater than the fee level of `rhs`?
bool operator()(const MaybeTx& lhs, const MaybeTx& rhs) const
bool
operator()(const MaybeTx& lhs, const MaybeTx& rhs) const
{
return lhs.feeLevel > rhs.feeLevel;
}
@@ -608,7 +617,7 @@ private:
class TxQAccount
{
public:
using TxMap = std::map <TxSeq, MaybeTx>;
using TxMap = std::map<TxSeq, MaybeTx>;
/// The account
AccountID const account;
@@ -662,15 +671,15 @@ private:
remove(TxSeq const& sequence);
};
using FeeHook = boost::intrusive::member_hook
<MaybeTx, boost::intrusive::set_member_hook<>,
using FeeHook = boost::intrusive::member_hook<
MaybeTx,
boost::intrusive::set_member_hook<>,
&MaybeTx::byFeeListHook>;
using FeeMultiSet = boost::intrusive::multiset
< MaybeTx, FeeHook,
boost::intrusive::compare <GreaterFee> >;
using FeeMultiSet = boost::intrusive::
multiset<MaybeTx, FeeHook, boost::intrusive::compare<GreaterFee>>;
using AccountMap = std::map <AccountID, TxQAccount>;
using AccountMap = std::map<AccountID, TxQAccount>;
/// Setup parameters used to control the behavior of the queue
Setup const setup_;
@@ -710,16 +719,20 @@ private:
private:
/// Is the queue at least `fillPercentage` full?
template<size_t fillPercentage = 100>
template <size_t fillPercentage = 100>
bool
isFull() const;
/** Checks if the indicated transaction fits the conditions
for being stored in the queue.
*/
bool canBeHeld(STTx const&, ApplyFlags const, OpenView const&,
bool
canBeHeld(
STTx const&,
ApplyFlags const,
OpenView const&,
AccountMap::iterator,
boost::optional<FeeMultiSet::iterator>);
boost::optional<FeeMultiSet::iterator>);
/// Erase and return the next entry in byFee_ (lower fee level)
FeeMultiSet::iterator_type erase(FeeMultiSet::const_iterator_type);
@@ -727,25 +740,32 @@ private:
is higher), or next entry in byFee_ (lower fee level).
Used to get the next "applyable" MaybeTx for accept().
*/
FeeMultiSet::iterator_type eraseAndAdvance(FeeMultiSet::const_iterator_type);
FeeMultiSet::iterator_type eraseAndAdvance(
FeeMultiSet::const_iterator_type);
/// Erase a range of items, based on TxQAccount::TxMap iterators
TxQAccount::TxMap::iterator
erase(TxQAccount& txQAccount, TxQAccount::TxMap::const_iterator begin,
erase(
TxQAccount& txQAccount,
TxQAccount::TxMap::const_iterator begin,
TxQAccount::TxMap::const_iterator end);
/**
All-or-nothing attempt to try to apply all the queued txs for `accountIter`
up to and including `tx`.
All-or-nothing attempt to try to apply all the queued txs for
`accountIter` up to and including `tx`.
*/
std::pair<TER, bool>
tryClearAccountQueue(Application& app, OpenView& view,
STTx const& tx, AccountMap::iterator const& accountIter,
TxQAccount::TxMap::iterator, FeeLevel64 feeLevelPaid,
PreflightResult const& pfresult,
std::size_t const txExtraCount, ApplyFlags flags,
FeeMetrics::Snapshot const& metricsSnapshot,
beast::Journal j);
tryClearAccountQueue(
Application& app,
OpenView& view,
STTx const& tx,
AccountMap::iterator const& accountIter,
TxQAccount::TxMap::iterator,
FeeLevel64 feeLevelPaid,
PreflightResult const& pfresult,
std::size_t const txExtraCount,
ApplyFlags flags,
FeeMetrics::Snapshot const& metricsSnapshot,
beast::Journal j);
};
/**
@@ -760,20 +780,19 @@ setup_TxQ(Config const&);
std::unique_ptr<TxQ>
make_TxQ(TxQ::Setup const&, beast::Journal);
template<class T>
template <class T>
std::pair<bool, XRPAmount>
toDrops(FeeLevel<T> const& level, XRPAmount const& baseFee)
{
return mulDiv(level, baseFee, TxQ::baseLevel);
}
inline
std::pair<bool, FeeLevel64>
inline std::pair<bool, FeeLevel64>
toFeeLevel(XRPAmount const& drops, XRPAmount const& baseFee)
{
return mulDiv(drops, TxQ::baseLevel, baseFee);
}
} // ripple
} // namespace ripple
#endif

View File

@@ -43,13 +43,14 @@ public:
ValidatorKeys(Config const& config, beast::Journal j);
bool configInvalid() const
bool
configInvalid() const
{
return configInvalid_;
}
private:
bool configInvalid_ = false; //< Set to true if config was invalid
bool configInvalid_ = false; //< Set to true if config was invalid
};
} // namespace ripple

View File

@@ -30,8 +30,8 @@
#include <boost/iterator/counting_iterator.hpp>
#include <boost/range/adaptors.hpp>
#include <mutex>
#include <shared_mutex>
#include <numeric>
#include <shared_mutex>
namespace ripple {
@@ -39,8 +39,7 @@ namespace ripple {
class Overlay;
class HashRouter;
enum class ListDisposition
{
enum class ListDisposition {
/// List is valid
accepted = 0,
@@ -64,7 +63,7 @@ std::string
to_string(ListDisposition disposition);
/** Changes in trusted nodes after updating validator list
*/
*/
struct TrustChanges
{
explicit TrustChanges() = default;
@@ -165,14 +164,14 @@ class ValidatorList
static const std::string filePrefix_;
public:
ValidatorList (
ValidatorList(
ManifestCache& validatorManifests,
ManifestCache& publisherManifests,
TimeKeeper& timeKeeper,
std::string const& databasePath,
beast::Journal j,
boost::optional<std::size_t> minimumQuorum = boost::none);
~ValidatorList () = default;
~ValidatorList() = default;
/** Describes the result of processing a Validator List (UNL),
including some of the information from the list which can
@@ -181,17 +180,16 @@ public:
*/
struct PublisherListStats
{
explicit PublisherListStats(ListDisposition d)
: disposition(d)
explicit PublisherListStats(ListDisposition d) : disposition(d)
{
}
PublisherListStats(ListDisposition d, PublicKey key,
bool avail, std::size_t seq)
: disposition(d)
, publisherKey(key)
, available(avail)
, sequence(seq)
PublisherListStats(
ListDisposition d,
PublicKey key,
bool avail,
std::size_t seq)
: disposition(d), publisherKey(key), available(avail), sequence(seq)
{
}
@@ -219,7 +217,7 @@ public:
@return `false` if an entry is invalid or unparsable
*/
bool
load (
load(
PublicKey const& localSigningKey,
std::vector<std::string> const& configKeys,
std::vector<std::string> const& publisherKeys);
@@ -252,7 +250,7 @@ public:
May be called concurrently
*/
PublisherListStats
applyListAndBroadcast (
applyListAndBroadcast(
std::string const& manifest,
std::string const& blob,
std::string const& signature,
@@ -285,7 +283,7 @@ public:
May be called concurrently
*/
PublisherListStats
applyList (
applyList(
std::string const& manifest,
std::string const& blob,
std::string const& signature,
@@ -321,7 +319,7 @@ public:
May be called concurrently
*/
TrustChanges
updateTrusted (hash_set<NodeID> const& seenValidators);
updateTrusted(hash_set<NodeID> const& seenValidators);
/** Get quorum value for current trusted key set
@@ -337,7 +335,7 @@ public:
@return quorum value
*/
std::size_t
quorum () const
quorum() const
{
return quorum_;
}
@@ -351,8 +349,7 @@ public:
May be called concurrently
*/
bool
trusted (
PublicKey const& identity) const;
trusted(PublicKey const& identity) const;
/** Returns `true` if public key is included on any lists
@@ -363,8 +360,7 @@ public:
May be called concurrently
*/
bool
listed (
PublicKey const& identity) const;
listed(PublicKey const& identity) const;
/** Returns master public key if public key is trusted
@@ -377,8 +373,7 @@ public:
May be called concurrently
*/
boost::optional<PublicKey>
getTrustedKey (
PublicKey const& identity) const;
getTrustedKey(PublicKey const& identity) const;
/** Returns listed master public if public key is included on any lists
@@ -391,8 +386,7 @@ public:
May be called concurrently
*/
boost::optional<PublicKey>
getListedKey (
PublicKey const& identity) const;
getListedKey(PublicKey const& identity) const;
/** Returns `true` if public key is a trusted publisher
@@ -403,8 +397,7 @@ public:
May be called concurrently
*/
bool
trustedPublisher (
PublicKey const& identity) const;
trustedPublisher(PublicKey const& identity) const;
/** Returns local validator public key
@@ -413,7 +406,7 @@ public:
May be called concurrently
*/
PublicKey
localPublicKey () const;
localPublicKey() const;
/** Invokes the callback once for every listed validation public key.
@@ -431,8 +424,7 @@ public:
May be called concurrently
*/
void
for_each_listed (
std::function<void(PublicKey const&, bool)> func) const;
for_each_listed(std::function<void(PublicKey const&, bool)> func) const;
/** Invokes the callback once for every available publisher list's raw
data members
@@ -462,12 +454,14 @@ public:
May be called concurrently
*/
void
for_each_available (
std::function<void(std::string const& manifest,
std::string const& blob, std::string const& signature,
std::uint32_t version,
PublicKey const& pubKey, std::size_t sequence,
uint256 const& hash)> func) const;
for_each_available(std::function<void(
std::string const& manifest,
std::string const& blob,
std::string const& signature,
std::uint32_t version,
PublicKey const& pubKey,
std::size_t sequence,
uint256 const& hash)> func) const;
/** Returns the current valid list for the given publisher key,
if available, as a Json object.
@@ -511,18 +505,16 @@ public:
return {quorum_, trustedSigningKeys_};
}
private:
/** Get the filename used for caching UNLs
*/
*/
boost::filesystem::path
GetCacheFileName(PublicKey const& pubKey);
/** Write a JSON UNL to a cache file
*/
*/
void
CacheValidatorFile(PublicKey const& pubKey,
PublisherList const& publisher);
CacheValidatorFile(PublicKey const& pubKey, PublisherList const& publisher);
/** Check response for trusted valid published list
@@ -533,7 +525,7 @@ private:
Calling public member function is expected to lock mutex
*/
ListDisposition
verify (
verify(
Json::Value& list,
PublicKey& pubKey,
std::string const& manifest,
@@ -551,7 +543,7 @@ private:
Calling public member function is expected to lock mutex
*/
bool
removePublisherList (PublicKey const& publisherKey);
removePublisherList(PublicKey const& publisherKey);
/** Return quorum for trusted validator set
@@ -560,9 +552,8 @@ private:
@param seen Number of trusted validators that have signed
recently received validations */
std::size_t
calculateQuorum (
std::size_t trusted, std::size_t seen);
calculateQuorum(std::size_t trusted, std::size_t seen);
};
} // ripple
} // namespace ripple
#endif

View File

@@ -20,17 +20,17 @@
#ifndef RIPPLE_APP_MISC_VALIDATORSITE_H_INCLUDED
#define RIPPLE_APP_MISC_VALIDATORSITE_H_INCLUDED
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/ValidatorList.h>
#include <ripple/app/misc/detail/Work.h>
#include <ripple/app/main/Application.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/core/Config.h>
#include <ripple/json/json_value.h>
#include <boost/asio.hpp>
#include <boost/optional.hpp>
#include <mutex>
#include <memory>
#include <mutex>
namespace ripple {
@@ -133,11 +133,11 @@ private:
const std::chrono::seconds requestTimeout_;
public:
ValidatorSite (
ValidatorSite(
Application& app,
boost::optional<beast::Journal> j = boost::none,
std::chrono::seconds timeout = std::chrono::seconds{20});
~ValidatorSite ();
~ValidatorSite();
/** Load configured site URIs.
@@ -150,8 +150,7 @@ public:
@return `false` if an entry is invalid or unparsable
*/
bool
load (
std::vector<std::string> const& siteURIs);
load(std::vector<std::string> const& siteURIs);
/** Start fetching lists from sites
@@ -162,7 +161,7 @@ public:
May be called concurrently
*/
void
start ();
start();
/** Wait for current fetches from sites to complete
@@ -171,7 +170,7 @@ public:
May be called concurrently
*/
void
join ();
join();
/** Stop fetching lists from sites
@@ -182,7 +181,7 @@ public:
May be called concurrently
*/
void
stop ();
stop();
/** Return JSON representation of configured validator sites
*/
@@ -193,23 +192,19 @@ private:
/// Queue next site to be fetched
/// lock over state_mutex_ required
void
setTimer (std::lock_guard<std::mutex>&);
setTimer(std::lock_guard<std::mutex>&);
/// request took too long
void
onRequestTimeout (
std::size_t siteIdx,
error_code const& ec);
onRequestTimeout(std::size_t siteIdx, error_code const& ec);
/// Fetch site whose time has come
void
onTimer (
std::size_t siteIdx,
error_code const& ec);
onTimer(std::size_t siteIdx, error_code const& ec);
/// Store latest list fetched from site
void
onSiteFetch (
onSiteFetch(
boost::system::error_code const& ec,
detail::response_type&& res,
std::size_t siteIdx);
@@ -224,7 +219,7 @@ private:
/// Initiate request to given resource.
/// lock over sites_mutex_ required
void
makeRequest (
makeRequest(
std::shared_ptr<Site::Resource> resource,
std::size_t siteIdx,
std::lock_guard<std::mutex>& lock);
@@ -232,7 +227,7 @@ private:
/// Parse json response from validator list site.
/// lock over sites_mutex_ required
void
parseJsonResponse (
parseJsonResponse(
std::string const& res,
std::size_t siteIdx,
std::lock_guard<std::mutex>& lock);
@@ -240,7 +235,7 @@ private:
/// Interpret a redirect response.
/// lock over sites_mutex_ required
std::shared_ptr<Site::Resource>
processRedirect (
processRedirect(
detail::response_type& res,
std::size_t siteIdx,
std::lock_guard<std::mutex>& lock);
@@ -251,6 +246,6 @@ private:
missingSite();
};
} // ripple
} // namespace ripple
#endif

View File

@@ -35,13 +35,15 @@ class Work
public:
virtual ~Work() = default;
virtual void run() = 0;
virtual void
run() = 0;
virtual void cancel() = 0;
virtual void
cancel() = 0;
};
} // detail
} // namespace detail
} // ripple
} // namespace ripple
#endif

View File

@@ -22,19 +22,18 @@
#include <ripple/app/misc/detail/Work.h>
#include <ripple/protocol/BuildInfo.h>
#include <boost/asio.hpp>
#include <boost/beast/core/multi_buffer.hpp>
#include <boost/beast/http/empty_body.hpp>
#include <boost/beast/http/read.hpp>
#include <boost/beast/http/write.hpp>
#include <boost/asio.hpp>
namespace ripple {
namespace detail {
template <class Impl>
class WorkBase
: public Work
class WorkBase : public Work
{
protected:
using error_code = boost::system::error_code;
@@ -42,6 +41,7 @@ protected:
public:
using callback_type =
std::function<void(error_code const&, response_type&&)>;
protected:
using socket_type = boost::asio::ip::tcp::socket;
using endpoint_type = boost::asio::ip::tcp::endpoint;
@@ -64,9 +64,11 @@ protected:
public:
WorkBase(
std::string const& host, std::string const& path,
std::string const& host,
std::string const& path,
std::string const& port,
boost::asio::io_service& ios, callback_type cb);
boost::asio::io_service& ios,
callback_type cb);
~WorkBase();
Impl&
@@ -75,9 +77,11 @@ public:
return *static_cast<Impl*>(this);
}
void run() override;
void
run() override;
void cancel() override;
void
cancel() override;
void
fail(error_code const& ec);
@@ -97,10 +101,13 @@ public:
//------------------------------------------------------------------------------
template<class Impl>
WorkBase<Impl>::WorkBase(std::string const& host,
std::string const& path, std::string const& port,
boost::asio::io_service& ios, callback_type cb)
template <class Impl>
WorkBase<Impl>::WorkBase(
std::string const& host,
std::string const& path,
std::string const& port,
boost::asio::io_service& ios,
callback_type cb)
: host_(host)
, path_(path)
, port_(port)
@@ -112,45 +119,47 @@ WorkBase<Impl>::WorkBase(std::string const& host,
{
}
template<class Impl>
template <class Impl>
WorkBase<Impl>::~WorkBase()
{
if (cb_)
cb_ (make_error_code(boost::system::errc::not_a_socket),
cb_(make_error_code(boost::system::errc::not_a_socket),
std::move(res_));
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::run()
{
if (! strand_.running_in_this_thread())
return ios_.post(strand_.wrap (std::bind(
&WorkBase::run, impl().shared_from_this())));
if (!strand_.running_in_this_thread())
return ios_.post(
strand_.wrap(std::bind(&WorkBase::run, impl().shared_from_this())));
resolver_.async_resolve(
query_type{host_, port_},
strand_.wrap (std::bind(&WorkBase::onResolve, impl().shared_from_this(),
strand_.wrap(std::bind(
&WorkBase::onResolve,
impl().shared_from_this(),
std::placeholders::_1,
std::placeholders::_2)));
std::placeholders::_2)));
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::cancel()
{
if (! strand_.running_in_this_thread())
if (!strand_.running_in_this_thread())
{
return ios_.post(strand_.wrap (std::bind(
&WorkBase::cancel, impl().shared_from_this())));
return ios_.post(strand_.wrap(
std::bind(&WorkBase::cancel, impl().shared_from_this())));
}
error_code ec;
resolver_.cancel();
socket_.cancel (ec);
socket_.cancel(ec);
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::fail(error_code const& ec)
{
@@ -161,47 +170,58 @@ WorkBase<Impl>::fail(error_code const& ec)
}
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::onResolve(error_code const& ec, resolver_type::iterator it)
{
if (ec)
return fail(ec);
socket_.async_connect(*it,
strand_.wrap (std::bind(&Impl::onConnect, impl().shared_from_this(),
socket_.async_connect(
*it,
strand_.wrap(std::bind(
&Impl::onConnect,
impl().shared_from_this(),
std::placeholders::_1)));
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::onStart()
{
req_.method(boost::beast::http::verb::get);
req_.target(path_.empty() ? "/" : path_);
req_.version(11);
req_.set (
"Host", host_ + ":" + port_);
req_.set ("User-Agent", BuildInfo::getFullVersionString());
req_.set("Host", host_ + ":" + port_);
req_.set("User-Agent", BuildInfo::getFullVersionString());
req_.prepare_payload();
boost::beast::http::async_write(impl().stream(), req_,
strand_.wrap (std::bind (&WorkBase::onRequest,
impl().shared_from_this(), std::placeholders::_1)));
boost::beast::http::async_write(
impl().stream(),
req_,
strand_.wrap(std::bind(
&WorkBase::onRequest,
impl().shared_from_this(),
std::placeholders::_1)));
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::onRequest(error_code const& ec)
{
if (ec)
return fail(ec);
boost::beast::http::async_read (impl().stream(), read_buf_, res_,
strand_.wrap (std::bind (&WorkBase::onResponse,
impl().shared_from_this(), std::placeholders::_1)));
boost::beast::http::async_read(
impl().stream(),
read_buf_,
res_,
strand_.wrap(std::bind(
&WorkBase::onResponse,
impl().shared_from_this(),
std::placeholders::_1)));
}
template<class Impl>
template <class Impl>
void
WorkBase<Impl>::onResponse(error_code const& ec)
{
@@ -213,8 +233,8 @@ WorkBase<Impl>::onResponse(error_code const& ec)
cb_ = nullptr;
}
} // detail
} // namespace detail
} // ripple
} // namespace ripple
#endif

View File

@@ -31,8 +31,7 @@ namespace ripple {
namespace detail {
// Work with files
class WorkFile: public Work
, public std::enable_shared_from_this<WorkFile>
class WorkFile : public Work, public std::enable_shared_from_this<WorkFile>
{
protected:
using error_code = boost::system::error_code;
@@ -42,48 +41,49 @@ protected:
public:
using callback_type =
std::function<void(error_code const&, response_type const&)>;
public:
WorkFile(
std::string const& path,
boost::asio::io_service& ios, callback_type cb);
boost::asio::io_service& ios,
callback_type cb);
~WorkFile();
void run() override;
void
run() override;
void cancel() override;
void
cancel() override;
private:
std::string path_;
callback_type cb_;
boost::asio::io_service& ios_;
boost::asio::io_service::strand strand_;
};
//------------------------------------------------------------------------------
WorkFile::WorkFile(
std::string const& path,
boost::asio::io_service& ios, callback_type cb)
: path_(path)
, cb_(std::move(cb))
, ios_(ios)
, strand_(ios)
boost::asio::io_service& ios,
callback_type cb)
: path_(path), cb_(std::move(cb)), ios_(ios), strand_(ios)
{
}
WorkFile::~WorkFile()
{
if (cb_)
cb_ (make_error_code(boost::system::errc::interrupted), {});
cb_(make_error_code(boost::system::errc::interrupted), {});
}
void
WorkFile::run()
{
if (! strand_.running_in_this_thread())
return ios_.post(strand_.wrap (std::bind(
&WorkFile::run, shared_from_this())));
if (!strand_.running_in_this_thread())
return ios_.post(
strand_.wrap(std::bind(&WorkFile::run, shared_from_this())));
error_code ec;
auto const fileContents = getFileContents(ec, path_, megabytes(1));
@@ -99,9 +99,8 @@ WorkFile::cancel()
// Nothing to do. Either it finished in run, or it didn't start.
}
} // namespace detail
} // detail
} // ripple
} // namespace ripple
#endif

View File

@@ -27,16 +27,18 @@ namespace ripple {
namespace detail {
// Work over TCP/IP
class WorkPlain : public WorkBase<WorkPlain>
, public std::enable_shared_from_this<WorkPlain>
class WorkPlain : public WorkBase<WorkPlain>,
public std::enable_shared_from_this<WorkPlain>
{
friend class WorkBase<WorkPlain>;
public:
WorkPlain(
std::string const& host,
std::string const& path, std::string const& port,
boost::asio::io_service& ios, callback_type cb);
std::string const& path,
std::string const& port,
boost::asio::io_service& ios,
callback_type cb);
~WorkPlain() = default;
private:
@@ -54,9 +56,11 @@ private:
WorkPlain::WorkPlain(
std::string const& host,
std::string const& path, std::string const& port,
boost::asio::io_service& ios, callback_type cb)
: WorkBase (host, path, port, ios, cb)
std::string const& path,
std::string const& port,
boost::asio::io_service& ios,
callback_type cb)
: WorkBase(host, path, port, ios, cb)
{
}
@@ -66,11 +70,11 @@ WorkPlain::onConnect(error_code const& ec)
if (ec)
return fail(ec);
onStart ();
onStart();
}
} // detail
} // namespace detail
} // ripple
} // namespace ripple
#endif

View File

@@ -33,8 +33,8 @@ namespace ripple {
namespace detail {
// Work over SSL
class WorkSSL : public WorkBase<WorkSSL>
, public std::enable_shared_from_this<WorkSSL>
class WorkSSL : public WorkBase<WorkSSL>,
public std::enable_shared_from_this<WorkSSL>
{
friend class WorkBase<WorkSSL>;
@@ -85,8 +85,8 @@ WorkSSL::WorkSSL(
{
auto ec = context_.preConnectVerify(stream_, host_);
if (ec)
Throw<std::runtime_error> (
boost::str (boost::format ("preConnectVerify: %s") % ec.message ()));
Throw<std::runtime_error>(
boost::str(boost::format("preConnectVerify: %s") % ec.message()));
}
void
@@ -98,7 +98,9 @@ WorkSSL::onConnect(error_code const& ec)
stream_.async_handshake(
boost::asio::ssl::stream_base::client,
strand_.wrap (boost::bind(&WorkSSL::onHandshake, shared_from_this(),
strand_.wrap(boost::bind(
&WorkSSL::onHandshake,
shared_from_this(),
boost::asio::placeholders::error)));
}
@@ -108,11 +110,11 @@ WorkSSL::onHandshake(error_code const& ec)
if (ec)
return fail(ec);
onStart ();
onStart();
}
} // detail
} // namespace detail
} // ripple
} // namespace ripple
#endif

View File

@@ -17,8 +17,8 @@
*/
//==============================================================================
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/ledger/LedgerToJson.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/misc/impl/AccountTxPaging.h>
@@ -30,7 +30,7 @@
namespace ripple {
void
convertBlobsToTxResult (
convertBlobsToTxResult(
NetworkOPs::AccountTxs& to,
std::uint32_t ledger_index,
std::string const& status,
@@ -38,23 +38,23 @@ convertBlobsToTxResult (
Blob const& rawMeta,
Application& app)
{
SerialIter it (makeSlice(rawTxn));
auto txn = std::make_shared<STTx const> (it);
SerialIter it(makeSlice(rawTxn));
auto txn = std::make_shared<STTx const>(it);
std::string reason;
auto tr = std::make_shared<Transaction> (txn, reason, app);
auto tr = std::make_shared<Transaction>(txn, reason, app);
tr->setStatus (Transaction::sqlTransactionStatus(status));
tr->setLedger (ledger_index);
tr->setStatus(Transaction::sqlTransactionStatus(status));
tr->setLedger(ledger_index);
auto metaset = std::make_shared<TxMeta> (
tr->getID (), tr->getLedger (), rawMeta);
auto metaset =
std::make_shared<TxMeta>(tr->getID(), tr->getLedger(), rawMeta);
to.emplace_back(std::move(tr), metaset);
};
void
saveLedgerAsync (Application& app, std::uint32_t seq)
saveLedgerAsync(Application& app, std::uint32_t seq)
{
if (auto l = app.getLedgerMaster().getLedgerBySeq(seq))
pendSaveValidated(app, l, false, false);
@@ -259,4 +259,4 @@ accountTxPage(
return;
}
}
} // namespace ripple

View File

@@ -20,19 +20,18 @@
#ifndef RIPPLE_APP_MISC_IMPL_ACCOUNTTXPAGING_H_INCLUDED
#define RIPPLE_APP_MISC_IMPL_ACCOUNTTXPAGING_H_INCLUDED
#include <ripple/core/DatabaseCon.h>
#include <ripple/app/misc/NetworkOPs.h>
#include <ripple/core/DatabaseCon.h>
#include <cstdint>
#include <string>
#include <utility>
//------------------------------------------------------------------------------
namespace ripple {
void
convertBlobsToTxResult (
convertBlobsToTxResult(
NetworkOPs::AccountTxs& to,
std::uint32_t ledger_index,
std::string const& status,
@@ -41,7 +40,7 @@ convertBlobsToTxResult (
Application& app);
void
saveLedgerAsync (Application& app, std::uint32_t seq);
saveLedgerAsync(Application& app, std::uint32_t seq);
void
accountTxPage(
@@ -61,6 +60,6 @@ accountTxPage(
int limit,
bool bAdmin,
std::uint32_t page_length);
}
} // namespace ripple
#endif

View File

@@ -19,11 +19,11 @@
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/AmendmentTable.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/jss.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/protocol/STValidation.h>
#include <ripple/protocol/TxFlags.h>
#include <ripple/protocol/jss.h>
#include <boost/format.hpp>
#include <boost/regex.hpp>
#include <algorithm>
@@ -31,38 +31,36 @@
namespace ripple {
static
std::vector<std::pair<uint256, std::string>>
parseSection (Section const& section)
static std::vector<std::pair<uint256, std::string>>
parseSection(Section const& section)
{
static boost::regex const re1 (
"^" // start of line
"(?:\\s*)" // whitespace (optional)
"([abcdefABCDEF0-9]{64})" // <hexadecimal amendment ID>
"(?:\\s+)" // whitespace
"(\\S+)" // <description>
, boost::regex_constants::optimize
);
static boost::regex const re1(
"^" // start of line
"(?:\\s*)" // whitespace (optional)
"([abcdefABCDEF0-9]{64})" // <hexadecimal amendment ID>
"(?:\\s+)" // whitespace
"(\\S+)" // <description>
,
boost::regex_constants::optimize);
std::vector<std::pair<uint256, std::string>> names;
for (auto const& line : section.lines ())
for (auto const& line : section.lines())
{
boost::smatch match;
if (!boost::regex_match (line, match, re1))
Throw<std::runtime_error> (
"Invalid entry '" + line +
"' in [" + section.name () + "]");
if (!boost::regex_match(line, match, re1))
Throw<std::runtime_error>(
"Invalid entry '" + line + "' in [" + section.name() + "]");
uint256 id;
if (!id.SetHexExact (match[1]))
Throw<std::runtime_error> (
"Invalid amendment ID '" + match[1] +
"' in [" + section.name () + "]");
if (!id.SetHexExact(match[1]))
Throw<std::runtime_error>(
"Invalid amendment ID '" + match[1] + "' in [" +
section.name() + "]");
names.push_back (std::make_pair (id, match[2]));
names.push_back(std::make_pair(id, match[2]));
}
return names;
@@ -90,7 +88,7 @@ struct AmendmentState
/** The name of this amendment, possibly empty. */
std::string name;
explicit AmendmentState () = default;
explicit AmendmentState() = default;
};
/** The status of all amendments requested in a given window. */
@@ -107,9 +105,10 @@ public:
// number of votes needed
int mThreshold = 0;
AmendmentSet () = default;
AmendmentSet() = default;
void tally (std::set<uint256> const& amendments)
void
tally(std::set<uint256> const& amendments)
{
++mTrustedValidations;
@@ -117,9 +116,10 @@ public:
++votes_[amendment];
}
int votes (uint256 const& amendment) const
int
votes(uint256 const& amendment) const
{
auto const& it = votes_.find (amendment);
auto const& it = votes_.find(amendment);
if (it == votes_.end())
return 0;
@@ -136,8 +136,7 @@ public:
Amendments are proposed and then adopted or rejected by the network. An
Amendment is uniquely identified by its AmendmentID, a 256-bit key.
*/
class AmendmentTableImpl final
: public AmendmentTable
class AmendmentTableImpl final : public AmendmentTable
{
protected:
std::mutex mutex_;
@@ -154,7 +153,7 @@ protected:
// The results of the last voting round - may be empty if
// we haven't participated in one yet.
std::unique_ptr <AmendmentSet> lastVote_;
std::unique_ptr<AmendmentSet> lastVote_;
// True if an unsupported amendment is enabled
bool unsupportedEnabled_;
@@ -166,15 +165,18 @@ protected:
beast::Journal const j_;
// Finds or creates state
AmendmentState* add (uint256 const& amendment);
AmendmentState*
add(uint256 const& amendment);
// Finds existing state
AmendmentState* get (uint256 const& amendment);
AmendmentState*
get(uint256 const& amendment);
void setJson (Json::Value& v, uint256 const& amendment, const AmendmentState&);
void
setJson(Json::Value& v, uint256 const& amendment, const AmendmentState&);
public:
AmendmentTableImpl (
AmendmentTableImpl(
std::chrono::seconds majorityTime,
int majorityFraction,
Section const& supported,
@@ -182,25 +184,36 @@ public:
Section const& vetoed,
beast::Journal journal);
uint256 find (std::string const& name) override;
uint256
find(std::string const& name) override;
bool veto (uint256 const& amendment) override;
bool unVeto (uint256 const& amendment) override;
bool
veto(uint256 const& amendment) override;
bool
unVeto(uint256 const& amendment) override;
bool enable (uint256 const& amendment) override;
bool disable (uint256 const& amendment) override;
bool
enable(uint256 const& amendment) override;
bool
disable(uint256 const& amendment) override;
bool isEnabled (uint256 const& amendment) override;
bool isSupported (uint256 const& amendment) override;
bool
isEnabled(uint256 const& amendment) override;
bool
isSupported(uint256 const& amendment) override;
bool hasUnsupportedEnabled () override;
bool
hasUnsupportedEnabled() override;
boost::optional<NetClock::time_point>
firstUnsupportedExpected() override;
Json::Value getJson (int) override;
Json::Value getJson (uint256 const&) override;
Json::Value
getJson(int) override;
Json::Value
getJson(uint256 const&) override;
bool needValidatedLedger (LedgerIndex seq) override;
bool
needValidatedLedger(LedgerIndex seq) override;
void
doValidatedLedger(
@@ -208,14 +221,14 @@ public:
std::set<uint256> const& enabled,
majorityAmendments_t const& majority) override;
std::vector <uint256>
doValidation (std::set<uint256> const& enabledAmendments) override;
std::vector<uint256>
doValidation(std::set<uint256> const& enabledAmendments) override;
std::vector <uint256>
getDesired () override;
std::vector<uint256>
getDesired() override;
std::map <uint256, std::uint32_t>
doVoting (
std::map<uint256, std::uint32_t>
doVoting(
NetClock::time_point closeTime,
std::set<uint256> const& enabledAmendments,
majorityAmendments_t const& majorityAmendments,
@@ -224,45 +237,43 @@ public:
//------------------------------------------------------------------------------
AmendmentTableImpl::AmendmentTableImpl (
std::chrono::seconds majorityTime,
int majorityFraction,
Section const& supported,
Section const& enabled,
Section const& vetoed,
beast::Journal journal)
: lastUpdateSeq_ (0)
, majorityTime_ (majorityTime)
, majorityFraction_ (majorityFraction)
, unsupportedEnabled_ (false)
, j_ (journal)
AmendmentTableImpl::AmendmentTableImpl(
std::chrono::seconds majorityTime,
int majorityFraction,
Section const& supported,
Section const& enabled,
Section const& vetoed,
beast::Journal journal)
: lastUpdateSeq_(0)
, majorityTime_(majorityTime)
, majorityFraction_(majorityFraction)
, unsupportedEnabled_(false)
, j_(journal)
{
assert (majorityFraction_ != 0);
assert(majorityFraction_ != 0);
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
for (auto const& a : parseSection(supported))
{
if (auto s = add (a.first))
if (auto s = add(a.first))
{
JLOG (j_.debug()) <<
"Amendment " << a.first << " is supported.";
JLOG(j_.debug()) << "Amendment " << a.first << " is supported.";
if (!a.second.empty ())
if (!a.second.empty())
s->name = a.second;
s->supported = true;
}
}
for (auto const& a : parseSection (enabled))
for (auto const& a : parseSection(enabled))
{
if (auto s = add (a.first))
if (auto s = add(a.first))
{
JLOG (j_.debug()) <<
"Amendment " << a.first << " is enabled.";
JLOG(j_.debug()) << "Amendment " << a.first << " is enabled.";
if (!a.second.empty ())
if (!a.second.empty())
s->name = a.second;
s->supported = true;
@@ -270,15 +281,14 @@ AmendmentTableImpl::AmendmentTableImpl (
}
}
for (auto const& a : parseSection (vetoed))
for (auto const& a : parseSection(vetoed))
{
// Unknown amendments are effectively vetoed already
if (auto s = get (a.first))
if (auto s = get(a.first))
{
JLOG (j_.info()) <<
"Amendment " << a.first << " is vetoed.";
JLOG(j_.info()) << "Amendment " << a.first << " is vetoed.";
if (!a.second.empty ())
if (!a.second.empty())
s->name = a.second;
s->vetoed = true;
@@ -287,17 +297,17 @@ AmendmentTableImpl::AmendmentTableImpl (
}
AmendmentState*
AmendmentTableImpl::add (uint256 const& amendmentHash)
AmendmentTableImpl::add(uint256 const& amendmentHash)
{
// call with the mutex held
return &amendmentMap_[amendmentHash];
}
AmendmentState*
AmendmentTableImpl::get (uint256 const& amendmentHash)
AmendmentTableImpl::get(uint256 const& amendmentHash)
{
// call with the mutex held
auto ret = amendmentMap_.find (amendmentHash);
auto ret = amendmentMap_.find(amendmentHash);
if (ret == amendmentMap_.end())
return nullptr;
@@ -306,9 +316,9 @@ AmendmentTableImpl::get (uint256 const& amendmentHash)
}
uint256
AmendmentTableImpl::find (std::string const& name)
AmendmentTableImpl::find(std::string const& name)
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
for (auto const& e : amendmentMap_)
{
@@ -320,10 +330,10 @@ AmendmentTableImpl::find (std::string const& name)
}
bool
AmendmentTableImpl::veto (uint256 const& amendment)
AmendmentTableImpl::veto(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = add (amendment);
std::lock_guard sl(mutex_);
auto s = add(amendment);
if (s->vetoed)
return false;
@@ -332,10 +342,10 @@ AmendmentTableImpl::veto (uint256 const& amendment)
}
bool
AmendmentTableImpl::unVeto (uint256 const& amendment)
AmendmentTableImpl::unVeto(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = get (amendment);
std::lock_guard sl(mutex_);
auto s = get(amendment);
if (!s || !s->vetoed)
return false;
@@ -344,20 +354,20 @@ AmendmentTableImpl::unVeto (uint256 const& amendment)
}
bool
AmendmentTableImpl::enable (uint256 const& amendment)
AmendmentTableImpl::enable(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = add (amendment);
std::lock_guard sl(mutex_);
auto s = add(amendment);
if (s->enabled)
return false;
s->enabled = true;
if (! s->supported)
if (!s->supported)
{
JLOG (j_.error()) <<
"Unsupported amendment " << amendment << " activated.";
JLOG(j_.error()) << "Unsupported amendment " << amendment
<< " activated.";
unsupportedEnabled_ = true;
}
@@ -365,10 +375,10 @@ AmendmentTableImpl::enable (uint256 const& amendment)
}
bool
AmendmentTableImpl::disable (uint256 const& amendment)
AmendmentTableImpl::disable(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = get (amendment);
std::lock_guard sl(mutex_);
auto s = get(amendment);
if (!s || !s->enabled)
return false;
@@ -378,25 +388,25 @@ AmendmentTableImpl::disable (uint256 const& amendment)
}
bool
AmendmentTableImpl::isEnabled (uint256 const& amendment)
AmendmentTableImpl::isEnabled(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = get (amendment);
std::lock_guard sl(mutex_);
auto s = get(amendment);
return s && s->enabled;
}
bool
AmendmentTableImpl::isSupported (uint256 const& amendment)
AmendmentTableImpl::isSupported(uint256 const& amendment)
{
std::lock_guard sl (mutex_);
auto s = get (amendment);
std::lock_guard sl(mutex_);
auto s = get(amendment);
return s && s->supported;
}
bool
AmendmentTableImpl::hasUnsupportedEnabled ()
AmendmentTableImpl::hasUnsupportedEnabled()
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
return unsupportedEnabled_;
}
@@ -407,86 +417,82 @@ AmendmentTableImpl::firstUnsupportedExpected()
return firstUnsupportedExpected_;
}
std::vector <uint256>
AmendmentTableImpl::doValidation (
std::set<uint256> const& enabled)
std::vector<uint256>
AmendmentTableImpl::doValidation(std::set<uint256> const& enabled)
{
// Get the list of amendments we support and do not
// veto, but that are not already enabled
std::vector <uint256> amendments;
amendments.reserve (amendmentMap_.size());
std::vector<uint256> amendments;
amendments.reserve(amendmentMap_.size());
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
for (auto const& e : amendmentMap_)
{
if (e.second.supported && ! e.second.vetoed &&
(enabled.count (e.first) == 0))
if (e.second.supported && !e.second.vetoed &&
(enabled.count(e.first) == 0))
{
amendments.push_back (e.first);
amendments.push_back(e.first);
}
}
}
if (! amendments.empty())
std::sort (amendments.begin (), amendments.end ());
if (!amendments.empty())
std::sort(amendments.begin(), amendments.end());
return amendments;
}
std::vector <uint256>
AmendmentTableImpl::getDesired ()
std::vector<uint256>
AmendmentTableImpl::getDesired()
{
// Get the list of amendments we support and do not veto
return doValidation({});
}
std::map <uint256, std::uint32_t>
AmendmentTableImpl::doVoting (
std::map<uint256, std::uint32_t>
AmendmentTableImpl::doVoting(
NetClock::time_point closeTime,
std::set<uint256> const& enabledAmendments,
majorityAmendments_t const& majorityAmendments,
std::vector<STValidation::pointer> const& valSet)
{
JLOG (j_.trace()) <<
"voting at " << closeTime.time_since_epoch().count() <<
": " << enabledAmendments.size() <<
", " << majorityAmendments.size() <<
", " << valSet.size();
JLOG(j_.trace()) << "voting at " << closeTime.time_since_epoch().count()
<< ": " << enabledAmendments.size() << ", "
<< majorityAmendments.size() << ", " << valSet.size();
auto vote = std::make_unique <AmendmentSet> ();
auto vote = std::make_unique<AmendmentSet>();
// process validations for ledger before flag ledger
for (auto const& val : valSet)
{
if (val->isTrusted ())
if (val->isTrusted())
{
std::set<uint256> ballot;
if (val->isFieldPresent (sfAmendments))
if (val->isFieldPresent(sfAmendments))
{
auto const choices =
val->getFieldV256 (sfAmendments);
ballot.insert (choices.begin (), choices.end ());
auto const choices = val->getFieldV256(sfAmendments);
ballot.insert(choices.begin(), choices.end());
}
vote->tally (ballot);
vote->tally(ballot);
}
}
vote->mThreshold = std::max(1,
(vote->mTrustedValidations * majorityFraction_) / 256);
vote->mThreshold =
std::max(1, (vote->mTrustedValidations * majorityFraction_) / 256);
JLOG (j_.debug()) <<
"Received " << vote->mTrustedValidations <<
" trusted validations, threshold is: " << vote->mThreshold;
JLOG(j_.debug()) << "Received " << vote->mTrustedValidations
<< " trusted validations, threshold is: "
<< vote->mThreshold;
// Map of amendments to the action to be taken for each one. The action is
// the value of the flags in the pseudo-transaction
std::map <uint256, std::uint32_t> actions;
std::map<uint256, std::uint32_t> actions;
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
// process all amendments we know of
for (auto const& entry : amendmentMap_)
@@ -494,43 +500,41 @@ AmendmentTableImpl::doVoting (
NetClock::time_point majorityTime = {};
bool const hasValMajority =
(vote->votes (entry.first) >= vote->mThreshold);
(vote->votes(entry.first) >= vote->mThreshold);
{
auto const it = majorityAmendments.find (entry.first);
if (it != majorityAmendments.end ())
auto const it = majorityAmendments.find(entry.first);
if (it != majorityAmendments.end())
majorityTime = it->second;
}
if (enabledAmendments.count (entry.first) != 0)
if (enabledAmendments.count(entry.first) != 0)
{
JLOG (j_.debug()) <<
entry.first << ": amendment already enabled";
JLOG(j_.debug())
<< entry.first << ": amendment already enabled";
}
else if (hasValMajority &&
(majorityTime == NetClock::time_point{}) &&
! entry.second.vetoed)
else if (
hasValMajority && (majorityTime == NetClock::time_point{}) &&
!entry.second.vetoed)
{
// Ledger says no majority, validators say yes
JLOG (j_.debug()) <<
entry.first << ": amendment got majority";
JLOG(j_.debug()) << entry.first << ": amendment got majority";
actions[entry.first] = tfGotMajority;
}
else if (! hasValMajority &&
(majorityTime != NetClock::time_point{}))
else if (
!hasValMajority && (majorityTime != NetClock::time_point{}))
{
// Ledger says majority, validators say no
JLOG (j_.debug()) <<
entry.first << ": amendment lost majority";
JLOG(j_.debug()) << entry.first << ": amendment lost majority";
actions[entry.first] = tfLostMajority;
}
else if ((majorityTime != NetClock::time_point{}) &&
else if (
(majorityTime != NetClock::time_point{}) &&
((majorityTime + majorityTime_) <= closeTime) &&
! entry.second.vetoed)
!entry.second.vetoed)
{
// Ledger says majority held
JLOG (j_.debug()) <<
entry.first << ": amendment majority held";
JLOG(j_.debug()) << entry.first << ": amendment majority held";
actions[entry.first] = 0;
}
}
@@ -543,9 +547,9 @@ AmendmentTableImpl::doVoting (
}
bool
AmendmentTableImpl::needValidatedLedger (LedgerIndex ledgerSeq)
AmendmentTableImpl::needValidatedLedger(LedgerIndex ledgerSeq)
{
std::lock_guard sl (mutex_);
std::lock_guard sl(mutex_);
// Is there a ledger in which an amendment could have been enabled
// between these two ledger sequences?
@@ -567,7 +571,7 @@ AmendmentTableImpl::doValidatedLedger(
// it's currently set. If it's not set when the loop is done, then any
// prior unknown amendments have lost majority.
firstUnsupportedExpected_.reset();
for (auto const& [ hash, time ] : majority)
for (auto const& [hash, time] : majority)
{
auto s = add(hash);
@@ -577,7 +581,7 @@ AmendmentTableImpl::doValidatedLedger(
if (!s->supported)
{
JLOG(j_.info()) << "Unsupported amendment " << hash
<< " reached majority at " << to_string(time);
<< " reached majority at " << to_string(time);
if (!firstUnsupportedExpected_ || firstUnsupportedExpected_ > time)
firstUnsupportedExpected_ = time;
}
@@ -587,7 +591,10 @@ AmendmentTableImpl::doValidatedLedger(
}
void
AmendmentTableImpl::setJson (Json::Value& v, const uint256& id, const AmendmentState& fs)
AmendmentTableImpl::setJson(
Json::Value& v,
const uint256& id,
const AmendmentState& fs)
{
if (!fs.name.empty())
v[jss::name] = fs.name;
@@ -600,7 +607,7 @@ AmendmentTableImpl::setJson (Json::Value& v, const uint256& id, const AmendmentS
{
auto const votesTotal = lastVote_->mTrustedValidations;
auto const votesNeeded = lastVote_->mThreshold;
auto const votesFor = lastVote_->votes (id);
auto const votesFor = lastVote_->votes(id);
v[jss::count] = votesFor;
v[jss::validations] = votesTotal;
@@ -614,36 +621,37 @@ AmendmentTableImpl::setJson (Json::Value& v, const uint256& id, const AmendmentS
}
Json::Value
AmendmentTableImpl::getJson (int)
AmendmentTableImpl::getJson(int)
{
Json::Value ret(Json::objectValue);
{
std::lock_guard sl(mutex_);
for (auto const& e : amendmentMap_)
{
setJson (ret[to_string (e.first)] = Json::objectValue,
e.first, e.second);
setJson(
ret[to_string(e.first)] = Json::objectValue, e.first, e.second);
}
}
return ret;
}
Json::Value
AmendmentTableImpl::getJson (uint256 const& amendmentID)
AmendmentTableImpl::getJson(uint256 const& amendmentID)
{
Json::Value ret = Json::objectValue;
Json::Value& jAmendment = (ret[to_string (amendmentID)] = Json::objectValue);
Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue);
{
std::lock_guard sl(mutex_);
auto a = add (amendmentID);
setJson (jAmendment, amendmentID, *a);
auto a = add(amendmentID);
setJson(jAmendment, amendmentID, *a);
}
return ret;
}
std::unique_ptr<AmendmentTable> make_AmendmentTable (
std::unique_ptr<AmendmentTable>
make_AmendmentTable(
std::chrono::seconds majorityTime,
int majorityFraction,
Section const& supported,
@@ -651,13 +659,8 @@ std::unique_ptr<AmendmentTable> make_AmendmentTable (
Section const& vetoed,
beast::Journal journal)
{
return std::make_unique<AmendmentTableImpl> (
majorityTime,
majorityFraction,
supported,
enabled,
vetoed,
journal);
return std::make_unique<AmendmentTableImpl>(
majorityTime, majorityFraction, supported, enabled, vetoed, journal);
}
} // ripple
} // namespace ripple

View File

@@ -18,14 +18,14 @@
//==============================================================================
#include <ripple/app/misc/LoadFeeTrack.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/FeeUnits.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/safe_cast.h>
#include <ripple/core/Config.h>
#include <ripple/ledger/ReadView.h>
#include <ripple/protocol/jss.h>
#include <ripple/protocol/STAmount.h>
#include <ripple/protocol/jss.h>
#include <cstdint>
#include <numeric>
@@ -34,9 +34,9 @@
namespace ripple {
bool
LoadFeeTrack::raiseLocalFee ()
LoadFeeTrack::raiseLocalFee()
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
if (++raiseCount_ < 2)
return false;
@@ -56,20 +56,20 @@ LoadFeeTrack::raiseLocalFee ()
if (origFee == localTxnLoadFee_)
return false;
JLOG(j_.debug()) << "Local load fee raised from " <<
origFee << " to " << localTxnLoadFee_;
JLOG(j_.debug()) << "Local load fee raised from " << origFee << " to "
<< localTxnLoadFee_;
return true;
}
bool
LoadFeeTrack::lowerLocalFee ()
LoadFeeTrack::lowerLocalFee()
{
std::lock_guard sl (lock_);
std::lock_guard sl(lock_);
std::uint32_t origFee = localTxnLoadFee_;
raiseCount_ = 0;
// Reduce slowly
localTxnLoadFee_ -= (localTxnLoadFee_ / lftFeeDecFraction );
localTxnLoadFee_ -= (localTxnLoadFee_ / lftFeeDecFraction);
if (localTxnLoadFee_ < lftNormalFee)
localTxnLoadFee_ = lftNormalFee;
@@ -77,8 +77,8 @@ LoadFeeTrack::lowerLocalFee ()
if (origFee == localTxnLoadFee_)
return false;
JLOG(j_.debug()) << "Local load fee lowered from " <<
origFee << " to " << localTxnLoadFee_;
JLOG(j_.debug()) << "Local load fee lowered from " << origFee << " to "
<< localTxnLoadFee_;
return true;
}
@@ -86,19 +86,20 @@ LoadFeeTrack::lowerLocalFee ()
// Scale using load as well as base rate
XRPAmount
scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const& feeTrack,
Fees const& fees, bool bUnlimited)
scaleFeeLoad(
FeeUnit64 fee,
LoadFeeTrack const& feeTrack,
Fees const& fees,
bool bUnlimited)
{
if (fee == 0)
return XRPAmount{0};
// Normally, types with different units wouldn't be mathematically
// compatible. This function is an exception.
auto lowestTerms = [](auto& a, auto& b)
{
auto value = [](auto val)
{
if constexpr(std::is_arithmetic_v<decltype(val)>)
auto lowestTerms = [](auto& a, auto& b) {
auto value = [](auto val) {
if constexpr (std::is_arithmetic_v<decltype(val)>)
return val;
else
return val.value();
@@ -127,8 +128,8 @@ scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const& feeTrack,
// The denominator of the fraction we're trying to compute.
// fees.units and lftNormalFee are both 32 bit,
// so the multiplication can't overflow.
auto den = FeeUnit64{ fees.units }
* safe_cast<std::uint64_t>(feeTrack.getLoadBase());
auto den = FeeUnit64{fees.units} *
safe_cast<std::uint64_t>(feeTrack.getLoadBase());
// Reduce fee * baseFee * feeFactor / (fees.units * lftNormalFee)
// to lowest terms.
lowestTerms(fee, den);
@@ -159,8 +160,8 @@ scaleFeeLoad(FeeUnit64 fee, LoadFeeTrack const& feeTrack,
auto const result = mulDiv(fee, baseFee, den);
if (!result.first)
Throw<std::overflow_error> ("scaleFeeLoad");
Throw<std::overflow_error>("scaleFeeLoad");
return result.second;
}
} // ripple
} // namespace ripple

View File

@@ -18,10 +18,10 @@
//==============================================================================
#include <ripple/app/misc/Manifest.h>
#include <ripple/basics/base64.h>
#include <ripple/basics/contract.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/StringUtilities.h>
#include <ripple/basics/base64.h>
#include <ripple/basics/contract.h>
#include <ripple/beast/rfc2616.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/json/json_reader.h>
@@ -34,40 +34,41 @@
namespace ripple {
boost::optional<Manifest> deserializeManifest(Slice s)
boost::optional<Manifest>
deserializeManifest(Slice s)
{
if (s.empty())
return boost::none;
static SOTemplate const manifestFormat {
// A manifest must include:
// - the master public key
{sfPublicKey, soeREQUIRED},
static SOTemplate const manifestFormat{
// A manifest must include:
// - the master public key
{sfPublicKey, soeREQUIRED},
// - a signature with that public key
{sfMasterSignature, soeREQUIRED},
// - a signature with that public key
{sfMasterSignature, soeREQUIRED},
// - a sequence number
{sfSequence, soeREQUIRED},
// - a sequence number
{sfSequence, soeREQUIRED},
// It may, optionally, contain:
// - a version number which defaults to 0
{sfVersion, soeDEFAULT},
// It may, optionally, contain:
// - a version number which defaults to 0
{sfVersion, soeDEFAULT},
// - a domain name
{sfDomain, soeOPTIONAL},
// - a domain name
{sfDomain, soeOPTIONAL},
// - an ephemeral signing key that can be changed as necessary
{sfSigningPubKey, soeOPTIONAL},
// - an ephemeral signing key that can be changed as necessary
{sfSigningPubKey, soeOPTIONAL},
// - a signature using the ephemeral signing key, if it is present
{sfSignature, soeOPTIONAL},
};
// - a signature using the ephemeral signing key, if it is present
{sfSignature, soeOPTIONAL},
};
try
{
SerialIter sit{ s };
STObject st{ sit, sfGeneric };
SerialIter sit{s};
STObject st{sit, sfGeneric};
st.applyTemplate(manifestFormat);
@@ -75,15 +76,15 @@ boost::optional<Manifest> deserializeManifest(Slice s)
if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
return boost::none;
auto const pk = st.getFieldVL (sfPublicKey);
auto const pk = st.getFieldVL(sfPublicKey);
if (! publicKeyType (makeSlice(pk)))
if (!publicKeyType(makeSlice(pk)))
return boost::none;
Manifest m;
m.serialized.assign(reinterpret_cast<char const*>(s.data()), s.size());
m.masterKey = PublicKey(makeSlice(pk));
m.sequence = st.getFieldU32 (sfSequence);
m.sequence = st.getFieldU32(sfSequence);
if (st.isFieldPresent(sfDomain))
{
@@ -93,23 +94,24 @@ boost::optional<Manifest> deserializeManifest(Slice s)
if (boost::algorithm::clamp(d.size(), 4, 128) != d.size())
return boost::none;
m.domain.assign (reinterpret_cast<char const*>(d.data()), d.size());
m.domain.assign(reinterpret_cast<char const*>(d.data()), d.size());
// This regular expression should do a decent job of weeding out
// obviously wrong domain names but it isn't perfect. It does not
// really support IDNs. If this turns out to be an issue, a more
// thorough regex can be used or this check can just be removed.
static boost::regex const re(
"^" // Beginning of line
"(" // Beginning of a segment
"(?!-)" // - must not begin with '-'
"[a-zA-Z0-9-]{1,63}" // - only alphanumeric and '-'
"(?<!-)" // - must not end with '-'
"\\." // segment separator
")+" // 1 or more segments
"[A-Za-z]{2,63}" // TLD
"$" // End of line
, boost::regex_constants::optimize);
"^" // Beginning of line
"(" // Beginning of a segment
"(?!-)" // - must not begin with '-'
"[a-zA-Z0-9-]{1,63}" // - only alphanumeric and '-'
"(?<!-)" // - must not end with '-'
"\\." // segment separator
")+" // 1 or more segments
"[A-Za-z]{2,63}" // TLD
"$" // End of line
,
boost::regex_constants::optimize);
if (!boost::regex_match(m.domain, re))
return boost::none;
@@ -140,7 +142,7 @@ boost::optional<Manifest> deserializeManifest(Slice s)
auto const spk = st.getFieldVL(sfSigningPubKey);
if (!publicKeyType (makeSlice(spk)))
if (!publicKeyType(makeSlice(spk)))
return boost::none;
m.signingKey = PublicKey(makeSlice(spk));
@@ -154,88 +156,92 @@ boost::optional<Manifest> deserializeManifest(Slice s)
}
}
template<class Stream>
template <class Stream>
Stream&
logMftAct (
logMftAct(
Stream& s,
std::string const& action,
PublicKey const& pk,
std::uint32_t seq)
{
s << "Manifest: " << action <<
";Pk: " << toBase58 (TokenType::NodePublic, pk) <<
";Seq: " << seq << ";";
s << "Manifest: " << action
<< ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
<< ";";
return s;
}
template<class Stream>
Stream& logMftAct (
template <class Stream>
Stream&
logMftAct(
Stream& s,
std::string const& action,
PublicKey const& pk,
std::uint32_t seq,
std::uint32_t oldSeq)
{
s << "Manifest: " << action <<
";Pk: " << toBase58 (TokenType::NodePublic, pk) <<
";Seq: " << seq <<
";OldSeq: " << oldSeq << ";";
s << "Manifest: " << action
<< ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
<< ";OldSeq: " << oldSeq << ";";
return s;
}
bool Manifest::verify () const
bool
Manifest::verify() const
{
STObject st (sfGeneric);
SerialIter sit (serialized.data (), serialized.size ());
st.set (sit);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
// Signing key and signature are not required for
// master key revocations
if (! revoked () && ! ripple::verify (st, HashPrefix::manifest, signingKey))
if (!revoked() && !ripple::verify(st, HashPrefix::manifest, signingKey))
return false;
return ripple::verify (
return ripple::verify(
st, HashPrefix::manifest, masterKey, sfMasterSignature);
}
uint256 Manifest::hash () const
uint256
Manifest::hash() const
{
STObject st (sfGeneric);
SerialIter sit (serialized.data (), serialized.size ());
st.set (sit);
return st.getHash (HashPrefix::manifest);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
return st.getHash(HashPrefix::manifest);
}
bool Manifest::revoked () const
bool
Manifest::revoked() const
{
/*
The maximum possible sequence number means that the master key
has been revoked.
*/
return sequence == std::numeric_limits<std::uint32_t>::max ();
return sequence == std::numeric_limits<std::uint32_t>::max();
}
boost::optional<Blob> Manifest::getSignature () const
boost::optional<Blob>
Manifest::getSignature() const
{
STObject st (sfGeneric);
SerialIter sit (serialized.data (), serialized.size ());
st.set (sit);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
if (!get(st, sfSignature))
return boost::none;
return st.getFieldVL (sfSignature);
return st.getFieldVL(sfSignature);
}
Blob Manifest::getMasterSignature () const
Blob
Manifest::getMasterSignature() const
{
STObject st (sfGeneric);
SerialIter sit (serialized.data (), serialized.size ());
st.set (sit);
return st.getFieldVL (sfMasterSignature);
STObject st(sfGeneric);
SerialIter sit(serialized.data(), serialized.size());
st.set(sit);
return st.getFieldVL(sfMasterSignature);
}
ValidatorToken::ValidatorToken(std::string const& m, SecretKey const& valSecret)
: manifest(m)
, validationSecret(valSecret)
: manifest(m), validationSecret(valSecret)
{
}
@@ -245,12 +251,13 @@ ValidatorToken::make_ValidatorToken(std::vector<std::string> const& tokenBlob)
try
{
std::string tokenStr;
tokenStr.reserve (
std::accumulate (tokenBlob.cbegin(), tokenBlob.cend(), std::size_t(0),
[] (std::size_t init, std::string const& s)
{
return init + s.size();
}));
tokenStr.reserve(std::accumulate(
tokenBlob.cbegin(),
tokenBlob.cend(),
std::size_t(0),
[](std::size_t init, std::string const& s) {
return init + s.size();
}));
for (auto const& line : tokenBlob)
tokenStr += beast::rfc2616::trim(line);
@@ -259,15 +266,16 @@ ValidatorToken::make_ValidatorToken(std::vector<std::string> const& tokenBlob)
Json::Reader r;
Json::Value token;
if (! r.parse (tokenStr, token))
if (!r.parse(tokenStr, token))
return boost::none;
if (token.isMember("manifest") && token["manifest"].isString() &&
token.isMember("validation_secret_key") &&
token["validation_secret_key"].isString())
{
auto const ret = strUnHex (token["validation_secret_key"].asString());
if (! ret || ret->empty())
auto const ret =
strUnHex(token["validation_secret_key"].asString());
if (!ret || ret->empty())
return boost::none;
return ValidatorToken(
@@ -286,79 +294,79 @@ ValidatorToken::make_ValidatorToken(std::vector<std::string> const& tokenBlob)
}
PublicKey
ManifestCache::getSigningKey (PublicKey const& pk) const
ManifestCache::getSigningKey(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
auto const iter = map_.find(pk);
if (iter != map_.end () && !iter->second.revoked ())
if (iter != map_.end() && !iter->second.revoked())
return iter->second.signingKey;
return pk;
}
PublicKey
ManifestCache::getMasterKey (PublicKey const& pk) const
ManifestCache::getMasterKey(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = signingToMasterKeys_.find (pk);
auto const iter = signingToMasterKeys_.find(pk);
if (iter != signingToMasterKeys_.end ())
if (iter != signingToMasterKeys_.end())
return iter->second;
return pk;
}
boost::optional<std::uint32_t>
ManifestCache::getSequence (PublicKey const& pk) const
ManifestCache::getSequence(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
auto const iter = map_.find(pk);
if (iter != map_.end () && !iter->second.revoked ())
if (iter != map_.end() && !iter->second.revoked())
return iter->second.sequence;
return boost::none;
}
boost::optional<std::string>
ManifestCache::getDomain (PublicKey const& pk) const
ManifestCache::getDomain(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
auto const iter = map_.find(pk);
if (iter != map_.end () && !iter->second.revoked ())
if (iter != map_.end() && !iter->second.revoked())
return iter->second.domain;
return boost::none;
}
boost::optional<std::string>
ManifestCache::getManifest (PublicKey const& pk) const
ManifestCache::getManifest(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
auto const iter = map_.find(pk);
if (iter != map_.end () && !iter->second.revoked ())
if (iter != map_.end() && !iter->second.revoked())
return iter->second.serialized;
return boost::none;
}
bool
ManifestCache::revoked (PublicKey const& pk) const
ManifestCache::revoked(PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
auto const iter = map_.find(pk);
if (iter != map_.end ())
return iter->second.revoked ();
if (iter != map_.end())
return iter->second.revoked();
return false;
}
ManifestDisposition
ManifestCache::applyManifest (Manifest m)
ManifestCache::applyManifest(Manifest m)
{
std::lock_guard applyLock{apply_mutex_};
@@ -368,8 +376,7 @@ ManifestCache::applyManifest (Manifest m)
*/
auto const iter = map_.find(m.masterKey);
if (iter != map_.end() &&
m.sequence <= iter->second.sequence)
if (iter != map_.end() && m.sequence <= iter->second.sequence)
{
/*
A manifest was received for a validator we're tracking, but
@@ -378,11 +385,16 @@ ManifestCache::applyManifest (Manifest m)
connects.
*/
if (auto stream = j_.debug())
logMftAct(stream, "Stale", m.masterKey, m.sequence, iter->second.sequence);
logMftAct(
stream,
"Stale",
m.masterKey,
m.sequence,
iter->second.sequence);
return ManifestDisposition::stale; // not a newer manifest, ignore
}
if (! m.verify())
if (!m.verify())
{
/*
A manifest's signature is invalid.
@@ -410,7 +422,7 @@ ManifestCache::applyManifest (Manifest m)
logMftAct(stream, "Revoked", m.masterKey, m.sequence);
}
if (iter == map_.end ())
if (iter == map_.end())
{
/*
This is the first received manifest for a trusted master key
@@ -420,7 +432,7 @@ ManifestCache::applyManifest (Manifest m)
if (auto stream = j_.info())
logMftAct(stream, "AcceptedNew", m.masterKey, m.sequence);
if (! revoked)
if (!revoked)
signingToMasterKeys_[m.signingKey] = m.masterKey;
auto masterKey = m.masterKey;
@@ -433,106 +445,104 @@ ManifestCache::applyManifest (Manifest m)
This is expected, but should happen infrequently.
*/
if (auto stream = j_.info())
logMftAct(stream, "AcceptedUpdate",
m.masterKey, m.sequence, iter->second.sequence);
logMftAct(
stream,
"AcceptedUpdate",
m.masterKey,
m.sequence,
iter->second.sequence);
signingToMasterKeys_.erase (iter->second.signingKey);
signingToMasterKeys_.erase(iter->second.signingKey);
if (! revoked)
if (!revoked)
signingToMasterKeys_[m.signingKey] = m.masterKey;
iter->second = std::move (m);
iter->second = std::move(m);
}
return ManifestDisposition::accepted;
}
void
ManifestCache::load (
DatabaseCon& dbCon, std::string const& dbTable)
ManifestCache::load(DatabaseCon& dbCon, std::string const& dbTable)
{
// Load manifests stored in database
std::string const sql =
"SELECT RawData FROM " + dbTable + ";";
auto db = dbCon.checkoutDb ();
soci::blob sociRawData (*db);
soci::statement st =
(db->prepare << sql,
soci::into (sociRawData));
st.execute ();
while (st.fetch ())
std::string const sql = "SELECT RawData FROM " + dbTable + ";";
auto db = dbCon.checkoutDb();
soci::blob sociRawData(*db);
soci::statement st = (db->prepare << sql, soci::into(sociRawData));
st.execute();
while (st.fetch())
{
std::string serialized;
convert (sociRawData, serialized);
convert(sociRawData, serialized);
if (auto mo = deserializeManifest(serialized))
{
if (!mo->verify())
{
JLOG(j_.warn())
<< "Unverifiable manifest in db";
JLOG(j_.warn()) << "Unverifiable manifest in db";
continue;
}
applyManifest (std::move(*mo));
applyManifest(std::move(*mo));
}
else
{
JLOG(j_.warn())
<< "Malformed manifest in database";
JLOG(j_.warn()) << "Malformed manifest in database";
}
}
}
bool
ManifestCache::load (
DatabaseCon& dbCon, std::string const& dbTable,
ManifestCache::load(
DatabaseCon& dbCon,
std::string const& dbTable,
std::string const& configManifest,
std::vector<std::string> const& configRevocation)
{
load (dbCon, dbTable);
load(dbCon, dbTable);
if (! configManifest.empty())
if (!configManifest.empty())
{
auto mo = deserializeManifest(base64_decode(configManifest));
if (! mo)
if (!mo)
{
JLOG (j_.error()) << "Malformed validator_token in config";
JLOG(j_.error()) << "Malformed validator_token in config";
return false;
}
if (mo->revoked())
{
JLOG (j_.warn()) <<
"Configured manifest revokes public key";
JLOG(j_.warn()) << "Configured manifest revokes public key";
}
if (applyManifest (std::move(*mo)) ==
ManifestDisposition::invalid)
if (applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
{
JLOG (j_.error()) << "Manifest in config was rejected";
JLOG(j_.error()) << "Manifest in config was rejected";
return false;
}
}
if (! configRevocation.empty())
if (!configRevocation.empty())
{
std::string revocationStr;
revocationStr.reserve (
std::accumulate (configRevocation.cbegin(), configRevocation.cend(), std::size_t(0),
[] (std::size_t init, std::string const& s)
{
return init + s.size();
}));
revocationStr.reserve(std::accumulate(
configRevocation.cbegin(),
configRevocation.cend(),
std::size_t(0),
[](std::size_t init, std::string const& s) {
return init + s.size();
}));
for (auto const& line : configRevocation)
revocationStr += beast::rfc2616::trim(line);
auto mo = deserializeManifest(base64_decode(revocationStr));
if (! mo || ! mo->revoked() ||
applyManifest (std::move(*mo)) == ManifestDisposition::invalid)
if (!mo || !mo->revoked() ||
applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
{
JLOG (j_.error()) << "Invalid validator key revocation in config";
JLOG(j_.error()) << "Invalid validator key revocation in config";
return false;
}
}
@@ -540,13 +550,15 @@ ManifestCache::load (
return true;
}
void ManifestCache::save (
DatabaseCon& dbCon, std::string const& dbTable,
std::function <bool (PublicKey const&)> isTrusted)
void
ManifestCache::save(
DatabaseCon& dbCon,
std::string const& dbTable,
std::function<bool(PublicKey const&)> isTrusted)
{
std::lock_guard lock{apply_mutex_};
auto db = dbCon.checkoutDb ();
auto db = dbCon.checkoutDb();
soci::transaction tr(*db);
*db << "DELETE FROM " << dbTable;
@@ -556,11 +568,9 @@ void ManifestCache::save (
{
// Save all revocation manifests,
// but only save trusted non-revocation manifests.
if (! v.second.revoked() && ! isTrusted (v.second.masterKey))
if (!v.second.revoked() && !isTrusted(v.second.masterKey))
{
JLOG(j_.info())
<< "Untrusted manifest in cache not saved to db";
JLOG(j_.info()) << "Untrusted manifest in cache not saved to db";
continue;
}
@@ -568,10 +578,9 @@ void ManifestCache::save (
// Do not reuse blob because manifest ecdsa signatures vary in length
// but blob write length is expected to be >= the last write
soci::blob rawData(*db);
convert (v.second.serialized, rawData);
*db << sql,
soci::use (rawData);
convert(v.second.serialized, rawData);
*db << sql, soci::use(rawData);
}
tr.commit ();
}
tr.commit();
}
} // namespace ripple

View File

@@ -17,14 +17,14 @@
*/
//==============================================================================
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/Log.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/app/ledger/LedgerMaster.h>
#include <ripple/app/main/Application.h>
#include <ripple/app/misc/HashRouter.h>
#include <ripple/app/misc/Transaction.h>
#include <ripple/app/tx/apply.h>
#include <ripple/basics/Log.h>
#include <ripple/basics/safe_cast.h>
#include <ripple/core/DatabaseCon.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/Feature.h>
#include <ripple/protocol/jss.h>
@@ -32,16 +32,15 @@
namespace ripple {
Transaction::Transaction (std::shared_ptr<STTx const> const& stx,
std::string& reason, Application& app)
noexcept
: mTransaction (stx)
, mApp (app)
, j_ (app.journal ("Ledger"))
Transaction::Transaction(
std::shared_ptr<STTx const> const& stx,
std::string& reason,
Application& app) noexcept
: mTransaction(stx), mApp(app), j_(app.journal("Ledger"))
{
try
{
mTransactionID = mTransaction->getTransactionID ();
mTransactionID = mTransaction->getTransactionID();
}
catch (std::exception& e)
{
@@ -56,86 +55,100 @@ Transaction::Transaction (std::shared_ptr<STTx const> const& stx,
// Misc.
//
void Transaction::setStatus (TransStatus ts, std::uint32_t lseq)
void
Transaction::setStatus(TransStatus ts, std::uint32_t lseq)
{
mStatus = ts;
mInLedger = lseq;
mStatus = ts;
mInLedger = lseq;
}
TransStatus Transaction::sqlTransactionStatus(
boost::optional<std::string> const& status)
TransStatus
Transaction::sqlTransactionStatus(boost::optional<std::string> const& status)
{
char const c = (status) ? (*status)[0] : safe_cast<char>(txnSqlUnknown);
switch (c)
{
case txnSqlNew: return NEW;
case txnSqlConflict: return CONFLICTED;
case txnSqlHeld: return HELD;
case txnSqlValidated: return COMMITTED;
case txnSqlIncluded: return INCLUDED;
case txnSqlNew:
return NEW;
case txnSqlConflict:
return CONFLICTED;
case txnSqlHeld:
return HELD;
case txnSqlValidated:
return COMMITTED;
case txnSqlIncluded:
return INCLUDED;
}
assert (c == txnSqlUnknown);
assert(c == txnSqlUnknown);
return INVALID;
}
Transaction::pointer Transaction::transactionFromSQL (
Transaction::pointer
Transaction::transactionFromSQL(
boost::optional<std::uint64_t> const& ledgerSeq,
boost::optional<std::string> const& status,
Blob const& rawTxn,
Application& app)
{
std::uint32_t const inLedger =
rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or (0));
rangeCheckedCast<std::uint32_t>(ledgerSeq.value_or(0));
SerialIter it (makeSlice(rawTxn));
auto txn = std::make_shared<STTx const> (it);
SerialIter it(makeSlice(rawTxn));
auto txn = std::make_shared<STTx const>(it);
std::string reason;
auto tr = std::make_shared<Transaction> (
txn, reason, app);
auto tr = std::make_shared<Transaction>(txn, reason, app);
tr->setStatus (sqlTransactionStatus (status));
tr->setLedger (inLedger);
tr->setStatus(sqlTransactionStatus(status));
tr->setLedger(inLedger);
return tr;
}
Transaction::pointer Transaction::load (uint256 const& id, Application& app, error_code_i& ec)
Transaction::pointer
Transaction::load(uint256 const& id, Application& app, error_code_i& ec)
{
return boost::get<pointer> (load (id, app, boost::none, ec));
return boost::get<pointer>(load(id, app, boost::none, ec));
}
boost::variant<Transaction::pointer, bool>
Transaction::load (uint256 const& id, Application& app, ClosedInterval<uint32_t> const& range,
Transaction::load(
uint256 const& id,
Application& app,
ClosedInterval<uint32_t> const& range,
error_code_i& ec)
{
using op = boost::optional<ClosedInterval<uint32_t>>;
return load (id, app, op {range}, ec);
return load(id, app, op{range}, ec);
}
boost::variant<Transaction::pointer, bool>
Transaction::load (uint256 const& id, Application& app, boost::optional<ClosedInterval<uint32_t>> const& range,
Transaction::load(
uint256 const& id,
Application& app,
boost::optional<ClosedInterval<uint32_t>> const& range,
error_code_i& ec)
{
std::string sql = "SELECT LedgerSeq,Status,RawTxn "
"FROM Transactions WHERE TransID='";
std::string sql =
"SELECT LedgerSeq,Status,RawTxn "
"FROM Transactions WHERE TransID='";
sql.append (to_string (id));
sql.append ("';");
sql.append(to_string(id));
sql.append("';");
boost::optional<std::uint64_t> ledgerSeq;
boost::optional<std::string> status;
Blob rawTxn;
{
auto db = app.getTxnDB ().checkoutDb ();
soci::blob sociRawTxnBlob (*db);
auto db = app.getTxnDB().checkoutDb();
soci::blob sociRawTxnBlob(*db);
soci::indicator rti;
*db << sql, soci::into (ledgerSeq), soci::into (status),
soci::into (sociRawTxnBlob, rti);
*db << sql, soci::into(ledgerSeq), soci::into(status),
soci::into(sociRawTxnBlob, rti);
auto const got_data = db->got_data ();
auto const got_data = db->got_data();
if ((!got_data || rti != soci::i_ok) && !range)
return nullptr;
@@ -144,27 +157,23 @@ Transaction::load (uint256 const& id, Application& app, boost::optional<ClosedIn
{
uint64_t count = 0;
*db << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE LedgerSeq BETWEEN "
<< range->first ()
<< " AND "
<< range->last ()
<< ";",
soci::into (count, rti);
*db << "SELECT COUNT(DISTINCT LedgerSeq) FROM Transactions WHERE "
"LedgerSeq BETWEEN "
<< range->first() << " AND " << range->last() << ";",
soci::into(count, rti);
if (!db->got_data () || rti != soci::i_ok)
if (!db->got_data() || rti != soci::i_ok)
return false;
return count == (range->last () - range->first () + 1);
return count == (range->last() - range->first() + 1);
}
convert (sociRawTxnBlob, rawTxn);
convert(sociRawTxnBlob, rawTxn);
}
try
{
return Transaction::transactionFromSQL(
ledgerSeq, status,
rawTxn, app);
return Transaction::transactionFromSQL(ledgerSeq, status, rawTxn, app);
}
catch (std::exception& e)
{
@@ -179,19 +188,19 @@ Transaction::load (uint256 const& id, Application& app, boost::optional<ClosedIn
}
// options 1 to include the date of the transaction
Json::Value Transaction::getJson (JsonOptions options, bool binary) const
Json::Value
Transaction::getJson(JsonOptions options, bool binary) const
{
Json::Value ret (mTransaction->getJson (JsonOptions::none, binary));
Json::Value ret(mTransaction->getJson(JsonOptions::none, binary));
if (mInLedger)
{
ret[jss::inLedger] = mInLedger; // Deprecated.
ret[jss::inLedger] = mInLedger; // Deprecated.
ret[jss::ledger_index] = mInLedger;
if (options == JsonOptions::include_date)
{
auto ct = mApp.getLedgerMaster().
getCloseTimeBySeq (mInLedger);
auto ct = mApp.getLedgerMaster().getCloseTimeBySeq(mInLedger);
if (ct)
ret[jss::date] = ct->time_since_epoch().count();
}
@@ -200,4 +209,4 @@ Json::Value Transaction::getJson (JsonOptions options, bool binary) const
return ret;
}
} // ripple
} // namespace ripple

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More