Skip to content

feat: faster lookups and batch note requests#1387

Merged
mmagician merged 11 commits into
mainfrom
igamigo-sync-improvements
Oct 15, 2025
Merged

feat: faster lookups and batch note requests#1387
mmagician merged 11 commits into
mainfrom
igamigo-sync-improvements

Conversation

@igamigo

@igamigo igamigo commented Oct 9, 2025

Copy link
Copy Markdown
Collaborator

No description provided.

Comment on lines 150 to +159
loop {
if !self
.sync_state_step(
&mut state_sync_update,
&mut current_partial_mmr,
&accounts,
note_tags.clone(),
)
.await?
{
let step = self
.sync_state_step(state_sync_update.block_num, &account_ids, note_tags.clone())
.await?;
let Some(step) = step else {
break;
};
state_sync_update.block_num = step.block_header.block_num();
state_sync_steps.push(step);
}

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.

Most of the code in this file is the same but rearranged:

  • Before, we'd do a call to sync_state which would return a set of new committed notes some of which could be public (and not currently tracked by the client), so a call to get_notes_by_id would be done subsequently
  • Now, all calls to sync_state are done down to the chain tip and then all public notes requests are batched into a single get_notes_by_id call

Comment on lines +51 to +53
"{QUERY} WHERE tx.status_variant IN ({}, {})",
TransactionStatusVariant::Pending as u8,
TransactionStatusVariant::Discarded as u8

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 makes the query hit the index

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.

good catch

Comment on lines +14 to +16
CREATE TABLE IF NOT EXISTS tracked_accounts (
id TEXT NOT NULL PRIMARY KEY
);

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 added for faster lookups. Selecting distinct account IDs still does a full table scan which means scanning through 35K rows, even with the index. We could use the settings table for this but it's not present in the 0.11 versions

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.

Selecting distinct account IDs still does a full table scan

You mean selecting unique account ids from the accounts table, right?

I don't have the full context on the problem, but an alternative idea would be to create an index on account id (and potentially nonce?):

CREATE INDEX idx_accounts_id_nonce ON accounts(id, nonce DESC);

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 what I meant with my comment above. Even with that same index (which already exists BTW), the query scans the same amount of rows (although it does not touch the table because the index covers it). There is also concrete difference in the flamegraph when benchmarking this. I can pull up an example if you are interested later since it would require setting it up.
An equivalent alternative could be to add something like is_latest_state and do a partial index (WHERE is_latest_state=1), but not sure we prefer it.

Comment thread crates/rust-client/src/sync/state_sync.rs Outdated
/// Applies the state sync update to the store.
///
/// See [`crate::Store::apply_state_sync()`] for what the update implies.
pub async fn apply_state_sync(&mut self, update: StateSyncUpdate) -> Result<(), ClientError> {

@igamigo igamigo Oct 9, 2025

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.

Made this public function so that users can easily apply syncs that they do manually through the StateSync component. This should help the faucet decide what it requests. For instance, we don't need to send the account ID prefix because we don't expect to receive notes from other accounts, we only care about the ones we create.

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.

If we give the users the option to apply this, we might also want to give them the tools to build what the state sync component needs to run correctly. Users can work around this by having an instance of their store though.


let return_notes = self.rpc_api.get_public_note_records(query_notes, None).await?;
let mut public_notes = BTreeMap::new();
for chunk in query_notes.chunks(1_000) {

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.

We need a better structured way of getting limits as defined by the node (#1139)

@igamigo igamigo added the no docs This PR does not require an update to documentation files label Oct 9, 2025
@igamigo
igamigo force-pushed the igamigo-sync-improvements branch from b40f3b6 to fe7615a Compare October 9, 2025 20:05
@igamigo
igamigo marked this pull request as ready for review October 9, 2025 20:23
@igamigo
igamigo requested a review from bobbinth October 9, 2025 20:23
Comment thread crates/rust-client/src/note/note_update_tracker.rs Outdated
Comment thread crates/rust-client/src/note/note_update_tracker.rs Outdated
Comment on lines +14 to +16
CREATE TABLE IF NOT EXISTS tracked_accounts (
id TEXT NOT NULL PRIMARY KEY
);

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.

Selecting distinct account IDs still does a full table scan

You mean selecting unique account ids from the accounts table, right?

I don't have the full context on the problem, but an alternative idea would be to create an index on account id (and potentially nonce?):

CREATE INDEX idx_accounts_id_nonce ON accounts(id, nonce DESC);

Comment on lines +51 to +53
"{QUERY} WHERE tx.status_variant IN ({}, {})",
TransactionStatusVariant::Pending as u8,
TransactionStatusVariant::Discarded as u8

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.

good catch

Comment thread crates/rust-client/src/sync/state_sync.rs Outdated
Comment thread crates/rust-client/src/sync/state_sync.rs
Comment thread crates/rust-client/src/sync/state_sync.rs Outdated
@igamigo
igamigo requested a review from mmagician October 14, 2025 18:42

@mmagician mmagician left a comment

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.

LGTM barring the lint (it looks like the usage of BlockUpdates::insert makes BlockUpdates::extend unused)

Comment thread CHANGELOG.md Outdated
Co-authored-by: Marti <marti@miden.team>
@igamigo

igamigo commented Oct 15, 2025

Copy link
Copy Markdown
Collaborator Author

I'm looking at improving one more thing that I should be pushing in the next few minutes.

@mmagician
mmagician merged commit 8385cbe into main Oct 15, 2025
27 checks passed
@mmagician
mmagician deleted the igamigo-sync-improvements branch October 15, 2025 18:30
fkrause98 pushed a commit that referenced this pull request Oct 24, 2025
* feat: faster lookups

* chore: lints

* reviews: logical or, add comment

* refactor: simpler inesrt function and comment

* chore: lints

* chore: add trace logs

* chore: format

* Update CHANGELOG.md

Co-authored-by: Marti <marti@miden.team>

* refactor: improve block header lookup and migration logic

* chore: lints

---------

Co-authored-by: Marti <marti@miden.team>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no docs This PR does not require an update to documentation files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants