-
Notifications
You must be signed in to change notification settings - Fork 56
feat(drive-abci, sdk)!: allow shielded-notes queries to span 4 MMR chunks #3756
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2550,7 +2550,8 @@ impl FromProof<platform::GetShieldedEncryptedNotesRequest> for ShieldedEncrypted | |||||||||||||||||||||||||
| .drive_abci | ||||||||||||||||||||||||||
| .query | ||||||||||||||||||||||||||
| .shielded_queries | ||||||||||||||||||||||||||
| .max_encrypted_notes_per_query as u32; | ||||||||||||||||||||||||||
| .max_query_chunks as u32 | ||||||||||||||||||||||||||
| * (1u32 << drive::drive::shielded::paths::SHIELDED_NOTES_CHUNK_POWER); | ||||||||||||||||||||||||||
|
Comment on lines
2550
to
+2554
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💬 Nitpick: Carried-forward (STILL VALID): verifier uses plain After the latest delta the server computes
Suggested change
source: ['claude'] |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| let (root_hash, notes) = Drive::verify_shielded_encrypted_notes( | ||||||||||||||||||||||||||
| &proof.grovedb_proof, | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,21 +40,39 @@ pub async fn sync_shielded_notes( | |
| ) -> Result<ShieldedSyncResult, Error> { | ||
| let config = config.unwrap_or_default(); | ||
|
|
||
| let chunk_size = sdk | ||
| // `mmr_chunk_size` is the on-chain MMR chunk size — the unit that | ||
| // `start_index` must align to. `fetch_size` is how many notes we | ||
| // pull per request; under `max_query_chunks=4` the server packs 4 | ||
| // MMR chunks into one proof, so each request advances by 4× the | ||
| // MMR chunk size. Decoupling the two means the SDK can opportunistically | ||
| // request larger spans without touching the on-chain tree shape. | ||
| let mmr_chunk_size: u64 = 1u64 << drive::drive::shielded::paths::SHIELDED_NOTES_CHUNK_POWER; | ||
| let max_query_chunks = sdk | ||
| .version() | ||
| .drive_abci | ||
| .query | ||
| .shielded_queries | ||
| .max_encrypted_notes_per_query as u64; | ||
|
|
||
| // Validate alignment | ||
| if chunk_size > 0 && !start_index.is_multiple_of(chunk_size) { | ||
| .max_query_chunks as u64; | ||
| let fetch_size = mmr_chunk_size | ||
| .saturating_mul(max_query_chunks) | ||
| .max(mmr_chunk_size); | ||
|
|
||
| // Validate alignment against the MMR chunk size (NOT the multi-chunk | ||
| // fetch size). The server only requires per-MMR-chunk alignment; any | ||
| // multiple of `mmr_chunk_size` is a legal start. A `start_index` | ||
| // produced by a previous sync pass will be a multiple of `fetch_size` | ||
| // (and therefore of `mmr_chunk_size`) so this check is normally a | ||
| // no-op — but a hand-built resume point could land on a non-fetch | ||
| // boundary and still be valid. | ||
| if mmr_chunk_size > 0 && !start_index.is_multiple_of(mmr_chunk_size) { | ||
| return Err(Error::Generic(format!( | ||
| "start_index {} is not chunk-aligned; must be a multiple of {}", | ||
| start_index, chunk_size | ||
| start_index, mmr_chunk_size | ||
| ))); | ||
| } | ||
|
|
||
| let chunk_size = fetch_size; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💬 Nitpick: Carried-forward (STILL VALID): redundant After the PR there are two legitimate 'chunk sizes' in this function — the MMR chunk size (alignment unit) and the per-request fetch window. The variable still named source: ['claude'] |
||
|
|
||
| let max_concurrent = config.max_concurrent.max(1); | ||
| let settings = config.request_settings; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guard
max_query_chunks > 0before derivingmax_notes.If
max_query_chunksis ever0(e.g., misconfigured/defaulted platform version),limitbecomes0, and the prove path underflows at Line 74 (start_index + limit - 1). Add an explicit non-zero validation early.Suggested fix
let max_query_chunks = platform_version .drive_abci .query .shielded_queries .max_query_chunks as u32; + if max_query_chunks == 0 { + return Ok(QueryValidationResult::new_with_error( + QueryError::InvalidArgument( + "platform version misconfigured: max_query_chunks must be greater than 0" + .to_string(), + ), + )); + } let max_notes = max_query_chunks .saturating_mul(mmr_chunk_size as u32) .min(u32::MAX);📝 Committable suggestion
🤖 Prompt for AI Agents