Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "freenet-stdlib"
version = "0.2.0"
version = "0.2.1"
edition = "2021"
rust-version = "1.80"
publish = true
Expand Down
86 changes: 86 additions & 0 deletions rust/src/delegate_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,14 @@ pub mod error_codes {
pub const ERR_MEMORY_BOUNDS: i32 = -9;
/// Contract code not registered in the index.
pub const ERR_CONTRACT_CODE_NOT_REGISTERED: i32 = -10;
/// Delegate creation depth limit exceeded.
pub const ERR_DEPTH_EXCEEDED: i32 = -20;
/// Per-call delegate creation limit exceeded.
pub const ERR_CREATIONS_EXCEEDED: i32 = -21;
/// Invalid WASM module (failed to construct DelegateContainer).
pub const ERR_INVALID_WASM: i32 = -23;
/// Failed to register delegate in secret/delegate store.
pub const ERR_STORE_FAILED: i32 = -24;
}

// ============================================================================
Expand Down Expand Up @@ -160,6 +168,24 @@ extern "C" {
fn __frnt__delegate__subscribe_contract(id_ptr: i64, id_len: i32) -> i64;
}

#[cfg(target_family = "wasm")]
#[link(wasm_import_module = "freenet_delegate_management")]
extern "C" {
/// Create a new delegate from WASM code + parameters.
/// Returns 0 on success, negative error code on failure.
/// On success, writes 32 bytes to out_key_ptr and 32 bytes to out_hash_ptr.
fn __frnt__delegate__create_delegate(
wasm_ptr: i64,
wasm_len: i64,
params_ptr: i64,
params_len: i32,
cipher_ptr: i64,
nonce_ptr: i64,
out_key_ptr: i64,
out_hash_ptr: i64,
) -> i32;
}

// ============================================================================
// DelegateCtx - Unified handle to context, secrets, and contracts
// ============================================================================
Expand All @@ -183,6 +209,9 @@ extern "C" {
/// [`put_contract_state`](Self::put_contract_state),
/// [`update_contract_state`](Self::update_contract_state),
/// [`subscribe_contract`](Self::subscribe_contract)
///
/// # Delegate Management Methods (V2)
/// - [`create_delegate`](Self::create_delegate)
#[derive(Default)]
#[repr(transparent)]
pub struct DelegateCtx {
Expand Down Expand Up @@ -526,6 +555,63 @@ impl DelegateCtx {
false
}
}

/// Create a new child delegate from WASM bytecode and parameters.
///
/// This V2 host function allows a delegate to spawn new delegates at runtime.
/// The child delegate is registered in the node's delegate store and secret store
/// with the provided cipher and nonce.
///
/// Returns `Ok((key_hash, code_hash))` where both are 32-byte arrays identifying
/// the newly created delegate. Returns `Err(error_code)` on failure.
///
/// # Resource Limits
/// - Maximum creation depth: 4 (prevents fork bombs)
/// - Maximum creations per process() call: 8
///
/// # Error Codes
/// - `-1`: Called outside process() context
/// - `-4`: Invalid parameter
/// - `-9`: WASM memory bounds violation
/// - `-20`: Depth limit exceeded
/// - `-21`: Per-call creation limit exceeded
/// - `-23`: Invalid WASM module
/// - `-24`: Store registration failed
pub fn create_delegate(
&mut self,
wasm_code: &[u8],
params: &[u8],
cipher: &[u8; 32],
nonce: &[u8; 24],
) -> Result<([u8; 32], [u8; 32]), i32> {
#[cfg(target_family = "wasm")]
{
let mut key_buf = [0u8; 32];
let mut hash_buf = [0u8; 32];
let result = unsafe {
__frnt__delegate__create_delegate(
wasm_code.as_ptr() as i64,
wasm_code.len() as i64,
params.as_ptr() as i64,
params.len() as i32,
cipher.as_ptr() as i64,
nonce.as_ptr() as i64,
key_buf.as_mut_ptr() as i64,
hash_buf.as_mut_ptr() as i64,
)
};
if result == 0 {
Ok((key_buf, hash_buf))
} else {
Err(result)
}
}
#[cfg(not(target_family = "wasm"))]
{
let _ = (wasm_code, params, cipher, nonce);
Err(error_codes::ERR_NOT_IN_PROCESS)
}
}
}

impl std::fmt::Debug for DelegateCtx {
Expand Down