diff --git a/hook/extern.h b/hook/extern.h index a618635e7..08deab613 100644 --- a/hook/extern.h +++ b/hook/extern.h @@ -361,9 +361,9 @@ xport_cancel(uint32_t read_ptr, uint32_t read_len, uint32_t flags); 1 = consensus_fallback, 2 = participant_aligned, 3 = validator_quorum, 4 = validator_full. - entropy_status writes five big-endian bytes: - tier:u8, count:u16, denominator:u16 - and returns ledger age (0 current, 1 previous, >1 stale). + entropy_status returns a packed non-negative value: + bits 32..39 tier, 16..31 count, 0..15 denominator. + Check for a negative error before using the ENTROPY_* macros. Classify tier before count/denominator arithmetic: fallback is tier 1 with count=denominator=0. Common policies are denominator-count <= 1, @@ -380,7 +380,7 @@ extern int64_t random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier); extern int64_t -entropy_status(uint32_t write_ptr, uint32_t write_len); +entropy_status(); #ifdef __cplusplus } diff --git a/hook/generate_extern.sh b/hook/generate_extern.sh index 6987ddad2..554e2e9c5 100755 --- a/hook/generate_extern.sh +++ b/hook/generate_extern.sh @@ -50,9 +50,9 @@ APPLY_HOOK="$SCRIPT_DIR/../include/xrpl/hook/hook_api.macro" print " 1 = consensus_fallback, 2 = participant_aligned,"; print " 3 = validator_quorum, 4 = validator_full."; print ""; - print " entropy_status writes five big-endian bytes:"; - print " tier:u8, count:u16, denominator:u16"; - print " and returns ledger age (0 current, 1 previous, >1 stale)."; + print " entropy_status returns a packed non-negative value:"; + print " bits 32..39 tier, 16..31 count, 0..15 denominator."; + print " Check for a negative error before using the ENTROPY_* macros."; print ""; print " Classify tier before count/denominator arithmetic: fallback is tier 1"; print " with count=denominator=0. Common policies are denominator-count <= 1,"; diff --git a/hook/macro.h b/hook/macro.h index 838c2b55c..3719ca293 100644 --- a/hook/macro.h +++ b/hook/macro.h @@ -145,6 +145,10 @@ int out_len = 0;\ #define SUB_OFFSET(x) ((int32_t)(x >> 32)) #define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL)) +#define ENTROPY_TIER(x) (((uint64_t)(x) >> 32U) & 0xFFU) +#define ENTROPY_COUNT(x) (((uint64_t)(x) >> 16U) & 0xFFFFU) +#define ENTROPY_DENOMINATOR(x) ((uint64_t)(x) & 0xFFFFU) + #define BUFFER_EQUAL_20(buf1, buf2)\ (\ *(((uint64_t*)(buf1)) + 0) == *(((uint64_t*)(buf2)) + 0) &&\ @@ -378,4 +382,3 @@ int out_len = 0;\ #endif - diff --git a/include/xrpl/hook/hook_api.macro b/include/xrpl/hook/hook_api.macro index cae5e063c..f2b1f347b 100644 --- a/include/xrpl/hook/hook_api.macro +++ b/include/xrpl/hook/hook_api.macro @@ -398,7 +398,7 @@ HOOK_API_DEFINITION( int64_t, random, (uint32_t, uint32_t, uint32_t), featureConsensusEntropy) -// int64_t entropy_status(uint32_t write_ptr, uint32_t write_len); +// int64_t entropy_status(); HOOK_API_DEFINITION( - int64_t, entropy_status, (uint32_t, uint32_t), + int64_t, entropy_status, (), featureConsensusEntropy) diff --git a/src/test/app/ConsensusEntropy_test.cpp b/src/test/app/ConsensusEntropy_test.cpp index f2a875a97..1bf04c135 100644 --- a/src/test/app/ConsensusEntropy_test.cpp +++ b/src/test/app/ConsensusEntropy_test.cpp @@ -482,45 +482,34 @@ class ConsensusEntropy_test : public beast::unit_test::suite #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 entropy_status(uint32_t write_ptr, uint32_t write_len); - #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) - #define OUT_OF_BOUNDS (-1) - #define TOO_SMALL (-4) + extern int64_t entropy_status(); + #define ENTROPY_TIER(x) (((uint64_t)(x) >> 32U) & 0xFFU) + #define ENTROPY_COUNT(x) (((uint64_t)(x) >> 16U) & 0xFFFFU) + #define ENTROPY_DENOMINATOR(x) ((uint64_t)(x) & 0xFFFFU) int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5] = {0xA5, 0xA5, 0xA5, 0xA5, 0xA5}; - - if (entropy_status((uint32_t)status, 4) != TOO_SMALL) - return accept(0, 0, 10); - for (int i = 0; GUARD(5), i < 5; ++i) - if (status[i] != 0xA5) - return accept(0, 0, 11); - - if (entropy_status(0xFFFFFFFEU, 5) != OUT_OF_BOUNDS) - return accept(0, 0, 12); - - int64_t age = entropy_status((uint32_t)status, 5); - if (age < 0 || age > 1) + int64_t status = entropy_status(); + if (status < 0) return accept(0, 0, 13); - uint32_t count = ((uint32_t)status[1] << 8) | status[2]; - uint32_t denominator = - ((uint32_t)status[3] << 8) | status[4]; - if (status[0] != 3 || count != 19 || denominator != 20) + uint32_t tier = ENTROPY_TIER(status); + uint32_t count = ENTROPY_COUNT(status); + uint32_t denominator = ENTROPY_DENOMINATOR(status); + if (tier != 3 || count != 19 || denominator != 20) return accept(0, 0, 14); // Common caller-side policies: tolerate one absent, require // 4/5 participation, and require an absolute floor of 19. - if (status[0] < 2 || denominator - count > 1) + if (tier < 2 || denominator - count > 1) return accept(0, 0, 15); if ((uint64_t)5 * count < (uint64_t)4 * denominator) return accept(0, 0, 16); if (count < 19) return accept(0, 0, 17); - return accept(0, 0, age); + return accept(0, 0, 0); } )[test.hook]"]; @@ -541,8 +530,6 @@ class ConsensusEntropy_test : public beast::unit_test::suite auto const hookExecutions = meta->getFieldArray(sfHookExecutions); BEAST_REQUIRE(hookExecutions.size() == 1); - // Open-ledger preview accepts age 1; final ordered execution sees the - // current-ledger pseudo first and records age 0 in final metadata. BEAST_EXPECT(hookReturnCode(hookExecutions[0]) == 0); BEAST_EXPECT(hookExecutions[0].getFieldU8(sfHookResult) == 3); } @@ -581,18 +568,20 @@ class ConsensusEntropy_test : public beast::unit_test::suite 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 dice(uint32_t sides, uint32_t min_tier); - extern int64_t entropy_status(uint32_t write_ptr, uint32_t write_len); + extern int64_t entropy_status(); + #define ENTROPY_TIER(x) (((uint64_t)(x) >> 32U) & 0xFFU) + #define ENTROPY_COUNT(x) (((uint64_t)(x) >> 16U) & 0xFFFFU) + #define ENTROPY_DENOMINATOR(x) ((uint64_t)(x) & 0xFFFFU) #define TOO_LITTLE_ENTROPY (-48) int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5]; - int64_t age = entropy_status((uint32_t)status, 5); - if (age < 0 || age > 1) + int64_t status = entropy_status(); + if (status < 0) return accept(0, 0, 20); - if (status[0] != 1 || status[1] != 0 || status[2] != 0 || - status[3] != 0 || status[4] != 0) + if (ENTROPY_TIER(status) != 1 || ENTROPY_COUNT(status) != 0 || + ENTROPY_DENOMINATOR(status) != 0) return accept(0, 0, 21); int64_t allowed = dice(6, 1); @@ -601,7 +590,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite if (dice(6, 2) != TOO_LITTLE_ENTROPY) return accept(0, 0, 23); - return accept(0, 0, age); + return accept(0, 0, 0); } )[test.hook]"]; @@ -694,7 +683,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite void testDiceWithoutAmendment() { - testcase("Hook dice() import fails without ConsensusEntropy amendment"); + testcase("Hook entropy imports independently require amendment"); using namespace jtx; Env env{*this, supported_amendments()}; @@ -705,31 +694,126 @@ class ConsensusEntropy_test : public beast::unit_test::suite BEAST_EXPECT(!env.le(keylet::consensusEntropy())); - // The CE hook APIs are amendment-scoped at install time. Without - // featureConsensusEntropy, a hook importing dice() is not installable, - // so the runtime path cannot be reached with the API disabled. - TestHook hook = consensusentropy_test_wasm[R"[test.hook]( + TestHook diceHook = 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 dice(uint32_t sides, uint32_t min_tier); - extern int64_t entropy_status(uint32_t write_ptr, uint32_t write_len); int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5]; - int64_t result = entropy_status((uint32_t)status, 5); - if (result >= 0) - result = dice(6, 3); - return accept(0, 0, result); + return accept(0, 0, dice(6, 3)); + } + )[test.hook]"]; + + TestHook randomHook = 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 random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier); + + int64_t hook(uint32_t r) + { + _g(1,1); + uint8_t buf[32]; + return accept(0, 0, random((uint32_t)buf, 32, 3)); + } + )[test.hook]"]; + + TestHook statusHook = 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 entropy_status(); + + int64_t hook(uint32_t r) + { + _g(1,1); + return accept(0, 0, entropy_status()); + } + )[test.hook]"]; + + env(ripple::test::jtx::hook(alice, {{hso(diceHook, overrideFlag)}}, 0), + M("set dice-no-amendment hook"), + HSFEE, + ter(temMALFORMED)); + env(ripple::test::jtx::hook( + alice, {{hso(randomHook, overrideFlag)}}, 0), + M("set random-no-amendment hook"), + HSFEE, + ter(temMALFORMED)); + env(ripple::test::jtx::hook( + alice, {{hso(statusHook, overrideFlag)}}, 0), + M("set entropy-status-no-amendment hook"), + HSFEE, + ter(temMALFORMED)); + } + + void + testRandomTierRequirementNotMet() + { + testcase("Hook random() fails before write below min_tier"); + using namespace jtx; + + Env env{ + *this, + envconfig(), + supported_amendments() | featureConsensusEntropy, + nullptr}; + + ConsensusTestConfig cfg; + cfg.standaloneEntropyTier = entropyTierValidatorQuorum; + cfg.standaloneEntropyCount = 19; + cfg.standaloneEntropyDenominator = 20; + env.app().getRuntimeConfig().setGlobalConfig(cfg); + + auto const alice = Account{"alice"}; + env.fund(XRP(10000), alice); + env.close(); + + 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 random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier); + #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) + #define TOO_LITTLE_ENTROPY (-48) + + int64_t hook(uint32_t r) + { + _g(1,1); + uint8_t buf[32]; + for (int i = 0; GUARD(32), i < 32; ++i) + buf[i] = 0xA5; + + if (random((uint32_t)buf, 32, 4) != TOO_LITTLE_ENTROPY) + return accept(0, 0, 30); + for (int i = 0; GUARD(32), i < 32; ++i) + if (buf[i] != 0xA5) + return accept(0, 0, 31); + + return accept(0, 0, 0); } )[test.hook]"]; env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), - M("set dice-no-amendment hook"), - HSFEE, - ter(temMALFORMED)); + M("set random-tier-requirement hook"), + HSFEE); + env.close(); + + Json::Value invoke; + invoke[jss::TransactionType] = "Invoke"; + invoke[jss::Account] = alice.human(); + env(invoke, M("test random min_tier unmet"), 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]) == 0); + BEAST_EXPECT(hookExecutions[0].getFieldU8(sfHookResult) == 3); } void @@ -825,6 +909,7 @@ class ConsensusEntropy_test : public beast::unit_test::suite testEntropyStatusFallback(); testDiceTierRequirementNotMet(); testDiceWithoutAmendment(); + testRandomTierRequirementNotMet(); testInvalidEntropyRequirements(); testRandom(); testDiceConsecutiveCallsDiffer(); diff --git a/src/test/app/ConsensusEntropy_test_hooks.h b/src/test/app/ConsensusEntropy_test_hooks.h index 6b6585145..782f6d4da 100644 --- a/src/test/app/ConsensusEntropy_test_hooks.h +++ b/src/test/app/ConsensusEntropy_test_hooks.h @@ -221,95 +221,54 @@ inline std::map> consensusentropy_test_wasm = #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 entropy_status(uint32_t write_ptr, uint32_t write_len); - #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) - #define OUT_OF_BOUNDS (-1) - #define TOO_SMALL (-4) + extern int64_t entropy_status(); + #define ENTROPY_TIER(x) (((uint64_t)(x) >> 32U) & 0xFFU) + #define ENTROPY_COUNT(x) (((uint64_t)(x) >> 16U) & 0xFFFFU) + #define ENTROPY_DENOMINATOR(x) ((uint64_t)(x) & 0xFFFFU) int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5] = {0xA5, 0xA5, 0xA5, 0xA5, 0xA5}; - - if (entropy_status((uint32_t)status, 4) != TOO_SMALL) - return accept(0, 0, 10); - for (int i = 0; GUARD(5), i < 5; ++i) - if (status[i] != 0xA5) - return accept(0, 0, 11); - - if (entropy_status(0xFFFFFFFEU, 5) != OUT_OF_BOUNDS) - return accept(0, 0, 12); - - int64_t age = entropy_status((uint32_t)status, 5); - if (age < 0 || age > 1) + int64_t status = entropy_status(); + if (status < 0) return accept(0, 0, 13); - uint32_t count = ((uint32_t)status[1] << 8) | status[2]; - uint32_t denominator = - ((uint32_t)status[3] << 8) | status[4]; - if (status[0] != 3 || count != 19 || denominator != 20) + uint32_t tier = ENTROPY_TIER(status); + uint32_t count = ENTROPY_COUNT(status); + uint32_t denominator = ENTROPY_DENOMINATOR(status); + if (tier != 3 || count != 19 || denominator != 20) return accept(0, 0, 14); // Common caller-side policies: tolerate one absent, require // 4/5 participation, and require an absolute floor of 19. - if (status[0] < 2 || denominator - count > 1) + if (tier < 2 || denominator - count > 1) return accept(0, 0, 15); if ((uint64_t)5 * count < (uint64_t)4 * denominator) return accept(0, 0, 16); if (count < 19) return accept(0, 0, 17); - return accept(0, 0, age); + return accept(0, 0, 0); } )[test.hook]", { 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, - 0x19U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, - 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, - 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, - 0x2CU, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, - 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0EU, 0x65U, 0x6EU, - 0x74U, 0x72U, 0x6FU, 0x70U, 0x79U, 0x5FU, 0x73U, 0x74U, 0x61U, - 0x74U, 0x75U, 0x73U, 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, 0xB2U, 0x02U, 0x01U, 0xAFU, 0x02U, 0x01U, - 0x01U, 0x7EU, 0x23U, 0x00U, 0x41U, 0x10U, 0x6BU, 0x22U, 0x00U, - 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, - 0x20U, 0x00U, 0x41U, 0xA5U, 0x01U, 0x3AU, 0x00U, 0x0CU, 0x20U, - 0x00U, 0x41U, 0xA5U, 0xCBU, 0x96U, 0xADU, 0x7AU, 0x36U, 0x02U, - 0x08U, 0x02U, 0x40U, 0x20U, 0x00U, 0x41U, 0x08U, 0x6AU, 0x41U, - 0x04U, 0x10U, 0x01U, 0x42U, 0x7CU, 0x52U, 0x04U, 0x40U, 0x42U, - 0x0AU, 0x21U, 0x01U, 0x0CU, 0x01U, 0x0BU, 0x41U, 0x91U, 0x80U, - 0x80U, 0x80U, 0x78U, 0x41U, 0x06U, 0x10U, 0x00U, 0x1AU, 0x42U, - 0x0BU, 0x21U, 0x01U, 0x20U, 0x00U, 0x2DU, 0x00U, 0x08U, 0x41U, - 0xA5U, 0x01U, 0x47U, 0x0DU, 0x00U, 0x41U, 0x91U, 0x80U, 0x80U, - 0x80U, 0x78U, 0x41U, 0x06U, 0x10U, 0x00U, 0x1AU, 0x20U, 0x00U, - 0x2DU, 0x00U, 0x09U, 0x41U, 0xA5U, 0x01U, 0x47U, 0x0DU, 0x00U, - 0x41U, 0x91U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x06U, 0x10U, - 0x00U, 0x1AU, 0x20U, 0x00U, 0x2DU, 0x00U, 0x0AU, 0x41U, 0xA5U, - 0x01U, 0x47U, 0x0DU, 0x00U, 0x41U, 0x91U, 0x80U, 0x80U, 0x80U, - 0x78U, 0x41U, 0x06U, 0x10U, 0x00U, 0x1AU, 0x20U, 0x00U, 0x2DU, - 0x00U, 0x0BU, 0x41U, 0xA5U, 0x01U, 0x47U, 0x0DU, 0x00U, 0x41U, - 0x91U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x06U, 0x10U, 0x00U, - 0x1AU, 0x20U, 0x00U, 0x2DU, 0x00U, 0x0CU, 0x41U, 0xA5U, 0x01U, - 0x47U, 0x0DU, 0x00U, 0x41U, 0x91U, 0x80U, 0x80U, 0x80U, 0x78U, - 0x41U, 0x06U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x7EU, 0x41U, 0x05U, - 0x10U, 0x01U, 0x42U, 0x7FU, 0x52U, 0x04U, 0x40U, 0x42U, 0x0CU, - 0x21U, 0x01U, 0x0CU, 0x01U, 0x0BU, 0x20U, 0x00U, 0x41U, 0x08U, - 0x6AU, 0x41U, 0x05U, 0x10U, 0x01U, 0x22U, 0x01U, 0x42U, 0x01U, - 0x56U, 0x04U, 0x40U, 0x42U, 0x0DU, 0x21U, 0x01U, 0x0CU, 0x01U, - 0x0BU, 0x42U, 0x0EU, 0x42U, 0x0EU, 0x42U, 0x0EU, 0x20U, 0x01U, - 0x20U, 0x00U, 0x2DU, 0x00U, 0x0CU, 0x20U, 0x00U, 0x2DU, 0x00U, - 0x0BU, 0x41U, 0x08U, 0x74U, 0x72U, 0x41U, 0x14U, 0x47U, 0x1BU, - 0x20U, 0x00U, 0x2DU, 0x00U, 0x0AU, 0x20U, 0x00U, 0x2DU, 0x00U, - 0x09U, 0x41U, 0x08U, 0x74U, 0x72U, 0x41U, 0x13U, 0x47U, 0x1BU, - 0x20U, 0x00U, 0x2DU, 0x00U, 0x08U, 0x41U, 0x03U, 0x47U, 0x1BU, - 0x21U, 0x01U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x01U, - 0x10U, 0x02U, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, 0x10U, 0x6AU, - 0x24U, 0x00U, 0x20U, 0x01U, 0x0BU, + 0x17U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x00U, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, + 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x2CU, 0x03U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x0EU, 0x65U, 0x6EU, 0x74U, 0x72U, + 0x6FU, 0x70U, 0x79U, 0x5FU, 0x73U, 0x74U, 0x61U, 0x74U, 0x75U, + 0x73U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, + 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U, + 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x01U, 0x07U, 0x08U, + 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, + 0x33U, 0x01U, 0x31U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, + 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, + 0x0DU, 0x42U, 0x0EU, 0x42U, 0x00U, 0x10U, 0x01U, 0x22U, 0x01U, + 0x42U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0x1FU, 0x83U, 0x42U, + 0x94U, 0x80U, 0xCCU, 0x80U, 0x30U, 0x52U, 0x1BU, 0x20U, 0x01U, + 0x42U, 0x00U, 0x53U, 0x1BU, 0x10U, 0x02U, 0x0BU, }}, /* ==== WASM: 5 ==== */ @@ -318,18 +277,20 @@ inline std::map> consensusentropy_test_wasm = 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 dice(uint32_t sides, uint32_t min_tier); - extern int64_t entropy_status(uint32_t write_ptr, uint32_t write_len); + extern int64_t entropy_status(); + #define ENTROPY_TIER(x) (((uint64_t)(x) >> 32U) & 0xFFU) + #define ENTROPY_COUNT(x) (((uint64_t)(x) >> 16U) & 0xFFFFU) + #define ENTROPY_DENOMINATOR(x) ((uint64_t)(x) & 0xFFFFU) #define TOO_LITTLE_ENTROPY (-48) int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5]; - int64_t age = entropy_status((uint32_t)status, 5); - if (age < 0 || age > 1) + int64_t status = entropy_status(); + if (status < 0) return accept(0, 0, 20); - if (status[0] != 1 || status[1] != 0 || status[2] != 0 || - status[3] != 0 || status[4] != 0) + if (ENTROPY_TIER(status) != 1 || ENTROPY_COUNT(status) != 0 || + ENTROPY_DENOMINATOR(status) != 0) return accept(0, 0, 21); int64_t allowed = dice(6, 1); @@ -338,40 +299,33 @@ inline std::map> consensusentropy_test_wasm = if (dice(6, 2) != TOO_LITTLE_ENTROPY) return accept(0, 0, 23); - return accept(0, 0, age); + return accept(0, 0, 0); } )[test.hook]", { 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, - 0x19U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, - 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, - 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, - 0x37U, 0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, - 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0EU, 0x65U, 0x6EU, - 0x74U, 0x72U, 0x6FU, 0x70U, 0x79U, 0x5FU, 0x73U, 0x74U, 0x61U, - 0x74U, 0x75U, 0x73U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, - 0x04U, 0x64U, 0x69U, 0x63U, 0x65U, 0x00U, 0x00U, 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, 0x04U, 0x0AU, 0x90U, 0x01U, 0x01U, 0x8DU, - 0x01U, 0x01U, 0x02U, 0x7EU, 0x23U, 0x00U, 0x41U, 0x10U, 0x6BU, - 0x22U, 0x00U, 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, - 0x00U, 0x1AU, 0x02U, 0x40U, 0x20U, 0x00U, 0x41U, 0x0BU, 0x6AU, - 0x41U, 0x05U, 0x10U, 0x01U, 0x22U, 0x02U, 0x42U, 0x01U, 0x56U, - 0x04U, 0x40U, 0x42U, 0x14U, 0x21U, 0x01U, 0x0CU, 0x01U, 0x0BU, - 0x42U, 0x15U, 0x21U, 0x01U, 0x20U, 0x00U, 0x2DU, 0x00U, 0x0BU, - 0x41U, 0x01U, 0x47U, 0x0DU, 0x00U, 0x20U, 0x00U, 0x2DU, 0x00U, - 0x0CU, 0x0DU, 0x00U, 0x20U, 0x00U, 0x2DU, 0x00U, 0x0DU, 0x0DU, - 0x00U, 0x20U, 0x00U, 0x2DU, 0x00U, 0x0EU, 0x0DU, 0x00U, 0x20U, - 0x00U, 0x2DU, 0x00U, 0x0FU, 0x0DU, 0x00U, 0x41U, 0x06U, 0x41U, - 0x01U, 0x10U, 0x02U, 0x42U, 0x05U, 0x56U, 0x04U, 0x40U, 0x42U, - 0x16U, 0x21U, 0x01U, 0x0CU, 0x01U, 0x0BU, 0x42U, 0x17U, 0x20U, - 0x02U, 0x41U, 0x06U, 0x41U, 0x02U, 0x10U, 0x02U, 0x42U, 0x50U, - 0x52U, 0x1BU, 0x21U, 0x01U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, - 0x20U, 0x01U, 0x10U, 0x03U, 0x21U, 0x01U, 0x20U, 0x00U, 0x41U, - 0x10U, 0x6AU, 0x24U, 0x00U, 0x20U, 0x01U, 0x0BU, + 0x1DU, 0x05U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x00U, 0x01U, 0x7EU, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, + 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, + 0x7FU, 0x01U, 0x7EU, 0x02U, 0x37U, 0x04U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x0EU, 0x65U, 0x6EU, 0x74U, 0x72U, 0x6FU, 0x70U, 0x79U, + 0x5FU, 0x73U, 0x74U, 0x61U, 0x74U, 0x75U, 0x73U, 0x00U, 0x01U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x04U, 0x64U, 0x69U, 0x63U, 0x65U, + 0x00U, 0x02U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, 0x63U, + 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x03U, 0x03U, 0x02U, 0x01U, + 0x04U, 0x05U, 0x03U, 0x01U, 0x00U, 0x01U, 0x07U, 0x08U, 0x01U, + 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x04U, 0x0AU, 0x54U, + 0x01U, 0x52U, 0x01U, 0x01U, 0x7EU, 0x41U, 0x01U, 0x41U, 0x01U, + 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x02U, 0x7EU, + 0x42U, 0x14U, 0x10U, 0x01U, 0x22U, 0x01U, 0x42U, 0x00U, 0x53U, + 0x0DU, 0x00U, 0x1AU, 0x42U, 0x15U, 0x20U, 0x01U, 0x42U, 0xFFU, + 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0x1FU, 0x83U, 0x42U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x10U, 0x52U, 0x0DU, 0x00U, 0x1AU, 0x42U, 0x16U, + 0x41U, 0x06U, 0x41U, 0x01U, 0x10U, 0x02U, 0x42U, 0x05U, 0x56U, + 0x0DU, 0x00U, 0x1AU, 0x42U, 0x17U, 0x42U, 0x00U, 0x41U, 0x06U, + 0x41U, 0x02U, 0x10U, 0x02U, 0x42U, 0x50U, 0x52U, 0x1BU, 0x0BU, + 0x10U, 0x03U, 0x0BU, }}, /* ==== WASM: 6 ==== */ @@ -410,43 +364,156 @@ inline std::map> consensusentropy_test_wasm = 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 dice(uint32_t sides, uint32_t min_tier); - extern int64_t entropy_status(uint32_t write_ptr, uint32_t write_len); int64_t hook(uint32_t r) { _g(1,1); - uint8_t status[5]; - int64_t result = entropy_status((uint32_t)status, 5); - if (result >= 0) - result = dice(6, 3); - return accept(0, 0, result); + return accept(0, 0, dice(6, 3)); } )[test.hook]", { 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, - 0x19U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, - 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, 0x03U, 0x7FU, 0x7FU, + 0x19U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, - 0x37U, 0x04U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, - 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x0EU, 0x65U, 0x6EU, - 0x74U, 0x72U, 0x6FU, 0x70U, 0x79U, 0x5FU, 0x73U, 0x74U, 0x61U, - 0x74U, 0x75U, 0x73U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, - 0x04U, 0x64U, 0x69U, 0x63U, 0x65U, 0x00U, 0x00U, 0x03U, 0x65U, + 0x22U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, + 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x04U, 0x64U, 0x69U, + 0x63U, 0x65U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, + 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x02U, 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x01U, 0x07U, + 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, + 0x0AU, 0x17U, 0x01U, 0x15U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, + 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x41U, 0x06U, + 0x41U, 0x03U, 0x10U, 0x01U, 0x10U, 0x02U, 0x0BU, + }}, + + /* ==== WASM: 8 ==== */ + {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 random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier); + + int64_t hook(uint32_t r) + { + _g(1,1); + uint8_t buf[32]; + return accept(0, 0, random((uint32_t)buf, 32, 3)); + } + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, + 0x1AU, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x03U, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, + 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, + 0x02U, 0x24U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, + 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x72U, + 0x61U, 0x6EU, 0x64U, 0x6FU, 0x6DU, 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, 0x04U, 0x0AU, 0x41U, 0x01U, 0x3FU, 0x01U, - 0x01U, 0x7EU, 0x23U, 0x00U, 0x41U, 0x10U, 0x6BU, 0x22U, 0x00U, + 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, 0x2FU, 0x01U, 0x2DU, 0x01U, + 0x01U, 0x7EU, 0x23U, 0x00U, 0x41U, 0x20U, 0x6BU, 0x22U, 0x00U, 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x00U, 0x1AU, - 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x00U, 0x41U, 0x0BU, 0x6AU, - 0x41U, 0x05U, 0x10U, 0x01U, 0x22U, 0x01U, 0x42U, 0x00U, 0x59U, - 0x04U, 0x7EU, 0x41U, 0x06U, 0x41U, 0x03U, 0x10U, 0x02U, 0x05U, - 0x20U, 0x01U, 0x0BU, 0x10U, 0x03U, 0x21U, 0x01U, 0x20U, 0x00U, - 0x41U, 0x10U, 0x6AU, 0x24U, 0x00U, 0x20U, 0x01U, 0x0BU, + 0x41U, 0x00U, 0x41U, 0x00U, 0x20U, 0x00U, 0x41U, 0x20U, 0x41U, + 0x03U, 0x10U, 0x01U, 0x10U, 0x02U, 0x21U, 0x01U, 0x20U, 0x00U, + 0x41U, 0x20U, 0x6AU, 0x24U, 0x00U, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 8 ==== */ + /* ==== WASM: 9 ==== */ + {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 entropy_status(); + + int64_t hook(uint32_t r) + { + _g(1,1); + return accept(0, 0, entropy_status()); + } + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, + 0x17U, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x00U, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, 0x7FU, 0x7EU, 0x01U, + 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x02U, 0x2CU, 0x03U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, + 0x03U, 0x65U, 0x6EU, 0x76U, 0x0EU, 0x65U, 0x6EU, 0x74U, 0x72U, + 0x6FU, 0x70U, 0x79U, 0x5FU, 0x73U, 0x74U, 0x61U, 0x74U, 0x75U, + 0x73U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x61U, + 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, 0x02U, + 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x01U, 0x07U, 0x08U, + 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x00U, 0x03U, 0x0AU, + 0x13U, 0x01U, 0x11U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, + 0x00U, 0x1AU, 0x41U, 0x00U, 0x41U, 0x00U, 0x10U, 0x01U, 0x10U, + 0x02U, 0x0BU, + }}, + + /* ==== WASM: 10 ==== */ + {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 random(uint32_t write_ptr, uint32_t write_len, uint32_t min_tier); + #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) + #define TOO_LITTLE_ENTROPY (-48) + + int64_t hook(uint32_t r) + { + _g(1,1); + uint8_t buf[32]; + for (int i = 0; GUARD(32), i < 32; ++i) + buf[i] = 0xA5; + + if (random((uint32_t)buf, 32, 4) != TOO_LITTLE_ENTROPY) + return accept(0, 0, 30); + for (int i = 0; GUARD(32), i < 32; ++i) + if (buf[i] != 0xA5) + return accept(0, 0, 31); + + return accept(0, 0, 0); + } + )[test.hook]", + { + 0x00U, 0x61U, 0x73U, 0x6DU, 0x01U, 0x00U, 0x00U, 0x00U, 0x01U, + 0x1AU, 0x04U, 0x60U, 0x02U, 0x7FU, 0x7FU, 0x01U, 0x7FU, 0x60U, + 0x03U, 0x7FU, 0x7FU, 0x7FU, 0x01U, 0x7EU, 0x60U, 0x03U, 0x7FU, + 0x7FU, 0x7EU, 0x01U, 0x7EU, 0x60U, 0x01U, 0x7FU, 0x01U, 0x7EU, + 0x02U, 0x24U, 0x03U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x02U, 0x5FU, + 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, 0x76U, 0x06U, 0x72U, + 0x61U, 0x6EU, 0x64U, 0x6FU, 0x6DU, 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, 0xC7U, 0x01U, 0x01U, 0xC4U, + 0x01U, 0x02U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x00U, 0x41U, + 0x20U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x00U, 0x41U, 0x01U, 0x41U, + 0x01U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x8DU, 0x80U, 0x80U, 0x80U, + 0x78U, 0x41U, 0x21U, 0x10U, 0x00U, 0x1AU, 0x41U, 0x00U, 0x21U, + 0x00U, 0x03U, 0x40U, 0x41U, 0x8DU, 0x80U, 0x80U, 0x80U, 0x78U, + 0x41U, 0x21U, 0x10U, 0x00U, 0x1AU, 0x20U, 0x00U, 0x20U, 0x01U, + 0x6AU, 0x41U, 0xA5U, 0x01U, 0x3AU, 0x00U, 0x00U, 0x01U, 0x01U, + 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, + 0x20U, 0x00U, 0x41U, 0x01U, 0x6AU, 0x22U, 0x00U, 0x41U, 0x20U, + 0x47U, 0x0DU, 0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x02U, + 0x7EU, 0x42U, 0x1EU, 0x20U, 0x01U, 0x41U, 0x20U, 0x41U, 0x04U, + 0x10U, 0x01U, 0x42U, 0x50U, 0x52U, 0x0DU, 0x00U, 0x1AU, 0x41U, + 0x92U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x21U, 0x10U, 0x00U, + 0x1AU, 0x41U, 0x00U, 0x21U, 0x00U, 0x02U, 0x40U, 0x03U, 0x40U, + 0x41U, 0x92U, 0x80U, 0x80U, 0x80U, 0x78U, 0x41U, 0x21U, 0x10U, + 0x00U, 0x1AU, 0x20U, 0x00U, 0x20U, 0x01U, 0x6AU, 0x2DU, 0x00U, + 0x00U, 0x41U, 0xA5U, 0x01U, 0x47U, 0x0DU, 0x01U, 0x01U, 0x01U, + 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, 0x01U, + 0x20U, 0x00U, 0x41U, 0x01U, 0x6AU, 0x22U, 0x00U, 0x41U, 0x20U, + 0x47U, 0x0DU, 0x00U, 0x0BU, 0x42U, 0x00U, 0x0CU, 0x01U, 0x0BU, + 0x42U, 0x1FU, 0x0BU, 0x10U, 0x02U, 0x21U, 0x02U, 0x20U, 0x01U, + 0x41U, 0x20U, 0x6AU, 0x24U, 0x00U, 0x20U, 0x02U, 0x0BU, + }}, + + /* ==== WASM: 11 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); diff --git a/src/xrpld/app/consensus/ConsensusEntropyIntent.md b/src/xrpld/app/consensus/ConsensusEntropyIntent.md index d7cd9c6da..c57993fa0 100644 --- a/src/xrpld/app/consensus/ConsensusEntropyIntent.md +++ b/src/xrpld/app/consensus/ConsensusEntropyIntent.md @@ -131,8 +131,8 @@ Hooks state `min_tier` explicitly on every draw (no hidden network default). Entropy is served iff it is **fresh** (current or previous ledger) **and** meets that class floor; otherwise the call **fails closed** (`TOO_LITTLE_ENTROPY`). `entropy_status()` separately exposes the stored tier, -contributor count, denominator, and ledger age so hooks can impose proportional -or absolute policies without freezing those policies into the host ABI. +contributor count, and denominator so hooks can impose proportional or absolute +policies without freezing those policies into the host ABI. Fallback is tier 1 with count/denominator `0/0`, so callers must classify tier before arithmetic. Draws are also domain-separated by the hook execution role that can share a transaction and hook hash: strong vs weak, callback vs direct diff --git a/src/xrpld/app/consensus/ConsensusExtensionsDesign.md b/src/xrpld/app/consensus/ConsensusExtensionsDesign.md index f0014432b..8a56d5746 100644 --- a/src/xrpld/app/consensus/ConsensusExtensionsDesign.md +++ b/src/xrpld/app/consensus/ConsensusExtensionsDesign.md @@ -383,9 +383,10 @@ fallback-grade randomness must do so explicitly at the call site. Valid `INVALID_ARGUMENT`, while valid-but-unmet requirements return `TOO_LITTLE_ENTROPY`. -`entropy_status(write_ptr, write_len)` writes the fixed five-byte big-endian -tuple `(tier:u8, count:u16, denominator:u16)` and returns the metadata's ledger -age. This lets Hook code implement policies such as one-absent tolerance, +`entropy_status()` returns a packed non-negative scalar with tier in bits +32..39, contributor count in bits 16..31, and denominator in bits 0..15. +Negative values remain Hook API errors. This lets Hook code implement policies +such as one-absent tolerance, proportional participation, or an absolute floor without widening the frozen draw API. It exposes no digest. Callers must classify tier before count or denominator arithmetic because fallback deliberately reports tier 1 and @@ -393,9 +394,9 @@ denominator arithmetic because fallback deliberately reports tier 1 and Open-ledger hook execution is provisional. During speculative open-ledger execution, `dice()`/`random()` and `entropy_status()` can only use the previous -ledger's finalized entropy (status age 1); final buildLCL execution sees the -current ledger's entropy pseudo-tx after it updates the SLE (status age 0). -Hooks that need final entropy must treat open-ledger RNG results as previews. +ledger's finalized entropy; final buildLCL execution sees the current ledger's +entropy pseudo-tx after it updates the SLE. Hooks that need final entropy must +treat open-ledger RNG results as previews. The fallback digest derives from the agreed pre-injection tx set hash to avoid circularity, and entropy pseudo-tx deduplication is value-based: if the agreed diff --git a/src/xrpld/app/hook/detail/applyHook.cpp b/src/xrpld/app/hook/detail/applyHook.cpp index 2860dec16..d5310a114 100644 --- a/src/xrpld/app/hook/detail/applyHook.cpp +++ b/src/xrpld/app/hook/detail/applyHook.cpp @@ -4266,38 +4266,17 @@ DEFINE_HOOK_FUNCTION( HOOK_TEARDOWN(); } -DEFINE_HOOK_FUNCTION( - int64_t, - entropy_status, - uint32_t write_ptr, - uint32_t write_len) +DEFINE_HOOK_FUNCTION(int64_t, entropy_status) { HOOK_SETUP(); - constexpr std::size_t statusSize = 5; - if (write_len < statusSize) - return TOO_SMALL; - - if (NOT_IN_BOUNDS(write_ptr, statusSize, memory_length)) - return OUT_OF_BOUNDS; - auto snapshot = readEntropySnapshot(view); if (std::holds_alternative(snapshot)) return std::get(snapshot); auto const& entropy = std::get(snapshot); - std::array const status{ - entropy.tier, - static_cast(entropy.count >> 8), - static_cast(entropy.count), - static_cast(entropy.denominator >> 8), - static_cast(entropy.denominator)}; - - if (!WasmEdge_ResultOK(WasmEdge_MemoryInstanceSetData( - memoryCtx, status.data(), write_ptr, status.size()))) - return INTERNAL_ERROR; - - return entropy.age; + return (std::uint64_t{entropy.tier} << 32U) | + (std::uint64_t{entropy.count} << 16U) | entropy.denominator; HOOK_TEARDOWN(); }