diff --git a/rpc/src/module/indexer.rs b/rpc/src/module/indexer.rs index 68ac3cab59..6f2eacf093 100644 --- a/rpc/src/module/indexer.rs +++ b/rpc/src/module/indexer.rs @@ -66,6 +66,24 @@ pub trait IndexerRpc { /// * limit: result size limit /// * after: pagination parameter, optional /// + /// ## Ordering + /// + /// Results are ordered by the RocksDB key, which has the structure: + /// `[Script (code_hash + hash_type + args)] + [BlockNumber] + [TxIndex] + [OutputIndex]` + /// + /// This means cells are primarily sorted by script, then by block number within each script. + /// When using prefix search mode with the same code_hash and hash_type, cells with different + /// args values will be sorted by args lexicographically, NOT by block number. + /// + /// **Important**: If you're scanning cells with variable args (e.g., using prefix search), + /// new cells created in later blocks may appear before your cursor if their args are + /// lexicographically smaller, potentially causing you to miss them in subsequent scans. + /// + /// For wallet implementations that need to track all cells in block order, consider: + /// - Using the Rich Indexer instead (which sorts by insertion order) + /// - Periodically rescanning from the beginning + /// - Using block_range filters to limit the scope of each scan + /// /// ## Returns /// /// If the number of objects is less than the requested `limit`, it indicates that these are the last page of get_cells. diff --git a/rpc/src/module/rich_indexer.rs b/rpc/src/module/rich_indexer.rs index c649d3d0ba..d228ea2ca3 100644 --- a/rpc/src/module/rich_indexer.rs +++ b/rpc/src/module/rich_indexer.rs @@ -26,7 +26,26 @@ pub trait RichIndexerRpc { /// Returns the live cells collection by the lock or type script. /// - /// The difference from the original CKB Indexer is that the `script_search_mode` parameter accepts the `partial` enumeration value. This implies that a partial search can be conducted on the `args` of the `script`. + /// ## Differences from CKB Indexer + /// + /// 1. **Partial search support**: The `script_search_mode` parameter accepts the `partial` enumeration value, + /// allowing partial search on the `args` of the `script`. + /// + /// 2. **Ordering mechanism**: Unlike CKB Indexer which sorts by RocksDB key structure + /// `[Script] + [BlockNumber] + [TxIndex] + [OutputIndex]`, Rich Indexer sorts results by an + /// auto-incrementing database primary key (`output.id`). + /// + /// **Key advantages over CKB Indexer**: + /// - Cells are returned in insertion order, which corresponds to block order + /// `(block_number, tx_index, output_index)` since blocks are indexed sequentially + /// - When using prefix search with variable args, new cells will NEVER appear before your cursor, + /// preventing missed cells in incremental scans (CKB Indexer sorts by script args lexicographically, + /// which can cause newer cells with smaller args to appear before older cursors) + /// - More resilient to chain reorganizations: During reorg, affected blocks are rolled back in reverse + /// order and re-indexed in forward order, maintaining block_number ordering. Reorged cells get new IDs + /// after the cursor, ensuring they won't be missed. (CKB Indexer may skip reorged cells if their + /// RocksDB keys fall before the cursor due to args ordering) + /// - Better suited for wallet implementations that need reliable, sequential cell tracking /// /// ## Params ///