use std::sync::Arc;
use wasmtime::{Engine, Linker, Module};
use crate::engine::HostState;
use crate::error::WasmtimeRuntimeError;
use cc_lb_plugin_wire::schema::HookKind;
use crate::inspect::{ModuleInspection, inspect_wasm};
use crate::probe::probe_hook_dispatch;
pub(crate) const VALIDATION_POLICY_VERSION: u32 = 1;
pub(crate) fn compute_content_hash(wasm_bytes: &[u8], memory_max_pages: u32) -> [u8; 32] {
let mut hasher = blake3::Hasher::new();
hasher.update(&VALIDATION_POLICY_VERSION.to_le_bytes());
hasher.update(&memory_max_pages.to_le_bytes());
hasher.update(wasm_bytes);
*hasher.finalize().as_bytes()
}
#[allow(unsafe_code)]
pub fn compile_module(
engine: &Engine,
linker: &Linker<HostState>,
kind: HookKind,
wasm_bytes: &[u8],
) -> Result<(Arc<wasmtime::InstancePre<HostState>>, ModuleInspection), WasmtimeRuntimeError> {
let inspection = inspect_wasm(kind, wasm_bytes)?;
let cwasm = engine
.precompile_module(wasm_bytes)
.map_err(|e| WasmtimeRuntimeError::ModuleCompile(anyhow::Error::from(e)))?;
let module = unsafe {
Module::deserialize(engine, &cwasm)
.map_err(|e| WasmtimeRuntimeError::ModuleCompile(anyhow::Error::from(e)))?
};
let instance_pre = linker
.instantiate_pre(&module)
.map_err(|e| WasmtimeRuntimeError::InstantiateFailed(anyhow::Error::from(e)))?;
Ok((Arc::new(instance_pre), inspection))
}
pub fn admit_wasm(
engine: &Engine,
linker: &Linker<HostState>,
kind: HookKind,
wasm_bytes: &[u8],
memory_max_pages: u32,
) -> Result<(Arc<wasmtime::InstancePre<HostState>>, ModuleInspection), WasmtimeRuntimeError> {
let (instance_pre, inspection) = compile_module(engine, linker, kind, wasm_bytes)?;
for (hook, wire_version) in &inspection.hook_versions {
probe_hook_dispatch(
Arc::clone(&instance_pre),
*hook,
*wire_version,
&inspection.metadata,
memory_max_pages,
)?;
}
Ok((instance_pre, inspection))
}