refactor: unify featureExport + featureConsensusEntropy into featureExportRNG

Single amendment flag for both features. numFeatures 94 → 93.
Exclude featureExportRNG from default test set to prevent
ConsensusEntropy pseudo-tx injection from breaking existing tests.
This commit is contained in:
Nicholas Dudfield
2026-02-21 17:46:46 +07:00
parent 3bead8dcb6
commit b9dd854595
14 changed files with 28 additions and 31 deletions

View File

@@ -454,7 +454,7 @@ RCLConsensus::Adaptor::onClose(
// all: no commitment, no reveal, no SHAMap entries. The surviving
// proposers will close those rounds with fewer commits (possibly
// falling back to ZERO entropy) until the rejoiner starts proposing.
if (proposing && prevLedger->rules().enabled(featureConsensusEntropy))
if (proposing && prevLedger->rules().enabled(featureExportRNG))
{
cacheUNLReport();
generateEntropySecret();
@@ -477,7 +477,7 @@ RCLConsensus::Adaptor::onClose(
{
JLOG(j_.debug()) << "RNG: onClose skipped (proposing=" << proposing
<< " amendment="
<< prevLedger->rules().enabled(featureConsensusEntropy)
<< prevLedger->rules().enabled(featureExportRNG)
<< ")";
}
@@ -610,7 +610,7 @@ RCLConsensus::Adaptor::doAccept(
// Inject consensus entropy pseudo-transaction (if amendment enabled)
// This must happen before buildLCL so the entropy tx is in the ledger
if (prevLedger.ledger_->rules().enabled(featureConsensusEntropy))
if (prevLedger.ledger_->rules().enabled(featureExportRNG))
injectEntropyPseudoTx(retriableTxs, prevLedger.seq() + 1);
else
clearRngState();

View File

@@ -15,9 +15,8 @@
#define uint256 std::string
#define featureHooksUpdate1 "1"
#define featureHooksUpdate2 "1"
#define featureExport "1"
#define featureExportRNG "1"
#define fix20250131 "1"
#define featureConsensusEntropy "1"
namespace hook_api {
struct Rules
{

View File

@@ -376,19 +376,19 @@ HOOK_API_DEFINITION(
// int64_t xport_reserve(uint32_t count);
HOOK_API_DEFINITION(
int64_t, xport_reserve, (uint32_t),
featureExport)
featureExportRNG)
// int64_t xport(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len);
HOOK_API_DEFINITION(
int64_t, xport, (uint32_t, uint32_t, uint32_t, uint32_t),
featureExport)
featureExportRNG)
// int64_t dice(uint32_t sides);
HOOK_API_DEFINITION(
int64_t, dice, (uint32_t),
featureConsensusEntropy)
featureExportRNG)
// int64_t random(uint32_t write_ptr, uint32_t write_len);
HOOK_API_DEFINITION(
int64_t, random, (uint32_t, uint32_t),
featureConsensusEntropy)
featureExportRNG)

View File

@@ -1712,7 +1712,7 @@ hook::finalizeHookResult(
meta.setFieldU16(
sfHookEmitCount,
emission_txnid.size()); // this will never wrap, hard limit
if (applyCtx.view().rules().enabled(featureExport))
if (applyCtx.view().rules().enabled(featureExportRNG))
{
meta.setFieldU16(sfHookExportCount, exported_txnid.size());
}

View File

@@ -473,7 +473,7 @@ signPendingExports(
{
std::vector<std::pair<uint256, STObject>> result;
if (!view.rules().enabled(featureExport))
if (!view.rules().enabled(featureExportRNG))
return result;
JLOG(j.trace()) << "signPendingExports: started";

View File

@@ -1542,7 +1542,7 @@ TxQ::accept(Application& app, OpenView& view)
}
// Inject exported transactions/signatures, if any
if (view.rules().enabled(featureExport))
if (view.rules().enabled(featureExportRNG))
{
do
{

View File

@@ -99,7 +99,7 @@ Change::preflight(PreflightContext const& ctx)
}
}
if (ctx.tx.getTxnType() == ttEXPORT && !ctx.rules.enabled(featureExport))
if (ctx.tx.getTxnType() == ttEXPORT && !ctx.rules.enabled(featureExportRNG))
{
JLOG(ctx.j.warn()) << "Change: Export not enabled";
return temDISABLED;
@@ -107,7 +107,7 @@ Change::preflight(PreflightContext const& ctx)
if (ctx.tx.getTxnType() == ttCONSENSUS_ENTROPY)
{
if (!ctx.rules.enabled(featureConsensusEntropy))
if (!ctx.rules.enabled(featureExportRNG))
{
JLOG(ctx.j.warn()) << "Change: ConsensusEntropy is not enabled.";
return temDISABLED;

View File

@@ -202,7 +202,7 @@ Import::preflight(PreflightContext const& ctx)
return temMALFORMED;
if (stpTrans->isFieldPresent(sfTicketSequence) &&
!ctx.rules.enabled(featureExport))
!ctx.rules.enabled(featureExportRNG))
{
JLOG(ctx.j.warn()) << "Import: cannot use TicketSequence XPOP.";
return temMALFORMED;
@@ -897,7 +897,7 @@ Import::preclaim(PreclaimContext const& ctx)
if (hasTicket)
{
if (!ctx.view.rules().enabled(featureExport))
if (!ctx.view.rules().enabled(featureExportRNG))
return tefINTERNAL;
auto const acc = stpTrans->getAccountID(sfAccount);

View File

@@ -443,7 +443,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj)
auto version = hookSetObj.getFieldU16(sfHookApiVersion);
// TODO: clarify API version history - version 1 was possibly
// JSHooks? For now only version 0 is valid. Export APIs (xport,
// xport_reserve) are gated by featureExport amendment via
// xport_reserve) are gated by featureExportRNG amendment via
// rulesVersion, not by sfHookApiVersion.
if (version != 0)
{

View File

@@ -74,7 +74,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 94;
static constexpr std::size_t numFeatures = 93;
/** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated
@@ -378,10 +378,9 @@ extern uint256 const fixInvalidTxFlags;
extern uint256 const featureExtendedHookState;
extern uint256 const fixCronStacking;
extern uint256 const fixHookAPI20251128;
extern uint256 const featureExport;
extern uint256 const featureExportRNG;
extern uint256 const featureHookOnV2;
extern uint256 const featureHooksUpdate2;
extern uint256 const featureConsensusEntropy;
} // namespace ripple
#endif

View File

@@ -484,10 +484,9 @@ REGISTER_FIX (fixInvalidTxFlags, Supported::yes, VoteBehavior::De
REGISTER_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FIX (fixCronStacking, Supported::yes, VoteBehavior::DefaultYes);
REGISTER_FIX (fixHookAPI20251128, Supported::yes, VoteBehavior::DefaultYes);
REGISTER_FEATURE(Export, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FEATURE(ExportRNG, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FEATURE(HookOnV2, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FEATURE(HooksUpdate2, Supported::yes, VoteBehavior::DefaultNo);
REGISTER_FEATURE(ConsensusEntropy, Supported::yes, VoteBehavior::DefaultNo);
// The following amendments are obsolete, but must remain supported
// because they could potentially get enabled.

View File

@@ -60,7 +60,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
BEAST_EXPECT(!env.le(keylet::consensusEntropy()));
@@ -89,7 +89,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
env.close();
@@ -134,7 +134,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
auto const alice = Account{"alice"};
@@ -211,7 +211,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
auto const alice = Account{"alice"};
@@ -289,7 +289,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
auto const alice = Account{"alice"};
@@ -369,7 +369,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
supported_amendments() | featureExportRNG,
nullptr};
auto const alice = Account{"alice"};

View File

@@ -75,7 +75,7 @@ public:
struct Export_test : public beast::unit_test::suite
{
// Hook that exports a payment using xport (for cross-chain export)
// xport APIs are gated by featureExport amendment, not sfHookApiVersion
// xport APIs are gated by featureExportRNG amendment, not sfHookApiVersion
TestHook xport_wasm = export_test_wasm[R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t id, uint32_t maxiter);
@@ -307,7 +307,7 @@ struct Export_test : public beast::unit_test::suite
{
using namespace test::jtx;
FeatureBitset const all{supported_amendments()};
FeatureBitset const allWithExport{all | featureExport};
FeatureBitset const allWithExport{all | featureExportRNG};
testXportPaymentWithValidator(allWithExport);
}
};

View File

@@ -86,7 +86,7 @@ supported_amendments()
// TODO: ConsensusEntropy injects a pseudo-tx every ledger which
// breaks existing test transaction count assumptions. Exclude from
// default test set until dedicated tests are written.
return FeatureBitset(feats) - featureConsensusEntropy;
return FeatureBitset(feats) - featureExportRNG;
//@@end rng-test-environment-gating
}();
return ids;