From 7b452a3071f4ccfab941a9827805d0fb9273cb5e Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 3 Oct 2024 12:19:32 +0200 Subject: [PATCH 1/4] fix(pathfinder/block_hash): fix transaction commitment calculation for empty signatures Turns out our 0.13.2 transaction commitment calculation algorithm was slightly different compared to the one used by the sequencer: for transaction types that _do_ have a signature field but it's empty we are required to use `[0]` as the signature when calculating the commitment leaf value. This issue was triggered in Sepolia testnet block 218484 that contains an Invoke v1 transaction with an empty signature field. Closes: #2282 --- crates/pathfinder/src/state/block_hash.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/pathfinder/src/state/block_hash.rs b/crates/pathfinder/src/state/block_hash.rs index 85f11ee331..000a712404 100644 --- a/crates/pathfinder/src/state/block_hash.rs +++ b/crates/pathfinder/src/state/block_hash.rs @@ -677,7 +677,13 @@ fn calculate_transaction_hash_with_signature(tx: &Transaction) -> Felt { TransactionVariant::InvokeV3(tx) => tx.signature.as_slice(), TransactionVariant::DeployV0(_) | TransactionVariant::DeployV1(_) - | TransactionVariant::L1Handler(_) => &[TransactionSignatureElem::ZERO], + | TransactionVariant::L1Handler(_) => &[], + }; + + let signature = if signature.is_empty() { + &[TransactionSignatureElem::ZERO] + } else { + signature }; let mut hasher = PoseidonHasher::new(); From f2721111adaeb250d674af0a220ced00648e0b81 Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 3 Oct 2024 12:24:16 +0200 Subject: [PATCH 2/4] chore(pathfinder): add a tool for verifying that transaction commitment in the header is correct This tool can be used to validate that our change in the tx commitment computation does not break historical blocks. --- .../examples/verify_transaction_commitment.rs | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 crates/pathfinder/examples/verify_transaction_commitment.rs diff --git a/crates/pathfinder/examples/verify_transaction_commitment.rs b/crates/pathfinder/examples/verify_transaction_commitment.rs new file mode 100644 index 0000000000..018cdb47aa --- /dev/null +++ b/crates/pathfinder/examples/verify_transaction_commitment.rs @@ -0,0 +1,76 @@ +use std::num::NonZeroU32; + +use anyhow::Context; +use pathfinder_common::BlockNumber; + +/// Verify transaction hashes in a pathfinder database. +/// +/// Iterates over all blocks in the database and verifies if the computed +/// transaction hashes match values we store for the block. +/// +/// Usage: +/// `cargo run --release -p pathfinder --example verify_transaction_hashes +/// mainnet ./mainnet.sqlite 100` +fn main() -> anyhow::Result<()> { + let database_path = std::env::args().nth(1).unwrap(); + let start_block = std::env::args().nth(2).unwrap_or("0".into()); + + let start_block = start_block + .parse::() + .context("Parse start block number")?; + + let storage = pathfinder_storage::StorageBuilder::file(database_path.into()) + .migrate()? + .create_pool(NonZeroU32::new(1).unwrap()) + .unwrap(); + let mut db = storage + .connection() + .context("Opening database connection")?; + + let latest_block_number = { + let tx = db.transaction().unwrap(); + tx.block_id(pathfinder_storage::BlockId::Latest) + .context("Fetching latest block number")? + .context("Latest block number does not exist")? + .0 + }; + + println!("Verifying transaction commitments..."); + + for block_number in start_block..latest_block_number.get() { + if block_number % 10 == 0 { + println!("Block: {block_number}") + } + + let tx = db.transaction().unwrap(); + let block_id = pathfinder_storage::BlockId::Number(BlockNumber::new_or_panic(block_number)); + let header = tx + .block_header(block_id) + .context("Fetching block header")? + .context("Block header missing")?; + let transactions = tx + .transaction_data_for_block(block_id)? + .context("Transaction data missing")?; + drop(tx); + + let transactions = transactions + .into_iter() + .map(|(tx, _, _)| tx) + .collect::>(); + let computed_transaction_commitment = + pathfinder_lib::state::block_hash::calculate_transaction_commitment( + &transactions, + header.starknet_version, + )?; + + if computed_transaction_commitment != header.transaction_commitment { + println!( + "Mismatch: block {block_number}, calculated {computed_transaction_commitment}", + ); + } + } + + println!("Done."); + + Ok(()) +} From 1a9ab9d887a35aa04e2461090718202248dc30eb Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 3 Oct 2024 12:33:31 +0200 Subject: [PATCH 3/4] chore: update CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a0b7d1d01..6dbc8d4274 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ More expansive patch notes and explanations may be found in the specific [pathfi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Fixed + +- Pathfinder stops syncing Sepolia testnet at block 218484 because of a block hash mismatch. + ## [0.14.3] - 2024-09-23 ### Fixed From ac319d0c2ac6e09898548b54b8341d7d36b173fb Mon Sep 17 00:00:00 2001 From: Krisztian Kovacs Date: Thu, 3 Oct 2024 12:57:34 +0200 Subject: [PATCH 4/4] chore: bump version to 0.14.4 --- CHANGELOG.md | 2 +- Cargo.lock | 42 ++++++++++++++++++------------------- Cargo.toml | 2 +- crates/load-test/Cargo.lock | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dbc8d4274..0d259cd9a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ More expansive patch notes and explanations may be found in the specific [pathfi The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## [0.14.4] - 2024-10-03 ### Fixed diff --git a/Cargo.lock b/Cargo.lock index 07329da511..ddc24cef0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3922,7 +3922,7 @@ dependencies = [ [[package]] name = "gateway-test-utils" -version = "0.14.3" +version = "0.14.4" dependencies = [ "http 0.2.12", "reqwest", @@ -6149,7 +6149,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "p2p" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "async-stream", @@ -6190,7 +6190,7 @@ dependencies = [ [[package]] name = "p2p_proto" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "fake", @@ -6211,7 +6211,7 @@ dependencies = [ [[package]] name = "p2p_proto_derive" -version = "0.14.3" +version = "0.14.4" dependencies = [ "proc-macro2", "quote", @@ -6220,7 +6220,7 @@ dependencies = [ [[package]] name = "p2p_stream" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "async-trait", @@ -6348,7 +6348,7 @@ checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" [[package]] name = "pathfinder" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "assert_matches", @@ -6415,7 +6415,7 @@ dependencies = [ [[package]] name = "pathfinder-common" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "bitvec", @@ -6439,7 +6439,7 @@ dependencies = [ [[package]] name = "pathfinder-compiler" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "cairo-lang-starknet 1.0.0-alpha.6", @@ -6460,7 +6460,7 @@ dependencies = [ [[package]] name = "pathfinder-crypto" -version = "0.14.3" +version = "0.14.4" dependencies = [ "ark-ff", "assert_matches", @@ -6477,7 +6477,7 @@ dependencies = [ [[package]] name = "pathfinder-ethereum" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "async-trait", @@ -6497,7 +6497,7 @@ dependencies = [ [[package]] name = "pathfinder-executor" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "blockifier", @@ -6518,7 +6518,7 @@ dependencies = [ [[package]] name = "pathfinder-merkle-tree" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "bitvec", @@ -6534,7 +6534,7 @@ dependencies = [ [[package]] name = "pathfinder-retry" -version = "0.14.3" +version = "0.14.4" dependencies = [ "tokio", "tokio-retry", @@ -6542,7 +6542,7 @@ dependencies = [ [[package]] name = "pathfinder-rpc" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "assert_matches", @@ -6593,7 +6593,7 @@ dependencies = [ [[package]] name = "pathfinder-serde" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "num-bigint 0.4.5", @@ -6608,7 +6608,7 @@ dependencies = [ [[package]] name = "pathfinder-storage" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "assert_matches", @@ -8279,7 +8279,7 @@ dependencies = [ [[package]] name = "starknet-gateway-client" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "assert_matches", @@ -8314,7 +8314,7 @@ dependencies = [ [[package]] name = "starknet-gateway-test-fixtures" -version = "0.14.3" +version = "0.14.4" dependencies = [ "pathfinder-common", "pathfinder-crypto", @@ -8322,7 +8322,7 @@ dependencies = [ [[package]] name = "starknet-gateway-types" -version = "0.14.3" +version = "0.14.4" dependencies = [ "anyhow", "assert_matches", @@ -8515,7 +8515,7 @@ dependencies = [ [[package]] name = "tagged" -version = "0.14.3" +version = "0.14.4" dependencies = [ "fake", "pretty_assertions_sorted", @@ -8524,7 +8524,7 @@ dependencies = [ [[package]] name = "tagged-debug-derive" -version = "0.14.3" +version = "0.14.4" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index ac895253fd..f348ee0e20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ lto = true opt-level = 3 [workspace.package] -version = "0.14.3" +version = "0.14.4" edition = "2021" license = "MIT OR Apache-2.0" rust-version = "1.76" diff --git a/crates/load-test/Cargo.lock b/crates/load-test/Cargo.lock index c316e4d9dd..3eb7fd205d 100644 --- a/crates/load-test/Cargo.lock +++ b/crates/load-test/Cargo.lock @@ -976,7 +976,7 @@ dependencies = [ [[package]] name = "pathfinder-crypto" -version = "0.14.3" +version = "0.14.4" dependencies = [ "bitvec", "fake",