Add UNLReport obj/pseudo txn. Tracks which validators were online and validating last 256 ledgers.

This commit is contained in:
Richard Holland
2023-06-12 12:31:00 +00:00
parent d31ee509a9
commit c33e64fa3d
15 changed files with 134 additions and 2 deletions

View File

@@ -99,6 +99,51 @@ NegativeUNLVote::doVoting(
assert(nidToKeyMap.count(n));
addTx(seq, nidToKeyMap[n], ToReEnable, initialSet);
}
// do reporting when enabled
if (prevLedger->rules().enabled(featureXahauGenesis) && scoreTable->size() > 0)
addReportingTx(seq, *scoreTable, nidToKeyMap, initialSet);
}
}
void
NegativeUNLVote::addReportingTx(
LedgerIndex seq,
hash_map<NodeID, std::uint32_t> const& scoreTable,
hash_map<NodeID, PublicKey> const& nidToKeyMap,
std::shared_ptr<SHAMap> const& initalSet)
{
std::vector<STObject> active;
active.reserve(scoreTable.size());
for (auto const& [n, score]: scoreTable)
{
if (score > 240)
{
active.emplace_back(sfActiveValidator);
active.back().setFieldVL(sfPublicKey, nidToKeyMap.at(n));
}
}
STTx repUnlTx(ttUNL_REPORT, [&](auto& obj)
{
obj.setFieldArray(sfActiveValidators, STArray(active, sfActiveValidators));
obj.setFieldU32(sfLedgerSequence, seq);
});
uint256 txID = repUnlTx.getTransactionID();
Serializer s;
repUnlTx.add(s);
if (!initalSet->addGiveItem(
SHAMapNodeType::tnTRANSACTION_NM,
std::make_shared<SHAMapItem>(txID, s.slice())))
{
JLOG(j_.warn()) << "R-UNL: ledger seq=" << seq
<< ", add ttUNL_REPORT tx failed";
}
else
{
JLOG(j_.debug()) << "R-UNL: ledger seq=" << seq
<< ", add a ttUNL_REPORT Tx with txID: " << txID;
}
}

View File

@@ -153,6 +153,16 @@ private:
NegativeUNLModify modify,
std::shared_ptr<SHAMap> const& initialSet);
/**
* As above, but make a report object instead of an n-unl
*/
void
addReportingTx(
LedgerIndex seq,
hash_map<NodeID, std::uint32_t> const& scoreTable,
hash_map<NodeID, PublicKey> const& nidToKeyMap,
std::shared_ptr<SHAMap> const& initalSet);
/**
* Pick one candidate from a vector of candidates.
*

View File

@@ -77,6 +77,13 @@ Change::preflight(PreflightContext const& ctx)
return temDISABLED;
}
if (ctx.tx.getTxnType() == ttUNL_REPORT &&
!ctx.rules.enabled(featureXahauGenesis))
{
JLOG(ctx.j.warn()) << "Change: UNLReport is not enabled.";
return temDISABLED;
}
return tesSUCCESS;
}
@@ -134,6 +141,7 @@ Change::preclaim(PreclaimContext const& ctx)
return tesSUCCESS;
case ttAMENDMENT:
case ttUNL_MODIFY:
case ttUNL_REPORT:
case ttEMIT_FAILURE:
return tesSUCCESS;
default:
@@ -154,12 +162,34 @@ Change::doApply()
return applyUNLModify();
case ttEMIT_FAILURE:
return applyEmitFailure();
case ttUNL_REPORT:
return applyUNLReport();
default:
assert(0);
return tefFAILURE;
}
}
TER
Change::applyUNLReport()
{
auto sle = view().peek(keylet::UNLReport());
bool const created = !!sle;
if (created)
sle = std::make_shared<SLE>(keylet::UNLReport());
sle->setFieldArray(sfActiveValidators, ctx_.tx.getFieldArray(sfActiveValidators));
if (created)
view().insert(sle);
else
view().update(sle);
return tesSUCCESS;
}
void
Change::preCompute()
{

View File

@@ -73,6 +73,9 @@ private:
TER
applyEmitFailure();
TER
applyUNLReport();
};
} // namespace ripple

View File

@@ -141,6 +141,7 @@ invoke_preflight(PreflightContext const& ctx)
case ttAMENDMENT:
case ttFEE:
case ttUNL_MODIFY:
case ttUNL_REPORT:
case ttEMIT_FAILURE:
return invoke_preflight_helper<Change>(ctx);
case ttHOOK_SET:
@@ -264,6 +265,7 @@ invoke_preclaim(PreclaimContext const& ctx)
case ttAMENDMENT:
case ttFEE:
case ttUNL_MODIFY:
case ttUNL_REPORT:
case ttEMIT_FAILURE:
return invoke_preclaim<Change>(ctx);
case ttNFTOKEN_MINT:
@@ -344,6 +346,7 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx)
case ttAMENDMENT:
case ttFEE:
case ttUNL_MODIFY:
case ttUNL_REPORT:
case ttEMIT_FAILURE:
return Change::calculateBaseFee(view, tx);
case ttNFTOKEN_MINT:
@@ -504,6 +507,7 @@ invoke_apply(ApplyContext& ctx)
case ttAMENDMENT:
case ttFEE:
case ttUNL_MODIFY:
case ttUNL_REPORT:
case ttEMIT_FAILURE: {
Change p(ctx);
return p();

View File

@@ -111,6 +111,9 @@ fees() noexcept;
Keylet const&
negativeUNL() noexcept;
Keylet const&
UNLReport() noexcept;
/** The beginning of an order book */
struct book_t
{

View File

@@ -172,6 +172,13 @@ enum LedgerEntryType : std::uint16_t
*/
ltURI_TOKEN = 0x0055,
/** A ledger object that reports on the active dUNL validators
* that were validating for more than 240 of the last 256 ledgers
*
* \sa keylet::UNLReport
*/
ltUNL_REPORT = 0x0052,
//---------------------------------------------------------------------------
/** A special type, matching any ledger entry type.

View File

@@ -581,6 +581,7 @@ extern SField const sfHookExecution;
extern SField const sfHookDefinition;
extern SField const sfHookParameter;
extern SField const sfHookGrant;
extern SField const sfActiveValidator;
// array of objects (common)
// ARRAY/1 is reserved for end of array
@@ -605,6 +606,7 @@ extern SField const sfHookParameters;
extern SField const sfHooks;
extern SField const sfHookGrants;
extern SField const sfGenesisMints;
extern SField const sfActiveValidators;
//------------------------------------------------------------------------------

View File

@@ -180,6 +180,7 @@ enum TxType : std::uint16_t
*/
ttUNL_MODIFY = 102,
ttEMIT_FAILURE = 103,
ttUNL_REPORT = 104,
};
// clang-format on

View File

@@ -71,6 +71,7 @@ enum class LedgerNameSpace : std::uint16_t {
NFTOKEN_SELL_OFFERS = 'i',
URI_TOKEN = 'U',
IMPORT_VLSEQ = 'I',
UNL_REPORT = 'R',
// No longer used or supported. Left here to reserve the space
// to avoid accidental reuse.
@@ -236,6 +237,14 @@ negativeUNL() noexcept
return ret;
}
Keylet const&
UNLReport() noexcept
{
static Keylet const ret{
ltUNL_REPORT, indexHash(LedgerNameSpace::UNL_REPORT)};
return ret;
}
Keylet
book_t::operator()(Book const& b) const
{

View File

@@ -298,6 +298,13 @@ LedgerFormats::LedgerFormats()
},
commonFields);
add(jss::UNLReport,
ltUNL_REPORT,
{
{sfActiveValidators, soeREQUIRED},
},
commonFields);
add(jss::EmittedTxn,
ltEMITTED_TXN,
{

View File

@@ -337,6 +337,7 @@ CONSTRUCT_UNTYPED_SFIELD(sfHookDefinition, "HookDefinition", OBJECT,
CONSTRUCT_UNTYPED_SFIELD(sfHookParameter, "HookParameter", OBJECT, 23);
CONSTRUCT_UNTYPED_SFIELD(sfHookGrant, "HookGrant", OBJECT, 24);
CONSTRUCT_UNTYPED_SFIELD(sfGenesisMint, "GenesisMint", OBJECT, 96);
CONSTRUCT_UNTYPED_SFIELD(sfActiveValidator, "ActiveValidator", OBJECT, 95);
// array of objects
// ARRAY/1 is reserved for end of array
@@ -357,6 +358,7 @@ CONSTRUCT_UNTYPED_SFIELD(sfDisabledValidators, "DisabledValidators", ARRAY,
CONSTRUCT_UNTYPED_SFIELD(sfHookExecutions, "HookExecutions", ARRAY, 18);
CONSTRUCT_UNTYPED_SFIELD(sfHookParameters, "HookParameters", ARRAY, 19);
CONSTRUCT_UNTYPED_SFIELD(sfHookGrants, "HookGrants", ARRAY, 20);
CONSTRUCT_UNTYPED_SFIELD(sfActiveValidators, "ActiveValidators", ARRAY, 95);
CONSTRUCT_UNTYPED_SFIELD(sfGenesisMints, "GenesisMints", ARRAY, 96);
// clang-format on

View File

@@ -564,7 +564,7 @@ isPseudoTx(STObject const& tx)
return false;
auto tt = safe_cast<TxType>(*t);
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY || tt == ttEMIT_FAILURE;
return tt == ttAMENDMENT || tt == ttFEE || tt == ttUNL_MODIFY || tt == ttEMIT_FAILURE || tt == ttUNL_REPORT;
}
} // namespace ripple

View File

@@ -192,6 +192,14 @@ TxFormats::TxFormats()
},
commonFields);
add(jss::UNLReport,
ttUNL_REPORT,
{
{sfLedgerSequence, soeREQUIRED},
{sfActiveValidators, soeREQUIRED},
},
commonFields);
add(jss::TicketCreate,
ttTICKET_CREATE,
{

View File

@@ -117,6 +117,7 @@ JSS(RippleState); // ledger type.
JSS(SLE_hit_rate); // out: GetCounts.
JSS(SetFee); // transaction type.
JSS(UNLModify); // transaction type.
JSS(UNLReport); // transaction type.
JSS(SettleDelay); // in: TransactionSign
JSS(SendMax); // in: TransactionSign
JSS(Sequence); // in/out: TransactionSign; field.