diff --git a/hook/genesis/headers/hookapi.h b/hook/genesis/headers/hookapi.h index c42ebe655..ab0ef4dd4 100644 --- a/hook/genesis/headers/hookapi.h +++ b/hook/genesis/headers/hookapi.h @@ -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 \ No newline at end of file +#endif diff --git a/hook/hookapi.h b/hook/hookapi.h index 69890544b..b1129dadd 100644 --- a/hook/hookapi.h +++ b/hook/hookapi.h @@ -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 diff --git a/include/xrpl/hook/Enum.h b/include/xrpl/hook/Enum.h index 8ad631f84..30f083bd6 100644 --- a/include/xrpl/hook/Enum.h +++ b/include/xrpl/hook/Enum.h @@ -315,6 +315,7 @@ enum keylet_code : uint32_t { MPTOKEN = 34, CREDENTIAL = 35, PERMISSIONED_DOMAIN = 36, + CONSENSUS_ENTROPY = 37, }; } diff --git a/src/test/app/ConsensusEntropy_test.cpp b/src/test/app/ConsensusEntropy_test.cpp index bdadfff20..5b78c8a55 100644 --- a/src/test/app/ConsensusEntropy_test.cpp +++ b/src/test/app/ConsensusEntropy_test.cpp @@ -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 + 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 + 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(); diff --git a/src/test/app/ConsensusEntropy_test_hooks.h b/src/test/app/ConsensusEntropy_test_hooks.h index 8130b7ced..764939319 100644 --- a/src/test/app/ConsensusEntropy_test_hooks.h +++ b/src/test/app/ConsensusEntropy_test_hooks.h @@ -11,6 +11,178 @@ namespace test { inline std::map> consensusentropy_test_wasm = { /* ==== WASM: 0 ==== */ + {R"[test.hook]( + #include + 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 + 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 extern int32_t _g(uint32_t, uint32_t); @@ -60,7 +232,7 @@ inline std::map> consensusentropy_test_wasm = 0x0BU, }}, - /* ==== WASM: 1 ==== */ + /* ==== WASM: 3 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -134,7 +306,7 @@ inline std::map> consensusentropy_test_wasm = 0x6AU, 0x24U, 0x00U, 0x20U, 0x04U, 0x0BU, }}, - /* ==== WASM: 2 ==== */ + /* ==== WASM: 4 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -186,7 +358,7 @@ inline std::map> consensusentropy_test_wasm = 0x14U, 0x86U, 0x20U, 0x01U, 0x84U, 0x10U, 0x03U, 0x0BU, }}, - /* ==== WASM: 3 ==== */ + /* ==== WASM: 5 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -218,7 +390,7 @@ inline std::map> consensusentropy_test_wasm = 0x0BU, }}, - /* ==== WASM: 4 ==== */ + /* ==== WASM: 6 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -250,7 +422,7 @@ inline std::map> consensusentropy_test_wasm = 0x0BU, }}, - /* ==== WASM: 5 ==== */ + /* ==== WASM: 7 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); diff --git a/src/xrpld/app/hook/detail/applyHook.cpp b/src/xrpld/app/hook/detail/applyHook.cpp index 60e7bab4c..edce0fb2e 100644 --- a/src/xrpld/app/hook/detail/applyHook.cpp +++ b/src/xrpld/app/hook/detail/applyHook.cpp @@ -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 cEmittedDir = makeKeyCache(ripple::keylet::emittedDir()); + static std::array 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,