Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate batch kernel parts from miden-node #1112

Merged
merged 52 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
6a696fd
feat: Add miden-batch-prover crate
PhilippGackstatter Jan 23, 2025
2b44b45
feat: Add `BatchId`
PhilippGackstatter Jan 24, 2025
71b5be9
Introduce `AccountUpdateError`
PhilippGackstatter Jan 24, 2025
792369a
feat: Add `ProposedBatch`
PhilippGackstatter Jan 24, 2025
4ca86ef
feat: Add `LocalBatchProver`
PhilippGackstatter Jan 24, 2025
206e47f
feat: Add `ProvenBatch`
PhilippGackstatter Jan 24, 2025
cf580af
feat: Migrate `LocalBatchProver` from node
PhilippGackstatter Jan 24, 2025
f28aa6f
chore: Rename `NoteAuthenticationInfo`
PhilippGackstatter Jan 27, 2025
4cc4453
feat:Add batch expiration block num
PhilippGackstatter Jan 27, 2025
53970f5
chore: Use core instead of std for `Display`
PhilippGackstatter Jan 27, 2025
5f50946
feat: Migrate `MockProvenTxBuilder`
PhilippGackstatter Jan 27, 2025
d961a78
feat: Test tx ordering in batches
PhilippGackstatter Jan 27, 2025
c3b3fe2
feat: Add `BatchAccountUpdate`
PhilippGackstatter Jan 27, 2025
43cbb81
chore: Extend test assertions
PhilippGackstatter Jan 28, 2025
c014be8
feat: Refactor and document batch output note tracker
PhilippGackstatter Jan 28, 2025
9f1be8b
feat: Add input/output notes commitment test
PhilippGackstatter Jan 28, 2025
5887560
feat: Remove `BlockNumber::from_usize`
PhilippGackstatter Jan 28, 2025
e8b4be4
feat: Check for duplicate input notes
PhilippGackstatter Jan 28, 2025
45dfa3f
feat: Add unauthenticated/authenticated scenario tests
PhilippGackstatter Jan 28, 2025
a7a9be2
chore: Misc doc fixes
PhilippGackstatter Jan 28, 2025
8ca80cd
feat: Move `ProposedBatch` and `ProvenBatch` to objects
PhilippGackstatter Jan 28, 2025
921c6d9
chore: Add changelog entry
PhilippGackstatter Jan 28, 2025
a4d4b1e
feat: Use MockChain for batch tests (partially)
PhilippGackstatter Jan 29, 2025
fda5530
chore: Move most validation to `ProposedBatch`
PhilippGackstatter Jan 29, 2025
18817bf
feat: Use MockChain for all tests
PhilippGackstatter Jan 29, 2025
63c0e08
feat: Implement note authentication and tests for it
PhilippGackstatter Jan 29, 2025
94d7382
feat: Verify transactions in batch
PhilippGackstatter Jan 29, 2025
46d01b0
chore: Document error conditions on proposed batch
PhilippGackstatter Jan 29, 2025
44d0330
feat: Check max input/output notes and account updates in batch
PhilippGackstatter Jan 29, 2025
5191aa5
feat: Check for duplicate transactions in batch
PhilippGackstatter Jan 30, 2025
fe51a24
feat: Add tests with a circular note dependency
PhilippGackstatter Jan 30, 2025
85d6ef5
feat: Rename batch prover crate
PhilippGackstatter Jan 30, 2025
4d6948b
chore: Address review comments
PhilippGackstatter Jan 30, 2025
8c01b15
chore: Unbox the `BlockHeader`
PhilippGackstatter Jan 30, 2025
81b3975
chore: Remove unused dependencies
PhilippGackstatter Jan 30, 2025
7dadd00
feat: Use `InputNotes` rather than `Vec`
PhilippGackstatter Jan 30, 2025
eefb495
feat: Compute batch ID as sequential hash over tx ID and account ID
PhilippGackstatter Jan 30, 2025
ec0ddd5
chore: Remove `BlockInclusionProof` and `NoteInclusionProofs`
PhilippGackstatter Jan 30, 2025
77bfc92
chore: Address more review comments
PhilippGackstatter Jan 30, 2025
d519962
chore: Move tests into dedicated file
PhilippGackstatter Jan 30, 2025
089761d
feat: Add `block_num` field to `ProvenTransaction`
PhilippGackstatter Jan 31, 2025
fb5170d
feat: Add `ChainMmr::from_mmr`
PhilippGackstatter Jan 31, 2025
84cc06f
feat: Add `BatchAccountUpdate::into_parts`
PhilippGackstatter Jan 31, 2025
3212118
feat: Add `ProvenBatch::produced_nullifiers`
PhilippGackstatter Jan 31, 2025
3a58866
feat: Add `BatchId::compute_from_ids`
PhilippGackstatter Jan 31, 2025
5eccbca
feat: Expose `BatchProveError` and rename `BatchProposeError`
PhilippGackstatter Feb 3, 2025
d6b041d
Merge remote-tracking branch 'origin/next' into pgackst-batch-prover-…
PhilippGackstatter Feb 3, 2025
6869e72
feat: Remove `compute` prefix from batch id constructors
PhilippGackstatter Feb 3, 2025
5de9b11
chore: Move `ChainMmr::from_mmr` behind test flag
PhilippGackstatter Feb 3, 2025
f67799d
chore: Address review comments
PhilippGackstatter Feb 3, 2025
23c70d0
feat: Disallow empty transaction batches
PhilippGackstatter Feb 3, 2025
6abf8dc
chore: Address review comments
PhilippGackstatter Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- [BREAKING] Incremented minimum supported Rust version to 1.84.
- [BREAKING] Moved `generated` module from `miden-proving-service-client` crate to `tx_prover::generated` hierarchy (#1102).
- Implement transaction batch prover in Rust (#1112).

## 0.7.1 (2025-01-24) - `miden-objects` crate only

Expand Down
27 changes: 27 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ resolver = "2"
members = [
"bin/bench-tx",
"bin/proving-service",
"crates/miden-tx-batch-prover",
"crates/miden-lib",
"crates/miden-objects",
"crates/miden-proving-service-client",
Expand Down
144 changes: 144 additions & 0 deletions crates/miden-objects/src/batch/account_update.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
use alloc::vec::Vec;

use vm_core::utils::{ByteReader, ByteWriter, Deserializable, Serializable};
use vm_processor::{DeserializationError, Digest};

use crate::{
account::{delta::AccountUpdateDetails, AccountId},
errors::BatchAccountUpdateError,
transaction::{ProvenTransaction, TransactionId},
};

// BATCH ACCOUNT UPDATE
// ================================================================================================

/// Represents the changes made to an account resulting from executing a batch of transactions.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BatchAccountUpdate {
/// ID of the updated account.
account_id: AccountId,

/// Commitment to the state of the account before this update is applied.
///
/// Equal to `Digest::default()` for new accounts.
initial_state_commitment: Digest,

/// Commitment to the state of the account after this update is applied.
final_state_commitment: Digest,

/// IDs of all transactions that updated the account.
transactions: Vec<TransactionId>,

/// A set of changes which can be applied to the previous account state (i.e. `initial_state`)
/// to get the new account state. For private accounts, this is set to
/// [`AccountUpdateDetails::Private`].
details: AccountUpdateDetails,
}

impl BatchAccountUpdate {
// CONSTRUCTORS
// --------------------------------------------------------------------------------------------

/// Creates a [`BatchAccountUpdate`] by cloning the update and other details from the provided
/// [`ProvenTransaction`].
pub fn from_transaction(transaction: &ProvenTransaction) -> Self {
Self {
account_id: transaction.account_id(),
initial_state_commitment: transaction.account_update().init_state_hash(),
final_state_commitment: transaction.account_update().final_state_hash(),
transactions: vec![transaction.id()],
details: transaction.account_update().details().clone(),
}
}

// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------

/// Returns the ID of the updated account.
pub fn account_id(&self) -> AccountId {
self.account_id
}

/// Returns a commitment to the state of the account before this update is applied.
///
/// This is equal to [`Digest::default()`] for new accounts.
pub fn initial_state_commitment(&self) -> Digest {
self.initial_state_commitment
}

/// Returns a commitment to the state of the account after this update is applied.
pub fn final_state_commitment(&self) -> Digest {
self.final_state_commitment
}

/// Returns a slice of [`TransactionId`]s that updated this account's state.
pub fn transactions(&self) -> &[TransactionId] {
&self.transactions
}

/// Returns the contained [`AccountUpdateDetails`].
///
/// This update can be used to build the new account state from the previous account state.
pub fn details(&self) -> &AccountUpdateDetails {
&self.details
}

/// Returns `true` if the account update details are for a private account.
pub fn is_private(&self) -> bool {
self.details.is_private()
}

// MUTATORS
// --------------------------------------------------------------------------------------------

/// Merges the transaction's update into this account update.
pub fn merge_proven_tx(
PhilippGackstatter marked this conversation as resolved.
Show resolved Hide resolved
&mut self,
tx: &ProvenTransaction,
) -> Result<(), BatchAccountUpdateError> {
if self.account_id != tx.account_id() {
return Err(BatchAccountUpdateError::AccountUpdateIdMismatch {
transaction: tx.id(),
expected_account_id: self.account_id,
actual_account_id: tx.account_id(),
});
}

if self.final_state_commitment != tx.account_update().init_state_hash() {
return Err(BatchAccountUpdateError::AccountUpdateInitialStateMismatch(tx.id()));
}

self.details = self.details.clone().merge(tx.account_update().details().clone()).map_err(
|source_err| BatchAccountUpdateError::TransactionUpdateMergeError(tx.id(), source_err),
)?;
self.final_state_commitment = tx.account_update().final_state_hash();
self.transactions.push(tx.id());

Ok(())
}
}

// SERIALIZATION
// ================================================================================================

impl Serializable for BatchAccountUpdate {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.account_id.write_into(target);
self.initial_state_commitment.write_into(target);
self.final_state_commitment.write_into(target);
self.transactions.write_into(target);
self.details.write_into(target);
}
}

impl Deserializable for BatchAccountUpdate {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
Ok(Self {
account_id: AccountId::read_from(source)?,
initial_state_commitment: Digest::read_from(source)?,
final_state_commitment: Digest::read_from(source)?,
transactions: <Vec<TransactionId>>::read_from(source)?,
details: AccountUpdateDetails::read_from(source)?,
})
}
}
56 changes: 56 additions & 0 deletions crates/miden-objects/src/batch/batch_id.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
use alloc::{string::String, vec::Vec};

use vm_core::{Felt, ZERO};
use vm_processor::Digest;

use crate::{transaction::ProvenTransaction, Hasher};

// BATCH ID
// ================================================================================================

/// Uniquely identifies a batch of transactions, i.e. both
/// [`ProposedBatch`](crate::batch::ProposedBatch) and [`ProvenBatch`](crate::batch::ProvenBatch).
///
/// This is a sequential hash of the tuple `(TRANSACTION_ID || [account_id_prefix,
/// account_id_suffix, 0, 0])` of all transactions and the accounts their executed against in the
/// batch.
#[derive(Debug, Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BatchId(Digest);

impl BatchId {
/// Calculates a batch ID from the given set of transactions.
pub fn compute<'tx, T>(txs: T) -> Self
where
T: Iterator<Item = &'tx ProvenTransaction>,
{
let mut elements: Vec<Felt> = Vec::new();
for tx in txs {
elements.extend_from_slice(tx.id().as_elements());
let [account_id_prefix, account_id_suffix] = <[Felt; 2]>::from(tx.account_id());
elements.extend_from_slice(&[account_id_prefix, account_id_suffix, ZERO, ZERO]);
}

Self(Hasher::hash_elements(&elements))
}

/// Returns the elements representation of this batch ID.
pub fn as_elements(&self) -> &[Felt] {
self.0.as_elements()
}

/// Returns the byte representation of this batch ID.
pub fn as_bytes(&self) -> [u8; 32] {
self.0.as_bytes()
}

/// Returns a big-endian, hex-encoded string.
pub fn to_hex(&self) -> String {
self.0.to_hex()
}
}

impl core::fmt::Display for BatchId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.to_hex())
}
}
12 changes: 12 additions & 0 deletions crates/miden-objects/src/batch/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,14 @@
mod note_tree;
pub use note_tree::BatchNoteTree;

mod batch_id;
pub use batch_id::BatchId;

mod account_update;
pub use account_update::BatchAccountUpdate;

mod proven_batch;
pub use proven_batch::ProvenBatch;

mod proposed_batch;
pub use proposed_batch::ProposedBatch;
5 changes: 5 additions & 0 deletions crates/miden-objects/src/batch/note_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,9 @@ impl BatchNoteTree {
pub fn root(&self) -> RpoDigest {
self.0.root()
}

/// Returns the number of non-empty leaves in this tree.
pub fn num_leaves(&self) -> usize {
self.0.num_leaves()
}
}
Loading
Loading