Skip to content
Closed
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
4 changes: 2 additions & 2 deletions executor/programs/rust/commit/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use lambda_vm_syscalls as syscalls;

pub fn main() {
let input: Vec<u8> = syscalls::syscalls::get_private_input();
let input = syscalls::syscalls::get_private_input();
syscalls::syscalls::print_string(format!("Private input received: {:?}\n", input).as_str());
syscalls::syscalls::commit(&input);
syscalls::syscalls::commit(input);
}
2 changes: 1 addition & 1 deletion executor/programs/rust/commit_sum/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use lambda_vm_syscalls as syscalls;

pub fn main() {
let input: Vec<u8> = syscalls::syscalls::get_private_input();
let input = syscalls::syscalls::get_private_input();
let a = input[0];
let b = input[1];
syscalls::syscalls::commit((a + b).to_le_bytes().as_ref());
Expand Down
2 changes: 1 addition & 1 deletion executor/programs/rust/ethrex/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rkyv::rancor::Error;

pub fn main() {
let input = lambda_vm_syscalls::syscalls::get_private_input();
let input = rkyv::from_bytes::<ProgramInput, Error>(&input).unwrap();
let input = rkyv::from_bytes::<ProgramInput, Error>(input).unwrap();
// LambdaVM crypto provider, defined in the lambda_vm repo and injected here
// (so crypto changes don't require an ethrex PR — see `crypto/ethrex-crypto`).
// It accelerates trait-routed `keccak256` (via the keccak_permute precompile)
Expand Down
2 changes: 1 addition & 1 deletion syscalls/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Published as `lambda-vm-syscalls`. Intended to be used from RISC-V (RV64IM) gues
| Function | Purpose |
|---|---|
| `commit(bytes: &[u8])` | Append bytes to the **public output** that the verifier checks. |
| `get_private_input() -> Vec<u8>` | Read the host-supplied private input bytes (memory-mapped at `0xFF000000`). |
| `get_private_input() -> &'static [u8]` | Read the host-supplied private input bytes zero-copy (memory-mapped at `0xFF000000`). |
| `sys_halt() -> !` | Terminate execution cleanly. Called automatically after `main` by the default entry point. |
| `keccak_permute(state: &mut [u64; 25])` | Keccak-f[1600] permutation precompile. |
| `ecsm_mul(xr: &mut [u8; 32], xg: &[u8; 32], k: &[u8; 32])` | secp256k1 scalar multiplication: writes `xR = (k·G)_x` (32-byte little-endian; `0 < k < N`). |
Expand Down
17 changes: 11 additions & 6 deletions syscalls/src/syscalls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,22 +78,27 @@ pub fn commit(slice: &[u8]) {
/// `PRIVATE_INPUT_START = 0xFF000000`.
///
/// The host pre-loads the input before execution; this function reads the
/// 4-byte LE length prefix and then copies the data bytes into a new `Vec`.
/// 4-byte LE length prefix and returns a zero-copy slice over the data bytes.
/// No ecall is performed — it's a plain memory read (ZisK-style).
///
/// The returned slice borrows from the fixed private-input mapping: the host
/// writes it before execution starts and never mutates it afterward, so the
/// borrow is valid for the whole run.
#[cfg(target_arch = "riscv64")]
pub fn get_private_input() -> Vec<u8> {
pub fn get_private_input() -> &'static [u8] {
// SAFETY: The host pre-loads private input at PRIVATE_INPUT_START before
// execution. The 4-byte LE length prefix is always valid (written by the
// executor). The data pointer and length are within the memory-mapped region.
// executor). The data pointer and length are within the memory-mapped region,
// which lives for the entire program execution and is never mutated after
// loading, so the 'static borrow is sound.
let len_ptr = PRIVATE_INPUT_START as *const u32;
let len = unsafe { core::ptr::read_volatile(len_ptr) } as usize;
let data_ptr = (PRIVATE_INPUT_START + 4) as *const u8;
let slice = unsafe { core::slice::from_raw_parts(data_ptr, len) };
slice.to_vec()
unsafe { core::slice::from_raw_parts(data_ptr, len) }
}

#[cfg(not(target_arch = "riscv64"))]
pub fn get_private_input() -> Vec<u8> {
pub fn get_private_input() -> &'static [u8] {
unimplemented!("syscalls are only implemented for riscv64 targets");
}

Expand Down