store: sync_account_vault and sync_account_storage_maps silently drop all updates when single block exceeds MAX_ROWS
- 主要语言
- Rust
- 星标
- 104
- 派生
- 138
- 平均合并
- 1 天 13 小时
- 30 天内合并 PR
- 56
描述
### Version
main branch, commit 597e354c (2026-08-09)
### Other packages versions
N/A store crate internal bug
### What happened?
sync_account_vault and sync_account_storage_maps silently lose data when a single block contains more vault/storage_map updates for an account than MAX_ROWS.
Vault: crates/store/src/db/models/queries/accounts.rs:556-573
Storage maps: crates/store/src/db/models/queries/accounts.rs:778-797
Current logic (vault example):
let (last_block_included, values) = if let Some(&(last_block_num, ..)) = raw.last()
&& raw.len() > MAX_ROWS
{
let values = raw
.into_iter()
.take_while(|(bn, ..)| *bn != last_block_num)
.map(AccountVaultValue::from_raw_row)
.collect::, DatabaseError>>()?;
let last_block_included = values.last().map_or(*block_range.start(), |v| v.block_num);
(last_block_included, values)
}
If ALL rows come from block_range.start() = N and the block is saturated:
- take_while(|bn| *bn != N) → empty values
- last_block_included = block_range.start() = N
- Client interprets: "Synced to N, no updates." → sets next_start = N + 1
- All vault/storage_map updates in block N are permanently lost to the client.
### What should have happened?
The function should never tell the client "you are fully synced to block N" when block N actually contains updates that were dropped due to pagination limits.
Either:
1. Return a non empty response guaranteeing progress, OR
2. Return an explicit error (e.g. BlockTooLargeToPage) so the client knows intra-block pagination is needed.
The client should never skip a block thinking it has no data.
### How can this be reproduced?
Trigger condition: >61,681 vault asset updates in a single block for a single account.
Achievable with high-throughput DeFi / NFT smart accounts if protocol batch/block limits increase.
Test that should fail on current code:
#[test]
fn supersaturated_single_block_vault_does_not_lose_data() {
// Insert MAX_ROWS + 100 vault updates for account A in block N
// Query sync_account_vault for A in range [N..]
// Must return updates AND not skip block N
}
No such test exists in tests.rs today for the all-from-same-block saturation case.
### Relevant log output
```shell
// No runtime log this is a silent data loss bug.
// The buggy path returns Ok((N, [])) which looks like a valid "no updates" response.
```
贡献指南
评估
这个 Issue 还没有评估数据。