Skip to main content

Module delegate_host

Module delegate_host 

Source
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:

CodeMeaning
0Success
-1Called outside process() context
-2Secret not found
-3Storage operation failed
-4Invalid parameter (e.g., negative length)
-5Context too large (exceeds i32::MAX)
-6Buffer too small
-7Contract not found in local store
-8Internal state store error
-9WASM memory bounds violation
-10Contract 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§

DelegateCtx
Opaque handle to the delegate’s execution environment.

Enums§

SubscribeOutcome
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 tag DelegateCtx::schedule_wakeup will send, in bytes.
MIN_WAKEUP_DELAY
Shortest delay DelegateCtx::schedule_wakeup will request. Anything below it is clamped up to it, by that function.

Functions§

clamp_wakeup_delay
Raise after to MIN_WAKEUP_DELAY if it is below it.
decode_contract_id_list
Decode the format written by encode_contract_id_list, or None if 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.