Expand description
Host function API for delegates.
This module provides synchronous access to delegate context, secrets, and contract state via host functions, eliminating the need for message round-trips.
§Example
use freenet_stdlib::prelude::*;
#[delegate]
impl DelegateInterface for MyDelegate {
fn process(
ctx: &mut DelegateCtx,
_params: Parameters<'static>,
_attested: Option<&'static [u8]>,
message: InboundDelegateMsg,
) -> Result<Vec<OutboundDelegateMsg>, DelegateError> {
// Read/write temporary context
let data = ctx.read();
ctx.write(b"new state");
// Access persistent secrets
if let Some(key) = ctx.get_secret(b"private_key") {
// use key...
}
ctx.set_secret(b"new_secret", b"value");
// V2: Direct contract access (no round-trips!)
let contract_id = [0u8; 32]; // your contract instance ID
if let Some(state) = ctx.get_contract_state(&contract_id) {
// process state...
}
ctx.put_contract_state(&contract_id, b"new state");
Ok(vec![])
}
}§Context vs Secrets vs Contracts
-
Context (
read/write): Temporary state within a single message batch. Reset between separate runtime calls. Use for intermediate processing state. -
Secrets (
get_secret/set_secret): Persistent encrypted storage. Survives across all delegate invocations. Use for private keys, tokens, etc. -
Contracts (
get_contract_state/put_contract_state/update_contract_state/subscribe_contract/list_subscriptions): V2 host functions for direct contract state access. Synchronous local reads/writes — no request/response round-trips.
§Adding a host function is the additive way to extend this API
Host functions are resolved by name at module instantiation. A delegate that imports one an older node does not provide fails to load, with a named missing-import error; a delegate that does not import it is unaffected. So adding a host function is additive for every existing delegate, and its failure mode for a too-old node is loud and diagnosable at load time.
Contrast the message API (OutboundDelegateMsg): a new variant sent to an
older host fails mid-protocol at bincode decode, with no way for the
delegate to have detected the host’s version first. Where a capability can
be expressed either way, prefer the host function.
§Error Codes
Host functions return negative values to indicate errors:
| Code | Meaning |
|---|---|
| 0 | Success |
| -1 | Called outside process() context |
| -2 | Secret not found |
| -3 | Storage operation failed |
| -4 | Invalid parameter (e.g., negative length) |
| -5 | Context too large (exceeds i32::MAX) |
| -6 | Buffer too small |
| -7 | Contract not found in local store |
| -8 | Internal state store error |
| -9 | WASM memory bounds violation |
| -10 | Contract code not registered |
The wrapper methods in DelegateCtx handle these error codes and present
a more ergonomic API.
Modules§
- error_
codes - Error codes returned by host functions.
Structs§
- Delegate
Ctx - Opaque handle to the delegate’s execution environment.
Enums§
- Subscribe
Outcome - What a delegate’s subscribe request actually achieved.
Constants§
- MAX_
SUBSCRIPTION_ LIST_ BYTES - Upper bound on the serialized subscription list a host may report from
__frnt__delegate__list_subscriptions_len, in bytes — 32 KiB, i.e. 1024 contract ids. - MAX_
WAKEUP_ TAG_ BYTES - Largest
tagDelegateCtx::schedule_wakeupwill send, in bytes. - MIN_
WAKEUP_ DELAY - Shortest delay
DelegateCtx::schedule_wakeupwill request. Anything below it is clamped up to it, by that function.
Functions§
- clamp_
wakeup_ delay - Raise
aftertoMIN_WAKEUP_DELAYif it is below it. - decode_
contract_ id_ list - Decode the format written by
encode_contract_id_list, orNoneif the buffer is not a whole number of ids. - decode_
secret_ key_ list - Inverse of
encode_secret_key_list. A truncated trailing record (which can only happen if the buffer was clipped mid-record) is dropped rather than panicking, so a short read degrades to “fewer keys” instead of a trap. - encode_
contract_ id_ list - Serialize contract instance ids for
DelegateCtx::list_subscriptions: the raw 32 bytes of each id, back to back, with no framing. - encode_
secret_ key_ list - Serialize a list of raw secret keys into the wire format read back by
decode_secret_key_list: for each key, a 4-byte little-endian length followed by that many key bytes. This is the encoding the host (__frnt__delegate__list_secrets) writes into the delegate’s output buffer.