fix zone PoC

This commit is contained in:
Giacomo Pasini 2024-06-26 11:33:52 +02:00
parent 507e1627d7
commit 3c991173c5
No known key found for this signature in database
GPG Key ID: FC08489D2D895D4B
7 changed files with 91 additions and 76 deletions

View File

@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["host", "methods"]
members = [ "common","host", "methods"]
# Always optimize; building and running the guest takes much longer without optimization.
[profile.dev]

7
goas/common/Cargo.toml Normal file
View File

@ -0,0 +1,7 @@
[package]
name = "common"
version = "0.1.0"
edition = "2021"
[dependencies]
serde = { version = "1", features = ["derive"] }

35
goas/common/src/lib.rs Normal file
View File

@ -0,0 +1,35 @@
use serde::{Serialize, Deserialize};
use std::collections::BTreeMap;
#[derive(Clone, Serialize, Deserialize)]
pub struct Note {
pub state_cm: [u8; 32],
pub journal_cm: [u8; 32],
pub zone_input: Input,
}
// state of the zone
pub type State = BTreeMap<u32, u32>;
// list of all inputs that were executed up to this point
pub type Journal = Vec<Input>;
#[derive(Clone, Copy, Serialize, Deserialize)]
pub enum Input {
Transfer { from: u32, to: u32, amount: u32 },
None,
}
/// State transition function of the zone
pub fn stf(mut state: State, input: Input) -> State {
match input {
Input::Transfer { from, to, amount } => {
// compute transfer
let from = state.entry(from).or_insert(0);
*from = from.checked_sub(amount).unwrap();
*state.entry(to).or_insert(0) += amount;
}
Input::None => {}
}
state
}

View File

@ -9,4 +9,5 @@ risc0-zkvm = { version = "1.0.1" }
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
serde = "1.0"
blake2 = "0.10"
bincode = "1"
bincode = "1"
common = { path = "../common" }

View File

@ -3,25 +3,8 @@
use blake2::{Blake2s256, Digest};
use methods::{METHOD_ELF, METHOD_ID};
use risc0_zkvm::{default_prover, ExecutorEnv};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use common::*;
// state of the zone
type State = BTreeMap<u32, u32>;
// list of all inputs that were executed up to this point
type Journal = Vec<Input>;
#[derive(Clone, Serialize, Deserialize)]
struct Note {
state_cm: [u8; 32],
journal_cm: [u8; 32],
zone_input: Input,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
enum Input {
Transfer { from: u32, to: u32, amount: u32 },
}
fn main() {
// Initialize tracing. In order to view logs, run `RUST_LOG=info cargo run`
@ -29,28 +12,43 @@ fn main() {
.with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env())
.init();
let state: BTreeMap<u32, u32> = [(0, 1000)].into_iter().collect();
let state: State = [(0, 1000)].into_iter().collect();
let journal = vec![];
let zone_input = Input::Transfer {
from: 0,
to: 1,
amount: 10,
};
let note = Note {
let in_note = Note {
state_cm: calculate_state_hash(&state),
journal_cm: calculate_journal_hash(&journal),
zone_input: Input::Transfer {
from: 0,
to: 1,
amount: 10,
},
zone_input,
};
let mut out_journal = journal.clone();
out_journal.push(zone_input);
let out_note = Note {
state_cm: calculate_state_hash(&stf(state.clone(), zone_input)),
journal_cm: calculate_journal_hash(&out_journal),
zone_input: Input::None,
};
let ptx_root = [0u8; 32];
let in_ptx_path: Vec<[u8; 32]> = vec![[0; 32]];
let out_ptx_path: Vec<[u8; 32]> = vec![[0; 32]];
let env = ExecutorEnv::builder()
.write(&ptx_root)
.unwrap()
.write(&in_ptx_path)
.unwrap()
.write(&note)
.write(&out_ptx_path)
.unwrap()
.write(&in_note)
.unwrap()
.write(&out_note)
.unwrap()
.write(&state)
.unwrap()
@ -64,7 +62,7 @@ fn main() {
// Proof information by proving the specified ELF binary.
// This struct contains the receipt along with statistics about execution of the guest
let opts = risc0_zkvm::ProverOpts::default();
let opts = risc0_zkvm::ProverOpts::succinct();
let prove_info = prover.prove_with_opts(env, METHOD_ELF, &opts).unwrap();
// extract the receipt.
@ -72,10 +70,7 @@ fn main() {
// TODO: Implement code for retrieving receipt journal here.
// For example:
let (state_cm, journal_cm): ([u8; 32], [u8; 32]) = receipt.journal.decode().unwrap();
// println!("After: {:?}", output);
std::fs::write("proof.stark", bincode::serialize(&receipt).unwrap()).unwrap();
// The receipt was verified at the end of proving, but the below code is an
// example of how someone else could verify this receipt.
receipt.verify(METHOD_ID).unwrap();

View File

@ -9,4 +9,5 @@ edition = "2021"
risc0-zkvm = { version = "1.0.1", default-features = false, features = ['std'] }
blake2 = "0.10"
serde = { version = "1.0", features = ["derive"] }
bincode = "1"
bincode = "1"
common = { path = "../../common" }

View File

@ -1,43 +1,12 @@
use blake2::{Blake2s256, Digest};
use risc0_zkvm::guest::env;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use common::*;
/// Public Inputs:
/// * ptx_root: the root of the partial tx merkle tree of inputs/outputs
/// Private inputs:
/// TODO
// state of the zone
type State = BTreeMap<u32, u32>;
// list of all inputs that were executed up to this point
type Journal = Vec<Input>;
#[derive(Clone, Serialize, Deserialize)]
struct Note {
state_cm: [u8; 32],
journal_cm: [u8; 32],
zone_input: Input,
}
#[derive(Clone, Copy, Serialize, Deserialize)]
enum Input {
Transfer { from: u32, to: u32, amount: u32 },
}
/// State transition function
fn stf(mut state: State, input: Input) -> State {
match input {
Input::Transfer { from, to, amount } => {
// compute transfer
let from = state.entry(from).or_insert(0);
*from = from.checked_sub(amount).unwrap();
*state.entry(to).or_insert(0) += amount;
}
}
state
}
/// Glue the zone and the cl together, specifically, it verifies the note requesting
/// a transfer is included as part of the same transaction in the cl
fn verify_ptx_inputs(ptx_root: [u8; 32], ptx_path: &[[u8; 32]], note: &Note) {
@ -47,36 +16,42 @@ fn verify_ptx_inputs(ptx_root: [u8; 32], ptx_path: &[[u8; 32]], note: &Note) {
/// Glue the zone and the cl together, specifically, it verifies an output note
/// containing the zone state is included as part of the same transaction in the cl
/// (this is done in the death condition to disallow burning)
fn verify_ptx_output(ptx_root: [u8; 32], ptx_path: &[[u8; 32]], note: &Note) {
fn verify_ptx_outputs(ptx_root: [u8; 32], ptx_path: &[[u8; 32]], note: &Note) {
assert!(verify_path(&ptx_root, &ptx_path, &note));
}
fn execute(
ptx_root: [u8; 32],
ptx_path: Vec<[u8; 32]>,
note: Note,
in_ptx_path: Vec<[u8; 32]>,
out_ptx_path: Vec<[u8; 32]>,
in_note: Note,
out_note: Note,
state: State,
mut journal: Journal,
) -> (State, Journal) {
// verify ptx/cl preconditions
verify_ptx_inputs(ptx_root, &ptx_path, &note);
verify_ptx_inputs(ptx_root, &in_ptx_path, &in_note);
// check the commitments match the actual data
let state_cm = calculate_state_hash(&state);
let journal_cm = calculate_journal_hash(&journal);
assert_eq!(state_cm, note.state_cm);
assert_eq!(journal_cm, note.journal_cm);
assert_eq!(state_cm, in_note.state_cm);
assert_eq!(journal_cm, in_note.journal_cm);
// then run the state transition function
let input = note.zone_input;
let input = in_note.zone_input;
let state = stf(state, input);
journal.push(input);
let state_cm = calculate_state_hash(&state);
let journal_cm = calculate_journal_hash(&journal);
// TODO: verify death constraints are propagated
assert_eq!(state_cm, out_note.state_cm);
assert_eq!(journal_cm, out_note.journal_cm);
// verifying ptx/cl postconditions
verify_ptx_outputs(ptx_root, &ptx_path, out_note);
verify_ptx_outputs(ptx_root, &out_ptx_path, &out_note);
// output the new state and the execution receipt
(state, journal)
}
@ -88,11 +63,12 @@ fn main() {
// private input
let in_ptx_path: Vec<[u8; 32]> = env::read();
let out_ptx_path: Vec<[u8; 32]> = env::read();
let note: Note = env::read();
let in_note: Note = env::read();
let out_note: Note = env::read();
let state: State = env::read();
let journal: Journal = env::read();
execute(ptx_root, in_ptx_path, out_ptx_path, note, state, journal);
execute(ptx_root, in_ptx_path, out_ptx_path, in_note, out_note, state, journal);
}
fn calculate_state_hash(state: &State) -> [u8; 32] {