-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c42dcd9
commit cfbd4ce
Showing
9 changed files
with
247 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[build-system] | ||
requires = ["maturin>=1,<2"] | ||
build-backend = "maturin" | ||
|
||
[project] | ||
name = "l2_r0prover" | ||
requires-python = ">=3.7" | ||
classifiers = [ | ||
"Programming Language :: Rust", | ||
"Programming Language :: Python :: Implementation :: CPython", | ||
"Programming Language :: Python :: Implementation :: PyPy", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use anyhow::Result; | ||
use pyo3::prelude::*; | ||
use risc0_binfmt::{MemoryImage, Program}; | ||
use risc0_zkvm_platform::memory::GUEST_MAX_MEM; | ||
use risc0_zkvm_platform::PAGE_SIZE; | ||
|
||
#[pyclass] | ||
pub struct Image { | ||
memory_image: MemoryImage, | ||
} | ||
|
||
impl Image { | ||
pub fn from_elf(elf: &[u8]) -> Result<Self> { | ||
let program = Program::load_elf(elf, GUEST_MAX_MEM as u32)?; | ||
let image = MemoryImage::new(&program, PAGE_SIZE as u32)?; | ||
Ok(Self { | ||
memory_image: image, | ||
}) | ||
} | ||
|
||
pub fn get_image(&self) -> MemoryImage { | ||
self.memory_image.clone() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
mod image; | ||
mod segment; | ||
mod session; | ||
|
||
use crate::image::Image; | ||
use crate::segment::{Segment, SegmentReceipt}; | ||
use crate::session::SessionInfo; | ||
use pyo3::prelude::*; | ||
use pyo3::types::PyBytes; | ||
use risc0_zkvm::{ExecutorEnv, ExecutorImpl, FileSegmentRef, SimpleSegmentRef, VerifierContext}; | ||
|
||
#[pyfunction] | ||
fn load_image_from_elf(elf: &PyBytes) -> PyResult<Image> { | ||
Ok(Image::from_elf(elf.as_bytes())?) | ||
} | ||
|
||
#[pyfunction] | ||
fn execute_with_input(image: &Image, input: &PyBytes) -> PyResult<(Vec<Segment>, SessionInfo)> { | ||
let env = ExecutorEnv::builder() | ||
.write_slice(input.as_bytes()) | ||
.build()?; | ||
|
||
let mut exec = ExecutorImpl::new(env, image.get_image())?; | ||
|
||
let time = std::time::Instant::now(); | ||
let session = exec.run()?; | ||
|
||
let mut segments = vec![]; | ||
for segment_ref in session.segments.iter() { | ||
segments.push(Segment::new(segment_ref.resolve()?)); | ||
} | ||
|
||
let session_info = SessionInfo::new(&session)?; | ||
Ok((segments, session_info)) | ||
} | ||
|
||
#[pyfunction] | ||
fn prove_segment(segment: &Segment) -> PyResult<SegmentReceipt> { | ||
let verifier_context = VerifierContext::default(); | ||
let res = segment.prove(&verifier_context)?; | ||
Ok(res) | ||
} | ||
|
||
#[pymodule] | ||
fn l2_r0prover(_py: Python<'_>, m: &PyModule) -> PyResult<()> { | ||
m.add_function(wrap_pyfunction!(load_image_from_elf, m)?)?; | ||
m.add_function(wrap_pyfunction!(execute_with_input, m)?)?; | ||
m.add_function(wrap_pyfunction!(prove_segment, m)?)?; | ||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
use anyhow::Result; | ||
use pyo3::prelude::*; | ||
use risc0_zkvm::VerifierContext; | ||
|
||
#[pyclass] | ||
pub struct Segment { | ||
segment: risc0_zkvm::Segment, | ||
} | ||
|
||
impl Segment { | ||
pub fn new(segment: risc0_zkvm::Segment) -> Self { | ||
Self { segment } | ||
} | ||
|
||
pub fn prove(&self, verifier_context: &VerifierContext) -> Result<SegmentReceipt> { | ||
Ok(SegmentReceipt::new(self.segment.prove(verifier_context)?)) | ||
} | ||
} | ||
|
||
#[pyclass] | ||
pub struct SegmentReceipt { | ||
segment_receipt: risc0_zkvm::SegmentReceipt, | ||
} | ||
|
||
impl SegmentReceipt { | ||
pub fn new(segment_receipt: risc0_zkvm::SegmentReceipt) -> Self { | ||
Self { segment_receipt } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
use anyhow::Result; | ||
use pyo3::exceptions::PyValueError; | ||
use pyo3::prelude::*; | ||
|
||
#[pyclass] | ||
#[derive(Clone)] | ||
pub struct ExitCode { | ||
exit_code: risc0_zkvm::ExitCode, | ||
} | ||
|
||
impl ExitCode { | ||
pub fn new(exit_code: risc0_zkvm::ExitCode) -> Self { | ||
Self { exit_code } | ||
} | ||
} | ||
|
||
#[pymethods] | ||
impl ExitCode { | ||
pub fn is_system_split(&self) -> PyResult<bool> { | ||
Ok(matches!(self.exit_code, risc0_zkvm::ExitCode::SystemSplit)) | ||
} | ||
|
||
pub fn is_session_limit(&self) -> PyResult<bool> { | ||
Ok(matches!(self.exit_code, risc0_zkvm::ExitCode::SessionLimit)) | ||
} | ||
|
||
pub fn is_paused(&self) -> PyResult<bool> { | ||
Ok(matches!(self.exit_code, risc0_zkvm::ExitCode::Paused(_))) | ||
} | ||
|
||
pub fn get_paused_code(&self) -> PyResult<u32> { | ||
match self.exit_code { | ||
risc0_zkvm::ExitCode::Paused(v) => Ok(v), | ||
_ => Err(PyValueError::new_err("The exit code is not for pausing.")), | ||
} | ||
} | ||
|
||
pub fn is_halted(&self) -> PyResult<bool> { | ||
Ok(matches!(self.exit_code, risc0_zkvm::ExitCode::Halted(_))) | ||
} | ||
|
||
pub fn get_halted_code(&self) -> PyResult<u32> { | ||
match self.exit_code { | ||
risc0_zkvm::ExitCode::Halted(v) => Ok(v), | ||
_ => Err(PyValueError::new_err("The exit code is not for halting.")), | ||
} | ||
} | ||
|
||
pub fn is_fault(&self) -> PyResult<bool> { | ||
Ok(matches!(self.exit_code, risc0_zkvm::ExitCode::Fault)) | ||
} | ||
} | ||
|
||
#[pyclass] | ||
pub struct SessionInfo { | ||
journal: Vec<u8>, | ||
exit_code: ExitCode, | ||
} | ||
|
||
impl SessionInfo { | ||
pub fn new(session: &risc0_zkvm::Session) -> Result<Self> { | ||
let journal = match &session.journal { | ||
Some(v) => v.bytes.clone(), | ||
None => vec![], | ||
}; | ||
Ok(Self { | ||
journal, | ||
exit_code: ExitCode::new(session.exit_code), | ||
}) | ||
} | ||
} | ||
|
||
#[pymethods] | ||
impl SessionInfo { | ||
pub fn get_journal(&self) -> PyResult<Vec<u8>> { | ||
Ok(self.journal.clone()) | ||
} | ||
|
||
pub fn get_exit_code(&self) -> PyResult<ExitCode> { | ||
Ok(self.exit_code.clone()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import l2_r0prover | ||
import time | ||
|
||
print("loading the ELF...") | ||
elf_handle = open("elf", mode="rb") | ||
elf = elf_handle.read() | ||
image = l2_r0prover.load_image_from_elf(elf) | ||
|
||
print("assembling the input...") | ||
input = bytes([33, 0, 0, 0, 2, 0, 0, 0, 193, 0, 0, 0, 8, 0, 0, 0, 182, 0, 0, 0, 138, 0, 0, 0, 205, 0, 0, 0, 80, 0, 0, 0, 133, 0, 0, 0, 90, 0, 0, 0, 55, 0, 0, 0, 33, 0, 0, 0, 217, 0, 0, 0, 22, 0, 0, 0, 160, 0, 0, 0, 77, 0, 0, 0, 95, 0, 0, 0, 229, 0, 0, 0, 121, 0, 0, 0, 46, 0, 0, 0, 59, 0, 0, 0, 43, 0, 0, 0, 194, 0, 0, 0, 32, 0, 0, 0, 157, 0, 0, 0, 140, 0, 0, 0, 30, 0, 0, 0, 142, 0, 0, 0, 163, 0, 0, 0, 157, 0, 0, 0, 167, 0, 0, 0, 109, 0, 0, 0, 174, 0, 0, 0, 87, 0, 0, 0, 67, 0, 0, 0, 84, 0, 0, 0, 104, 0, 0, 0, 105, 0, 0, 0, 115, 0, 0, 0, 32, 0, 0, 0, 105, 0, 0, 0, 115, 0, 0, 0, 32, 0, 0, 0, 97, 0, 0, 0, 32, 0, 0, 0, 109, 0, 0, 0, 101, 0, 0, 0, 115, 0, 0, 0, 115, 0, 0, 0, 97, 0, 0, 0, 103, 0, 0, 0, 101, 0, 0, 0, 32, 0, 0, 0, 116, 0, 0, 0, 104, 0, 0, 0, 97, 0, 0, 0, 116, 0, 0, 0, 32, 0, 0, 0, 119, 0, 0, 0, 105, 0, 0, 0, 108, 0, 0, 0, 108, 0, 0, 0, 32, 0, 0, 0, 98, 0, 0, 0, 101, 0, 0, 0, 32, 0, 0, 0, 115, 0, 0, 0, 105, 0, 0, 0, 103, 0, 0, 0, 110, 0, 0, 0, 101, 0, 0, 0, 100, 0, 0, 0, 44, 0, 0, 0, 32, 0, 0, 0, 97, 0, 0, 0, 110, 0, 0, 0, 100, 0, 0, 0, 32, 0, 0, 0, 118, 0, 0, 0, 101, 0, 0, 0, 114, 0, 0, 0, 105, 0, 0, 0, 102, 0, 0, 0, 105, 0, 0, 0, 101, 0, 0, 0, 100, 0, 0, 0, 32, 0, 0, 0, 119, 0, 0, 0, 105, 0, 0, 0, 116, 0, 0, 0, 104, 0, 0, 0, 105, 0, 0, 0, 110, 0, 0, 0, 32, 0, 0, 0, 116, 0, 0, 0, 104, 0, 0, 0, 101, 0, 0, 0, 32, 0, 0, 0, 122, 0, 0, 0, 107, 0, 0, 0, 86, 0, 0, 0, 77, 0, 0, 0, 90, 0, 0, 0, 82, 0, 0, 0, 115, 0, 0, 0, 129, 0, 0, 0, 167, 0, 0, 0, 101, 0, 0, 0, 18, 0, 0, 0, 87, 0, 0, 0, 91, 0, 0, 0, 83, 0, 0, 0, 98, 0, 0, 0, 111, 0, 0, 0, 74, 0, 0, 0, 65, 0, 0, 0, 151, 0, 0, 0, 141, 0, 0, 0, 101, 0, 0, 0, 20, 0, 0, 0, 220, 0, 0, 0, 16, 0, 0, 0, 184, 0, 0, 0, 172, 0, 0, 0, 230, 0, 0, 0, 167, 0, 0, 0, 248, 0, 0, 0, 219, 0, 0, 0, 253, 0, 0, 0, 19, 0, 0, 0, 48, 0, 0, 0, 121, 0, 0, 0, 128, 0, 0, 0, 78, 0, 0, 0, 36, 0, 0, 0, 110, 0, 0, 0, 166, 0, 0, 0, 254, 0, 0, 0, 143, 0, 0, 0, 239, 0, 0, 0, 29, 0, 0, 0, 183, 0, 0, 0, 17, 0, 0, 0, 31, 0, 0, 0, 243, 0, 0, 0, 193, 0, 0, 0, 183, 0, 0, 0, 235, 0, 0, 0, 139, 0, 0, 0, 85, 0, 0, 0, 203, 0, 0, 0, 182, 0, 0, 0, 252, 0, 0, 0, 248, 0, 0, 0, 239, 0, 0, 0, 9, 0, 0, 0, 175, 0, 0, 0, 243, 0, 0, 0, 126, 0, 0, 0, 65, 0, 0, 0, 102, 0, 0, 0, 9, 0, 0, 0, 209, 0, 0, 0, 162, 0, 0, 0, 86, 0, 0, 0, 52, 0, 0, 0]) | ||
|
||
print("running the VM...") | ||
tic = time.perf_counter() | ||
segments, info = l2_r0prover.execute_with_input(image, input) | ||
toc = time.perf_counter() | ||
print(f"VM execution takes {toc - tic: 0.4f} seconds") | ||
print(info.get_journal()) | ||
|
||
print("generate the receipt for the 1st segment...") | ||
tic = time.perf_counter() | ||
receipt_1 = l2_r0prover.prove_segment(segments[0]) | ||
toc = time.perf_counter() | ||
print(f"Receipt for the 1st segment takes {toc - tic: 0.4f} seconds") | ||
|
||
print("generate the receipt for the 2nd segment...") | ||
tic = time.perf_counter() | ||
receipt_2 = l2_r0prover.prove_segment(segments[1]) | ||
toc = time.perf_counter() | ||
print(f"Receipt for the 2nd segment takes {toc - tic: 0.4f} seconds") |