mirror of
https://github.com/Xahau/xahaud.git
synced 2026-01-30 03:25:17 +00:00
Compare commits
1 Commits
featRNG2
...
fixXahauGe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac93b24c91 |
@@ -24,6 +24,7 @@
|
||||
#include <ripple/app/misc/AmendmentTable.h>
|
||||
#include <ripple/app/misc/NetworkOPs.h>
|
||||
#include <ripple/app/tx/impl/Change.h>
|
||||
#include <ripple/app/tx/impl/SetHook.h>
|
||||
#include <ripple/app/tx/impl/SetSignerList.h>
|
||||
#include <ripple/app/tx/impl/XahauGenesis.h>
|
||||
#include <ripple/basics/Log.h>
|
||||
@@ -583,10 +584,6 @@ Change::activateXahauGenesis()
|
||||
SetSignerList::removeFromLedger(ctx_.app, sb, accid, j_);
|
||||
|
||||
// Step 4: install genesis hooks
|
||||
sle->setFieldU32(
|
||||
sfOwnerCount, sle->getFieldU32(sfOwnerCount) + genesis_hooks.size());
|
||||
sb.update(sle);
|
||||
|
||||
if (sb.exists(keylet::hook(accid)))
|
||||
{
|
||||
JLOG(j_.warn()) << "featureXahauGenesis genesis account already has "
|
||||
@@ -597,6 +594,7 @@ Change::activateXahauGenesis()
|
||||
{
|
||||
ripple::STArray hooks{sfHooks, static_cast<int>(genesis_hooks.size())};
|
||||
int hookCount = 0;
|
||||
uint32_t hookReserve = 0;
|
||||
|
||||
for (auto const& [hookOn, wasmBytes, params] : genesis_hooks)
|
||||
{
|
||||
@@ -702,8 +700,14 @@ Change::activateXahauGenesis()
|
||||
}
|
||||
|
||||
hooks.push_back(hookObj);
|
||||
|
||||
hookReserve += SetHook::computeHookReserve(hookObj);
|
||||
}
|
||||
|
||||
sle->setFieldU32(
|
||||
sfOwnerCount, sle->getFieldU32(sfOwnerCount) + hookReserve);
|
||||
sb.update(sle);
|
||||
|
||||
auto sle = std::make_shared<SLE>(keylet::hook(accid));
|
||||
sle->setFieldArray(sfHooks, hooks);
|
||||
sle->setAccountID(sfAccount, accid);
|
||||
@@ -744,6 +748,8 @@ Change::activateXahauGenesis()
|
||||
ripple::STArray hooks{sfHooks, 1};
|
||||
STObject hookObj{sfHook};
|
||||
hookObj.setFieldH256(sfHookHash, governHash);
|
||||
|
||||
uint32_t hookReserve = 0;
|
||||
// parameters
|
||||
{
|
||||
std::vector<STObject> vec;
|
||||
@@ -759,6 +765,7 @@ Change::activateXahauGenesis()
|
||||
sfHookParameters, STArray(vec, sfHookParameters));
|
||||
}
|
||||
|
||||
hookReserve += SetHook::computeHookReserve(hookObj);
|
||||
hooks.push_back(hookObj);
|
||||
|
||||
auto sle = std::make_shared<SLE>(hookKL);
|
||||
@@ -785,7 +792,8 @@ Change::activateXahauGenesis()
|
||||
|
||||
sle->setAccountID(sfRegularKey, noAccount());
|
||||
sle->setFieldU32(sfFlags, lsfDisableMaster);
|
||||
sle->setFieldU32(sfOwnerCount, sle->getFieldU32(sfOwnerCount) + 1);
|
||||
sle->setFieldU32(
|
||||
sfOwnerCount, sle->getFieldU32(sfOwnerCount) + hookReserve);
|
||||
sb.update(sle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1173,6 +1173,23 @@ updateHookParameters(
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
SetHook::computeHookReserve(STObject const& hookObj)
|
||||
{
|
||||
if (!hookObj.isFieldPresent(sfHookHash))
|
||||
return 0;
|
||||
|
||||
int reserve{1};
|
||||
|
||||
if (hookObj.isFieldPresent(sfHookParameters))
|
||||
reserve += hookObj.getFieldArray(sfHookParameters).size();
|
||||
|
||||
if (hookObj.isFieldPresent(sfHookGrants))
|
||||
reserve += hookObj.getFieldArray(sfHookGrants).size();
|
||||
|
||||
return reserve;
|
||||
};
|
||||
|
||||
struct KeyletComparator
|
||||
{
|
||||
bool
|
||||
@@ -1837,28 +1854,14 @@ SetHook::setHook()
|
||||
int oldHookReserve = 0;
|
||||
int newHookReserve = 0;
|
||||
|
||||
auto const computeHookReserve = [](STObject const& hookObj) -> int {
|
||||
if (!hookObj.isFieldPresent(sfHookHash))
|
||||
return 0;
|
||||
|
||||
int reserve{1};
|
||||
|
||||
if (hookObj.isFieldPresent(sfHookParameters))
|
||||
reserve += hookObj.getFieldArray(sfHookParameters).size();
|
||||
|
||||
if (hookObj.isFieldPresent(sfHookGrants))
|
||||
reserve += hookObj.getFieldArray(sfHookGrants).size();
|
||||
|
||||
return reserve;
|
||||
};
|
||||
|
||||
for (int i = 0; i < hook::maxHookChainLength(); ++i)
|
||||
{
|
||||
if (oldHooks && i < oldHookCount)
|
||||
oldHookReserve += computeHookReserve(((*oldHooks).get())[i]);
|
||||
oldHookReserve +=
|
||||
SetHook::computeHookReserve(((*oldHooks).get())[i]);
|
||||
|
||||
if (i < newHooks.size())
|
||||
newHookReserve += computeHookReserve(newHooks[i]);
|
||||
newHookReserve += SetHook::computeHookReserve(newHooks[i]);
|
||||
}
|
||||
|
||||
reserveDelta = newHookReserve - oldHookReserve;
|
||||
|
||||
@@ -91,6 +91,9 @@ public:
|
||||
static HookSetValidation
|
||||
validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj);
|
||||
|
||||
static uint32_t
|
||||
computeHookReserve(STObject const& hookObj);
|
||||
|
||||
private:
|
||||
TER
|
||||
setHook();
|
||||
|
||||
@@ -479,23 +479,10 @@ private:
|
||||
to reach consensus. Update our position only on the timer, and in this
|
||||
phase.
|
||||
|
||||
If we have consensus, move to the shuffle phase.
|
||||
*/
|
||||
void
|
||||
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();
|
||||
phaseEstablish();
|
||||
|
||||
/** Evaluate whether pausing increases likelihood of validation.
|
||||
*
|
||||
@@ -601,10 +588,6 @@ private:
|
||||
// Peer proposed positions for the current round
|
||||
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
|
||||
// ledgers or rounds
|
||||
hash_map<NodeID_t, std::deque<PeerPosition_t>> recentPeerPositions_;
|
||||
@@ -849,10 +832,6 @@ Consensus<Adaptor>::timerEntry(NetClock::time_point const& now)
|
||||
{
|
||||
phaseEstablish();
|
||||
}
|
||||
else if (phase_ == ConsensusPhase::shuffle)
|
||||
{
|
||||
phaseShuffle();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Adaptor>
|
||||
@@ -1312,12 +1291,8 @@ Consensus<Adaptor>::phaseEstablish()
|
||||
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";
|
||||
|
||||
/*
|
||||
phase_ = ConsensusPhase::accepted;
|
||||
JLOG(j_.debug()) << "transitioned to ConsensusPhase::accepted";
|
||||
adaptor_.onAccept(
|
||||
*result_,
|
||||
previousLedger_,
|
||||
@@ -1325,60 +1300,6 @@ Consensus<Adaptor>::phaseEstablish()
|
||||
rawCloseTimes_,
|
||||
mode_.get(),
|
||||
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>
|
||||
|
||||
@@ -87,15 +87,15 @@ to_string(ConsensusMode m)
|
||||
/** Phases of consensus for a single ledger round.
|
||||
|
||||
@code
|
||||
"close" "shuffle" "accept"
|
||||
open ------- > establish -------> shuffle ---------> accepted
|
||||
^ | |
|
||||
|---------------| |
|
||||
^ "startRound" |
|
||||
|-----------------------------------------------------|
|
||||
"close" "accept"
|
||||
open ------- > establish ---------> accepted
|
||||
^ | |
|
||||
|---------------| |
|
||||
^ "startRound" |
|
||||
|------------------------------------|
|
||||
@endcode
|
||||
|
||||
The typical transition goes from open to establish to shuffle to accepted and
|
||||
The typical transition goes from open to establish to accepted and
|
||||
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,
|
||||
consensus will internally go back to open (see Consensus::handleWrongLedger).
|
||||
@@ -107,9 +107,6 @@ enum class ConsensusPhase {
|
||||
//! Establishing consensus by exchanging proposals with our peers
|
||||
establish,
|
||||
|
||||
//! Negotitate featureRNG entropy
|
||||
shuffle,
|
||||
|
||||
//! 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 consensus phase occur while in this phase.
|
||||
@@ -125,8 +122,6 @@ to_string(ConsensusPhase p)
|
||||
return "open";
|
||||
case ConsensusPhase::establish:
|
||||
return "establish";
|
||||
case ConsensusPhase::shuffle:
|
||||
return "shuffle";
|
||||
case ConsensusPhase::accepted:
|
||||
return "accepted";
|
||||
default:
|
||||
|
||||
@@ -1094,7 +1094,6 @@ trustTransferLockedBalance(
|
||||
}
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
} // namespace ripple
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1918,100 +1918,6 @@ PeerImp::onMessage(std::shared_ptr<protocol::TMLedgerData> const& 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
|
||||
PeerImp::onMessage(std::shared_ptr<protocol::TMProposeSet> const& m)
|
||||
{
|
||||
|
||||
@@ -450,12 +450,3 @@ message TMHaveTransactions
|
||||
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
|
||||
}
|
||||
|
||||
@@ -139,7 +139,9 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
false, // means the calling test already burned some of the genesis
|
||||
bool skipTests = false,
|
||||
bool const testFlag = false,
|
||||
bool const badNetID = false)
|
||||
bool const badNetID = false,
|
||||
uint32_t const expectedOwnerCount =
|
||||
10 /** testFlag ? 10 : 14 (default) */)
|
||||
{
|
||||
using namespace jtx;
|
||||
|
||||
@@ -247,7 +249,10 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(
|
||||
genesisAccRoot->getFieldAmount(sfBalance) ==
|
||||
XahauGenesis::GenesisAmount);
|
||||
BEAST_EXPECT(genesisAccRoot->getFieldU32(sfOwnerCount) == 2);
|
||||
BEAST_EXPECT(
|
||||
genesisAccRoot->getFieldU32(sfOwnerCount) == !testFlag
|
||||
? expectedOwnerCount
|
||||
: 14);
|
||||
|
||||
// ensure the definitions are correctly set
|
||||
{
|
||||
@@ -583,7 +588,14 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
toBase58(t), membersStr);
|
||||
}
|
||||
|
||||
activate(__LINE__, env, true, false, true);
|
||||
activate(
|
||||
__LINE__,
|
||||
env,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
{},
|
||||
3 /* IRR,IRD,IMC */ + members.size() + tables.size());
|
||||
|
||||
env.close();
|
||||
env.close();
|
||||
@@ -2235,6 +2247,8 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(!!hookLE);
|
||||
uint256 const ns = beast::zero;
|
||||
uint8_t mc = 0;
|
||||
uint8_t paramsCount = 0;
|
||||
|
||||
if (hookLE)
|
||||
{
|
||||
auto const hooksArray = hookLE->getFieldArray(sfHooks);
|
||||
@@ -2242,6 +2256,9 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
hooksArray.size() == 1 &&
|
||||
hooksArray[0].getFieldH256(sfHookHash) == governHookHash);
|
||||
|
||||
paramsCount =
|
||||
hooksArray[0].getFieldArray(sfHookParameters).size();
|
||||
|
||||
for (Account const* m : members)
|
||||
{
|
||||
auto const mVec = vecFromAcc(*m);
|
||||
@@ -2308,7 +2325,9 @@ struct XahauGenesis_test : public beast::unit_test::suite
|
||||
BEAST_EXPECT(!!root);
|
||||
if (root)
|
||||
{
|
||||
BEAST_EXPECT(root->getFieldU32(sfOwnerCount) == mc * 2 + 2);
|
||||
BEAST_EXPECT(
|
||||
root->getFieldU32(sfOwnerCount) ==
|
||||
mc * 2 + 2 + paramsCount);
|
||||
BEAST_EXPECT(root->getFieldU32(sfFlags) & lsfDisableMaster);
|
||||
BEAST_EXPECT(root->getAccountID(sfRegularKey) == noAccount());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user