feat(hooks): expose consensus entropy keylet

This commit is contained in:
Nicholas Dudfield
2026-07-03 07:23:07 +07:00
parent e8d40472e9
commit 7c5ddb06d8
6 changed files with 357 additions and 7 deletions

View File

@@ -36,6 +36,7 @@
#define KEYLET_EMITTED 22
#define KEYLET_NFT_OFFER 23
#define KEYLET_HOOK_DEFINITION 24
#define KEYLET_CONSENSUS_ENTROPY 37
#define COMPARE_EQUAL 1U
#define COMPARE_LESS 2U
@@ -47,4 +48,4 @@
#include "macro.h"
#include "types.h"
#endif
#endif

View File

@@ -38,6 +38,7 @@
#define KEYLET_HOOK_DEFINITION 24
#define KEYLET_HOOK_STATE_DIR 25
#define KEYLET_CRON 26
#define KEYLET_CONSENSUS_ENTROPY 37
#define COMPARE_EQUAL 1U
#define COMPARE_LESS 2U

View File

@@ -315,6 +315,7 @@ enum keylet_code : uint32_t {
MPTOKEN = 34,
CREDENTIAL = 35,
PERMISSIONED_DOMAIN = 36,
CONSENSUS_ENTROPY = 37,
};
}

View File

@@ -138,6 +138,170 @@ class ConsensusEntropy_test : public beast::unit_test::suite
BEAST_EXPECT(!env.le(keylet::consensusEntropy()));
}
void
testConsensusEntropyKeylet()
{
testcase("Hook can read ConsensusEntropy via util_keylet");
using namespace jtx;
Env env{
*this,
envconfig(),
supported_amendments() | featureConsensusEntropy,
nullptr};
auto const alice = Account{"alice"};
env.fund(XRP(10000), alice);
env.close();
auto const sle = env.le(keylet::consensusEntropy());
BEAST_REQUIRE(sle);
BEAST_EXPECT(sle->getFieldU16(sfEntropyCount) == 20);
BEAST_EXPECT(sle->getFieldU16(sfEntropyDenominator) == 20);
BEAST_EXPECT(
sle->getFieldU8(sfEntropyTier) == entropyTierValidatorFull);
TestHook hook = consensusentropy_test_wasm[R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
extern int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
extern int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
extern int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot_no);
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
#define KEYLET_CONSENSUS_ENTROPY 37
#define sfEntropyTier ((16U << 16U) + 21U)
#define sfEntropyCount ((1U << 16U) + 99U)
#define sfEntropyDenominator ((1U << 16U) + 100U)
#define sfDigest ((5U << 16U) + 21U)
int64_t hook(uint32_t r)
{
_g(1,1);
uint8_t keylet[34];
int64_t result = util_keylet((uint32_t)keylet, 34, KEYLET_CONSENSUS_ENTROPY, 0, 0, 0, 0, 0, 0);
if (result != 34)
rollback(0, 0, result);
result = slot_set((uint32_t)keylet, 34, 1);
if (result != 1)
rollback(0, 0, result);
result = slot_subfield(1, sfEntropyCount, 2);
if (result != 2)
rollback(0, 0, result);
if (slot(0, 0, 2) != 20)
rollback(0, 0, -20);
result = slot_subfield(1, sfEntropyDenominator, 3);
if (result != 3)
rollback(0, 0, result);
if (slot(0, 0, 3) != 20)
rollback(0, 0, -21);
result = slot_subfield(1, sfEntropyTier, 4);
if (result != 4)
rollback(0, 0, result);
if (slot(0, 0, 4) != 4)
rollback(0, 0, -22);
result = slot_subfield(1, sfDigest, 5);
if (result != 5)
rollback(0, 0, result);
uint8_t digest[32];
result = slot((uint32_t)digest, 32, 5);
if (result != 32)
rollback(0, 0, result);
int nonzero = 0;
for (int i = 0; GUARD(32), i < 32; ++i)
if (digest[i] != 0) nonzero = 1;
if (!nonzero)
rollback(0, 0, -23);
return accept((uint32_t)digest, 32, 42);
}
)[test.hook]"];
env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0),
M("set consensus entropy keylet hook"),
HSFEE);
env.close();
Json::Value invoke;
invoke[jss::TransactionType] = "Invoke";
invoke[jss::Account] = alice.human();
env(invoke, M("test consensus entropy keylet"), fee(XRP(1)));
auto meta = env.meta();
BEAST_REQUIRE(meta);
BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions));
auto const hookExecutions = meta->getFieldArray(sfHookExecutions);
BEAST_REQUIRE(hookExecutions.size() == 1);
BEAST_EXPECT(hookReturnCode(hookExecutions[0]) == 42);
BEAST_EXPECT(hookExecutions[0].getFieldU8(sfHookResult) == 3);
auto const retStr = hookExecutions[0].getFieldVL(sfHookReturnString);
BEAST_REQUIRE(retStr.size() == 32);
}
void
testConsensusEntropyKeyletRequiresAmendment()
{
testcase("ConsensusEntropy keylet is amendment gated");
using namespace jtx;
Env env{*this};
auto const alice = Account{"alice"};
env.fund(XRP(10000), alice);
env.close();
BEAST_EXPECT(!env.le(keylet::consensusEntropy()));
TestHook hook = consensusentropy_test_wasm[R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
#define KEYLET_CONSENSUS_ENTROPY 37
int64_t hook(uint32_t r)
{
_g(1,1);
uint8_t keylet[34];
int64_t result = util_keylet((uint32_t)keylet, 34, KEYLET_CONSENSUS_ENTROPY, 0, 0, 0, 0, 0, 0);
return accept(0, 0, result);
}
)[test.hook]"];
env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0),
M("set consensus entropy keylet gated hook"),
HSFEE);
env.close();
Json::Value invoke;
invoke[jss::TransactionType] = "Invoke";
invoke[jss::Account] = alice.human();
env(invoke, M("test consensus entropy keylet gated"), fee(XRP(1)));
auto meta = env.meta();
BEAST_REQUIRE(meta);
BEAST_REQUIRE(meta->isFieldPresent(sfHookExecutions));
auto const hookExecutions = meta->getFieldArray(sfHookExecutions);
BEAST_REQUIRE(hookExecutions.size() == 1);
BEAST_EXPECT(hookReturnCode(hookExecutions[0]) == -7);
BEAST_EXPECT(hookExecutions[0].getFieldU8(sfHookResult) == 3);
}
void
testDice()
{
@@ -583,6 +747,8 @@ class ConsensusEntropy_test : public beast::unit_test::suite
testSLECreated();
testSLEUpdatedOnSubsequentClose();
testNoSLEWithoutAmendment();
testConsensusEntropyKeylet();
testConsensusEntropyKeyletRequiresAmendment();
testDice();
testDiceZeroSides();
testDiceRequirementNotMet();

View File

@@ -11,6 +11,178 @@ namespace test {
inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
{
/* ==== WASM: 0 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
extern int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot);
extern int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot);
extern int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot_no);
#define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1)
#define KEYLET_CONSENSUS_ENTROPY 37
#define sfEntropyTier ((16U << 16U) + 21U)
#define sfEntropyCount ((1U << 16U) + 99U)
#define sfEntropyDenominator ((1U << 16U) + 100U)
#define sfDigest ((5U << 16U) + 21U)
int64_t hook(uint32_t r)
{
_g(1,1);
uint8_t keylet[34];
int64_t result = util_keylet((uint32_t)keylet, 34, KEYLET_CONSENSUS_ENTROPY, 0, 0, 0, 0, 0, 0);
if (result != 34)
rollback(0, 0, result);
result = slot_set((uint32_t)keylet, 34, 1);
if (result != 1)
rollback(0, 0, result);
result = slot_subfield(1, sfEntropyCount, 2);
if (result != 2)
rollback(0, 0, result);
if (slot(0, 0, 2) != 20)
rollback(0, 0, -20);
result = slot_subfield(1, sfEntropyDenominator, 3);
if (result != 3)
rollback(0, 0, result);
if (slot(0, 0, 3) != 20)
rollback(0, 0, -21);
result = slot_subfield(1, sfEntropyTier, 4);
if (result != 4)
rollback(0, 0, result);
if (slot(0, 0, 4) != 4)
rollback(0, 0, -22);
result = slot_subfield(1, sfDigest, 5);
if (result != 5)
rollback(0, 0, result);
uint8_t digest[32];
result = slot((uint32_t)digest, 32, 5);
if (result != 32)
rollback(0, 0, result);
int nonzero = 0;
for (int i = 0; GUARD(32), i < 32; ++i)
if (digest[i] != 0) nonzero = 1;
if (!nonzero)
rollback(0, 0, -23);
return accept((uint32_t)digest, 32, 42);
}
)[test.hook]",
{
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U,
0x27U, 0x05U, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU,
0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x02U,
0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x09U, 0x7FU, 0x7FU, 0x7FU,
0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U,
0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x66U, 0x07U, 0x03U, 0x65U,
0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x02U, 0x03U, 0x65U,
0x6EU, 0x76U, 0x0BU, 0x75U, 0x74U, 0x69U, 0x6CU, 0x5FU, 0x6BU,
0x65U, 0x79U, 0x6CU, 0x65U, 0x74U, 0x00U, 0x03U, 0x03U, 0x65U,
0x6EU, 0x76U, 0x08U, 0x72U, 0x6FU, 0x6CU, 0x6CU, 0x62U, 0x61U,
0x63U, 0x6BU, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x08U,
0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, 0x00U,
0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0DU, 0x73U, 0x6CU, 0x6FU,
0x74U, 0x5FU, 0x73U, 0x75U, 0x62U, 0x66U, 0x69U, 0x65U, 0x6CU,
0x64U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x04U, 0x73U,
0x6CU, 0x6FU, 0x74U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U,
0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x01U,
0x03U, 0x02U, 0x01U, 0x04U, 0x05U, 0x03U, 0x01U, 0x00U, 0x01U,
0x06U, 0x08U, 0x01U, 0x7FU, 0x01U, 0x41U, 0x80U, 0x80U, 0x04U,
0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU,
0x00U, 0x07U, 0x0AU, 0x84U, 0x03U, 0x01U, 0x81U, 0x03U, 0x02U,
0x01U, 0x7EU, 0x03U, 0x7FU, 0x23U, 0x00U, 0x41U, 0xD0U, 0x00U,
0x6BU, 0x22U, 0x00U, 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U,
0x10U, 0x00U, 0x1AU, 0x20U, 0x00U, 0x41U, 0x20U, 0x6AU, 0x41U,
0x22U, 0x41U, 0x25U, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x00U,
0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x00U, 0x10U, 0x01U, 0x22U,
0x01U, 0x42U, 0x22U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U,
0x00U, 0x20U, 0x01U, 0x10U, 0x02U, 0x1AU, 0x0BU, 0x20U, 0x00U,
0x41U, 0x20U, 0x6AU, 0x41U, 0x22U, 0x41U, 0x01U, 0x10U, 0x03U,
0x22U, 0x01U, 0x42U, 0x01U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U,
0x41U, 0x00U, 0x20U, 0x01U, 0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U,
0x01U, 0x41U, 0xE3U, 0x80U, 0x04U, 0x41U, 0x02U, 0x10U, 0x04U,
0x22U, 0x01U, 0x42U, 0x02U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U,
0x41U, 0x00U, 0x20U, 0x01U, 0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U,
0x00U, 0x41U, 0x00U, 0x41U, 0x02U, 0x10U, 0x05U, 0x42U, 0x14U,
0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x6CU,
0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U, 0x01U, 0x41U, 0xE4U, 0x80U,
0x04U, 0x41U, 0x03U, 0x10U, 0x04U, 0x22U, 0x01U, 0x42U, 0x03U,
0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U,
0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U,
0x03U, 0x10U, 0x05U, 0x42U, 0x14U, 0x52U, 0x04U, 0x40U, 0x41U,
0x00U, 0x41U, 0x00U, 0x42U, 0x6BU, 0x10U, 0x02U, 0x1AU, 0x0BU,
0x41U, 0x01U, 0x41U, 0x95U, 0x80U, 0xC0U, 0x00U, 0x41U, 0x04U,
0x10U, 0x04U, 0x22U, 0x01U, 0x42U, 0x04U, 0x52U, 0x04U, 0x40U,
0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U, 0x10U, 0x02U, 0x1AU,
0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x04U, 0x10U, 0x05U,
0x42U, 0x04U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U,
0x42U, 0x6AU, 0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U, 0x01U, 0x41U,
0x95U, 0x80U, 0x14U, 0x41U, 0x05U, 0x10U, 0x04U, 0x22U, 0x01U,
0x42U, 0x05U, 0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U,
0x20U, 0x01U, 0x10U, 0x02U, 0x1AU, 0x0BU, 0x20U, 0x00U, 0x41U,
0x20U, 0x41U, 0x05U, 0x10U, 0x05U, 0x22U, 0x01U, 0x42U, 0x20U,
0x52U, 0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U,
0x10U, 0x02U, 0x1AU, 0x0BU, 0x41U, 0xBAU, 0x80U, 0x80U, 0x80U,
0x78U, 0x41U, 0x21U, 0x10U, 0x00U, 0x1AU, 0x03U, 0x40U, 0x41U,
0xBAU, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x21U, 0x10U, 0x00U,
0x1AU, 0x20U, 0x00U, 0x20U, 0x02U, 0x6AU, 0x2DU, 0x00U, 0x00U,
0x21U, 0x04U, 0x41U, 0x01U, 0x20U, 0x03U, 0x20U, 0x04U, 0x1BU,
0x21U, 0x03U, 0x20U, 0x02U, 0x41U, 0x01U, 0x6AU, 0x22U, 0x02U,
0x41U, 0x20U, 0x47U, 0x0DU, 0x00U, 0x0BU, 0x20U, 0x03U, 0x45U,
0x04U, 0x40U, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x69U, 0x10U,
0x02U, 0x1AU, 0x0BU, 0x20U, 0x00U, 0x41U, 0x20U, 0x42U, 0x2AU,
0x10U, 0x06U, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, 0xD0U, 0x00U,
0x6AU, 0x24U, 0x00U, 0x20U, 0x01U, 0x0BU,
}},
/* ==== WASM: 1 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
extern int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code);
extern int64_t util_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t keylet_type, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f);
#define KEYLET_CONSENSUS_ENTROPY 37
int64_t hook(uint32_t r)
{
_g(1,1);
uint8_t keylet[34];
int64_t result = util_keylet((uint32_t)keylet, 34, KEYLET_CONSENSUS_ENTROPY, 0, 0, 0, 0, 0, 0);
return accept(0, 0, result);
}
)[test.hook]",
{
0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U,
0x20U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U,
0x09U, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU,
0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U,
0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x29U, 0x03U,
0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U,
0x03U, 0x65U, 0x6EU, 0x76U, 0x0BU, 0x75U, 0x74U, 0x69U, 0x6CU,
0x5FU, 0x6BU, 0x65U, 0x79U, 0x6CU, 0x65U, 0x74U, 0x00U, 0x01U,
0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, 0x63U, 0x65U,
0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U, 0x01U, 0x03U, 0x05U,
0x03U, 0x01U, 0x00U, 0x01U, 0x06U, 0x08U, 0x01U, 0x7FU, 0x01U,
0x41U, 0x80U, 0x80U, 0x04U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U,
0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, 0x3BU, 0x01U,
0x39U, 0x01U, 0x01U, 0x7EU, 0x23U, 0x00U, 0x41U, 0x30U, 0x6BU,
0x22U, 0x00U, 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U,
0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x00U, 0x41U,
0x22U, 0x41U, 0x25U, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x00U,
0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x00U, 0x10U, 0x01U, 0x10U,
0x02U, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, 0x30U, 0x6AU, 0x24U,
0x00U, 0x20U, 0x01U, 0x0BU,
}},
/* ==== WASM: 2 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
@@ -60,7 +232,7 @@ inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
0x0BU,
}},
/* ==== WASM: 1 ==== */
/* ==== WASM: 3 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
@@ -134,7 +306,7 @@ inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
0x6AU, 0x24U, 0x00U, 0x20U, 0x04U, 0x0BU,
}},
/* ==== WASM: 2 ==== */
/* ==== WASM: 4 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
@@ -186,7 +358,7 @@ inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
0x14U, 0x86U, 0x20U, 0x01U, 0x84U, 0x10U, 0x03U, 0x0BU,
}},
/* ==== WASM: 3 ==== */
/* ==== WASM: 5 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
@@ -218,7 +390,7 @@ inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
0x0BU,
}},
/* ==== WASM: 4 ==== */
/* ==== WASM: 6 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);
@@ -250,7 +422,7 @@ inline std::map<std::string, std::vector<uint8_t>> consensusentropy_test_wasm =
0x0BU,
}},
/* ==== WASM: 5 ==== */
/* ==== WASM: 7 ==== */
{R"[test.hook](
#include <stdint.h>
extern int32_t _g(uint32_t, uint32_t);

View File

@@ -2438,7 +2438,12 @@ DEFINE_HOOK_FUNCTION(
case keylet_code::AMENDMENTS:
case keylet_code::FEES:
case keylet_code::NEGATIVE_UNL:
case keylet_code::EMITTED_DIR: {
case keylet_code::EMITTED_DIR:
case keylet_code::CONSENSUS_ENTROPY: {
if (keylet_type == keylet_code::CONSENSUS_ENTROPY &&
!applyCtx.view().rules().enabled(featureConsensusEntropy))
return INVALID_ARGUMENT;
if (a != 0 || b != 0 || c != 0 || d != 0 || e != 0 || f != 0)
return INVALID_ARGUMENT;
@@ -2462,6 +2467,8 @@ DEFINE_HOOK_FUNCTION(
makeKeyCache(ripple::keylet::negativeUNL());
static std::array<uint8_t, 34> cEmittedDir =
makeKeyCache(ripple::keylet::emittedDir());
static std::array<uint8_t, 34> cConsensusEntropy =
makeKeyCache(ripple::keylet::consensusEntropy());
WRITE_WASM_MEMORY_AND_RETURN(
write_ptr,
@@ -2470,6 +2477,8 @@ DEFINE_HOOK_FUNCTION(
: keylet_type == keylet_code::FEES ? cFees.data()
: keylet_type == keylet_code::NEGATIVE_UNL
? cNegativeUNL.data()
: keylet_type == keylet_code::CONSENSUS_ENTROPY
? cConsensusEntropy.data()
: cEmittedDir.data(),
34,
memory,