diff --git a/Cargo.lock b/Cargo.lock index 180fea022d..f6a717ceb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8455,6 +8455,7 @@ dependencies = [ "pathfinder-rpc", "pathfinder-serde", "pathfinder-storage", + "pathfinder-validator", "pathfinder-version", "pretty_assertions_sorted", "primitive-types", @@ -8871,6 +8872,32 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "pathfinder-validator" +version = "0.22.2" +dependencies = [ + "anyhow", + "assert_matches", + "p2p", + "p2p_proto", + "pathfinder-block-commitments", + "pathfinder-class-hash", + "pathfinder-common", + "pathfinder-compiler", + "pathfinder-crypto", + "pathfinder-executor", + "pathfinder-gas-price", + "pathfinder-rpc", + "pathfinder-storage", + "rayon", + "rstest", + "serde_json", + "starknet_api", + "thiserror 2.0.18", + "tokio", + "tracing", +] + [[package]] name = "pathfinder-version" version = "0.22.2" diff --git a/Cargo.toml b/Cargo.toml index bf23b42ecc..136d73992f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ members = [ "crates/tagged", "crates/tagged-debug-derive", "crates/util", + "crates/validator", "crates/version", ] exclude = ["crates/load-test", "utils/pathfinder-probe"] diff --git a/crates/pathfinder/Cargo.toml b/crates/pathfinder/Cargo.toml index 4b83ea6e45..08a2a5334b 100644 --- a/crates/pathfinder/Cargo.toml +++ b/crates/pathfinder/Cargo.toml @@ -14,7 +14,7 @@ path = "src/lib.rs" cairo-native = ["pathfinder-executor/cairo-native"] consensus-integration-tests = [] tokio-console = ["console-subscriber", "tokio/tracing"] -p2p = ["pathfinder-consensus"] +p2p = ["pathfinder-consensus", "pathfinder-validator/p2p"] [dependencies] anyhow = { workspace = true } @@ -55,6 +55,7 @@ pathfinder-retry = { path = "../retry" } pathfinder-rpc = { path = "../rpc" } pathfinder-serde = { path = "../serde" } pathfinder-storage = { path = "../storage" } +pathfinder-validator = { path = "../validator" } pathfinder-version = { path = "../version" } primitive-types = { workspace = true } rand = { workspace = true } @@ -91,6 +92,7 @@ pathfinder-compiler = { path = "../compiler" } pathfinder-executor = { path = "../executor" } pathfinder-rpc = { path = "../rpc" } pathfinder-storage = { path = "../storage", features = ["small_aggregate_filters"] } +pathfinder-validator = { path = "../validator", features = ["skip-commitment-validation"] } pretty_assertions_sorted = { workspace = true } proptest = { workspace = true } rstest = { workspace = true } diff --git a/crates/pathfinder/src/consensus.rs b/crates/pathfinder/src/consensus.rs index 390df7b4c0..0332167894 100644 --- a/crates/pathfinder/src/consensus.rs +++ b/crates/pathfinder/src/consensus.rs @@ -4,16 +4,13 @@ use p2p::consensus::Event; use pathfinder_common::{consensus_info, ChainId}; use pathfinder_gas_price::L1GasPriceProvider; use pathfinder_storage::Storage; +use pathfinder_validator::ValidatorWorkerPool; use tokio::sync::{mpsc, watch}; use crate::config::integration_testing::InjectFailureConfig; use crate::config::ConsensusConfig; -use crate::validator::ValidatorWorkerPool; use crate::SyncMessageToConsensus; -mod error; -pub use error::{ProposalError, ProposalHandlingError}; - #[cfg(feature = "p2p")] mod inner; diff --git a/crates/pathfinder/src/consensus/inner/batch_execution.rs b/crates/pathfinder/src/consensus/inner/batch_execution.rs index 796283e56c..8d4524ec8b 100644 --- a/crates/pathfinder/src/consensus/inner/batch_execution.rs +++ b/crates/pathfinder/src/consensus/inner/batch_execution.rs @@ -13,9 +13,8 @@ use p2p_proto::consensus as proto_consensus; use pathfinder_common::DecidedBlocks; use pathfinder_gas_price::{L1GasPriceProvider, L2GasPriceProvider}; use pathfinder_storage::Storage; - -use crate::consensus::ProposalHandlingError; -use crate::validator::{ +use pathfinder_validator::error::ProposalHandlingError; +use pathfinder_validator::{ should_defer_validation, TransactionExt, ValidatorStage, @@ -379,13 +378,13 @@ mod tests { use pathfinder_crypto::Felt; use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_storage::StorageBuilder; + use pathfinder_validator::{ProdTransactionMapper, ValidatorBlockInfoStage}; use super::*; use crate::consensus::inner::dummy_proposal::{ create_test_proposal_init, create_transaction_batch, }; - use crate::validator::{ProdTransactionMapper, ValidatorBlockInfoStage}; /// Creates a worker pool for tests. fn create_test_worker_pool() -> ValidatorWorkerPool { diff --git a/crates/pathfinder/src/consensus/inner/dummy_proposal.rs b/crates/pathfinder/src/consensus/inner/dummy_proposal.rs index df743d3409..2fdc3892a2 100644 --- a/crates/pathfinder/src/consensus/inner/dummy_proposal.rs +++ b/crates/pathfinder/src/consensus/inner/dummy_proposal.rs @@ -22,11 +22,11 @@ use pathfinder_consensus::Round; use pathfinder_crypto::Felt; use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_storage::Storage; +use pathfinder_validator::{ProdTransactionMapper, ValidatorBlockInfoStage}; use rand::seq::SliceRandom; use rand::{thread_rng, Rng, SeedableRng}; use crate::devnet::{self, strictly_increasing_timestamp, Account}; -use crate::validator::{ProdTransactionMapper, ValidatorBlockInfoStage}; // TODO consider waiting for the parent block to land in the decided blocks /// Blocks consensus tasks's processing loop until the parent block of height is diff --git a/crates/pathfinder/src/consensus/inner/p2p_task.rs b/crates/pathfinder/src/consensus/inner/p2p_task.rs index 785db06ded..d47db1678e 100644 --- a/crates/pathfinder/src/consensus/inner/p2p_task.rs +++ b/crates/pathfinder/src/consensus/inner/p2p_task.rs @@ -42,6 +42,15 @@ use pathfinder_consensus::{ use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_gas_price::{L1GasPriceProvider, L2GasPriceConstants, L2GasPriceProvider}; use pathfinder_storage::{Storage, Transaction, TransactionBehavior}; +use pathfinder_validator::error::{ProposalError, ProposalHandlingError}; +use pathfinder_validator::{ + should_defer_validation, + ProdTransactionMapper, + TransactionExt, + ValidatorBlockInfoStage, + ValidatorStage, + ValidatorWorkerPool, +}; use tokio::sync::{mpsc, watch}; use super::gossip_retry::{GossipHandler, GossipRetryConfig}; @@ -54,15 +63,6 @@ use crate::consensus::inner::batch_execution::{ ProposalCommitmentWithOrigin, }; use crate::consensus::inner::create_empty_block; -use crate::consensus::{ProposalError, ProposalHandlingError}; -use crate::validator::{ - should_defer_validation, - ProdTransactionMapper, - TransactionExt, - ValidatorBlockInfoStage, - ValidatorStage, - ValidatorWorkerPool, -}; use crate::SyncMessageToConsensus; #[cfg(test)] @@ -427,8 +427,6 @@ pub fn spawn( use pathfinder_common::StateCommitment; use pathfinder_merkle_tree::starknet_state::update_starknet_state; - use crate::validator; - let starknet_version = block.header.starknet_version; let state_commitment = update_starknet_state( &main_db_tx, @@ -451,12 +449,12 @@ pub fn spawn( let resp = match state_commitment { Ok(state_commitment) => { if state_commitment == block.header.state_commitment { - validator::ValidationResult::Valid + pathfinder_validator::ValidationResult::Valid } else { - validator::ValidationResult::Invalid + pathfinder_validator::ValidationResult::Invalid } } - Err(e) => validator::ValidationResult::Error(e), + Err(e) => pathfinder_validator::ValidationResult::Error(e), }; reply @@ -1593,13 +1591,13 @@ mod tests { use pathfinder_crypto::Felt; use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_storage::StorageBuilder; + use pathfinder_validator::ValidatorWorkerPool; use super::*; use crate::consensus::inner::dummy_proposal::{ create_with_invalid_l1_handler_transactions, ProposalCreationConfig, }; - use crate::validator::ValidatorWorkerPool; /// Creates a worker pool for tests. fn create_test_worker_pool() -> ValidatorWorkerPool { diff --git a/crates/pathfinder/src/consensus/inner/p2p_task/p2p_task_tests.rs b/crates/pathfinder/src/consensus/inner/p2p_task/p2p_task_tests.rs index 4ed523031c..7481d78e7e 100644 --- a/crates/pathfinder/src/consensus/inner/p2p_task/p2p_task_tests.rs +++ b/crates/pathfinder/src/consensus/inner/p2p_task/p2p_task_tests.rs @@ -26,6 +26,7 @@ use pathfinder_common::{ use pathfinder_consensus::ConsensusCommand; use pathfinder_crypto::Felt; use pathfinder_storage::{Storage, StorageBuilder}; +use pathfinder_validator::ValidatorWorkerPool; use tokio::sync::{mpsc, watch}; use tokio::time::error::Elapsed; use tokio::time::timeout; @@ -41,7 +42,6 @@ use crate::consensus::inner::{ P2PTaskConfig, P2PTaskEvent, }; -use crate::validator::ValidatorWorkerPool; use crate::SyncMessageToConsensus; /// Helper struct to setup and manage the test environment (databases, diff --git a/crates/pathfinder/src/consensus/inner/proposal_validator.rs b/crates/pathfinder/src/consensus/inner/proposal_validator.rs index 222ce0478e..067dc7fa1e 100644 --- a/crates/pathfinder/src/consensus/inner/proposal_validator.rs +++ b/crates/pathfinder/src/consensus/inner/proposal_validator.rs @@ -1,8 +1,7 @@ use p2p::consensus::HeightAndRound; use p2p_proto::consensus::{ProposalInit, ProposalPart}; use pathfinder_common::ContractAddress; - -use crate::consensus::{ProposalError, ProposalHandlingError}; +use pathfinder_validator::error::{ProposalError, ProposalHandlingError}; /// Validates the structure of incoming proposal parts and stores them. /// diff --git a/crates/pathfinder/src/devnet.rs b/crates/pathfinder/src/devnet.rs index 7aed0ee571..f15db4fbff 100644 --- a/crates/pathfinder/src/devnet.rs +++ b/crates/pathfinder/src/devnet.rs @@ -47,17 +47,17 @@ use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_merkle_tree::starknet_state::update_starknet_state; use pathfinder_storage::pruning::BlockchainHistoryMode; use pathfinder_storage::{Storage, StorageBuilder, TriePruneMode}; - -pub use crate::devnet::account::Account; -use crate::devnet::class::{preprocess_sierra, PrepocessedSierra}; -use crate::devnet::fixtures::RESOURCE_BOUNDS; -use crate::validator::{ +use pathfinder_validator::{ ProdTransactionMapper, ValidatorBlockInfoStage, ValidatorTransactionBatchStage, ValidatorWorkerPool, }; +pub use crate::devnet::account::Account; +use crate::devnet::class::{preprocess_sierra, PrepocessedSierra}; +use crate::devnet::fixtures::RESOURCE_BOUNDS; + mod account; mod class; mod contract; @@ -440,11 +440,11 @@ pub mod tests { use pathfinder_executor::{ConcurrentStateReader, ExecutorWorkerPool}; use pathfinder_merkle_tree::starknet_state::update_starknet_state; use pathfinder_storage::{Storage, StorageBuilder}; + use pathfinder_validator::{ProdTransactionMapper, ValidatorWorkerPool}; use tempfile::TempDir; use crate::devnet::account::Account; use crate::devnet::{fixtures, init_db, init_proposal_and_validator, BootDb}; - use crate::validator::{ProdTransactionMapper, ValidatorWorkerPool}; #[test_log::test] fn init_declare_deploy_invoke_hello_abi() { diff --git a/crates/pathfinder/src/lib.rs b/crates/pathfinder/src/lib.rs index e0059ac4fd..a0a6a18542 100644 --- a/crates/pathfinder/src/lib.rs +++ b/crates/pathfinder/src/lib.rs @@ -7,8 +7,6 @@ pub mod monitoring; pub mod p2p_network; pub mod state; pub mod sync; -pub mod validator; - pub enum SyncMessageToConsensus { /// Ask consensus for the finalized and **decided upon** block with given /// number. The only difference from a committed block is that the state @@ -37,4 +35,4 @@ pub enum SyncMessageToConsensus { pub type ConsensusFinalizedBlockReply = tokio::sync::oneshot::Sender>>; -pub type ValidateBlockReply = tokio::sync::oneshot::Sender; +pub type ValidateBlockReply = tokio::sync::oneshot::Sender; diff --git a/crates/validator/Cargo.toml b/crates/validator/Cargo.toml new file mode 100644 index 0000000000..ee56e9b9ba --- /dev/null +++ b/crates/validator/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "pathfinder-validator" +version = { workspace = true } +authors = { workspace = true } +edition = { workspace = true } +license = { workspace = true } +rust-version = { workspace = true } + +[features] +p2p = [] +skip-commitment-validation = [] + +[dependencies] +anyhow = { workspace = true } +p2p = { path = "../p2p" } +p2p_proto = { path = "../p2p_proto" } +pathfinder-block-commitments = { path = "../block-commitments" } +pathfinder-class-hash = { path = "../class-hash" } +pathfinder-common = { path = "../common" } +pathfinder-compiler = { path = "../compiler" } +pathfinder-executor = { path = "../executor" } +pathfinder-gas-price = { path = "../gas-price" } +pathfinder-rpc = { path = "../rpc" } +pathfinder-storage = { path = "../storage" } +rayon = { workspace = true } +serde_json = { workspace = true } +starknet_api = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } + +[dev-dependencies] +assert_matches = { workspace = true } +pathfinder-common = { path = "../common", features = ["full-serde"] } +pathfinder-crypto = { path = "../crypto" } +pathfinder-executor = { path = "../executor" } +pathfinder-storage = { path = "../storage", features = ["small_aggregate_filters"] } +rstest = { workspace = true } +tokio = { workspace = true, features = ["test-util"] } diff --git a/crates/pathfinder/src/consensus/error.rs b/crates/validator/src/error.rs similarity index 99% rename from crates/pathfinder/src/consensus/error.rs rename to crates/validator/src/error.rs index 485215695c..8258811804 100644 --- a/crates/pathfinder/src/consensus/error.rs +++ b/crates/validator/src/error.rs @@ -2,7 +2,7 @@ use pathfinder_storage::StorageError; -use crate::validator::WrongValidatorStageError; +use crate::WrongValidatorStageError; /// Errors that can occur when handling incoming proposal parts. /// diff --git a/crates/pathfinder/src/validator.rs b/crates/validator/src/lib.rs similarity index 99% rename from crates/pathfinder/src/validator.rs rename to crates/validator/src/lib.rs index f92ccdc15c..6084e14466 100644 --- a/crates/pathfinder/src/validator.rs +++ b/crates/validator/src/lib.rs @@ -73,7 +73,9 @@ use pathfinder_gas_price::{ L2GasPriceValidationResult, }; -use crate::consensus::ProposalHandlingError; +pub mod error; + +use crate::error::ProposalHandlingError; /// TODO: Use this type as validation result. pub enum ValidationResult { @@ -275,7 +277,7 @@ impl ValidatorBlockInfoStage { /// /// Used only for testing and dummy proposal creation. #[cfg(any(test, feature = "p2p"))] - pub(crate) fn skip_validation( + pub fn skip_validation( self, block_info: BlockInfo, main_storage: Storage, @@ -767,7 +769,7 @@ impl ValidatorTransactionBatchStage { // Skip commitment validation in tests when using dummy commitment (ZERO) // This allows e2e tests to focus on batch execution logic without commitment // complexity - #[cfg(test)] + #[cfg(any(test, feature = "skip-commitment-validation"))] if expected_proposal_commitment.0.is_zero() { return Ok(block); } @@ -1194,7 +1196,7 @@ mod tests { use rstest::rstest; use super::*; - use crate::consensus::ProposalError; + use crate::error::ProposalError; /// Creates a worker pool for tests. fn create_test_worker_pool() -> ValidatorWorkerPool {