Skip to content

Commit

Permalink
runner (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
xlc committed May 23, 2024
1 parent 0fb3a86 commit 6895160
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 33 deletions.
129 changes: 124 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 13 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ panic = "unwind"
opt-level = 3

[workspace.dependencies]
# local
xcq-api = { path = "xcq-api", default-features = false }
xcq-executor = { path = "xcq-executor", default-features = false }
xcq-extension-core = { path = "xcq-extension-core", default-features = false }
Expand All @@ -43,10 +44,18 @@ xcq-runtime-api = { path = "xcq-runtime-api", default-features = false }
xcq-test-runner = { path = "xcq-test-runner", default-features = false }
xcq-types = { path = "xcq-types", default-features = false }

env_logger = { version = "0.11.3" }
parity-scale-codec = { version = "3.6.12", default-features = false }
scale-info = { version = "2.11.3", default-features = false }

# polkavm
polkavm = { path = "vendor/polkavm/crates/polkavm", default-features = false }

# polkadot-sdk
sp-api = { version = "29.0.0", default-features = false }

# nostd
parity-scale-codec = { version = "3.6.12", default-features = false, features = ["derive", "max-encoded-len"] }
scale-info = { version = "2.11.3", default-features = false, features = ["derive"] }
tracing = { version = "0.1.40", default-features = false }

# std
clap = { version = "4.5.4", features = ["derive"] }
env_logger = { version = "0.11.3" }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
15 changes: 14 additions & 1 deletion xcq-executor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,20 @@ repository.workspace = true
version.workspace = true

[dependencies]
tracing = { workspace = true }

polkavm = { workspace = true }

xcq-api = { workspace = true }
xcq-primitives = { workspace = true }

[features]
default = ["std"]
std = []
std = [
"tracing/std",

"polkavm/std",

"xcq-api/std",
"xcq-primitives/std",
]
85 changes: 76 additions & 9 deletions xcq-executor/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,83 @@
#![cfg_attr(not(feature = "std"), no_std)]

pub fn add(left: usize, right: usize) -> usize {
left + right
extern crate alloc;

pub use alloc::vec::Vec;
pub use polkavm::{Config, Engine, Linker, Module, ProgramBlob};

pub trait XcqExecutorContext {
fn register_host_functions<T>(&mut self, linker: &mut Linker<T>);
}

pub struct XcqExecutor<Ctx: XcqExecutorContext> {
engine: Engine,
linker: Linker<Ctx>,
context: Ctx,
}

#[derive(Debug)]
pub enum XcqExecutorError {
ProgramParseError(polkavm::ProgramParseError),
PrepareError(polkavm::Error),
ExecutionError(polkavm::ExecutionError<polkavm::Error>),
}

impl From<polkavm::ProgramParseError> for XcqExecutorError {
fn from(err: polkavm::ProgramParseError) -> Self {
Self::ProgramParseError(err)
}
}

#[cfg(test)]
mod tests {
use super::*;
impl From<polkavm::Error> for XcqExecutorError {
fn from(err: polkavm::Error) -> Self {
Self::PrepareError(err)
}
}

impl From<polkavm::ExecutionError<polkavm::Error>> for XcqExecutorError {
fn from(err: polkavm::ExecutionError<polkavm::Error>) -> Self {
Self::ExecutionError(err)
}
}

impl<Ctx: XcqExecutorContext> XcqExecutor<Ctx> {
pub fn new(config: Config, mut context: Ctx) -> Self {
let engine = Engine::new(&config).unwrap();
let mut linker = Linker::<Ctx>::new(&engine);
context.register_host_functions(&mut linker);
Self {
engine,
linker,
context,
}
}

pub fn execute(&mut self, raw_blob: &[u8], input: &[u8]) -> Result<Vec<u8>, XcqExecutorError> {
let blob = ProgramBlob::parse(raw_blob.into())?;
let module = Module::from_blob(&self.engine, &Default::default(), blob)?;
let instance_pre = self.linker.instantiate_pre(&module)?;
let instance = instance_pre.instantiate()?;

// Args are passed via guest's heap
let input_ptr = if !input.is_empty() {
let ptr = instance
.sbrk(input.len() as u32)?
.expect("sbrk must be able to allocate memory here");
instance
.write_memory(ptr, input)
.map_err(|e| XcqExecutorError::ExecutionError(polkavm::ExecutionError::Trap(e)))?;
ptr
} else {
0
};

#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
// return value is u64 instead of (u32, u32) due to https://github.com/koute/polkavm/issues/116
let res = instance.call_typed::<(u32,), u64>(&mut self.context, "main", (input_ptr,))?;
let res_ptr = (res >> 32) as u32;
let res_len = (res & 0xffffffff) as u32;
let result = instance
.read_memory_into_vec(res_ptr, res_len)
.map_err(|e| XcqExecutorError::ExecutionError(polkavm::ExecutionError::Trap(e)))?;
Ok(result)
}
}
7 changes: 7 additions & 0 deletions xcq-test-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ repository.workspace = true
version.workspace = true

[dependencies]
clap = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }

xcq-executor = { workspace = true, features = ["std"] }

polkavm = { workspace = true }
Loading

0 comments on commit 6895160

Please sign in to comment.