From 4e00f5772f81b19e5da88f2ba868b6a21a1e9567 Mon Sep 17 00:00:00 2001 From: frisitano Date: Tue, 18 Jul 2023 15:29:58 +0200 Subject: [PATCH] feat: refactor verify_transaction api --- playground/miden-wasm/Cargo.toml | 1 + playground/miden-wasm/src/transaction.rs | 122 +++++++++++++---------- 2 files changed, 72 insertions(+), 51 deletions(-) diff --git a/playground/miden-wasm/Cargo.toml b/playground/miden-wasm/Cargo.toml index 7b5e6bf..3a02ed5 100644 --- a/playground/miden-wasm/Cargo.toml +++ b/playground/miden-wasm/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" crate-type = ["cdylib", "rlib"] [dependencies] +assembly = { package = "miden-assembly", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "frisitano-tx-result", default-features = false } hex = { version = "0.4", default-features = false } miden-vm = { package = "miden-vm", git = "https://github.com/0xPolygonMiden/miden-vm.git", branch = "frisitano-tx-result", default-features = false } miden-tx = { git = "https://github.com/0xPolygonMiden/miden-base.git", branch = "frisitano-prover-tx", features = ["testing"], default-features = false } diff --git a/playground/miden-wasm/src/transaction.rs b/playground/miden-wasm/src/transaction.rs index c22321b..d1374c1 100644 --- a/playground/miden-wasm/src/transaction.rs +++ b/playground/miden-wasm/src/transaction.rs @@ -1,12 +1,16 @@ +use super::ExecutionProof; +use assembly::Assembler; +use miden_lib::{MidenLib, SatKernel}; use miden_objects::{ notes::Note, transaction::{PreparedTransaction, ProvenTransaction}, }; +use miden_stdlib::StdLibrary; use miden_tx::{mock::MockDataStore, TransactionExecutor, TransactionProver}; use miden_vm::{ crypto::RpoDigest, math::{Felt, StarkField}, - ProgramInfo, ProofOptions, Word, + ProgramInfo, ProofOptions, StackInputs, StackOutputs, Word, }; use serde::{Deserialize, Serialize}; use serde_wasm_bindgen::Serializer; @@ -131,6 +135,9 @@ pub struct WasmProvenTransaction { pub consumed_notes: Vec>, pub created_notes: Vec>, pub tx_script_root: Option>, + pub stack_inputs: Vec, + pub stack_outputs: Vec, + pub program_hash: Vec, pub proof: Vec, } @@ -168,6 +175,20 @@ impl From for WasmProvenTransaction { tx_script_root: proven_transaction .tx_script_root() .and_then(|x| Some(Into::::into(x).into())), + stack_inputs: proven_transaction + .stack_inputs() + .values() + .iter() + .rev() + .map(|x| x.as_int()) + .collect::>(), + stack_outputs: proven_transaction + .stack_outputs() + .stack() + .iter() + .cloned() + .collect(), + program_hash: Into::::into(proven_transaction.program_hash()).into(), proof: proven_transaction.proof().to_bytes(), } } @@ -176,8 +197,7 @@ impl From for WasmProvenTransaction { // PROVE TRANSACTION // ================================================================================================ -#[wasm_bindgen] -pub fn prove_transaction() -> Result { +pub fn do_prove_transaction() -> Result { let data_store = MockDataStore::new(); let mut executor = TransactionExecutor::new(data_store.clone()); @@ -199,10 +219,15 @@ pub fn prove_transaction() -> Result { .map_err(|err| format!("Failed to prepare transaction - {:?}", err))?; let prover = TransactionProver::new(ProofOptions::default()); - let proven_transaction: WasmProvenTransaction = prover + Ok(prover .prove_prepared_transaction(prepared_transaction) .map_err(|e| format!("Failed to prove prepared transaction - {:?}", e))? - .into(); + .into()) +} + +#[wasm_bindgen] +pub fn prove_transaction() -> Result { + let proven_transaction: WasmProvenTransaction = do_prove_transaction()?; let serializer = Serializer::new().serialize_large_number_types_as_bigints(true); Ok(proven_transaction.serialize(&serializer)?) @@ -215,57 +240,42 @@ pub fn prove_transaction() -> Result { #[derive(Serialize, Deserialize, Debug)] pub struct WasmVerifyTransactionResult { pub success: bool, - pub proof: Vec, } // VERIFY TRANSACTION // ================================================================================================ #[wasm_bindgen] -pub fn verify_transaction() -> Result { - let data_store = MockDataStore::new(); - let mut executor = TransactionExecutor::new(data_store.clone()); - - let account_id = data_store.account.id(); - executor - .load_account(account_id) - .map_err(|err| format!("Failed to load account - {:?}", err))?; - - let block_ref = data_store.block_header.block_num().as_int() as u32; - let note_origins = data_store - .notes - .iter() - .take(1) - .map(|note| note.proof().as_ref().unwrap().origin().clone()) - .collect::>(); - - let prepared_transaction = executor - .prepare_transaction(data_store.account.id(), block_ref, ¬e_origins, None) - .map_err(|err| format!("Failed to prepare transaction - {:?}", err))?; - - let program_hash = prepared_transaction.tx_program().hash(); - let kernel = prepared_transaction.tx_program().kernel().clone(); - - let prover = TransactionProver::new(ProofOptions::default()); - let proven_transaction = prover - .prove_prepared_transaction(prepared_transaction) - .map_err(|e| format!("Failed to prove prepared transaction - {:?}", e))?; - - let stack_inputs = proven_transaction.stack_inputs(); - let stack_outputs = proven_transaction.stack_outputs(); - let program_info = ProgramInfo::new(program_hash, kernel); - let _result: u32 = miden_vm::verify( - program_info, - stack_inputs, - stack_outputs, - proven_transaction.proof().clone(), - ) - .map_err(|err| format!("Program failed verification! - {}", err))?; - - Ok(WasmVerifyTransactionResult { - success: true, - proof: proven_transaction.proof().to_bytes(), - }) +pub fn verify_transaction( + stack_inputs: Vec, + stack_outputs: Vec, + program_hash: Vec, + proof: Vec, +) -> Result { + let stack_inputs = StackInputs::try_from_values(stack_inputs) + .map_err(|e| format!("Invalid stack inputs: {}", e))?; + let stack_outputs = StackOutputs::new(stack_outputs, Default::default()); + let program_hash: [Felt; 4] = program_hash + .into_iter() + .map(|x| Felt::try_from(x.to_le_bytes()).map_err(|x| format!("{x}"))) + .collect::, String>>()? + .try_into() + .map_err(|x| format!("Invalid program hash: {:?}", x))?; + let program_hash = RpoDigest::new(program_hash); + let proof = ExecutionProof::from_bytes(&proof) + .map_err(|err| format!("Failed to deserialize proof - {}", err))?; + let assembler = Assembler::default() + .with_library(&MidenLib::default()) + .expect("library is well formed") + .with_library(&StdLibrary::default()) + .expect("library is well formed") + .with_kernel(SatKernel::kernel()) + .expect("kernel is well formed"); + let program_info = ProgramInfo::new(program_hash, assembler.kernel().clone()); + let _result: u32 = miden_vm::verify(program_info, stack_inputs, stack_outputs, proof) + .map_err(|err| format!("Program failed verification! - {}", err))?; + + Ok(WasmVerifyTransactionResult { success: true }) } // TESTS @@ -273,5 +283,15 @@ pub fn verify_transaction() -> Result { #[test] fn test_verify_transaction() { - println!("{:?}", verify_transaction().unwrap()); + let proven_transaction = do_prove_transaction().unwrap(); + println!( + "{:?}", + verify_transaction( + proven_transaction.stack_inputs, + proven_transaction.stack_outputs, + proven_transaction.program_hash, + proven_transaction.proof + ) + .unwrap() + ); }