From d64d3cd01499792d6282b3cf9fb9c9d1493ef694 Mon Sep 17 00:00:00 2001 From: evalir Date: Mon, 11 May 2026 15:42:49 +0200 Subject: [PATCH] feat(tx-cache)!: drop target_block_number from BundleKey MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bundle GET endpoint in tx-pool-webservice is permissioned per-slot, and a slot maps 1:1 to a rollup block — so the target block is fully determined by the caller's slot permission, server-side. Carrying it in the cursor was at best redundant and at worst a client-controlled partition selector that bypassed the slot scoping. Drops the field from the cursor wire format. The server is now the sole source of the partition key for the GSI query. Breaking change for consumers paginating /bundles: the cursor returned by tx-pool-webservice no longer includes targetBlockNumber. Co-Authored-By: Claude Opus 4.7 (1M context) --- crates/tx-cache/src/types.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/tx-cache/src/types.rs b/crates/tx-cache/src/types.rs index 8fb8ce27..4bbec03a 100644 --- a/crates/tx-cache/src/types.rs +++ b/crates/tx-cache/src/types.rs @@ -419,8 +419,9 @@ pub struct TxKey { /// The query object keys for the bundle GET endpoint. /// -/// Cursor for the `block_number_index` GSI: paginates bundles for a given -/// target block in score-descending order. +/// Cursor for paginating bundles for the caller's permissioned target block +/// in score-descending order. The target block is server-derived from the +/// caller's slot permission and is not part of this cursor. #[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] #[serde(rename_all = "camelCase")] pub struct BundleKey { @@ -428,8 +429,6 @@ pub struct BundleKey { pub id: Uuid, /// The bundle score. pub score: u64, - /// The bundle's target block number. - pub target_block_number: u64, } /// The query object keys for the order GET endpoint. @@ -589,9 +588,9 @@ mod tests { let cache_response = CacheResponse::paginated( BundleList { bundles: vec![dummy_bundle_with_id(uuid)] }, - BundleKey { id: uuid, score: 100, target_block_number: 42 }, + BundleKey { id: uuid, score: 100 }, ); - let expected_json = r#"{"bundles":[{"id":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33","bundle":{"txs":[],"blockNumber":"0x0","replacementUuid":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33"}}],"nextCursor":{"id":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33","score":100,"targetBlockNumber":42}}"#; + let expected_json = r#"{"bundles":[{"id":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33","bundle":{"txs":[],"blockNumber":"0x0","replacementUuid":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33"}}],"nextCursor":{"id":"5932d4bb-58d9-41a9-851d-8dd7f04ccc33","score":100}}"#; let serialized = serde_json::to_string(&cache_response).unwrap(); assert_eq!(serialized, expected_json); let deserialized =