From 4b843cc6ca5e32881bb9c7558eb0c05f6cb88cba Mon Sep 17 00:00:00 2001 From: Augusto Hack Date: Wed, 28 Feb 2024 19:05:14 +0100 Subject: [PATCH] mock: add proven tx builder (#474) --- Cargo.toml | 1 + miden-tx/Cargo.toml | 2 +- mock/Cargo.toml | 5 ++- mock/src/builders/mod.rs | 2 + mock/src/builders/tx.rs | 68 ++++++++++++++++++++++++++++++ objects/src/notes/envelope.rs | 1 + objects/src/notes/note_id.rs | 1 + objects/src/notes/nullifier.rs | 1 + objects/src/transaction/mod.rs | 4 +- objects/src/transaction/outputs.rs | 4 ++ 10 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 mock/src/builders/tx.rs diff --git a/Cargo.toml b/Cargo.toml index 9a8b1bd02..ce79469fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,3 +20,4 @@ lto = true assembly = { package = "miden-assembly", version = "0.8", default-features = false } miden-verifier = { package = "miden-verifier", version = "0.8", default-features = false } vm-processor = { package = "miden-processor", version = "0.8", default-features = false } +miden-prover = { package = "miden-prover", version = "0.8", default-features = false } diff --git a/miden-tx/Cargo.toml b/miden-tx/Cargo.toml index d35a5ba8a..0ceff4250 100644 --- a/miden-tx/Cargo.toml +++ b/miden-tx/Cargo.toml @@ -23,7 +23,7 @@ std = ["miden-lib/std", "miden-objects/std", "miden-prover/std", "miden-verifier [dependencies] miden-lib = { package = "miden-lib", path = "../miden-lib", default-features = false } miden-objects = { package = "miden-objects", path = "../objects", default-features = false } -miden-prover = { package = "miden-prover", version = "0.8", default-features = false } +miden-prover = { workspace = true } miden-verifier = { workspace = true } vm-processor = { workspace = true } diff --git a/mock/Cargo.toml b/mock/Cargo.toml index e257ee4d6..9704c7ded 100644 --- a/mock/Cargo.toml +++ b/mock/Cargo.toml @@ -25,12 +25,13 @@ std = ["miden-lib/std", "miden-objects/std"] [dependencies] clap = { version = "4.4", features = ["derive"], optional = true } env_logger = { version = "0.11" } -hex = "0.4" +hex = { version = "0.4" } miden-lib = { path = "../miden-lib" } miden-objects = { path = "../objects" , features = ["serde", "log", "testing"] } +miden-prover = { workspace = true } postcard = { version = "1.0", features = [ "alloc" ] } rand = { version = "0.8" } +rand-utils = { package = "winter-rand-utils", version = "0.8" } rand_pcg = { version = "0.3", features = ["serde1"] } serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] } vm-processor = { workspace = true, features = ["internals"] } -rand-utils = { package = "winter-rand-utils", version = "0.8" } diff --git a/mock/src/builders/mod.rs b/mock/src/builders/mod.rs index d2216e06e..a2df68a1b 100644 --- a/mock/src/builders/mod.rs +++ b/mock/src/builders/mod.rs @@ -9,6 +9,7 @@ mod error; mod fungible_asset; mod nonfungible_asset; mod note; +mod tx; // RE-EXPORTS // ================================================================================================ @@ -19,6 +20,7 @@ pub use error::AccountBuilderError; pub use fungible_asset::FungibleAssetBuilder; pub use nonfungible_asset::{NonFungibleAssetBuilder, NonFungibleAssetDetailsBuilder}; pub use note::NoteBuilder; +pub use tx::ProvenTransactionBuilder; pub fn str_to_account_code(source: &str) -> Result { let assembler = TransactionKernel::assembler(); diff --git a/mock/src/builders/tx.rs b/mock/src/builders/tx.rs new file mode 100644 index 000000000..321c1b49a --- /dev/null +++ b/mock/src/builders/tx.rs @@ -0,0 +1,68 @@ +use miden_objects::{ + accounts::AccountId, + notes::{NoteEnvelope, Nullifier}, + transaction::{InputNotes, OutputNotes, ProvenTransaction, ToEnvelope, ToNullifier}, + vm::ExecutionProof, + Digest, +}; +use miden_prover::{HashFunction, StarkProof}; + +/// Builder for an `ProvenTransaction`, the builder allows for a fluent API to construct an account. +/// Each transaction needs a unique builder. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct ProvenTransactionBuilder { + account_id: AccountId, + note_envelopes: Vec, + nullifiers: Vec, + initial_account_hash: Digest, + final_account_hash: Digest, +} + +impl ProvenTransactionBuilder { + pub fn new( + account_id: AccountId, + initial_account_hash: Digest, + final_account_hash: Digest, + ) -> Self { + Self { + account_id, + initial_account_hash, + final_account_hash, + note_envelopes: Vec::new(), + nullifiers: Vec::new(), + } + } + + pub fn add_note_envelope(mut self, note_envelope: I) -> Self { + self.note_envelopes.push(note_envelope.to_envelope()); + self + } + pub fn add_note_envelopes>( + mut self, + note_envelopes: I, + ) -> Self { + for note_envelope in note_envelopes.into_iter() { + self.note_envelopes.push(note_envelope.to_envelope()); + } + self + } + + pub fn add_nullifier(mut self, nullifier: I) -> Self { + self.nullifiers.push(nullifier.nullifier()); + self + } + + pub fn build(self) -> ProvenTransaction { + ProvenTransaction::new( + self.account_id, + self.initial_account_hash, + self.final_account_hash, + InputNotes::new(self.nullifiers).unwrap(), + OutputNotes::new(self.note_envelopes).unwrap(), + None, + Digest::default(), + ExecutionProof::new(StarkProof::new_dummy(), HashFunction::Blake3_192), + ) + } +} diff --git a/objects/src/notes/envelope.rs b/objects/src/notes/envelope.rs index 77a6efc4a..bad967eac 100644 --- a/objects/src/notes/envelope.rs +++ b/objects/src/notes/envelope.rs @@ -18,6 +18,7 @@ use crate::utils::collections::*; /// - num assets /// - ZERO #[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct NoteEnvelope { note_id: NoteId, note_metadata: NoteMetadata, diff --git a/objects/src/notes/note_id.rs b/objects/src/notes/note_id.rs index fa88ed55c..a5aa7cf88 100644 --- a/objects/src/notes/note_id.rs +++ b/objects/src/notes/note_id.rs @@ -22,6 +22,7 @@ use crate::utils::{ /// - To compute a note ID, we do not need to know the note's serial_num. Knowing the hash /// of the serial_num (as well as script hash, input hash, and note assets) is sufficient. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct NoteId(Digest); impl NoteId { diff --git a/objects/src/notes/nullifier.rs b/objects/src/notes/nullifier.rs index 081d4987e..fd680c3d3 100644 --- a/objects/src/notes/nullifier.rs +++ b/objects/src/notes/nullifier.rs @@ -19,6 +19,7 @@ use crate::utils::{hex_to_bytes, string::*, HexParseError}; /// - To compute the nullifier we must know all components of the note: serial_num, script_hash, /// input_hash and asset_hash. #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Nullifier(Digest); impl Nullifier { diff --git a/objects/src/transaction/mod.rs b/objects/src/transaction/mod.rs index 078cebbf1..fb92e2346 100644 --- a/objects/src/transaction/mod.rs +++ b/objects/src/transaction/mod.rs @@ -17,8 +17,8 @@ mod tx_witness; pub use chain_mmr::ChainMmr; pub use executed_tx::ExecutedTransaction; -pub use inputs::{InputNote, InputNotes, TransactionInputs}; -pub use outputs::{OutputNote, OutputNotes, TransactionOutputs}; +pub use inputs::{InputNote, InputNotes, ToNullifier, TransactionInputs}; +pub use outputs::{OutputNote, OutputNotes, ToEnvelope, TransactionOutputs}; pub use prepared_tx::PreparedTransaction; pub use proven_tx::ProvenTransaction; pub use transaction_id::TransactionId; diff --git a/objects/src/transaction/outputs.rs b/objects/src/transaction/outputs.rs index c543ef8fc..064ad7063 100644 --- a/objects/src/transaction/outputs.rs +++ b/objects/src/transaction/outputs.rs @@ -33,6 +33,10 @@ pub trait ToEnvelope: { fn id(&self) -> NoteId; fn metadata(&self) -> NoteMetadata; + + fn to_envelope(&self) -> NoteEnvelope { + NoteEnvelope::new(self.id(), self.metadata()) + } } impl ToEnvelope for OutputNote {