From cc37a969ff32c5ee50c63bfb300bb81b469ef1c5 Mon Sep 17 00:00:00 2001 From: tequ Date: Wed, 22 Oct 2025 16:54:38 +0900 Subject: [PATCH 01/33] Refactor: Whitelisted Hook APIs --- src/ripple/app/hook/Enum.h | 179 ++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 80 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 19209389e5..a61553a76b 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -350,90 +350,109 @@ const uint8_t max_emit = 255; const uint8_t max_params = 16; const double fee_base_multiplier = 1.1f; +#define I32 0x7FU +#define I64 0x7EU + +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, ...) \ + { \ + FUNCTION_NAME, \ + { \ + RETURN_TYPE, __VA_ARGS__ \ + } \ + } + +using APIWhitelist = std::map>; + // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes -static const std::map> import_whitelist{ - {"_g", {0x7FU, 0x7FU, 0x7FU}}, - {"accept", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"rollback", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"util_raddr", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_accid", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_verify", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_sha512h", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_keylet", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_validate", {0x7EU, 0x7FU, 0x7FU}}, - {"sto_subfield", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_subarray", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_emplace", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_erase", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"etxn_burden", {0x7EU}}, - {"etxn_details", {0x7EU, 0x7FU, 0x7FU}}, - {"etxn_fee_base", {0x7EU, 0x7FU, 0x7FU}}, - {"etxn_reserve", {0x7EU, 0x7FU}}, - {"etxn_generation", {0x7EU}}, - {"etxn_nonce", {0x7EU, 0x7FU, 0x7FU}}, - {"emit", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"float_set", {0x7EU, 0x7FU, 0x7EU}}, - {"float_multiply", {0x7EU, 0x7EU, 0x7EU}}, - {"float_mulratio", {0x7EU, 0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"float_negate", {0x7EU, 0x7EU}}, - {"float_compare", {0x7EU, 0x7EU, 0x7EU, 0x7FU}}, - {"float_sum", {0x7EU, 0x7EU, 0x7EU}}, - {"float_sto", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7EU, 0x7FU}}, - {"float_sto_set", {0x7EU, 0x7FU, 0x7FU}}, - {"float_invert", {0x7EU, 0x7EU}}, - {"float_divide", {0x7EU, 0x7EU, 0x7EU}}, - {"float_one", {0x7EU}}, - {"float_mantissa", {0x7EU, 0x7EU}}, - {"float_sign", {0x7EU, 0x7EU}}, - {"float_int", {0x7EU, 0x7EU, 0x7FU, 0x7FU}}, - {"float_log", {0x7EU, 0x7EU}}, - {"float_root", {0x7EU, 0x7EU, 0x7FU}}, - {"fee_base", {0x7EU}}, - {"ledger_seq", {0x7EU}}, - {"ledger_last_time", {0x7EU}}, - {"ledger_last_hash", {0x7EU, 0x7FU, 0x7FU}}, - {"ledger_nonce", {0x7EU, 0x7FU, 0x7FU}}, - {"ledger_keylet", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_account", {0x7EU, 0x7FU, 0x7FU}}, - {"hook_hash", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_param_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_param", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_again", {0x7EU}}, - {"hook_skip", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_pos", {0x7EU}}, - {"slot", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_clear", {0x7EU, 0x7FU}}, - {"slot_count", {0x7EU, 0x7FU}}, - {"slot_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_size", {0x7EU, 0x7FU}}, - {"slot_subarray", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_subfield", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_type", {0x7EU, 0x7FU, 0x7FU}}, - {"slot_float", {0x7EU, 0x7FU}}, - {"state_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state_foreign_set", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state_foreign", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"trace", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"trace_num", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"trace_float", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"otxn_burden", {0x7EU}}, - {"otxn_field", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"otxn_generation", {0x7EU}}, - {"otxn_id", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"otxn_type", {0x7EU}}, - {"otxn_slot", {0x7EU, 0x7FU}}, - {"otxn_param", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"meta_slot", {0x7EU, 0x7FU}}}; +static const APIWhitelist import_whitelist{ + // clang-format off + HOOK_API_DEFINITION(I32, "_g", I32, I32), + HOOK_API_DEFINITION(I64, "accept", I32, I32, I64), + HOOK_API_DEFINITION(I64, "rollback", I32, I32, I64), + HOOK_API_DEFINITION(I64, "util_raddr", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_accid", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_verify", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_sha512h", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_keylet", I32, I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_validate", I32, I32), + HOOK_API_DEFINITION(I64, "sto_subfield", I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_subarray", I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_emplace", I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_erase", I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "etxn_burden"), + HOOK_API_DEFINITION(I64, "etxn_details", I32, I32), + HOOK_API_DEFINITION(I64, "etxn_fee_base", I32, I32), + HOOK_API_DEFINITION(I64, "etxn_reserve", I32), + HOOK_API_DEFINITION(I64, "etxn_generation"), + HOOK_API_DEFINITION(I64, "etxn_nonce", I32, I32), + HOOK_API_DEFINITION(I64, "emit", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "float_set", I32, I64), + HOOK_API_DEFINITION(I64, "float_multiply", I64, I64), + HOOK_API_DEFINITION(I64, "float_mulratio", I64, I32, I32, I32), + HOOK_API_DEFINITION(I64, "float_negate", I64), + HOOK_API_DEFINITION(I64, "float_compare", I64, I64, I32), + HOOK_API_DEFINITION(I64, "float_sum", I64, I64), + HOOK_API_DEFINITION(I64, "float_sto", I32, I32, I32, I32, I32, I32, I64, I32), + HOOK_API_DEFINITION(I64, "float_sto_set", I32, I32), + HOOK_API_DEFINITION(I64, "float_invert", I64), + HOOK_API_DEFINITION(I64, "float_divide", I64, I64), + HOOK_API_DEFINITION(I64, "float_one"), + HOOK_API_DEFINITION(I64, "float_mantissa", I64), + HOOK_API_DEFINITION(I64, "float_sign", I64), + HOOK_API_DEFINITION(I64, "float_int", I64, I32, I32), + HOOK_API_DEFINITION(I64, "float_log", I64), + HOOK_API_DEFINITION(I64, "float_root", I64, I32), + HOOK_API_DEFINITION(I64, "fee_base"), + HOOK_API_DEFINITION(I64, "ledger_seq"), + HOOK_API_DEFINITION(I64, "ledger_last_time"), + HOOK_API_DEFINITION(I64, "ledger_last_hash", I32, I32), + HOOK_API_DEFINITION(I64, "ledger_nonce", I32, I32), + HOOK_API_DEFINITION(I64, "ledger_keylet", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_account", I32, I32), + HOOK_API_DEFINITION(I64, "hook_hash", I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_param_set", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_param", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_again"), + HOOK_API_DEFINITION(I64, "hook_skip", I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_pos"), + HOOK_API_DEFINITION(I64, "slot", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_clear", I32), + HOOK_API_DEFINITION(I64, "slot_count", I32), + HOOK_API_DEFINITION(I64, "slot_set", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_size", I32), + HOOK_API_DEFINITION(I64, "slot_subarray", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_subfield", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_type", I32, I32), + HOOK_API_DEFINITION(I64, "slot_float", I32), + HOOK_API_DEFINITION(I64, "state_set", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state_foreign_set", I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state_foreign", I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "trace", I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "trace_num", I32, I32, I64), + HOOK_API_DEFINITION(I64, "trace_float", I32, I32, I64), + HOOK_API_DEFINITION(I64, "otxn_burden"), + HOOK_API_DEFINITION(I64, "otxn_field", I32, I32, I32), + HOOK_API_DEFINITION(I64, "otxn_generation"), + HOOK_API_DEFINITION(I64, "otxn_id", I32, I32, I32), + HOOK_API_DEFINITION(I64, "otxn_type"), + HOOK_API_DEFINITION(I64, "otxn_slot", I32), + HOOK_API_DEFINITION(I64, "otxn_param", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "meta_slot", I32), + // clang-format on +}; // featureHooks1 -static const std::map> import_whitelist_1{ - {"xpop_slot", {0x7EU, 0x7FU, 0x7FU}}}; +static const APIWhitelist import_whitelist_1{ + // clang-format off + HOOK_API_DEFINITION(I64, "xpop_slot", I32, I32) + // clang-format on +}; + +#undef HOOK_API_DEFINITION +#undef I32 +#undef I64 }; // namespace hook_api #endif From 88bb5438588745854a1111a74865bbf63faef45a Mon Sep 17 00:00:00 2001 From: tequ Date: Wed, 22 Oct 2025 16:54:38 +0900 Subject: [PATCH 02/33] Refactor: Whitelisted Hook APIs --- src/ripple/app/hook/Enum.h | 179 ++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 80 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 7f449958d1..3af3d0cc75 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -368,90 +368,109 @@ const uint8_t max_emit = 255; const uint8_t max_params = 16; const double fee_base_multiplier = 1.1f; +#define I32 0x7FU +#define I64 0x7EU + +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, ...) \ + { \ + FUNCTION_NAME, \ + { \ + RETURN_TYPE, __VA_ARGS__ \ + } \ + } + +using APIWhitelist = std::map>; + // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes -static const std::map> import_whitelist{ - {"_g", {0x7FU, 0x7FU, 0x7FU}}, - {"accept", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"rollback", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"util_raddr", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_accid", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_verify", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_sha512h", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"util_keylet", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_validate", {0x7EU, 0x7FU, 0x7FU}}, - {"sto_subfield", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_subarray", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_emplace", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"sto_erase", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"etxn_burden", {0x7EU}}, - {"etxn_details", {0x7EU, 0x7FU, 0x7FU}}, - {"etxn_fee_base", {0x7EU, 0x7FU, 0x7FU}}, - {"etxn_reserve", {0x7EU, 0x7FU}}, - {"etxn_generation", {0x7EU}}, - {"etxn_nonce", {0x7EU, 0x7FU, 0x7FU}}, - {"emit", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"float_set", {0x7EU, 0x7FU, 0x7EU}}, - {"float_multiply", {0x7EU, 0x7EU, 0x7EU}}, - {"float_mulratio", {0x7EU, 0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"float_negate", {0x7EU, 0x7EU}}, - {"float_compare", {0x7EU, 0x7EU, 0x7EU, 0x7FU}}, - {"float_sum", {0x7EU, 0x7EU, 0x7EU}}, - {"float_sto", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7EU, 0x7FU}}, - {"float_sto_set", {0x7EU, 0x7FU, 0x7FU}}, - {"float_invert", {0x7EU, 0x7EU}}, - {"float_divide", {0x7EU, 0x7EU, 0x7EU}}, - {"float_one", {0x7EU}}, - {"float_mantissa", {0x7EU, 0x7EU}}, - {"float_sign", {0x7EU, 0x7EU}}, - {"float_int", {0x7EU, 0x7EU, 0x7FU, 0x7FU}}, - {"float_log", {0x7EU, 0x7EU}}, - {"float_root", {0x7EU, 0x7EU, 0x7FU}}, - {"fee_base", {0x7EU}}, - {"ledger_seq", {0x7EU}}, - {"ledger_last_time", {0x7EU}}, - {"ledger_last_hash", {0x7EU, 0x7FU, 0x7FU}}, - {"ledger_nonce", {0x7EU, 0x7FU, 0x7FU}}, - {"ledger_keylet", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_account", {0x7EU, 0x7FU, 0x7FU}}, - {"hook_hash", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_param_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_param", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_again", {0x7EU}}, - {"hook_skip", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"hook_pos", {0x7EU}}, - {"slot", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_clear", {0x7EU, 0x7FU}}, - {"slot_count", {0x7EU, 0x7FU}}, - {"slot_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_size", {0x7EU, 0x7FU}}, - {"slot_subarray", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_subfield", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"slot_type", {0x7EU, 0x7FU, 0x7FU}}, - {"slot_float", {0x7EU, 0x7FU}}, - {"state_set", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state_foreign_set", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"state_foreign", - {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"trace", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"trace_num", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"trace_float", {0x7EU, 0x7FU, 0x7FU, 0x7EU}}, - {"otxn_burden", {0x7EU}}, - {"otxn_field", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"otxn_generation", {0x7EU}}, - {"otxn_id", {0x7EU, 0x7FU, 0x7FU, 0x7FU}}, - {"otxn_type", {0x7EU}}, - {"otxn_slot", {0x7EU, 0x7FU}}, - {"otxn_param", {0x7EU, 0x7FU, 0x7FU, 0x7FU, 0x7FU}}, - {"meta_slot", {0x7EU, 0x7FU}}}; +static const APIWhitelist import_whitelist{ + // clang-format off + HOOK_API_DEFINITION(I32, "_g", I32, I32), + HOOK_API_DEFINITION(I64, "accept", I32, I32, I64), + HOOK_API_DEFINITION(I64, "rollback", I32, I32, I64), + HOOK_API_DEFINITION(I64, "util_raddr", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_accid", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_verify", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_sha512h", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "util_keylet", I32, I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_validate", I32, I32), + HOOK_API_DEFINITION(I64, "sto_subfield", I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_subarray", I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_emplace", I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "sto_erase", I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "etxn_burden"), + HOOK_API_DEFINITION(I64, "etxn_details", I32, I32), + HOOK_API_DEFINITION(I64, "etxn_fee_base", I32, I32), + HOOK_API_DEFINITION(I64, "etxn_reserve", I32), + HOOK_API_DEFINITION(I64, "etxn_generation"), + HOOK_API_DEFINITION(I64, "etxn_nonce", I32, I32), + HOOK_API_DEFINITION(I64, "emit", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "float_set", I32, I64), + HOOK_API_DEFINITION(I64, "float_multiply", I64, I64), + HOOK_API_DEFINITION(I64, "float_mulratio", I64, I32, I32, I32), + HOOK_API_DEFINITION(I64, "float_negate", I64), + HOOK_API_DEFINITION(I64, "float_compare", I64, I64, I32), + HOOK_API_DEFINITION(I64, "float_sum", I64, I64), + HOOK_API_DEFINITION(I64, "float_sto", I32, I32, I32, I32, I32, I32, I64, I32), + HOOK_API_DEFINITION(I64, "float_sto_set", I32, I32), + HOOK_API_DEFINITION(I64, "float_invert", I64), + HOOK_API_DEFINITION(I64, "float_divide", I64, I64), + HOOK_API_DEFINITION(I64, "float_one"), + HOOK_API_DEFINITION(I64, "float_mantissa", I64), + HOOK_API_DEFINITION(I64, "float_sign", I64), + HOOK_API_DEFINITION(I64, "float_int", I64, I32, I32), + HOOK_API_DEFINITION(I64, "float_log", I64), + HOOK_API_DEFINITION(I64, "float_root", I64, I32), + HOOK_API_DEFINITION(I64, "fee_base"), + HOOK_API_DEFINITION(I64, "ledger_seq"), + HOOK_API_DEFINITION(I64, "ledger_last_time"), + HOOK_API_DEFINITION(I64, "ledger_last_hash", I32, I32), + HOOK_API_DEFINITION(I64, "ledger_nonce", I32, I32), + HOOK_API_DEFINITION(I64, "ledger_keylet", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_account", I32, I32), + HOOK_API_DEFINITION(I64, "hook_hash", I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_param_set", I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_param", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_again"), + HOOK_API_DEFINITION(I64, "hook_skip", I32, I32, I32), + HOOK_API_DEFINITION(I64, "hook_pos"), + HOOK_API_DEFINITION(I64, "slot", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_clear", I32), + HOOK_API_DEFINITION(I64, "slot_count", I32), + HOOK_API_DEFINITION(I64, "slot_set", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_size", I32), + HOOK_API_DEFINITION(I64, "slot_subarray", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_subfield", I32, I32, I32), + HOOK_API_DEFINITION(I64, "slot_type", I32, I32), + HOOK_API_DEFINITION(I64, "slot_float", I32), + HOOK_API_DEFINITION(I64, "state_set", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state_foreign_set", I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "state_foreign", I32, I32, I32, I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "trace", I32, I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "trace_num", I32, I32, I64), + HOOK_API_DEFINITION(I64, "trace_float", I32, I32, I64), + HOOK_API_DEFINITION(I64, "otxn_burden"), + HOOK_API_DEFINITION(I64, "otxn_field", I32, I32, I32), + HOOK_API_DEFINITION(I64, "otxn_generation"), + HOOK_API_DEFINITION(I64, "otxn_id", I32, I32, I32), + HOOK_API_DEFINITION(I64, "otxn_type"), + HOOK_API_DEFINITION(I64, "otxn_slot", I32), + HOOK_API_DEFINITION(I64, "otxn_param", I32, I32, I32, I32), + HOOK_API_DEFINITION(I64, "meta_slot", I32), + // clang-format on +}; // featureHooks1 -static const std::map> import_whitelist_1{ - {"xpop_slot", {0x7EU, 0x7FU, 0x7FU}}}; +static const APIWhitelist import_whitelist_1{ + // clang-format off + HOOK_API_DEFINITION(I64, "xpop_slot", I32, I32) + // clang-format on +}; + +#undef HOOK_API_DEFINITION +#undef I32 +#undef I64 }; // namespace hook_api #endif From 0b1cfb52c5489c147341aae842bc2fc3a221ec35 Mon Sep 17 00:00:00 2001 From: tequ Date: Sun, 26 Oct 2025 17:36:33 +0900 Subject: [PATCH 03/33] Support for execution costs per Hook APIs --- src/ripple/app/hook/Enum.h | 165 ++++++++------- src/ripple/app/hook/Guard.h | 127 ++++++----- src/ripple/app/hook/applyHook.h | 185 ++++++++-------- src/ripple/app/hook/guard_checker.cpp | 2 +- src/ripple/app/hook/impl/applyHook.cpp | 18 ++ src/ripple/app/tx/impl/Change.cpp | 1 + src/ripple/app/tx/impl/SetHook.cpp | 8 +- src/ripple/protocol/Feature.h | 3 +- src/ripple/protocol/impl/Feature.cpp | 1 + src/test/app/SetHook_test.cpp | 69 ++++++ src/test/app/SetHook_wasm.h | 282 +++++++++++++++++-------- 11 files changed, 550 insertions(+), 311 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 3af3d0cc75..17284ebbe3 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -371,101 +371,104 @@ const double fee_base_multiplier = 1.1f; #define I32 0x7FU #define I64 0x7EU -#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, ...) \ - { \ - FUNCTION_NAME, \ - { \ - RETURN_TYPE, __VA_ARGS__ \ - } \ +#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, COST) \ + { \ + FUNCTION_NAME, \ + { \ + {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}, COST \ + } \ } -using APIWhitelist = std::map>; +using APIWhitelist = + std::map, uint32_t>>; // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes static const APIWhitelist import_whitelist{ // clang-format off - HOOK_API_DEFINITION(I32, "_g", I32, I32), - HOOK_API_DEFINITION(I64, "accept", I32, I32, I64), - HOOK_API_DEFINITION(I64, "rollback", I32, I32, I64), - HOOK_API_DEFINITION(I64, "util_raddr", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_accid", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_verify", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_sha512h", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_keylet", I32, I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_validate", I32, I32), - HOOK_API_DEFINITION(I64, "sto_subfield", I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_subarray", I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_emplace", I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_erase", I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "etxn_burden"), - HOOK_API_DEFINITION(I64, "etxn_details", I32, I32), - HOOK_API_DEFINITION(I64, "etxn_fee_base", I32, I32), - HOOK_API_DEFINITION(I64, "etxn_reserve", I32), - HOOK_API_DEFINITION(I64, "etxn_generation"), - HOOK_API_DEFINITION(I64, "etxn_nonce", I32, I32), - HOOK_API_DEFINITION(I64, "emit", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "float_set", I32, I64), - HOOK_API_DEFINITION(I64, "float_multiply", I64, I64), - HOOK_API_DEFINITION(I64, "float_mulratio", I64, I32, I32, I32), - HOOK_API_DEFINITION(I64, "float_negate", I64), - HOOK_API_DEFINITION(I64, "float_compare", I64, I64, I32), - HOOK_API_DEFINITION(I64, "float_sum", I64, I64), - HOOK_API_DEFINITION(I64, "float_sto", I32, I32, I32, I32, I32, I32, I64, I32), - HOOK_API_DEFINITION(I64, "float_sto_set", I32, I32), - HOOK_API_DEFINITION(I64, "float_invert", I64), - HOOK_API_DEFINITION(I64, "float_divide", I64, I64), - HOOK_API_DEFINITION(I64, "float_one"), - HOOK_API_DEFINITION(I64, "float_mantissa", I64), - HOOK_API_DEFINITION(I64, "float_sign", I64), - HOOK_API_DEFINITION(I64, "float_int", I64, I32, I32), - HOOK_API_DEFINITION(I64, "float_log", I64), - HOOK_API_DEFINITION(I64, "float_root", I64, I32), - HOOK_API_DEFINITION(I64, "fee_base"), - HOOK_API_DEFINITION(I64, "ledger_seq"), - HOOK_API_DEFINITION(I64, "ledger_last_time"), - HOOK_API_DEFINITION(I64, "ledger_last_hash", I32, I32), - HOOK_API_DEFINITION(I64, "ledger_nonce", I32, I32), - HOOK_API_DEFINITION(I64, "ledger_keylet", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_account", I32, I32), - HOOK_API_DEFINITION(I64, "hook_hash", I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_param_set", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_param", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_again"), - HOOK_API_DEFINITION(I64, "hook_skip", I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_pos"), - HOOK_API_DEFINITION(I64, "slot", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_clear", I32), - HOOK_API_DEFINITION(I64, "slot_count", I32), - HOOK_API_DEFINITION(I64, "slot_set", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_size", I32), - HOOK_API_DEFINITION(I64, "slot_subarray", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_subfield", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_type", I32, I32), - HOOK_API_DEFINITION(I64, "slot_float", I32), - HOOK_API_DEFINITION(I64, "state_set", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state_foreign_set", I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state_foreign", I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "trace", I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "trace_num", I32, I32, I64), - HOOK_API_DEFINITION(I64, "trace_float", I32, I32, I64), - HOOK_API_DEFINITION(I64, "otxn_burden"), - HOOK_API_DEFINITION(I64, "otxn_field", I32, I32, I32), - HOOK_API_DEFINITION(I64, "otxn_generation"), - HOOK_API_DEFINITION(I64, "otxn_id", I32, I32, I32), - HOOK_API_DEFINITION(I64, "otxn_type"), - HOOK_API_DEFINITION(I64, "otxn_slot", I32), - HOOK_API_DEFINITION(I64, "otxn_param", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "meta_slot", I32), + // TODO: update costs for each API + HOOK_API_DEFINITION(I32, "_g", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "accept", (I32, I32, I64), 100), + HOOK_API_DEFINITION(I64, "rollback", (I32, I32, I64), 100), + HOOK_API_DEFINITION(I64, "util_raddr", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "util_accid", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "util_verify", (I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "util_sha512h", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "util_keylet", (I32, I32, I32, I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "sto_validate", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "sto_subfield", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "sto_subarray", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "sto_emplace", (I32, I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "sto_erase", (I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "etxn_burden", (), 100), + HOOK_API_DEFINITION(I64, "etxn_details", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "etxn_fee_base", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "etxn_reserve", (I32), 100), + HOOK_API_DEFINITION(I64, "etxn_generation", (), 100), + HOOK_API_DEFINITION(I64, "etxn_nonce", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "emit", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "float_set", (I32, I64),0), + HOOK_API_DEFINITION(I64, "float_multiply", (I64, I64), 100), + HOOK_API_DEFINITION(I64, "float_mulratio", (I64, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "float_negate", (I64), 100), + HOOK_API_DEFINITION(I64, "float_compare", (I64, I64, I32), 100), + HOOK_API_DEFINITION(I64, "float_sum", (I64, I64), 100), + HOOK_API_DEFINITION(I64, "float_sto", (I32, I32, I32, I32, I32, I32, I64, I32), 100), + HOOK_API_DEFINITION(I64, "float_sto_set", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "float_invert", (I64), 100), + HOOK_API_DEFINITION(I64, "float_divide", (I64, I64), 100), + HOOK_API_DEFINITION(I64, "float_one", (), 100), + HOOK_API_DEFINITION(I64, "float_mantissa", (I64), 100), + HOOK_API_DEFINITION(I64, "float_sign", (I64), 100), + HOOK_API_DEFINITION(I64, "float_int", (I64, I32, I32), 100), + HOOK_API_DEFINITION(I64, "float_log", (I64), 100), + HOOK_API_DEFINITION(I64, "float_root", (I64, I32), 100), + HOOK_API_DEFINITION(I64, "fee_base", (), 100), + HOOK_API_DEFINITION(I64, "ledger_seq", (), 100), + HOOK_API_DEFINITION(I64, "ledger_last_time", (), 100), + HOOK_API_DEFINITION(I64, "ledger_last_hash", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "ledger_nonce", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "ledger_keylet", (I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_account", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_hash", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_param_set", (I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_param", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_again", (), 100), + HOOK_API_DEFINITION(I64, "hook_skip", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "hook_pos", (), 100), + HOOK_API_DEFINITION(I64, "slot", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "slot_clear", (I32), 100), + HOOK_API_DEFINITION(I64, "slot_count", (I32), 100), + HOOK_API_DEFINITION(I64, "slot_set", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "slot_size", (I32), 100), + HOOK_API_DEFINITION(I64, "slot_subarray", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "slot_subfield", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "slot_type", (I32, I32), 100), + HOOK_API_DEFINITION(I64, "slot_float", (I32), 100), + HOOK_API_DEFINITION(I64, "state_set", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "state_foreign_set", (I32, I32, I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "state", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "state_foreign", (I32, I32, I32, I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "trace", (I32, I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "trace_num", (I32, I32, I64), 100), + HOOK_API_DEFINITION(I64, "trace_float", (I32, I32, I64), 100), + HOOK_API_DEFINITION(I64, "otxn_burden", (), 100), + HOOK_API_DEFINITION(I64, "otxn_field", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "otxn_generation", (), 100), + HOOK_API_DEFINITION(I64, "otxn_id", (I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "otxn_type", (), 100), + HOOK_API_DEFINITION(I64, "otxn_slot", (I32), 100), + HOOK_API_DEFINITION(I64, "otxn_param", (I32, I32, I32, I32), 100), + HOOK_API_DEFINITION(I64, "meta_slot", (I32), 100), // clang-format on }; // featureHooks1 static const APIWhitelist import_whitelist_1{ // clang-format off - HOOK_API_DEFINITION(I64, "xpop_slot", I32, I32) + HOOK_API_DEFINITION(I64, "xpop_slot", (I32, I32), 100), // clang-format on }; diff --git a/src/ripple/app/hook/Guard.h b/src/ripple/app/hook/Guard.h index f395af4481..99c6efdf39 100644 --- a/src/ripple/app/hook/Guard.h +++ b/src/ripple/app/hook/Guard.h @@ -145,6 +145,7 @@ struct WasmBlkInf uint32_t sanity_check; uint32_t iteration_bound; uint32_t instruction_count; + uint32_t execution_cost; WasmBlkInf* parent; std::vector children; uint32_t start_byte; @@ -194,7 +195,7 @@ struct WasmBlkInf level, \ " " \ " ", \ - worst_case_execution, \ + instruction_count, \ blk->start_byte, \ blk->instruction_count, \ blk->iteration_bound, \ @@ -203,20 +204,20 @@ struct WasmBlkInf &(blk->parent)); \ } // compute worst case execution time -inline uint64_t +inline std::pair compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached) { if (level > 16) { *recursion_limit_reached = true; - return 0; + return {0, 0}; } if (blk->sanity_check != 0x1234ABCDU) { printf("!!! sanity check failed\n"); *recursion_limit_reached = true; - return (uint64_t)-1; + return {(uint64_t)-1, (uint64_t)-1}; } WasmBlkInf const* parent = blk->parent; @@ -225,23 +226,28 @@ compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached) { printf("!!! parent sanity check failed\n"); *recursion_limit_reached = true; - return (uint64_t)-1; + return {(uint64_t)-1, (uint64_t)-1}; } - uint64_t worst_case_execution = blk->instruction_count; + uint64_t instruction_count = blk->instruction_count; + uint64_t execution_cost = blk->execution_cost; double multiplier = 1.0; if (blk->children.size() > 0) for (auto const& child : blk->children) - worst_case_execution += + { + auto [child_instruction_count, child_execution_cost] = compute_wce(child, level + 1, recursion_limit_reached); + instruction_count += child_instruction_count; + execution_cost += child_execution_cost; + } if (parent == 0 || parent->iteration_bound == 0) // this condtion should never occur [defensively programmed] { PRINT_WCE(1); - return worst_case_execution; + return {instruction_count, execution_cost}; } // if the block has a parent then the quotient of its guard and its parent's @@ -250,12 +256,12 @@ compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached) multiplier = ((double)(blk->iteration_bound)) / ((double)(parent->iteration_bound)); - worst_case_execution *= multiplier; - if (worst_case_execution < 1.0) - worst_case_execution = 1.0; + instruction_count *= multiplier; + if (instruction_count < 1.0) + instruction_count = 1.0; PRINT_WCE(3); - return worst_case_execution; + return {instruction_count, execution_cost}; }; // checks the WASM binary for the appropriate required _g guard calls and @@ -263,12 +269,15 @@ compute_wce(const WasmBlkInf* blk, int level, bool* recursion_limit_reached) // expr under analysis begins and end_offset is where it ends returns {worst // case instruction count} if valid or {} if invalid may throw overflow_error, // length_error -inline std::optional +inline std::optional< + std::pair> // {instruction count, execution cost} check_guard( std::vector const& wasm, int codesec, int start_offset, int end_offset, + std::map, uint32_t>> + import_type_map, int guard_func_idx, int last_import_idx, GuardLog guardLog, @@ -333,6 +342,7 @@ check_guard( ADVANCE(1); current->instruction_count++; + current->execution_cost++; // unreachable and nop instructions if (instr == 0x00U || // unreachable @@ -512,6 +522,9 @@ check_guard( GUARD_ERROR("Too many guard calls! Limit is 1024"); } + uint32_t cost = import_type_map[callee_idx].second; + current->execution_cost += cost; + continue; } @@ -788,7 +801,8 @@ check_guard( } bool recursion_limit_reached = false; - uint64_t wce = compute_wce(&(*root), 0, &recursion_limit_reached); + auto [instruction_count, execution_cost] = + compute_wce(&(*root), 0, &recursion_limit_reached); if (recursion_limit_reached) { GUARDLOG(hook::log::NESTING_LIMIT) @@ -800,9 +814,9 @@ check_guard( GUARDLOG(hook::log::INSTRUCTION_COUNT) << "GuardCheck " - << "Total worse-case execution count: " << wce << "\n"; + << "Total worse-case execution count: " << instruction_count << "\n"; - if (wce >= 0xFFFFU) + if (instruction_count >= 0xFFFFU) { GUARDLOG(hook::log::INSTRUCTION_EXCESS) << "GuardCheck " @@ -812,7 +826,7 @@ check_guard( << "\n"; return {}; } - return wce; + return std::pair{instruction_count, execution_cost}; } // RH TODO: reprogram this function to use REQUIRE/ADVANCE @@ -826,6 +840,7 @@ validateGuards( std::vector const& wasm, GuardLog guardLog, std::string guardLogAccStr, + bool returnCost, /* RH NOTE: * rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02 * and update 3 is 0x04 ideally at rule version 3 all bits so far are set @@ -875,7 +890,9 @@ validateGuards( std::map func_type_map; std::map< int /* type idx */, - std::map> + std::pair< + std::map, + uint32_t /* cost */>> import_type_map; // now we check for guards... first check if _g is imported @@ -1020,40 +1037,47 @@ validateGuards( int type_idx = parseLeb128(wasm, i, &i); CHECK_SHORT_HOOK(); - if (import_name == "_g") + uint32_t cost = 0; + + auto merged_import_whitelist = hook_api::import_whitelist; + if (rulesVersion > 0) { - guard_import_number = func_upto; + merged_import_whitelist.insert( + hook_api::import_whitelist_1.begin(), + hook_api::import_whitelist_1.end()); } - else if ( - hook_api::import_whitelist.find(import_name) == - hook_api::import_whitelist.end()) + + auto it = merged_import_whitelist.find(import_name); + auto it_end = merged_import_whitelist.end(); + bool found_in_whitelist = (it != it_end); + + if (import_name == "_g") + guard_import_number = func_upto; + + if (found_in_whitelist) + cost = it->second.second; + else { - if (rulesVersion > 0 && - hook_api::import_whitelist_1.find(import_name) != - hook_api::import_whitelist_1.end()) - { - // PASS, this is a version 1 api - } - else - { - GUARDLOG(hook::log::IMPORT_ILLEGAL) - << "Malformed transaction. " - << "Hook attempted to import a function that does " - "not " - << "appear in the hook_api function set: `" - << import_name << "`" - << "\n"; - return {}; - } + GUARDLOG(hook::log::IMPORT_ILLEGAL) + << "Malformed transaction. " + << "Hook attempted to import a function that does " + "not " + << "appear in the hook_api function set: `" + << import_name << "`" + << "\n"; + return {}; } // add to import map if (import_type_map.find(type_idx) == import_type_map.end()) import_type_map[type_idx] = { - {func_upto, std::move(import_name)}}; + {{func_upto, std::move(import_name)}}, cost}; else - import_type_map[type_idx].emplace( + { + import_type_map[type_idx].first.emplace( func_upto, std::move(import_name)); + import_type_map[type_idx].second = cost; + } func_upto++; } @@ -1256,14 +1280,16 @@ validateGuards( if (auto const& usage = import_type_map.find(j); usage != import_type_map.end()) { - for (auto const& [import_idx, api_name] : usage->second) + for (auto const& [import_idx, api_name] : + usage->second.first) { auto const& api_signature = hook_api::import_whitelist.find(api_name) != hook_api::import_whitelist.end() - ? hook_api::import_whitelist.find(api_name)->second + ? hook_api::import_whitelist.find(api_name) + ->second.first : hook_api::import_whitelist_1.find(api_name) - ->second; + ->second.first; if (!first_signature) { @@ -1502,6 +1528,7 @@ validateGuards( j, i, code_end, + import_type_map, guard_import_number, last_import_number, guardLog, @@ -1512,9 +1539,15 @@ validateGuards( return {}; if (hook_func_idx && *hook_func_idx == j) - maxInstrCountHook = *valid; + if (!returnCost) + maxInstrCountHook = valid->first; + else + maxInstrCountHook = valid->second; else if (cbak_func_idx && *cbak_func_idx == j) - maxInstrCountCbak = *valid; + if (!returnCost) + maxInstrCountCbak = valid->first; + else + maxInstrCountCbak = valid->second; else { if (DEBUG_GUARD) diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 2c1f250bbf..be99d4e3d0 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -471,6 +471,11 @@ computeExecutionFee(uint64_t instructionCount); int64_t computeCreationFee(uint64_t byteCount); +constexpr uint32_t MICRO_DROPS_PER_DROP{1'000'000}; + +std::pair +computeHookInstructionCosts(std::pair const&, Rules const&); + struct HookResult { ripple::uint256 const hookSetTxnID; @@ -597,14 +602,14 @@ gatherHookParameters( beast::Journal const& j_); // RH TODO: call destruct for these on rippled shutdown -#define ADD_HOOK_FUNCTION(F, ctx) \ +#define ADD_HOOK_FUNCTION(F, ctx, cost) \ { \ WasmEdge_FunctionInstanceContext* hf = \ WasmEdge_FunctionInstanceCreate( \ hook_api::WasmFunctionType##F, \ hook_api::WasmFunction##F, \ (void*)(&ctx), \ - 0); \ + cost); \ WasmEdge_ModuleInstanceAddFunction( \ importObj, hook_api::WasmFunctionName##F, hf); \ } @@ -792,96 +797,96 @@ class HookExecutor WasmEdge_LogSetDebugLevel(); - ADD_HOOK_FUNCTION(_g, ctx); - ADD_HOOK_FUNCTION(accept, ctx); - ADD_HOOK_FUNCTION(rollback, ctx); - ADD_HOOK_FUNCTION(util_raddr, ctx); - ADD_HOOK_FUNCTION(util_accid, ctx); - ADD_HOOK_FUNCTION(util_verify, ctx); - ADD_HOOK_FUNCTION(util_sha512h, ctx); - ADD_HOOK_FUNCTION(sto_validate, ctx); - ADD_HOOK_FUNCTION(sto_subfield, ctx); - ADD_HOOK_FUNCTION(sto_subarray, ctx); - ADD_HOOK_FUNCTION(sto_emplace, ctx); - ADD_HOOK_FUNCTION(sto_erase, ctx); - ADD_HOOK_FUNCTION(util_keylet, ctx); - - ADD_HOOK_FUNCTION(emit, ctx); - ADD_HOOK_FUNCTION(etxn_burden, ctx); - ADD_HOOK_FUNCTION(etxn_fee_base, ctx); - ADD_HOOK_FUNCTION(etxn_details, ctx); - ADD_HOOK_FUNCTION(etxn_reserve, ctx); - ADD_HOOK_FUNCTION(etxn_generation, ctx); - ADD_HOOK_FUNCTION(etxn_nonce, ctx); - - ADD_HOOK_FUNCTION(float_set, ctx); - ADD_HOOK_FUNCTION(float_multiply, ctx); - ADD_HOOK_FUNCTION(float_mulratio, ctx); - ADD_HOOK_FUNCTION(float_negate, ctx); - ADD_HOOK_FUNCTION(float_compare, ctx); - ADD_HOOK_FUNCTION(float_sum, ctx); - ADD_HOOK_FUNCTION(float_sto, ctx); - ADD_HOOK_FUNCTION(float_sto_set, ctx); - ADD_HOOK_FUNCTION(float_invert, ctx); - - ADD_HOOK_FUNCTION(float_divide, ctx); - ADD_HOOK_FUNCTION(float_one, ctx); - ADD_HOOK_FUNCTION(float_mantissa, ctx); - ADD_HOOK_FUNCTION(float_sign, ctx); - ADD_HOOK_FUNCTION(float_int, ctx); - ADD_HOOK_FUNCTION(float_log, ctx); - ADD_HOOK_FUNCTION(float_root, ctx); - - ADD_HOOK_FUNCTION(otxn_burden, ctx); - ADD_HOOK_FUNCTION(otxn_generation, ctx); - ADD_HOOK_FUNCTION(otxn_field, ctx); - ADD_HOOK_FUNCTION(otxn_id, ctx); - ADD_HOOK_FUNCTION(otxn_type, ctx); - ADD_HOOK_FUNCTION(otxn_slot, ctx); - ADD_HOOK_FUNCTION(otxn_param, ctx); - - ADD_HOOK_FUNCTION(hook_account, ctx); - ADD_HOOK_FUNCTION(hook_hash, ctx); - ADD_HOOK_FUNCTION(hook_again, ctx); - ADD_HOOK_FUNCTION(fee_base, ctx); - ADD_HOOK_FUNCTION(ledger_seq, ctx); - ADD_HOOK_FUNCTION(ledger_last_hash, ctx); - ADD_HOOK_FUNCTION(ledger_last_time, ctx); - ADD_HOOK_FUNCTION(ledger_nonce, ctx); - ADD_HOOK_FUNCTION(ledger_keylet, ctx); - - ADD_HOOK_FUNCTION(hook_param, ctx); - ADD_HOOK_FUNCTION(hook_param_set, ctx); - ADD_HOOK_FUNCTION(hook_skip, ctx); - ADD_HOOK_FUNCTION(hook_pos, ctx); - - ADD_HOOK_FUNCTION(state, ctx); - ADD_HOOK_FUNCTION(state_foreign, ctx); - ADD_HOOK_FUNCTION(state_set, ctx); - ADD_HOOK_FUNCTION(state_foreign_set, ctx); - - ADD_HOOK_FUNCTION(slot, ctx); - ADD_HOOK_FUNCTION(slot_clear, ctx); - ADD_HOOK_FUNCTION(slot_count, ctx); - ADD_HOOK_FUNCTION(slot_set, ctx); - ADD_HOOK_FUNCTION(slot_size, ctx); - ADD_HOOK_FUNCTION(slot_subarray, ctx); - ADD_HOOK_FUNCTION(slot_subfield, ctx); - ADD_HOOK_FUNCTION(slot_type, ctx); - ADD_HOOK_FUNCTION(slot_float, ctx); - - ADD_HOOK_FUNCTION(trace, ctx); - ADD_HOOK_FUNCTION(trace_num, ctx); - ADD_HOOK_FUNCTION(trace_float, ctx); - - ADD_HOOK_FUNCTION(meta_slot, ctx); - ADD_HOOK_FUNCTION(xpop_slot, ctx); + ADD_HOOK_FUNCTION(_g, ctx, 0); + ADD_HOOK_FUNCTION(accept, ctx, 0); + ADD_HOOK_FUNCTION(rollback, ctx, 0); + ADD_HOOK_FUNCTION(util_raddr, ctx, 0); + ADD_HOOK_FUNCTION(util_accid, ctx, 0); + ADD_HOOK_FUNCTION(util_verify, ctx, 0); + ADD_HOOK_FUNCTION(util_sha512h, ctx, 0); + ADD_HOOK_FUNCTION(sto_validate, ctx, 0); + ADD_HOOK_FUNCTION(sto_subfield, ctx, 0); + ADD_HOOK_FUNCTION(sto_subarray, ctx, 0); + ADD_HOOK_FUNCTION(sto_emplace, ctx, 0); + ADD_HOOK_FUNCTION(sto_erase, ctx, 0); + ADD_HOOK_FUNCTION(util_keylet, ctx, 0); + + ADD_HOOK_FUNCTION(emit, ctx, 0); + ADD_HOOK_FUNCTION(etxn_burden, ctx, 0); + ADD_HOOK_FUNCTION(etxn_fee_base, ctx, 0); + ADD_HOOK_FUNCTION(etxn_details, ctx, 0); + ADD_HOOK_FUNCTION(etxn_reserve, ctx, 0); + ADD_HOOK_FUNCTION(etxn_generation, ctx, 0); + ADD_HOOK_FUNCTION(etxn_nonce, ctx, 0); + + ADD_HOOK_FUNCTION(float_set, ctx, 0); + ADD_HOOK_FUNCTION(float_multiply, ctx, 0); + ADD_HOOK_FUNCTION(float_mulratio, ctx, 0); + ADD_HOOK_FUNCTION(float_negate, ctx, 0); + ADD_HOOK_FUNCTION(float_compare, ctx, 0); + ADD_HOOK_FUNCTION(float_sum, ctx, 0); + ADD_HOOK_FUNCTION(float_sto, ctx, 0); + ADD_HOOK_FUNCTION(float_sto_set, ctx, 0); + ADD_HOOK_FUNCTION(float_invert, ctx, 0); + + ADD_HOOK_FUNCTION(float_divide, ctx, 0); + ADD_HOOK_FUNCTION(float_one, ctx, 0); + ADD_HOOK_FUNCTION(float_mantissa, ctx, 0); + ADD_HOOK_FUNCTION(float_sign, ctx, 0); + ADD_HOOK_FUNCTION(float_int, ctx, 0); + ADD_HOOK_FUNCTION(float_log, ctx, 0); + ADD_HOOK_FUNCTION(float_root, ctx, 0); + + ADD_HOOK_FUNCTION(otxn_burden, ctx, 0); + ADD_HOOK_FUNCTION(otxn_generation, ctx, 0); + ADD_HOOK_FUNCTION(otxn_field, ctx, 0); + ADD_HOOK_FUNCTION(otxn_id, ctx, 0); + ADD_HOOK_FUNCTION(otxn_type, ctx, 0); + ADD_HOOK_FUNCTION(otxn_slot, ctx, 0); + ADD_HOOK_FUNCTION(otxn_param, ctx, 0); + + ADD_HOOK_FUNCTION(hook_account, ctx, 0); + ADD_HOOK_FUNCTION(hook_hash, ctx, 0); + ADD_HOOK_FUNCTION(hook_again, ctx, 0); + ADD_HOOK_FUNCTION(fee_base, ctx, 0); + ADD_HOOK_FUNCTION(ledger_seq, ctx, 0); + ADD_HOOK_FUNCTION(ledger_last_hash, ctx, 0); + ADD_HOOK_FUNCTION(ledger_last_time, ctx, 0); + ADD_HOOK_FUNCTION(ledger_nonce, ctx, 0); + ADD_HOOK_FUNCTION(ledger_keylet, ctx, 0); + + ADD_HOOK_FUNCTION(hook_param, ctx, 0); + ADD_HOOK_FUNCTION(hook_param_set, ctx, 0); + ADD_HOOK_FUNCTION(hook_skip, ctx, 0); + ADD_HOOK_FUNCTION(hook_pos, ctx, 0); + + ADD_HOOK_FUNCTION(state, ctx, 0); + ADD_HOOK_FUNCTION(state_foreign, ctx, 0); + ADD_HOOK_FUNCTION(state_set, ctx, 0); + ADD_HOOK_FUNCTION(state_foreign_set, ctx, 0); + + ADD_HOOK_FUNCTION(slot, ctx, 0); + ADD_HOOK_FUNCTION(slot_clear, ctx, 0); + ADD_HOOK_FUNCTION(slot_count, ctx, 0); + ADD_HOOK_FUNCTION(slot_set, ctx, 0); + ADD_HOOK_FUNCTION(slot_size, ctx, 0); + ADD_HOOK_FUNCTION(slot_subarray, ctx, 0); + ADD_HOOK_FUNCTION(slot_subfield, ctx, 0); + ADD_HOOK_FUNCTION(slot_type, ctx, 0); + ADD_HOOK_FUNCTION(slot_float, ctx, 0); + + ADD_HOOK_FUNCTION(trace, ctx, 0); + ADD_HOOK_FUNCTION(trace_num, ctx, 0); + ADD_HOOK_FUNCTION(trace_float, ctx, 0); + + ADD_HOOK_FUNCTION(meta_slot, ctx, 0); + ADD_HOOK_FUNCTION(xpop_slot, ctx, 0); /* - ADD_HOOK_FUNCTION(str_find, ctx); - ADD_HOOK_FUNCTION(str_replace, ctx); - ADD_HOOK_FUNCTION(str_compare, ctx); - ADD_HOOK_FUNCTION(str_concat, ctx); + ADD_HOOK_FUNCTION(str_find, ctx, 0); + ADD_HOOK_FUNCTION(str_replace, ctx, 0); + ADD_HOOK_FUNCTION(str_compare, ctx, 0); + ADD_HOOK_FUNCTION(str_concat, ctx, 0); */ WasmEdge_TableInstanceContext* hostTable = diff --git a/src/ripple/app/hook/guard_checker.cpp b/src/ripple/app/hook/guard_checker.cpp index f20d24617b..a9e4c07b68 100644 --- a/src/ripple/app/hook/guard_checker.cpp +++ b/src/ripple/app/hook/guard_checker.cpp @@ -79,7 +79,7 @@ main(int argc, char** argv) close(fd); - auto result = validateGuards(hook, std::cout, "", 3); + auto result = validateGuards(hook, std::cout, "", false, 3); if (!result) { diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index d07e19be78..1ab1ccbadb 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -920,6 +920,24 @@ hook::computeCreationFee(uint64_t byteCount) return fee; } +std::pair +hook::computeHookInstructionCosts( + std::pair const& instrCounts, + Rules const& rules) +{ + if (!rules.enabled(featureHookFeeV2)) + return instrCounts; + + auto const GAS_PRICE = + 100'000; // TODO: should be voted by validators like reserve + + double const gas_cost = double(GAS_PRICE) / double(MICRO_DROPS_PER_DROP); + + return { + uint64_t(instrCounts.first * gas_cost), + uint64_t(instrCounts.second * gas_cost)}; +} + // many datatypes can be encoded into an int64_t inline int64_t data_as_int64(void const* ptr_raw, uint32_t len) diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 37a436feea..9a32a2ad27 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -605,6 +605,7 @@ Change::activateXahauGenesis() wasmBytes, // wasm to verify loggerStream, "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + false, (ctx_.view().rules().enabled(featureHooksUpdate1) ? 1 : 0) + (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index 9ca8295571..9f7f35345a 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -490,6 +490,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) hook, // wasm to verify logger, hsacc, + ctx.rules.enabled(featureHookFeeV2), (ctx.rules.enabled(featureHooksUpdate1) ? 1 : 0) + (ctx.rules.enabled(fix20250131) ? 2 : 0)); @@ -1637,9 +1638,12 @@ SetHook::setHook() assert(false); // should never happen } - // otherwise assign instruction counts - std::tie(maxInstrCountHook, maxInstrCountCbak) = + auto const instrCounts = std::get>(valid); + + std::tie(maxInstrCountHook, maxInstrCountCbak) = + hook::computeHookInstructionCosts( + instrCounts, ctx.rules); } catch (std::exception& e) { diff --git a/src/ripple/protocol/Feature.h b/src/ripple/protocol/Feature.h index ed6b4e73f8..14eeda0eac 100644 --- a/src/ripple/protocol/Feature.h +++ b/src/ripple/protocol/Feature.h @@ -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 = 88; +static constexpr std::size_t numFeatures = 89; /** Amendments that this server supports and the default voting behavior. Whether they are enabled depends on the Rules defined in the validated @@ -376,6 +376,7 @@ extern uint256 const featureIOUIssuerWeakTSH; extern uint256 const featureCron; extern uint256 const fixInvalidTxFlags; extern uint256 const featureExtendedHookState; +extern uint256 const featureHookFeeV2; } // namespace ripple diff --git a/src/ripple/protocol/impl/Feature.cpp b/src/ripple/protocol/impl/Feature.cpp index 64d05f1342..bc0642f13a 100644 --- a/src/ripple/protocol/impl/Feature.cpp +++ b/src/ripple/protocol/impl/Feature.cpp @@ -482,6 +482,7 @@ REGISTER_FEATURE(IOUIssuerWeakTSH, Supported::yes, VoteBehavior::De REGISTER_FEATURE(Cron, Supported::yes, VoteBehavior::DefaultNo); REGISTER_FIX (fixInvalidTxFlags, Supported::yes, VoteBehavior::DefaultYes); REGISTER_FEATURE(ExtendedHookState, Supported::yes, VoteBehavior::DefaultNo); +REGISTER_FEATURE(HookFeeV2, Supported::yes, VoteBehavior::DefaultNo); // The following amendments are obsolete, but must remain supported // because they could potentially get enabled. diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 8fef47656f..7c38414c1e 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -2570,6 +2570,74 @@ class SetHook0_test : public beast::unit_test::suite } } + void + testGuardCost(FeatureBitset features) + { + testcase("Test guard cost"); + using namespace jtx; + + auto const alice = Account{"alice"}; + auto const bob = Account{"bob"}; + + for (auto withCost : {true, false}) + { + Env env{ + *this, + withCost ? features | featureHookFeeV2 + : features - featureHookFeeV2}; + + env.fund(XRP(10000), alice); + env.fund(XRP(10000), bob); + TestHook hook_wasm = wasm[R"[test.hook]( + #include + extern int32_t _g (uint32_t id, uint32_t maxiter); + #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + extern int64_t hook_account (uint32_t, uint32_t); + int64_t hook(uint32_t reserved) + { + uint8_t acc[20]; + for (int i = 0; i < 10; ++i) + { + _g(1, 11); + for (int j = 0; j < 2; ++j) + { + _g(2, 30); + for (int k = 0; k < 5; ++k) + { + _g(3, 120); + hook_account(acc, 20); + } + for (int k = 0; k < 5; ++k) + { + _g(4, 120); + hook_account(acc, 20); + } + } + } + return accept(0,0,2); + } + )[test.hook]"]; + + HASH_WASM(hook); + + env(ripple::test::jtx::hook( + alice, {{hso(hook_wasm, overrideFlag)}}, 0), + HSFEE); + env.close(); + + auto const hookDef = env.le(hook_keylet); + + BEAST_EXPECT(hookDef); + auto const hookFee = hookDef->getFieldAmount(sfFee); + + if (withCost) + BEAST_EXPECT(hookFee == XRPAmount{449}); + else + BEAST_EXPECT(hookFee == XRPAmount{1944}); + } + } + void test_emit(FeatureBitset features) { @@ -13180,6 +13248,7 @@ class SetHook0_test : public beast::unit_test::suite test_rollback(features); testGuards(features); + testGuardCost(features); test_emit(features); // // test_etxn_burden(features); // tested above diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index 626e4a849a..68ef3a60fe 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -543,6 +543,110 @@ std::map> wasm = { }}, /* ==== WASM: 6 ==== */ + {R"[test.hook]( + #include + extern int32_t _g (uint32_t id, uint32_t maxiter); + #define GUARD(maxiter) _g((1ULL << 31U) + __LINE__, (maxiter)+1) + extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); + extern int64_t hook_account (uint32_t, uint32_t); + int64_t hook(uint32_t reserved) + { + uint8_t acc[20]; + for (int i = 0; i < 10; ++i) + { + _g(1, 11); + for (int j = 0; j < 2; ++j) + { + _g(2, 30); + for (int k = 0; k < 5; ++k) + { + _g(3, 120); + hook_account(acc, 20); + } + for (int k = 0; k < 5; ++k) + { + _g(4, 120); + hook_account(acc, 20); + } + } + } + return accept(0,0,2); + } + )[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, 0x2AU, 0x03U, 0x03U, 0x65U, + 0x6EU, 0x76U, 0x02U, 0x5FU, 0x67U, 0x00U, 0x00U, 0x03U, 0x65U, 0x6EU, + 0x76U, 0x0CU, 0x68U, 0x6FU, 0x6FU, 0x6BU, 0x5FU, 0x61U, 0x63U, 0x63U, + 0x6FU, 0x75U, 0x6EU, 0x74U, 0x00U, 0x01U, 0x03U, 0x65U, 0x6EU, 0x76U, + 0x06U, 0x61U, 0x63U, 0x63U, 0x65U, 0x70U, 0x74U, 0x00U, 0x02U, 0x03U, + 0x02U, 0x01U, 0x03U, 0x05U, 0x03U, 0x01U, 0x00U, 0x02U, 0x06U, 0x21U, + 0x05U, 0x7FU, 0x01U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, + 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, + 0x7FU, 0x00U, 0x41U, 0x80U, 0x88U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, + 0x80U, 0x08U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, + 0x6BU, 0x00U, 0x03U, 0x0AU, 0xB3U, 0x84U, 0x00U, 0x01U, 0xAFU, 0x84U, + 0x00U, 0x02U, 0x02U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x41U, 0x20U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x41U, 0x0AU, 0x21U, 0x02U, 0x03U, 0x40U, 0x41U, + 0x01U, 0x41U, 0x0BU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x41U, 0x02U, 0x41U, 0x1EU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, + 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, + 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, + 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, + 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, + 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, + 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, + 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, + 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, + 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x41U, 0x02U, 0x41U, 0x1EU, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, + 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, + 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, + 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x03U, 0x41U, 0xF8U, 0x00U, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, + 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, + 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, + 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, + 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, + 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, 0x04U, 0x41U, 0xF8U, + 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, + 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x41U, + 0x04U, 0x41U, 0xF8U, 0x00U, 0x10U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x1AU, 0x20U, 0x01U, 0x41U, 0x14U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x20U, 0x02U, 0x41U, 0x7FU, 0x6AU, 0x22U, 0x02U, 0x0DU, + 0x00U, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x02U, 0x10U, 0x82U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x21U, 0x03U, 0x20U, 0x01U, 0x41U, 0x20U, + 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x03U, 0x0BU, + }}, + + /* ==== WASM: 7 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -1159,7 +1263,7 @@ std::map> wasm = { 0x78U, 0x29U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 7 ==== */ + /* ==== WASM: 8 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1264,7 +1368,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 8 ==== */ + /* ==== WASM: 9 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1361,7 +1465,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 9 ==== */ + /* ==== WASM: 10 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1484,7 +1588,7 @@ std::map> wasm = { 0x4EU, 0x59U, 0x5FU, 0x4EU, 0x4FU, 0x4EU, 0x43U, 0x45U, 0x53U, 0x00U, }}, - /* ==== WASM: 10 ==== */ + /* ==== WASM: 11 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1564,7 +1668,7 @@ std::map> wasm = { 0x54U, 0x00U, }}, - /* ==== WASM: 11 ==== */ + /* ==== WASM: 12 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1609,7 +1713,7 @@ std::map> wasm = { 0x30U, 0x00U, }}, - /* ==== WASM: 12 ==== */ + /* ==== WASM: 13 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -1928,7 +2032,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 13 ==== */ + /* ==== WASM: 14 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -2714,7 +2818,7 @@ std::map> wasm = { 0x37U, 0x36U, 0x33U, 0x4CU, 0x4CU, 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 14 ==== */ + /* ==== WASM: 15 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3104,7 +3208,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 15 ==== */ + /* ==== WASM: 16 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3285,7 +3389,7 @@ std::map> wasm = { 0x38U, 0x4CU, 0x4CU, 0x29U, 0x00U, }}, - /* ==== WASM: 16 ==== */ + /* ==== WASM: 17 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3474,7 +3578,7 @@ std::map> wasm = { 0x29U, 0x00U, }}, - /* ==== WASM: 17 ==== */ + /* ==== WASM: 18 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -3713,7 +3817,7 @@ std::map> wasm = { 0x00U, 0x42U, 0x00U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 18 ==== */ + /* ==== WASM: 19 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -4415,7 +4519,7 @@ std::map> wasm = { 0x38U, 0x35U, 0x35U, 0x32U, 0x55U, 0x29U, 0x00U, }}, - /* ==== WASM: 19 ==== */ + /* ==== WASM: 20 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5760,7 +5864,7 @@ std::map> wasm = { 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 20 ==== */ + /* ==== WASM: 21 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5862,7 +5966,7 @@ std::map> wasm = { 0x84U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 21 ==== */ + /* ==== WASM: 22 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -5905,7 +6009,7 @@ std::map> wasm = { 0x00U, 0x0BU, }}, - /* ==== WASM: 22 ==== */ + /* ==== WASM: 23 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6053,7 +6157,7 @@ std::map> wasm = { 0x34U, 0x34U, 0x4CU, 0x4CU, 0x2CU, 0x20U, 0x33U, 0x29U, 0x00U, }}, - /* ==== WASM: 23 ==== */ + /* ==== WASM: 24 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6381,7 +6485,7 @@ std::map> wasm = { 0x38U, 0x34U, 0x39U, 0x30U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 24 ==== */ + /* ==== WASM: 25 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -6586,7 +6690,7 @@ std::map> wasm = { 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 25 ==== */ + /* ==== WASM: 26 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -7270,7 +7374,7 @@ std::map> wasm = { 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 26 ==== */ + /* ==== WASM: 27 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -7565,7 +7669,7 @@ std::map> wasm = { 0x32U, 0x34U, 0x31U, 0x36U, 0x55U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 27 ==== */ + /* ==== WASM: 28 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8278,7 +8382,7 @@ std::map> wasm = { 0x31U, 0x33U, 0x33U, 0x38U, 0x20U, 0x29U, 0x00U, }}, - /* ==== WASM: 28 ==== */ + /* ==== WASM: 29 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8363,7 +8467,7 @@ std::map> wasm = { 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U, 0x30U, 0x00U, }}, - /* ==== WASM: 29 ==== */ + /* ==== WASM: 30 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8425,7 +8529,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x0BU, }}, - /* ==== WASM: 30 ==== */ + /* ==== WASM: 31 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8502,7 +8606,7 @@ std::map> wasm = { 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 31 ==== */ + /* ==== WASM: 32 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8579,7 +8683,7 @@ std::map> wasm = { 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 32 ==== */ + /* ==== WASM: 33 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8836,7 +8940,7 @@ std::map> wasm = { 0x00U, 0x00U, }}, - /* ==== WASM: 33 ==== */ + /* ==== WASM: 34 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -8994,7 +9098,7 @@ std::map> wasm = { 0x04U, 0x00U, 0x00U, }}, - /* ==== WASM: 34 ==== */ + /* ==== WASM: 35 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9347,7 +9451,7 @@ std::map> wasm = { 0x00U, 0x2AU, 0x04U, 0x00U, 0x00U, 0x31U, 0x04U, 0x00U, 0x00U, }}, - /* ==== WASM: 35 ==== */ + /* ==== WASM: 36 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9380,7 +9484,7 @@ std::map> wasm = { 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 36 ==== */ + /* ==== WASM: 37 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9607,7 +9711,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 37 ==== */ + /* ==== WASM: 38 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9638,7 +9742,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 38 ==== */ + /* ==== WASM: 39 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -9949,7 +10053,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 39 ==== */ + /* ==== WASM: 40 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10026,7 +10130,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 40 ==== */ + /* ==== WASM: 41 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10060,7 +10164,7 @@ std::map> wasm = { 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x0BU, }}, - /* ==== WASM: 41 ==== */ + /* ==== WASM: 42 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10147,7 +10251,7 @@ std::map> wasm = { 0x32U, 0x00U, }}, - /* ==== WASM: 42 ==== */ + /* ==== WASM: 43 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10181,7 +10285,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 43 ==== */ + /* ==== WASM: 44 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10321,7 +10425,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x4DU, 0x45U, 0x54U, 0x00U, }}, - /* ==== WASM: 44 ==== */ + /* ==== WASM: 45 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10511,7 +10615,7 @@ std::map> wasm = { 0x31U, 0x34U, 0x00U, }}, - /* ==== WASM: 45 ==== */ + /* ==== WASM: 46 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10665,7 +10769,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 46 ==== */ + /* ==== WASM: 47 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10826,7 +10930,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 47 ==== */ + /* ==== WASM: 48 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -10983,7 +11087,7 @@ std::map> wasm = { 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 48 ==== */ + /* ==== WASM: 49 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11068,7 +11172,7 @@ std::map> wasm = { 0x74U, 0x79U, 0x70U, 0x65U, 0x28U, 0x29U, 0x00U, }}, - /* ==== WASM: 49 ==== */ + /* ==== WASM: 50 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11325,7 +11429,7 @@ std::map> wasm = { 0x00U, 0x00U, }}, - /* ==== WASM: 50 ==== */ + /* ==== WASM: 51 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11563,7 +11667,7 @@ std::map> wasm = { 0x3EU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 51 ==== */ + /* ==== WASM: 52 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11659,7 +11763,7 @@ std::map> wasm = { 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 52 ==== */ + /* ==== WASM: 53 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11769,7 +11873,7 @@ std::map> wasm = { 0x20U, 0x31U, 0x00U, }}, - /* ==== WASM: 53 ==== */ + /* ==== WASM: 54 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -11899,7 +12003,7 @@ std::map> wasm = { 0x30U, 0x30U, 0x30U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 54 ==== */ + /* ==== WASM: 55 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12173,7 +12277,7 @@ std::map> wasm = { 0x30U, 0x00U, }}, - /* ==== WASM: 55 ==== */ + /* ==== WASM: 56 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12310,7 +12414,7 @@ std::map> wasm = { 0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U, }}, - /* ==== WASM: 56 ==== */ + /* ==== WASM: 57 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12604,7 +12708,7 @@ std::map> wasm = { 0x5FU, 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 57 ==== */ + /* ==== WASM: 58 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -12838,7 +12942,7 @@ std::map> wasm = { 0x5FU, 0x53U, 0x4CU, 0x4FU, 0x54U, 0x53U, 0x00U, }}, - /* ==== WASM: 58 ==== */ + /* ==== WASM: 59 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13134,7 +13238,7 @@ std::map> wasm = { 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 59 ==== */ + /* ==== WASM: 60 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13338,7 +13442,7 @@ std::map> wasm = { 0x6EU, 0x74U, 0x32U, 0x22U, 0x20U, 0x2BU, 0x20U, 0x69U, 0x29U, 0x00U, }}, - /* ==== WASM: 60 ==== */ + /* ==== WASM: 61 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13455,7 +13559,7 @@ std::map> wasm = { 0x69U, 0x29U, 0x00U, }}, - /* ==== WASM: 61 ==== */ + /* ==== WASM: 62 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13564,7 +13668,7 @@ std::map> wasm = { 0x6EU, 0x74U, 0x65U, 0x6EU, 0x74U, 0x32U, 0x22U, 0x29U, 0x00U, }}, - /* ==== WASM: 62 ==== */ + /* ==== WASM: 63 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -13837,7 +13941,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 63 ==== */ + /* ==== WASM: 64 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -14056,7 +14160,7 @@ std::map> wasm = { 0x30U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 64 ==== */ + /* ==== WASM: 65 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14168,7 +14272,7 @@ std::map> wasm = { 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 65 ==== */ + /* ==== WASM: 66 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -14304,7 +14408,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 66 ==== */ + /* ==== WASM: 67 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14440,7 +14544,7 @@ std::map> wasm = { 0x49U, 0x47U, 0x00U, }}, - /* ==== WASM: 67 ==== */ + /* ==== WASM: 68 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14579,7 +14683,7 @@ std::map> wasm = { 0x66U, 0x28U, 0x64U, 0x61U, 0x74U, 0x61U, 0x32U, 0x29U, 0x00U, }}, - /* ==== WASM: 68 ==== */ + /* ==== WASM: 69 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14691,7 +14795,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 69 ==== */ + /* ==== WASM: 70 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14785,7 +14889,7 @@ std::map> wasm = { 0x61U, 0x64U, 0x5BU, 0x69U, 0x5DU, 0x00U, }}, - /* ==== WASM: 70 ==== */ + /* ==== WASM: 71 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -14918,7 +15022,7 @@ std::map> wasm = { 0x64U, 0x5BU, 0x69U, 0x5DU, 0x00U, }}, - /* ==== WASM: 71 ==== */ + /* ==== WASM: 72 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15006,7 +15110,7 @@ std::map> wasm = { 0x61U, 0x74U, 0x61U, 0x29U, 0x00U, }}, - /* ==== WASM: 72 ==== */ + /* ==== WASM: 73 ==== */ {R"[test.hook]( #include #define sfInvoiceID ((5U << 16U) + 17U) @@ -15117,7 +15221,7 @@ std::map> wasm = { 0x20U, 0x33U, 0x32U, 0x00U, }}, - /* ==== WASM: 73 ==== */ + /* ==== WASM: 74 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15328,7 +15432,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 74 ==== */ + /* ==== WASM: 75 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -15436,7 +15540,7 @@ std::map> wasm = { 0x20U, 0x22U, 0x32U, 0x22U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x00U, }}, - /* ==== WASM: 75 ==== */ + /* ==== WASM: 76 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16048,7 +16152,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 76 ==== */ + /* ==== WASM: 77 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16398,7 +16502,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 77 ==== */ + /* ==== WASM: 78 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16534,7 +16638,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 78 ==== */ + /* ==== WASM: 79 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16707,7 +16811,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 79 ==== */ + /* ==== WASM: 80 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16855,7 +16959,7 @@ std::map> wasm = { 0x30U, 0x00U, 0x22U, 0x00U, 0x00U, 0x00U, 0x00U, }}, - /* ==== WASM: 80 ==== */ + /* ==== WASM: 81 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16952,7 +17056,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 81 ==== */ + /* ==== WASM: 82 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17011,7 +17115,7 @@ std::map> wasm = { 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 82 ==== */ + /* ==== WASM: 83 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17070,7 +17174,7 @@ std::map> wasm = { 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 83 ==== */ + /* ==== WASM: 84 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -18899,7 +19003,7 @@ std::map> wasm = { 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 84 ==== */ + /* ==== WASM: 85 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -20179,7 +20283,7 @@ std::map> wasm = { 0x29U, 0x2CU, 0x20U, 0x30U, 0x2CU, 0x30U, 0x20U, 0x29U, 0x29U, 0x00U, }}, - /* ==== WASM: 85 ==== */ + /* ==== WASM: 86 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -23112,7 +23216,7 @@ std::map> wasm = { 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 86 ==== */ + /* ==== WASM: 87 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25077,7 +25181,7 @@ std::map> wasm = { 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 87 ==== */ + /* ==== WASM: 88 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25362,7 +25466,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 88 ==== */ + /* ==== WASM: 89 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -25949,7 +26053,7 @@ std::map> wasm = { 0x4EU, 0x5FU, 0x46U, 0x41U, 0x49U, 0x4CU, 0x55U, 0x52U, 0x45U, 0x00U, }}, - /* ==== WASM: 89 ==== */ + /* ==== WASM: 90 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25978,7 +26082,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 90 ==== */ + /* ==== WASM: 91 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26010,7 +26114,7 @@ std::map> wasm = { 0x20U, 0x52U, 0x65U, 0x6AU, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x00U, }}, - /* ==== WASM: 91 ==== */ + /* ==== WASM: 92 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32 i64) (result i64))) @@ -26037,7 +26141,7 @@ std::map> wasm = { 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x00U, 0x0BU, }}, - /* ==== WASM: 92 ==== */ + /* ==== WASM: 93 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i32))) @@ -26090,7 +26194,7 @@ std::map> wasm = { 0x00U, 0x1AU, 0x0BU, }}, - /* ==== WASM: 93 ==== */ + /* ==== WASM: 94 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -32733,7 +32837,7 @@ std::map> wasm = { 0x39U, 0x30U, 0x31U, 0x32U, 0x33U, 0x00U, }}, - /* ==== WASM: 94 ==== */ + /* ==== WASM: 95 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -32779,7 +32883,7 @@ std::map> wasm = { 0x0BU, 0x06U, 0x76U, 0x61U, 0x6CU, 0x75U, 0x65U, 0x00U, }}, - /* ==== WASM: 95 ==== */ + /* ==== WASM: 96 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); From d611e16796279fae5f2d2988a54f0560af93abaa Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 21:02:06 +0900 Subject: [PATCH 04/33] refactor whitelist APIs to enable amendment guard outside Guard.h --- src/ripple/app/hook/Enum.h | 181 +++++++++++++------------- src/ripple/app/hook/Guard.h | 20 +-- src/ripple/app/hook/guard_checker.cpp | 5 +- src/ripple/app/tx/impl/Change.cpp | 5 +- src/ripple/app/tx/impl/SetHook.cpp | 4 +- 5 files changed, 107 insertions(+), 108 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index ce012aea57..d0ddf2fb7e 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,3 +1,7 @@ +#ifndef GUARD_CHECKER_BUILD +#include +#include +#endif #include #include #include @@ -372,12 +376,8 @@ const double fee_base_multiplier = 1.1f; #define HOOK_WRAP_PARAMS(...) __VA_ARGS__ #define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, COST) \ - { \ - FUNCTION_NAME, \ - { \ - {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}, COST \ - } \ - } + whitelist[FUNCTION_NAME] = { \ + {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}, COST}; using APIWhitelist = std::map, uint32_t>>; @@ -385,91 +385,98 @@ using APIWhitelist = // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes -static const APIWhitelist import_whitelist{ +inline APIWhitelist +getImportWhitelist( +#ifndef GUARD_CHECKER_BUILD + Rules const& rules +#endif +) +{ + APIWhitelist whitelist; // clang-format off // TODO: update costs for each API - HOOK_API_DEFINITION(I32, "_g", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "accept", (I32, I32, I64), 100), - HOOK_API_DEFINITION(I64, "rollback", (I32, I32, I64), 100), - HOOK_API_DEFINITION(I64, "util_raddr", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "util_accid", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "util_verify", (I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "util_sha512h", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "util_keylet", (I32, I32, I32, I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "sto_validate", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "sto_subfield", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "sto_subarray", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "sto_emplace", (I32, I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "sto_erase", (I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "etxn_burden", (), 100), - HOOK_API_DEFINITION(I64, "etxn_details", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "etxn_fee_base", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "etxn_reserve", (I32), 100), - HOOK_API_DEFINITION(I64, "etxn_generation", (), 100), - HOOK_API_DEFINITION(I64, "etxn_nonce", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "emit", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "float_set", (I32, I64),0), - HOOK_API_DEFINITION(I64, "float_multiply", (I64, I64), 100), - HOOK_API_DEFINITION(I64, "float_mulratio", (I64, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "float_negate", (I64), 100), - HOOK_API_DEFINITION(I64, "float_compare", (I64, I64, I32), 100), - HOOK_API_DEFINITION(I64, "float_sum", (I64, I64), 100), - HOOK_API_DEFINITION(I64, "float_sto", (I32, I32, I32, I32, I32, I32, I64, I32), 100), - HOOK_API_DEFINITION(I64, "float_sto_set", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "float_invert", (I64), 100), - HOOK_API_DEFINITION(I64, "float_divide", (I64, I64), 100), - HOOK_API_DEFINITION(I64, "float_one", (), 100), - HOOK_API_DEFINITION(I64, "float_mantissa", (I64), 100), - HOOK_API_DEFINITION(I64, "float_sign", (I64), 100), - HOOK_API_DEFINITION(I64, "float_int", (I64, I32, I32), 100), - HOOK_API_DEFINITION(I64, "float_log", (I64), 100), - HOOK_API_DEFINITION(I64, "float_root", (I64, I32), 100), - HOOK_API_DEFINITION(I64, "fee_base", (), 100), - HOOK_API_DEFINITION(I64, "ledger_seq", (), 100), - HOOK_API_DEFINITION(I64, "ledger_last_time", (), 100), - HOOK_API_DEFINITION(I64, "ledger_last_hash", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "ledger_nonce", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "ledger_keylet", (I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_account", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_hash", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_param_set", (I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_param", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_again", (), 100), - HOOK_API_DEFINITION(I64, "hook_skip", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "hook_pos", (), 100), - HOOK_API_DEFINITION(I64, "slot", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "slot_clear", (I32), 100), - HOOK_API_DEFINITION(I64, "slot_count", (I32), 100), - HOOK_API_DEFINITION(I64, "slot_set", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "slot_size", (I32), 100), - HOOK_API_DEFINITION(I64, "slot_subarray", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "slot_subfield", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "slot_type", (I32, I32), 100), - HOOK_API_DEFINITION(I64, "slot_float", (I32), 100), - HOOK_API_DEFINITION(I64, "state_set", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "state_foreign_set", (I32, I32, I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "state", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "state_foreign", (I32, I32, I32, I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "trace", (I32, I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "trace_num", (I32, I32, I64), 100), - HOOK_API_DEFINITION(I64, "trace_float", (I32, I32, I64), 100), - HOOK_API_DEFINITION(I64, "otxn_burden", (), 100), - HOOK_API_DEFINITION(I64, "otxn_field", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "otxn_generation", (), 100), - HOOK_API_DEFINITION(I64, "otxn_id", (I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "otxn_type", (), 100), - HOOK_API_DEFINITION(I64, "otxn_slot", (I32), 100), - HOOK_API_DEFINITION(I64, "otxn_param", (I32, I32, I32, I32), 100), - HOOK_API_DEFINITION(I64, "meta_slot", (I32), 100), - // clang-format on -}; + HOOK_API_DEFINITION(I32, "_g", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "accept", (I32, I32, I64), 100) + HOOK_API_DEFINITION(I64, "rollback", (I32, I32, I64), 100) + HOOK_API_DEFINITION(I64, "util_raddr", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "util_accid", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "util_verify", (I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "util_sha512h", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "util_keylet", (I32, I32, I32, I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "sto_validate", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "sto_subfield", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "sto_subarray", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "sto_emplace", (I32, I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "sto_erase", (I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "etxn_burden", (), 100) + HOOK_API_DEFINITION(I64, "etxn_details", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "etxn_fee_base", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "etxn_reserve", (I32), 100) + HOOK_API_DEFINITION(I64, "etxn_generation", (), 100) + HOOK_API_DEFINITION(I64, "etxn_nonce", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "emit", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "float_set", (I32, I64),0) + HOOK_API_DEFINITION(I64, "float_multiply", (I64, I64), 100) + HOOK_API_DEFINITION(I64, "float_mulratio", (I64, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "float_negate", (I64), 100) + HOOK_API_DEFINITION(I64, "float_compare", (I64, I64, I32), 100) + HOOK_API_DEFINITION(I64, "float_sum", (I64, I64), 100) + HOOK_API_DEFINITION(I64, "float_sto", (I32, I32, I32, I32, I32, I32, I64, I32), 100) + HOOK_API_DEFINITION(I64, "float_sto_set", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "float_invert", (I64), 100) + HOOK_API_DEFINITION(I64, "float_divide", (I64, I64), 100) + HOOK_API_DEFINITION(I64, "float_one", (), 100) + HOOK_API_DEFINITION(I64, "float_mantissa", (I64), 100) + HOOK_API_DEFINITION(I64, "float_sign", (I64), 100) + HOOK_API_DEFINITION(I64, "float_int", (I64, I32, I32), 100) + HOOK_API_DEFINITION(I64, "float_log", (I64), 100) + HOOK_API_DEFINITION(I64, "float_root", (I64, I32), 100) + HOOK_API_DEFINITION(I64, "fee_base", (), 100) + HOOK_API_DEFINITION(I64, "ledger_seq", (), 100) + HOOK_API_DEFINITION(I64, "ledger_last_time", (), 100) + HOOK_API_DEFINITION(I64, "ledger_last_hash", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "ledger_nonce", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "ledger_keylet", (I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_account", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_hash", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_param_set", (I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_param", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_again", (), 100) + HOOK_API_DEFINITION(I64, "hook_skip", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "hook_pos", (), 100) + HOOK_API_DEFINITION(I64, "slot", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "slot_clear", (I32), 100) + HOOK_API_DEFINITION(I64, "slot_count", (I32), 100) + HOOK_API_DEFINITION(I64, "slot_set", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "slot_size", (I32), 100) + HOOK_API_DEFINITION(I64, "slot_subarray", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "slot_subfield", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "slot_type", (I32, I32), 100) + HOOK_API_DEFINITION(I64, "slot_float", (I32), 100) + HOOK_API_DEFINITION(I64, "state_set", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "state_foreign_set", (I32, I32, I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "state", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "state_foreign", (I32, I32, I32, I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "trace", (I32, I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "trace_num", (I32, I32, I64), 100) + HOOK_API_DEFINITION(I64, "trace_float", (I32, I32, I64), 100) + HOOK_API_DEFINITION(I64, "otxn_burden", (), 100) + HOOK_API_DEFINITION(I64, "otxn_field", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "otxn_generation", (), 100) + HOOK_API_DEFINITION(I64, "otxn_id", (I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "otxn_type", (), 100) + HOOK_API_DEFINITION(I64, "otxn_slot", (I32), 100) + HOOK_API_DEFINITION(I64, "otxn_param", (I32, I32, I32, I32), 100) + HOOK_API_DEFINITION(I64, "meta_slot", (I32), 100) -// featureHooks1 -static const APIWhitelist import_whitelist_1{ - // clang-format off - HOOK_API_DEFINITION(I64, "xpop_slot", (I32, I32), 100), + #ifndef GUARD_CHECKER_BUILD + if (rules.enabled(featureHooksUpdate1)) + #endif + HOOK_API_DEFINITION(I64, "xpop_slot", (I32, I32), 100) + + return whitelist; // clang-format on -}; +} #undef HOOK_API_DEFINITION #undef I32 diff --git a/src/ripple/app/hook/Guard.h b/src/ripple/app/hook/Guard.h index 99c6efdf39..b6a3cf3b9a 100644 --- a/src/ripple/app/hook/Guard.h +++ b/src/ripple/app/hook/Guard.h @@ -841,6 +841,7 @@ validateGuards( GuardLog guardLog, std::string guardLogAccStr, bool returnCost, + hook_api::APIWhitelist const import_whitelist, /* RH NOTE: * rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02 * and update 3 is 0x04 ideally at rule version 3 all bits so far are set @@ -1039,16 +1040,8 @@ validateGuards( uint32_t cost = 0; - auto merged_import_whitelist = hook_api::import_whitelist; - if (rulesVersion > 0) - { - merged_import_whitelist.insert( - hook_api::import_whitelist_1.begin(), - hook_api::import_whitelist_1.end()); - } - - auto it = merged_import_whitelist.find(import_name); - auto it_end = merged_import_whitelist.end(); + auto it = import_whitelist.find(import_name); + auto it_end = import_whitelist.end(); bool found_in_whitelist = (it != it_end); if (import_name == "_g") @@ -1284,12 +1277,7 @@ validateGuards( usage->second.first) { auto const& api_signature = - hook_api::import_whitelist.find(api_name) != - hook_api::import_whitelist.end() - ? hook_api::import_whitelist.find(api_name) - ->second.first - : hook_api::import_whitelist_1.find(api_name) - ->second.first; + import_whitelist.find(api_name)->second.first; if (!first_signature) { diff --git a/src/ripple/app/hook/guard_checker.cpp b/src/ripple/app/hook/guard_checker.cpp index a9e4c07b68..a241ba5f63 100644 --- a/src/ripple/app/hook/guard_checker.cpp +++ b/src/ripple/app/hook/guard_checker.cpp @@ -1,3 +1,5 @@ +#define GUARD_CHECKER_BUILD +#include "Enum.h" #include "Guard.h" #include #include @@ -79,7 +81,8 @@ main(int argc, char** argv) close(fd); - auto result = validateGuards(hook, std::cout, "", false, 3); + auto result = validateGuards( + hook, std::cout, "", false, hook_api::getImportWhitelist(), 3); if (!result) { diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 9a32a2ad27..55fa12c47c 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -606,8 +607,8 @@ Change::activateXahauGenesis() loggerStream, "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", false, - (ctx_.view().rules().enabled(featureHooksUpdate1) ? 1 : 0) + - (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); + hook_api::getImportWhitelist(ctx_.view().rules()), + (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); if (!result) { diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index 9f7f35345a..10ea385e31 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -491,8 +491,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) logger, hsacc, ctx.rules.enabled(featureHookFeeV2), - (ctx.rules.enabled(featureHooksUpdate1) ? 1 : 0) + - (ctx.rules.enabled(fix20250131) ? 2 : 0)); + hook_api::getImportWhitelist(ctx.rules), + (ctx.rules.enabled(fix20250131) ? 2 : 0)); if (ctx.j.trace()) { From 4269ef736b596ebb1fe06962bdec2d0a4be715f8 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 21:02:06 +0900 Subject: [PATCH 05/33] additional refactor --- src/ripple/app/hook/Enum.h | 165 +++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 80 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 3af3d0cc75..06501fbbdb 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,3 +1,7 @@ +#ifndef GUARD_CHECKER_BUILD +#include +#include +#endif #include #include #include @@ -371,12 +375,13 @@ const double fee_base_multiplier = 1.1f; #define I32 0x7FU #define I64 0x7EU -#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, ...) \ - { \ - FUNCTION_NAME, \ - { \ - RETURN_TYPE, __VA_ARGS__ \ - } \ +#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE) \ + { \ +#FUNCTION_NAME, \ + { \ + RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE \ + } \ } using APIWhitelist = std::map>; @@ -386,86 +391,86 @@ using APIWhitelist = std::map>; // code (vec[0] and its parameters vec[>0]) as wasm type codes static const APIWhitelist import_whitelist{ // clang-format off - HOOK_API_DEFINITION(I32, "_g", I32, I32), - HOOK_API_DEFINITION(I64, "accept", I32, I32, I64), - HOOK_API_DEFINITION(I64, "rollback", I32, I32, I64), - HOOK_API_DEFINITION(I64, "util_raddr", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_accid", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_verify", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_sha512h", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "util_keylet", I32, I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_validate", I32, I32), - HOOK_API_DEFINITION(I64, "sto_subfield", I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_subarray", I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_emplace", I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "sto_erase", I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "etxn_burden"), - HOOK_API_DEFINITION(I64, "etxn_details", I32, I32), - HOOK_API_DEFINITION(I64, "etxn_fee_base", I32, I32), - HOOK_API_DEFINITION(I64, "etxn_reserve", I32), - HOOK_API_DEFINITION(I64, "etxn_generation"), - HOOK_API_DEFINITION(I64, "etxn_nonce", I32, I32), - HOOK_API_DEFINITION(I64, "emit", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "float_set", I32, I64), - HOOK_API_DEFINITION(I64, "float_multiply", I64, I64), - HOOK_API_DEFINITION(I64, "float_mulratio", I64, I32, I32, I32), - HOOK_API_DEFINITION(I64, "float_negate", I64), - HOOK_API_DEFINITION(I64, "float_compare", I64, I64, I32), - HOOK_API_DEFINITION(I64, "float_sum", I64, I64), - HOOK_API_DEFINITION(I64, "float_sto", I32, I32, I32, I32, I32, I32, I64, I32), - HOOK_API_DEFINITION(I64, "float_sto_set", I32, I32), - HOOK_API_DEFINITION(I64, "float_invert", I64), - HOOK_API_DEFINITION(I64, "float_divide", I64, I64), - HOOK_API_DEFINITION(I64, "float_one"), - HOOK_API_DEFINITION(I64, "float_mantissa", I64), - HOOK_API_DEFINITION(I64, "float_sign", I64), - HOOK_API_DEFINITION(I64, "float_int", I64, I32, I32), - HOOK_API_DEFINITION(I64, "float_log", I64), - HOOK_API_DEFINITION(I64, "float_root", I64, I32), - HOOK_API_DEFINITION(I64, "fee_base"), - HOOK_API_DEFINITION(I64, "ledger_seq"), - HOOK_API_DEFINITION(I64, "ledger_last_time"), - HOOK_API_DEFINITION(I64, "ledger_last_hash", I32, I32), - HOOK_API_DEFINITION(I64, "ledger_nonce", I32, I32), - HOOK_API_DEFINITION(I64, "ledger_keylet", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_account", I32, I32), - HOOK_API_DEFINITION(I64, "hook_hash", I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_param_set", I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_param", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_again"), - HOOK_API_DEFINITION(I64, "hook_skip", I32, I32, I32), - HOOK_API_DEFINITION(I64, "hook_pos"), - HOOK_API_DEFINITION(I64, "slot", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_clear", I32), - HOOK_API_DEFINITION(I64, "slot_count", I32), - HOOK_API_DEFINITION(I64, "slot_set", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_size", I32), - HOOK_API_DEFINITION(I64, "slot_subarray", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_subfield", I32, I32, I32), - HOOK_API_DEFINITION(I64, "slot_type", I32, I32), - HOOK_API_DEFINITION(I64, "slot_float", I32), - HOOK_API_DEFINITION(I64, "state_set", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state_foreign_set", I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "state_foreign", I32, I32, I32, I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "trace", I32, I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "trace_num", I32, I32, I64), - HOOK_API_DEFINITION(I64, "trace_float", I32, I32, I64), - HOOK_API_DEFINITION(I64, "otxn_burden"), - HOOK_API_DEFINITION(I64, "otxn_field", I32, I32, I32), - HOOK_API_DEFINITION(I64, "otxn_generation"), - HOOK_API_DEFINITION(I64, "otxn_id", I32, I32, I32), - HOOK_API_DEFINITION(I64, "otxn_type"), - HOOK_API_DEFINITION(I64, "otxn_slot", I32), - HOOK_API_DEFINITION(I64, "otxn_param", I32, I32, I32, I32), - HOOK_API_DEFINITION(I64, "meta_slot", I32), + HOOK_API_DEFINITION(I32, _g, (I32, I32)), + HOOK_API_DEFINITION(I64, accept, (I32, I32, I64)), + HOOK_API_DEFINITION(I64, rollback, (I32, I32, I64)), + HOOK_API_DEFINITION(I64, util_raddr, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, util_accid, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, util_verify, (I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, util_sha512h, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, util_keylet, (I32, I32, I32, I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, sto_validate, (I32, I32)), + HOOK_API_DEFINITION(I64, sto_subfield, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, sto_subarray, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, sto_emplace, (I32, I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, sto_erase, (I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, etxn_burden, ()), + HOOK_API_DEFINITION(I64, etxn_details, (I32, I32)), + HOOK_API_DEFINITION(I64, etxn_fee_base, (I32, I32)), + HOOK_API_DEFINITION(I64, etxn_reserve, (I32)), + HOOK_API_DEFINITION(I64, etxn_generation, ()), + HOOK_API_DEFINITION(I64, etxn_nonce, (I32, I32)), + HOOK_API_DEFINITION(I64, emit, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, float_set, (I32, I64)), + HOOK_API_DEFINITION(I64, float_multiply, (I64, I64)), + HOOK_API_DEFINITION(I64, float_mulratio, (I64, I32, I32, I32)), + HOOK_API_DEFINITION(I64, float_negate, (I64)), + HOOK_API_DEFINITION(I64, float_compare, (I64, I64, I32)), + HOOK_API_DEFINITION(I64, float_sum, (I64, I64)), + HOOK_API_DEFINITION(I64, float_sto, (I32, I32, I32, I32, I32, I32, I64, I32)), + HOOK_API_DEFINITION(I64, float_sto_set, (I32, I32)), + HOOK_API_DEFINITION(I64, float_invert, (I64)), + HOOK_API_DEFINITION(I64, float_divide, (I64, I64)), + HOOK_API_DEFINITION(I64, float_one, ()), + HOOK_API_DEFINITION(I64, float_mantissa, (I64)), + HOOK_API_DEFINITION(I64, float_sign, (I64)), + HOOK_API_DEFINITION(I64, float_int, (I64, I32, I32)), + HOOK_API_DEFINITION(I64, float_log, (I64)), + HOOK_API_DEFINITION(I64, float_root, (I64, I32)), + HOOK_API_DEFINITION(I64, fee_base, ()), + HOOK_API_DEFINITION(I64, ledger_seq, ()), + HOOK_API_DEFINITION(I64, ledger_last_time, ()), + HOOK_API_DEFINITION(I64, ledger_last_hash, (I32, I32)), + HOOK_API_DEFINITION(I64, ledger_nonce, (I32, I32)), + HOOK_API_DEFINITION(I64, ledger_keylet, (I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, hook_account, (I32, I32)), + HOOK_API_DEFINITION(I64, hook_hash, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, hook_param_set, (I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, hook_param, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, hook_again, ()), + HOOK_API_DEFINITION(I64, hook_skip, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, hook_pos, ()), + HOOK_API_DEFINITION(I64, slot, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, slot_clear, (I32)), + HOOK_API_DEFINITION(I64, slot_count, (I32)), + HOOK_API_DEFINITION(I64, slot_set, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, slot_size, (I32)), + HOOK_API_DEFINITION(I64, slot_subarray, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, slot_subfield, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, slot_type, (I32, I32)), + HOOK_API_DEFINITION(I64, slot_float, (I32)), + HOOK_API_DEFINITION(I64, state_set, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, state_foreign_set, (I32, I32, I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, state, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, state_foreign, (I32, I32, I32, I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, trace, (I32, I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, trace_num, (I32, I32, I64)), + HOOK_API_DEFINITION(I64, trace_float, (I32, I32, I64)), + HOOK_API_DEFINITION(I64, otxn_burden, ()), + HOOK_API_DEFINITION(I64, otxn_field, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, otxn_generation, ()), + HOOK_API_DEFINITION(I64, otxn_id, (I32, I32, I32)), + HOOK_API_DEFINITION(I64, otxn_type, ()), + HOOK_API_DEFINITION(I64, otxn_slot, (I32)), + HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)), + HOOK_API_DEFINITION(I64, meta_slot, (I32)), // clang-format on }; // featureHooks1 static const APIWhitelist import_whitelist_1{ // clang-format off - HOOK_API_DEFINITION(I64, "xpop_slot", I32, I32) + HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)), // clang-format on }; From 9c0feaf6c75de95f3c73ed6c82479a0a2f58ba40 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 22:06:53 +0900 Subject: [PATCH 06/33] fix --- src/ripple/app/hook/Enum.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 06501fbbdb..5a19dedd81 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,7 +1,3 @@ -#ifndef GUARD_CHECKER_BUILD -#include -#include -#endif #include #include #include From 24e18c9766f3d3b1277b6d2868e7ebb210c47f6e Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 22:18:10 +0900 Subject: [PATCH 07/33] Refactor2: Hook APIs Amendment Guards --- src/ripple/app/hook/Enum.h | 176 +++++++++++++------------- src/ripple/app/hook/Guard.h | 40 +++--- src/ripple/app/hook/guard_checker.cpp | 5 +- src/ripple/app/tx/impl/Change.cpp | 5 +- src/ripple/app/tx/impl/SetHook.cpp | 4 +- 5 files changed, 113 insertions(+), 117 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 5a19dedd81..0083745d78 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -373,102 +373,104 @@ const double fee_base_multiplier = 1.1f; #define HOOK_WRAP_PARAMS(...) __VA_ARGS__ #define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE) \ - { \ -#FUNCTION_NAME, \ - { \ - RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE \ - } \ - } + whitelist[#FUNCTION_NAME] = {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}; using APIWhitelist = std::map>; // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes -static const APIWhitelist import_whitelist{ +inline APIWhitelist +getImportWhitelist( +#ifndef GUARD_CHECKER_BUILD + Rules const& rules +#endif +) +{ + APIWhitelist whitelist; // clang-format off - HOOK_API_DEFINITION(I32, _g, (I32, I32)), - HOOK_API_DEFINITION(I64, accept, (I32, I32, I64)), - HOOK_API_DEFINITION(I64, rollback, (I32, I32, I64)), - HOOK_API_DEFINITION(I64, util_raddr, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, util_accid, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, util_verify, (I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, util_sha512h, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, util_keylet, (I32, I32, I32, I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, sto_validate, (I32, I32)), - HOOK_API_DEFINITION(I64, sto_subfield, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, sto_subarray, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, sto_emplace, (I32, I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, sto_erase, (I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, etxn_burden, ()), - HOOK_API_DEFINITION(I64, etxn_details, (I32, I32)), - HOOK_API_DEFINITION(I64, etxn_fee_base, (I32, I32)), - HOOK_API_DEFINITION(I64, etxn_reserve, (I32)), - HOOK_API_DEFINITION(I64, etxn_generation, ()), - HOOK_API_DEFINITION(I64, etxn_nonce, (I32, I32)), - HOOK_API_DEFINITION(I64, emit, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, float_set, (I32, I64)), - HOOK_API_DEFINITION(I64, float_multiply, (I64, I64)), - HOOK_API_DEFINITION(I64, float_mulratio, (I64, I32, I32, I32)), - HOOK_API_DEFINITION(I64, float_negate, (I64)), - HOOK_API_DEFINITION(I64, float_compare, (I64, I64, I32)), - HOOK_API_DEFINITION(I64, float_sum, (I64, I64)), - HOOK_API_DEFINITION(I64, float_sto, (I32, I32, I32, I32, I32, I32, I64, I32)), - HOOK_API_DEFINITION(I64, float_sto_set, (I32, I32)), - HOOK_API_DEFINITION(I64, float_invert, (I64)), - HOOK_API_DEFINITION(I64, float_divide, (I64, I64)), - HOOK_API_DEFINITION(I64, float_one, ()), - HOOK_API_DEFINITION(I64, float_mantissa, (I64)), - HOOK_API_DEFINITION(I64, float_sign, (I64)), - HOOK_API_DEFINITION(I64, float_int, (I64, I32, I32)), - HOOK_API_DEFINITION(I64, float_log, (I64)), - HOOK_API_DEFINITION(I64, float_root, (I64, I32)), - HOOK_API_DEFINITION(I64, fee_base, ()), - HOOK_API_DEFINITION(I64, ledger_seq, ()), - HOOK_API_DEFINITION(I64, ledger_last_time, ()), - HOOK_API_DEFINITION(I64, ledger_last_hash, (I32, I32)), - HOOK_API_DEFINITION(I64, ledger_nonce, (I32, I32)), - HOOK_API_DEFINITION(I64, ledger_keylet, (I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, hook_account, (I32, I32)), - HOOK_API_DEFINITION(I64, hook_hash, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, hook_param_set, (I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, hook_param, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, hook_again, ()), - HOOK_API_DEFINITION(I64, hook_skip, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, hook_pos, ()), - HOOK_API_DEFINITION(I64, slot, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, slot_clear, (I32)), - HOOK_API_DEFINITION(I64, slot_count, (I32)), - HOOK_API_DEFINITION(I64, slot_set, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, slot_size, (I32)), - HOOK_API_DEFINITION(I64, slot_subarray, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, slot_subfield, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, slot_type, (I32, I32)), - HOOK_API_DEFINITION(I64, slot_float, (I32)), - HOOK_API_DEFINITION(I64, state_set, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, state_foreign_set, (I32, I32, I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, state, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, state_foreign, (I32, I32, I32, I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, trace, (I32, I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, trace_num, (I32, I32, I64)), - HOOK_API_DEFINITION(I64, trace_float, (I32, I32, I64)), - HOOK_API_DEFINITION(I64, otxn_burden, ()), - HOOK_API_DEFINITION(I64, otxn_field, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, otxn_generation, ()), - HOOK_API_DEFINITION(I64, otxn_id, (I32, I32, I32)), - HOOK_API_DEFINITION(I64, otxn_type, ()), - HOOK_API_DEFINITION(I64, otxn_slot, (I32)), - HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)), - HOOK_API_DEFINITION(I64, meta_slot, (I32)), - // clang-format on -}; + HOOK_API_DEFINITION(I32, _g, (I32, I32)) + HOOK_API_DEFINITION(I64, accept, (I32, I32, I64)) + HOOK_API_DEFINITION(I64, rollback, (I32, I32, I64)) + HOOK_API_DEFINITION(I64, util_raddr, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, util_accid, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, util_verify, (I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, util_sha512h, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, util_keylet, (I32, I32, I32, I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, sto_validate, (I32, I32)) + HOOK_API_DEFINITION(I64, sto_subfield, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, sto_subarray, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, sto_emplace, (I32, I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, sto_erase, (I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, etxn_burden, ()) + HOOK_API_DEFINITION(I64, etxn_details, (I32, I32)) + HOOK_API_DEFINITION(I64, etxn_fee_base, (I32, I32)) + HOOK_API_DEFINITION(I64, etxn_reserve, (I32)) + HOOK_API_DEFINITION(I64, etxn_generation, ()) + HOOK_API_DEFINITION(I64, etxn_nonce, (I32, I32)) + HOOK_API_DEFINITION(I64, emit, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, float_set, (I32, I64)) + HOOK_API_DEFINITION(I64, float_multiply, (I64, I64)) + HOOK_API_DEFINITION(I64, float_mulratio, (I64, I32, I32, I32)) + HOOK_API_DEFINITION(I64, float_negate, (I64)) + HOOK_API_DEFINITION(I64, float_compare, (I64, I64, I32)) + HOOK_API_DEFINITION(I64, float_sum, (I64, I64)) + HOOK_API_DEFINITION(I64, float_sto, (I32, I32, I32, I32, I32, I32, I64, I32)) + HOOK_API_DEFINITION(I64, float_sto_set, (I32, I32)) + HOOK_API_DEFINITION(I64, float_invert, (I64)) + HOOK_API_DEFINITION(I64, float_divide, (I64, I64)) + HOOK_API_DEFINITION(I64, float_one, ()) + HOOK_API_DEFINITION(I64, float_mantissa, (I64)) + HOOK_API_DEFINITION(I64, float_sign, (I64)) + HOOK_API_DEFINITION(I64, float_int, (I64, I32, I32)) + HOOK_API_DEFINITION(I64, float_log, (I64)) + HOOK_API_DEFINITION(I64, float_root, (I64, I32)) + HOOK_API_DEFINITION(I64, fee_base, ()) + HOOK_API_DEFINITION(I64, ledger_seq, ()) + HOOK_API_DEFINITION(I64, ledger_last_time, ()) + HOOK_API_DEFINITION(I64, ledger_last_hash, (I32, I32)) + HOOK_API_DEFINITION(I64, ledger_nonce, (I32, I32)) + HOOK_API_DEFINITION(I64, ledger_keylet, (I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, hook_account, (I32, I32)) + HOOK_API_DEFINITION(I64, hook_hash, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, hook_param_set, (I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, hook_param, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, hook_again, ()) + HOOK_API_DEFINITION(I64, hook_skip, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, hook_pos, ()) + HOOK_API_DEFINITION(I64, slot, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, slot_clear, (I32)) + HOOK_API_DEFINITION(I64, slot_count, (I32)) + HOOK_API_DEFINITION(I64, slot_set, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, slot_size, (I32)) + HOOK_API_DEFINITION(I64, slot_subarray, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, slot_subfield, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, slot_type, (I32, I32)) + HOOK_API_DEFINITION(I64, slot_float, (I32)) + HOOK_API_DEFINITION(I64, state_set, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, state_foreign_set, (I32, I32, I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, state, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, state_foreign, (I32, I32, I32, I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, trace, (I32, I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, trace_num, (I32, I32, I64)) + HOOK_API_DEFINITION(I64, trace_float, (I32, I32, I64)) + HOOK_API_DEFINITION(I64, otxn_burden, ()) + HOOK_API_DEFINITION(I64, otxn_field, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, otxn_generation, ()) + HOOK_API_DEFINITION(I64, otxn_id, (I32, I32, I32)) + HOOK_API_DEFINITION(I64, otxn_type, ()) + HOOK_API_DEFINITION(I64, otxn_slot, (I32)) + HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)) + HOOK_API_DEFINITION(I64, meta_slot, (I32)) -// featureHooks1 -static const APIWhitelist import_whitelist_1{ - // clang-format off - HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)), + #ifndef GUARD_CHECKER_BUILD + if (rules.enabled(featureHooksUpdate1)) + #endif + HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)) + + return whitelist; // clang-format on -}; +} #undef HOOK_API_DEFINITION #undef I32 diff --git a/src/ripple/app/hook/Guard.h b/src/ripple/app/hook/Guard.h index f395af4481..09e5509a81 100644 --- a/src/ripple/app/hook/Guard.h +++ b/src/ripple/app/hook/Guard.h @@ -826,6 +826,7 @@ validateGuards( std::vector const& wasm, GuardLog guardLog, std::string guardLogAccStr, + hook_api::APIWhitelist const import_whitelist, /* RH NOTE: * rules version is a bit field, so rule update 1 is 0x01, update 2 is 0x02 * and update 3 is 0x04 ideally at rule version 3 all bits so far are set @@ -1020,31 +1021,24 @@ validateGuards( int type_idx = parseLeb128(wasm, i, &i); CHECK_SHORT_HOOK(); + auto it = import_whitelist.find(import_name); + auto it_end = import_whitelist.end(); + bool found_in_whitelist = (it != it_end); + if (import_name == "_g") { guard_import_number = func_upto; } - else if ( - hook_api::import_whitelist.find(import_name) == - hook_api::import_whitelist.end()) + if (!found_in_whitelist) { - if (rulesVersion > 0 && - hook_api::import_whitelist_1.find(import_name) != - hook_api::import_whitelist_1.end()) - { - // PASS, this is a version 1 api - } - else - { - GUARDLOG(hook::log::IMPORT_ILLEGAL) - << "Malformed transaction. " - << "Hook attempted to import a function that does " - "not " - << "appear in the hook_api function set: `" - << import_name << "`" - << "\n"; - return {}; - } + GUARDLOG(hook::log::IMPORT_ILLEGAL) + << "Malformed transaction. " + << "Hook attempted to import a function that does " + "not " + << "appear in the hook_api function set: `" + << import_name << "`" + << "\n"; + return {}; } // add to import map @@ -1259,11 +1253,7 @@ validateGuards( for (auto const& [import_idx, api_name] : usage->second) { auto const& api_signature = - hook_api::import_whitelist.find(api_name) != - hook_api::import_whitelist.end() - ? hook_api::import_whitelist.find(api_name)->second - : hook_api::import_whitelist_1.find(api_name) - ->second; + import_whitelist.find(api_name)->second; if (!first_signature) { diff --git a/src/ripple/app/hook/guard_checker.cpp b/src/ripple/app/hook/guard_checker.cpp index f20d24617b..adcfc79070 100644 --- a/src/ripple/app/hook/guard_checker.cpp +++ b/src/ripple/app/hook/guard_checker.cpp @@ -1,3 +1,5 @@ +#define GUARD_CHECKER_BUILD +#include "Enum.h" #include "Guard.h" #include #include @@ -79,7 +81,8 @@ main(int argc, char** argv) close(fd); - auto result = validateGuards(hook, std::cout, "", 3); + auto result = + validateGuards(hook, std::cout, "", hook_api::getImportWhitelist(), 3); if (!result) { diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 37a436feea..3c64c065a1 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -17,6 +17,7 @@ */ //============================================================================== +#include #include #include #include @@ -605,8 +606,8 @@ Change::activateXahauGenesis() wasmBytes, // wasm to verify loggerStream, "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", - (ctx_.view().rules().enabled(featureHooksUpdate1) ? 1 : 0) + - (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); + hook_api::getImportWhitelist(ctx_.view().rules()), + (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); if (!result) { diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index 9ca8295571..8b32a6fc25 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -490,8 +490,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) hook, // wasm to verify logger, hsacc, - (ctx.rules.enabled(featureHooksUpdate1) ? 1 : 0) + - (ctx.rules.enabled(fix20250131) ? 2 : 0)); + hook_api::getImportWhitelist(ctx.rules), + (ctx.rules.enabled(fix20250131) ? 2 : 0)); if (ctx.j.trace()) { From adebc3cb8dd9d684cc497063bdc6547264bc1309 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 22:18:10 +0900 Subject: [PATCH 08/33] refactor: rulesVersion --- src/ripple/app/hook/Enum.h | 22 ++++++++++++++++++++++ src/ripple/app/hook/Guard.h | 6 +++--- src/ripple/app/hook/guard_checker.cpp | 8 ++++++-- src/ripple/app/tx/impl/Change.cpp | 2 +- src/ripple/app/tx/impl/SetHook.cpp | 2 +- 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 0083745d78..cded5a2749 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -475,5 +475,27 @@ getImportWhitelist( #undef HOOK_API_DEFINITION #undef I32 #undef I64 + +enum GuardRulesVersion : uint64_t { + GuardRuleFix20250131 = 0x00000001, +}; + +inline uint64_t +getGuardRulesVersion( +#ifndef GUARD_CHECKER_BUILD + Rules const& rules +#endif +) +{ + uint64_t version = 0; +#ifndef GUARD_CHECKER_BUILD + if (rules.enabled(fix20250131)) + version |= GuardRuleFix20250131; +#else + version = -1; // all bits set for guard checker +#endif + return version; +} + }; // namespace hook_api #endif diff --git a/src/ripple/app/hook/Guard.h b/src/ripple/app/hook/Guard.h index 09e5509a81..051d82128b 100644 --- a/src/ripple/app/hook/Guard.h +++ b/src/ripple/app/hook/Guard.h @@ -634,7 +634,7 @@ check_guard( } else if (fc_type == 10) // memory.copy { - if (rulesVersion & 0x02U) + if (rulesVersion & hook_api::GuardRuleFix20250131) GUARD_ERROR("Memory.copy instruction is not allowed."); REQUIRE(2); @@ -642,7 +642,7 @@ check_guard( } else if (fc_type == 11) // memory.fill { - if (rulesVersion & 0x02U) + if (rulesVersion & hook_api::GuardRuleFix20250131) GUARD_ERROR("Memory.fill instruction is not allowed."); ADVANCE(1); @@ -836,7 +836,7 @@ validateGuards( * might have unforeseen consequences, without also rolling back further * changes that are fine. */ - uint64_t rulesVersion = 0) + uint64_t rulesVersion = 0x00) { uint64_t byteCount = wasm.size(); diff --git a/src/ripple/app/hook/guard_checker.cpp b/src/ripple/app/hook/guard_checker.cpp index adcfc79070..f40f4c7eaf 100644 --- a/src/ripple/app/hook/guard_checker.cpp +++ b/src/ripple/app/hook/guard_checker.cpp @@ -81,8 +81,12 @@ main(int argc, char** argv) close(fd); - auto result = - validateGuards(hook, std::cout, "", hook_api::getImportWhitelist(), 3); + auto result = validateGuards( + hook, + std::cout, + "", + hook_api::getImportWhitelist(), + hook_api::getGuardRulesVersion()); if (!result) { diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index 3c64c065a1..1a78e0815c 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -607,7 +607,7 @@ Change::activateXahauGenesis() loggerStream, "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", hook_api::getImportWhitelist(ctx_.view().rules()), - (ctx_.view().rules().enabled(fix20250131) ? 2 : 0)); + hook_api::getGuardRulesVersion(ctx_.view().rules())); if (!result) { diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index 8b32a6fc25..2b35f2a592 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -491,7 +491,7 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) logger, hsacc, hook_api::getImportWhitelist(ctx.rules), - (ctx.rules.enabled(fix20250131) ? 2 : 0)); + hook_api::getGuardRulesVersion(ctx.rules)); if (ctx.j.trace()) { From c89967e2742e7bee7922304decfcf920536f21fc Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 30 Oct 2025 22:19:44 +0900 Subject: [PATCH 09/33] bad merge --- src/ripple/app/hook/Enum.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index cded5a2749..000afeffe6 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,3 +1,7 @@ +#ifndef GUARD_CHECKER_BUILD +#include +#include +#endif #include #include #include From fce6cedec159445bd3a6c16745f2fce6bb83a37c Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 31 Oct 2025 15:53:59 +0900 Subject: [PATCH 10/33] Refactor3: Consolidate the Hook API definitions from Enum.h and ApplyHook.h into a single file. --- src/ripple/app/hook/Enum.h | 120 ++------ src/ripple/app/hook/Macro.h | 24 +- src/ripple/app/hook/applyHook.h | 476 ++--------------------------- src/ripple/app/hook/hook_api.macro | 221 ++++++++++++++ 4 files changed, 292 insertions(+), 549 deletions(-) create mode 100644 src/ripple/app/hook/hook_api.macro diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index ddb87bf6cb..6c50ff62e6 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,4 +1,5 @@ #ifndef GUARD_CHECKER_BUILD +#include #include #include #endif @@ -371,13 +372,6 @@ const uint8_t max_emit = 255; const uint8_t max_params = 16; const double fee_base_multiplier = 1.1f; -#define I32 0x7FU -#define I64 0x7EU - -#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ -#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE) \ - whitelist[#FUNCTION_NAME] = {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}; - using APIWhitelist = std::map>; // RH NOTE: Find descriptions of api functions in ./impl/applyHook.cpp and @@ -391,88 +385,40 @@ getImportWhitelist( ) { APIWhitelist whitelist; - // clang-format off - HOOK_API_DEFINITION(I32, _g, (I32, I32)) - HOOK_API_DEFINITION(I64, accept, (I32, I32, I64)) - HOOK_API_DEFINITION(I64, rollback, (I32, I32, I64)) - HOOK_API_DEFINITION(I64, util_raddr, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, util_accid, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, util_verify, (I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, util_sha512h, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, util_keylet, (I32, I32, I32, I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, sto_validate, (I32, I32)) - HOOK_API_DEFINITION(I64, sto_subfield, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, sto_subarray, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, sto_emplace, (I32, I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, sto_erase, (I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, etxn_burden, ()) - HOOK_API_DEFINITION(I64, etxn_details, (I32, I32)) - HOOK_API_DEFINITION(I64, etxn_fee_base, (I32, I32)) - HOOK_API_DEFINITION(I64, etxn_reserve, (I32)) - HOOK_API_DEFINITION(I64, etxn_generation, ()) - HOOK_API_DEFINITION(I64, etxn_nonce, (I32, I32)) - HOOK_API_DEFINITION(I64, emit, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, float_set, (I32, I64)) - HOOK_API_DEFINITION(I64, float_multiply, (I64, I64)) - HOOK_API_DEFINITION(I64, float_mulratio, (I64, I32, I32, I32)) - HOOK_API_DEFINITION(I64, float_negate, (I64)) - HOOK_API_DEFINITION(I64, float_compare, (I64, I64, I32)) - HOOK_API_DEFINITION(I64, float_sum, (I64, I64)) - HOOK_API_DEFINITION(I64, float_sto, (I32, I32, I32, I32, I32, I32, I64, I32)) - HOOK_API_DEFINITION(I64, float_sto_set, (I32, I32)) - HOOK_API_DEFINITION(I64, float_invert, (I64)) - HOOK_API_DEFINITION(I64, float_divide, (I64, I64)) - HOOK_API_DEFINITION(I64, float_one, ()) - HOOK_API_DEFINITION(I64, float_mantissa, (I64)) - HOOK_API_DEFINITION(I64, float_sign, (I64)) - HOOK_API_DEFINITION(I64, float_int, (I64, I32, I32)) - HOOK_API_DEFINITION(I64, float_log, (I64)) - HOOK_API_DEFINITION(I64, float_root, (I64, I32)) - HOOK_API_DEFINITION(I64, fee_base, ()) - HOOK_API_DEFINITION(I64, ledger_seq, ()) - HOOK_API_DEFINITION(I64, ledger_last_time, ()) - HOOK_API_DEFINITION(I64, ledger_last_hash, (I32, I32)) - HOOK_API_DEFINITION(I64, ledger_nonce, (I32, I32)) - HOOK_API_DEFINITION(I64, ledger_keylet, (I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, hook_account, (I32, I32)) - HOOK_API_DEFINITION(I64, hook_hash, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, hook_param_set, (I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, hook_param, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, hook_again, ()) - HOOK_API_DEFINITION(I64, hook_skip, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, hook_pos, ()) - HOOK_API_DEFINITION(I64, slot, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, slot_clear, (I32)) - HOOK_API_DEFINITION(I64, slot_count, (I32)) - HOOK_API_DEFINITION(I64, slot_set, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, slot_size, (I32)) - HOOK_API_DEFINITION(I64, slot_subarray, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, slot_subfield, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, slot_type, (I32, I32)) - HOOK_API_DEFINITION(I64, slot_float, (I32)) - HOOK_API_DEFINITION(I64, state_set, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, state_foreign_set, (I32, I32, I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, state, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, state_foreign, (I32, I32, I32, I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, trace, (I32, I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, trace_num, (I32, I32, I64)) - HOOK_API_DEFINITION(I64, trace_float, (I32, I32, I64)) - HOOK_API_DEFINITION(I64, otxn_burden, ()) - HOOK_API_DEFINITION(I64, otxn_field, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, otxn_generation, ()) - HOOK_API_DEFINITION(I64, otxn_id, (I32, I32, I32)) - HOOK_API_DEFINITION(I64, otxn_type, ()) - HOOK_API_DEFINITION(I64, otxn_slot, (I32)) - HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)) - HOOK_API_DEFINITION(I64, meta_slot, (I32)) - - #ifndef GUARD_CHECKER_BUILD - if (rules.enabled(featureHooksUpdate1)) - #endif - HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)) +#ifndef GUARD_CHECKER_BUILD + std::map amendments = {}; +#endif + +#pragma push_macro("HOOK_API_DEFINITION") +#undef HOOK_API_DEFINITION + +#define int64_t 0x7EU +#define int32_t 0x7FU +#define uint32_t 0x7FU + +#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ + +#ifdef GUARD_CHECKER_BUILD +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, ...) \ + whitelist[#FUNCTION_NAME] = {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}; +#else +#define HOOK_API_DEFINITION( \ + RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \ + if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \ + whitelist[#FUNCTION_NAME] = { \ + RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}; +#endif + +#include "hook_api.macro" + +#undef HOOK_API_DEFINITION +#undef HOOK_WRAP_PARAMS +#undef int64_t +#undef int32_t +#undef uint32_t +#pragma pop_macro("HOOK_API_DEFINITION") return whitelist; - // clang-format on } #undef HOOK_API_DEFINITION diff --git a/src/ripple/app/hook/Macro.h b/src/ripple/app/hook/Macro.h index 5f309b2e31..153677d4b3 100644 --- a/src/ripple/app/hook/Macro.h +++ b/src/ripple/app/hook/Macro.h @@ -88,18 +88,18 @@ #define WASM_VAL_TYPE(T, b) CAT2(TYP_, T) -#define DECLARE_HOOK_FUNCTION(R, F, ...) \ - R F(hook::HookContext& hookCtx, \ - WasmEdge_CallingFrameContext const& frameCtx, \ - __VA_ARGS__); \ - extern WasmEdge_Result WasmFunction##F( \ - void* data_ptr, \ - const WasmEdge_CallingFrameContext* frameCtx, \ - const WasmEdge_Value* in, \ - WasmEdge_Value* out); \ - extern WasmEdge_ValType WasmFunctionParams##F[]; \ - extern WasmEdge_ValType WasmFunctionResult##F[]; \ - extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \ +#define DECLARE_HOOK_FUNCTION(R, F, ...) \ + R F(hook::HookContext& hookCtx, \ + WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \ + , )##__VA_ARGS__); \ + extern WasmEdge_Result WasmFunction##F( \ + void* data_ptr, \ + const WasmEdge_CallingFrameContext* frameCtx, \ + const WasmEdge_Value* in, \ + WasmEdge_Value* out); \ + extern WasmEdge_ValType WasmFunctionParams##F[]; \ + extern WasmEdge_ValType WasmFunctionResult##F[]; \ + extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \ extern WasmEdge_String WasmFunctionName##F; #define DECLARE_HOOK_FUNCNARG(R, F) \ diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 2c1f250bbf..3fa02cbe63 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -61,365 +61,20 @@ namespace hook_api { if (HOOK_DBG) \ fprintf -DECLARE_HOOK_FUNCTION(int32_t, _g, uint32_t guard_id, uint32_t maxiter); - -DECLARE_HOOK_FUNCTION( - int64_t, - accept, - uint32_t read_ptr, - uint32_t read_len, - int64_t error_code); -DECLARE_HOOK_FUNCTION( - int64_t, - rollback, - uint32_t read_ptr, - uint32_t read_len, - int64_t error_code); - -DECLARE_HOOK_FUNCTION( - int64_t, - util_raddr, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCTION( - int64_t, - util_accid, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCTION( - int64_t, - util_verify, - uint32_t dread_ptr, - uint32_t dread_len, - uint32_t sread_ptr, - uint32_t sread_len, - uint32_t kread_ptr, - uint32_t kread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - util_sha512h, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCTION( - 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); - -DECLARE_HOOK_FUNCTION( - int64_t, - sto_validate, - uint32_t tread_ptr, - uint32_t tread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - sto_subfield, - uint32_t read_ptr, - uint32_t read_len, - uint32_t field_id); -DECLARE_HOOK_FUNCTION( - int64_t, - sto_subarray, - uint32_t read_ptr, - uint32_t read_len, - uint32_t array_id); -DECLARE_HOOK_FUNCTION( - int64_t, - sto_emplace, - uint32_t write_ptr, - uint32_t write_len, - uint32_t sread_ptr, - uint32_t sread_len, - uint32_t fread_ptr, - uint32_t fread_len, - uint32_t field_id); -DECLARE_HOOK_FUNCTION( - int64_t, - sto_erase, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len, - uint32_t field_id); - -DECLARE_HOOK_FUNCNARG(int64_t, etxn_burden); -DECLARE_HOOK_FUNCTION( - int64_t, - etxn_details, - uint32_t write_ptr, - uint32_t write_len); -DECLARE_HOOK_FUNCTION( - int64_t, - etxn_fee_base, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCTION(int64_t, etxn_reserve, uint32_t count); -DECLARE_HOOK_FUNCNARG(int64_t, etxn_generation); -DECLARE_HOOK_FUNCTION( - int64_t, - etxn_nonce, - uint32_t write_ptr, - uint32_t write_len); -DECLARE_HOOK_FUNCTION( - int64_t, - emit, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); - -DECLARE_HOOK_FUNCTION(int64_t, float_set, int32_t exponent, int64_t mantissa); -DECLARE_HOOK_FUNCTION(int64_t, float_multiply, int64_t float1, int64_t float2); -DECLARE_HOOK_FUNCTION( - int64_t, - float_mulratio, - int64_t float1, - uint32_t round_up, - uint32_t numerator, - uint32_t denominator); -DECLARE_HOOK_FUNCTION(int64_t, float_negate, int64_t float1); -DECLARE_HOOK_FUNCTION( - int64_t, - float_compare, - int64_t float1, - int64_t float2, - uint32_t mode); -DECLARE_HOOK_FUNCTION(int64_t, float_sum, int64_t float1, int64_t float2); -DECLARE_HOOK_FUNCTION( - int64_t, - float_sto, - uint32_t write_ptr, - uint32_t write_len, - uint32_t cread_ptr, - uint32_t cread_len, - uint32_t iread_ptr, - uint32_t iread_len, - int64_t float1, - uint32_t field_code); -DECLARE_HOOK_FUNCTION( - int64_t, - float_sto_set, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCTION(int64_t, float_invert, int64_t float1); -DECLARE_HOOK_FUNCTION(int64_t, float_divide, int64_t float1, int64_t float2); -DECLARE_HOOK_FUNCNARG(int64_t, float_one); -DECLARE_HOOK_FUNCTION(int64_t, float_mantissa, int64_t float1); -DECLARE_HOOK_FUNCTION(int64_t, float_sign, int64_t float1); -DECLARE_HOOK_FUNCTION( - int64_t, - float_int, - int64_t float1, - uint32_t decimal_places, - uint32_t abs); -DECLARE_HOOK_FUNCTION(int64_t, float_log, int64_t float1); -DECLARE_HOOK_FUNCTION(int64_t, float_root, int64_t float1, uint32_t n); - -DECLARE_HOOK_FUNCNARG(int64_t, fee_base); -DECLARE_HOOK_FUNCNARG(int64_t, ledger_seq); -DECLARE_HOOK_FUNCNARG(int64_t, ledger_last_time); -DECLARE_HOOK_FUNCTION( - int64_t, - ledger_last_hash, - uint32_t write_ptr, - uint32_t write_len); -DECLARE_HOOK_FUNCTION( - int64_t, - ledger_nonce, - uint32_t write_ptr, - uint32_t write_len); -DECLARE_HOOK_FUNCTION( - int64_t, - ledger_keylet, - uint32_t write_ptr, - uint32_t write_len, - uint32_t lread_ptr, - uint32_t lread_len, - uint32_t hread_ptr, - uint32_t hread_len); - -DECLARE_HOOK_FUNCTION( - int64_t, - hook_account, - uint32_t write_ptr, - uint32_t write_len); -DECLARE_HOOK_FUNCTION( - int64_t, - hook_hash, - uint32_t write_ptr, - uint32_t write_len, - int32_t hook_no); -DECLARE_HOOK_FUNCTION( - int64_t, - hook_param_set, - uint32_t read_ptr, - uint32_t read_len, - uint32_t kread_ptr, - uint32_t kread_len, - uint32_t hread_ptr, - uint32_t hread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - hook_param, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); -DECLARE_HOOK_FUNCNARG(int64_t, hook_again); -DECLARE_HOOK_FUNCTION( - int64_t, - hook_skip, - uint32_t read_ptr, - uint32_t read_len, - uint32_t flags); -DECLARE_HOOK_FUNCNARG(int64_t, hook_pos); - -DECLARE_HOOK_FUNCTION( - int64_t, - slot, - uint32_t write_ptr, - uint32_t write_len, - uint32_t slot); -DECLARE_HOOK_FUNCTION(int64_t, slot_clear, uint32_t slot); -DECLARE_HOOK_FUNCTION(int64_t, slot_count, uint32_t slot); -DECLARE_HOOK_FUNCTION( - int64_t, - slot_set, - uint32_t read_ptr, - uint32_t read_len, - uint32_t slot); -DECLARE_HOOK_FUNCTION(int64_t, slot_size, uint32_t slot); -DECLARE_HOOK_FUNCTION( - int64_t, - slot_subarray, - uint32_t parent_slot, - uint32_t array_id, - uint32_t new_slot); -DECLARE_HOOK_FUNCTION( - int64_t, - slot_subfield, - uint32_t parent_slot, - uint32_t field_id, - uint32_t new_slot); -DECLARE_HOOK_FUNCTION(int64_t, slot_type, uint32_t slot_no, uint32_t flags); -DECLARE_HOOK_FUNCTION(int64_t, slot_float, uint32_t slot_no); - -DECLARE_HOOK_FUNCTION( - int64_t, - state_set, - uint32_t read_ptr, - uint32_t read_len, - uint32_t kread_ptr, - uint32_t kread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - state_foreign_set, - uint32_t read_ptr, - uint32_t read_len, - uint32_t kread_ptr, - uint32_t kread_len, - uint32_t nread_ptr, - uint32_t nread_len, - uint32_t aread_ptr, - uint32_t aread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - state, - uint32_t write_ptr, - uint32_t write_len, - uint32_t kread_ptr, - uint32_t kread_len); -DECLARE_HOOK_FUNCTION( - int64_t, - state_foreign, - uint32_t write_ptr, - uint32_t write_len, - uint32_t kread_ptr, - uint32_t kread_len, - uint32_t nread_ptr, - uint32_t nread_len, - uint32_t aread_ptr, - uint32_t aread_len); - -DECLARE_HOOK_FUNCTION( - int64_t, - trace, - uint32_t mread_ptr, - uint32_t mread_len, - uint32_t dread_ptr, - uint32_t dread_len, - uint32_t as_hex); -DECLARE_HOOK_FUNCTION( - int64_t, - trace_num, - uint32_t read_ptr, - uint32_t read_len, - int64_t number); -DECLARE_HOOK_FUNCTION( - int64_t, - trace_float, - uint32_t read_ptr, - uint32_t read_len, - int64_t float1); - -DECLARE_HOOK_FUNCNARG(int64_t, otxn_burden); -DECLARE_HOOK_FUNCTION( - int64_t, - otxn_field, - uint32_t write_ptr, - uint32_t write_len, - uint32_t field_id); -DECLARE_HOOK_FUNCNARG(int64_t, otxn_generation); -DECLARE_HOOK_FUNCTION( - int64_t, - otxn_id, - uint32_t write_ptr, - uint32_t write_len, - uint32_t flags); -DECLARE_HOOK_FUNCNARG(int64_t, otxn_type); -DECLARE_HOOK_FUNCTION(int64_t, otxn_slot, uint32_t slot_no); -DECLARE_HOOK_FUNCTION( - int64_t, - otxn_param, - uint32_t write_ptr, - uint32_t write_len, - uint32_t read_ptr, - uint32_t read_len); - -DECLARE_HOOK_FUNCTION(int64_t, meta_slot, uint32_t slot_no); -DECLARE_HOOK_FUNCTION( - int64_t, - xpop_slot, - uint32_t slot_no_tx, - uint32_t slot_no_meta); - -/* - DECLARE_HOOK_FUNCTION(int64_t, str_find, uint32_t hread_ptr, - uint32_t hread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t mode, - uint32_t n); DECLARE_HOOK_FUNCTION(int64_t, str_replace, uint32_t - write_ptr, uint32_t write_len, uint32_t hread_ptr, uint32_t hread_len, - uint32_t nread_ptr, - uint32_t nread_len, uint32_t rread_ptr, uint32_t rread_len, uint32_t mode, - uint32_t n); DECLARE_HOOK_FUNCTION(int64_t, str_compare, uint32_t - fread_ptr, uint32_t fread_len, uint32_t sread_ptr, uint32_t sread_len, - uint32_t mode); - DECLARE_HOOK_FUNCTION(int64_t, str_concat, uint32_t write_ptr, - uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint64_t operand, - uint32_t operand_type); -*/ +#pragma push_macro("HOOK_API_DEFINITION") +#undef HOOK_API_DEFINITION + +#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, ...) \ + DECLARE_HOOK_FUNCTION( \ + RETURN_TYPE, FUNCTION_NAME, HOOK_WRAP_PARAMS PARAMS_TUPLE); + +#include + +#undef HOOK_API_DEFINITION +#undef HOOK_WRAP_PARAMS +#pragma pop_macro("HOOK_API_DEFINITION") + } /* end namespace hook_api */ namespace hook { @@ -792,97 +447,18 @@ class HookExecutor WasmEdge_LogSetDebugLevel(); - ADD_HOOK_FUNCTION(_g, ctx); - ADD_HOOK_FUNCTION(accept, ctx); - ADD_HOOK_FUNCTION(rollback, ctx); - ADD_HOOK_FUNCTION(util_raddr, ctx); - ADD_HOOK_FUNCTION(util_accid, ctx); - ADD_HOOK_FUNCTION(util_verify, ctx); - ADD_HOOK_FUNCTION(util_sha512h, ctx); - ADD_HOOK_FUNCTION(sto_validate, ctx); - ADD_HOOK_FUNCTION(sto_subfield, ctx); - ADD_HOOK_FUNCTION(sto_subarray, ctx); - ADD_HOOK_FUNCTION(sto_emplace, ctx); - ADD_HOOK_FUNCTION(sto_erase, ctx); - ADD_HOOK_FUNCTION(util_keylet, ctx); - - ADD_HOOK_FUNCTION(emit, ctx); - ADD_HOOK_FUNCTION(etxn_burden, ctx); - ADD_HOOK_FUNCTION(etxn_fee_base, ctx); - ADD_HOOK_FUNCTION(etxn_details, ctx); - ADD_HOOK_FUNCTION(etxn_reserve, ctx); - ADD_HOOK_FUNCTION(etxn_generation, ctx); - ADD_HOOK_FUNCTION(etxn_nonce, ctx); - - ADD_HOOK_FUNCTION(float_set, ctx); - ADD_HOOK_FUNCTION(float_multiply, ctx); - ADD_HOOK_FUNCTION(float_mulratio, ctx); - ADD_HOOK_FUNCTION(float_negate, ctx); - ADD_HOOK_FUNCTION(float_compare, ctx); - ADD_HOOK_FUNCTION(float_sum, ctx); - ADD_HOOK_FUNCTION(float_sto, ctx); - ADD_HOOK_FUNCTION(float_sto_set, ctx); - ADD_HOOK_FUNCTION(float_invert, ctx); - - ADD_HOOK_FUNCTION(float_divide, ctx); - ADD_HOOK_FUNCTION(float_one, ctx); - ADD_HOOK_FUNCTION(float_mantissa, ctx); - ADD_HOOK_FUNCTION(float_sign, ctx); - ADD_HOOK_FUNCTION(float_int, ctx); - ADD_HOOK_FUNCTION(float_log, ctx); - ADD_HOOK_FUNCTION(float_root, ctx); - - ADD_HOOK_FUNCTION(otxn_burden, ctx); - ADD_HOOK_FUNCTION(otxn_generation, ctx); - ADD_HOOK_FUNCTION(otxn_field, ctx); - ADD_HOOK_FUNCTION(otxn_id, ctx); - ADD_HOOK_FUNCTION(otxn_type, ctx); - ADD_HOOK_FUNCTION(otxn_slot, ctx); - ADD_HOOK_FUNCTION(otxn_param, ctx); - - ADD_HOOK_FUNCTION(hook_account, ctx); - ADD_HOOK_FUNCTION(hook_hash, ctx); - ADD_HOOK_FUNCTION(hook_again, ctx); - ADD_HOOK_FUNCTION(fee_base, ctx); - ADD_HOOK_FUNCTION(ledger_seq, ctx); - ADD_HOOK_FUNCTION(ledger_last_hash, ctx); - ADD_HOOK_FUNCTION(ledger_last_time, ctx); - ADD_HOOK_FUNCTION(ledger_nonce, ctx); - ADD_HOOK_FUNCTION(ledger_keylet, ctx); - - ADD_HOOK_FUNCTION(hook_param, ctx); - ADD_HOOK_FUNCTION(hook_param_set, ctx); - ADD_HOOK_FUNCTION(hook_skip, ctx); - ADD_HOOK_FUNCTION(hook_pos, ctx); - - ADD_HOOK_FUNCTION(state, ctx); - ADD_HOOK_FUNCTION(state_foreign, ctx); - ADD_HOOK_FUNCTION(state_set, ctx); - ADD_HOOK_FUNCTION(state_foreign_set, ctx); - - ADD_HOOK_FUNCTION(slot, ctx); - ADD_HOOK_FUNCTION(slot_clear, ctx); - ADD_HOOK_FUNCTION(slot_count, ctx); - ADD_HOOK_FUNCTION(slot_set, ctx); - ADD_HOOK_FUNCTION(slot_size, ctx); - ADD_HOOK_FUNCTION(slot_subarray, ctx); - ADD_HOOK_FUNCTION(slot_subfield, ctx); - ADD_HOOK_FUNCTION(slot_type, ctx); - ADD_HOOK_FUNCTION(slot_float, ctx); - - ADD_HOOK_FUNCTION(trace, ctx); - ADD_HOOK_FUNCTION(trace_num, ctx); - ADD_HOOK_FUNCTION(trace_float, ctx); - - ADD_HOOK_FUNCTION(meta_slot, ctx); - ADD_HOOK_FUNCTION(xpop_slot, ctx); - - /* - ADD_HOOK_FUNCTION(str_find, ctx); - ADD_HOOK_FUNCTION(str_replace, ctx); - ADD_HOOK_FUNCTION(str_compare, ctx); - ADD_HOOK_FUNCTION(str_concat, ctx); - */ +#pragma push_macro("HOOK_API_DEFINITION") +#undef HOOK_API_DEFINITION + +#define HOOK_WRAP_PARAMS(...) __VA_ARGS__ +#define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, ...) \ + ADD_HOOK_FUNCTION(FUNCTION_NAME, ctx); + +#include + +#undef HOOK_API_DEFINITION +#undef HOOK_WRAP_PARAMS +#pragma pop_macro("HOOK_API_DEFINITION") WasmEdge_TableInstanceContext* hostTable = WasmEdge_TableInstanceCreate(tableType); diff --git a/src/ripple/app/hook/hook_api.macro b/src/ripple/app/hook/hook_api.macro new file mode 100644 index 0000000000..fa9683e2af --- /dev/null +++ b/src/ripple/app/hook/hook_api.macro @@ -0,0 +1,221 @@ +// int32_t _g(uint32_t guard_id, uint32_t maxiter) +HOOK_API_DEFINITION(int32_t, _g, (uint32_t, uint32_t), uint256{}) + +// int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code) +HOOK_API_DEFINITION(int64_t, accept, (uint32_t, uint32_t, int64_t), uint256{}) + +// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code) +HOOK_API_DEFINITION(int64_t, rollback, (uint32_t, uint32_t, int64_t), uint256{}) + +// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len) +HOOK_API_DEFINITION(int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// 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) +HOOK_API_DEFINITION(int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len) +HOOK_API_DEFINITION(int64_t, sto_validate, (uint32_t, uint32_t), uint256{}) + +// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id) +HOOK_API_DEFINITION(int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id) +HOOK_API_DEFINITION(int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id) +HOOK_API_DEFINITION(int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id) +HOOK_API_DEFINITION(int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t etxn_burden() +HOOK_API_DEFINITION(int64_t, etxn_burden, (), uint256{}) + +// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len) +HOOK_API_DEFINITION(int64_t, etxn_details, (uint32_t, uint32_t), uint256{}) + +// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, etxn_fee_base, (uint32_t, uint32_t), uint256{}) + +// int64_t etxn_reserve(uint32_t count) +HOOK_API_DEFINITION(int64_t, etxn_reserve, (uint32_t), uint256{}) + +// int64_t etxn_generation() +HOOK_API_DEFINITION(int64_t, etxn_generation, (), uint256{}) + +// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len) +HOOK_API_DEFINITION(int64_t, etxn_nonce, (uint32_t, uint32_t), uint256{}) + +// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t float_set(int32_t exponent, int64_t mantissa) +HOOK_API_DEFINITION(int64_t, float_set, (int32_t, int64_t), uint256{}) + +// int64_t float_multiply(int64_t float1, int64_t float2) +HOOK_API_DEFINITION(int64_t, float_multiply, (int64_t, int64_t), uint256{}) + +// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator) +HOOK_API_DEFINITION(int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t float_negate(int64_t float1) +HOOK_API_DEFINITION(int64_t, float_negate, (int64_t), uint256{}) + +// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode) +HOOK_API_DEFINITION(int64_t, float_compare, (int64_t, int64_t, uint32_t), uint256{}) + +// int64_t float_sum(int64_t float1, int64_t float2) +HOOK_API_DEFINITION(int64_t, float_sum, (int64_t, int64_t), uint256{}) + +// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code) +HOOK_API_DEFINITION(int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t), uint256{}) + +// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, float_sto_set, (uint32_t, uint32_t), uint256{}) + +// int64_t float_invert(int64_t float1) +HOOK_API_DEFINITION(int64_t, float_invert, (int64_t), uint256{}) + +// int64_t float_divide(int64_t float1, int64_t float2) +HOOK_API_DEFINITION(int64_t, float_divide, (int64_t, int64_t), uint256{}) + +// int64_t float_one() +HOOK_API_DEFINITION(int64_t, float_one, (), uint256{}) + +// int64_t float_mantissa(int64_t float1) +HOOK_API_DEFINITION(int64_t, float_mantissa, (int64_t), uint256{}) + +// int64_t float_sign(int64_t float1) +HOOK_API_DEFINITION(int64_t, float_sign, (int64_t), uint256{}) + +// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs) +HOOK_API_DEFINITION(int64_t, float_int, (int64_t, uint32_t, uint32_t), uint256{}) + +// int64_t float_log(int64_t float1) +HOOK_API_DEFINITION(int64_t, float_log, (int64_t), uint256{}) + +// int64_t float_root(int64_t float1, uint32_t n) +HOOK_API_DEFINITION(int64_t, float_root, (int64_t, uint32_t), uint256{}) + +// int64_t fee_base() +HOOK_API_DEFINITION(int64_t, fee_base, (), uint256{}) + +// int64_t ledger_seq() +HOOK_API_DEFINITION(int64_t, ledger_seq, (), uint256{}) + +// int64_t ledger_last_time() +HOOK_API_DEFINITION(int64_t, ledger_last_time, (), uint256{}) + +// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len) +HOOK_API_DEFINITION(int64_t, ledger_last_hash, (uint32_t, uint32_t), uint256{}) + +// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len) +HOOK_API_DEFINITION(int64_t, ledger_nonce, (uint32_t, uint32_t), uint256{}) + +// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len) +HOOK_API_DEFINITION(int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t hook_account(uint32_t write_ptr, uint32_t write_len) +HOOK_API_DEFINITION(int64_t, hook_account, (uint32_t, uint32_t), uint256{}) + +// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no) +HOOK_API_DEFINITION(int64_t, hook_hash, (uint32_t, uint32_t, int32_t), uint256{}) + +// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len) +HOOK_API_DEFINITION(int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t hook_again() +HOOK_API_DEFINITION(int64_t, hook_again, (), uint256{}) + +// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags) +HOOK_API_DEFINITION(int64_t, hook_skip, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t hook_pos() +HOOK_API_DEFINITION(int64_t, hook_pos, (), uint256{}) + +// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot) +HOOK_API_DEFINITION(int64_t, slot, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t slot_clear(uint32_t slot) +HOOK_API_DEFINITION(int64_t, slot_clear, (uint32_t), uint256{}) + +// int64_t slot_count(uint32_t slot) +HOOK_API_DEFINITION(int64_t, slot_count, (uint32_t), uint256{}) + +// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot) +HOOK_API_DEFINITION(int64_t, slot_set, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t slot_size(uint32_t slot) +HOOK_API_DEFINITION(int64_t, slot_size, (uint32_t), uint256{}) + +// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot) +HOOK_API_DEFINITION(int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot) +HOOK_API_DEFINITION(int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t slot_type(uint32_t slot_no, uint32_t flags) +HOOK_API_DEFINITION(int64_t, slot_type, (uint32_t, uint32_t), uint256{}) + +// int64_t slot_float(uint32_t slot_no) +HOOK_API_DEFINITION(int64_t, slot_float, (uint32_t), uint256{}) + +// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len) +HOOK_API_DEFINITION(int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len) +HOOK_API_DEFINITION(int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len) +HOOK_API_DEFINITION(int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len) +HOOK_API_DEFINITION(int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex) +HOOK_API_DEFINITION(int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number) +HOOK_API_DEFINITION(int64_t, trace_num, (uint32_t, uint32_t, int64_t), uint256{}) + +// int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1) +HOOK_API_DEFINITION(int64_t, trace_float, (uint32_t, uint32_t, int64_t), uint256{}) + +// int64_t otxn_burden() +HOOK_API_DEFINITION(int64_t, otxn_burden, (), uint256{}) + +// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id) +HOOK_API_DEFINITION(int64_t, otxn_field, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t otxn_generation() +HOOK_API_DEFINITION(int64_t, otxn_generation, (), uint256{}) + +// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags) +HOOK_API_DEFINITION(int64_t, otxn_id, (uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t otxn_type() +HOOK_API_DEFINITION(int64_t, otxn_type, (), uint256{}) + +// int64_t otxn_slot(uint32_t slot_no) +HOOK_API_DEFINITION(int64_t, otxn_slot, (uint32_t), uint256{}) + +// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +HOOK_API_DEFINITION(int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) + +// int64_t meta_slot(uint32_t slot_no) +HOOK_API_DEFINITION(int64_t, meta_slot, (uint32_t), uint256{}) + +// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta) +HOOK_API_DEFINITION(int64_t, xpop_slot, (uint32_t, uint32_t), featureHooksUpdate1) From e92b99362a65c41b932651f7142195113b8521ba Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 31 Oct 2025 16:45:14 +0900 Subject: [PATCH 11/33] add `xpop_slot` test before featureHooksUpdate1 --- src/test/app/SetHook_test.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 3efe5c5c8c..29b0cc0b55 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -23,6 +23,8 @@ #include #include #include +#include "ripple/protocol/Feature.h" +#include "ripple/protocol/TER.h" #include #include #include @@ -6828,7 +6830,10 @@ class SetHook0_test : public beast::unit_test::suite std::vector const keys = { "ED74D4036C6591A4BDF9C54CEFA39B996A5DCE5F86D11FDA1874481CE9D5A1CDC" "1"}; - Env env{*this, network::makeNetworkVLConfig(21337, keys)}; + Env env{ + *this, + network::makeNetworkVLConfig(21337, keys), + features - featureHooksUpdate1}; auto const master = Account("masterpassphrase"); env(noop(master), fee(10'000'000'000), ter(tesSUCCESS)); @@ -6906,6 +6911,16 @@ class SetHook0_test : public beast::unit_test::suite } )[test.hook]"]; + // before featureHooksUpdate1 + env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), + M("set xpop_slot (disabled)"), + HSFEE, + ter(temMALFORMED)); + env.close(); + + env.enableFeature(featureHooksUpdate1); + env.close(); + // install the hook on alice env(ripple::test::jtx::hook(alice, {{hso(hook, overrideFlag)}}, 0), M("set xpop_slot"), From 047b7139f78ea11c19e1731a0dd5eca867459e3e Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 4 Nov 2025 14:01:37 +0900 Subject: [PATCH 12/33] update generate_extern.sh --- .../workflows/verify-generated-headers.yml | 9 ++ hook/extern.h | 22 +-- hook/generate_extern.sh | 140 +++-------------- src/ripple/app/hook/hook_api.macro | 148 +++++++++--------- 4 files changed, 120 insertions(+), 199 deletions(-) diff --git a/.github/workflows/verify-generated-headers.yml b/.github/workflows/verify-generated-headers.yml index 4120f7b7f9..ce4d382ed5 100644 --- a/.github/workflows/verify-generated-headers.yml +++ b/.github/workflows/verify-generated-headers.yml @@ -24,6 +24,15 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Download and install clang-format + run: | + sudo apt-get update -y + sudo apt-get install -y libtinfo5 + curl -LO https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.1/clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz + tar -xf clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04.tar.xz + sudo mv clang+llvm-10.0.1-x86_64-linux-gnu-ubuntu-16.04 /opt/clang-10 + sudo ln -s /opt/clang-10/bin/clang-format /usr/local/bin/clang-format-10 + - name: Verify ${{ matrix.target }} run: | set -euo pipefail diff --git a/hook/extern.h b/hook/extern.h index ee34af6ff8..667cec2a4c 100644 --- a/hook/extern.h +++ b/hook/extern.h @@ -82,7 +82,7 @@ sto_erase( uint32_t field_id); extern int64_t -etxn_burden(void); +etxn_burden(); extern int64_t etxn_details(uint32_t write_ptr, uint32_t write_len); @@ -94,7 +94,7 @@ extern int64_t etxn_reserve(uint32_t count); extern int64_t -etxn_generation(void); +etxn_generation(); extern int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len); @@ -149,7 +149,7 @@ extern int64_t float_divide(int64_t float1, int64_t float2); extern int64_t -float_one(void); +float_one(); extern int64_t float_mantissa(int64_t float1); @@ -167,13 +167,13 @@ extern int64_t float_root(int64_t float1, uint32_t n); extern int64_t -fee_base(void); +fee_base(); extern int64_t -ledger_seq(void); +ledger_seq(); extern int64_t -ledger_last_time(void); +ledger_last_time(); extern int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len); @@ -213,13 +213,13 @@ hook_param( uint32_t read_len); extern int64_t -hook_again(void); +hook_again(); extern int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); extern int64_t -hook_pos(void); +hook_pos(); extern int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); @@ -299,19 +299,19 @@ extern int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); extern int64_t -otxn_burden(void); +otxn_burden(); extern int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); extern int64_t -otxn_generation(void); +otxn_generation(); extern int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags); extern int64_t -otxn_type(void); +otxn_type(); extern int64_t otxn_slot(uint32_t slot_no); diff --git a/hook/generate_extern.sh b/hook/generate_extern.sh index 2e9598ad02..7a6a2f9ea1 100755 --- a/hook/generate_extern.sh +++ b/hook/generate_extern.sh @@ -4,7 +4,9 @@ set -eu SCRIPT_DIR=$(dirname "$0") SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) -APPLY_HOOK="$SCRIPT_DIR/../src/ripple/app/hook/applyHook.h" +APPLY_HOOK="$SCRIPT_DIR/../src/ripple/app/hook/hook_api.macro" +TMPFILE=$(mktemp) +TMPFILE=$(cd "$(dirname "$TMPFILE")" && pwd)/$(basename "$TMPFILE") { echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' @@ -19,127 +21,37 @@ APPLY_HOOK="$SCRIPT_DIR/../src/ripple/app/hook/applyHook.h" return s; } - function emit(ret, name, argc, argt, argn) { - attr = (name == "_g") ? " __attribute__((noduplicate))" : ""; - if (!first) - printf("\n"); - first = 0; - printf("extern %s%s\n", ret, attr); - if (argc == 0) { - printf("%s(void);\n", name); - return; - } - if (argc <= 3) { - line = argt[1] " " argn[1]; - for (i = 2; i <= argc; ++i) - line = line ", " argt[i] " " argn[i]; - printf("%s(%s);\n", name, line); - return; - } - printf("%s(\n", name); - for (i = 1; i <= argc; ++i) { - sep = (i < argc) ? "," : ");"; - printf(" %s %s%s\n", argt[i], argn[i], sep); - } - } - - function process(buffer, kind, payload, parts, n, i, arg, tokens, argc, argt, argn) { - if (kind == "func") - sub(/^DECLARE_HOOK_FUNCTION[[:space:]]*\(/, "", buffer); - else - sub(/^DECLARE_HOOK_FUNCNARG[[:space:]]*\(/, "", buffer); - buffer = trim(buffer); - sub(/\)[[:space:]]*$/, "", buffer); - n = split(buffer, parts, ","); - for (i = 1; i <= n; ++i) - parts[i] = trim(parts[i]); - ret = parts[1]; - name = parts[2]; - argc = 0; - delete argt; - delete argn; - for (i = 3; i <= n; ++i) { - arg = parts[i]; - if (arg == "") - continue; - split(arg, tokens, /[[:space:]]+/); - if (length(tokens) < 2) - continue; - ++argc; - argt[argc] = tokens[1]; - argn[argc] = tokens[2]; - } - emit(ret, name, argc, argt, argn); - } - - BEGIN { - first = 1; - in_block = 0; - in_macro = 0; - } - { line = $0; - if (in_block) { - if (line ~ /\*\//) { - sub(/.*\*\//, "", line); - in_block = 0; - } - else - next; - } - while (line ~ /\/\*/) { - if (line ~ /\/\*.*\*\//) { - gsub(/\/\*.*\*\//, "", line); - } - else { - sub(/\/\*.*/, "", line); - in_block = 1; - break; - } - } - sub(/\/\/.*$/, "", line); - line = trim(line); - if (line == "") - next; - - if (!in_macro && line ~ /^DECLARE_HOOK_FUNCTION\(/) { - buffer = line; - kind = "func"; - if (line ~ /\);[[:space:]]*$/) { - sub(/\);[[:space:]]*$/, "", buffer); - process(buffer, kind); - } - else - in_macro = 1; + + # Skip block comments + if (line ~ /\/\*/) { next; } - if (!in_macro && line ~ /^DECLARE_HOOK_FUNCNARG\(/) { - buffer = line; - kind = "narg"; - if (line ~ /\);[[:space:]]*$/) { - sub(/\);[[:space:]]*$/, "", buffer); - process(buffer, kind); - } - else - in_macro = 1; - next; - } - if (in_macro) { - buffer = buffer " " line; - if (line ~ /\);[[:space:]]*$/) { - sub(/\);[[:space:]]*$/, "", buffer); - process(buffer, kind); - in_macro = 0; + + # Look for comment lines that start with // and contain function signature + if (line ~ /^[[:space:]]*\/\/[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]+[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\(/) { + # Remove leading // and trim + sub(/^[[:space:]]*\/\/[[:space:]]*/, "", line); + line = trim(line); + + # Check if function name is "_g" to add attribute + if (line ~ /[[:space:]]+_g[[:space:]]*\(/) { + # Insert __attribute__((noduplicate)) before _g + sub(/[[:space:]]+_g/, " __attribute__((noduplicate)) _g", line); } + + # printf("\n"); + + printf("extern %s\n\n", line); } } - - END { - printf("\n"); - } ' "$APPLY_HOOK" echo '#define HOOK_EXTERN' echo '#endif // HOOK_EXTERN' -} +} > "$TMPFILE" + +cd "$SCRIPT_DIR/.." +clang-format --style=file "$TMPFILE" +rm "$TMPFILE" diff --git a/src/ripple/app/hook/hook_api.macro b/src/ripple/app/hook/hook_api.macro index fa9683e2af..d0d479a547 100644 --- a/src/ripple/app/hook/hook_api.macro +++ b/src/ripple/app/hook/hook_api.macro @@ -1,221 +1,221 @@ -// int32_t _g(uint32_t guard_id, uint32_t maxiter) +// int32_t _g(uint32_t guard_id, uint32_t maxiter); HOOK_API_DEFINITION(int32_t, _g, (uint32_t, uint32_t), uint256{}) -// int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code) +// int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code); HOOK_API_DEFINITION(int64_t, accept, (uint32_t, uint32_t, int64_t), uint256{}) -// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code) +// int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code); HOOK_API_DEFINITION(int64_t, rollback, (uint32_t, uint32_t, int64_t), uint256{}) -// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len) +// int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION(int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// 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) +// 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); HOOK_API_DEFINITION(int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len) +// int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len); HOOK_API_DEFINITION(int64_t, sto_validate, (uint32_t, uint32_t), uint256{}) -// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id) +// int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id); HOOK_API_DEFINITION(int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id) +// int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id); HOOK_API_DEFINITION(int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id) +// int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id); HOOK_API_DEFINITION(int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id) +// int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id); HOOK_API_DEFINITION(int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t etxn_burden() +// int64_t etxn_burden(); HOOK_API_DEFINITION(int64_t, etxn_burden, (), uint256{}) -// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len) +// int64_t etxn_details(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION(int64_t, etxn_details, (uint32_t, uint32_t), uint256{}) -// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len) +// int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, etxn_fee_base, (uint32_t, uint32_t), uint256{}) -// int64_t etxn_reserve(uint32_t count) +// int64_t etxn_reserve(uint32_t count); HOOK_API_DEFINITION(int64_t, etxn_reserve, (uint32_t), uint256{}) -// int64_t etxn_generation() +// int64_t etxn_generation(); HOOK_API_DEFINITION(int64_t, etxn_generation, (), uint256{}) -// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len) +// int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION(int64_t, etxn_nonce, (uint32_t, uint32_t), uint256{}) -// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t float_set(int32_t exponent, int64_t mantissa) +// int64_t float_set(int32_t exponent, int64_t mantissa); HOOK_API_DEFINITION(int64_t, float_set, (int32_t, int64_t), uint256{}) -// int64_t float_multiply(int64_t float1, int64_t float2) +// int64_t float_multiply(int64_t float1, int64_t float2); HOOK_API_DEFINITION(int64_t, float_multiply, (int64_t, int64_t), uint256{}) -// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator) +// int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator); HOOK_API_DEFINITION(int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t float_negate(int64_t float1) +// int64_t float_negate(int64_t float1); HOOK_API_DEFINITION(int64_t, float_negate, (int64_t), uint256{}) -// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode) +// int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode); HOOK_API_DEFINITION(int64_t, float_compare, (int64_t, int64_t, uint32_t), uint256{}) -// int64_t float_sum(int64_t float1, int64_t float2) +// int64_t float_sum(int64_t float1, int64_t float2); HOOK_API_DEFINITION(int64_t, float_sum, (int64_t, int64_t), uint256{}) -// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code) +// int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code); HOOK_API_DEFINITION(int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t), uint256{}) -// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len) +// int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, float_sto_set, (uint32_t, uint32_t), uint256{}) -// int64_t float_invert(int64_t float1) +// int64_t float_invert(int64_t float1); HOOK_API_DEFINITION(int64_t, float_invert, (int64_t), uint256{}) -// int64_t float_divide(int64_t float1, int64_t float2) +// int64_t float_divide(int64_t float1, int64_t float2); HOOK_API_DEFINITION(int64_t, float_divide, (int64_t, int64_t), uint256{}) -// int64_t float_one() +// int64_t float_one(); HOOK_API_DEFINITION(int64_t, float_one, (), uint256{}) -// int64_t float_mantissa(int64_t float1) +// int64_t float_mantissa(int64_t float1); HOOK_API_DEFINITION(int64_t, float_mantissa, (int64_t), uint256{}) -// int64_t float_sign(int64_t float1) +// int64_t float_sign(int64_t float1); HOOK_API_DEFINITION(int64_t, float_sign, (int64_t), uint256{}) -// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs) +// int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs); HOOK_API_DEFINITION(int64_t, float_int, (int64_t, uint32_t, uint32_t), uint256{}) -// int64_t float_log(int64_t float1) +// int64_t float_log(int64_t float1); HOOK_API_DEFINITION(int64_t, float_log, (int64_t), uint256{}) -// int64_t float_root(int64_t float1, uint32_t n) +// int64_t float_root(int64_t float1, uint32_t n); HOOK_API_DEFINITION(int64_t, float_root, (int64_t, uint32_t), uint256{}) -// int64_t fee_base() +// int64_t fee_base(); HOOK_API_DEFINITION(int64_t, fee_base, (), uint256{}) -// int64_t ledger_seq() +// int64_t ledger_seq(); HOOK_API_DEFINITION(int64_t, ledger_seq, (), uint256{}) -// int64_t ledger_last_time() +// int64_t ledger_last_time(); HOOK_API_DEFINITION(int64_t, ledger_last_time, (), uint256{}) -// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len) +// int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION(int64_t, ledger_last_hash, (uint32_t, uint32_t), uint256{}) -// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len) +// int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION(int64_t, ledger_nonce, (uint32_t, uint32_t), uint256{}) -// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len) +// int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len); HOOK_API_DEFINITION(int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t hook_account(uint32_t write_ptr, uint32_t write_len) +// int64_t hook_account(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION(int64_t, hook_account, (uint32_t, uint32_t), uint256{}) -// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no) +// int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no); HOOK_API_DEFINITION(int64_t, hook_hash, (uint32_t, uint32_t, int32_t), uint256{}) -// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len) +// int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len); HOOK_API_DEFINITION(int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t hook_again() +// int64_t hook_again(); HOOK_API_DEFINITION(int64_t, hook_again, (), uint256{}) -// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags) +// int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); HOOK_API_DEFINITION(int64_t, hook_skip, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t hook_pos() +// int64_t hook_pos(); HOOK_API_DEFINITION(int64_t, hook_pos, (), uint256{}) -// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot) +// int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); HOOK_API_DEFINITION(int64_t, slot, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t slot_clear(uint32_t slot) +// int64_t slot_clear(uint32_t slot); HOOK_API_DEFINITION(int64_t, slot_clear, (uint32_t), uint256{}) -// int64_t slot_count(uint32_t slot) +// int64_t slot_count(uint32_t slot); HOOK_API_DEFINITION(int64_t, slot_count, (uint32_t), uint256{}) -// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot) +// int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot); HOOK_API_DEFINITION(int64_t, slot_set, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t slot_size(uint32_t slot) +// int64_t slot_size(uint32_t slot); HOOK_API_DEFINITION(int64_t, slot_size, (uint32_t), uint256{}) -// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot) +// int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot); HOOK_API_DEFINITION(int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot) +// int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot); HOOK_API_DEFINITION(int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t slot_type(uint32_t slot_no, uint32_t flags) +// int64_t slot_type(uint32_t slot_no, uint32_t flags); HOOK_API_DEFINITION(int64_t, slot_type, (uint32_t, uint32_t), uint256{}) -// int64_t slot_float(uint32_t slot_no) +// int64_t slot_float(uint32_t slot_no); HOOK_API_DEFINITION(int64_t, slot_float, (uint32_t), uint256{}) -// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len) +// int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION(int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len) +// int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); HOOK_API_DEFINITION(int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len) +// int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION(int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len) +// int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); HOOK_API_DEFINITION(int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex) +// int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex); HOOK_API_DEFINITION(int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number) +// int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number); HOOK_API_DEFINITION(int64_t, trace_num, (uint32_t, uint32_t, int64_t), uint256{}) -// int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1) +// int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); HOOK_API_DEFINITION(int64_t, trace_float, (uint32_t, uint32_t, int64_t), uint256{}) -// int64_t otxn_burden() +// int64_t otxn_burden(); HOOK_API_DEFINITION(int64_t, otxn_burden, (), uint256{}) -// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id) +// int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); HOOK_API_DEFINITION(int64_t, otxn_field, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t otxn_generation() +// int64_t otxn_generation(); HOOK_API_DEFINITION(int64_t, otxn_generation, (), uint256{}) -// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags) +// int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags); HOOK_API_DEFINITION(int64_t, otxn_id, (uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t otxn_type() +// int64_t otxn_type(); HOOK_API_DEFINITION(int64_t, otxn_type, (), uint256{}) -// int64_t otxn_slot(uint32_t slot_no) +// int64_t otxn_slot(uint32_t slot_no); HOOK_API_DEFINITION(int64_t, otxn_slot, (uint32_t), uint256{}) -// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len) +// int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION(int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) -// int64_t meta_slot(uint32_t slot_no) +// int64_t meta_slot(uint32_t slot_no); HOOK_API_DEFINITION(int64_t, meta_slot, (uint32_t), uint256{}) -// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta) +// int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta); HOOK_API_DEFINITION(int64_t, xpop_slot, (uint32_t, uint32_t), featureHooksUpdate1) From 0955ab28ac70e967aa69a31aa33445f171871e9d Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 4 Nov 2025 14:50:21 +0900 Subject: [PATCH 13/33] fix workflow --- .github/workflows/verify-generated-headers.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/verify-generated-headers.yml b/.github/workflows/verify-generated-headers.yml index ce4d382ed5..723e7181b9 100644 --- a/.github/workflows/verify-generated-headers.yml +++ b/.github/workflows/verify-generated-headers.yml @@ -18,7 +18,9 @@ jobs: generator: bash ./hook/generate_sfcodes.sh - target: hook/tts.h generator: ./hook/generate_tts.sh - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 + env: + CLANG_VERSION: 10 name: ${{ matrix.target }} steps: - name: Checkout repository From cdf3008d9dd4ca23c2559ede4cfdbfdca5e03412 Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 4 Nov 2025 14:59:15 +0900 Subject: [PATCH 14/33] fix script --- hook/generate_extern.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/hook/generate_extern.sh b/hook/generate_extern.sh index 7a6a2f9ea1..0f05dac523 100755 --- a/hook/generate_extern.sh +++ b/hook/generate_extern.sh @@ -5,8 +5,6 @@ SCRIPT_DIR=$(dirname "$0") SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) APPLY_HOOK="$SCRIPT_DIR/../src/ripple/app/hook/hook_api.macro" -TMPFILE=$(mktemp) -TMPFILE=$(cd "$(dirname "$TMPFILE")" && pwd)/$(basename "$TMPFILE") { echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' @@ -50,8 +48,7 @@ TMPFILE=$(cd "$(dirname "$TMPFILE")" && pwd)/$(basename "$TMPFILE") echo '#define HOOK_EXTERN' echo '#endif // HOOK_EXTERN' -} > "$TMPFILE" - -cd "$SCRIPT_DIR/.." -clang-format --style=file "$TMPFILE" -rm "$TMPFILE" +} | ( + cd "$SCRIPT_DIR/.." + clang-format --style=file - +) From 5e60bdfbaf1d9aad8eb1b12f1db84d82363115d1 Mon Sep 17 00:00:00 2001 From: tequ Date: Wed, 5 Nov 2025 13:21:49 +0900 Subject: [PATCH 15/33] fix --- src/test/app/SetHook_test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 29b0cc0b55..55f5dcebef 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -23,8 +23,6 @@ #include #include #include -#include "ripple/protocol/Feature.h" -#include "ripple/protocol/TER.h" #include #include #include From a28baff8e9b304ac25b86ae509c233130644c1f0 Mon Sep 17 00:00:00 2001 From: tequ Date: Sat, 8 Nov 2025 12:23:20 +0900 Subject: [PATCH 16/33] Use HookCost field and add `HookDefinitionUpdate` transaction to re-execute guard-checker --- Builds/CMake/RippledCore.cmake | 1 + src/ripple/app/hook/applyHook.h | 11 +- src/ripple/app/hook/impl/applyHook.cpp | 86 ++++++++++-- .../app/tx/impl/HookDefinitionUpdate.cpp | 123 ++++++++++++++++++ src/ripple/app/tx/impl/HookDefinitionUpdate.h | 53 ++++++++ src/ripple/app/tx/impl/SetHook.cpp | 85 +++--------- src/ripple/app/tx/impl/Transactor.cpp | 102 +++++++++++---- src/ripple/app/tx/impl/Transactor.h | 2 +- src/ripple/app/tx/impl/applySteps.cpp | 11 ++ src/ripple/protocol/SField.h | 2 + src/ripple/protocol/TxFormats.h | 3 + src/ripple/protocol/impl/LedgerFormats.cpp | 6 +- src/ripple/protocol/impl/SField.cpp | 2 + src/ripple/protocol/impl/TxFormats.cpp | 7 + src/ripple/protocol/jss.h | 31 ++--- src/test/app/SetHook_test.cpp | 14 +- 16 files changed, 413 insertions(+), 126 deletions(-) create mode 100644 src/ripple/app/tx/impl/HookDefinitionUpdate.cpp create mode 100644 src/ripple/app/tx/impl/HookDefinitionUpdate.h diff --git a/Builds/CMake/RippledCore.cmake b/Builds/CMake/RippledCore.cmake index 6830323661..92d3d7f6f3 100644 --- a/Builds/CMake/RippledCore.cmake +++ b/Builds/CMake/RippledCore.cmake @@ -463,6 +463,7 @@ target_sources (rippled PRIVATE src/ripple/app/tx/impl/DepositPreauth.cpp src/ripple/app/tx/impl/Escrow.cpp src/ripple/app/tx/impl/GenesisMint.cpp + src/ripple/app/tx/impl/HookDefinitionUpdate.cpp src/ripple/app/tx/impl/Import.cpp src/ripple/app/tx/impl/InvariantCheck.cpp src/ripple/app/tx/impl/Invoke.cpp diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 2054b30134..7a64a24a42 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -128,8 +128,15 @@ computeCreationFee(uint64_t byteCount); constexpr uint32_t MICRO_DROPS_PER_DROP{1'000'000}; -std::pair -computeHookInstructionCosts(std::pair const&, Rules const&); +XRPAmount +hookCostToFee(uint64_t hookCost); + +std::optional> +doValidateGuards( + STTx const& tx, + Blob const& wasm, + Rules const& rules, + beast::Journal const& j); struct HookResult { diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 4142c4974c..124b5565c1 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -920,22 +921,83 @@ hook::computeCreationFee(uint64_t byteCount) return fee; } -std::pair -hook::computeHookInstructionCosts( - std::pair const& instrCounts, - Rules const& rules) +XRPAmount +hook::hookCostToFee(uint64_t hookCost) { - if (!rules.enabled(featureHookFeeV2)) - return instrCounts; + XRPAmount fee{0}; + // TODO: TEQU should be voted by validators like reserve + auto const GAS_PRICE = 100'000; + double const gas_cost = + double(GAS_PRICE) / double(hook::MICRO_DROPS_PER_DROP); + fee = uint64_t(hookCost * gas_cost); + return fee; +} - auto const GAS_PRICE = - 100'000; // TODO: should be voted by validators like reserve +std::optional> +hook::doValidateGuards( + STTx const& tx, + Blob const& wasm, + Rules const& rules, + beast::Journal const& j) +{ + // RH NOTE: validateGuards has a generic non-rippled specific + // interface so it can be used in other projects (i.e. tooling). + // As such the calling here is a bit convoluted. + + std::optional>> logger; + std::ostringstream loggerStream; + std::string hsacc{""}; + if (j.trace()) + { + logger = loggerStream; + std::stringstream ss; + +#define HS_ACC() tx.getAccountID(sfAccount) << "-" << tx.getTransactionID() + ss << HS_ACC(); +#undef HS_ACC + hsacc = ss.str(); + } + + auto result = validateGuards( + wasm, // wasm to verify + logger, + hsacc, + rules.enabled(featureHookFeeV2), + hook_api::getImportWhitelist(rules), + hook_api::getGuardRulesVersion(rules)); + + if (j.trace()) + { + // clunky but to get the stream to accept the output + // correctly we will split on new line and feed each line + // one by one into the trace stream beast::Journal should be + // updated to inherit from basic_ostream then this + // wouldn't be necessary. + + // is this a needless copy or does the compiler do copy + // elision here? + std::string s = loggerStream.str(); + + char* data = s.data(); + size_t len = s.size(); + + char* last = data; + size_t i = 0; + for (; i < len; ++i) + { + if (data[i] == '\n') + { + data[i] = '\0'; + j.trace() << last; + last = data + i; + } + } - double const gas_cost = double(GAS_PRICE) / double(MICRO_DROPS_PER_DROP); + if (last < data + i) + j.trace() << last; + } - return { - uint64_t(instrCounts.first * gas_cost), - uint64_t(instrCounts.second * gas_cost)}; + return result; } // many datatypes can be encoded into an int64_t diff --git a/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp new file mode 100644 index 0000000000..c7c97d8c23 --- /dev/null +++ b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp @@ -0,0 +1,123 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 XRPL-Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ripple/protocol/SField.h" +#include "ripple/protocol/TER.h" + +namespace ripple { + +NotTEC +HookDefinitionUpdate::preflight(PreflightContext const& ctx) +{ + if (!ctx.rules.enabled(featureHookFeeV2)) + return temDISABLED; + + auto const& tx = ctx.tx; + auto const& j = ctx.j; + + if (auto const ret = preflight1(ctx); !isTesSuccess(ret)) + return ret; + + // TODO: check flags + + return preflight2(ctx); +} + +TER +HookDefinitionUpdate::preclaim(PreclaimContext const& ctx) +{ + auto const& view = ctx.view; + auto const& tx = ctx.tx; + + auto exists = + view.exists(keylet::hookDefinition(tx.getFieldH256(sfHookHash))); + if (!exists) + return tecNO_ENTRY; + + return tesSUCCESS; +} + +TER +HookDefinitionUpdate::doApply() +{ + auto& view = ctx_.view(); + auto const& tx = ctx_.tx; + + auto hookDefSle = + view.peek(keylet::hookDefinition(tx.getFieldH256(sfHookHash))); + if (!hookDefSle) + return tefINTERNAL; + + Blob hook = hookDefSle->getFieldVL(sfCreateCode); + + auto const result = + hook::doValidateGuards(tx, hook, view.rules(), ctx_.journal); + if (!result) + return tecINTERNAL; + + auto const [hookCost, callbackCost] = *result; + + { + // if result is same as old, don't update sle + if (hookCost == hookDefSle->getFieldU64(sfHookCost) && + callbackCost == hookDefSle->getFieldU64(sfHookCallbackCost)) + return tesSUCCESS; + } + + { + // set new cost fields + hookDefSle->setFieldU64(sfHookCost, hookCost); + if (callbackCost > 0) + hookDefSle->setFieldU64(sfHookCallbackCost, callbackCost); + else if (hookDefSle->isFieldPresent(sfHookCallbackCost)) + hookDefSle->makeFieldAbsent(sfHookCallbackCost); + } + + { + // remove old fee fields + if (hookDefSle->isFieldPresent(sfFee)) + hookDefSle->makeFieldAbsent(sfFee); + if (hookDefSle->isFieldPresent(sfHookCallbackFee)) + hookDefSle->makeFieldAbsent(sfHookCallbackFee); + } + + view.update(hookDefSle); + + return tesSUCCESS; +} + +XRPAmount +HookDefinitionUpdate::calculateBaseFee(ReadView const& view, STTx const& tx) +{ + auto const baseFee = Transactor::calculateBaseFee(view, tx); + + // TODO: add a cost based on the size of the hook code? + + return baseFee; +} + +} // namespace ripple diff --git a/src/ripple/app/tx/impl/HookDefinitionUpdate.h b/src/ripple/app/tx/impl/HookDefinitionUpdate.h new file mode 100644 index 0000000000..f7b265cfa9 --- /dev/null +++ b/src/ripple/app/tx/impl/HookDefinitionUpdate.h @@ -0,0 +1,53 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2025 XRPL-Labs + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef RIPPLE_TX_HOOKDEFINITIONUPDATE_H_INCLUDED +#define RIPPLE_TX_HOOKDEFINITIONUPDATE_H_INCLUDED + +#include +#include +#include + +namespace ripple { + +class HookDefinitionUpdate : public Transactor +{ +public: + static constexpr ConsequencesFactoryType ConsequencesFactory{Normal}; + + explicit HookDefinitionUpdate(ApplyContext& ctx) : Transactor(ctx) + { + } + + static XRPAmount + calculateBaseFee(ReadView const& view, STTx const& tx); + + static NotTEC + preflight(PreflightContext const& ctx); + + static TER + preclaim(PreclaimContext const&); + + TER + doApply() override; +}; + +} // namespace ripple + +#endif diff --git a/src/ripple/app/tx/impl/SetHook.cpp b/src/ripple/app/tx/impl/SetHook.cpp index c91bfe74d6..51007ba598 100644 --- a/src/ripple/app/tx/impl/SetHook.cpp +++ b/src/ripple/app/tx/impl/SetHook.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -470,60 +469,8 @@ SetHook::validateHookSetEntry(SetHookCtx& ctx, STObject const& hookSetObj) Blob hook = hookSetObj.getFieldVL(sfCreateCode); - // RH NOTE: validateGuards has a generic non-rippled specific - // interface so it can be used in other projects (i.e. tooling). - // As such the calling here is a bit convoluted. - - std::optional>> - logger; - std::ostringstream loggerStream; - std::string hsacc{""}; - if (ctx.j.trace()) - { - logger = loggerStream; - std::stringstream ss; - ss << HS_ACC(); - hsacc = ss.str(); - } - - auto result = validateGuards( - hook, // wasm to verify - logger, - hsacc, - ctx.rules.enabled(featureHookFeeV2), - hook_api::getImportWhitelist(ctx.rules), - hook_api::getGuardRulesVersion(ctx.rules)); - - if (ctx.j.trace()) - { - // clunky but to get the stream to accept the output - // correctly we will split on new line and feed each line - // one by one into the trace stream beast::Journal should be - // updated to inherit from basic_ostream then this - // wouldn't be necessary. - - // is this a needless copy or does the compiler do copy - // elision here? - std::string s = loggerStream.str(); - - char* data = s.data(); - size_t len = s.size(); - - char* last = data; - size_t i = 0; - for (; i < len; ++i) - { - if (data[i] == '\n') - { - data[i] = '\0'; - ctx.j.trace() << last; - last = data + i; - } - } - - if (last < data + i) - ctx.j.trace() << last; - } + auto const result = + hook::doValidateGuards(ctx.tx, hook, ctx.rules, ctx.j); if (!result) return false; @@ -1642,8 +1589,7 @@ SetHook::setHook() std::get>(valid); std::tie(maxInstrCountHook, maxInstrCountCbak) = - hook::computeHookInstructionCosts( - instrCounts, ctx.rules); + instrCounts; } catch (std::exception& e) { @@ -1684,15 +1630,26 @@ SetHook::setHook() newHookDef->setFieldH256( sfHookSetTxnID, ctx.tx.getTransactionID()); newHookDef->setFieldU64(sfReferenceCount, 1); - newHookDef->setFieldAmount( - sfFee, - XRPAmount{ - hook::computeExecutionFee(maxInstrCountHook)}); - if (maxInstrCountCbak > 0) + + if (view().rules().enabled(featureHookFeeV2)) + { + newHookDef->setFieldU64(sfHookCost, maxInstrCountHook); + if (maxInstrCountCbak > 0) + newHookDef->setFieldU64( + sfHookCallbackCost, maxInstrCountCbak); + } + else + { newHookDef->setFieldAmount( - sfHookCallbackFee, + sfFee, XRPAmount{ - hook::computeExecutionFee(maxInstrCountCbak)}); + hook::computeExecutionFee(maxInstrCountHook)}); + if (maxInstrCountCbak > 0) + newHookDef->setFieldAmount( + sfHookCallbackFee, + XRPAmount{hook::computeExecutionFee( + maxInstrCountCbak)}); + } if (flags) newHookDef->setFieldU32(sfFlags, newFlags); diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 75a26747da..69d5b9893a 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -207,7 +207,7 @@ Transactor::Transactor(ApplyContext& ctx) // RH NOTE: this only computes one chain at a time, so if there is a receiving // side to a txn then it must seperately be computed by a second call here -XRPAmount +std::pair Transactor::calculateHookChainFee( ReadView const& view, STTx const& tx, @@ -216,9 +216,10 @@ Transactor::calculateHookChainFee( { std::shared_ptr hookSLE = view.read(hookKeylet); if (!hookSLE) - return XRPAmount{0}; + return std::make_pair(XRPAmount{0}, 0); XRPAmount fee{0}; + uint64_t hookCost{0}; auto const& hooks = hookSLE->getFieldArray(sfHooks); @@ -255,19 +256,35 @@ Transactor::calculateHookChainFee( if (hook::canHook(tx.getTxnType(), hookOn) && (!collectCallsOnly || (flags & hook::hsfCOLLECT))) { - XRPAmount const toAdd{hookDef->getFieldAmount(sfFee).xrp().drops()}; + if (hookDef->isFieldPresent(sfFee)) + { + XRPAmount const toAdd{ + hookDef->getFieldAmount(sfFee).xrp().drops()}; - // this overflow should never happen, if somehow it does - // fee is set to the largest possible valid xrp value to force - // fail the transaction - if (fee + toAdd < fee) - fee = XRPAmount{INITIAL_XRP.drops()}; + // this overflow should never happen, if somehow it does + // fee is set to the largest possible valid xrp value to force + // fail the transaction + if (fee + toAdd < fee) + fee = XRPAmount{INITIAL_XRP.drops()}; + else + fee += toAdd; + } else - fee += toAdd; + { + uint64_t const toAdd{hookDef->getFieldU64(sfHookCost)}; + + // this overflow should never happen, if somehow it does + // fee is set to the largest possible valid xrp value to force + // fail the transaction + if (hookCost + toAdd < hookCost) + hookCost = std::numeric_limits::max(); + else + hookCost += toAdd; + } } } - return fee; + return std::make_pair(fee, hookCost); } XRPAmount @@ -293,6 +310,7 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) tx.isFieldPresent(sfSigners) ? tx.getFieldArray(sfSigners).size() : 0; XRPAmount hookExecutionFee{0}; + uint64_t hookCost{0}; uint64_t burden{1}; if (view.rules().enabled(featureHooks)) { @@ -315,18 +333,32 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) std::shared_ptr hookDef = view.read(keylet::hookDefinition(callbackHookHash)); - if (hookDef && hookDef->isFieldPresent(sfHookCallbackFee)) + if (hookDef) { - XRPAmount const toAdd{ - hookDef->getFieldAmount(sfHookCallbackFee).xrp().drops()}; - - // this overflow should never happen, if somehow it does - // fee is set to the largest possible valid xrp value to force - // fail the transaction - if (hookExecutionFee + toAdd < hookExecutionFee) - hookExecutionFee = XRPAmount{INITIAL_XRP.drops()}; - else - hookExecutionFee += toAdd; + if (hookDef->isFieldPresent(sfHookCallbackFee)) + { + XRPAmount const toAdd{ + hookDef->getFieldAmount(sfHookCallbackFee) + .xrp() + .drops()}; + + // this overflow should never happen, if somehow it does + // fee is set to the largest possible valid xrp value to + // force fail the transaction + if (hookExecutionFee + toAdd < hookExecutionFee) + hookExecutionFee = XRPAmount{INITIAL_XRP.drops()}; + else + hookExecutionFee += toAdd; + } + if (hookDef->isFieldPresent(sfHookCallbackCost)) + { + uint64_t const toAdd{ + hookDef->getFieldU64(sfHookCallbackCost)}; + if (hookCost + toAdd < hookCost) + hookCost = std::numeric_limits::max(); + else + hookCost += toAdd; + } } assert(emitDetails.isFieldPresent(sfEmitBurden)); @@ -334,8 +366,12 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) burden = emitDetails.getFieldU64(sfEmitBurden); } else - hookExecutionFee += calculateHookChainFee( + { + auto const hookChainFee = calculateHookChainFee( view, tx, keylet::hook(tx.getAccountID(sfAccount))); + hookExecutionFee += hookChainFee.first; + hookCost += hookChainFee.second; + } // find any additional stakeholders whose hooks will be executed and // charged to this transaction @@ -344,8 +380,12 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) for (auto& [tshAcc, canRollback] : tsh) if (canRollback) - hookExecutionFee += + { + auto const hookChainFee = calculateHookChainFee(view, tx, keylet::hook(tshAcc)); + hookExecutionFee += hookChainFee.first; + hookCost += hookChainFee.second; + } } XRPAmount accumulator = baseFee; @@ -399,6 +439,8 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) // transaction. do { + hookExecutionFee += hook::hookCostToFee(hookCost); + if (accumulator * burden < accumulator) break; @@ -1260,7 +1302,8 @@ Transactor::executeHookChain( return tecINTERNAL; } - bool hasCallback = hookDef->isFieldPresent(sfHookCallbackFee); + bool hasCallback = hookDef->isFieldPresent(sfHookCallbackFee) || + hookDef->isFieldPresent(sfHookCallbackCost); try { @@ -1365,7 +1408,8 @@ Transactor::doHookCallback( return; } - if (!hookDef->isFieldPresent(sfHookCallbackFee)) + if (!hookDef->isFieldPresent(sfHookCallbackFee) && + !hookDef->isFieldPresent(sfHookCallbackCost)) { JLOG(j_.trace()) << "HookInfo[" << callbackAccountID << "]: Callback specified by emitted txn " @@ -1558,8 +1602,11 @@ Transactor::doTSH( continue; // compute and deduct fees for the TSH if applicable - XRPAmount tshFeeDrops = + auto const tshFee = calculateHookChainFee(view, ctx_.tx, klTshHook, !canRollback); + XRPAmount tshFeeDrops{tshFee.first}; + + tshFeeDrops += hook::hookCostToFee(tshFee.second); // no hooks to execute, skip tsh if (tshFeeDrops == 0) @@ -1701,7 +1748,8 @@ Transactor::doAgainAsWeak( stateMap, ctx_, hookAccountID, - hookDef->isFieldPresent(sfHookCallbackFee), + hookDef->isFieldPresent(sfHookCallbackFee) || + hookDef->isFieldPresent(sfHookCallbackCost), false, false, 2UL, // param 2 = aaw diff --git a/src/ripple/app/tx/impl/Transactor.h b/src/ripple/app/tx/impl/Transactor.h index 7a2882e86c..7ad69aa767 100644 --- a/src/ripple/app/tx/impl/Transactor.h +++ b/src/ripple/app/tx/impl/Transactor.h @@ -174,7 +174,7 @@ class Transactor // Hooks - static XRPAmount + static std::pair calculateHookChainFee( ReadView const& view, STTx const& tx, diff --git a/src/ripple/app/tx/impl/applySteps.cpp b/src/ripple/app/tx/impl/applySteps.cpp index a18f78e1c2..a4deee7699 100644 --- a/src/ripple/app/tx/impl/applySteps.cpp +++ b/src/ripple/app/tx/impl/applySteps.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -187,6 +188,8 @@ invoke_preflight(PreflightContext const& ctx) return invoke_preflight_helper(ctx); case ttCRON: return invoke_preflight_helper(ctx); + case ttHOOK_DEFINITION_UPDATE: + return invoke_preflight_helper(ctx); default: assert(false); return {temUNKNOWN, TxConsequences{temUNKNOWN}}; @@ -316,6 +319,8 @@ invoke_preclaim(PreclaimContext const& ctx) return invoke_preclaim(ctx); case ttCRON: return invoke_preclaim(ctx); + case ttHOOK_DEFINITION_UPDATE: + return invoke_preclaim(ctx); default: assert(false); return temUNKNOWN; @@ -407,6 +412,8 @@ invoke_calculateBaseFee(ReadView const& view, STTx const& tx) return CronSet::calculateBaseFee(view, tx); case ttCRON: return Cron::calculateBaseFee(view, tx); + case ttHOOK_DEFINITION_UPDATE: + return HookDefinitionUpdate::calculateBaseFee(view, tx); default: return XRPAmount{0}; } @@ -608,6 +615,10 @@ invoke_apply(ApplyContext& ctx) Cron p(ctx); return p(); } + case ttHOOK_DEFINITION_UPDATE: { + HookDefinitionUpdate p(ctx); + return p(); + } default: assert(false); return {temUNKNOWN, false}; diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index f507b22326..7042a6bfe1 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -438,6 +438,8 @@ extern SF_UINT64 const sfRewardAccumulator; extern SF_UINT64 const sfAccountCount; extern SF_UINT64 const sfAccountIndex; extern SF_UINT64 const sfTouchCount; +extern SF_UINT64 const sfHookCost; +extern SF_UINT64 const sfHookCallbackCost; // 128-bit extern SF_UINT128 const sfEmailHash; diff --git a/src/ripple/protocol/TxFormats.h b/src/ripple/protocol/TxFormats.h index bea5905cbf..590da4e16f 100644 --- a/src/ripple/protocol/TxFormats.h +++ b/src/ripple/protocol/TxFormats.h @@ -149,6 +149,9 @@ enum TxType : std::uint16_t ttURITOKEN_CREATE_SELL_OFFER = 48, ttURITOKEN_CANCEL_SELL_OFFER = 49, + /** This transaction updates a hook definition. */ + ttHOOK_DEFINITION_UPDATE = 91, + /* A pseudo-txn alarm signal for invoking a hook, emitted by validators after alarm set conditions are met */ ttCRON = 92, diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index 5f51976be3..13d396f2fc 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -236,8 +236,10 @@ LedgerFormats::LedgerFormats() {sfCreateCode, soeREQUIRED}, {sfHookSetTxnID, soeREQUIRED}, {sfReferenceCount, soeREQUIRED}, - {sfFee, soeREQUIRED}, - {sfHookCallbackFee, soeOPTIONAL} + {sfFee, soeOPTIONAL}, + {sfHookCallbackFee, soeOPTIONAL}, + {sfHookCost, soeOPTIONAL}, + {sfHookCallbackCost, soeOPTIONAL}, }, commonFields); diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index c4f2ef85a5..5eb508d1a5 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -187,6 +187,8 @@ CONSTRUCT_TYPED_SFIELD(sfEmitBurden, "EmitBurden", UINT64, CONSTRUCT_TYPED_SFIELD(sfHookInstructionCount, "HookInstructionCount", UINT64, 17); CONSTRUCT_TYPED_SFIELD(sfHookReturnCode, "HookReturnCode", UINT64, 18); CONSTRUCT_TYPED_SFIELD(sfReferenceCount, "ReferenceCount", UINT64, 19); +CONSTRUCT_TYPED_SFIELD(sfHookCallbackCost, "HookCallbackCost", UINT64, 95); +CONSTRUCT_TYPED_SFIELD(sfHookCost, "HookCost", UINT64, 96); CONSTRUCT_TYPED_SFIELD(sfTouchCount, "TouchCount", UINT64, 97); CONSTRUCT_TYPED_SFIELD(sfAccountIndex, "AccountIndex", UINT64, 98); CONSTRUCT_TYPED_SFIELD(sfAccountCount, "AccountCount", UINT64, 99); diff --git a/src/ripple/protocol/impl/TxFormats.cpp b/src/ripple/protocol/impl/TxFormats.cpp index 789de36f2d..e6334569d3 100644 --- a/src/ripple/protocol/impl/TxFormats.cpp +++ b/src/ripple/protocol/impl/TxFormats.cpp @@ -490,6 +490,13 @@ TxFormats::TxFormats() {sfStartTime, soeOPTIONAL}, }, commonFields); + + add(jss::HookDefinitionUpdate, + ttHOOK_DEFINITION_UPDATE, + { + {sfHookHash, soeREQUIRED}, + }, + commonFields); } TxFormats const& diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index 3160372689..6bc315bd42 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -80,21 +80,22 @@ JSS(GenesisMint); // tt JSS(GenesisMints); JSS(GovernanceMarks); JSS(GovernanceFlags); -JSS(HookApiVersion); // field -JSS(HookCanEmit); // field -JSS(HookHash); // field -JSS(HookNamespace); // field -JSS(HookOn); // field -JSS(Hooks); // field -JSS(HookGrants); // field -JSS(HookParameters); // field -JSS(HookParameterName); // field -JSS(HookParameterValue); // field -JSS(HookParameter); // field -JSS(HookGrant); // field -JSS(isSerialized); // out: RPC server_definitions -JSS(isSigningField); // out: RPC server_definitions -JSS(isVLEncoded); // out: RPC server_definitions +JSS(HookApiVersion); // field +JSS(HookCanEmit); // field +JSS(HookHash); // field +JSS(HookNamespace); // field +JSS(HookOn); // field +JSS(Hooks); // field +JSS(HookGrants); // field +JSS(HookParameters); // field +JSS(HookParameterName); // field +JSS(HookParameterValue); // field +JSS(HookParameter); // field +JSS(HookGrant); // field +JSS(HookDefinitionUpdate); // transaction type. +JSS(isSerialized); // out: RPC server_definitions +JSS(isSigningField); // out: RPC server_definitions +JSS(isVLEncoded); // out: RPC server_definitions JSS(Import); JSS(ImportVLSequence); JSS(Invalid); // diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index cb8bbadbd0..48043cf0ab 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -2631,12 +2631,18 @@ class SetHook0_test : public beast::unit_test::suite auto const hookDef = env.le(hook_keylet); BEAST_EXPECT(hookDef); - auto const hookFee = hookDef->getFieldAmount(sfFee); - if (withCost) - BEAST_EXPECT(hookFee == XRPAmount{449}); + { + auto const hookCost = hookDef->getFieldU64(sfHookCost); + BEAST_EXPECT(hookCost == 4494); + BEAST_EXPECT(!hookDef->isFieldPresent(sfFee)); + } else + { + auto const hookFee = hookDef->getFieldAmount(sfFee); BEAST_EXPECT(hookFee == XRPAmount{1944}); + BEAST_EXPECT(!hookDef->isFieldPresent(sfHookCost)); + } } } @@ -13251,6 +13257,8 @@ class SetHook0_test : public beast::unit_test::suite void testWithFeatures(FeatureBitset features) { + test_emit(features); // + return; testHooksOwnerDir(features); testHooksDisabled(features); testTxStructure(features); From 5ae68851d8e077ab4cbdabe0022507f3a15f4763 Mon Sep 17 00:00:00 2001 From: tequ Date: Sat, 8 Nov 2025 12:26:59 +0900 Subject: [PATCH 17/33] update hook/sfcodes.h --- hook/sfcodes.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hook/sfcodes.h b/hook/sfcodes.h index 8c7bc48f49..0c79ccd153 100644 --- a/hook/sfcodes.h +++ b/hook/sfcodes.h @@ -87,6 +87,8 @@ #define sfHookInstructionCount ((3U << 16U) + 17U) #define sfHookReturnCode ((3U << 16U) + 18U) #define sfReferenceCount ((3U << 16U) + 19U) +#define sfHookCallbackCost ((3U << 16U) + 95U) +#define sfHookCost ((3U << 16U) + 96U) #define sfTouchCount ((3U << 16U) + 97U) #define sfAccountIndex ((3U << 16U) + 98U) #define sfAccountCount ((3U << 16U) + 99U) From 2d77acfaa61affc4143791917f6be385128d9ca0 Mon Sep 17 00:00:00 2001 From: tequ Date: Sat, 8 Nov 2025 12:48:57 +0900 Subject: [PATCH 18/33] add comments --- src/ripple/app/tx/impl/HookDefinitionUpdate.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp index c7c97d8c23..c7dabe8849 100644 --- a/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp +++ b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp @@ -77,6 +77,9 @@ HookDefinitionUpdate::doApply() auto const result = hook::doValidateGuards(tx, hook, view.rules(), ctx_.journal); if (!result) + // TODO: TEQU better error code + // For compatibility, if an already deployed HookDefinition fails with a + // new guard-checker, don't update/delete it return tecINTERNAL; auto const [hookCost, callbackCost] = *result; From 79e1cc265511a6f758901af7d2da3a718154454d Mon Sep 17 00:00:00 2001 From: tequ Date: Sat, 8 Nov 2025 12:51:35 +0900 Subject: [PATCH 19/33] update hook/tts.h --- hook/tts.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hook/tts.h b/hook/tts.h index bd03b03995..e2f564555a 100644 --- a/hook/tts.h +++ b/hook/tts.h @@ -34,6 +34,7 @@ #define ttURITOKEN_BUY 47 #define ttURITOKEN_CREATE_SELL_OFFER 48 #define ttURITOKEN_CANCEL_SELL_OFFER 49 +#define ttHOOK_DEFINITION_UPDATE 91 #define ttCRON 92 #define ttCRON_SET 93 #define ttREMARKS_SET 94 From 7c96052f030b97ac66858e3033cffc9480b6fafb Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 20 Nov 2025 11:08:55 +0900 Subject: [PATCH 20/33] remove unused DECLARE_HOOK_FUNCNARG macro --- src/ripple/app/hook/Macro.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/ripple/app/hook/Macro.h b/src/ripple/app/hook/Macro.h index 153677d4b3..10c89ae09e 100644 --- a/src/ripple/app/hook/Macro.h +++ b/src/ripple/app/hook/Macro.h @@ -102,18 +102,6 @@ extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \ extern WasmEdge_String WasmFunctionName##F; -#define DECLARE_HOOK_FUNCNARG(R, F) \ - R F(hook::HookContext& hookCtx, \ - WasmEdge_CallingFrameContext const& frameCtx); \ - extern WasmEdge_Result WasmFunction##F( \ - void* data_ptr, \ - const WasmEdge_CallingFrameContext* frameCtx, \ - const WasmEdge_Value* in, \ - WasmEdge_Value* out); \ - extern WasmEdge_ValType WasmFunctionResult##F[]; \ - extern WasmEdge_FunctionTypeContext* WasmFunctionType##F; \ - extern WasmEdge_String WasmFunctionName##F; - #define DEFINE_HOOK_FUNCTION(R, F, ...) \ WasmEdge_Result hook_api::WasmFunction##F( \ void* data_ptr, \ From 4c0d3ab99ddbfa059e9f25a20d1d55de382913db Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 20 Nov 2025 12:04:27 +0900 Subject: [PATCH 21/33] fix DECLARE_HOOK_FUNCTION macro --- src/ripple/app/hook/Macro.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ripple/app/hook/Macro.h b/src/ripple/app/hook/Macro.h index 10c89ae09e..fb21e567bf 100644 --- a/src/ripple/app/hook/Macro.h +++ b/src/ripple/app/hook/Macro.h @@ -91,7 +91,7 @@ #define DECLARE_HOOK_FUNCTION(R, F, ...) \ R F(hook::HookContext& hookCtx, \ WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \ - , )##__VA_ARGS__); \ + COMMA __VA_ARGS__)); \ extern WasmEdge_Result WasmFunction##F( \ void* data_ptr, \ const WasmEdge_CallingFrameContext* frameCtx, \ From 2fc07955c8474df8f405569e516b1c3bf04e09de Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 20 Nov 2025 12:05:46 +0900 Subject: [PATCH 22/33] refactor DEFINE_HOOK_FUNCNARG --- src/ripple/app/hook/Macro.h | 57 ++++++++++---------------- src/ripple/app/hook/impl/applyHook.cpp | 22 +++++----- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/ripple/app/hook/Macro.h b/src/ripple/app/hook/Macro.h index fb21e567bf..f3688c02a8 100644 --- a/src/ripple/app/hook/Macro.h +++ b/src/ripple/app/hook/Macro.h @@ -24,8 +24,21 @@ #define VA_NARGS_IMPL( \ _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) \ N -#define VA_NARGS(__drop, ...) \ - VA_NARGS_IMPL(__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) +#define VA_NARGS(__drop, ...) \ + VA_NARGS_IMPL( \ + __VA_OPT__(__VA_ARGS__ COMMA) 12, \ + 11, \ + 10, \ + 9, \ + 8, \ + 7, \ + 6, \ + 5, \ + 4, \ + 3, \ + 2, \ + 1, \ + 0) #define FIRST(a, b) a #define SECOND(a, b) b #define STRIP_TYPES(...) FOR_VARS(SECOND, 0, __VA_ARGS__) @@ -109,21 +122,21 @@ const WasmEdge_Value* in, \ WasmEdge_Value* out) \ { \ - int _stack = 0; \ - FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__); \ + __VA_OPT__(int _stack = 0;) \ + __VA_OPT__(FOR_VARS(VAR_ASSIGN, 2, __VA_ARGS__);) \ hook::HookContext* hookCtx = \ reinterpret_cast(data_ptr); \ R return_code = hook_api::F( \ *hookCtx, \ - *const_cast(frameCtx), \ - STRIP_TYPES(__VA_ARGS__)); \ + *const_cast(frameCtx) \ + __VA_OPT__(COMMA STRIP_TYPES(__VA_ARGS__))); \ if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \ return WasmEdge_Result_Terminate; \ out[0] = RET_ASSIGN(R, return_code); \ return WasmEdge_Result_Success; \ }; \ WasmEdge_ValType hook_api::WasmFunctionParams##F[] = { \ - FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__)}; \ + __VA_OPT__(FOR_VARS(WASM_VAL_TYPE, 0, __VA_ARGS__))}; \ WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \ WASM_VAL_TYPE(R, dummy)}; \ WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \ @@ -136,34 +149,8 @@ WasmEdge_StringCreateByCString(#F); \ R hook_api::F( \ hook::HookContext& hookCtx, \ - WasmEdge_CallingFrameContext const& frameCtx, \ - __VA_ARGS__) - -#define DEFINE_HOOK_FUNCNARG(R, F) \ - WasmEdge_Result hook_api::WasmFunction##F( \ - void* data_ptr, \ - const WasmEdge_CallingFrameContext* frameCtx, \ - const WasmEdge_Value* in, \ - WasmEdge_Value* out) \ - { \ - hook::HookContext* hookCtx = \ - reinterpret_cast(data_ptr); \ - R return_code = hook_api::F( \ - *hookCtx, *const_cast(frameCtx)); \ - if (return_code == RC_ROLLBACK || return_code == RC_ACCEPT) \ - return WasmEdge_Result_Terminate; \ - out[0] = CAT2(RET_, R(return_code)); \ - return WasmEdge_Result_Success; \ - }; \ - WasmEdge_ValType hook_api::WasmFunctionResult##F[1] = { \ - WASM_VAL_TYPE(R, dummy)}; \ - WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \ - WasmEdge_FunctionTypeCreate({}, 0, WasmFunctionResult##F, 1); \ - WasmEdge_String hook_api::WasmFunctionName##F = \ - WasmEdge_StringCreateByCString(#F); \ - R hook_api::F( \ - hook::HookContext& hookCtx, \ - WasmEdge_CallingFrameContext const& frameCtx) + WasmEdge_CallingFrameContext const& frameCtx __VA_OPT__( \ + COMMA __VA_ARGS__)) #define HOOK_SETUP() \ try \ diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 9c90090980..16d7e7cdc3 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -2275,7 +2275,7 @@ DEFINE_HOOK_FUNCTION( } // Return the tt (Transaction Type) numeric code of the originating transaction -DEFINE_HOOK_FUNCNARG(int64_t, otxn_type) +DEFINE_HOOK_FUNCTION(int64_t, otxn_type) { HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, // hookCtx on current stack @@ -2325,7 +2325,7 @@ DEFINE_HOOK_FUNCTION(int64_t, otxn_slot, uint32_t slot_into) // Return the burden of the originating transaction... this will be 1 unless the // originating transaction was itself an emitted transaction from a previous // hook invocation -DEFINE_HOOK_FUNCNARG(int64_t, otxn_burden) +DEFINE_HOOK_FUNCTION(int64_t, otxn_burden) { HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, // hookCtx on current stack @@ -2362,7 +2362,7 @@ DEFINE_HOOK_FUNCNARG(int64_t, otxn_burden) // Return the generation of the originating transaction... this will be 1 unless // the originating transaction was itself an emitted transaction from a previous // hook invocation -DEFINE_HOOK_FUNCNARG(int64_t, otxn_generation) +DEFINE_HOOK_FUNCTION(int64_t, otxn_generation) { HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, // hookCtx on current stack @@ -2394,14 +2394,14 @@ DEFINE_HOOK_FUNCNARG(int64_t, otxn_generation) } // Return the generation of a hypothetically emitted transaction from this hook -DEFINE_HOOK_FUNCNARG(int64_t, etxn_generation) +DEFINE_HOOK_FUNCTION(int64_t, etxn_generation) { // proxy only, no setup or teardown return otxn_generation(hookCtx, frameCtx) + 1; } // Return the current ledger sequence number -DEFINE_HOOK_FUNCNARG(int64_t, ledger_seq) +DEFINE_HOOK_FUNCTION(int64_t, ledger_seq) { HOOK_SETUP(); @@ -2431,7 +2431,7 @@ DEFINE_HOOK_FUNCTION( HOOK_TEARDOWN(); } -DEFINE_HOOK_FUNCNARG(int64_t, ledger_last_time) +DEFINE_HOOK_FUNCTION(int64_t, ledger_last_time) { HOOK_SETUP(); @@ -3889,7 +3889,7 @@ DEFINE_HOOK_FUNCTION(int64_t, etxn_reserve, uint32_t count) } // Compute the burden of an emitted transaction based on a number of factors -DEFINE_HOOK_FUNCNARG(int64_t, etxn_burden) +DEFINE_HOOK_FUNCTION(int64_t, etxn_burden) { HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, // hookCtx on current stack @@ -4672,7 +4672,7 @@ DEFINE_HOOK_FUNCTION( } // Return the current fee base of the current ledger (multiplied by a margin) -DEFINE_HOOK_FUNCNARG(int64_t, fee_base) +DEFINE_HOOK_FUNCTION(int64_t, fee_base) { HOOK_SETUP(); // populates memory_ctx, memory, memory_length, applyCtx, // hookCtx on current stack @@ -5590,7 +5590,7 @@ DEFINE_HOOK_FUNCTION(int64_t, float_divide, int64_t float1, int64_t float2) HOOK_TEARDOWN(); } -DEFINE_HOOK_FUNCNARG(int64_t, float_one) +DEFINE_HOOK_FUNCTION(int64_t, float_one) { return float_one_internal; } @@ -5986,12 +5986,12 @@ DEFINE_HOOK_FUNCTION( HOOK_TEARDOWN(); } -DEFINE_HOOK_FUNCNARG(int64_t, hook_pos) +DEFINE_HOOK_FUNCTION(int64_t, hook_pos) { return hookCtx.result.hookChainPosition; } -DEFINE_HOOK_FUNCNARG(int64_t, hook_again) +DEFINE_HOOK_FUNCTION(int64_t, hook_again) { HOOK_SETUP(); From 6dedbf976a940a5a6056a6e84db50dfc18d4b819 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 20 Nov 2025 12:33:01 +0900 Subject: [PATCH 23/33] fix --- src/ripple/app/hook/Macro.h | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/ripple/app/hook/Macro.h b/src/ripple/app/hook/Macro.h index f3688c02a8..ebf3499b24 100644 --- a/src/ripple/app/hook/Macro.h +++ b/src/ripple/app/hook/Macro.h @@ -24,21 +24,9 @@ #define VA_NARGS_IMPL( \ _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) \ N -#define VA_NARGS(__drop, ...) \ - VA_NARGS_IMPL( \ - __VA_OPT__(__VA_ARGS__ COMMA) 12, \ - 11, \ - 10, \ - 9, \ - 8, \ - 7, \ - 6, \ - 5, \ - 4, \ - 3, \ - 2, \ - 1, \ - 0) +#define VA_NARGS(__drop, ...) \ + VA_NARGS_IMPL( \ + __VA_OPT__(__VA_ARGS__, ) 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) #define FIRST(a, b) a #define SECOND(a, b) b #define STRIP_TYPES(...) FOR_VARS(SECOND, 0, __VA_ARGS__) @@ -142,7 +130,7 @@ WasmEdge_FunctionTypeContext* hook_api::WasmFunctionType##F = \ WasmEdge_FunctionTypeCreate( \ WasmFunctionParams##F, \ - VA_NARGS(NULL, __VA_ARGS__), \ + VA_NARGS(NULL __VA_OPT__(, __VA_ARGS__)), \ WasmFunctionResult##F, \ 1); \ WasmEdge_String hook_api::WasmFunctionName##F = \ From 0da64a8ffaa2ac4c22a6411bc4cacceac0099dc7 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 11 Dec 2025 11:20:04 +0900 Subject: [PATCH 24/33] Update SetHook_wasm.h --- src/test/app/SetHook_wasm.h | 45 +++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index af492d4735..a2bd839884 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -16364,7 +16364,7 @@ std::map> wasm = { 0x63U, 0x65U, 0x29U, 0x20U, 0x3EU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 77 ==== */ + /* ==== WASM: 78 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16714,7 +16714,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 78 ==== */ + /* ==== WASM: 79 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16850,9 +16850,7 @@ std::map> wasm = { 0x00U, }}, - /* ==== WASM: 79 ==== */ -<<<<<<< HEAD -======= + /* ==== WASM: 80 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -16911,8 +16909,7 @@ std::map> wasm = { 0x64U, 0xE1U, 0xF1U, }}, - /* ==== WASM: 79 ==== */ ->>>>>>> refactor-whitelist-api-3 + /* ==== WASM: 81 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17085,7 +17082,7 @@ std::map> wasm = { 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, }}, - /* ==== WASM: 80 ==== */ + /* ==== WASM: 82 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17233,7 +17230,7 @@ std::map> wasm = { 0x30U, 0x00U, 0x22U, 0x00U, 0x00U, 0x00U, 0x00U, }}, - /* ==== WASM: 81 ==== */ + /* ==== WASM: 83 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17330,7 +17327,7 @@ std::map> wasm = { 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 82 ==== */ + /* ==== WASM: 84 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17389,7 +17386,7 @@ std::map> wasm = { 0x4FU, 0x46U, 0x5FU, 0x42U, 0x4FU, 0x55U, 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 83 ==== */ + /* ==== WASM: 85 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -17448,7 +17445,7 @@ std::map> wasm = { 0x4EU, 0x44U, 0x53U, 0x00U, }}, - /* ==== WASM: 84 ==== */ + /* ==== WASM: 86 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -19277,7 +19274,7 @@ std::map> wasm = { 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 85 ==== */ + /* ==== WASM: 87 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -20619,7 +20616,7 @@ std::map> wasm = { 0x20U, 0x30U, 0x2CU, 0x20U, 0x30U, 0x29U, 0x29U, 0x00U, }}, - /* ==== WASM: 86 ==== */ + /* ==== WASM: 88 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -23552,7 +23549,7 @@ std::map> wasm = { 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 87 ==== */ + /* ==== WASM: 89 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25517,7 +25514,7 @@ std::map> wasm = { 0x54U, 0x4FU, 0x4FU, 0x5FU, 0x53U, 0x4DU, 0x41U, 0x4CU, 0x4CU, 0x00U, }}, - /* ==== WASM: 88 ==== */ + /* ==== WASM: 90 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -25802,7 +25799,7 @@ std::map> wasm = { 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x30U, 0x00U, }}, - /* ==== WASM: 89 ==== */ + /* ==== WASM: 91 ==== */ {R"[test.hook]( #include extern int32_t _g(uint32_t, uint32_t); @@ -26389,7 +26386,7 @@ std::map> wasm = { 0x4EU, 0x5FU, 0x46U, 0x41U, 0x49U, 0x4CU, 0x55U, 0x52U, 0x45U, 0x00U, }}, - /* ==== WASM: 90 ==== */ + /* ==== WASM: 92 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26418,7 +26415,7 @@ std::map> wasm = { 0x0BU, }}, - /* ==== WASM: 91 ==== */ + /* ==== WASM: 93 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -26450,7 +26447,7 @@ std::map> wasm = { 0x20U, 0x52U, 0x65U, 0x6AU, 0x65U, 0x63U, 0x74U, 0x65U, 0x64U, 0x00U, }}, - /* ==== WASM: 92 ==== */ + /* ==== WASM: 94 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32 i64) (result i64))) @@ -26477,7 +26474,7 @@ std::map> wasm = { 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x00U, 0x0BU, }}, - /* ==== WASM: 93 ==== */ + /* ==== WASM: 95 ==== */ {R"[test.hook]( (module (type (;0;) (func (param i32 i32) (result i32))) @@ -26530,7 +26527,7 @@ std::map> wasm = { 0x00U, 0x1AU, 0x0BU, }}, - /* ==== WASM: 94 ==== */ + /* ==== WASM: 96 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33173,7 +33170,7 @@ std::map> wasm = { 0x39U, 0x30U, 0x31U, 0x32U, 0x33U, 0x00U, }}, - /* ==== WASM: 95 ==== */ + /* ==== WASM: 97 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); @@ -33219,7 +33216,7 @@ std::map> wasm = { 0x0BU, 0x06U, 0x76U, 0x61U, 0x6CU, 0x75U, 0x65U, 0x00U, }}, - /* ==== WASM: 96 ==== */ + /* ==== WASM: 98 ==== */ {R"[test.hook]( #include extern int32_t _g (uint32_t id, uint32_t maxiter); From 8a9eb1f0a8101bddff6683a7987e657d4d3ed263 Mon Sep 17 00:00:00 2001 From: tequ Date: Thu, 11 Dec 2025 16:26:25 +0900 Subject: [PATCH 25/33] Fix to use macros only top of Enum.h --- src/ripple/app/hook/Enum.h | 42 ++++++++++++++------------- src/ripple/app/hook/guard_checker.cpp | 7 +++-- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index ddb87bf6cb..0ef817defe 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -1,7 +1,3 @@ -#ifndef GUARD_CHECKER_BUILD -#include -#include -#endif #include #include #include @@ -9,6 +5,26 @@ #include #ifndef HOOKENUM_INCLUDED #define HOOKENUM_INCLUDED 1 + +#ifndef GUARD_CHECKER_BUILD +#include +#include +#else +// Override Feature and Rules for guard checker build +#define featureHooksUpdate1 1 +#define fix20250131 1 +namespace hook_api { +struct Rules +{ + constexpr bool + enabled(int feature) const + { + return true; + } +}; +} // namespace hook_api +#endif + namespace ripple { enum HookSetOperation : int8_t { hsoINVALID = -1, @@ -384,11 +400,7 @@ using APIWhitelist = std::map>; // hookapi.h (include for hooks) this is a map of the api name to its return // code (vec[0] and its parameters vec[>0]) as wasm type codes inline APIWhitelist -getImportWhitelist( -#ifndef GUARD_CHECKER_BUILD - Rules const& rules -#endif -) +getImportWhitelist(Rules const& rules) { APIWhitelist whitelist; // clang-format off @@ -466,9 +478,7 @@ getImportWhitelist( HOOK_API_DEFINITION(I64, otxn_param, (I32, I32, I32, I32)) HOOK_API_DEFINITION(I64, meta_slot, (I32)) - #ifndef GUARD_CHECKER_BUILD if (rules.enabled(featureHooksUpdate1)) - #endif HOOK_API_DEFINITION(I64, xpop_slot, (I32, I32)) return whitelist; @@ -484,19 +494,11 @@ enum GuardRulesVersion : uint64_t { }; inline uint64_t -getGuardRulesVersion( -#ifndef GUARD_CHECKER_BUILD - Rules const& rules -#endif -) +getGuardRulesVersion(Rules const& rules) { uint64_t version = 0; -#ifndef GUARD_CHECKER_BUILD if (rules.enabled(fix20250131)) version |= GuardRuleFix20250131; -#else - version = -1; // all bits set for guard checker -#endif return version; } diff --git a/src/ripple/app/hook/guard_checker.cpp b/src/ripple/app/hook/guard_checker.cpp index f40f4c7eaf..1fc61ea2d0 100644 --- a/src/ripple/app/hook/guard_checker.cpp +++ b/src/ripple/app/hook/guard_checker.cpp @@ -81,12 +81,15 @@ main(int argc, char** argv) close(fd); + // Dummy rules for guard checker build + hook_api::Rules rules; + auto result = validateGuards( hook, std::cout, "", - hook_api::getImportWhitelist(), - hook_api::getGuardRulesVersion()); + hook_api::getImportWhitelist(rules), + hook_api::getGuardRulesVersion(rules)); if (!result) { From 379fb0f82b7100f39267febcee6d6ecc8244e392 Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 12 Dec 2025 15:44:17 +0900 Subject: [PATCH 26/33] format hook_api.macro --- src/ripple/app/hook/hook_api.macro | 296 +++++++++++++++++++++-------- 1 file changed, 222 insertions(+), 74 deletions(-) diff --git a/src/ripple/app/hook/hook_api.macro b/src/ripple/app/hook/hook_api.macro index d0d479a547..6f76f4f8d0 100644 --- a/src/ripple/app/hook/hook_api.macro +++ b/src/ripple/app/hook/hook_api.macro @@ -1,221 +1,369 @@ // int32_t _g(uint32_t guard_id, uint32_t maxiter); -HOOK_API_DEFINITION(int32_t, _g, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int32_t, _g, (uint32_t, uint32_t), + uint256{}) // int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code); -HOOK_API_DEFINITION(int64_t, accept, (uint32_t, uint32_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, accept, (uint32_t, uint32_t, int64_t), + uint256{}) // int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code); -HOOK_API_DEFINITION(int64_t, rollback, (uint32_t, uint32_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, rollback, (uint32_t, uint32_t, int64_t), + uint256{}) // int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len); -HOOK_API_DEFINITION(int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // 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); -HOOK_API_DEFINITION(int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len); -HOOK_API_DEFINITION(int64_t, sto_validate, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, sto_validate, (uint32_t, uint32_t), + uint256{}) // int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id); -HOOK_API_DEFINITION(int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id); -HOOK_API_DEFINITION(int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id); -HOOK_API_DEFINITION(int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id); -HOOK_API_DEFINITION(int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t etxn_burden(); -HOOK_API_DEFINITION(int64_t, etxn_burden, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_burden, (), + uint256{}) // int64_t etxn_details(uint32_t write_ptr, uint32_t write_len); -HOOK_API_DEFINITION(int64_t, etxn_details, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_details, (uint32_t, uint32_t), + uint256{}) // int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, etxn_fee_base, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_fee_base, (uint32_t, uint32_t), + uint256{}) // int64_t etxn_reserve(uint32_t count); -HOOK_API_DEFINITION(int64_t, etxn_reserve, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_reserve, (uint32_t), + uint256{}) // int64_t etxn_generation(); -HOOK_API_DEFINITION(int64_t, etxn_generation, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_generation, (), + uint256{}) // int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len); -HOOK_API_DEFINITION(int64_t, etxn_nonce, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, etxn_nonce, (uint32_t, uint32_t), + uint256{}) // int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t float_set(int32_t exponent, int64_t mantissa); -HOOK_API_DEFINITION(int64_t, float_set, (int32_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_set, (int32_t, int64_t), + uint256{}) // int64_t float_multiply(int64_t float1, int64_t float2); -HOOK_API_DEFINITION(int64_t, float_multiply, (int64_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_multiply, (int64_t, int64_t), + uint256{}) // int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator); -HOOK_API_DEFINITION(int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t float_negate(int64_t float1); -HOOK_API_DEFINITION(int64_t, float_negate, (int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_negate, (int64_t), + uint256{}) // int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode); -HOOK_API_DEFINITION(int64_t, float_compare, (int64_t, int64_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_compare, (int64_t, int64_t, uint32_t), + uint256{}) // int64_t float_sum(int64_t float1, int64_t float2); -HOOK_API_DEFINITION(int64_t, float_sum, (int64_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_sum, (int64_t, int64_t), + uint256{}) // int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code); -HOOK_API_DEFINITION(int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t), + uint256{}) // int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, float_sto_set, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_sto_set, (uint32_t, uint32_t), + uint256{}) // int64_t float_invert(int64_t float1); -HOOK_API_DEFINITION(int64_t, float_invert, (int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_invert, (int64_t), + uint256{}) // int64_t float_divide(int64_t float1, int64_t float2); -HOOK_API_DEFINITION(int64_t, float_divide, (int64_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_divide, (int64_t, int64_t), + uint256{}) // int64_t float_one(); -HOOK_API_DEFINITION(int64_t, float_one, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_one, (), + uint256{}) // int64_t float_mantissa(int64_t float1); -HOOK_API_DEFINITION(int64_t, float_mantissa, (int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_mantissa, (int64_t), + uint256{}) // int64_t float_sign(int64_t float1); -HOOK_API_DEFINITION(int64_t, float_sign, (int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_sign, (int64_t), + uint256{}) // int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs); -HOOK_API_DEFINITION(int64_t, float_int, (int64_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_int, (int64_t, uint32_t, uint32_t), + uint256{}) // int64_t float_log(int64_t float1); -HOOK_API_DEFINITION(int64_t, float_log, (int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_log, (int64_t), + uint256{}) // int64_t float_root(int64_t float1, uint32_t n); -HOOK_API_DEFINITION(int64_t, float_root, (int64_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, float_root, (int64_t, uint32_t), + uint256{}) // int64_t fee_base(); -HOOK_API_DEFINITION(int64_t, fee_base, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, fee_base, (), + uint256{}) // int64_t ledger_seq(); -HOOK_API_DEFINITION(int64_t, ledger_seq, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, ledger_seq, (), + uint256{}) // int64_t ledger_last_time(); -HOOK_API_DEFINITION(int64_t, ledger_last_time, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, ledger_last_time, (), + uint256{}) // int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len); -HOOK_API_DEFINITION(int64_t, ledger_last_hash, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, ledger_last_hash, (uint32_t, uint32_t), + uint256{}) // int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len); -HOOK_API_DEFINITION(int64_t, ledger_nonce, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, ledger_nonce, (uint32_t, uint32_t), + uint256{}) // int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len); -HOOK_API_DEFINITION(int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t hook_account(uint32_t write_ptr, uint32_t write_len); -HOOK_API_DEFINITION(int64_t, hook_account, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_account, (uint32_t, uint32_t), + uint256{}) // int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no); -HOOK_API_DEFINITION(int64_t, hook_hash, (uint32_t, uint32_t, int32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_hash, (uint32_t, uint32_t, int32_t), + uint256{}) // int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len); -HOOK_API_DEFINITION(int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t hook_again(); -HOOK_API_DEFINITION(int64_t, hook_again, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_again, (), + uint256{}) // int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); -HOOK_API_DEFINITION(int64_t, hook_skip, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_skip, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t hook_pos(); -HOOK_API_DEFINITION(int64_t, hook_pos, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, hook_pos, (), + uint256{}) // int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); -HOOK_API_DEFINITION(int64_t, slot, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t slot_clear(uint32_t slot); -HOOK_API_DEFINITION(int64_t, slot_clear, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_clear, (uint32_t), + uint256{}) // int64_t slot_count(uint32_t slot); -HOOK_API_DEFINITION(int64_t, slot_count, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_count, (uint32_t), + uint256{}) // int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot); -HOOK_API_DEFINITION(int64_t, slot_set, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_set, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t slot_size(uint32_t slot); -HOOK_API_DEFINITION(int64_t, slot_size, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_size, (uint32_t), + uint256{}) // int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot); -HOOK_API_DEFINITION(int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot); -HOOK_API_DEFINITION(int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t slot_type(uint32_t slot_no, uint32_t flags); -HOOK_API_DEFINITION(int64_t, slot_type, (uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_type, (uint32_t, uint32_t), + uint256{}) // int64_t slot_float(uint32_t slot_no); -HOOK_API_DEFINITION(int64_t, slot_float, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, slot_float, (uint32_t), + uint256{}) // int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len); -HOOK_API_DEFINITION(int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); -HOOK_API_DEFINITION(int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len); -HOOK_API_DEFINITION(int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); -HOOK_API_DEFINITION(int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex); -HOOK_API_DEFINITION(int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number); -HOOK_API_DEFINITION(int64_t, trace_num, (uint32_t, uint32_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, trace_num, (uint32_t, uint32_t, int64_t), + uint256{}) // int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); -HOOK_API_DEFINITION(int64_t, trace_float, (uint32_t, uint32_t, int64_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, trace_float, (uint32_t, uint32_t, int64_t), + uint256{}) // int64_t otxn_burden(); -HOOK_API_DEFINITION(int64_t, otxn_burden, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_burden, (), + uint256{}) // int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); -HOOK_API_DEFINITION(int64_t, otxn_field, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_field, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t otxn_generation(); -HOOK_API_DEFINITION(int64_t, otxn_generation, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_generation, (), + uint256{}) // int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags); -HOOK_API_DEFINITION(int64_t, otxn_id, (uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_id, (uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t otxn_type(); -HOOK_API_DEFINITION(int64_t, otxn_type, (), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_type, (), + uint256{}) // int64_t otxn_slot(uint32_t slot_no); -HOOK_API_DEFINITION(int64_t, otxn_slot, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_slot, (uint32_t), + uint256{}) // int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); -HOOK_API_DEFINITION(int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t), + uint256{}) // int64_t meta_slot(uint32_t slot_no); -HOOK_API_DEFINITION(int64_t, meta_slot, (uint32_t), uint256{}) +HOOK_API_DEFINITION( + int64_t, meta_slot, (uint32_t), + uint256{}) // int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta); -HOOK_API_DEFINITION(int64_t, xpop_slot, (uint32_t, uint32_t), featureHooksUpdate1) +HOOK_API_DEFINITION( + int64_t, xpop_slot, (uint32_t, uint32_t), + featureHooksUpdate1) From ad623c06d4518e10594ccf96610bd9d8203f4177 Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 12 Dec 2025 16:48:21 +0900 Subject: [PATCH 27/33] update header --- src/ripple/app/tx/impl/HookDefinitionUpdate.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp index c7dabe8849..d89d66c5e0 100644 --- a/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp +++ b/src/ripple/app/tx/impl/HookDefinitionUpdate.cpp @@ -17,16 +17,7 @@ */ //============================================================================== -#include #include -#include -#include -#include -#include -#include -#include -#include "ripple/protocol/SField.h" -#include "ripple/protocol/TER.h" namespace ripple { From 3be98304fd3bc4a3dd45f7f8c253d509672d90ea Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 16 Dec 2025 23:05:19 +0900 Subject: [PATCH 28/33] Add GasPrice voting --- cfg/xahaud-example.cfg | 9 +++ src/ripple/app/hook/applyHook.h | 2 +- src/ripple/app/hook/impl/applyHook.cpp | 7 +-- src/ripple/app/ledger/Ledger.cpp | 29 ++++++++- src/ripple/app/misc/FeeVoteImpl.cpp | 62 ++++++++++++++++--- src/ripple/app/misc/NetworkOPs.cpp | 14 +++++ src/ripple/app/tx/impl/Change.cpp | 12 ++++ src/ripple/app/tx/impl/Transactor.cpp | 4 +- src/ripple/core/Config.h | 3 + src/ripple/core/impl/Config.cpp | 7 +++ src/ripple/ledger/ReadView.h | 2 + src/ripple/protocol/SField.h | 1 + src/ripple/protocol/impl/LedgerFormats.cpp | 2 + src/ripple/protocol/impl/SField.cpp | 1 + src/ripple/protocol/impl/STValidation.cpp | 2 + src/ripple/protocol/impl/TxFormats.cpp | 2 + src/ripple/protocol/jss.h | 1 + src/test/app/FeeVote_test.cpp | 18 ++++-- src/test/app/Import_test.cpp | 72 +++++++++++++++++++--- src/test/app/SetHook_test.cpp | 9 +-- src/test/app/Wildcard_test.cpp | 3 +- src/test/app/XahauGenesis_test.cpp | 5 +- src/test/jtx/impl/envconfig.cpp | 1 + src/test/jtx/impl/network.cpp | 18 ++++-- src/test/jtx/network.h | 7 ++- 25 files changed, 253 insertions(+), 40 deletions(-) diff --git a/cfg/xahaud-example.cfg b/cfg/xahaud-example.cfg index 42c520d4b3..3ed13253d2 100644 --- a/cfg/xahaud-example.cfg +++ b/cfg/xahaud-example.cfg @@ -1502,6 +1502,15 @@ # Example: # owner_reserve = 2000000 # 2 XAH # +# hook_gas_price = +# +# The gas price for hooks is used to calculate the execution fee for hooks. +# +# If this parameter is unspecified, xahaud will use an internal +# default. Don't change this without understanding the consequences. +# +# Example: +# hook_gas_price = 1000000 #------------------------------------------------------------------------------- # # 9. Misc Settings diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 7a64a24a42..440ed15da5 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -129,7 +129,7 @@ computeCreationFee(uint64_t byteCount); constexpr uint32_t MICRO_DROPS_PER_DROP{1'000'000}; XRPAmount -hookCostToFee(uint64_t hookCost); +hookCostToFee(ReadView const& view, uint64_t hookCost); std::optional> doValidateGuards( diff --git a/src/ripple/app/hook/impl/applyHook.cpp b/src/ripple/app/hook/impl/applyHook.cpp index 087d67d3ea..fd7f6f236c 100644 --- a/src/ripple/app/hook/impl/applyHook.cpp +++ b/src/ripple/app/hook/impl/applyHook.cpp @@ -922,13 +922,12 @@ hook::computeCreationFee(uint64_t byteCount) } XRPAmount -hook::hookCostToFee(uint64_t hookCost) +hook::hookCostToFee(ReadView const& view, uint64_t hookCost) { XRPAmount fee{0}; - // TODO: TEQU should be voted by validators like reserve - auto const GAS_PRICE = 100'000; + auto const HOOK_GAS_PRICE = view.fees().hookGasPrice; double const gas_cost = - double(GAS_PRICE) / double(hook::MICRO_DROPS_PER_DROP); + double(HOOK_GAS_PRICE) / double(hook::MICRO_DROPS_PER_DROP); fee = uint64_t(hookCost * gas_cost); return fee; } diff --git a/src/ripple/app/ledger/Ledger.cpp b/src/ripple/app/ledger/Ledger.cpp index 5faaff5880..b50e083494 100644 --- a/src/ripple/app/ledger/Ledger.cpp +++ b/src/ripple/app/ledger/Ledger.cpp @@ -246,6 +246,13 @@ Ledger::Ledger( sle->at(sfReserveIncrement) = *f; sle->at(sfReferenceFeeUnits) = Config::FEE_UNITS_DEPRECATED; } + + if (std::find(amendments.begin(), amendments.end(), featureHookFeeV2) != + amendments.end()) + { + // TODO: want to set sfHookGasPrice when running unittest. + sle->at(sfHookGasPrice) = config.FEES.hook_gas_price; + } rawInsert(sle); } @@ -671,6 +678,7 @@ Ledger::setup() { bool oldFees = false; bool newFees = false; + bool hookFees = false; { auto const baseFee = sle->at(~sfBaseFee); auto const reserveBase = sle->at(~sfReserveBase); @@ -704,12 +712,26 @@ Ledger::setup() assign(fees_.increment, reserveIncrementXRP); newFees = baseFeeXRP || reserveBaseXRP || reserveIncrementXRP; } + { + auto const hookGasPrice = sle->at(~sfHookGasPrice); + auto assign = [](std::uint32_t& dest, + std::optional const& src) { + if (src) + dest = src.value(); + }; + assign(fees_.hookGasPrice, hookGasPrice); + hookFees = !!hookGasPrice; + } if (oldFees && newFees) // Should be all of one or the other, but not both ret = false; if (!rules_.enabled(featureXRPFees) && newFees) // Can't populate the new fees before the amendment is enabled ret = false; + if (!rules_.enabled(featureHookFeeV2) && hookFees) + // Can't populate the Hook Fee V2 before the amendment is + // enabled + ret = false; } } catch (SHAMapMissingNode const&) @@ -728,13 +750,18 @@ Ledger::setup() void Ledger::defaultFees(Config const& config) { - assert(fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0); + assert( + fees_.base == 0 && fees_.reserve == 0 && fees_.increment == 0 && + fees_.hookGasPrice == 0); if (fees_.base == 0) fees_.base = config.FEES.reference_fee; if (fees_.reserve == 0) fees_.reserve = config.FEES.account_reserve; if (fees_.increment == 0) fees_.increment = config.FEES.owner_reserve; + + if (fees_.hookGasPrice == 0) + fees_.hookGasPrice = config.FEES.hook_gas_price; } std::shared_ptr diff --git a/src/ripple/app/misc/FeeVoteImpl.cpp b/src/ripple/app/misc/FeeVoteImpl.cpp index 0d60dc6b78..ab047baf4d 100644 --- a/src/ripple/app/misc/FeeVoteImpl.cpp +++ b/src/ripple/app/misc/FeeVoteImpl.cpp @@ -29,10 +29,10 @@ namespace ripple { namespace detail { +template class VotableValue { private: - using value_type = XRPAmount; value_type const current_; // The current setting value_type const target_; // The setting we want std::map voteMap_; @@ -67,8 +67,9 @@ class VotableValue getVotes() const; }; -auto -VotableValue::getVotes() const -> std::pair +template +std::pair +VotableValue::getVotes() const { value_type ourVote = current_; int weight = 0; @@ -191,6 +192,28 @@ FeeVoteImpl::doValidation( "reserve increment", sfReserveIncrement); } + + if (rules.enabled(featureHookFeeV2)) + { + auto vote = [&v, this]( + auto const current, + std::uint32_t target, + char const* name, + auto const& sfield) { + if (current != target) + { + JLOG(journal_.info()) + << "Voting for " << name << " of " << target; + + v[sfield] = target; + } + }; + vote( + lastFees.hookGasPrice, + target_.hook_gas_price, + "hook gas price", + sfHookGasPrice); + } } void @@ -211,11 +234,14 @@ FeeVoteImpl::doVoting( detail::VotableValue incReserveVote( lastClosedLedger->fees().increment, target_.owner_reserve); + detail::VotableValue hookGasPriceVote( + lastClosedLedger->fees().hookGasPrice, target_.hook_gas_price); + auto const& rules = lastClosedLedger->rules(); if (rules.enabled(featureXRPFees)) { auto doVote = [](std::shared_ptr const& val, - detail::VotableValue& value, + detail::VotableValue& value, SF_AMOUNT const& xrpField) { if (auto const field = ~val->at(~xrpField); field && field->native()) @@ -244,7 +270,7 @@ FeeVoteImpl::doVoting( else { auto doVote = [](std::shared_ptr const& val, - detail::VotableValue& value, + detail::VotableValue& value, auto const& valueField) { if (auto const field = val->at(~valueField)) { @@ -275,6 +301,23 @@ FeeVoteImpl::doVoting( doVote(val, incReserveVote, sfReserveIncrement); } } + if (rules.enabled(featureHookFeeV2)) + { + auto doVote = [](std::shared_ptr const& val, + detail::VotableValue& value, + SF_UINT32 const& valueField) { + if (auto const field = ~val->at(~valueField); field) + value.addVote(field.value()); + else + value.noVote(); + }; + for (auto const& val : set) + { + if (!val->isTrusted()) + continue; + doVote(val, hookGasPriceVote, sfHookGasPrice); + } + } // choose our positions // TODO: Use structured binding once LLVM issue @@ -283,15 +326,18 @@ FeeVoteImpl::doVoting( auto const baseFee = baseFeeVote.getVotes(); auto const baseReserve = baseReserveVote.getVotes(); auto const incReserve = incReserveVote.getVotes(); + auto const hookGasPrice = hookGasPriceVote.getVotes(); auto const seq = lastClosedLedger->info().seq + 1; // add transactions to our position - if (baseFee.second || baseReserve.second || incReserve.second) + if (baseFee.second || baseReserve.second || incReserve.second || + hookGasPrice.second) { JLOG(journal_.warn()) << "We are voting for a fee change: " << baseFee.first << "/" - << baseReserve.first << "/" << incReserve.first; + << baseReserve.first << "/" << incReserve.first << "/" + << hookGasPrice.first; STTx feeTx(ttFEE, [=, &rules](auto& obj) { obj[sfAccount] = AccountID(); @@ -315,6 +361,8 @@ FeeVoteImpl::doVoting( incReserveVote.current()); obj[sfReferenceFeeUnits] = Config::FEE_UNITS_DEPRECATED; } + if (rules.enabled(featureHookFeeV2)) + obj[sfHookGasPrice] = hookGasPrice.first; }); uint256 txID = feeTx.getTransactionID(); diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp index 0e5b8ef5f5..1d092d9b47 100644 --- a/src/ripple/app/misc/NetworkOPs.cpp +++ b/src/ripple/app/misc/NetworkOPs.cpp @@ -2191,6 +2191,9 @@ NetworkOPsImp::pubValidation(std::shared_ptr const& val) reserveIncXRP && reserveIncXRP->native()) jvObj[jss::reserve_inc] = reserveIncXRP->xrp().jsonClipped(); + if (auto const hookGasPrice = ~val->at(~sfHookGasPrice); hookGasPrice) + jvObj[jss::hook_gas_price] = *hookGasPrice; + for (auto i = mStreamMaps[sValidations].begin(); i != mStreamMaps[sValidations].end();) { @@ -2624,12 +2627,16 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) l[jss::seq] = Json::UInt(lpClosed->info().seq); l[jss::hash] = to_string(lpClosed->info().hash); + auto const hookFeeV2 = lpClosed->rules().enabled(featureHookFeeV2); + if (!human) { l[jss::base_fee] = baseFee.jsonClipped(); l[jss::reserve_base] = lpClosed->fees().accountReserve(0).jsonClipped(); l[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped(); + if (hookFeeV2) + l[jss::hook_gas_price] = lpClosed->fees().hookGasPrice; l[jss::close_time] = Json::Value::UInt( lpClosed->info().closeTime.time_since_epoch().count()); } @@ -2645,6 +2652,8 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters) lpClosed->fees().accountReserve(0).decimalXRP(); l[jss::reserve_inc_native] = lpClosed->fees().increment.decimalXRP(); + if (hookFeeV2) + l[jss::hook_gas_price] = lpClosed->fees().hookGasPrice; auto const nowOffset = app_.timeKeeper().nowOffset(); if (std::abs(nowOffset.count()) >= 60) @@ -2958,6 +2967,9 @@ NetworkOPsImp::pubLedger(std::shared_ptr const& lpAccepted) jvObj[jss::reserve_inc] = lpAccepted->fees().increment.jsonClipped(); + if (lpAccepted->rules().enabled(featureHookFeeV2)) + jvObj[jss::hook_gas_price] = lpAccepted->fees().hookGasPrice; + jvObj[jss::txn_count] = Json::UInt(alpAccepted->size()); if (mMode >= OperatingMode::SYNCING) @@ -3982,6 +3994,8 @@ NetworkOPsImp::subLedger(InfoSub::ref isrListener, Json::Value& jvResult) jvResult[jss::reserve_base] = lpClosed->fees().accountReserve(0).jsonClipped(); jvResult[jss::reserve_inc] = lpClosed->fees().increment.jsonClipped(); + if (lpClosed->rules().enabled(featureHookFeeV2)) + jvResult[jss::hook_gas_price] = lpClosed->fees().hookGasPrice; } if ((mMode >= OperatingMode::SYNCING) && !isNeedNetworkLedger()) diff --git a/src/ripple/app/tx/impl/Change.cpp b/src/ripple/app/tx/impl/Change.cpp index da13ebf01b..a7e3975ff3 100644 --- a/src/ripple/app/tx/impl/Change.cpp +++ b/src/ripple/app/tx/impl/Change.cpp @@ -151,6 +151,16 @@ Change::preclaim(PreclaimContext const& ctx) ctx.tx.isFieldPresent(sfReserveIncrementDrops)) return temDISABLED; } + if (ctx.view.rules().enabled(featureHookFeeV2)) + { + if (!ctx.tx.isFieldPresent(sfHookGasPrice)) + return temMALFORMED; + } + else + { + if (ctx.tx.isFieldPresent(sfHookGasPrice)) + return temDISABLED; + } return tesSUCCESS; case ttAMENDMENT: case ttUNL_MODIFY: @@ -1026,6 +1036,8 @@ Change::applyFee() set(feeObject, ctx_.tx, sfReserveBase); set(feeObject, ctx_.tx, sfReserveIncrement); } + if (view().rules().enabled(featureHookFeeV2)) + set(feeObject, ctx_.tx, sfHookGasPrice); view().update(feeObject); diff --git a/src/ripple/app/tx/impl/Transactor.cpp b/src/ripple/app/tx/impl/Transactor.cpp index 3fe9738da9..b0869c48d7 100644 --- a/src/ripple/app/tx/impl/Transactor.cpp +++ b/src/ripple/app/tx/impl/Transactor.cpp @@ -439,7 +439,7 @@ Transactor::calculateBaseFee(ReadView const& view, STTx const& tx) // transaction. do { - hookExecutionFee += hook::hookCostToFee(hookCost); + hookExecutionFee += hook::hookCostToFee(view, hookCost); if (accumulator * burden < accumulator) break; @@ -1635,7 +1635,7 @@ Transactor::doTSH( calculateHookChainFee(view, ctx_.tx, klTshHook, !canRollback); XRPAmount tshFeeDrops{tshFee.first}; - tshFeeDrops += hook::hookCostToFee(tshFee.second); + tshFeeDrops += hook::hookCostToFee(view, tshFee.second); // no hooks to execute, skip tsh if (tshFeeDrops == 0) diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h index 0909f88ac1..1995f9b723 100644 --- a/src/ripple/core/Config.h +++ b/src/ripple/core/Config.h @@ -79,6 +79,9 @@ struct FeeSetup /** The per-owned item reserve requirement in drops. */ XRPAmount owner_reserve{2 * DROPS_PER_XRP}; + /** The gas price for hooks in drops. */ + std::uint32_t hook_gas_price{1'000'000}; // TODO: default value + /* (Remember to update the example cfg files when changing any of these * values.) */ }; diff --git a/src/ripple/core/impl/Config.cpp b/src/ripple/core/impl/Config.cpp index 9fd23f33e0..451e54d286 100644 --- a/src/ripple/core/impl/Config.cpp +++ b/src/ripple/core/impl/Config.cpp @@ -1079,6 +1079,13 @@ setup_FeeVote(Section const& section) if (set(temp, "owner_reserve", section)) setup.owner_reserve = temp; } + { + std::uint32_t temp; + if (set(temp, "hook_gas_price", section)) + { + setup.hook_gas_price = temp; + } + } return setup; } } // namespace ripple diff --git a/src/ripple/ledger/ReadView.h b/src/ripple/ledger/ReadView.h index e019d602f0..c634a858ba 100644 --- a/src/ripple/ledger/ReadView.h +++ b/src/ripple/ledger/ReadView.h @@ -52,6 +52,8 @@ struct Fees XRPAmount reserve{0}; // Reserve base (drops) XRPAmount increment{0}; // Reserve increment (drops) + std::uint32_t hookGasPrice{0}; // price per cost unit for hooks + explicit Fees() = default; Fees(Fees const&) = default; Fees& diff --git a/src/ripple/protocol/SField.h b/src/ripple/protocol/SField.h index 7042a6bfe1..99a5256327 100644 --- a/src/ripple/protocol/SField.h +++ b/src/ripple/protocol/SField.h @@ -414,6 +414,7 @@ extern SF_UINT32 const sfXahauActivationLgrSeq; extern SF_UINT32 const sfDelaySeconds; extern SF_UINT32 const sfRepeatCount; extern SF_UINT32 const sfStartTime; +extern SF_UINT32 const sfHookGasPrice; // 64-bit integers (common) extern SF_UINT64 const sfIndexNext; diff --git a/src/ripple/protocol/impl/LedgerFormats.cpp b/src/ripple/protocol/impl/LedgerFormats.cpp index 13d396f2fc..066b1790c7 100644 --- a/src/ripple/protocol/impl/LedgerFormats.cpp +++ b/src/ripple/protocol/impl/LedgerFormats.cpp @@ -185,6 +185,8 @@ LedgerFormats::LedgerFormats() {sfXahauActivationLgrSeq, soeOPTIONAL}, {sfAccountCount, soeOPTIONAL}, {sfNetworkID, soeOPTIONAL}, + // Hooks Cost + {sfHookGasPrice, soeOPTIONAL}, }, commonFields); diff --git a/src/ripple/protocol/impl/SField.cpp b/src/ripple/protocol/impl/SField.cpp index 5eb508d1a5..f02ae0f2c9 100644 --- a/src/ripple/protocol/impl/SField.cpp +++ b/src/ripple/protocol/impl/SField.cpp @@ -158,6 +158,7 @@ CONSTRUCT_TYPED_SFIELD(sfLockCount, "LockCount", UINT32, CONSTRUCT_TYPED_SFIELD(sfFirstNFTokenSequence, "FirstNFTokenSequence", UINT32, 50); +CONSTRUCT_TYPED_SFIELD(sfHookGasPrice, "HookGasPrice", UINT32, 92); CONSTRUCT_TYPED_SFIELD(sfStartTime, "StartTime", UINT32, 93); CONSTRUCT_TYPED_SFIELD(sfRepeatCount, "RepeatCount", UINT32, 94); CONSTRUCT_TYPED_SFIELD(sfDelaySeconds, "DelaySeconds", UINT32, 95); diff --git a/src/ripple/protocol/impl/STValidation.cpp b/src/ripple/protocol/impl/STValidation.cpp index e62a81733b..460c149894 100644 --- a/src/ripple/protocol/impl/STValidation.cpp +++ b/src/ripple/protocol/impl/STValidation.cpp @@ -66,6 +66,8 @@ STValidation::validationFormat() {sfBaseFeeDrops, soeOPTIONAL}, {sfReserveBaseDrops, soeOPTIONAL}, {sfReserveIncrementDrops, soeOPTIONAL}, + // HookCost + {sfHookGasPrice, soeOPTIONAL}, }; // clang-format on diff --git a/src/ripple/protocol/impl/TxFormats.cpp b/src/ripple/protocol/impl/TxFormats.cpp index e6334569d3..d741d5de2c 100644 --- a/src/ripple/protocol/impl/TxFormats.cpp +++ b/src/ripple/protocol/impl/TxFormats.cpp @@ -196,6 +196,8 @@ TxFormats::TxFormats() {sfBaseFeeDrops, soeOPTIONAL}, {sfReserveBaseDrops, soeOPTIONAL}, {sfReserveIncrementDrops, soeOPTIONAL}, + // HookCost + {sfHookGasPrice, soeOPTIONAL}, }, commonFields); diff --git a/src/ripple/protocol/jss.h b/src/ripple/protocol/jss.h index 6bc315bd42..2e1c57210b 100644 --- a/src/ripple/protocol/jss.h +++ b/src/ripple/protocol/jss.h @@ -369,6 +369,7 @@ JSS(highest_ticket); // out: AccountInfo JSS(historical_perminute); // historical_perminute. JSS(hook); // in: LedgerEntry JSS(hook_definition); // in: LedgerEntry +JSS(hook_gas_price); // JSS(hook_state); // in: LedgerEntry JSS(hostid); // out: NetworkOPs JSS(hotwallet); // in: GatewayBalances diff --git a/src/test/app/FeeVote_test.cpp b/src/test/app/FeeVote_test.cpp index ad38aefb20..f3932007d3 100644 --- a/src/test/app/FeeVote_test.cpp +++ b/src/test/app/FeeVote_test.cpp @@ -37,36 +37,42 @@ class FeeVote_test : public beast::unit_test::suite BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve); BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve); + BEAST_EXPECT(setup.hook_gas_price == defaultSetup.hook_gas_price); } { Section config; config.append( {"reference_fee = 50", "account_reserve = 1234567", - "owner_reserve = 1234"}); + "owner_reserve = 1234", + "hook_gas_price = 12345"}); auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == 50); BEAST_EXPECT(setup.account_reserve == 1234567); BEAST_EXPECT(setup.owner_reserve == 1234); + BEAST_EXPECT(setup.hook_gas_price == 12345); } { Section config; config.append( {"reference_fee = blah", "account_reserve = yada", - "owner_reserve = foo"}); + "owner_reserve = foo", + "hook_gas_price = baa"}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve); BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve); + BEAST_EXPECT(setup.hook_gas_price == defaultSetup.hook_gas_price); } { Section config; config.append( {"reference_fee = -50", "account_reserve = -1234567", - "owner_reserve = -1234"}); + "owner_reserve = -1234", + "hook_gas_price = -12345"}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); @@ -74,6 +80,8 @@ class FeeVote_test : public beast::unit_test::suite setup.account_reserve == static_cast(-1234567)); BEAST_EXPECT( setup.owner_reserve == static_cast(-1234)); + BEAST_EXPECT( + setup.hook_gas_price == static_cast(-12345)); } { const auto big64 = std::to_string( @@ -84,12 +92,14 @@ class FeeVote_test : public beast::unit_test::suite config.append( {"reference_fee = " + big64, "account_reserve = " + big64, - "owner_reserve = " + big64}); + "owner_reserve = " + big64, + "hook_gas_price = " + big64}); // Illegal values are ignored, and the defaults left unchanged auto setup = setup_FeeVote(config); BEAST_EXPECT(setup.reference_fee == defaultSetup.reference_fee); BEAST_EXPECT(setup.account_reserve == defaultSetup.account_reserve); BEAST_EXPECT(setup.owner_reserve == defaultSetup.owner_reserve); + BEAST_EXPECT(setup.hook_gas_price == defaultSetup.hook_gas_price); } } diff --git a/src/test/app/Import_test.cpp b/src/test/app/Import_test.cpp index 0579528362..5e5e69b9d8 100644 --- a/src/test/app/Import_test.cpp +++ b/src/test/app/Import_test.cpp @@ -5786,7 +5786,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 1999998), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 1999998), features}; // confirm total coins header @@ -5830,7 +5837,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 1999998), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 1999998), features}; // confirm total coins header @@ -5875,7 +5889,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 1999998), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 1999998), features}; // confirm total coins header @@ -5921,7 +5942,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 4999999), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 4999999), features}; // confirm total coins header @@ -5965,7 +5993,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 19999999), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 19999999), features}; // confirm total coins header @@ -6009,7 +6044,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 29999998), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 29999998), features}; // confirm total coins header @@ -6053,7 +6095,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 29999998), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 29999998), features}; // confirm total coins header @@ -6096,7 +6145,14 @@ class Import_test : public beast::unit_test::suite test::jtx::Env env{ *this, network::makeGenesisConfig( - features, 21337, keys, "10", "1000000", "200000", 50000000), + features, + 21337, + keys, + "10", + "1000000", + "200000", + "1000000", + 50000000), features}; // confirm total coins header diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 4e97461380..b6ce50c50b 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -98,6 +98,7 @@ class SetHook0_test : public beast::unit_test::suite std::string fee, std::string a_res, std::string o_res, + std::string g_res, uint32_t ledgerID) { using namespace jtx; @@ -224,7 +225,8 @@ class SetHook0_test : public beast::unit_test::suite config.append( {"reference_fee = " + fee, "account_reserve = " + a_res, - "owner_reserve = " + o_res}); + "owner_reserve = " + o_res, + "hook_gas_price = " + g_res}); auto setup = setup_FeeVote(config); cfg->FEES = setup; return cfg; @@ -1237,7 +1239,8 @@ class SetHook0_test : public beast::unit_test::suite test::jtx::Env env{ *this, - makePageCapConfig(features, 21337, "10", "1000000", "200000", 0), + makePageCapConfig( + features, 21337, "10", "1000000", "200000", "1000000", 0), features}; bool const hasFix = env.current()->rules().enabled(fixPageCap); @@ -13467,8 +13470,6 @@ class SetHook0_test : public beast::unit_test::suite void testWithFeatures(FeatureBitset features) { - test_emit(features); // - return; testHooksOwnerDir(features); testHooksDisabled(features); testTxStructure(features); diff --git a/src/test/app/Wildcard_test.cpp b/src/test/app/Wildcard_test.cpp index fc330b449f..03bedff90c 100644 --- a/src/test/app/Wildcard_test.cpp +++ b/src/test/app/Wildcard_test.cpp @@ -35,7 +35,8 @@ class Wildcard_test : public beast::unit_test::suite config.append( {"reference_fee = 10", "account_reserve = 1000000", - "owner_reserve = 200000"}); + "owner_reserve = 200000", + "hook_gas_price = 1000000"}); auto setup = setup_FeeVote(config); cfg->FEES = setup; return cfg; diff --git a/src/test/app/XahauGenesis_test.cpp b/src/test/app/XahauGenesis_test.cpp index 8353a3ce9a..e32d69235d 100644 --- a/src/test/app/XahauGenesis_test.cpp +++ b/src/test/app/XahauGenesis_test.cpp @@ -4818,6 +4818,7 @@ struct XahauGenesis_test : public beast::unit_test::suite std::string fee, std::string a_res, std::string o_res, + std::string g_res, uint32_t ledgerID) { using namespace jtx; @@ -4925,7 +4926,8 @@ struct XahauGenesis_test : public beast::unit_test::suite config.append( {"reference_fee = " + fee, "account_reserve = " + a_res, - "owner_reserve = " + o_res}); + "owner_reserve = " + o_res, + "hook_gas_price = " + g_res}); auto setup = setup_FeeVote(config); cfg->FEES = setup; @@ -4963,6 +4965,7 @@ struct XahauGenesis_test : public beast::unit_test::suite "10", "1000000", "200000", + "1000000", 0), features - featureXahauGenesis}; diff --git a/src/test/jtx/impl/envconfig.cpp b/src/test/jtx/impl/envconfig.cpp index ce2c2ae60a..8adc969a9f 100644 --- a/src/test/jtx/impl/envconfig.cpp +++ b/src/test/jtx/impl/envconfig.cpp @@ -48,6 +48,7 @@ setupConfigForUnitTests(Config& cfg) cfg.FEES.reference_fee = 10; cfg.FEES.account_reserve = XRP(200).value().xrp().drops(); cfg.FEES.owner_reserve = XRP(50).value().xrp().drops(); + cfg.FEES.hook_gas_price = 1'000'000; cfg.overwrite(ConfigSection::nodeDatabase(), "type", "rwdb"); cfg.overwrite(ConfigSection::nodeDatabase(), "path", "main"); diff --git a/src/test/jtx/impl/network.cpp b/src/test/jtx/impl/network.cpp index e08976ca35..2c0fe4d168 100644 --- a/src/test/jtx/impl/network.cpp +++ b/src/test/jtx/impl/network.cpp @@ -37,7 +37,8 @@ makeNetworkConfig( uint32_t networkID, std::string fee, std::string a_res, - std::string o_res) + std::string o_res, + std::string g_res) { using namespace jtx; return envconfig([&](std::unique_ptr cfg) { @@ -46,9 +47,12 @@ makeNetworkConfig( config.append( {"reference_fee = " + fee, "account_reserve = " + a_res, - "owner_reserve = " + o_res}); + "owner_reserve = " + o_res, + "hook_gas_price = " + g_res}); auto setup = setup_FeeVote(config); cfg->FEES = setup; + cfg->section("voting") = config; + // cfg->START_UP = Config::FRESH; return cfg; }); } @@ -59,7 +63,8 @@ makeNetworkVLConfig( std::vector keys, std::string fee, std::string a_res, - std::string o_res) + std::string o_res, + std::string g_res) { using namespace jtx; return envconfig([&](std::unique_ptr cfg) { @@ -68,7 +73,8 @@ makeNetworkVLConfig( config.append( {"reference_fee = " + fee, "account_reserve = " + a_res, - "owner_reserve = " + o_res}); + "owner_reserve = " + o_res, + "hook_gas_price = " + g_res}); auto setup = setup_FeeVote(config); cfg->FEES = setup; @@ -98,6 +104,7 @@ makeGenesisConfig( std::string fee, std::string a_res, std::string o_res, + std::string g_res, uint32_t ledgerID) { using namespace jtx; @@ -129,7 +136,8 @@ makeGenesisConfig( config.append( {"reference_fee = " + fee, "account_reserve = " + a_res, - "owner_reserve = " + o_res}); + "owner_reserve = " + o_res, + "hook_gas_price = " + g_res}); auto setup = setup_FeeVote(config); cfg->FEES = setup; diff --git a/src/test/jtx/network.h b/src/test/jtx/network.h index b43367cdee..85267c1f41 100644 --- a/src/test/jtx/network.h +++ b/src/test/jtx/network.h @@ -35,7 +35,8 @@ makeNetworkConfig( uint32_t networkID, std::string fee = "10", std::string a_res = "1000000", - std::string o_res = "200000"); + std::string o_res = "200000", + std::string g_res = "1000000"); std::unique_ptr makeNetworkVLConfig( @@ -43,7 +44,8 @@ makeNetworkVLConfig( std::vector keys, std::string fee = "10", std::string a_res = "1000000", - std::string o_res = "200000"); + std::string o_res = "200000", + std::string g_res = "1000000"); std::unique_ptr makeGenesisConfig( @@ -53,6 +55,7 @@ makeGenesisConfig( std::string fee = "10", std::string a_res = "1000000", std::string o_res = "200000", + std::string g_res = "1000000", uint32_t ledgerID = 0); } // namespace network From a4ca4e9b452c6ab78e0f3963b4e2a70bda53ed4c Mon Sep 17 00:00:00 2001 From: tequ Date: Mon, 22 Dec 2025 13:00:44 +0900 Subject: [PATCH 29/33] Update sfcodes.h --- hook/sfcodes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/hook/sfcodes.h b/hook/sfcodes.h index 0c79ccd153..100c480512 100644 --- a/hook/sfcodes.h +++ b/hook/sfcodes.h @@ -63,6 +63,7 @@ #define sfEmitGeneration ((2U << 16U) + 46U) #define sfLockCount ((2U << 16U) + 49U) #define sfFirstNFTokenSequence ((2U << 16U) + 50U) +#define sfHookGasPrice ((2U << 16U) + 92U) #define sfStartTime ((2U << 16U) + 93U) #define sfRepeatCount ((2U << 16U) + 94U) #define sfDelaySeconds ((2U << 16U) + 95U) From 3d04cbf8c89644e522e300e438c758cdca81264a Mon Sep 17 00:00:00 2001 From: tequ Date: Mon, 22 Dec 2025 16:55:50 +0900 Subject: [PATCH 30/33] Update tests --- src/test/app/GenesisMint_test.cpp | 36 ++++++- src/test/app/SetHookTSH_test.cpp | 144 ++++++++++++++++++++++++- src/test/app/SetHook_test.cpp | 115 +++++++++++++++++++- src/test/app/SetHook_wasm.h | 111 +++++++++---------- src/test/app/Touch_test.cpp | 9 ++ src/test/jtx/impl/network.cpp | 1 - src/test/rpc/AccountNamespace_test.cpp | 9 ++ src/test/rpc/LedgerRPC_test.cpp | 8 ++ 8 files changed, 365 insertions(+), 68 deletions(-) diff --git a/src/test/app/GenesisMint_test.cpp b/src/test/app/GenesisMint_test.cpp index 9f183f0c69..f92c6d2e1b 100644 --- a/src/test/app/GenesisMint_test.cpp +++ b/src/test/app/GenesisMint_test.cpp @@ -24,6 +24,23 @@ namespace ripple { namespace test { struct GenesisMint_test : public beast::unit_test::suite { + // Close the ledger until doVoting for FeatureHookFeeV2 is called + void + incLgrSeqForGasPriceEnabled(jtx::Env& env) + { + if (!env.current()->rules().enabled(featureHookFeeV2)) + return; + + BEAST_EXPECT(!env.le(keylet::fees())->isFieldPresent(sfHookGasPrice)); + + auto const seq = env.current()->info().seq; + BEAST_EXPECT(seq <= 256); + for (int i = seq; i <= 256; ++i) + env.close(); + env.close(); + BEAST_EXPECT(env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } + void validateEmittedTxn(jtx::Env& env, std::string result, uint64_t lineno) { @@ -95,6 +112,8 @@ struct GenesisMint_test : public beast::unit_test::suite using namespace std::literals::chrono_literals; Env env{*this, envconfig(), features}; + incLgrSeqForGasPriceEnabled(env); + auto const alice = Account("alice"); auto const bob = Account("bob"); auto const invoker = Account("invoker"); @@ -139,6 +158,8 @@ struct GenesisMint_test : public beast::unit_test::suite features, nullptr, beast::severities::kDisabled}; + incLgrSeqForGasPriceEnabled(env); + auto const alice = Account("alice"); auto const bob = Account("bob"); auto const invoker = Account("invoker"); @@ -233,14 +254,20 @@ struct GenesisMint_test : public beast::unit_test::suite auto acc = env.le(keylet::account(carol.id())); BEAST_EXPECT( acc->getFieldAmount(sfBalance).xrp().drops() == 67890000000ULL); - BEAST_EXPECT(acc->getFieldU32(sfSequence) == 60); + if (env.current()->rules().enabled(featureHookFeeV2)) + BEAST_EXPECT(acc->getFieldU32(sfSequence) == 2610); + else + BEAST_EXPECT(acc->getFieldU32(sfSequence) == 60); } { auto acc = env.le(keylet::account(david.id())); BEAST_EXPECT( acc->getFieldAmount(sfBalance).xrp().drops() == 12345000000ULL); - BEAST_EXPECT(acc->getFieldU32(sfSequence) == 60); + if (env.current()->rules().enabled(featureHookFeeV2)) + BEAST_EXPECT(acc->getFieldU32(sfSequence) == 2610); + else + BEAST_EXPECT(acc->getFieldU32(sfSequence) == 60); } // lots of entries @@ -646,6 +673,8 @@ struct GenesisMint_test : public beast::unit_test::suite using namespace std::literals::chrono_literals; Env env{*this, envconfig(), features}; + incLgrSeqForGasPriceEnabled(env); + auto const alice = Account("alice"); auto const bob = Account("bob"); env.fund(XRP(10000), alice, bob); @@ -668,6 +697,8 @@ struct GenesisMint_test : public beast::unit_test::suite using namespace std::literals::chrono_literals; Env env{*this, envconfig(), features}; + incLgrSeqForGasPriceEnabled(env); + auto const alice = Account("alice"); auto const bob = Account("bob"); env.fund(XRP(10000), alice, bob); @@ -700,6 +731,7 @@ struct GenesisMint_test : public beast::unit_test::suite testWithFeats(sa); testWithFeats(sa - fixXahauV1); testWithFeats(sa - fixHookAPI20251128); + testWithFeats(sa - featureHookFeeV2); } }; diff --git a/src/test/app/SetHookTSH_test.cpp b/src/test/app/SetHookTSH_test.cpp index 5df238a986..880b11fa51 100644 --- a/src/test/app/SetHookTSH_test.cpp +++ b/src/test/app/SetHookTSH_test.cpp @@ -629,6 +629,23 @@ struct SetHookTSH0_test : public beast::unit_test::suite 0x61U, 0x72U, 0x74U, 0x2EU, 0x22U, 0x00U, 0x22U, 0x74U, 0x73U, 0x68U, 0x2EU, 0x63U, 0x3AU, 0x20U, 0x45U, 0x6EU, 0x64U, 0x2EU, 0x22U}; + // Close the ledger until doVoting for FeatureHookFeeV2 is called + void + incLgrSeqForGasPriceEnabled(jtx::Env& env) + { + if (!env.current()->rules().enabled(featureHookFeeV2)) + return; + + BEAST_EXPECT(!env.le(keylet::fees())->isFieldPresent(sfHookGasPrice)); + + auto const seq = env.current()->info().seq; + BEAST_EXPECT(seq <= 256); + for (int i = seq; i <= 256; ++i) + env.close(); + env.close(); + BEAST_EXPECT(env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } + void addWeakTSH(jtx::Env& env, jtx::Account const& account) { @@ -789,6 +806,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -830,6 +848,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const bene = Account("bob"); @@ -882,6 +901,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -917,6 +937,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -962,6 +983,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -997,6 +1019,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1041,6 +1064,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1073,6 +1097,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1114,6 +1139,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1151,6 +1177,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1188,6 +1215,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -1256,6 +1284,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account("issuer"); @@ -1289,6 +1318,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account("issuer"); @@ -1331,6 +1361,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("gw"); auto const holder = Account("bob"); @@ -1368,6 +1399,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("gw"); auto const holder = Account("bob"); @@ -1420,6 +1452,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const authed = Account("alice"); auto const account = Account("bob"); @@ -1453,6 +1486,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const authed = Account("alice"); auto const account = Account("bob"); @@ -1509,6 +1543,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1553,6 +1588,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -1607,6 +1643,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1651,6 +1688,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1695,6 +1733,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -1766,6 +1805,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1817,6 +1857,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -1878,6 +1919,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1929,6 +1971,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -1984,6 +2027,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -2062,6 +2106,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2099,6 +2144,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2136,6 +2182,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -2200,6 +2247,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2241,6 +2289,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2282,6 +2331,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2323,6 +2373,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2364,6 +2415,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -2432,6 +2484,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2480,6 +2533,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2532,6 +2586,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2580,6 +2635,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -2632,6 +2688,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -2715,6 +2772,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = env.master; @@ -2766,6 +2824,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = env.master; @@ -2818,6 +2877,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = env.master; @@ -2905,6 +2965,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite network::makeNetworkVLConfig( 21337, keys, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account("bob"); @@ -2945,6 +3006,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite network::makeNetworkVLConfig( 21337, keys, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account("bob"); @@ -3002,6 +3064,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -3035,6 +3098,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -3082,6 +3146,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const gw = Account{"gateway"}; @@ -3131,6 +3196,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const gw = Account{"gateway"}; @@ -3168,6 +3234,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const cross = Account("bob"); @@ -3212,6 +3279,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("carol"); auto const cross = Account("bob"); @@ -3272,6 +3340,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3302,6 +3371,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3332,6 +3402,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const cross = Account("bob"); @@ -3373,6 +3444,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const cross = Account("bob"); @@ -3451,6 +3523,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3496,6 +3569,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3542,6 +3616,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3590,6 +3665,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3638,6 +3714,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -3709,6 +3786,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3743,6 +3821,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3777,6 +3856,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -3837,6 +3917,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3877,6 +3958,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -3918,6 +4000,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -3987,6 +4070,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -4033,6 +4117,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -4063,6 +4148,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -4106,6 +4192,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const signer1 = Account{"bob"}; @@ -4139,6 +4226,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const signer1 = Account{"bob"}; @@ -4201,6 +4289,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -4243,6 +4332,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account{"gw"}; @@ -4274,6 +4364,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account{"gw"}; @@ -4334,6 +4425,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const buyer = Account("carol"); @@ -4373,6 +4465,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const buyer = Account("carol"); @@ -4416,6 +4509,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const buyer = Account("carol"); @@ -4456,6 +4550,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const buyer = Account("carol"); @@ -4509,6 +4604,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4557,6 +4653,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4614,6 +4711,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4663,6 +4761,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4720,6 +4819,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4778,6 +4878,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4836,6 +4937,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4897,6 +4999,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -4957,6 +5060,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5016,6 +5120,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5075,6 +5180,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -5145,6 +5251,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5201,6 +5308,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -5267,6 +5375,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -5334,6 +5443,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5400,6 +5510,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5453,6 +5564,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5507,6 +5619,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5560,6 +5673,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5613,6 +5727,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5667,6 +5782,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const issuer = Account("alice"); auto const owner = Account("bob"); @@ -5724,6 +5840,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -5817,6 +5934,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account{"gw"}; @@ -5848,6 +5966,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account{"gw"}; @@ -5877,6 +5996,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -5914,6 +6034,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const issuer = Account{"gw"}; @@ -5955,6 +6076,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -6015,6 +6137,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -6045,6 +6168,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account{"bob"}; @@ -6075,6 +6199,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -6110,6 +6235,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); bool const withIOUIssuerWeakTSH = env.current()->rules().enabled(featureIOUIssuerWeakTSH); @@ -6163,6 +6289,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -6219,6 +6346,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); auto const dest = Account("bob"); @@ -6284,6 +6412,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -6328,6 +6457,7 @@ struct SetHookTSH0_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + incLgrSeqForGasPriceEnabled(env); auto const account = Account("alice"); env.fund(XRP(1000), account); @@ -6531,11 +6661,13 @@ struct SetHookTSH0_test : public beast::unit_test::suite using namespace test::jtx; static FeatureBitset const all{supported_amendments()}; - static std::array const feats{ + static std::array const feats{ all, - all - fixXahauV1 - fixXahauV2 - featureIOUIssuerWeakTSH, - all - fixXahauV2 - featureIOUIssuerWeakTSH, - all - featureIOUIssuerWeakTSH, + all - fixXahauV1 - fixXahauV2 - featureIOUIssuerWeakTSH - + featureHookFeeV2, + all - fixXahauV2 - featureIOUIssuerWeakTSH - featureHookFeeV2, + all - featureIOUIssuerWeakTSH - featureHookFeeV2, + all - featureHookFeeV2, }; if (BEAST_EXPECT(instance < feats.size())) @@ -6566,12 +6698,14 @@ struct SetHookTSH0_test : public beast::unit_test::suite SETHOOKTSH_TEST(1, false) SETHOOKTSH_TEST(2, false) -SETHOOKTSH_TEST(3, true) +SETHOOKTSH_TEST(3, false) +SETHOOKTSH_TEST(4, true) BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH0, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH1, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH2, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH3, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(SetHookTSH4, app, ripple, 2); } // namespace test } // namespace ripple diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index b6ce50c50b..99465d04d0 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -84,6 +84,23 @@ class SetHook0_test : public beast::unit_test::suite jv[jss::Flags] = hsfOVERRIDE; } + // Close the ledger until doVoting for FeatureHookFeeV2 is called + void + incLgrSeqForGasPriceEnabled(jtx::Env& env) + { + if (!env.current()->rules().enabled(featureHookFeeV2)) + return; + + BEAST_EXPECT(!env.le(keylet::fees())->isFieldPresent(sfHookGasPrice)); + + auto const seq = env.current()->info().seq; + BEAST_EXPECT(seq <= 256); + for (int i = seq; i <= 256; ++i) + env.close(); + env.close(); + BEAST_EXPECT(env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } + public: // This is a large fee, large enough that we can set most small test hooks // without running into fee issues we only want to test fee code specifically in @@ -241,6 +258,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const gw = Account{"gateway"}; @@ -870,6 +888,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Checks malformed nsdelete operation"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); bool const fixNS = env.current()->rules().enabled(fixNSDelete); bool const hasHookCanEmit = @@ -1154,6 +1173,7 @@ class SetHook0_test : public beast::unit_test::suite 0x6aU, 0x24U, 0x00U, 0x0bU}; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); bool const fixNS = env.current()->rules().enabled(fixNSDelete); auto const bob = Account{"bob"}; @@ -1242,6 +1262,7 @@ class SetHook0_test : public beast::unit_test::suite makePageCapConfig( features, 21337, "10", "1000000", "200000", "1000000", 0), features}; + incLgrSeqForGasPriceEnabled(env); bool const hasFix = env.current()->rules().enabled(fixPageCap); @@ -2323,6 +2344,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test accept() hookapi"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -2344,6 +2366,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test rollback() hookapi"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -2368,6 +2391,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test guards"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -2588,6 +2612,7 @@ class SetHook0_test : public beast::unit_test::suite *this, withCost ? features | featureHookFeeV2 : features - featureHookFeeV2}; + incLgrSeqForGasPriceEnabled(env); env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); @@ -2653,6 +2678,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test emit"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3157,6 +3183,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3275,6 +3302,7 @@ class SetHook0_test : public beast::unit_test::suite f = f - fixHookAPI20251128; Env env{*this, f}; + incLgrSeqForGasPriceEnabled(env); env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); @@ -3316,6 +3344,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3380,6 +3409,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3429,6 +3459,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3469,6 +3500,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_compare"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3602,6 +3634,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_divide"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3801,6 +3834,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_int"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -3930,6 +3964,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_invert"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4018,6 +4053,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_log"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4101,6 +4137,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_mantissa"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4230,6 +4267,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_mulratio"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4385,6 +4423,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_multiply"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4684,6 +4723,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_negate"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4755,6 +4795,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_one"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4796,6 +4837,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_root"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4874,6 +4916,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_set"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -4947,6 +4990,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_sign"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -5060,6 +5104,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_sto"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -5265,6 +5310,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_sto_set"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -5407,6 +5453,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test float_sum"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -5589,6 +5636,7 @@ class SetHook0_test : public beast::unit_test::suite auto const test = [&](Account alice) -> void { Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; env.fund(XRP(10000), alice); @@ -5710,6 +5758,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test hook_again"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -5788,6 +5837,7 @@ class SetHook0_test : public beast::unit_test::suite auto const test = [&](Account alice) -> void { Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; env.fund(XRP(10000), alice); @@ -5947,6 +5997,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test hook_param"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6074,6 +6125,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test hook_param_set"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6283,6 +6335,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test hook_pos"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6337,6 +6390,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test hook_skip"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6459,6 +6513,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test ledger_keylet"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6561,6 +6616,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -6635,6 +6691,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test ledger_last_time"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6703,6 +6760,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -6801,6 +6859,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test ledger_seq"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6860,6 +6919,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test meta_slot"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -6953,6 +7013,7 @@ class SetHook0_test : public beast::unit_test::suite *this, network::makeNetworkVLConfig(21337, keys), features - featureHooksUpdate1}; + incLgrSeqForGasPriceEnabled(env); auto const master = Account("masterpassphrase"); env(noop(master), fee(10'000'000'000), ter(tesSUCCESS)); @@ -7078,6 +7139,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test otxn_field"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7148,6 +7210,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test otxn_id"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7231,6 +7294,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test otxn_slot"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7313,6 +7377,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test otxn_type"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7384,6 +7449,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test otxn_param"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7507,6 +7573,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7620,6 +7687,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot_clear"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7678,6 +7746,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot_count"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7743,6 +7812,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot_float"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7818,6 +7888,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot_set"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7928,6 +7999,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test slot_size"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); Account const alice{"alice"}; Account const bob{"bob"}; @@ -7980,7 +8052,7 @@ class SetHook0_test : public beast::unit_test::suite ASSERT(s > 0); // pull the object out into a buffer, check the number of bytes written is correct - uint8_t buf[4096]; + uint8_t buf[8210]; // ltSkip(3)+FLS(6)+LLS(6)+ Hashes(3+8,192(32*256)) ASSERT(slot(SBUF(buf), 1) == s); // check the object is valid @@ -8008,6 +8080,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8148,6 +8221,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8249,6 +8323,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8388,6 +8463,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8529,6 +8605,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8749,6 +8826,7 @@ class SetHook0_test : public beast::unit_test::suite 0x6eU, 0x74U, 0x32U}; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -8799,7 +8877,11 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test state_foreign_set"); using namespace jtx; - Env env{*this, features}; + Env env{ + *this, + network::makeNetworkConfig(21137, "10", "200000000", "50000000"), + features}; + incLgrSeqForGasPriceEnabled(env); auto const david = Account("david"); // grantee generic auto const cho = Account{"cho"}; // invoker @@ -9264,7 +9346,11 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test state_set"); using namespace jtx; - Env env{*this, features}; + Env env{ + *this, + network::makeNetworkConfig(21137, "10", "200000000", "50000000"), + features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -10258,6 +10344,7 @@ class SetHook0_test : public beast::unit_test::suite { Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); @@ -10485,6 +10572,7 @@ class SetHook0_test : public beast::unit_test::suite for (auto f : {features, features - fixHookAPI20251128}) { Env env{*this, f}; + incLgrSeqForGasPriceEnabled(env); bool const hasFix = env.current()->rules().enabled(fixHookAPI20251128); @@ -10528,6 +10616,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -10668,6 +10757,7 @@ class SetHook0_test : public beast::unit_test::suite auto const alice = Account{"alice"}; { Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); env.fund(XRP(10000), alice); env.fund(XRP(10000), bob); @@ -10772,6 +10862,7 @@ class SetHook0_test : public beast::unit_test::suite *this, isfixHookAPI20251128 ? features | fixHookAPI20251128 : features - fixHookAPI20251128}; + incLgrSeqForGasPriceEnabled(env); env.fund(XRP(10000), alice, bob); env.close(); @@ -10828,6 +10919,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -10912,6 +11004,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const bob = Account{"bob"}; auto const alice = Account{"alice"}; @@ -10995,6 +11088,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -11045,6 +11139,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -11089,6 +11184,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -11131,6 +11227,7 @@ class SetHook0_test : public beast::unit_test::suite { using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -11401,6 +11498,7 @@ class SetHook0_test : public beast::unit_test::suite using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -11988,6 +12086,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test util_raddr"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -12441,6 +12540,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test util_sha512h"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -12814,6 +12914,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("Test util_verify"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const alice = Account{"alice"}; auto const bob = Account{"bob"}; @@ -12928,6 +13029,7 @@ class SetHook0_test : public beast::unit_test::suite testcase("test HookCanEmit"); using namespace jtx; Env env{*this, features}; + incLgrSeqForGasPriceEnabled(env); auto const caller = Account{"caller"}; auto const alice = Account{"alice"}; @@ -13592,8 +13694,9 @@ class SetHook0_test : public beast::unit_test::suite using namespace test::jtx; static FeatureBitset const all{supported_amendments()}; - static std::array const feats{ + static std::array const feats{ all, + all - featureHookFeeV2, all - fixXahauV2, all - fixXahauV1 - fixXahauV2, all - fixXahauV1 - fixXahauV2 - fixNSDelete, @@ -13770,7 +13873,8 @@ SETHOOK_TEST(2, false) SETHOOK_TEST(3, false) SETHOOK_TEST(4, false) SETHOOK_TEST(5, false) -SETHOOK_TEST(6, true) +SETHOOK_TEST(6, false) +SETHOOK_TEST(7, true) BEAST_DEFINE_TESTSUITE_PRIO(SetHook0, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHook1, app, ripple, 2); @@ -13779,6 +13883,7 @@ BEAST_DEFINE_TESTSUITE_PRIO(SetHook3, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHook4, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHook5, app, ripple, 2); BEAST_DEFINE_TESTSUITE_PRIO(SetHook6, app, ripple, 2); +BEAST_DEFINE_TESTSUITE_PRIO(SetHook7, app, ripple, 2); } // namespace test } // namespace ripple #undef M diff --git a/src/test/app/SetHook_wasm.h b/src/test/app/SetHook_wasm.h index a2bd839884..e913e43821 100644 --- a/src/test/app/SetHook_wasm.h +++ b/src/test/app/SetHook_wasm.h @@ -12349,7 +12349,7 @@ std::map> wasm = { ASSERT(s > 0); // pull the object out into a buffer, check the number of bytes written is correct - uint8_t buf[4096]; + uint8_t buf[8210]; // ltSkip(3)+FLS(6)+LLS(6)+ Hashes(3+8,192(32*256)) ASSERT(slot(SBUF(buf), 1) == s); // check the object is valid @@ -12380,63 +12380,64 @@ std::map> wasm = { 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0xE0U, 0x89U, 0x04U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x7FU, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x07U, 0x08U, 0x01U, 0x04U, 0x68U, 0x6FU, 0x6FU, - 0x6BU, 0x00U, 0x07U, 0x0AU, 0xCCU, 0x82U, 0x00U, 0x01U, 0xC8U, 0x82U, + 0x6BU, 0x00U, 0x07U, 0x0AU, 0xCFU, 0x82U, 0x00U, 0x01U, 0xCBU, 0x82U, 0x00U, 0x02U, 0x01U, 0x7FU, 0x01U, 0x7EU, 0x23U, 0x80U, 0x80U, 0x80U, - 0x80U, 0x00U, 0x41U, 0x80U, 0x20U, 0x6BU, 0x22U, 0x01U, 0x24U, 0x80U, - 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, 0x80U, - 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, - 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7BU, 0x51U, 0x0DU, 0x00U, - 0x41U, 0xA2U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1DU, 0x42U, 0x21U, - 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, - 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U, 0x41U, 0x01U, - 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, 0x51U, 0x0DU, - 0x00U, 0x41U, 0xBFU, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1EU, 0x42U, - 0x24U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, + 0x80U, 0x00U, 0x41U, 0xA0U, 0xC0U, 0x00U, 0x6BU, 0x22U, 0x01U, 0x24U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x41U, 0x01U, 0x41U, 0x01U, 0x10U, + 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x02U, 0x40U, 0x41U, 0x01U, + 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x7BU, 0x51U, 0x0DU, + 0x00U, 0x41U, 0xA2U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1DU, 0x42U, + 0x21U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U, 0x41U, - 0xFFU, 0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0xFFU, - 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xDDU, 0x88U, 0x80U, 0x80U, 0x00U, - 0x41U, 0x22U, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, - 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, - 0x80U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, 0x80U, - 0x00U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xFFU, 0x88U, 0x80U, 0x80U, 0x00U, - 0x41U, 0x1FU, 0x42U, 0x28U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, - 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, - 0x80U, 0x00U, 0x22U, 0x02U, 0x42U, 0x00U, 0x55U, 0x0DU, 0x00U, 0x41U, - 0x9EU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x06U, 0x42U, 0x2CU, 0x10U, + 0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, 0x51U, + 0x0DU, 0x00U, 0x41U, 0xBFU, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x1EU, + 0x42U, 0x24U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, + 0x02U, 0x40U, 0x41U, 0x80U, 0x88U, 0x80U, 0x80U, 0x00U, 0x41U, 0x22U, + 0x41U, 0xFFU, 0x01U, 0x10U, 0x83U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, + 0xFFU, 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xDDU, 0x88U, 0x80U, 0x80U, + 0x00U, 0x41U, 0x22U, 0x42U, 0x25U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x41U, 0xFFU, 0x01U, 0x10U, 0x81U, 0x80U, 0x80U, + 0x80U, 0x00U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xFFU, 0x88U, 0x80U, 0x80U, + 0x00U, 0x41U, 0x1FU, 0x42U, 0x28U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x41U, 0x01U, 0x10U, 0x81U, 0x80U, + 0x80U, 0x80U, 0x00U, 0x22U, 0x02U, 0x42U, 0x00U, 0x55U, 0x0DU, 0x00U, + 0x41U, 0x9EU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x06U, 0x42U, 0x2CU, + 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, + 0x20U, 0x01U, 0x41U, 0x92U, 0xC0U, 0x00U, 0x41U, 0x01U, 0x10U, 0x84U, + 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U, 0x51U, 0x0DU, 0x00U, 0x41U, + 0xA4U, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, 0x18U, 0x42U, 0x30U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, - 0x01U, 0x41U, 0x80U, 0x20U, 0x41U, 0x01U, 0x10U, 0x84U, 0x80U, 0x80U, - 0x80U, 0x00U, 0x20U, 0x02U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xA4U, 0x89U, - 0x80U, 0x80U, 0x00U, 0x41U, 0x18U, 0x42U, 0x30U, 0x10U, 0x82U, 0x80U, - 0x80U, 0x80U, 0x00U, 0x1AU, 0x0BU, 0x02U, 0x40U, 0x20U, 0x01U, 0x20U, - 0x02U, 0xA7U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, 0x42U, 0x01U, - 0x51U, 0x0DU, 0x00U, 0x41U, 0xBCU, 0x89U, 0x80U, 0x80U, 0x00U, 0x41U, - 0x1AU, 0x42U, 0x33U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, - 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, 0x86U, 0x80U, - 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0x80U, 0x20U, 0x6AU, - 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, 0x02U, 0x0BU, 0x0BU, - 0xE4U, 0x01U, 0x02U, 0x00U, 0x41U, 0x80U, 0x08U, 0x0BU, 0x22U, 0x00U, - 0x68U, 0xB4U, 0x97U, 0x9AU, 0x36U, 0xCDU, 0xC7U, 0xF3U, 0xD3U, 0xD5U, - 0xC3U, 0x1AU, 0x4EU, 0xAEU, 0x2AU, 0xC7U, 0xD7U, 0x20U, 0x9DU, 0xDAU, - 0x87U, 0x75U, 0x88U, 0xB9U, 0xAFU, 0xC6U, 0x67U, 0x99U, 0x69U, 0x2AU, - 0xB0U, 0xD6U, 0x6BU, 0x00U, 0x41U, 0xA2U, 0x08U, 0x0BU, 0xB4U, 0x01U, - 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U, - 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x44U, 0x4FU, 0x45U, 0x53U, - 0x4EU, 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, 0x54U, 0x00U, 0x73U, - 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x53U, 0x42U, - 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, 0x6BU, 0x29U, 0x2CU, - 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U, 0x73U, - 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, 0x28U, 0x53U, 0x42U, - 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, 0x6BU, 0x29U, 0x2CU, - 0x20U, 0x32U, 0x35U, 0x35U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x32U, - 0x35U, 0x35U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, - 0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x73U, - 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U, 0x32U, - 0x35U, 0x35U, 0x29U, 0x00U, 0x73U, 0x20U, 0x3EU, 0x20U, 0x30U, 0x00U, - 0x73U, 0x6CU, 0x6FU, 0x74U, 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, - 0x62U, 0x75U, 0x66U, 0x29U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, - 0x3DU, 0x20U, 0x73U, 0x00U, 0x73U, 0x74U, 0x6FU, 0x5FU, 0x76U, 0x61U, - 0x6CU, 0x69U, 0x64U, 0x61U, 0x74U, 0x65U, 0x28U, 0x62U, 0x75U, 0x66U, - 0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x31U, 0x00U, + 0x01U, 0x20U, 0x02U, 0xA7U, 0x10U, 0x85U, 0x80U, 0x80U, 0x80U, 0x00U, + 0x42U, 0x01U, 0x51U, 0x0DU, 0x00U, 0x41U, 0xBCU, 0x89U, 0x80U, 0x80U, + 0x00U, 0x41U, 0x1AU, 0x42U, 0x33U, 0x10U, 0x82U, 0x80U, 0x80U, 0x80U, + 0x00U, 0x1AU, 0x0BU, 0x41U, 0x00U, 0x41U, 0x00U, 0x42U, 0x00U, 0x10U, + 0x86U, 0x80U, 0x80U, 0x80U, 0x00U, 0x1AU, 0x20U, 0x01U, 0x41U, 0xA0U, + 0xC0U, 0x00U, 0x6AU, 0x24U, 0x80U, 0x80U, 0x80U, 0x80U, 0x00U, 0x20U, + 0x02U, 0x0BU, 0x0BU, 0xE4U, 0x01U, 0x02U, 0x00U, 0x41U, 0x80U, 0x08U, + 0x0BU, 0x22U, 0x00U, 0x68U, 0xB4U, 0x97U, 0x9AU, 0x36U, 0xCDU, 0xC7U, + 0xF3U, 0xD3U, 0xD5U, 0xC3U, 0x1AU, 0x4EU, 0xAEU, 0x2AU, 0xC7U, 0xD7U, + 0x20U, 0x9DU, 0xDAU, 0x87U, 0x75U, 0x88U, 0xB9U, 0xAFU, 0xC6U, 0x67U, + 0x99U, 0x69U, 0x2AU, 0xB0U, 0xD6U, 0x6BU, 0x00U, 0x41U, 0xA2U, 0x08U, + 0x0BU, 0xB4U, 0x01U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, + 0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x44U, + 0x4FU, 0x45U, 0x53U, 0x4EU, 0x54U, 0x5FU, 0x45U, 0x58U, 0x49U, 0x53U, + 0x54U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, + 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, + 0x6BU, 0x29U, 0x2CU, 0x20U, 0x31U, 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, + 0x31U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x65U, 0x74U, + 0x28U, 0x53U, 0x42U, 0x55U, 0x46U, 0x28U, 0x6BU, 0x6CU, 0x5FU, 0x73U, + 0x6BU, 0x29U, 0x2CU, 0x20U, 0x32U, 0x35U, 0x35U, 0x29U, 0x20U, 0x3DU, + 0x3DU, 0x20U, 0x32U, 0x35U, 0x35U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, + 0x5FU, 0x73U, 0x69U, 0x7AU, 0x65U, 0x28U, 0x31U, 0x29U, 0x20U, 0x3DU, + 0x3DU, 0x20U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x5FU, 0x73U, 0x69U, 0x7AU, + 0x65U, 0x28U, 0x32U, 0x35U, 0x35U, 0x29U, 0x00U, 0x73U, 0x20U, 0x3EU, + 0x20U, 0x30U, 0x00U, 0x73U, 0x6CU, 0x6FU, 0x74U, 0x28U, 0x53U, 0x42U, + 0x55U, 0x46U, 0x28U, 0x62U, 0x75U, 0x66U, 0x29U, 0x2CU, 0x20U, 0x31U, + 0x29U, 0x20U, 0x3DU, 0x3DU, 0x20U, 0x73U, 0x00U, 0x73U, 0x74U, 0x6FU, + 0x5FU, 0x76U, 0x61U, 0x6CU, 0x69U, 0x64U, 0x61U, 0x74U, 0x65U, 0x28U, + 0x62U, 0x75U, 0x66U, 0x2CU, 0x20U, 0x73U, 0x29U, 0x20U, 0x3DU, 0x3DU, + 0x20U, 0x31U, 0x00U, }}, /* ==== WASM: 57 ==== */ diff --git a/src/test/app/Touch_test.cpp b/src/test/app/Touch_test.cpp index b5df8d2b92..cb24bfbfa7 100644 --- a/src/test/app/Touch_test.cpp +++ b/src/test/app/Touch_test.cpp @@ -424,6 +424,14 @@ struct Touch_test : public beast::unit_test::suite *this, network::makeNetworkConfig(21337, "10", "1000000", "200000"), features}; + if (env.current()->rules().enabled(featureHookFeeV2)) + { + for (int i = 0; i < 257; ++i) + env.close(); + env.close(); + BEAST_EXPECT( + env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } auto const alice = Account("alice"); auto const issuer = env.master; @@ -1403,6 +1411,7 @@ struct Touch_test : public beast::unit_test::suite testAllTxns(sa); testAllTxns(sa - fixHookAPI20251128); testAllTxns(sa - featureTouch - fixHookAPI20251128); + testAllTxns(sa - featureHookFeeV2); } }; diff --git a/src/test/jtx/impl/network.cpp b/src/test/jtx/impl/network.cpp index 2c0fe4d168..15a4adf20d 100644 --- a/src/test/jtx/impl/network.cpp +++ b/src/test/jtx/impl/network.cpp @@ -52,7 +52,6 @@ makeNetworkConfig( auto setup = setup_FeeVote(config); cfg->FEES = setup; cfg->section("voting") = config; - // cfg->START_UP = Config::FRESH; return cfg; }); } diff --git a/src/test/rpc/AccountNamespace_test.cpp b/src/test/rpc/AccountNamespace_test.cpp index aeeb040493..5538193df7 100644 --- a/src/test/rpc/AccountNamespace_test.cpp +++ b/src/test/rpc/AccountNamespace_test.cpp @@ -34,6 +34,14 @@ class AccountNamespace_test : public beast::unit_test::suite using namespace jtx; Env env(*this); + if (env.current()->rules().enabled(featureHookFeeV2)) + { + for (int i = 0; i < 257; ++i) + env.close(); + env.close(); + BEAST_EXPECT( + env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } Account const alice{"alice"}; Account const bob{"bob"}; @@ -225,6 +233,7 @@ class AccountNamespace_test : public beast::unit_test::suite using namespace test::jtx; FeatureBitset const all{supported_amendments()}; testErrors(all); + testErrors(all - featureHookFeeV2); } }; diff --git a/src/test/rpc/LedgerRPC_test.cpp b/src/test/rpc/LedgerRPC_test.cpp index 0f4b1c8237..c048d8e5d4 100644 --- a/src/test/rpc/LedgerRPC_test.cpp +++ b/src/test/rpc/LedgerRPC_test.cpp @@ -1104,6 +1104,14 @@ class LedgerRPC_test : public beast::unit_test::suite testcase("ledger_entry Request Hook State"); using namespace test::jtx; Env env{*this}; + if (env.current()->rules().enabled(featureHookFeeV2)) + { + for (int i = 0; i < 257; ++i) + env.close(); + env.close(); + BEAST_EXPECT( + env.le(keylet::fees())->getFieldU32(sfHookGasPrice) > 0); + } Account const alice{"alice"}; Account const bob{"bob"}; env.fund(XRP(10000), alice, bob); From 0e400a2f16429ea618689d9c01c6f40cd4da7b92 Mon Sep 17 00:00:00 2001 From: tequ Date: Mon, 22 Dec 2025 23:18:08 +0900 Subject: [PATCH 31/33] fix --- src/test/app/SetHook_test.cpp | 11 +++++++---- src/test/jtx/impl/envconfig.cpp | 2 ++ src/test/jtx/impl/network.cpp | 4 +++- src/test/jtx/network.h | 6 +++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 99465d04d0..59fc58f625 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -243,9 +243,12 @@ class SetHook0_test : public beast::unit_test::suite {"reference_fee = " + fee, "account_reserve = " + a_res, "owner_reserve = " + o_res, - "hook_gas_price = " + g_res}); + "hook_gas_price = 1000"}); auto setup = setup_FeeVote(config); cfg->FEES = setup; + cfg->section("voting") = config; + // override hook gas price for doVoting + cfg->section("voting").set("hook_gas_price", g_res); return cfg; }); } @@ -3623,7 +3626,7 @@ class SetHook0_test : public beast::unit_test::suite HSFEE); env.close(); - env(pay(bob, alice, XRP(1)), M("test float_compare"), fee(XRP(1))); + env(pay(bob, alice, XRP(1)), M("test float_compare"), HSFEE); env.close(); } } @@ -3953,7 +3956,7 @@ class SetHook0_test : public beast::unit_test::suite HSFEE); env.close(); - env(pay(bob, alice, XRP(1)), M("test float_int"), fee(XRP(1))); + env(pay(bob, alice, XRP(1)), M("test float_int"), HSFEE); env.close(); } } @@ -13546,7 +13549,7 @@ class SetHook0_test : public beast::unit_test::suite // invoke the hook env(pay(caller, acc, XRP(1)), M("test hookcanemit 3"), - fee(XRP(1))); + fee(XRP(10))); env.close(); auto meta = env.meta(); diff --git a/src/test/jtx/impl/envconfig.cpp b/src/test/jtx/impl/envconfig.cpp index 8adc969a9f..1195f18de7 100644 --- a/src/test/jtx/impl/envconfig.cpp +++ b/src/test/jtx/impl/envconfig.cpp @@ -50,6 +50,8 @@ setupConfigForUnitTests(Config& cfg) cfg.FEES.owner_reserve = XRP(50).value().xrp().drops(); cfg.FEES.hook_gas_price = 1'000'000; + cfg["voting"].set("hook_gas_price", to_string(10'000)); + cfg.overwrite(ConfigSection::nodeDatabase(), "type", "rwdb"); cfg.overwrite(ConfigSection::nodeDatabase(), "path", "main"); cfg.overwrite(SECTION_RELATIONAL_DB, "backend", "rwdb"); diff --git a/src/test/jtx/impl/network.cpp b/src/test/jtx/impl/network.cpp index 15a4adf20d..231e7a04ac 100644 --- a/src/test/jtx/impl/network.cpp +++ b/src/test/jtx/impl/network.cpp @@ -48,10 +48,12 @@ makeNetworkConfig( {"reference_fee = " + fee, "account_reserve = " + a_res, "owner_reserve = " + o_res, - "hook_gas_price = " + g_res}); + "hook_gas_price = 1"}); auto setup = setup_FeeVote(config); cfg->FEES = setup; cfg->section("voting") = config; + // override hook gas price for doVoting + cfg->section("voting").set("hook_gas_price", g_res); return cfg; }); } diff --git a/src/test/jtx/network.h b/src/test/jtx/network.h index 85267c1f41..e726654aae 100644 --- a/src/test/jtx/network.h +++ b/src/test/jtx/network.h @@ -36,7 +36,7 @@ makeNetworkConfig( std::string fee = "10", std::string a_res = "1000000", std::string o_res = "200000", - std::string g_res = "1000000"); + std::string g_res = "100000"); std::unique_ptr makeNetworkVLConfig( @@ -45,7 +45,7 @@ makeNetworkVLConfig( std::string fee = "10", std::string a_res = "1000000", std::string o_res = "200000", - std::string g_res = "1000000"); + std::string g_res = "100000"); std::unique_ptr makeGenesisConfig( @@ -55,7 +55,7 @@ makeGenesisConfig( std::string fee = "10", std::string a_res = "1000000", std::string o_res = "200000", - std::string g_res = "1000000", + std::string g_res = "100000", uint32_t ledgerID = 0); } // namespace network From 5a07f7fcf2c84bd4b7da41e4e09be5a3235bfccf Mon Sep 17 00:00:00 2001 From: tequ Date: Tue, 23 Dec 2025 17:00:26 +0900 Subject: [PATCH 32/33] fix test --- src/test/app/SetHook_test.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/test/app/SetHook_test.cpp b/src/test/app/SetHook_test.cpp index 59fc58f625..fc477896c2 100644 --- a/src/test/app/SetHook_test.cpp +++ b/src/test/app/SetHook_test.cpp @@ -13700,14 +13700,15 @@ class SetHook0_test : public beast::unit_test::suite static std::array const feats{ all, all - featureHookFeeV2, - all - fixXahauV2, - all - fixXahauV1 - fixXahauV2, - all - fixXahauV1 - fixXahauV2 - fixNSDelete, - all - fixXahauV1 - fixXahauV2 - fixNSDelete - fixPageCap, + all - fixXahauV2 - featureHookFeeV2, + all - fixXahauV1 - fixXahauV2 - featureHookFeeV2, + all - fixXahauV1 - fixXahauV2 - fixNSDelete - featureHookFeeV2, all - fixXahauV1 - fixXahauV2 - fixNSDelete - fixPageCap - - featureHookCanEmit, + featureHookFeeV2, all - fixXahauV1 - fixXahauV2 - fixNSDelete - fixPageCap - - featureExtendedHookState, + featureHookCanEmit - featureHookFeeV2, + all - fixXahauV1 - fixXahauV2 - fixNSDelete - fixPageCap - + featureExtendedHookState - featureHookFeeV2, }; if (BEAST_EXPECT(instance < feats.size())) From ef8381ece159f53c17579dd2d28efc3749d922a9 Mon Sep 17 00:00:00 2001 From: tequ Date: Fri, 16 Jan 2026 14:03:01 +0900 Subject: [PATCH 33/33] Organizing Hook API costs --- src/ripple/app/hook/Enum.h | 25 ++- src/ripple/app/hook/applyHook.h | 6 + src/ripple/app/hook/hook_api.macro | 296 ++++++++++++++--------------- 3 files changed, 174 insertions(+), 153 deletions(-) diff --git a/src/ripple/app/hook/Enum.h b/src/ripple/app/hook/Enum.h index 32e94c4764..4ebb711e82 100644 --- a/src/ripple/app/hook/Enum.h +++ b/src/ripple/app/hook/Enum.h @@ -401,7 +401,9 @@ getImportWhitelist(Rules const& rules) APIWhitelist whitelist; #pragma push_macro("HOOK_API_DEFINITION") +#pragma push_macro("HOOK_API_COST") #undef HOOK_API_DEFINITION +#undef HOOK_API_COST #define int64_t 0x7EU #define int32_t 0x7FU @@ -409,21 +411,34 @@ getImportWhitelist(Rules const& rules) #define HOOK_WRAP_PARAMS(...) __VA_ARGS__ -#define HOOK_API_DEFINITION( \ - RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT, COST) \ - if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \ - whitelist[#FUNCTION_NAME] = { \ - {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}, COST}; +#define HOOK_API_DEFINITION( \ + RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, AMENDMENT) \ + if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \ + whitelist[#FUNCTION_NAME] = { \ + {RETURN_TYPE, HOOK_WRAP_PARAMS PARAMS_TUPLE}, 0}; + +#define HOOK_API_COST(FUNCTION_NAME, COST, AMENDMENT) \ + if (AMENDMENT == uint256{} || rules.enabled(AMENDMENT)) \ + whitelist[#FUNCTION_NAME].second = COST; #include "hook_api.macro" +#undef HOOK_API_COST #undef HOOK_API_DEFINITION #undef HOOK_WRAP_PARAMS #undef int64_t #undef int32_t #undef uint32_t +#pragma pop_macro("HOOK_API_COST") #pragma pop_macro("HOOK_API_DEFINITION") + // all cost should > 0 + for (auto& [function, pair] : whitelist) + { + if (pair.second <= 0) + return {}; + } + return whitelist; } diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index 440ed15da5..8ba0505db6 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -63,14 +63,17 @@ namespace hook_api { #pragma push_macro("HOOK_API_DEFINITION") #undef HOOK_API_DEFINITION +#undef HOOK_API_COST #define HOOK_WRAP_PARAMS(...) __VA_ARGS__ #define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, ...) \ DECLARE_HOOK_FUNCTION( \ RETURN_TYPE, FUNCTION_NAME, HOOK_WRAP_PARAMS PARAMS_TUPLE); +#define HOOK_API_COST(...) #include +#undef HOOK_API_COST #undef HOOK_API_DEFINITION #undef HOOK_WRAP_PARAMS #pragma pop_macro("HOOK_API_DEFINITION") @@ -461,14 +464,17 @@ class HookExecutor #pragma push_macro("HOOK_API_DEFINITION") #undef HOOK_API_DEFINITION +#undef HOOK_API_COST #define HOOK_WRAP_PARAMS(...) __VA_ARGS__ #define HOOK_API_DEFINITION(RETURN_TYPE, FUNCTION_NAME, PARAMS_TUPLE, ...) \ ADD_HOOK_FUNCTION(FUNCTION_NAME, ctx, 0); +#define HOOK_API_COST(...) #include #undef HOOK_API_DEFINITION +#undef HOOK_API_COST #undef HOOK_WRAP_PARAMS #pragma pop_macro("HOOK_API_DEFINITION") diff --git a/src/ripple/app/hook/hook_api.macro b/src/ripple/app/hook/hook_api.macro index 029da2adfe..d87648f0e2 100644 --- a/src/ripple/app/hook/hook_api.macro +++ b/src/ripple/app/hook/hook_api.macro @@ -1,443 +1,443 @@ // int32_t _g(uint32_t guard_id, uint32_t maxiter); HOOK_API_DEFINITION( int32_t, _g, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(_g, 100, uint256{}) // int64_t accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code); HOOK_API_DEFINITION( int64_t, accept, (uint32_t, uint32_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(accept, 100, uint256{}) // int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code); HOOK_API_DEFINITION( int64_t, rollback, (uint32_t, uint32_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(rollback, 100, uint256{}) // int64_t util_raddr(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, util_raddr, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(util_raddr, 100, uint256{}) // int64_t util_accid(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, util_accid, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(util_accid, 100, uint256{}) // int64_t util_verify(uint32_t dread_ptr, uint32_t dread_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION( int64_t, util_verify, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(util_verify, 100, uint256{}) // int64_t util_sha512h(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, util_sha512h, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(util_sha512h, 100, uint256{}) // 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); HOOK_API_DEFINITION( int64_t, util_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(util_keylet, 100, uint256{}) // int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len); HOOK_API_DEFINITION( int64_t, sto_validate, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(sto_validate, 100, uint256{}) // int64_t sto_subfield(uint32_t read_ptr, uint32_t read_len, uint32_t field_id); HOOK_API_DEFINITION( int64_t, sto_subfield, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(sto_subfield, 100, uint256{}) // int64_t sto_subarray(uint32_t read_ptr, uint32_t read_len, uint32_t array_id); HOOK_API_DEFINITION( int64_t, sto_subarray, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(sto_subarray, 100, uint256{}) // int64_t sto_emplace(uint32_t write_ptr, uint32_t write_len, uint32_t sread_ptr, uint32_t sread_len, uint32_t fread_ptr, uint32_t fread_len, uint32_t field_id); HOOK_API_DEFINITION( int64_t, sto_emplace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(sto_emplace, 100, uint256{}) // int64_t sto_erase(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len, uint32_t field_id); HOOK_API_DEFINITION( int64_t, sto_erase, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(sto_erase, 100, uint256{}) // int64_t etxn_burden(); HOOK_API_DEFINITION( int64_t, etxn_burden, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_burden, 100, uint256{}) // int64_t etxn_details(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION( int64_t, etxn_details, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_details, 100, uint256{}) // int64_t etxn_fee_base(uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, etxn_fee_base, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_fee_base, 100, uint256{}) // int64_t etxn_reserve(uint32_t count); HOOK_API_DEFINITION( int64_t, etxn_reserve, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_reserve, 100, uint256{}) // int64_t etxn_generation(); HOOK_API_DEFINITION( int64_t, etxn_generation, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_generation, 100, uint256{}) // int64_t etxn_nonce(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION( int64_t, etxn_nonce, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(etxn_nonce, 100, uint256{}) // int64_t emit(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, emit, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(emit, 100, uint256{}) // int64_t float_set(int32_t exponent, int64_t mantissa); HOOK_API_DEFINITION( int64_t, float_set, (int32_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_set, 100, uint256{}) // int64_t float_multiply(int64_t float1, int64_t float2); HOOK_API_DEFINITION( int64_t, float_multiply, (int64_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_multiply, 100, uint256{}) // int64_t float_mulratio(int64_t float1, uint32_t round_up, uint32_t numerator, uint32_t denominator); HOOK_API_DEFINITION( int64_t, float_mulratio, (int64_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_mulratio, 100, uint256{}) // int64_t float_negate(int64_t float1); HOOK_API_DEFINITION( int64_t, float_negate, (int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_negate, 100, uint256{}) // int64_t float_compare(int64_t float1, int64_t float2, uint32_t mode); HOOK_API_DEFINITION( int64_t, float_compare, (int64_t, int64_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_compare, 100, uint256{}) // int64_t float_sum(int64_t float1, int64_t float2); HOOK_API_DEFINITION( int64_t, float_sum, (int64_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_sum, 100, uint256{}) // int64_t float_sto(uint32_t write_ptr, uint32_t write_len, uint32_t cread_ptr, uint32_t cread_len, uint32_t iread_ptr, uint32_t iread_len, int64_t float1, uint32_t field_code); HOOK_API_DEFINITION( int64_t, float_sto, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, int64_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_sto, 100, uint256{}) // int64_t float_sto_set(uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, float_sto_set, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_sto_set, 100, uint256{}) // int64_t float_invert(int64_t float1); HOOK_API_DEFINITION( int64_t, float_invert, (int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_invert, 100, uint256{}) // int64_t float_divide(int64_t float1, int64_t float2); HOOK_API_DEFINITION( int64_t, float_divide, (int64_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_divide, 100, uint256{}) // int64_t float_one(); HOOK_API_DEFINITION( int64_t, float_one, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_one, 100, uint256{}) // int64_t float_mantissa(int64_t float1); HOOK_API_DEFINITION( int64_t, float_mantissa, (int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_mantissa, 100, uint256{}) // int64_t float_sign(int64_t float1); HOOK_API_DEFINITION( int64_t, float_sign, (int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_sign, 100, uint256{}) // int64_t float_int(int64_t float1, uint32_t decimal_places, uint32_t abs); HOOK_API_DEFINITION( int64_t, float_int, (int64_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_int, 100, uint256{}) // int64_t float_log(int64_t float1); HOOK_API_DEFINITION( int64_t, float_log, (int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_log, 100, uint256{}) // int64_t float_root(int64_t float1, uint32_t n); HOOK_API_DEFINITION( int64_t, float_root, (int64_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(float_root, 100, uint256{}) // int64_t fee_base(); HOOK_API_DEFINITION( int64_t, fee_base, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(fee_base, 100, uint256{}) // int64_t ledger_seq(); HOOK_API_DEFINITION( int64_t, ledger_seq, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(ledger_seq, 100, uint256{}) // int64_t ledger_last_time(); HOOK_API_DEFINITION( int64_t, ledger_last_time, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(ledger_last_time, 100, uint256{}) // int64_t ledger_last_hash(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION( int64_t, ledger_last_hash, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(ledger_last_hash, 100, uint256{}) // int64_t ledger_nonce(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION( int64_t, ledger_nonce, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(ledger_nonce, 100, uint256{}) // int64_t ledger_keylet(uint32_t write_ptr, uint32_t write_len, uint32_t lread_ptr, uint32_t lread_len, uint32_t hread_ptr, uint32_t hread_len); HOOK_API_DEFINITION( int64_t, ledger_keylet, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(ledger_keylet, 100, uint256{}) // int64_t hook_account(uint32_t write_ptr, uint32_t write_len); HOOK_API_DEFINITION( int64_t, hook_account, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_account, 100, uint256{}) // int64_t hook_hash(uint32_t write_ptr, uint32_t write_len, int32_t hook_no); HOOK_API_DEFINITION( int64_t, hook_hash, (uint32_t, uint32_t, int32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_hash, 100, uint256{}) // int64_t hook_param_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len); HOOK_API_DEFINITION( int64_t, hook_param_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_param_set, 100, uint256{}) // int64_t hook_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, hook_param, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_param, 100, uint256{}) // int64_t hook_again(); HOOK_API_DEFINITION( int64_t, hook_again, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_again, 100, uint256{}) // int64_t hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); HOOK_API_DEFINITION( int64_t, hook_skip, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_skip, 100, uint256{}) // int64_t hook_pos(); HOOK_API_DEFINITION( int64_t, hook_pos, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(hook_pos, 100, uint256{}) // int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); HOOK_API_DEFINITION( int64_t, slot, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot, 100, uint256{}) // int64_t slot_clear(uint32_t slot); HOOK_API_DEFINITION( int64_t, slot_clear, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_clear, 100, uint256{}) // int64_t slot_count(uint32_t slot); HOOK_API_DEFINITION( int64_t, slot_count, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_count, 100, uint256{}) // int64_t slot_set(uint32_t read_ptr, uint32_t read_len, uint32_t slot); HOOK_API_DEFINITION( int64_t, slot_set, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_set, 100, uint256{}) // int64_t slot_size(uint32_t slot); HOOK_API_DEFINITION( int64_t, slot_size, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_size, 100, uint256{}) // int64_t slot_subarray(uint32_t parent_slot, uint32_t array_id, uint32_t new_slot); HOOK_API_DEFINITION( int64_t, slot_subarray, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_subarray, 100, uint256{}) // int64_t slot_subfield(uint32_t parent_slot, uint32_t field_id, uint32_t new_slot); HOOK_API_DEFINITION( int64_t, slot_subfield, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_subfield, 100, uint256{}) // int64_t slot_type(uint32_t slot_no, uint32_t flags); HOOK_API_DEFINITION( int64_t, slot_type, (uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_type, 100, uint256{}) // int64_t slot_float(uint32_t slot_no); HOOK_API_DEFINITION( int64_t, slot_float, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(slot_float, 100, uint256{}) // int64_t state_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION( int64_t, state_set, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(state_set, 100, uint256{}) // int64_t state_foreign_set(uint32_t read_ptr, uint32_t read_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); HOOK_API_DEFINITION( int64_t, state_foreign_set, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(state_foreign_set, 100, uint256{}) // int64_t state(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len); HOOK_API_DEFINITION( int64_t, state, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(state, 100, uint256{}) // int64_t state_foreign(uint32_t write_ptr, uint32_t write_len, uint32_t kread_ptr, uint32_t kread_len, uint32_t nread_ptr, uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); HOOK_API_DEFINITION( int64_t, state_foreign, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(state_foreign, 100, uint256{}) // int64_t trace(uint32_t mread_ptr, uint32_t mread_len, uint32_t dread_ptr, uint32_t dread_len, uint32_t as_hex); HOOK_API_DEFINITION( int64_t, trace, (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(trace, 100, uint256{}) // int64_t trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number); HOOK_API_DEFINITION( int64_t, trace_num, (uint32_t, uint32_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(trace_num, 100, uint256{}) // int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); HOOK_API_DEFINITION( int64_t, trace_float, (uint32_t, uint32_t, int64_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(trace_float, 100, uint256{}) // int64_t otxn_burden(); HOOK_API_DEFINITION( int64_t, otxn_burden, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_burden, 100, uint256{}) // int64_t otxn_field(uint32_t write_ptr, uint32_t write_len, uint32_t field_id); HOOK_API_DEFINITION( int64_t, otxn_field, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_field, 100, uint256{}) // int64_t otxn_generation(); HOOK_API_DEFINITION( int64_t, otxn_generation, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_generation, 100, uint256{}) // int64_t otxn_id(uint32_t write_ptr, uint32_t write_len, uint32_t flags); HOOK_API_DEFINITION( int64_t, otxn_id, (uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_id, 100, uint256{}) // int64_t otxn_type(); HOOK_API_DEFINITION( int64_t, otxn_type, (), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_type, 100, uint256{}) // int64_t otxn_slot(uint32_t slot_no); HOOK_API_DEFINITION( int64_t, otxn_slot, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_slot, 100, uint256{}) // int64_t otxn_param(uint32_t write_ptr, uint32_t write_len, uint32_t read_ptr, uint32_t read_len); HOOK_API_DEFINITION( int64_t, otxn_param, (uint32_t, uint32_t, uint32_t, uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(otxn_param, 100, uint256{}) // int64_t meta_slot(uint32_t slot_no); HOOK_API_DEFINITION( int64_t, meta_slot, (uint32_t), - uint256{}, - 100) + uint256{}) +HOOK_API_COST(meta_slot, 100, uint256{}) // int64_t xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta); HOOK_API_DEFINITION( int64_t, xpop_slot, (uint32_t, uint32_t), - featureHooksUpdate1, - 100) + featureHooksUpdate1) +HOOK_API_COST(xpop_slot, 100, uint256{})