fix zone PoC
This commit is contained in:
parent
507e1627d7
commit
3c991173c5
|
@ -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]
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1", features = ["derive"] }
|
|
@ -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
|
||||
}
|
|
@ -10,3 +10,4 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|||
serde = "1.0"
|
||||
blake2 = "0.10"
|
||||
bincode = "1"
|
||||
common = { path = "../common" }
|
|
@ -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(¬e)
|
||||
.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();
|
||||
|
|
|
@ -10,3 +10,4 @@ risc0-zkvm = { version = "1.0.1", default-features = false, features = ['std'] }
|
|||
blake2 = "0.10"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
bincode = "1"
|
||||
common = { path = "../../common" }
|
|
@ -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, ¬e));
|
||||
}
|
||||
|
||||
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, ¬e);
|
||||
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] {
|
||||
|
|
Loading…
Reference in New Issue