From 3a7dc299942ba18f9e1f18205fcd4b05c7f98b17 Mon Sep 17 00:00:00 2001 From: echobt Date: Tue, 17 Feb 2026 07:34:37 +0000 Subject: [PATCH 1/3] fix(challenge-sdk-wasm): align host function signatures with runtime interface - Fix http_get, http_post, dns_resolve extern signatures to use 4 params (req_ptr, req_len, resp_ptr, resp_len) matching the host linker registrations - Add http_request extern for the generic HTTP host function - Fix storage externs: rename storage_set to storage_propose_write, add storage_delete, update return types to match host pack_result convention - Update all wrapper functions to pass correct arguments - Change host_http_post to accept single serialized request (body is part of the HttpPostRequest struct deserialized by the host) --- .../challenge-sdk-wasm/src/host_functions.rs | 66 +++++++++++++------ 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/crates/challenge-sdk-wasm/src/host_functions.rs b/crates/challenge-sdk-wasm/src/host_functions.rs index 7913bfec..360663b1 100644 --- a/crates/challenge-sdk-wasm/src/host_functions.rs +++ b/crates/challenge-sdk-wasm/src/host_functions.rs @@ -3,15 +3,34 @@ use alloc::vec::Vec; #[link(wasm_import_module = "platform_network")] extern "C" { - fn http_get(req_ptr: i32, req_len: i32, resp_ptr: i32) -> i32; - fn http_post(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32, extra: i32) -> i32; - fn dns_resolve(req_ptr: i32, req_len: i32, resp_ptr: i32) -> i32; + fn http_request(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32) -> i32; + fn http_get(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32) -> i32; + fn http_post(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32) -> i32; + fn dns_resolve(req_ptr: i32, req_len: i32, resp_ptr: i32, resp_len: i32) -> i32; } #[link(wasm_import_module = "platform_storage")] extern "C" { - fn storage_get(key_ptr: i32, key_len: i32, value_ptr: i32) -> i32; - fn storage_set(key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32) -> i32; + fn storage_get(key_ptr: i32, key_len: i32) -> i64; + fn storage_propose_write(key_ptr: i32, key_len: i32, value_ptr: i32, value_len: i32) -> i64; + fn storage_delete(key_ptr: i32, key_len: i32) -> i32; +} + +pub fn host_http_request(request: &[u8]) -> Result, i32> { + let mut response_buf = vec![0u8; 65536]; + let status = unsafe { + http_request( + request.as_ptr() as i32, + request.len() as i32, + response_buf.as_mut_ptr() as i32, + response_buf.len() as i32, + ) + }; + if status < 0 { + return Err(status); + } + response_buf.truncate(status as usize); + Ok(response_buf) } pub fn host_http_get(request: &[u8]) -> Result, i32> { @@ -21,6 +40,7 @@ pub fn host_http_get(request: &[u8]) -> Result, i32> { request.as_ptr() as i32, request.len() as i32, response_buf.as_mut_ptr() as i32, + response_buf.len() as i32, ) }; if status < 0 { @@ -30,7 +50,7 @@ pub fn host_http_get(request: &[u8]) -> Result, i32> { Ok(response_buf) } -pub fn host_http_post(request: &[u8], body: &[u8]) -> Result, i32> { +pub fn host_http_post(request: &[u8]) -> Result, i32> { let mut response_buf = vec![0u8; 65536]; let status = unsafe { http_post( @@ -38,7 +58,6 @@ pub fn host_http_post(request: &[u8], body: &[u8]) -> Result, i32> { request.len() as i32, response_buf.as_mut_ptr() as i32, response_buf.len() as i32, - body.len() as i32, ) }; if status < 0 { @@ -55,6 +74,7 @@ pub fn host_dns_resolve(request: &[u8]) -> Result, i32> { request.as_ptr() as i32, request.len() as i32, response_buf.as_mut_ptr() as i32, + response_buf.len() as i32, ) }; if status < 0 { @@ -64,31 +84,35 @@ pub fn host_dns_resolve(request: &[u8]) -> Result, i32> { Ok(response_buf) } -pub fn host_storage_get(key: &[u8]) -> Result, i32> { - let mut value_buf = vec![0u8; 65536]; - let status = unsafe { - storage_get( - key.as_ptr() as i32, - key.len() as i32, - value_buf.as_mut_ptr() as i32, - ) - }; +pub fn host_storage_get(key: &[u8]) -> Result<(i32, u32), i32> { + let packed = unsafe { storage_get(key.as_ptr() as i32, key.len() as i32) }; + let status = (packed >> 32) as i32; + let value = (packed & 0xFFFFFFFF) as u32; if status < 0 { return Err(status); } - value_buf.truncate(status as usize); - Ok(value_buf) + Ok((status, value)) } -pub fn host_storage_set(key: &[u8], value: &[u8]) -> Result<(), i32> { - let status = unsafe { - storage_set( +pub fn host_storage_propose_write(key: &[u8], value: &[u8]) -> Result<(i32, u32), i32> { + let packed = unsafe { + storage_propose_write( key.as_ptr() as i32, key.len() as i32, value.as_ptr() as i32, value.len() as i32, ) }; + let status = (packed >> 32) as i32; + let result = (packed & 0xFFFFFFFF) as u32; + if status < 0 { + return Err(status); + } + Ok((status, result)) +} + +pub fn host_storage_delete(key: &[u8]) -> Result<(), i32> { + let status = unsafe { storage_delete(key.as_ptr() as i32, key.len() as i32) }; if status < 0 { return Err(status); } From 6de577db5178812f3c9b083c170897624f46b2bd Mon Sep 17 00:00:00 2001 From: echobt Date: Tue, 17 Feb 2026 07:37:20 +0000 Subject: [PATCH 2/3] feat(challenge-sdk-wasm): extend guest SDK types and add platform host functions Extend the guest SDK to support richer evaluation types and new host function modules needed by term-challenge. Types (types.rs): Add optional fields to EvaluationInput (submission_id, participant_id, epoch, metadata) and EvaluationOutput (score_f64, results, execution_time_ms) with #[serde(default)] for backward compatibility. Update the success() and error() constructors to initialize new fields as None. Host functions (host_functions.rs): Add platform_exec module with exec_command(cmd_ptr, cmd_len, resp_ptr, resp_len) -> i32 for sandboxed command execution, and platform_time module with get_timestamp() -> i64. Include safe Rust wrappers host_exec_command() and host_get_timestamp(). Trait (lib.rs): Add challenge_id() method to the Challenge trait with a default implementation that delegates to name(). --- .../challenge-sdk-wasm/src/host_functions.rs | 31 +++++++++++++++++++ crates/challenge-sdk-wasm/src/lib.rs | 3 ++ crates/challenge-sdk-wasm/src/types.rs | 20 ++++++++++++ 3 files changed, 54 insertions(+) diff --git a/crates/challenge-sdk-wasm/src/host_functions.rs b/crates/challenge-sdk-wasm/src/host_functions.rs index 360663b1..0f8c89d1 100644 --- a/crates/challenge-sdk-wasm/src/host_functions.rs +++ b/crates/challenge-sdk-wasm/src/host_functions.rs @@ -118,3 +118,34 @@ pub fn host_storage_delete(key: &[u8]) -> Result<(), i32> { } Ok(()) } + +#[link(wasm_import_module = "platform_exec")] +extern "C" { + fn exec_command(cmd_ptr: i32, cmd_len: i32, resp_ptr: i32, resp_len: i32) -> i32; +} + +pub fn host_exec_command(command: &[u8]) -> Result, i32> { + let mut response_buf = vec![0u8; 65536]; + let status = unsafe { + exec_command( + command.as_ptr() as i32, + command.len() as i32, + response_buf.as_mut_ptr() as i32, + response_buf.len() as i32, + ) + }; + if status < 0 { + return Err(status); + } + response_buf.truncate(status as usize); + Ok(response_buf) +} + +#[link(wasm_import_module = "platform_time")] +extern "C" { + fn get_timestamp() -> i64; +} + +pub fn host_get_timestamp() -> i64 { + unsafe { get_timestamp() } +} diff --git a/crates/challenge-sdk-wasm/src/lib.rs b/crates/challenge-sdk-wasm/src/lib.rs index e2ed5021..1eb737a6 100644 --- a/crates/challenge-sdk-wasm/src/lib.rs +++ b/crates/challenge-sdk-wasm/src/lib.rs @@ -13,6 +13,9 @@ pub trait Challenge { fn version(&self) -> &'static str; fn evaluate(&self, input: EvaluationInput) -> EvaluationOutput; fn validate(&self, input: EvaluationInput) -> bool; + fn challenge_id(&self) -> &'static str { + self.name() + } } /// Pack a pointer and length into a single i64 value. diff --git a/crates/challenge-sdk-wasm/src/types.rs b/crates/challenge-sdk-wasm/src/types.rs index 10e819e5..0f2d75a1 100644 --- a/crates/challenge-sdk-wasm/src/types.rs +++ b/crates/challenge-sdk-wasm/src/types.rs @@ -7,6 +7,14 @@ pub struct EvaluationInput { pub agent_data: Vec, pub challenge_id: String, pub params: Vec, + #[serde(default)] + pub submission_id: Option, + #[serde(default)] + pub participant_id: Option, + #[serde(default)] + pub epoch: Option, + #[serde(default)] + pub metadata: Option>, } #[derive(Clone, Debug, Serialize, Deserialize)] @@ -14,6 +22,12 @@ pub struct EvaluationOutput { pub score: i64, pub valid: bool, pub message: String, + #[serde(default)] + pub score_f64: Option, + #[serde(default)] + pub results: Option>, + #[serde(default)] + pub execution_time_ms: Option, } impl EvaluationOutput { @@ -22,6 +36,9 @@ impl EvaluationOutput { score, valid: true, message: String::from(message), + score_f64: None, + results: None, + execution_time_ms: None, } } @@ -30,6 +47,9 @@ impl EvaluationOutput { score: 0, valid: false, message: String::from(message), + score_f64: None, + results: None, + execution_time_ms: None, } } } From d4f840d323e6bfe6248d770f5bbf51011c4a6fd0 Mon Sep 17 00:00:00 2001 From: echobt Date: Tue, 17 Feb 2026 08:23:14 +0000 Subject: [PATCH 3/3] ci: trigger CI after merge conflict resolution