Skip to content
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ad707df
wip draft
Mirko-von-Leipzig Sep 18, 2024
555117a
end of day
Mirko-von-Leipzig Sep 18, 2024
15d2430
Final form (pfft probably not)
Mirko-von-Leipzig Sep 19, 2024
256c339
fmt
Mirko-von-Leipzig Sep 19, 2024
3eae7f1
Missing update of parent batch
Mirko-von-Leipzig Sep 19, 2024
e9eee63
Rename module tx_pool to pool.
Mirko-von-Leipzig Sep 20, 2024
838da64
Rename to Mempool so that tx pool becomes available
Mirko-von-Leipzig Sep 20, 2024
9d28bbf
Rename pool to mempool module
Mirko-von-Leipzig Sep 20, 2024
a8601f2
wip transaction graph
Mirko-von-Leipzig Sep 20, 2024
27c5c5a
Use batch graph
Mirko-von-Leipzig Sep 25, 2024
b80d017
Rename file
Mirko-von-Leipzig Sep 25, 2024
069b5e1
Improve staleness book keeping
Mirko-von-Leipzig Sep 25, 2024
ecdaf8f
Example block producer usage
Mirko-von-Leipzig Sep 25, 2024
3553007
Incomplete batch producer impl
Mirko-von-Leipzig Sep 25, 2024
b19957a
fmt
Mirko-von-Leipzig Sep 25, 2024
7063823
Naming
Mirko-von-Leipzig Sep 25, 2024
924e7b1
Fix stray tick
Mirko-von-Leipzig Sep 26, 2024
c80a19d
Batch job now uses transactions, notes still missing.
Mirko-von-Leipzig Sep 26, 2024
b5eb7be
Rename BatchId -> BatchJobId to distinguish with batch hash
Mirko-von-Leipzig Sep 26, 2024
027dd30
Improve submit transaction error handling.
Mirko-von-Leipzig Oct 1, 2024
f029b2f
Add basic block builder
Mirko-von-Leipzig Oct 1, 2024
76c9912
Only allow a single inflight block
Mirko-von-Leipzig Oct 1, 2024
474704e
Implement block failure.
Mirko-von-Leipzig Oct 1, 2024
5476f22
Move limits into mempool
Mirko-von-Leipzig Oct 1, 2024
e65cf53
Refactor account state to allow committed state.
Mirko-von-Leipzig Oct 2, 2024
2cdabbc
Remove outdated comment about unsupported multiple-in-lfight txs
Mirko-von-Leipzig Oct 3, 2024
2479db3
Revert to usings IDs only
Mirko-von-Leipzig Oct 4, 2024
acbfa64
Only select independent batches for a block
Mirko-von-Leipzig Oct 4, 2024
b6590c5
Support nullifiers in state
Mirko-von-Leipzig Oct 4, 2024
5008fdd
Rename state module to inflight_state
Mirko-von-Leipzig Oct 4, 2024
b0645d3
Move error to error module
Mirko-von-Leipzig Oct 4, 2024
7957553
Move state diff to state module
Mirko-von-Leipzig Oct 4, 2024
349685c
Minor rewording
Mirko-von-Leipzig Oct 4, 2024
45627f3
fmt
Mirko-von-Leipzig Oct 4, 2024
4ba9f24
Leave tx proof verification to the rpc component
Mirko-von-Leipzig Oct 7, 2024
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
3 changes: 1 addition & 2 deletions crates/block-producer/src/batch_builder/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ pub type BatchId = Blake3Digest<32>;
// TRANSACTION BATCH
// ================================================================================================

/// A batch of transactions that share a common proof. For any given account, at most 1 transaction
/// in the batch must be addressing that account (issue: #186).
/// A batch of transactions that share a common proof.
///
/// Note: Until recursive proofs are available in the Miden VM, we don't include the common proof.
#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down
100 changes: 94 additions & 6 deletions crates/block-producer/src/batch_builder/mod.rs
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just an example; more scrutiny should be applied when we fill in the details.

Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use std::{cmp::min, collections::BTreeSet, sync::Arc, time::Duration};

use async_trait::async_trait;
use miden_objects::{notes::NoteId, transaction::OutputNote};
use tokio::time;
use std::{cmp::min, collections::BTreeSet, num::NonZeroUsize, sync::Arc, time::Duration};

use miden_objects::{
notes::NoteId,
transaction::{OutputNote, TransactionId},
};
use tokio::{sync::Mutex, time};
use tonic::async_trait;
use tracing::{debug, info, instrument, Span};

use crate::{block_builder::BlockBuilder, ProvenTransaction, SharedRwVec, COMPONENT};
use crate::{
block_builder::BlockBuilder,
mempool::{BatchJobId, Mempool},
ProvenTransaction, SharedRwVec, COMPONENT,
};

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -206,3 +213,84 @@ where
Ok(())
}
}

pub struct BatchProducer {
pub batch_interval: Duration,
pub workers: NonZeroUsize,
pub mempool: Arc<Mutex<Mempool>>,
pub tx_per_batch: usize,
}

type BatchResult = Result<BatchJobId, (BatchJobId, BuildBatchError)>;

/// Wrapper around tokio's JoinSet that remains pending if the set is empty,
/// instead of returning None.
struct WorkerPool(tokio::task::JoinSet<BatchResult>);

impl WorkerPool {
async fn join_next(&mut self) -> Result<BatchResult, tokio::task::JoinError> {
if self.0.is_empty() {
std::future::pending().await
} else {
// Cannot be None as its not empty.
self.0.join_next().await.unwrap()
}
}

fn len(&self) -> usize {
self.0.len()
}

fn spawn(&mut self, id: BatchJobId, transactions: Vec<TransactionId>) {
self.0.spawn(async move {
todo!("Do actual work like aggregating transaction data");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to the above comment: batch building could also take 3 - 5 seconds. Let's artificially simulate this for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was wondering if we should also simulate failures. So something like sleep a random period, and then randomly fail a batch every now and then.

If we do want this, the failure rate should probably be a configurable parameter. Similar for the entire block.

Though this might annoy users if this causes a user tx to expire. And could look bad ito throughput; though I don't think that's an issue right now (?).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is configurable and not too difficult to add, I don't mind doing it.

});
}
}

impl BatchProducer {
pub async fn run(self) {
let mut interval = tokio::time::interval(self.batch_interval);
interval.set_missed_tick_behavior(time::MissedTickBehavior::Delay);

let mut inflight = WorkerPool(tokio::task::JoinSet::new());

loop {
tokio::select! {
_ = interval.tick() => {
if inflight.len() >= self.workers.get() {
tracing::info!("All batch workers occupied.");
continue;
}

// Transactions available?
let Some((batch_id, transactions)) =
self.mempool.lock().await.select_batch()
else {
tracing::info!("No transactions available for batch.");
continue;
};

inflight.spawn(batch_id, transactions);
},
result = inflight.join_next() => {
let mut mempool = self.mempool.lock().await;
match result {
Err(err) => {
tracing::warn!(%err, "Batch job panic'd.")
// TODO: somehow embed the batch ID into the join error, though this doesn't seem possible?
// mempool.batch_failed(batch_id);
},
Ok(Err((batch_id, err))) => {
tracing::warn!(%batch_id, %err, "Batch job failed.");
mempool.batch_failed(batch_id);
},
Ok(Ok(batch_id)) => {
mempool.batch_proved(batch_id);
}
}
}
}
}
}
}
34 changes: 33 additions & 1 deletion crates/block-producer/src/block_builder/mod.rs
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an example.

Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ use miden_objects::{
notes::{NoteHeader, Nullifier},
transaction::InputNoteCommitment,
};
use tokio::sync::Mutex;
use tracing::{debug, info, instrument};

use crate::{
batch_builder::batch::TransactionBatch,
errors::BuildBlockError,
store::{ApplyBlock, Store},
mempool::{BatchJobId, Mempool},
store::{ApplyBlock, DefaultStore, Store},
COMPONENT,
};

Expand Down Expand Up @@ -143,3 +145,33 @@ where
Ok(())
}
}

struct BlockProducer {
pub mempool: Arc<Mutex<Mempool>>,
pub block_interval: tokio::time::Duration,
}

impl BlockProducer {
pub async fn run(self) {
let mut interval = tokio::time::interval(self.block_interval);
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);

loop {
interval.tick().await;

let (block_number, batches) = self.mempool.lock().await.select_block();

let result = self.build_and_commit_block(batches).await;
let mut mempool = self.mempool.lock().await;

match result {
Ok(_) => mempool.block_committed(block_number),
Err(_) => mempool.block_failed(block_number),
}
}
}

async fn build_and_commit_block(&self, batches: BTreeSet<BatchJobId>) -> Result<(), ()> {
todo!("Aggregate, prove and commit block");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will contain building the block and saving it to the store, right?

For block building, since we don't actually prove anything yet, I am thinking we could put in an artificial delay of 3 - 5 seconds to get the conditions close to the real thing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. I was also considering injecting failures randomly as mentioned here.

}
}
28 changes: 28 additions & 0 deletions crates/block-producer/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::collections::BTreeSet;

use miden_node_proto::errors::ConversionError;
use miden_node_utils::formatting::format_opt;
use miden_objects::{
Expand All @@ -9,8 +11,11 @@ use miden_objects::{
MAX_BATCHES_PER_BLOCK, MAX_INPUT_NOTES_PER_BATCH, MAX_OUTPUT_NOTES_PER_BATCH,
};
use miden_processor::ExecutionError;
use miden_tx::TransactionVerifierError;
use thiserror::Error;

use crate::mempool::BlockNumber;

// Transaction verification errors
// =================================================================================================

Expand Down Expand Up @@ -58,6 +63,29 @@ pub enum AddTransactionError {
VerificationFailed(#[from] VerifyTxError),
}

#[derive(thiserror::Error, Debug, PartialEq)]
pub enum AddTransactionErrorRework {
#[error("Transaction's initial account state {expected} did not match the current account state {current}.")]
InvalidAccountState { current: Digest, expected: Digest },
#[error("Transaction input data is stale. Required data fresher than {stale_limit} but inputs are from {input_block}.")]
StaleInputs {
input_block: BlockNumber,
stale_limit: BlockNumber,
},
#[error("Authenticated note nullifier {0} not found.")]
AuthenticatedNoteNotFound(Nullifier),
#[error("Unauthenticated note {0} not found.")]
UnauthenticatedNoteNotFound(NoteId),
#[error("Note nullifiers already consumed: {0:?}")]
NotesAlreadyConsumed(BTreeSet<Nullifier>),
#[error(transparent)]
TxInputsError(#[from] TxInputsError),
#[error(transparent)]
ProofVerificationFailed(#[from] TransactionVerifierError),
#[error("Failed to deserialize transaction: {0}.")]
DeserializationError(String),
}

// Batch building errors
// =================================================================================================

Expand Down
4 changes: 4 additions & 0 deletions crates/block-producer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// TODO: remove once block-producer rework is complete
#![allow(unused)]

use std::{sync::Arc, time::Duration};

use batch_builder::batch::TransactionBatch;
Expand All @@ -10,6 +13,7 @@ pub mod test_utils;
mod batch_builder;
mod block_builder;
mod errors;
mod mempool;
mod state_view;
mod store;
mod txqueue;
Expand Down
Loading