Skip to content

Commit

Permalink
WIP Test risc0 guest
Browse files Browse the repository at this point in the history
  • Loading branch information
mpernambuco committed Aug 19, 2024
1 parent c161181 commit 95afe40
Show file tree
Hide file tree
Showing 37 changed files with 2,357 additions and 11 deletions.
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ help:
@echo '* all - Build the src/ code. To build from a clean clone, run: make submodules all'
@echo ' uarch - Build microarchitecture (requires riscv64-cartesi-linux-gnu-* toolchain)'
@echo ' uarch-with-linux-env - Build microarchitecture using the linux-env docker image'
@echo ' zkarch-with-linux-env - Build zk microarchitecture using the linux-env docker image'
@echo ' build-tests-all - Build all tests (machine, uarch and misc)'
@echo ' build-tests-machine - Build machine emulator tests (requires rv64gc-lp64d riscv64-cartesi-linux-gnu-* toolchain)'
@echo ' build-tests-machine-with-toolchain - Build machine emulator tests using the rv64gc-lp64d toolchain docker image'
Expand Down Expand Up @@ -246,6 +247,9 @@ source-default:
uarch: $(SRCDIR)/machine-c-version.h
@eval $$($(MAKE) -s --no-print-directory env); $(MAKE) -C uarch

zkarch: $(SRCDIR)/machine-c-version.h
@eval $$($(MAKE) -s --no-print-directory env); $(MAKE) -C zkarch

$(SRCDIR)/machine-c-version.h:
@eval $$($(MAKE) -s --no-print-directory env); $(MAKE) -C $(SRCDIR) machine-c-version.h

Expand Down Expand Up @@ -317,6 +321,9 @@ linux-env-exec: check-linux-env
uarch-with-linux-env:
@$(MAKE) linux-env-exec CONTAINER_COMMAND="make uarch"

zkarch-with-linux-env:
@$(MAKE) linux-env-exec CONTAINER_COMMAND="make zkarch"

# Create install directories
$(BIN_INSTALL_PATH) $(LIB_INSTALL_PATH) $(LUA_INSTALL_PATH) $(LUA_INSTALL_CPATH) $(LUA_INSTALL_CPATH)/cartesi $(LUA_INSTALL_PATH)/cartesi $(INC_INSTALL_PATH) $(IMAGES_INSTALL_PATH) $(UARCH_INSTALL_PATH) $(TESTS_DATA_INSTALL_PATH) $(TESTS_SCRIPTS_INSTALL_PATH) $(TESTS_LUA_INSTALL_PATH):
mkdir -m 0755 -p $@
Expand Down Expand Up @@ -396,6 +403,6 @@ $(ADD_GENERATED_FILES_DIFF): $(GENERATED_FILES)
git diff --no-prefix --staged --output=$(ADD_GENERATED_FILES_DIFF)
git reset -- $(GENERATED_FILES)

.PHONY: help all submodules doc clean distclean src luacartesi hash uarch \
.PHONY: help all submodules doc clean distclean src luacartesi hash uarch zkarch \
create-generated-files-patch $(SUBDIRS) $(SUBCLEAN)

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
11 changes: 11 additions & 0 deletions rust/verify_steps/host/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "host"
version = "0.1.0"
edition = "2021"

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

pub struct PageInfo {
pub address: u64,
pub data: [u8; 4986],
}

fn load_pages(dir_path: &str) -> Vec<PageInfo> {
let mut files = fs::read_dir(dir_path)
.expect("Could not read directory")
.filter_map(|entry| {
let entry = entry.ok()?;
let path = entry.path();
if path.is_file() {
Some(path)
} else {
None
}
})
.collect::<Vec<_>>();

files.sort_by_key(|path| {
u64::from_str_radix(path.file_name().unwrap().to_str().unwrap(), 16).unwrap()
});
let mut pages = Vec::new();
for file_path in files {
let filename = file_path.file_name().unwrap().to_str().unwrap();
let address = u64::from_str_radix(filename, 16).unwrap();
let mut file = File::open(&file_path).expect("Could not open file");
let mut data = [0 as u8; 4986];
// read file contents and push a new page info
file.read(&mut data).expect("Could not read file contents");
pages.push(PageInfo {
address,
data,
});
}
pages
}

// Page files generated by the following command:
// mkdir -p /tmp/loxa3
// cartesi-machine.lua --max-mcycle=0 --log-steps=1,/tmp/loxa3
fn main() {
let pages = load_pages("/tmp/loxa3");
// Initialize tracing. In order to view logs, run `RUST_LOG=info cargo run`
tracing_subscriber::fmt()
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
.init();

let mut builder = ExecutorEnv::builder();
// stupid way to send pages to the guest. Will improve later.
builder.write(&pages.len()).unwrap();
let mut temp: [u8; 32] = [0; 32];
for page in pages {
builder.write(&page.address).unwrap();
println!("writing page: {:x}", page.address);
for i in (0..4096).step_by(32) {
temp.copy_from_slice(&page.data[i..(i + 32)]);
builder.write(&temp).unwrap();
}
}

let env = builder.build().unwrap();

let prover = default_prover();
let receipt = prover
.prove(env, TESTE1_ELF)
.unwrap();

let output:u64 = receipt.journal.decode().unwrap();
println!("result: {:x}", output);
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();
}
13 changes: 13 additions & 0 deletions rust/verify_steps/methods/guest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[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 }

[build-dependencies]
cc = "1.0"
5 changes: 5 additions & 0 deletions rust/verify_steps/methods/guest/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
cc::Build::new()
.object("../../../../zkarch/zkarch-replay-steps.o")
.compile("loxa");
}
57 changes: 57 additions & 0 deletions rust/verify_steps/methods/guest/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#![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;
risc0_zkvm::guest::entry!(main);
use std::ptr;
use std::os::raw::{c_char, c_ulonglong};

#[repr(C)]
pub struct PageInfo {
pub address: c_ulonglong,
pub data: [c_char; 4096],
pub next: *mut PageInfo,
}

extern "C" {
pub fn zkarch_replay_steps(steps: c_ulonglong, pages: *mut PageInfo) -> c_ulonglong;
}

fn main() {
// linked list of pages
let mut _head : *mut PageInfo = ptr::null_mut();
let mut _current : *mut PageInfo = ptr::null_mut();
// read page count
let _page_count : u64 = env::read();
// stupid way of reading pages. Will improve later.
for _ in 0.._page_count {
let _asdress : u64 = env::read();
let mut _page = PageInfo {
address: _asdress,
data: [0; 4096],
next: ptr::null_mut(),
};
// even stupider way of reading page data. Will improve later.
for _i in (0..4096).step_by(32) {
env::read_slice(&mut _page.data[_i..(_i + 32)]);
}
if _head.is_null() {
_head = Box::into_raw(Box::new(_page));
_current = _head;
} else {
let _new_page = Box::into_raw(Box::new(_page));
unsafe {
(*_current).next = _new_page;
_current = _new_page;
}
}
}

let mctcle_end: u64;
unsafe {
mctcle_end = zkarch_replay_steps(1, _head);
}

env::commit(&_page_count);
}
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"
22 changes: 22 additions & 0 deletions src/cartesi-machine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ where options are:
store machine to <directory>, where "%%h" is substituted by the
state hash in the directory name.
--log-steps=<steps>,<directory>
log <steps> and save affected pages to <directory>.
--load=<directory>
load machine previously stored in <directory>.
Expand Down Expand Up @@ -603,6 +606,8 @@ local log_uarch_step = false
local auto_uarch_reset = false
local log_uarch_reset = false
local store_dir
local log_steps_steps
local log_steps_dir
local load_dir
local cmdline_opts_finished = false
local store_config = false
Expand Down Expand Up @@ -1295,6 +1300,15 @@ local options = {
return true
end,
},
{
"^%-%-log%-steps%=(.*),(.*)$",
function(s, d)
if (not s) or (not d) then return false end
log_steps_steps = assert(util.parse_number(s), "invalid steps " .. s)
log_steps_dir = d
return true
end,
},
{
"^%-%-remote%-address%=(.*)$",
function(o)
Expand Down Expand Up @@ -2298,6 +2312,14 @@ if max_uarch_cycle > 0 then
end
end
if gdb_stub then gdb_stub:close() end
if log_steps_steps then
stderr(string.format("Saving %d steps to %s\n", log_steps_steps, log_steps_dir))
local mcycle_end = machine:read_mcycle() + log_steps_steps
machine:log_steps(mcycle_end, log_steps_dir)
-- TODO: consider remote
cartesi.machine.replay_steps(mcycle_end, log_steps_dir)

end
if log_uarch_step then
assert(config.processor.iunrep == 0, "micro step proof is meaningless in unreproducible mode")
stderr("Gathering micro step log: please wait\n")
Expand Down
7 changes: 7 additions & 0 deletions src/clua-i-virtual-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,12 @@ static int machine_obj_index_store(lua_State *L) {
return 0;
}

static int machine_obj_index_log_steps(lua_State *L) {
auto &m = clua_check<clua_managed_cm_ptr<cm_machine>>(L, 1);
TRY_EXECUTE(cm_log_steps(m.get(), luaL_checkinteger(L, 2), luaL_checkstring(L, 3), err_msg));
return 0;
}

/// \brief This is the machine:verify_dirty_page_maps() method implementation.
/// \param L Lua state.
static int machine_obj_index_verify_dirty_page_maps(lua_State *L) {
Expand Down Expand Up @@ -718,6 +724,7 @@ static const auto machine_obj_index = cartesi::clua_make_luaL_Reg_array({
{"log_uarch_reset", machine_obj_index_log_uarch_reset},
{"send_cmio_response", machine_obj_index_send_cmio_response},
{"log_send_cmio_response", machine_obj_index_log_send_cmio_response},
{"log_steps", machine_obj_index_log_steps},
});

/// \brief This is the machine __close metamethod implementation.
Expand Down
7 changes: 7 additions & 0 deletions src/clua-machine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ static int machine_class_index_verify_send_cmio_response_state_transition(lua_St
return 1;
}

static int machine_class_index_replay_steps(lua_State *L) {
lua_settop(L, 2);
TRY_EXECUTE(cm_replay_steps(luaL_checkinteger(L, 1), luaL_checkstring(L, 2), err_msg));
return 1;
}

/// \brief Contents of the machine class metatable __index table.
static const auto machine_class_index = cartesi::clua_make_luaL_Reg_array({
{"get_default_config", machine_class_index_get_default_config},
Expand All @@ -183,6 +189,7 @@ static const auto machine_class_index = cartesi::clua_make_luaL_Reg_array({
{"get_csr_address", machine_class_index_get_csr_address},
{"verify_send_cmio_response_log", machine_class_index_verify_send_cmio_response_log},
{"verify_send_cmio_response_state_transition", machine_class_index_verify_send_cmio_response_state_transition},
{"replay_steps", machine_class_index_replay_steps},
});

/// \brief This is the cartesi.machine() constructor implementation.
Expand Down
10 changes: 10 additions & 0 deletions src/i-state-access.h
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,16 @@ class i_state_access { // CRTP
return derived().template do_read_memory_word<T>(paddr, hpage, hoffset, pval);
}

template <typename T, typename U>
T aliased_unaligned_read(const void *host_ptr, uint64_t paddr) {
return derived().template do_aliased_unaligned_read<T, U>(host_ptr, paddr);
}

template <typename T>
inline T aliased_aligned_read(const void *host_ptr, uint64_t paddr) {
return derived().template do_aliased_aligned_read<T>(host_ptr, paddr);
}

/// \brief Writes a word to memory.
/// \tparam T Type of word to write.
/// \param paddr Target physical address.
Expand Down
5 changes: 5 additions & 0 deletions src/i-virtual-machine.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ class i_virtual_machine {
do_store(dir);
}

void log_steps(uint64_t mcycle_end, const std::string &directory) {
do_log_steps(mcycle_end, directory);
}

/// \brief Runs the machine for one micro cycle logging all accesses to the state.
access_log log_uarch_step(const access_log::type &log_type, bool one_based = false) {
return do_log_uarch_step(log_type, one_based);
Expand Down Expand Up @@ -809,6 +813,7 @@ class i_virtual_machine {
virtual void do_destroy() = 0;
virtual void do_commit() = 0;
virtual void do_rollback() = 0;
virtual void do_log_steps(uint64_t steps, const std::string &directory) = 0;
virtual uint64_t do_read_uarch_x(int i) const = 0;
virtual void do_write_uarch_x(int i, uint64_t val) = 0;
virtual uint64_t do_read_uarch_pc(void) const = 0;
Expand Down
Loading

0 comments on commit 95afe40

Please sign in to comment.