mirror of
https://github.com/Xahau/xahaud.git
synced 2026-02-03 21:45:17 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc17cb44a7 |
@@ -479,11 +479,24 @@ private:
|
|||||||
to reach consensus. Update our position only on the timer, and in this
|
to reach consensus. Update our position only on the timer, and in this
|
||||||
phase.
|
phase.
|
||||||
|
|
||||||
If we have consensus, move to the accepted phase.
|
If we have consensus, move to the shuffle phase.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
phaseEstablish();
|
phaseEstablish();
|
||||||
|
|
||||||
|
|
||||||
|
/** Handle shuffle phase.
|
||||||
|
|
||||||
|
In the shuffle phase, UNLReport nodes exchange entropy to build
|
||||||
|
a consensus entropy that is then used as an RNG source for Hooks.
|
||||||
|
|
||||||
|
The entropy is injected as a ttSHUFFLE psuedo into the final ledger
|
||||||
|
|
||||||
|
If we have consensus, move to the accepted phase.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
phaseShuffle();
|
||||||
|
|
||||||
/** Evaluate whether pausing increases likelihood of validation.
|
/** Evaluate whether pausing increases likelihood of validation.
|
||||||
*
|
*
|
||||||
* As a validator that has previously synced to the network, if our most
|
* As a validator that has previously synced to the network, if our most
|
||||||
@@ -588,6 +601,10 @@ private:
|
|||||||
// Peer proposed positions for the current round
|
// Peer proposed positions for the current round
|
||||||
hash_map<NodeID_t, PeerPosition_t> currPeerPositions_;
|
hash_map<NodeID_t, PeerPosition_t> currPeerPositions_;
|
||||||
|
|
||||||
|
// our and our peers' entropy as per TMShuffle, used in phaseShuffle
|
||||||
|
std::optional<uint256> ourEntropy_;
|
||||||
|
hash_map<NodeID_t, std::pair<uint256, uint256>> currPeerEntropy_;
|
||||||
|
|
||||||
// Recently received peer positions, available when transitioning between
|
// Recently received peer positions, available when transitioning between
|
||||||
// ledgers or rounds
|
// ledgers or rounds
|
||||||
hash_map<NodeID_t, std::deque<PeerPosition_t>> recentPeerPositions_;
|
hash_map<NodeID_t, std::deque<PeerPosition_t>> recentPeerPositions_;
|
||||||
@@ -832,6 +849,10 @@ Consensus<Adaptor>::timerEntry(NetClock::time_point const& now)
|
|||||||
{
|
{
|
||||||
phaseEstablish();
|
phaseEstablish();
|
||||||
}
|
}
|
||||||
|
else if (phase_ == ConsensusPhase::shuffle)
|
||||||
|
{
|
||||||
|
phaseShuffle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Adaptor>
|
template <class Adaptor>
|
||||||
@@ -1291,8 +1312,12 @@ Consensus<Adaptor>::phaseEstablish()
|
|||||||
adaptor_.updateOperatingMode(currPeerPositions_.size());
|
adaptor_.updateOperatingMode(currPeerPositions_.size());
|
||||||
prevProposers_ = currPeerPositions_.size();
|
prevProposers_ = currPeerPositions_.size();
|
||||||
prevRoundTime_ = result_->roundTime.read();
|
prevRoundTime_ = result_->roundTime.read();
|
||||||
phase_ = ConsensusPhase::accepted;
|
|
||||||
JLOG(j_.debug()) << "transitioned to ConsensusPhase::accepted";
|
// RHTODO: guard with amendment
|
||||||
|
phase_ = ConsensusPhase::shuffle;
|
||||||
|
JLOG(j_.debug()) << "transitioned to ConsensusPhase::shuffle";
|
||||||
|
|
||||||
|
/*
|
||||||
adaptor_.onAccept(
|
adaptor_.onAccept(
|
||||||
*result_,
|
*result_,
|
||||||
previousLedger_,
|
previousLedger_,
|
||||||
@@ -1300,6 +1325,60 @@ Consensus<Adaptor>::phaseEstablish()
|
|||||||
rawCloseTimes_,
|
rawCloseTimes_,
|
||||||
mode_.get(),
|
mode_.get(),
|
||||||
getJson(true));
|
getJson(true));
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Adaptor>
|
||||||
|
void
|
||||||
|
Consensus<Adaptor>::phaseShuffle()
|
||||||
|
{
|
||||||
|
// can only establish consensus if we already took a stance
|
||||||
|
assert(result_);
|
||||||
|
|
||||||
|
using namespace std::chrono;
|
||||||
|
ConsensusParms const& parms = adaptor_.parms();
|
||||||
|
|
||||||
|
result_->roundTime.tick(clock_.now());
|
||||||
|
result_->proposers = currPeerPositions_.size();
|
||||||
|
|
||||||
|
convergePercent_ = result_->roundTime.read() * 100 /
|
||||||
|
std::max<milliseconds>(prevRoundTime_, parms.avMIN_CONSENSUS_TIME);
|
||||||
|
|
||||||
|
// Give everyone a chance to take an initial position
|
||||||
|
if (result_->roundTime.read() < parms.ledgerMIN_CONSENSUS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
updateOurPositions();
|
||||||
|
|
||||||
|
// Nothing to do if too many laggards or we don't have consensus.
|
||||||
|
if (shouldPause() || !haveConsensus())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!haveCloseTimeConsensus_)
|
||||||
|
{
|
||||||
|
JLOG(j_.info()) << "We have TX consensus but not CT consensus";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JLOG(j_.info()) << "Converge cutoff (" << currPeerPositions_.size()
|
||||||
|
<< " participants)";
|
||||||
|
adaptor_.updateOperatingMode(currPeerPositions_.size());
|
||||||
|
prevProposers_ = currPeerPositions_.size();
|
||||||
|
prevRoundTime_ = result_->roundTime.read();
|
||||||
|
|
||||||
|
// RHTODO: guard with amendment
|
||||||
|
phase_ = ConsensusPhase::shuffle;
|
||||||
|
JLOG(j_.debug()) << "transitioned to ConsensusPhase::shuffle";
|
||||||
|
|
||||||
|
/*
|
||||||
|
adaptor_.onAccept(
|
||||||
|
*result_,
|
||||||
|
previousLedger_,
|
||||||
|
closeResolution_,
|
||||||
|
rawCloseTimes_,
|
||||||
|
mode_.get(),
|
||||||
|
getJson(true));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Adaptor>
|
template <class Adaptor>
|
||||||
|
|||||||
@@ -87,15 +87,15 @@ to_string(ConsensusMode m)
|
|||||||
/** Phases of consensus for a single ledger round.
|
/** Phases of consensus for a single ledger round.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
"close" "accept"
|
"close" "shuffle" "accept"
|
||||||
open ------- > establish ---------> accepted
|
open ------- > establish -------> shuffle ---------> accepted
|
||||||
^ | |
|
^ | |
|
||||||
|---------------| |
|
|---------------| |
|
||||||
^ "startRound" |
|
^ "startRound" |
|
||||||
|------------------------------------|
|
|-----------------------------------------------------|
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
The typical transition goes from open to establish to accepted and
|
The typical transition goes from open to establish to shuffle to accepted and
|
||||||
then a call to startRound begins the process anew. However, if a wrong prior
|
then a call to startRound begins the process anew. However, if a wrong prior
|
||||||
ledger is detected and recovered during the establish or accept phase,
|
ledger is detected and recovered during the establish or accept phase,
|
||||||
consensus will internally go back to open (see Consensus::handleWrongLedger).
|
consensus will internally go back to open (see Consensus::handleWrongLedger).
|
||||||
@@ -107,6 +107,9 @@ enum class ConsensusPhase {
|
|||||||
//! Establishing consensus by exchanging proposals with our peers
|
//! Establishing consensus by exchanging proposals with our peers
|
||||||
establish,
|
establish,
|
||||||
|
|
||||||
|
//! Negotitate featureRNG entropy
|
||||||
|
shuffle,
|
||||||
|
|
||||||
//! We have accepted a new last closed ledger and are waiting on a call
|
//! We have accepted a new last closed ledger and are waiting on a call
|
||||||
//! to startRound to begin the next consensus round. No changes
|
//! to startRound to begin the next consensus round. No changes
|
||||||
//! to consensus phase occur while in this phase.
|
//! to consensus phase occur while in this phase.
|
||||||
@@ -122,6 +125,8 @@ to_string(ConsensusPhase p)
|
|||||||
return "open";
|
return "open";
|
||||||
case ConsensusPhase::establish:
|
case ConsensusPhase::establish:
|
||||||
return "establish";
|
return "establish";
|
||||||
|
case ConsensusPhase::shuffle:
|
||||||
|
return "shuffle";
|
||||||
case ConsensusPhase::accepted:
|
case ConsensusPhase::accepted:
|
||||||
return "accepted";
|
return "accepted";
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1094,6 +1094,7 @@ trustTransferLockedBalance(
|
|||||||
}
|
}
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ripple
|
} // namespace ripple
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1918,6 +1918,100 @@ PeerImp::onMessage(std::shared_ptr<protocol::TMLedgerData> const& m)
|
|||||||
app_.getInboundLedgers().gotLedgerData(ledgerHash, shared_from_this(), m);
|
app_.getInboundLedgers().gotLedgerData(ledgerHash, shared_from_this(), m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PeerImp::onMessage(std::shared_ptr<protocol::TMShuffle> const& m)
|
||||||
|
{
|
||||||
|
protocol::TMShuffle& shuf = *m;
|
||||||
|
|
||||||
|
auto const sig = makeSlice(shf.signature());
|
||||||
|
|
||||||
|
// Preliminary check for the validity of the signature: A DER encoded
|
||||||
|
// signature can't be longer than 72 bytes.
|
||||||
|
if ((std::clamp<std::size_t>(sig.size(), 64, 72) != sig.size()) ||
|
||||||
|
(publicKeyType(makeSlice(shf.nodepubkey())) != KeyType::secp256k1))
|
||||||
|
{
|
||||||
|
JLOG(p_journal_.warn()) << "Shuffle: malformed";
|
||||||
|
fee_ = Resource::feeInvalidSignature;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!stringIsUint256Sized(shf.nodeentropy()) ||
|
||||||
|
!stringIsUint256Sized(shf.consensusentropy()) ||
|
||||||
|
!stringIsUint256Sized(shf.previousledger()))
|
||||||
|
{
|
||||||
|
JLOG(p_journal_.warn()) << "Shuffle: malformed";
|
||||||
|
fee_ = Resource::feeInvalidRequest;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PublicKey const publicKey{makeSlice(shf.nodepubkey())};
|
||||||
|
auto const isTrusted = app_.validators().trusted(publicKey);
|
||||||
|
|
||||||
|
if (!isTrusted)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint256 const prevLedger{shf.previousledger()};
|
||||||
|
uint32_t const shuffleSeq{shf.shuffleseq()};
|
||||||
|
uint256 const nodeEntropy{shf.nodeentropy()};
|
||||||
|
uint256 const consensusEntropy{shf.consensusentropy()};
|
||||||
|
|
||||||
|
uint256 const suppression = sha512Half(std::string("TMShuffle", sig));
|
||||||
|
|
||||||
|
if (auto [added, relayed] =
|
||||||
|
app_.getHashRouter().addSuppressionPeerWithStatus(suppression, id_);
|
||||||
|
!added)
|
||||||
|
{
|
||||||
|
// Count unique messages (Slots has it's own 'HashRouter'), which a peer
|
||||||
|
// receives within IDLED seconds since the message has been relayed.
|
||||||
|
if (reduceRelayReady() && relayed &&
|
||||||
|
(stopwatch().now() - *relayed) < reduce_relay::IDLED)
|
||||||
|
overlay_.updateSlotAndSquelch(
|
||||||
|
suppression, publicKey, id_, protocol::mtSHUFFLE);
|
||||||
|
JLOG(p_journal_.trace()) << "Shuffle: duplicate";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isTrusted)
|
||||||
|
{
|
||||||
|
if (tracking_.load() == Tracking::diverged)
|
||||||
|
{
|
||||||
|
JLOG(p_journal_.debug())
|
||||||
|
<< "Proposal: Dropping untrusted (peer divergence)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cluster() && app_.getFeeTrack().isLoadedLocal())
|
||||||
|
{
|
||||||
|
JLOG(p_journal_.debug()) << "Proposal: Dropping untrusted (load)";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JLOG(p_journal_.trace())
|
||||||
|
<< "Proposal: " << (isTrusted ? "trusted" : "untrusted");
|
||||||
|
|
||||||
|
auto proposal = RCLCxPeerPos(
|
||||||
|
publicKey,
|
||||||
|
sig,
|
||||||
|
suppression,
|
||||||
|
RCLCxPeerPos::Proposal{
|
||||||
|
prevLedger,
|
||||||
|
set.proposeseq(),
|
||||||
|
proposeHash,
|
||||||
|
closeTime,
|
||||||
|
app_.timeKeeper().closeTime(),
|
||||||
|
calcNodeID(app_.validatorManifests().getMasterKey(publicKey))});
|
||||||
|
|
||||||
|
std::weak_ptr<PeerImp> weak = shared_from_this();
|
||||||
|
app_.getJobQueue().addJob(
|
||||||
|
isTrusted ? jtPROPOSAL_t : jtPROPOSAL_ut,
|
||||||
|
"recvPropose->checkPropose",
|
||||||
|
[weak, isTrusted, m, proposal]() {
|
||||||
|
if (auto peer = weak.lock())
|
||||||
|
peer->checkPropose(isTrusted, m, proposal);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PeerImp::onMessage(std::shared_ptr<protocol::TMProposeSet> const& m)
|
PeerImp::onMessage(std::shared_ptr<protocol::TMProposeSet> const& m)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -450,3 +450,12 @@ message TMHaveTransactions
|
|||||||
repeated bytes hashes = 1;
|
repeated bytes hashes = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message TMShuffle
|
||||||
|
{
|
||||||
|
required bytes nodeEntropy = 1;
|
||||||
|
required bytes consensusEntropy = 2;
|
||||||
|
required uint32 shuffleSeq = 3;
|
||||||
|
required bytes nodePubKey = 4;
|
||||||
|
required bytes previousledger = 5;
|
||||||
|
required bytes signature = 6; // signature of above fields
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user