Skip to content

Commit 1e0ba66

Browse files
authored
feat(testing): migrate testing support from spacejam (#12)
* feat(testing): migrate testing support from spacejam * chore(testing): introduce storage key * feat(jade): introduce read write host calls * feat(jade): support operands fetching * feat(svc): introduce logging in host calls * chore(testing): migrate tests here * chore(services): rlib as well for services * chore(jade): make testing a feature of jade * chore(cjam): patch cdylib on building services * chore(sys): adapt new interfaces * feat(cli): sync the service output dir * chore(sys): make clippy happy * chore(testing): get back preimage insertion * feat(sys): dealloc memory pointers on receiving results * fix(jade): correct the arguments of is_authozired * feat(services): make things work again
1 parent dfca69c commit 1e0ba66

37 files changed

+1388
-60
lines changed

Cargo.lock

Lines changed: 238 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ repository = "https://github.com/spacejamapp/jade"
1414
cjam = { path = "crates/cli" }
1515
jade = { path = "crates/jade", default-features = false }
1616
jade-derive = { path = "crates/jade/derive" }
17-
sys = { path = "crates/sys" }
17+
spacevm = { path = "crates/sys", package = "spacevm-sys" }
18+
testing = { path = "crates/testing", package = "jade-testing" }
19+
20+
# services
21+
nauth = { path = "services/nauth" }
22+
stoken = { path = "services/stoken" }
1823

1924
# spacejam dependencies
2025
codec = { package = "serde-jam", version = "0.0.13-pre.1", default-features = false }

crates/cli/src/builder.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ pub fn build_pvm_blob(
161161
}
162162

163163
child
164-
.args(["build", "-Z", "build-std=core,alloc"])
164+
.args(["rustc", "-Z", "build-std=core,alloc"])
165165
.arg(profile.to_arg())
166166
.arg("--target")
167167
.arg(target_json_path)
@@ -170,7 +170,9 @@ pub fn build_pvm_blob(
170170
"tiny"
171171
} else {
172172
""
173-
}) // Disable stripping for LLVM 19 compatibility
173+
})
174+
.arg("--lib")
175+
.arg("--crate-type=cdylib")
174176
.env(
175177
"RUSTFLAGS",
176178
format!(
@@ -223,12 +225,13 @@ pub fn build_pvm_blob(
223225
.expect("Failed to link pvm program:");
224226

225227
// Write out a full `.pvm` blob for debugging/inspection.
226-
fs::create_dir_all(out_dir).expect("Failed to create jam directory");
227-
let output_path_pvm = out_dir.join(format!("{}.pvm", &info.name));
228+
let jam_out = out_dir.join("jam");
229+
fs::create_dir_all(&jam_out).expect("Failed to create jam directory");
230+
let output_path_pvm = jam_out.join(format!("{}.pvm", &info.name));
228231
fs::write(output_path_pvm, &linked).expect("Error writing resulting binary");
229232
let name = info.name.clone();
230233
let metadata = ConventionalMetadata::Info(info).encode().into();
231-
let output_file = blob_type.output_file(out_dir, &name);
234+
let output_file = blob_type.output_file(&jam_out, &name);
232235
if !matches!(blob_type, BlobType::CoreVmGuest) {
233236
let parts = polkavm_linker::ProgramParts::from_bytes(linked.into())
234237
.expect("failed to deserialize linked PolkaVM program");

crates/cli/src/cmd/build.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//! `jam build` command
22
3-
use std::path::PathBuf;
4-
53
use crate::{
64
builder,
75
manifest::{ModuleType, Profile},
86
};
97
use clap::Parser;
8+
use std::path::PathBuf;
109

1110
/// CLI utility for building PVM code blobs, particularly services and authorizers.
1211
#[derive(Parser, Debug, Default)]

crates/cli/src/util.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,10 @@ pub fn build(package: &str, module: Option<ModuleType>, path: Option<String>) ->
1919

2020
// Build the service
2121
let target = etc::find_up("target")?;
22-
let jam = target.join("jam");
2322
let current = path
2423
.map(PathBuf::from)
2524
.unwrap_or_else(|| env::current_dir().expect("Unable to get current directory"));
26-
let binary = jam.join(package).join(format!("{package}.jam"));
25+
let binary = target.join("jam").join(format!("{package}.jam"));
2726
let rebuild = if !binary.exists() {
2827
true
2928
} else {
@@ -36,7 +35,7 @@ pub fn build(package: &str, module: Option<ModuleType>, path: Option<String>) ->
3635
if let Some(module) = module {
3736
build.module = module;
3837
}
39-
build.target = Some(jam.join(package));
38+
build.target = Some(target);
4039
build.run()?;
4140
}
4241

crates/jade/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ homepage.workspace = true
88
repository.workspace = true
99

1010
[dependencies]
11+
anyhow.workspace = true
1112
codec.workspace = true
1213
jade-derive.workspace = true
14+
serde.workspace = true
1315
service.workspace = true
1416
polkavm-derive.workspace = true
17+
testing = { workspace = true, optional = true }
1518

1619
[features]
1720
default = []
18-
std = ["codec/std", "service/std"]
21+
logging = []
22+
testing = ["dep:testing"]
23+
std = ["anyhow/std", "codec/std", "serde/std", "service/std"]
1924
tiny = []

crates/jade/derive/src/accumulate.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ pub fn accumulate(_args: TokenStream, input: TokenStream) -> TokenStream {
2222
let buf = unsafe { core::slice::from_raw_parts(ptr as *const u8, size as usize) };
2323
let jade::service::vm::AccumulateParams {slot, id, results} =
2424
jade::codec::decode(buf).expect("failed to decode accumulate parameters");
25-
if let Some(result) = #funame(slot, id, results) {
25+
let operands = jade::host::fetch::operands().expect("failed to fetch operands");
26+
if let Some(result) = #funame(slot, id, operands) {
2627
((&result).as_ptr() as u64, result.len() as u64)
2728
} else {
2829
(0, 0)

crates/jade/derive/src/authorize.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@ pub fn is_authorized(_args: TokenStream, input: TokenStream) -> TokenStream {
2020
#fun
2121

2222
let buf = unsafe { core::slice::from_raw_parts(ptr as *const u8, size as usize) };
23-
let (param, package, core_index): (AuthConfig, WorkPackage, CoreIndex) =
24-
jade::codec::decode(buf).expect("failed to decode is_authorized parameters");
25-
let result = #funame(param, package, core_index);
23+
let core_index: CoreIndex =
24+
jade::codec::decode(buf).inspect_err(|e| jade::error!("decoded is_authorized parameters: {:?}", e))
25+
.expect("failed to decode is_authorized parameters");
26+
let result = #funame(core_index);
2627
((&result).as_ptr() as u64, result.len() as u64)
2728
}
2829
}

crates/jade/src/host/general.rs

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! General host calls
2+
3+
use crate::host::import;
4+
use core::ptr;
5+
6+
/// Get the gas used
7+
pub fn gas() -> u64 {
8+
unsafe { import::gas() }
9+
}
10+
11+
/// Fetch operations
12+
pub mod fetch {
13+
use super::*;
14+
use crate::prelude::{Vec, vec};
15+
use anyhow::Result;
16+
use service::vm::Operand;
17+
18+
/// Fetch a value from the storage
19+
pub fn operands() -> Result<Vec<Operand>> {
20+
let len = unsafe { import::fetch(core::ptr::null_mut(), 0, 0, 14, 0, 0) };
21+
let mut target = vec![0; len as usize];
22+
let _ = unsafe { import::fetch(target.as_mut_ptr(), 0, len as u64, 14, 0, 0) };
23+
codec::decode(target.as_slice()).map_err(Into::into)
24+
}
25+
}
26+
27+
/// Storage operations
28+
pub mod storage {
29+
use super::*;
30+
use anyhow::Result;
31+
32+
/// Read a value from the storage
33+
pub fn read<R: serde::de::DeserializeOwned>(key: impl AsRef<[u8]>) -> Option<R> {
34+
let len = unsafe {
35+
import::read(
36+
u64::MAX as _,
37+
key.as_ref().as_ptr(),
38+
key.as_ref().len() as u64,
39+
ptr::null_mut(),
40+
0,
41+
0,
42+
)
43+
};
44+
45+
if len == u64::MAX {
46+
return None;
47+
} else if len == 0 {
48+
return None;
49+
}
50+
51+
let ptr = unsafe {
52+
import::read(
53+
u64::MAX as _,
54+
key.as_ref().as_ptr(),
55+
key.as_ref().len() as u64,
56+
ptr::null_mut(),
57+
0,
58+
len,
59+
)
60+
};
61+
62+
let value = unsafe { core::slice::from_raw_parts(ptr as _, len as usize) };
63+
codec::decode(value).ok()
64+
}
65+
66+
/// Write a value to the storage
67+
pub fn write<W: serde::Serialize>(key: impl AsRef<[u8]>, value: &W) -> Result<()> {
68+
let value = codec::encode(value)?;
69+
unsafe {
70+
import::write(
71+
key.as_ref().as_ptr(),
72+
key.as_ref().len() as u64,
73+
value.as_ptr(),
74+
value.len() as u64,
75+
);
76+
};
77+
78+
Ok(())
79+
}
80+
}

crates/jade/src/host/import.rs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//! Imports of host calls
2+
3+
#[polkavm_derive::polkavm_import]
4+
extern "C" {
5+
// NOTE: This is NOT part of the GP.
6+
#[polkavm_import(index = 100)]
7+
pub fn log(
8+
level: u64,
9+
target_ptr: *const u8,
10+
target_len: u64,
11+
text_ptr: *const u8,
12+
text_len: u64,
13+
);
14+
15+
/// Get the gas used
16+
#[polkavm_import(index = 0)]
17+
pub fn gas() -> u64;
18+
19+
/// Fetch a value from the storage
20+
#[polkavm_import(index = 1)]
21+
pub fn fetch(buffer: *mut u8, offset: u64, buffer_len: u64, kind: u64, a: u64, b: u64) -> u64;
22+
23+
/// Read a value from the storage
24+
#[polkavm_import(index = 3)]
25+
pub fn read(
26+
service: u64,
27+
key_ptr: *const u8,
28+
key_len: u64,
29+
out: *mut u8,
30+
offset: u64,
31+
out_len: u64,
32+
) -> u64;
33+
34+
/// Write a value to the storage
35+
#[polkavm_import(index = 4)]
36+
pub fn write(key_ptr: *const u8, key_len: u64, value: *const u8, value_len: u64) -> u64;
37+
38+
/// Get the info of the service
39+
#[polkavm_import(index = 5)]
40+
pub fn info(service: u64, service_info_ptr: *mut u8) -> u64;
41+
}

0 commit comments

Comments
 (0)