Skip to content

Control APIs

This page documents the ten control Hook APIs: the functions that terminate hook execution, guard loops, and inspect or influence the hook's position and parameters within the hook chain.

All signatures are copied verbatim from hook/extern.h. Return codes reference the shared error table in ../../glossary.md; the values quoted below come from include/xrpl/hook/Enum.h and hook/error.h.


Execution-termination model

A hook is a WebAssembly function that returns control to the ledger in exactly one of two ways:

  • accept — the originating transaction is applied. Any state changes the hook wrote and any transactions it emitted are kept.
  • rollback — the originating transaction is rejected. State changes and emitted transactions from this hook are discarded.

Both functions terminate the hook immediately: internally they set the hook's exit type and return the special sentinel codes RC_ACCEPT (-20) or RC_ROLLBACK (-19) to the VM, which stops execution. Code after an accept/rollback call in the same path never runs.

If a hook function returns normally (falls off the end of hook()) without calling either, the default exit type is ROLLBACK (see applyHook.cpp, where the result is initialised with exitType = ROLLBACK "unless the hook calls accept()"). Under the fixXahauV3 amendment the default becomes WASM_ERROR instead; either way, not calling accept rejects the transaction. Always call accept explicitly on the success path.

Each hook execution records a metadata entry (sfHookExecution) that captures the outcome (verified in applyHook.cpp):

  • sfHookResult — the exit type as a uint8_t (ExitType: WASM_ERROR=1, ROLLBACK=2, ACCEPT=3; UNSET=0).
  • sfHookReturnCode — the error_code you passed to accept/rollback, stored as uint64_t. Negative values are encoded by setting the most-significant bit (0x8000000000000000 + (-code)), so a returned -16 appears as a large unsigned number.
  • sfHookReturnString — the reason string you passed (see the per-function notes).
  • sfHookInstructionCount, sfHookEmitCount, sfHookStateChangeCount, sfHookHash, etc.

This metadata is how off-ledger tooling learns why a hook accepted or rejected, so the error_code and reason string you pass are your primary debugging channel.


The guard system

WebAssembly on Xahau is metered by a guard mechanism rather than an open-ended gas counter (Guard-type hooks; HookApiVersion 0). Every loop must call _g at its very top, declaring the maximum number of iterations it will run. This makes worst-case execution cost statically computable, so the network can price a SetHook up front and guarantee that hooks halt.

Two enforcement points exist:

  1. Install time (static validation). When a hook is set, the server runs the guard validator in include/xrpl/hook/Guard.h (check_guard) over the WASM. It walks the code section and, for every loop opcode (0x03), requires the immediately following instructions to be exactly i32.const <guard_id>, i32.const <maxiter>, call _g. A loop that is missing this prologue, that specifies maxiter == 0, or that calls a function other than _g there is rejected and the SetHook fails (log codes such as GUARD_MISSING). There is a hard limit of 1024 guard calls per hook.

  2. Run time (dynamic enforcement). During execution _g counts calls per guard_id. If a guarded loop exceeds its declared maxiter, _g sets the exit type to ROLLBACK with exit code GUARD_VIOLATION (-16) and terminates the hook. GUARD_VIOLATION in the metadata therefore means "a loop ran more times than it promised."

The developer-facing GUARD(maxiter) / GUARDM(maxiter, n) macros (in hook/macro.h) build the guard_id from the source line number so each loop gets a distinct id; see ../macros.md. You rarely call _g by hand except for the mandatory _g(1,1) at the top of hook().


Index

FunctionPurpose
acceptTerminate the hook and let the originating transaction proceed.
rollbackTerminate the hook and reject the originating transaction.
_gLoop/branch guard; required at the top of every loop.
hook_accountWrite the AccountID the hook is installed on.
hook_hashWrite the WASM hash of a hook in the chain.
hook_posReturn this hook's position within the hook chain.
hook_paramRead this hook's install-time parameter value by key.
hook_param_setOverride a parameter for a later hook in the chain.
hook_againRequest a weak (post-apply) re-execution of the hook.
hook_skipSkip (or un-skip) a named hook in the chain.