All Hooks are compiled to a single webassembly module before they can be set onto an Xahau account.
A Hook always implements and exports exactly one or both of the following functions:
int64_t hook(uint32_t ctx) { ... }
required
Executed whenever a transaction comes into or leaves from the account the Hook is set on (ctx = 0
) or
Executed when executed as a Weak Transactional Stakeholder (ctx > 0
).
int64_t cbak(uint32_t ctx) { ... }
optional
Executed when an emitted transaction is successfully accepted into a ledger (ctx = 0
) or
Executed when an emitted transaction cannot be accepted into any ledger (ctx = 1
).
Hooks are not allowed to specify other functions. Instead they must make clever use of macros to do all their computation within these two functions. This is part of a computational restriction on hooks to keep their runtime predictable.
Additionally Hooks are afforded no heap memory. All required memory must be reserved and used on the stack.
Here is an example Hook written in C. The Hook prints 0...3 to the trace log before accepting the originating transaction.
📘 Hint
For educational purposes the above example deliberately does not include
hookapi.h
(which developers would typically use.)
A variety of compilers will generate valid webassembly from a C source file. Once compiled, a Hook exists as a binary .wasm
file. This contains a webassembly module. Using wasmcc
to compile and the wasm2wat
tool to convert to human readable webassembly this binary form can be rendered to the human readable form. Below appears the compilation result of the above example.
The average Hook developer will never need to examine webassembly directly. However it is a useful conceptual exercise to review the contents of the sample Hook.
Above we can see:
Three functions are imported from the Hooks API (_g
, accept
, trace_num
)
Two functions are defined by the hook (cbak
, hook
)
Two functions are exported by the hook (again: cbak
, hook
)
Some static (constant) data is recorded in the hook (see data
at the bottom).
It is very important to note that a Hook must only import functions available to it from the Hooks API and must only export the cbak
and hook
functions. In additional all hooks must import _g
from the Hooks API, which is the guard
function.
📘 Hint
Webassembly is a platform-independent general computation
bytecode
language. It has a one-to-one mapping with a human readable equivalent. These are used interchangeably.
Most webassembly compilers (including the one above) produce additional exports for their own linking purposes. In many cases the generation of these is difficult or impossible to disable.
Unwanted exports will lead to an otherwise valid Hook being rejected. Therefore after compilation developers should use the Hook Cleaner Utility to strip out these out. Failure to do so will lead to your Hook being rejected.
❗️ Important
Don't forget to use the Hook Cleaner Utility or your Hooks will be rejected.