From a1675fb1d8bcb56f9943028ee7467b2f163761e1 Mon Sep 17 00:00:00 2001 From: Dori Medini Date: Thu, 30 Apr 2026 16:38:34 +0300 Subject: [PATCH] central_systest_blobs: sort hashsets when dumping --- Cargo.lock | 1 + crates/central_systest_blobs/Cargo.toml | 1 + .../resources/blob_file_generation | 2 +- .../resources/preconfirmed_block.json | 22 +++++----- .../src/cende_blob_regression_test.rs | 41 ++++++++++++++++--- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 63dea389115..140880ec5bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4881,6 +4881,7 @@ dependencies = [ "google-cloud-storage", "http 1.3.1", "mockall", + "serde", "serde_json", "starknet_api", "starknet_committer", diff --git a/crates/central_systest_blobs/Cargo.toml b/crates/central_systest_blobs/Cargo.toml index 3e0584f7421..e689a770e66 100644 --- a/crates/central_systest_blobs/Cargo.toml +++ b/crates/central_systest_blobs/Cargo.toml @@ -19,6 +19,7 @@ expect-test.workspace = true google-cloud-storage.workspace = true http.workspace = true mockall.workspace = true +serde.workspace = true serde_json.workspace = true starknet_api = { workspace = true, features = ["testing"] } starknet_committer = { workspace = true, features = ["testing"] } diff --git a/crates/central_systest_blobs/resources/blob_file_generation b/crates/central_systest_blobs/resources/blob_file_generation index bf0d87ab1b2..7813681f5b4 100644 --- a/crates/central_systest_blobs/resources/blob_file_generation +++ b/crates/central_systest_blobs/resources/blob_file_generation @@ -1 +1 @@ -4 \ No newline at end of file +5 \ No newline at end of file diff --git a/crates/central_systest_blobs/resources/preconfirmed_block.json b/crates/central_systest_blobs/resources/preconfirmed_block.json index 01b446a3062..67829e299b4 100644 --- a/crates/central_systest_blobs/resources/preconfirmed_block.json +++ b/crates/central_systest_blobs/resources/preconfirmed_block.json @@ -1,16 +1,12 @@ { "block_number": 0, - "round": 0, - "write_iteration": 0, "pre_confirmed_block": { - "status": "PRE_CONFIRMED", - "starknet_version": "0.14.3", "l1_da_mode": "CALLDATA", - "l1_gas_price": { + "l1_data_gas_price": { "price_in_fri": "0x1", "price_in_wei": "0x1" }, - "l1_data_gas_price": { + "l1_gas_price": { "price_in_fri": "0x1", "price_in_wei": "0x1" }, @@ -18,10 +14,14 @@ "price_in_fri": "0x1", "price_in_wei": "0x1" }, - "timestamp": 1000, "sequencer_address": "0x1000", - "transactions": [], + "starknet_version": "0.14.3", + "status": "PRE_CONFIRMED", + "timestamp": 1000, "transaction_receipts": [], - "transaction_state_diffs": [] - } -} \ No newline at end of file + "transaction_state_diffs": [], + "transactions": [] + }, + "round": 0, + "write_iteration": 0 +} diff --git a/crates/central_systest_blobs/src/cende_blob_regression_test.rs b/crates/central_systest_blobs/src/cende_blob_regression_test.rs index f126b01f5d7..3780e25b599 100644 --- a/crates/central_systest_blobs/src/cende_blob_regression_test.rs +++ b/crates/central_systest_blobs/src/cende_blob_regression_test.rs @@ -498,6 +498,38 @@ impl BlobFactory { // Blob file storage // ===================== +/// Sorts arrays of HashSet-backed fields that have non-deterministic iteration order. +/// Object keys are already deterministic because serde_json::Value uses BTreeMap. +fn normalize_set_arrays(value: &mut serde_json::Value) { + const SET_FIELDS: &[&str] = + &["accessed_blocks", "accessed_contract_addresses", "accessed_storage_keys"]; + match value { + serde_json::Value::Object(map) => { + for (key, val) in map.iter_mut() { + if SET_FIELDS.contains(&key.as_str()) { + if let serde_json::Value::Array(arr) = val { + arr.sort_by_key(|a| a.to_string()); + } + } else { + normalize_set_arrays(val); + } + } + } + serde_json::Value::Array(arr) => { + for item in arr.iter_mut() { + normalize_set_arrays(item); + } + } + _ => {} + } +} + +fn to_normalized_json(value: &impl serde::Serialize) -> String { + let mut json_value = serde_json::to_value(value).unwrap(); + normalize_set_arrays(&mut json_value); + format!("{}\n", serde_json::to_string_pretty(&json_value).unwrap()) +} + async fn gcs_client() -> Client { Client::new(ClientConfig::default().with_auth().await.expect( "Failed to create GCS client config. Did you run `gcloud auth application-default login`?", @@ -538,8 +570,8 @@ async fn fetch_raw_blobs_at_generation( } /// Pushes the blobs to GCS. -async fn bump_generation_and_store_blob_file(blobs: &[AerospikeBlob], client: &Client) { - let blobs_json = serde_json::to_string_pretty(blobs).unwrap(); +async fn bump_generation_and_store_blob_file(blobs: Vec, client: &Client) { + let blobs_json = to_normalized_json(&blobs); let next_generation = find_next_available_blobs_generation(client).await; client .upload_object( @@ -574,13 +606,12 @@ async fn test_make_data() { // TODO(Dori): create txs. let (blobs, preconfirmed_block) = blob_factory.finalize().await; expect_file![CHAIN_INFO_PATH].assert_eq(&serde_json::to_string_pretty(&chain_info).unwrap()); - expect_file![PRECONFIRMED_BLOCK_PATH] - .assert_eq(&serde_json::to_string_pretty(&preconfirmed_block).unwrap()); + expect_file![PRECONFIRMED_BLOCK_PATH].assert_eq(&to_normalized_json(&preconfirmed_block)); // Upload or download blobs depending on the fix mode. let client = gcs_client().await; if env::var("UPDATE_EXPECT").is_ok() { - bump_generation_and_store_blob_file(&blobs, &client).await; + bump_generation_and_store_blob_file(blobs, &client).await; } else { let fetched_blobs = fetch_blob_file(&client).await; assert_eq!(