Skip to content

Commit

Permalink
feat: add block relevance in StateSyncUpdate
Browse files Browse the repository at this point in the history
  • Loading branch information
tomyrd committed Jan 29, 2025
1 parent 8d5e93f commit e61c958
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 127 deletions.
3 changes: 1 addition & 2 deletions bin/miden-cli/src/commands/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ impl SyncCmd {
let new_details = client.sync_state().await?;

println!("State synced to block {}", new_details.block_num);
println!("New public notes: {}", new_details.received_notes.len());
println!("Tracked notes updated: {}", new_details.committed_notes.len());
println!("Committed notes: {}", new_details.committed_notes.len());
println!("Tracked notes consumed: {}", new_details.consumed_notes.len());
println!("Tracked accounts updated: {}", new_details.updated_accounts.len());
println!("Locked accounts: {}", new_details.locked_accounts.len());
Expand Down
10 changes: 1 addition & 9 deletions crates/rust-client/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,15 +327,7 @@ pub trait Store: Send + Sync {
/// locally does not match the `StateSyncUpdate` information, the account may be locked.
/// - Storing new MMR authentication nodes.
/// - Updating the tracked public accounts.
///
/// A [StateSyncUpdate] corresponds to an update from a single `SyncState` RPC call. For the
/// client to be up to date against the current chain tip, multiple calls may be performed, and
/// so multiple store updates could happen sequentially.
async fn apply_state_sync_step(
&self,
state_sync_update: StateSyncUpdate,
new_block_has_relevant_notes: bool,
) -> Result<(), StoreError>;
async fn apply_state_sync(&self, state_sync_update: StateSyncUpdate) -> Result<(), StoreError>;
}

// CHAIN MMR NODE FILTER
Expand Down
8 changes: 2 additions & 6 deletions crates/rust-client/src/store/sqlite_store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,13 +144,9 @@ impl Store for SqliteStore {
self.interact_with_connection(SqliteStore::get_sync_height).await
}

async fn apply_state_sync_step(
&self,
state_sync_update: StateSyncUpdate,
block_has_relevant_notes: bool,
) -> Result<(), StoreError> {
async fn apply_state_sync(&self, state_sync_update: StateSyncUpdate) -> Result<(), StoreError> {
self.interact_with_connection(move |conn| {
SqliteStore::apply_state_sync_step(conn, state_sync_update, block_has_relevant_notes)
SqliteStore::apply_state_sync(conn, state_sync_update)
})
.await
}
Expand Down
23 changes: 9 additions & 14 deletions crates/rust-client/src/store/sqlite_store/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ impl SqliteStore {
.expect("state sync block number exists")
}

pub(super) fn apply_state_sync_step(
pub(super) fn apply_state_sync(
conn: &mut Connection,
state_sync_update: StateSyncUpdate,
_block_has_relevant_notes: bool,
) -> Result<(), StoreError> {
let StateSyncUpdate {
block_headers,
block_num,
block_updates,
note_updates,
transaction_updates,
account_updates,
Expand All @@ -123,25 +123,20 @@ impl SqliteStore {

// Update state sync block number
const BLOCK_NUMBER_QUERY: &str = "UPDATE state_sync SET block_num = ?";
if let Some(max_block_num) =
block_headers.iter().map(|(header, ..)| header.block_num().as_u32()).max()
{
tx.execute(BLOCK_NUMBER_QUERY, params![max_block_num as i64])?;
}
tx.execute(BLOCK_NUMBER_QUERY, params![block_num.as_u64() as i64])?;

for (block_header, block_has_relevant_notes, new_mmr_peaks, new_authentication_nodes) in
block_headers
{
for (block_header, block_has_relevant_notes, new_mmr_peaks) in block_updates.block_headers {
Self::insert_block_header_tx(
&tx,
block_header,
new_mmr_peaks,
block_has_relevant_notes,
)?;

// Insert new authentication nodes (inner nodes of the PartialMmr)
Self::insert_chain_mmr_nodes_tx(&tx, &new_authentication_nodes)?;
}

// Insert new authentication nodes (inner nodes of the PartialMmr)
Self::insert_chain_mmr_nodes_tx(&tx, &block_updates.new_authentication_nodes)?;

// Update notes
apply_note_updates_tx(&tx, &note_updates)?;

Expand Down
42 changes: 13 additions & 29 deletions crates/rust-client/src/sync/block_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ use miden_objects::{
};
use tracing::warn;

use super::NoteUpdates;
use crate::{
note::NoteScreener,
store::{ChainMmrNodeFilter, NoteFilter, StoreError},
Client, ClientError,
};

#[derive(Debug, Clone, Default)]
pub struct BlockUpdates {
pub block_headers: Vec<(BlockHeader, bool, MmrPeaks)>,
pub new_authentication_nodes: Vec<(InOrderIndex, Digest)>,
}

impl BlockUpdates {
pub fn extend(&mut self, other: BlockUpdates) {
self.block_headers.extend(other.block_headers);
self.new_authentication_nodes.extend(other.new_authentication_nodes);
}
}

/// Network information management methods.
impl<R: FeltRng> Client<R> {
/// Updates committed notes with no MMR data. These could be notes that were
Expand Down Expand Up @@ -73,33 +84,6 @@ impl<R: FeltRng> Client<R> {
// HELPERS
// --------------------------------------------------------------------------------------------

/// Checks the relevance of the block by verifying if any of the input notes in the block are
/// relevant to the client. If any of the notes are relevant, the function returns `true`.
pub(crate) async fn check_block_relevance(
&self,
note_updates: &NoteUpdates,
) -> Result<bool, ClientError> {
// We'll only do the check for either incoming public notes or expected input notes as
// output notes are not really candidates to be consumed here.

let note_screener = NoteScreener::new(self.store.clone());

// Find all relevant Input Notes using the note checker
for input_note in note_updates.committed_input_notes() {
// TODO: Map the below error into a better representation (ie, we expected to be able
// to convert here)
if !note_screener
.check_relevance(&input_note.try_into().map_err(ClientError::NoteRecordError)?)
.await?
.is_empty()
{
return Ok(true);
}
}

Ok(false)
}

/// Builds the current store view of the chain's [PartialMmr]. Because we want to add all new
/// authentication nodes that could come from applying the MMR updates, we need to track all
/// known leaves thus far.
Expand Down
42 changes: 25 additions & 17 deletions crates/rust-client/src/sync/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
//! let sync_summary: SyncSummary = client.sync_state().await?;
//!
//! println!("Synced up to block number: {}", sync_summary.block_num);
//! println!("Received notes: {}", sync_summary.received_notes.len());
//! println!("Committed notes: {}", sync_summary.committed_notes.len());
//! println!("Consumed notes: {}", sync_summary.consumed_notes.len());
//! println!("Updated accounts: {}", sync_summary.updated_accounts.len());
Expand Down Expand Up @@ -66,7 +65,7 @@ use miden_objects::{
transaction::TransactionId,
};

use crate::{note::NoteUpdates, Client, ClientError};
use crate::{Client, ClientError};

mod block_header;

Expand All @@ -75,17 +74,15 @@ pub use tag::{NoteTagRecord, NoteTagSource};

mod state_sync;
pub use state_sync::{
on_note_received, on_nullifier_received, on_transaction_committed, OnNoteReceived,
OnNullifierReceived, OnTransactionCommitted, StateSync, StateSyncUpdate, SyncStatus,
on_block_received, on_note_received, on_nullifier_received, on_transaction_committed,
OnNoteReceived, OnNullifierReceived, OnTransactionCommitted, StateSync, StateSyncUpdate,
};

/// Contains stats about the sync operation.
pub struct SyncSummary {
/// Block number up to which the client has been synced.
pub block_num: BlockNumber,
/// IDs of new notes received.
pub received_notes: Vec<NoteId>,
/// IDs of tracked notes that received inclusion proofs.
/// IDs of notes that have been committed.
pub committed_notes: Vec<NoteId>,
/// IDs of notes that have been consumed.
pub consumed_notes: Vec<NoteId>,
Expand All @@ -100,7 +97,6 @@ pub struct SyncSummary {
impl SyncSummary {
pub fn new(
block_num: BlockNumber,
received_notes: Vec<NoteId>,
committed_notes: Vec<NoteId>,
consumed_notes: Vec<NoteId>,
updated_accounts: Vec<AccountId>,
Expand All @@ -109,7 +105,6 @@ impl SyncSummary {
) -> Self {
Self {
block_num,
received_notes,
committed_notes,
consumed_notes,
updated_accounts,
Expand All @@ -121,7 +116,6 @@ impl SyncSummary {
pub fn new_empty(block_num: BlockNumber) -> Self {
Self {
block_num,
received_notes: vec![],
committed_notes: vec![],
consumed_notes: vec![],
updated_accounts: vec![],
Expand All @@ -131,16 +125,14 @@ impl SyncSummary {
}

pub fn is_empty(&self) -> bool {
self.received_notes.is_empty()
&& self.committed_notes.is_empty()
self.committed_notes.is_empty()
&& self.consumed_notes.is_empty()
&& self.updated_accounts.is_empty()
&& self.locked_accounts.is_empty()
}

pub fn combine_with(&mut self, mut other: Self) {
self.block_num = max(self.block_num, other.block_num);
self.received_notes.append(&mut other.received_notes);
self.committed_notes.append(&mut other.committed_notes);
self.consumed_notes.append(&mut other.consumed_notes);
self.updated_accounts.append(&mut other.updated_accounts);
Expand Down Expand Up @@ -219,6 +211,25 @@ impl<R: FeltRng> Client<R> {
))
}
}),
Box::new({
let store_clone = self.store.clone();
move |new_block_header,
note_updates,
current_block_header,
current_block_has_relevant_notes,
current_partial_mmr,
mmr_delta| {
Box::pin(on_block_received(
store_clone.clone(),
new_block_header,
note_updates,
current_block_header,
current_block_has_relevant_notes,
current_partial_mmr,
mmr_delta,
))
}
}),
);

// Get current state of the client
Expand Down Expand Up @@ -256,12 +267,9 @@ impl<R: FeltRng> Client<R> {

let sync_summary: SyncSummary = (&state_sync_update).into();

let has_relevant_notes =
self.check_block_relevance(&state_sync_update.note_updates).await?;

// Apply received and computed updates to the store
self.store
.apply_state_sync_step(state_sync_update, has_relevant_notes)
.apply_state_sync(state_sync_update)
.await
.map_err(ClientError::StoreError)?;

Expand Down
Loading

0 comments on commit e61c958

Please sign in to comment.