diff --git a/.github/workflows/verify-generated-headers.yml b/.github/workflows/verify-generated-headers.yml new file mode 100644 index 000000000..4120f7b7f --- /dev/null +++ b/.github/workflows/verify-generated-headers.yml @@ -0,0 +1,36 @@ +name: Verify Generated Hook Headers + +on: + push: + pull_request: + +jobs: + verify-generated-headers: + strategy: + fail-fast: false + matrix: + include: + - target: hook/error.h + generator: ./hook/generate_error.sh + - target: hook/extern.h + generator: ./hook/generate_extern.sh + - target: hook/sfcodes.h + generator: bash ./hook/generate_sfcodes.sh + - target: hook/tts.h + generator: ./hook/generate_tts.sh + runs-on: ubuntu-latest + name: ${{ matrix.target }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Verify ${{ matrix.target }} + run: | + set -euo pipefail + chmod +x hook/generate_*.sh || true + + tmp=$(mktemp) + trap 'rm -f "$tmp"' EXIT + + ${{ matrix.generator }} > "$tmp" + diff -u ${{ matrix.target }} "$tmp" diff --git a/hook/error.h b/hook/error.h index 2d7060ee1..63e0c03bb 100644 --- a/hook/error.h +++ b/hook/error.h @@ -48,4 +48,4 @@ #define TOO_MANY_STATE_MODIFICATIONS -44 #define TOO_MANY_NAMESPACES -45 #define HOOK_ERROR_CODES -#endif //HOOK_ERROR_CODES \ No newline at end of file +#endif //HOOK_ERROR_CODES diff --git a/hook/extern.h b/hook/extern.h index baf0e6de2..ee34af6ff 100644 --- a/hook/extern.h +++ b/hook/extern.h @@ -12,8 +12,6 @@ accept(uint32_t read_ptr, uint32_t read_len, int64_t error_code); extern int64_t rollback(uint32_t read_ptr, uint32_t read_len, int64_t error_code); -// UTIL - extern int64_t util_raddr( uint32_t write_ptr, @@ -56,8 +54,6 @@ util_keylet( uint32_t e, uint32_t f); -// STO - extern int64_t sto_validate(uint32_t tread_ptr, uint32_t tread_len); @@ -85,8 +81,6 @@ sto_erase( uint32_t read_len, uint32_t field_id); -// EMITTED TXN - extern int64_t etxn_burden(void); @@ -112,8 +106,6 @@ emit( uint32_t read_ptr, uint32_t read_len); -// FLOAT - extern int64_t float_set(int32_t exponent, int64_t mantissa); @@ -174,8 +166,6 @@ float_log(int64_t float1); extern int64_t float_root(int64_t float1, uint32_t n); -// LEDGER - extern int64_t fee_base(void); @@ -200,8 +190,6 @@ ledger_keylet( uint32_t hread_ptr, uint32_t hread_len); -// HOOK - extern int64_t hook_account(uint32_t write_ptr, uint32_t write_len); @@ -233,8 +221,6 @@ hook_skip(uint32_t read_ptr, uint32_t read_len, uint32_t flags); extern int64_t hook_pos(void); -// SLOT - extern int64_t slot(uint32_t write_ptr, uint32_t write_len, uint32_t slot); @@ -262,8 +248,6 @@ slot_type(uint32_t slot_no, uint32_t flags); extern int64_t slot_float(uint32_t slot_no); -// STATE - extern int64_t state_set( uint32_t read_ptr, @@ -300,8 +284,6 @@ state_foreign( uint32_t aread_ptr, uint32_t aread_len); -// TRACE - extern int64_t trace( uint32_t mread_ptr, @@ -316,8 +298,6 @@ trace_num(uint32_t read_ptr, uint32_t read_len, int64_t number); extern int64_t trace_float(uint32_t read_ptr, uint32_t read_len, int64_t float1); -// OTXN - extern int64_t otxn_burden(void); @@ -346,9 +326,8 @@ otxn_param( extern int64_t meta_slot(uint32_t slot_no); -// featureHooks1 - -extern int64_t xpop_slot(uint32_t, uint32_t); +extern int64_t +xpop_slot(uint32_t slot_no_tx, uint32_t slot_no_meta); #define HOOK_EXTERN #endif // HOOK_EXTERN diff --git a/hook/generate_error.sh b/hook/generate_error.sh new file mode 100755 index 000000000..1e5aaadb2 --- /dev/null +++ b/hook/generate_error.sh @@ -0,0 +1,58 @@ +#!/bin/bash +set -eu + +SCRIPT_DIR=$(dirname "$0") +SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) + +ENUM_FILE="$SCRIPT_DIR/../src/ripple/app/hook/Enum.h" + +echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' +echo '// Generated using generate_error.sh' +echo '#ifndef HOOK_ERROR_CODES' +sed -n '/enum hook_return_code/,/};/p' "$ENUM_FILE" | + awk ' + function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s } + function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s } + function trim(s) { return rtrim(ltrim(s)) } + function emit(entry) { + entry = trim(entry) + if (entry == "") + return + gsub(/,[[:space:]]*$/, "", entry) + split(entry, parts, "=") + if (length(parts) < 2) + return + name = trim(parts[1]) + value = trim(parts[2]) + if (name == "" || value == "") + return + printf "#define %s %s\n", name, value + } + + { + line = $0 + if (line ~ /enum[[:space:]]+hook_return_code/) + next + if (line ~ /^[[:space:]]*\{/) + next + + sub(/\/\/.*$/, "", line) + + if (line ~ /^[[:space:]]*\};/) { + emit(buffer) + exit + } + + if (line ~ /^[[:space:]]*$/) + next + + buffer = buffer line " " + + if (line ~ /,[[:space:]]*$/) { + emit(buffer) + buffer = "" + } + } + ' +echo '#define HOOK_ERROR_CODES' +echo '#endif //HOOK_ERROR_CODES' diff --git a/hook/generate_extern.sh b/hook/generate_extern.sh new file mode 100755 index 000000000..2e9598ad0 --- /dev/null +++ b/hook/generate_extern.sh @@ -0,0 +1,145 @@ +#!/bin/bash +set -eu + +SCRIPT_DIR=$(dirname "$0") +SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) + +APPLY_HOOK="$SCRIPT_DIR/../src/ripple/app/hook/applyHook.h" + +{ + echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' + echo '// Generated using generate_extern.sh' + echo '#include ' + echo '#ifndef HOOK_EXTERN' + echo + awk ' + function trim(s) { + sub(/^[[:space:]]+/, "", s); + sub(/[[:space:]]+$/, "", s); + 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; + 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; + } + } + } + + END { + printf("\n"); + } + ' "$APPLY_HOOK" + + echo '#define HOOK_EXTERN' + echo '#endif // HOOK_EXTERN' +} diff --git a/hook/generate_sfcodes.sh b/hook/generate_sfcodes.sh index 255bbc63a..9a7ba99aa 100755 --- a/hook/generate_sfcodes.sh +++ b/hook/generate_sfcodes.sh @@ -1,8 +1,13 @@ -#/bin/bash -RIPPLED_ROOT="../src/ripple" +#!/bin/bash +set -eu + +SCRIPT_DIR=$(dirname "$0") +SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) + +RIPPLED_ROOT="$SCRIPT_DIR/../src/ripple" echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' echo '// Generated using generate_sfcodes.sh' -cat $RIPPLED_ROOT/protocol/impl/SField.cpp | grep -E '^CONSTRUCT_' | +cat "$RIPPLED_ROOT/protocol/impl/SField.cpp" | grep -E '^CONSTRUCT_' | sed 's/UINT16,/1,/g' | sed 's/UINT32,/2,/g' | sed 's/UINT64,/3,/g' | diff --git a/hook/generate_tts.sh b/hook/generate_tts.sh new file mode 100755 index 000000000..b27b8237c --- /dev/null +++ b/hook/generate_tts.sh @@ -0,0 +1,38 @@ +#!/bin/bash +set -eu + +SCRIPT_DIR=$(dirname "$0") +SCRIPT_DIR=$(cd "$SCRIPT_DIR" && pwd) + +RIPPLED_ROOT="$SCRIPT_DIR/../src/ripple" +TX_FORMATS="$RIPPLED_ROOT/protocol/TxFormats.h" + +echo '// For documentation please see: https://xrpl-hooks.readme.io/reference/' +echo '// Generated using generate_tts.sh' +sed -n '/enum TxType/,/};/p' "$TX_FORMATS" | + awk ' + function ltrim(s) { sub(/^[[:space:]]+/, "", s); return s } + function rtrim(s) { sub(/[[:space:]]+$/, "", s); return s } + function trim(s) { return rtrim(ltrim(s)) } + + /^[ \t]*tt[A-Z0-9_]+/ { + line = $0 + deprecated = (line ~ /\[\[deprecated/) + gsub(/\[\[deprecated[^]]*\]\]/, "", line) + sub(/\/\/.*$/, "", line) + gsub(/,[[:space:]]*$/, "", line) + + split(line, parts, "=") + if (length(parts) < 2) + next + + name = trim(parts[1]) + value = trim(parts[2]) + if (name == "" || value == "") + next + + prefix = deprecated ? "// " : "" + postfix = deprecated ? " // deprecated" : "" + printf "%s#define %s %s%s\n", prefix, name, value, postfix + } + ' diff --git a/hook/sfcodes.h b/hook/sfcodes.h index 242d14499..77d13f6aa 100644 --- a/hook/sfcodes.h +++ b/hook/sfcodes.h @@ -108,6 +108,7 @@ #define sfEmitParentTxnID ((5U << 16U) + 11U) #define sfEmitNonce ((5U << 16U) + 12U) #define sfEmitHookHash ((5U << 16U) + 13U) +#define sfObjectID ((5U << 16U) + 14U) #define sfBookDirectory ((5U << 16U) + 16U) #define sfInvoiceID ((5U << 16U) + 17U) #define sfNickname ((5U << 16U) + 18U) @@ -132,6 +133,7 @@ #define sfGovernanceFlags ((5U << 16U) + 99U) #define sfGovernanceMarks ((5U << 16U) + 98U) #define sfEmittedTxnID ((5U << 16U) + 97U) +#define sfHookCanEmit ((5U << 16U) + 96U) #define sfCron ((5U << 16U) + 95U) #define sfAmount ((6U << 16U) + 1U) #define sfBalance ((6U << 16U) + 2U) @@ -177,6 +179,8 @@ #define sfHookParameterName ((7U << 16U) + 24U) #define sfHookParameterValue ((7U << 16U) + 25U) #define sfBlob ((7U << 16U) + 26U) +#define sfRemarkValue ((7U << 16U) + 98U) +#define sfRemarkName ((7U << 16U) + 99U) #define sfAccount ((8U << 16U) + 1U) #define sfOwner ((8U << 16U) + 2U) #define sfDestination ((8U << 16U) + 3U) @@ -216,6 +220,7 @@ #define sfHookDefinition ((14U << 16U) + 22U) #define sfHookParameter ((14U << 16U) + 23U) #define sfHookGrant ((14U << 16U) + 24U) +#define sfRemark ((14U << 16U) + 97U) #define sfGenesisMint ((14U << 16U) + 96U) #define sfActiveValidator ((14U << 16U) + 95U) #define sfImportVLKey ((14U << 16U) + 94U) @@ -236,6 +241,7 @@ #define sfHookExecutions ((15U << 16U) + 18U) #define sfHookParameters ((15U << 16U) + 19U) #define sfHookGrants ((15U << 16U) + 20U) +#define sfRemarks ((15U << 16U) + 97U) #define sfGenesisMints ((15U << 16U) + 96U) #define sfActiveValidators ((15U << 16U) + 95U) #define sfImportVLKeys ((15U << 16U) + 94U) diff --git a/hook/tts.h b/hook/tts.h index 75ce47470..bd03b0399 100644 --- a/hook/tts.h +++ b/hook/tts.h @@ -1,4 +1,5 @@ // For documentation please see: https://xrpl-hooks.readme.io/reference/ +// Generated using generate_tts.sh #define ttPAYMENT 0 #define ttESCROW_CREATE 1 #define ttESCROW_FINISH 2 @@ -8,6 +9,7 @@ // #define ttNICKNAME_SET 6 // deprecated #define ttOFFER_CREATE 7 #define ttOFFER_CANCEL 8 +// #define ttCONTRACT 9 // deprecated #define ttTICKET_CREATE 10 // #define ttSPINAL_TAP 11 // deprecated #define ttSIGNER_LIST_SET 12 @@ -26,6 +28,7 @@ #define ttNFTOKEN_CREATE_OFFER 27 #define ttNFTOKEN_CANCEL_OFFER 28 #define ttNFTOKEN_ACCEPT_OFFER 29 +#define ttCLAWBACK 30 #define ttURITOKEN_MINT 45 #define ttURITOKEN_BURN 46 #define ttURITOKEN_BUY 47 @@ -33,6 +36,7 @@ #define ttURITOKEN_CANCEL_SELL_OFFER 49 #define ttCRON 92 #define ttCRON_SET 93 +#define ttREMARKS_SET 94 #define ttREMIT 95 #define ttGENESIS_MINT 96 #define ttIMPORT 97 diff --git a/src/ripple/app/hook/applyHook.h b/src/ripple/app/hook/applyHook.h index d6855969a..011f50f3e 100644 --- a/src/ripple/app/hook/applyHook.h +++ b/src/ripple/app/hook/applyHook.h @@ -74,6 +74,7 @@ DECLARE_HOOK_FUNCTION( uint32_t read_ptr, uint32_t read_len, int64_t error_code); + DECLARE_HOOK_FUNCTION( int64_t, util_raddr, @@ -97,6 +98,26 @@ DECLARE_HOOK_FUNCTION( 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, @@ -133,25 +154,6 @@ DECLARE_HOOK_FUNCTION( uint32_t read_len, uint32_t field_id); -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_FUNCNARG(int64_t, etxn_burden); DECLARE_HOOK_FUNCTION( int64_t, @@ -214,7 +216,6 @@ DECLARE_HOOK_FUNCTION( 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( @@ -226,17 +227,6 @@ DECLARE_HOOK_FUNCTION( 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_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_FUNCNARG(int64_t, fee_base); DECLARE_HOOK_FUNCNARG(int64_t, ledger_seq); DECLARE_HOOK_FUNCNARG(int64_t, ledger_last_time); @@ -250,7 +240,6 @@ DECLARE_HOOK_FUNCTION( ledger_nonce, uint32_t write_ptr, uint32_t write_len); - DECLARE_HOOK_FUNCTION( int64_t, ledger_keylet, @@ -261,6 +250,17 @@ DECLARE_HOOK_FUNCTION( 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, @@ -270,7 +270,6 @@ DECLARE_HOOK_FUNCTION( uint32_t kread_len, uint32_t hread_ptr, uint32_t hread_len); - DECLARE_HOOK_FUNCTION( int64_t, hook_param, @@ -278,9 +277,7 @@ DECLARE_HOOK_FUNCTION( 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, @@ -355,6 +352,7 @@ DECLARE_HOOK_FUNCTION( uint32_t nread_len, uint32_t aread_ptr, uint32_t aread_len); + DECLARE_HOOK_FUNCTION( int64_t, trace,