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
1 change: 1 addition & 0 deletions bins/validator-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ async fn main() -> Result<()> {
enable_fuel: args.wasm_enable_fuel,
fuel_limit: args.wasm_fuel_limit,
storage_host_config: wasm_runtime_interface::StorageHostConfig::default(),
storage_backend: std::sync::Arc::new(wasm_runtime_interface::InMemoryStorageBackend::new()),
}) {
Ok(executor) => {
info!(
Expand Down
77 changes: 49 additions & 28 deletions bins/validator-node/src/wasm_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,30 @@ use std::time::Instant;
use tracing::{debug, info};
use wasm_runtime_interface::{
ConsensusPolicy, ExecPolicy, InMemoryStorageBackend, InstanceConfig, NetworkHostFunctions,
NetworkPolicy, NoopStorageBackend, RuntimeConfig, SandboxHostFunctions, SandboxPolicy,
StorageHostConfig, StorageHostState, TerminalPolicy, TimePolicy, WasmModule, WasmRuntime,
WasmRuntimeError,
NetworkPolicy, RuntimeConfig, SandboxHostFunctions, SandboxPolicy, StorageBackend,
StorageHostConfig, TerminalPolicy, TimePolicy, WasmModule, WasmRuntime, WasmRuntimeError,
};

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EvaluationInput {
pub agent_data: Vec<u8>,
pub challenge_id: String,
pub params: Vec<u8>,
#[serde(default)]
pub task_definition: Option<Vec<u8>>,
#[serde(default)]
pub environment_config: Option<Vec<u8>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct EvaluationOutput {
pub score: i64,
pub valid: bool,
pub message: String,
#[serde(default)]
pub metrics: Option<Vec<u8>>,
#[serde(default)]
pub details: Option<Vec<u8>>,
}

impl EvaluationOutput {
Expand All @@ -34,6 +41,8 @@ impl EvaluationOutput {
score,
valid: true,
message: String::from(message),
metrics: None,
details: None,
}
}

Expand All @@ -43,6 +52,8 @@ impl EvaluationOutput {
score: 0,
valid: false,
message: String::from(message),
metrics: None,
details: None,
}
}
}
Expand All @@ -53,6 +64,7 @@ pub struct WasmExecutorConfig {
pub enable_fuel: bool,
pub fuel_limit: Option<u64>,
pub storage_host_config: StorageHostConfig,
pub storage_backend: Arc<dyn StorageBackend>,
}

impl Default for WasmExecutorConfig {
Expand All @@ -63,6 +75,7 @@ impl Default for WasmExecutorConfig {
enable_fuel: false,
fuel_limit: None,
storage_host_config: StorageHostConfig::default(),
storage_backend: Arc::new(InMemoryStorageBackend::new()),
}
}
}
Expand Down Expand Up @@ -143,6 +156,8 @@ impl WasmChallengeExecutor {
agent_data: agent_data.to_vec(),
challenge_id: challenge_id.to_string(),
params: params.to_vec(),
task_definition: None,
environment_config: None,
};

let serialized =
Expand All @@ -162,6 +177,15 @@ impl WasmChallengeExecutor {
validator_id: "validator".to_string(),
restart_id: String::new(),
config_version: 0,
storage_host_config: StorageHostConfig {
allow_direct_writes: true,
require_consensus: false,
..self.config.storage_host_config.clone()
},
storage_backend: Arc::clone(&self.config.storage_backend),
fixed_timestamp_ms: None,
consensus_policy: ConsensusPolicy::default(),
terminal_policy: TerminalPolicy::default(),
..Default::default()
};

Expand All @@ -170,12 +194,6 @@ impl WasmChallengeExecutor {
.instantiate(&module, instance_config, Some(network_host_fns))
.map_err(|e| anyhow::anyhow!("WASM instantiation failed: {}", e))?;

let _storage_state = StorageHostState::new(
challenge_id.to_string(),
self.config.storage_host_config.clone(),
Arc::new(NoopStorageBackend),
);

let initial_fuel = instance.fuel_remaining();

let ptr = self.allocate_input(&mut instance, &serialized)?;
Expand Down Expand Up @@ -261,6 +279,8 @@ impl WasmChallengeExecutor {
agent_data: agent_data.to_vec(),
challenge_id: challenge_id.to_string(),
params: params.to_vec(),
task_definition: None,
environment_config: None,
};

let serialized =
Expand All @@ -280,6 +300,15 @@ impl WasmChallengeExecutor {
validator_id: "validator".to_string(),
restart_id: String::new(),
config_version: 0,
storage_host_config: StorageHostConfig {
allow_direct_writes: true,
require_consensus: false,
..self.config.storage_host_config.clone()
},
storage_backend: Arc::clone(&self.config.storage_backend),
fixed_timestamp_ms: None,
consensus_policy: ConsensusPolicy::default(),
terminal_policy: TerminalPolicy::default(),
..Default::default()
};

Expand All @@ -288,12 +317,6 @@ impl WasmChallengeExecutor {
.instantiate(&module, instance_config, Some(network_host_fns))
.map_err(|e| anyhow::anyhow!("WASM instantiation failed: {}", e))?;

let _storage_state = StorageHostState::new(
challenge_id.to_string(),
self.config.storage_host_config.clone(),
Arc::new(NoopStorageBackend),
);

let initial_fuel = instance.fuel_remaining();

let ptr = self.allocate_input(&mut instance, &serialized)?;
Expand Down Expand Up @@ -396,6 +419,7 @@ impl WasmChallengeExecutor {
fixed_timestamp_ms: None,
consensus_policy: ConsensusPolicy::default(),
terminal_policy: TerminalPolicy::default(),
..Default::default()
};

let mut instance = self
Expand All @@ -405,21 +429,17 @@ impl WasmChallengeExecutor {

let initial_fuel = instance.fuel_remaining();

let result_ptr = instance
.call_return_i32("get_tasks")
let result = instance
.call_return_i64("get_tasks")
.map_err(|e| anyhow::anyhow!("WASM get_tasks call failed: {}", e))?;

let result_data = if result_ptr > 0 {
let len = instance
.call_return_i32("get_tasks_result_len")
.unwrap_or(0);
if len > 0 {
instance
.read_memory(result_ptr as usize, len as usize)
.unwrap_or_default()
} else {
Vec::new()
}
let out_len = (result >> 32) as i32;
let out_ptr = (result & 0xFFFF_FFFF) as i32;

let result_data = if out_ptr > 0 && out_len > 0 {
instance
.read_memory(out_ptr as usize, out_len as usize)
.unwrap_or_default()
} else {
Vec::new()
};
Expand Down Expand Up @@ -478,6 +498,7 @@ impl WasmChallengeExecutor {
fixed_timestamp_ms: None,
consensus_policy: ConsensusPolicy::default(),
terminal_policy: TerminalPolicy::default(),
..Default::default()
};

let mut instance = self
Expand Down
1 change: 1 addition & 0 deletions crates/challenge-sdk-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ bincode = { version = "1.3", default-features = false }
[features]
default = []
large-arena = [] # 4 MiB arena instead of the default 1 MiB
huge-arena = [] # 16 MiB arena for complex challenges with large payloads
7 changes: 5 additions & 2 deletions crates/challenge-sdk-wasm/src/alloc_impl.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use core::cell::UnsafeCell;

#[cfg(feature = "large-arena")]
#[cfg(feature = "huge-arena")]
const ARENA_SIZE: usize = 16 * 1024 * 1024;

#[cfg(all(feature = "large-arena", not(feature = "huge-arena")))]
const ARENA_SIZE: usize = 4 * 1024 * 1024;

#[cfg(not(feature = "large-arena"))]
#[cfg(not(any(feature = "large-arena", feature = "huge-arena")))]
const ARENA_SIZE: usize = 1024 * 1024;

struct BumpAllocator {
Expand Down
1 change: 1 addition & 0 deletions crates/challenge-sdk-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub use types::{
score_f64_scaled, SandboxExecRequest, SandboxExecResponse, TaskDefinition, TaskResult,
TermEvaluationParams,
};
pub use types::{ContainerRunRequest, ContainerRunResponse};
pub use types::{EvaluationInput, EvaluationOutput};

pub trait Challenge {
Expand Down
21 changes: 21 additions & 0 deletions crates/challenge-sdk-wasm/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,24 @@ pub struct TermEvaluationParams {
pub timeout_ms: u64,
pub environment_config: Option<Vec<u8>>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ContainerRunRequest {
pub image: String,
pub command: Vec<String>,
pub env_vars: Vec<(String, String)>,
pub working_dir: Option<String>,
pub stdin: Option<Vec<u8>>,
pub memory_limit_mb: Option<u64>,
pub cpu_limit: Option<u32>,
pub network_mode: Option<String>,
pub timeout_ms: u64,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ContainerRunResponse {
pub exit_code: i32,
pub stdout: Vec<u8>,
pub stderr: Vec<u8>,
pub duration_ms: u64,
}
4 changes: 2 additions & 2 deletions crates/wasm-runtime-interface/src/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub fn output_to_response(
execution_time_ms: i64,
) -> EvalResponse {
if output.valid {
let score = output.score as f64 / 100.0;
let score = output.score as f64 / 10_000.0;
let results = serde_json::json!({ "message": output.message });
EvalResponse::success(request_id, score, results).with_time(execution_time_ms)
} else {
Expand Down Expand Up @@ -185,7 +185,7 @@ mod tests {

#[test]
fn test_output_to_response_success() {
let output = EvaluationOutput::success(100, "perfect");
let output = EvaluationOutput::success(10000, "perfect");
let resp = output_to_response(&output, "req-1", 42);
assert!(resp.success);
assert_eq!(resp.request_id, "req-1");
Expand Down
Loading