Skip to content

Commit

Permalink
feat!: add zkarch (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpernambuco committed Oct 7, 2024
1 parent f5d6969 commit ac88d0d
Show file tree
Hide file tree
Showing 20 changed files with 511 additions and 3 deletions.
6 changes: 6 additions & 0 deletions rust/verify_steps/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.DS_Store
Cargo.lock
methods/guest/Cargo.lock
target/
.vscode

11 changes: 11 additions & 0 deletions rust/verify_steps/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[workspace]
resolver = "2"
members = ["host", "methods"]

# Always optimize; building and running the guest takes much longer without optimization.
[profile.dev]
opt-level = 3

[profile.release]
debug = 1
lto = true
12 changes: 12 additions & 0 deletions rust/verify_steps/host/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "host"
version = "0.1.0"
edition = "2021"

[dependencies]
memmap2 = "0.3"
methods = { path = "../methods" }
risc0-zkvm = { version = "0.21.0" }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
hex = "0.4"
sha2 = "0.10"
74 changes: 74 additions & 0 deletions rust/verify_steps/host/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use std::env;
use memmap2::MmapOptions;
use std::fs::{File};
use methods::{
TESTE1_ELF, TESTE1_ID
};
use risc0_zkvm::{
default_prover,
ExecutorEnv };


/*
How to run this:
1) create a step log
cartesi-machine.lua --max-mcycle=0 --log-step=1,/tmp/step.bin
Logging step of 1 cycles to /tmp/step.bin
0: 5b4d6e46f7c024a1c108dcd2d7c174ec8ed2259a7ca53e362c611c2476791cb0
1: f66a12a3601c991025f7658226220f8346365f98958f5859a3add8954c1b1dd4
2) pass hashes, log file and mcycle_count to the host
cargo run 5b4d6e46f7c024a1c108dcd2d7c174ec8ed2259a7ca53e362c611c2476791cb0 /tmp/step.bin 1 f66a12a3601c991025f7658226220f8346365f98958f5859a3add8954c1b1dd4
*/
fn main() {
fn parse_hash(hex: &str) -> [u8; 32] {
let bytes = hex::decode(hex).expect("Invalid hex string");
let mut array = [0; 32];
array.copy_from_slice(&bytes);
array
}

let args: Vec<String> = env::args().collect();
if args.len() != 5 {
eprintln!("Usage: {} <root_hash_before> <log_file_path> <mcycle_count> <root_hash_after>", args[0]);
std::process::exit(1);
}
let root_hash_before = parse_hash(&args[1]);
let log_file_path = &args[2];
let mcycle_count: u64 = args[3].parse().expect("Invalid step count");
let root_hash_after = parse_hash(&args[4]);
assert_eq!(root_hash_before.len(), 32);
assert_eq!(root_hash_after.len(), 32);

// mmap the step log file
let log_file = File::open(log_file_path).expect("Could not open log file");
let log_file_len = log_file.metadata().expect("Could not get metadata").len();
let log_file = unsafe {
MmapOptions::new()
.len(log_file_len as usize)
.map(&log_file)
.expect("Could not memory map log file")
};

// build, run and verify the prover
let mut builder = ExecutorEnv::builder();
builder.write(&mcycle_count).unwrap();
builder.write(&root_hash_before).unwrap();
builder.write(&root_hash_after).unwrap();
builder.write(&log_file_len).unwrap();
for i in (0..log_file_len).step_by(1) {
builder.write(&log_file[i as usize]).unwrap();
}
let env = builder.build().unwrap();
let prover = default_prover();
let receipt = prover
.prove(env, TESTE1_ELF)
.unwrap();

//todo result to be hashes and mcycle_count
let result: bool = receipt.journal.decode().unwrap();
println!("host: result from guest: {:?}", result);
receipt
.verify(TESTE1_ID)
.unwrap();
}
10 changes: 10 additions & 0 deletions rust/verify_steps/methods/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "methods"
version = "0.1.0"
edition = "2021"

[build-dependencies]
risc0-build = { version = "0.21.0" }

[package.metadata.risc0]
methods = ["guest"]
3 changes: 3 additions & 0 deletions rust/verify_steps/methods/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
risc0_build::embed_methods();
}
14 changes: 14 additions & 0 deletions rust/verify_steps/methods/guest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "teste1"
version = "0.1.0"
edition = "2021"

[workspace]

[dependencies]
# If you want to try (experimental) std support, add `features = [ "std" ]` to risc0-zkvm
risc0-zkvm = { version = "0.21.0", default-features = true }
tiny-keccak = { version = "2.0", features = ["keccak"] }

[build-dependencies]
cc = "1.0"
14 changes: 14 additions & 0 deletions rust/verify_steps/methods/guest/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// fn main() {
// cc::Build::new()
// .object("../../../../zkarch/zkarch-replay-steps.o")
// .compile("loxa");
// }

fn main() {
const OBJ_PATH: &str = "../../../../zkarch/zkarch-replay-steps.o";

println!("cargo:rerun-if-changed={}", OBJ_PATH);
cc::Build::new()
.object(OBJ_PATH)
.compile("cartesi_zkarch_replay_steps");
}
89 changes: 89 additions & 0 deletions rust/verify_steps/methods/guest/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#![no_main]
// If you want to try std support, also update the guest Cargo.toml file
//#![no_std] // std support is experimental

use risc0_zkvm::guest::env;
use std::ffi::{CStr};
risc0_zkvm::guest::entry!(main);
use std::os::raw::{c_char, c_ulong, c_ulonglong};
use tiny_keccak::{Hasher, Keccak};

#[no_mangle]
pub extern "C" fn interop_print(text: *const c_char) {
let str = unsafe { CStr::from_ptr(text).to_string_lossy().into_owned() };
println!("print_from_c: {}", str);
}

#[no_mangle]
pub extern "C" fn interop_merkle_tree_hash(data: *const c_char, size: c_ulong, hash: *mut c_char) {
let mut hasher = Keccak::v256();
if size > 32 {
unsafe {
let half_size = size / 2;
let left_hash = [0u8; 32];
interop_merkle_tree_hash(data, half_size, left_hash.as_ptr() as *mut c_char);
let right_hash = [0u8; 32];
interop_merkle_tree_hash(data.add(half_size as usize) as *const c_char, half_size, right_hash.as_ptr() as *mut c_char);
hasher.update(left_hash.as_ref());
hasher.update(right_hash.as_ref());
let mut result_bytes = [0u8; 32];
hasher.finalize(&mut result_bytes);
std::ptr::copy(result_bytes.as_ptr(), hash as *mut u8, 32);
}
} else{
let mut hasher = Keccak::v256();
hasher.update(unsafe { std::slice::from_raw_parts(data as *const u8, size as usize) });
let mut result_bytes = [0u8; 32];
hasher.finalize(&mut result_bytes);
unsafe {
std::ptr::copy(result_bytes.as_ptr(), hash as *mut u8, 32);
}
}
}

#[no_mangle]
pub extern "C" fn interop_concat_hash(left: *const c_char, right: *const c_char, result: *mut c_char) {
let mut hasher = Keccak::v256();
hasher.update(unsafe { std::slice::from_raw_parts(left as *const u8, 32) });
hasher.update(unsafe { std::slice::from_raw_parts(right as *const u8, 32) });
let mut result_bytes = [0u8; 32];
hasher.finalize(&mut result_bytes);
unsafe {
std::ptr::copy(result_bytes.as_ptr(), result as *mut u8, 32);
}
}

#[no_mangle]
pub extern "C" fn interop_abort_with_msg(msg: *const c_char) {
let str = unsafe { CStr::from_ptr(msg).to_string_lossy().into_owned() };
panic!("abort_with_msg: {}", str);
}

extern "C" {
pub fn zkarch_replay_steps(root_hash_before: *const c_char, raw_log_data: *const c_char, raw_log_size: c_ulonglong, mcycle_count: c_ulonglong, root_hash_after: *const c_char) -> c_ulonglong;
}


fn main() {
let mcycle_count: u64 = env::read();
let root_hash_before : [u8; 32] = env::read();
let root_hash_after : [u8; 32] = env::read();
let raw_log_length : u64 = env::read();
println!("guest: mcycle_count: {:?}", mcycle_count);
println!("guest: root_hash_before: {:?}", root_hash_before);
println!("guest: root_hash_after: {:?}", root_hash_after);
println!("guest: raw_log_length: {:?}", raw_log_length);
let mut raw_log: Vec<u8> = vec![0; raw_log_length as usize];
for i in (0..raw_log_length).step_by(1) {
raw_log[i as usize] = env::read();
}
println!("guest: before zkarch_replay_steps");
unsafe {
zkarch_replay_steps(root_hash_before.as_ptr() as *const c_char, raw_log.as_ptr() as *const c_char, raw_log_length, mcycle_count, root_hash_after.as_ptr() as *const c_char);
}
println!("guest: after zkarch_replay_steps");
let result : bool = true; // TODO: result -> root_hash_before, mcycle_count and root_hash_after
println!("guest: commiting");
env::commit(&result);
println!("guest: committed");
}
1 change: 1 addition & 0 deletions rust/verify_steps/methods/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
include!(concat!(env!("OUT_DIR"), "/methods.rs"));
4 changes: 4 additions & 0 deletions rust/verify_steps/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[toolchain]
channel = "stable"
components = ["rustfmt", "rust-src"]
profile = "minimal"
8 changes: 6 additions & 2 deletions src/interpret.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
#include <cstdint>
#include <utility>

#ifdef MICROARCHITECTURE
#if defined(MICROARCHITECTURE)
#include "uarch-machine-state-access.h"
#include "uarch-runtime.h"
#elif defined(ZKARCHITECTURE)
#include "replay-step-state-access.h"
#else
#include "record-step-state-access.h"
#include "replay-step-state-access.h"
Expand Down Expand Up @@ -5674,8 +5676,10 @@ interpreter_break_reason interpret(STATE_ACCESS &a, uint64_t mcycle_end) {
}
}

#ifdef MICROARCHITECTURE
#if defined(MICROARCHITECTURE)
template interpreter_break_reason interpret(uarch_machine_state_access &a, uint64_t mcycle_end);
#elif defined(ZKARCHITECTURE)
template interpreter_break_reason interpret(replay_step_state_access &a, uint64_t mcycle_end);
#else
// Explicit instantiation for state_access
template interpreter_break_reason interpret(state_access &a, uint64_t mcycle_end);
Expand Down
5 changes: 4 additions & 1 deletion src/interpret.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,13 @@ enum class interpreter_break_reason {
template <typename STATE_ACCESS>
interpreter_break_reason interpret(STATE_ACCESS &a, uint64_t mcycle_end);

#ifdef MICROARCHITECTURE
#if defined(MICROARCHITECTURE)
class uarch_machine_state_access;
// Declaration of explicit instantiation in module interpret.cpp when compiled with microarchitecture
extern template interpreter_break_reason interpret(uarch_machine_state_access &a, uint64_t mcycle_end);
#elif defined(ZKARCHITECTURE)
class replay_step_state_access;
extern template interpreter_break_reason interpret(replay_step_state_access &a, uint64_t mcycle_end);
#else
// Forward declarations
class state_access;
Expand Down
4 changes: 4 additions & 0 deletions src/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,8 @@ uint64_t os_get_concurrency() {
#endif
}

#ifndef ZKARCHITECTURE

bool os_parallel_for(uint64_t n, const std::function<bool(uint64_t j, const parallel_for_mutex &mutex)> &task) {
#ifdef HAVE_THREADS
if (n > 1) {
Expand Down Expand Up @@ -717,6 +719,8 @@ bool os_parallel_for(uint64_t n, const std::function<bool(uint64_t j, const para
return succeeded;
}

#endif // ifndef ZKARCHITECTURE

bool os_select_fds(const os_select_before_callback &before_cb, const os_select_after_callback &after_cb,
uint64_t *timeout_us) {
// Create empty fd sets
Expand Down
3 changes: 3 additions & 0 deletions src/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ int64_t os_now_us();
/// \brief Get the number of concurrent threads supported by the OS
uint64_t os_get_concurrency();

#ifndef ZKARCHITECTURE
/// \brief Mutex for os_parallel_for()
struct parallel_for_mutex {
std::function<void()> lock;
Expand Down Expand Up @@ -141,6 +142,8 @@ using os_select_after_callback = std::function<bool(int select_ret, select_fd_se
bool os_select_fds(const os_select_before_callback &before_cb, const os_select_after_callback &after_cb,
uint64_t *timeout_us);

#endif // ifndef ZKARCHITECTURE

/// \brief Disable sigpipe
void os_disable_sigpipe();

Expand Down
10 changes: 10 additions & 0 deletions zkarch/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
*.o
*.tmp
*.ld
*.elf
*.bin
.DS_Store
.vscode
uarch-pristine-hash.c
uarch-pristine-ram.c
compute-uarch-pristine-hash
Loading

0 comments on commit ac88d0d

Please sign in to comment.