diff --git a/guest-programs/Cargo.lock b/guest-programs/Cargo.lock index a9c231c2..22285c09 100644 --- a/guest-programs/Cargo.lock +++ b/guest-programs/Cargo.lock @@ -59,6 +59,14 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "jam-service-fib" +version = "0.1.0" +dependencies = [ + "polkavm-derive", + "simplealloc", +] + [[package]] name = "mos6502" version = "0.1.0" diff --git a/guest-programs/Cargo.toml b/guest-programs/Cargo.toml index d3f90c43..a8eac1fc 100644 --- a/guest-programs/Cargo.toml +++ b/guest-programs/Cargo.toml @@ -14,6 +14,7 @@ resolver = "2" members = [ # Examples: "example-hello-world", + "jam-service-fib", # Benchmarks: "bench-minimal", diff --git a/guest-programs/jam-service-fib/Cargo.toml b/guest-programs/jam-service-fib/Cargo.toml index fc37acf1..3c2c1d5d 100644 --- a/guest-programs/jam-service-fib/Cargo.toml +++ b/guest-programs/jam-service-fib/Cargo.toml @@ -1,3 +1,5 @@ +cargo-features = ["edition2024"] + [package] name = "jam-service-fib" version = "0.1.0" @@ -7,12 +9,9 @@ publish = false [lib] name = "fib" path = "src/main.rs" -crate-type = ["cdylib"] - -[[bin]] -name = "jam-service-fib" -path = "src/main.rs" +crate-type = ["staticlib", "rlib"] [dependencies] polkavm-derive = { path = "../../crates/polkavm-derive" } simplealloc = { path = "../../crates/simplealloc" } + diff --git a/guest-programs/jam-service-fib/src/main.rs b/guest-programs/jam-service-fib/src/main.rs index f8422f00..7efc7b7c 100644 --- a/guest-programs/jam-service-fib/src/main.rs +++ b/guest-programs/jam-service-fib/src/main.rs @@ -1,6 +1,21 @@ #![no_std] #![no_main] +extern crate alloc; + +use alloc::vec::Vec; +use simplealloc::SimpleAlloc; + +#[global_allocator] +static ALLOCATOR: SimpleAlloc<4096> = SimpleAlloc::new(); + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + unsafe { + core::arch::asm!("unimp", options(noreturn)); + } +} + #[polkavm_derive::polkavm_import] extern "C" { #[polkavm_import(index = 0)] @@ -59,11 +74,13 @@ extern "C" { pub fn sha2_256(data: *const u8, data_len: u32, hash_ptr: *mut u8) -> u32; } -fn is_authorized() -> bool { - true +#[polkavm_derive::polkavm_export] +extern "C" fn is_authorized_ext() -> u32 { + 0 } -fn refine() -> [u8; 12] { +#[polkavm_derive::polkavm_export] +extern "C" fn refine_ext() -> u32 { let mut buffer = [0u8; 12]; let result = unsafe { import(0, buffer.as_mut_ptr(), buffer.len() as u32) }; @@ -73,13 +90,11 @@ fn refine() -> [u8; 12] { let fib_n_minus_1 = u32::from_le_bytes(buffer[8..12].try_into().unwrap()); let new_fib_n = fib_n + fib_n_minus_1; - - let new_buffer = [ - (n + 1).to_le_bytes(), - new_fib_n.to_le_bytes(), - fib_n.to_le_bytes(), - ] - .concat(); + let new_buffer: Vec = [(n + 1).to_le_bytes(), new_fib_n.to_le_bytes(), fib_n.to_le_bytes()] + .iter() + .flat_map(|array| array.iter()) + .copied() + .collect(); buffer.copy_from_slice(&new_buffer); } else { @@ -90,25 +105,22 @@ fn refine() -> [u8; 12] { export(buffer.as_mut_ptr(), buffer.len() as u32); } - buffer + 0 } -fn accumulate() -> [u8; 12] { - let mut buffer = [0u8; 12]; +#[polkavm_derive::polkavm_export] +extern "C" fn accumulate_ext() -> u32 { + let buffer = [0u8; 12]; let key = [0u8; 1]; unsafe { write(key.as_ptr(), 1, buffer.as_ptr(), buffer.len() as u32); } - buffer + 0 } -fn on_transfer() -> bool { - true +#[polkavm_derive::polkavm_export] +extern "C" fn on_transfer_ext() -> u32 { + 0 } - -// TODO: (1) Get toolchain instructions sufficient to get above Rust compiled into PVM with -// (a) ecalli 16/17/3 in place of import/export (refine) + write (accumulate) -// (b) entrypoints 0/5/10/15 going into is_authorized/refine/accumulate/on_transfer -// (2) get polkatool to output .pvm byte code with (1b) streamlined diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 7897a24d..dd500d2b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,2 +1,5 @@ [toolchain] -channel = "1.75.0" +channel = "rve-nightly" +components = ["rustc", "cargo", "rust-std"] +targets = ["riscv32imc-unknown-none-elf"] + diff --git a/tools/polkatool/jam_service.pvm b/tools/polkatool/jam_service.pvm new file mode 100644 index 00000000..50d8a89f Binary files /dev/null and b/tools/polkatool/jam_service.pvm differ diff --git a/tools/polkatool/src/main.rs b/tools/polkatool/src/main.rs index 4f7fb3c9..d494d685 100644 --- a/tools/polkatool/src/main.rs +++ b/tools/polkatool/src/main.rs @@ -62,6 +62,12 @@ enum Args { /// The input files. inputs: Vec, }, + + /// Builds JAM-ready polkavm file + JAMService { + /// The input file. + input: PathBuf, + }, } macro_rules! bail { @@ -90,6 +96,7 @@ fn main() { } => main_disassemble(input, format, display_gas, show_raw_bytes, output), Args::Assemble { input, output } => main_assemble(input, output), Args::Stats { inputs } => main_stats(inputs), + Args::JAMService { input } => main_jam_service(input), }; if let Err(error) = result { @@ -233,3 +240,30 @@ fn main_assemble(input_path: PathBuf, output_path: PathBuf) -> Result<(), String Ok(()) } + +fn main_jam_service(input_path: PathBuf) -> Result<(), String> { + if !input_path.exists() { + bail!("File does not exist: {input_path:?}"); + } + + use std::fs; + + let mut config = polkavm_linker::Config::default(); + config.set_strip(true); + config.set_dispatch_table(vec![ + b"is_authorized_ext".into(), + b"refine_ext".into(), + b"accumulate_ext".into(), + b"on_transfer_ext".into(), + ]); + + let elf = fs::read(input_path).map_err(|err| format!("Failed to read ELF file: {}", err))?; + let raw_blob = + polkavm_linker::program_from_elf(config, elf.as_ref()).map_err(|err| format!("Failed to create program from ELF: {}", err))?; + let parts = + polkavm_linker::ProgramParts::from_bytes(raw_blob.into()).map_err(|err| format!("Failed to parse program parts: {}", err))?; + + fs::write("jam_service.pvm", &parts.code_and_jump_table).map_err(|err| format!("Failed to write jam_service.pvm: {}", err))?; + + Ok(()) +}