Skip to content

Commit 97d91f7

Browse files
committed
Merge remote-tracking branch 'upstream/ripple/wasmi-host-functions' into hf-macro2
2 parents 88704bf + 65f9cf8 commit 97d91f7

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

src/xrpld/app/wasm/README.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# WASM Module for Programmable Escrows
2+
3+
This module provides WebAssembly (WASM) execution capabilities for programmable
4+
escrows on the XRP Ledger. When an escrow is finished, the WASM code runs to
5+
determine whether the escrow conditions are met, enabling custom programmable
6+
logic for escrow release conditions.
7+
8+
For the full specification, see
9+
[XLS-0102: WASM VM](https://xls.xrpl.org/xls/XLS-0102-wasm-vm.html).
10+
11+
## Architecture
12+
13+
The module follows a layered architecture:
14+
15+
```
16+
┌─────────────────────────────────────────────────────────────┐
17+
│ WasmEngine (WasmVM.h) │
18+
│ runEscrowWasm(), preflightEscrowWasm() │
19+
│ Host function registration │
20+
├─────────────────────────────────────────────────────────────┤
21+
│ WasmiEngine (WasmiVM.h) │
22+
│ Low-level wasmi interpreter integration │
23+
├─────────────────────────────────────────────────────────────┤
24+
│ HostFuncWrapper │ HostFuncImpl │
25+
│ C-style WASM bridges │ C++ implementations │
26+
├─────────────────────────────────────────────────────────────┤
27+
│ HostFunc (Interface) │
28+
│ Abstract base class for host functions │
29+
└─────────────────────────────────────────────────────────────┘
30+
```
31+
32+
### Key Components
33+
34+
- **`WasmVM.h` / `detail/WasmVM.cpp`** - High-level facade providing:
35+
- `WasmEngine` singleton that wraps the underlying WASM interpreter
36+
- `runEscrowWasm()` - Execute WASM code for escrow finish
37+
- `preflightEscrowWasm()` - Validate WASM code during preflight
38+
- `createWasmImport()` - Register all host functions
39+
40+
- **`WasmiVM.h` / `detail/WasmiVM.cpp`** - Low-level integration with the
41+
[wasmi](https://github.com/wasmi-labs/wasmi) WebAssembly interpreter:
42+
- `WasmiEngine` - Manages WASM modules, instances, and execution
43+
- Memory management and gas metering
44+
- Function invocation and result handling
45+
46+
- **`HostFunc.h`** - Abstract `HostFunctions` base class defining the interface
47+
for all callable host functions. Each method returns
48+
`Expected<T, HostFunctionError>`.
49+
50+
- **`HostFuncImpl.h` / `detail/HostFuncImpl*.cpp`** - Concrete
51+
`WasmHostFunctionsImpl` class that implements host functions with access to
52+
`ApplyContext` for ledger state queries. Implementation split across files:
53+
- `HostFuncImpl.cpp` - Core utilities (updateData, checkSignature, etc.)
54+
- `HostFuncImplFloat.cpp` - Float/number arithmetic operations
55+
- `HostFuncImplGetter.cpp` - Field access (transaction, ledger objects)
56+
- `HostFuncImplKeylet.cpp` - Keylet construction functions
57+
- `HostFuncImplLedgerHeader.cpp` - Ledger header info access
58+
- `HostFuncImplNFT.cpp` - NFT-related queries
59+
- `HostFuncImplTrace.cpp` - Debugging/tracing functions
60+
61+
- **`HostFuncWrapper.h` / `detail/HostFuncWrapper.cpp`** - C-style wrapper
62+
functions that bridge WASM calls to C++ `HostFunctions` methods. Each host
63+
function has:
64+
- A `_proto` type alias defining the function signature
65+
- A `_wrap` function that extracts parameters and calls the implementation
66+
67+
- **`ParamsHelper.h`** - Utilities for WASM parameter handling:
68+
- `WASM_IMPORT_FUNC` / `WASM_IMPORT_FUNC2` macros for registration
69+
- `wasmParams()` helper for building parameter vectors
70+
- Type conversion between WASM and C++ types
71+
72+
## Host Functions
73+
74+
Host functions allow WASM code to interact with the XRP Ledger. They are
75+
organized into categories:
76+
77+
- **Ledger Information** - Access ledger sequence, timestamps, hashes, fees
78+
- **Transaction & Ledger Object Access** - Read fields from the transaction
79+
and ledger objects (including the current escrow object)
80+
- **Keylet Construction** - Build keylets to look up various ledger object types
81+
- **Cryptography** - Signature verification and hashing
82+
- **Float Arithmetic** - Mathematical operations for amount calculations
83+
- **NFT Operations** - Query NFT properties
84+
- **Tracing/Debugging** - Log messages for debugging
85+
86+
For the complete list of available host functions, their WASM names, and gas
87+
costs, see the [XLS-0102 specification](https://xls.xrpl.org/xls/XLS-0102-wasm-vm.html)
88+
or `detail/WasmVM.cpp` where they are registered via `WASM_IMPORT_FUNC2` macros.
89+
For method signatures, see `HostFunc.h`.
90+
91+
## Gas Model
92+
93+
Each host function has an associated gas cost. The gas cost is specified when
94+
registering the function in `detail/WasmVM.cpp`:
95+
96+
```cpp
97+
WASM_IMPORT_FUNC2(i, getLedgerSqn, "get_ledger_sqn", hfs, 60);
98+
// ^^ gas cost
99+
```
100+
101+
WASM execution is metered, and if the gas limit is exceeded, execution fails.
102+
103+
## Entry Point
104+
105+
The WASM module must export a function with the name defined by
106+
`ESCROW_FUNCTION_NAME` (currently `"finish"`). This function:
107+
108+
- Takes no parameters (or parameters passed via host function calls)
109+
- Returns an `int32_t`:
110+
- `1` (or positive): Escrow conditions are met, allow finish
111+
- `0` (or negative): Escrow conditions are not met, reject finish
112+
113+
## Adding a New Host Function
114+
115+
To add a new host function, follow these steps:
116+
117+
### 1. Add to HostFunc.h (Base Class)
118+
119+
Add a virtual method declaration with a default implementation that returns an
120+
error:
121+
122+
```cpp
123+
virtual Expected<ReturnType, HostFunctionError>
124+
myNewFunction(ParamType1 param1, ParamType2 param2)
125+
{
126+
return Unexpected(HostFunctionError::INTERNAL);
127+
}
128+
```
129+
130+
### 2. Add to HostFuncImpl.h (Declaration)
131+
132+
Add the method override declaration in `WasmHostFunctionsImpl`:
133+
134+
```cpp
135+
Expected<ReturnType, HostFunctionError>
136+
myNewFunction(ParamType1 param1, ParamType2 param2) override;
137+
```
138+
139+
### 3. Implement in detail/HostFuncImpl\*.cpp
140+
141+
Add the implementation in the appropriate file:
142+
143+
```cpp
144+
Expected<ReturnType, HostFunctionError>
145+
WasmHostFunctionsImpl::myNewFunction(ParamType1 param1, ParamType2 param2)
146+
{
147+
// Implementation using ctx (ApplyContext) for ledger access
148+
return result;
149+
}
150+
```
151+
152+
### 4. Add Wrapper to HostFuncWrapper.h
153+
154+
Add the prototype and wrapper declaration:
155+
156+
```cpp
157+
using myNewFunction_proto = int32_t(uint8_t const*, int32_t, ...);
158+
wasm_trap_t*
159+
myNewFunction_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results);
160+
```
161+
162+
### 5. Implement Wrapper in detail/HostFuncWrapper.cpp
163+
164+
Implement the C-style wrapper that bridges WASM to C++:
165+
166+
```cpp
167+
wasm_trap_t*
168+
myNewFunction_wrap(void* env, wasm_val_vec_t const* params, wasm_val_vec_t* results)
169+
{
170+
// Extract parameters from params
171+
// Call hfs->myNewFunction(...)
172+
// Set results and return
173+
}
174+
```
175+
176+
### 6. Register in WasmVM.cpp
177+
178+
Add the function registration in `setCommonHostFunctions()` or
179+
`createWasmImport()`:
180+
181+
```cpp
182+
WASM_IMPORT_FUNC2(i, myNewFunction, "my_new_function", hfs, 100);
183+
// ^^ WASM name ^^ gas cost
184+
```
185+
186+
> [!IMPORTANT]
187+
> New host functions MUST be amendment-gated in `WasmVM.cpp`.
188+
> Wrap the registration in an amendment check to ensure the function is only
189+
> available after the corresponding amendment is enabled on the network.

0 commit comments

Comments
 (0)