3#include <xrpld/consensus/ConsensusParms.h>
5#include <xrpl/basics/Log.h>
6#include <xrpl/beast/utility/Journal.h>
7#include <xrpl/json/json_writer.h>
9#include <boost/container/flat_map.hpp>
27template <
class Tx_t,
class NodeID_t>
31 using Map_t = boost::container::flat_map<NodeID_t, bool>;
79 if (nextCutoff.consensusTime > currentCutoff.consensusTime ||
104 int const weight = support / total;
114 s <<
"Transaction " <<
ID() <<
" is stalled. We have been voting "
116 <<
" rounds. Peers have not changed their votes in " << peersUnchanged
117 <<
" rounds. The transaction has " << weight <<
"% support. ";
119 CLOG(clog) << s.
str();
148 setVote(NodeID_t
const& peer,
bool votesYes);
155 unVote(NodeID_t
const& peer);
191template <
class Tx_t,
class NodeID_t>
195 auto const [it, inserted] = votes_.insert(
std::make_pair(peer, votesYes));
202 JLOG(j_.
debug()) <<
"Peer " << peer <<
" votes YES on " << tx_.id();
207 JLOG(j_.
debug()) <<
"Peer " << peer <<
" votes NO on " << tx_.id();
213 else if (votesYes && !it->second)
215 JLOG(j_.
debug()) <<
"Peer " << peer <<
" now votes YES on " << tx_.id();
222 else if (!votesYes && it->second)
224 JLOG(j_.
debug()) <<
"Peer " << peer <<
" now votes NO on " << tx_.id();
234template <
class Tx_t,
class NodeID_t>
238 auto it = votes_.find(peer);
240 if (it != votes_.end())
251template <
class Tx_t,
class NodeID_t>
255 if (ourVote_ && (nays_ == 0))
258 if (!ourVote_ && (yays_ == 0))
261 bool newPosition =
false;
270 auto const [requiredPct, newState] =
274 avalancheState_ = *newState;
275 avalancheCounter_ = 0;
281 weight = (yays_ * 100 + (ourVote_ ? 100 : 0)) / (nays_ + yays_ + 1);
283 newPosition = weight > requiredPct;
289 newPosition = yays_ > nays_;
292 if (newPosition == ourVote_)
294 ++currentVoteCounter_;
295 JLOG(j_.
info()) <<
"No change (" << (ourVote_ ?
"YES" :
"NO") <<
") on " << tx_.id()
296 <<
" : weight " << weight <<
", percent " << percentTime
297 <<
", round(s) with this vote: " << currentVoteCounter_;
302 currentVoteCounter_ = 0;
303 ourVote_ = newPosition;
304 JLOG(j_.
debug()) <<
"We now vote " << (ourVote_ ?
"YES" :
"NO") <<
" on " << tx_.id();
309template <
class Tx_t,
class NodeID_t>
319 ret[
"our_vote"] = ourVote_;
324 for (
auto const& [nodeId, vote] : votes_)
326 ret[
"votes"] = std::move(votes);
Decorator for streaming out compact json.
A generic endpoint for log messages.
A transaction discovered to be in dispute during consensus.
std::size_t currentVoteCounter_
The number of rounds we've gone without changing our vote.
bool stalled(ConsensusParms const &p, bool proposing, int peersUnchanged, beast::Journal j, std::unique_ptr< std::stringstream > const &clog) const
Are we and our peers "stalled" where we probably won't change our vote?
bool updateVote(int percentTime, bool proposing, ConsensusParms const &p)
Update our vote given progression of consensus.
void unVote(NodeID_t const &peer)
Remove a peer's vote.
DisputedTx(Tx_t const &tx, bool ourVote, std::size_t numPeers, beast::Journal j)
Constructor.
bool getOurVote() const
Our vote on whether the transaction should be included.
boost::container::flat_map< NodeID_t, bool > Map_t
Tx_t const & tx() const
The disputed transaction.
Json::Value getJson() const
JSON representation of dispute, used for debugging.
TxID_t const & ID() const
The unique id/hash of the disputed transaction.
std::size_t avalancheCounter_
How long we have been in the current acceptance phase.
bool setVote(NodeID_t const &peer, bool votesYes)
Change a peer's vote.
ConsensusParms::AvalancheState avalancheState_
Which minimum acceptance percentage phase we are currently in.
void setOurVote(bool o)
Change our vote.
@ objectValue
object value (collection of name/value pairs).
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
@ proposing
We are normal participant in consensus and propose our position.
Json::Value getJson(LedgerFill const &fill)
Return a new Json::Value representing the ledger with given options.
std::string to_string(base_uint< Bits, Tag > const &a)
std::pair< std::size_t, std::optional< ConsensusParms::AvalancheState > > getNeededWeight(ConsensusParms const &p, ConsensusParms::AvalancheState currentState, int percentTime, std::size_t currentRounds, std::size_t minimumRounds)
Consensus algorithm parameters.
std::size_t const minCONSENSUS_PCT
The percentage threshold above which we can declare consensus.
std::size_t const avSTALLED_ROUNDS
Number of rounds before a stuck vote is considered unlikely to change because voting stalled.
std::size_t const avMIN_ROUNDS
Number of rounds before certain actions can happen.
std::map< AvalancheState, AvalancheCutoff > const avalancheCutoffs
Map the consensus requirement avalanche state to the amount of time that must pass before moving to t...