diff --git a/goas/common/Cargo.toml b/goas/common/Cargo.toml index 0e28ae9..aa48d9c 100644 --- a/goas/common/Cargo.toml +++ b/goas/common/Cargo.toml @@ -4,4 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] -serde = { version = "1", features = ["derive"] } \ No newline at end of file +serde = { version = "1", features = ["derive"] } diff --git a/goas/common/src/lib.rs b/goas/common/src/lib.rs index d7ed49e..13a532f 100644 --- a/goas/common/src/lib.rs +++ b/goas/common/src/lib.rs @@ -1,13 +1,6 @@ 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; // list of all inputs that were executed up to this point @@ -32,4 +25,4 @@ pub fn stf(mut state: State, input: Input) -> State { Input::None => {} } state -} \ No newline at end of file +} diff --git a/goas/host/Cargo.toml b/goas/host/Cargo.toml index 6bf14bd..b05a77b 100644 --- a/goas/host/Cargo.toml +++ b/goas/host/Cargo.toml @@ -14,4 +14,6 @@ blake2 = "0.10" bincode = "1" common = { path = "../common" } tempfile = "3" -clap = { version = "4", features = ["derive"] } \ No newline at end of file +clap = { version = "4", features = ["derive"] } +rand = "0.8.5" +cl = { path = "../../cl" } diff --git a/goas/host/src/main.rs b/goas/host/src/main.rs index b541a70..dd26265 100644 --- a/goas/host/src/main.rs +++ b/goas/host/src/main.rs @@ -4,7 +4,11 @@ use blake2::{Blake2s256, Digest}; use methods::{METHOD_ELF, METHOD_ID}; use risc0_zkvm::{default_prover, ExecutorEnv}; use common::*; - +use cl::note::NoteWitness; +use cl::input::InputWitness; +use cl::output::OutputWitness; +use cl::nullifier::{NullifierCommitment, Nullifier +use cl::partial_tx::{PartialTx, PartialTxWitness}; fn main() { // Initialize tracing. In order to view logs, run `RUST_LOG=info cargo run` @@ -12,6 +16,8 @@ fn main() { .with_env_filter(tracing_subscriber::filter::EnvFilter::from_default_env()) .init(); + let mut rng = rand::thread_rng(); + let state: State = [(0, 1000)].into_iter().collect(); let journal = vec![]; let zone_input = Input::Transfer { @@ -20,28 +26,35 @@ fn main() { amount: 10, }; - let in_note = Note { - state_cm: calculate_state_hash(&state), - journal_cm: calculate_journal_hash(&journal), - zone_input, - }; + let in_state_cm = calculate_state_hash(&state), + let in_journal_cm = calculate_journal_hash(&journal), + let in_state_root = merkle::node(in_start_cm, in_journal_cm); + let in_note = NoteWitness::new(1, "ZONE", in_state_root, &mut rng); 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 out_state_cm = calculate_state_hash(&stf(state.clone(), zone_input)), + let out_journal_cm = calculate_journal_hash(&out_journal), + let out_state_root = merkle::node(out_state_cm, out_journal_cm); + let out_note = NoteWitness::new(1, "ZONE", out_state_root, &mut rng); - 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 ptx = PartialTx::from_witness(PartialTxWitness { + inputs: vec![InputWitness::random(in_note, &mut rng)], + outputs: vec![OutputWitness::random(out_note, NullifierCommitment::random(&mut rng), &mut rng)], + }); + + let ptx_root = ptx.root(); + let in_ptx_path = ptx.input_merkle_path(0); + let out_ptx_path = ptx.output_merkle_path(0); let env = ExecutorEnv::builder() .write(&ptx_root) .unwrap() + .write(&ptx.input_root) + .unwrap() + .write(&ptx.output_root) + .unwrap() .write(&in_ptx_path) .unwrap() .write(&out_ptx_path) diff --git a/goas/methods/guest/src/main.rs b/goas/methods/guest/src/main.rs index 22bc96f..25070aa 100644 --- a/goas/methods/guest/src/main.rs +++ b/goas/methods/guest/src/main.rs @@ -1,6 +1,8 @@ use blake2::{Blake2s256, Digest}; use risc0_zkvm::guest::env; use common::*; +use cl::merkle; +use cl::note::NoteWitness /// Public Inputs: /// * ptx_root: the root of the partial tx merkle tree of inputs/outputs @@ -22,38 +24,39 @@ fn verify_ptx_outputs(ptx_root: [u8; 32], ptx_path: &[[u8; 32]], note: &Note) { fn execute( ptx_root: [u8; 32], - in_ptx_path: Vec<[u8; 32]>, - out_ptx_path: Vec<[u8; 32]>, - in_note: Note, - out_note: Note, + input_root: [u8; 32], + output_root: [u8; 32], + in_ptx_path: Vec, + out_ptx_path: Vec, + in_note: NoteWitness, + out_note: NotWitness, + input: Input, state: State, mut journal: Journal, -) -> (State, Journal) { +) { // verify ptx/cl preconditions - verify_ptx_inputs(ptx_root, &in_ptx_path, &in_note); + + assert_eq!(ptx_root, merkle::node(input_root, output_root)); + assert!(merkle::verify_path(in_note.commit().0, in_ptx_path, input_root)); // 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, in_note.state_cm); - assert_eq!(journal_cm, in_note.journal_cm); + let state_root = merkle::node(state_cm, journal_cm); + assert_eq!(state_root, in_note.state); // then run the state transition function - 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, &out_ptx_path, &out_note); - // output the new state and the execution receipt - (state, journal) + + let out_state_cm = calculate_state_hash(&state); + let out_journal_cm = calculate_journal_hash(&journal); + let out_state_root = merkle::node(out_state_cm, out_journal_cm); + // TODO: verify death constraints are propagated + assert_eq!(out_state_root, out_note.state); + assert!(merkle::verify_path(out_note.commit().0, out_ptx_path, output_root)); } fn main() { @@ -61,14 +64,17 @@ fn main() { let ptx_root: [u8; 32] = env::read(); // private input - let in_ptx_path: Vec<[u8; 32]> = env::read(); - let out_ptx_path: Vec<[u8; 32]> = env::read(); - let in_note: Note = env::read(); - let out_note: Note = env::read(); + let input_root: [u8; 32] = env::read(); + let output_root: [u8; 32] = env::read(); + let in_ptx_path: Vec = env::read(); + let out_ptx_path: Vec = env::read(); + let in_note: NoteWitness = env::read(); + let out_note: NoteWitness = env::read(); + let input: Input = env::read() let state: State = env::read(); let journal: Journal = env::read(); - execute(ptx_root, in_ptx_path, out_ptx_path, in_note, out_note, state, journal); + execute(ptx_root, input_root, output_root, in_ptx_path, out_ptx_path, in_note, out_note, input, state, journal); } fn calculate_state_hash(state: &State) -> [u8; 32] {