Skip to content

Conversation

@itamar-starkware
Copy link
Contributor

@itamar-starkware itamar-starkware commented Dec 8, 2025

Refactored the StatefulTransactionValidator to use async/await instead of spawning blocking tasks for each validation step.

What changed?

  • Removed the need to pass a runtime handle to extract_state_nonce_and_run_validations
  • Restructured the validation flow to be fully async, only using spawn_blocking for the CPU-intensive blockifier validation
  • Simplified the validator initialization by deferring the creation of the blockifier validator until needed
  • Split validation into clearer phases with run_pre_validation_checks and run_validate_entry_point
  • Removed dependency on the blockifier's block_info() method, using the gateway's block info provider instead
  • Updated tests to match the new async validation flow

Why make this change?

This refactoring improves code clarity and performance by:

  • Using async/await for most operations, reducing the number of thread context switches
  • Only using blocking tasks for CPU-intensive operations that can't be made async
  • Creating a cleaner separation between validation phases
  • Making the code more maintainable by removing unnecessary indirection through the blockifier validator

The change preserves all existing validation logic while making the code structure more straightforward and efficient.

@itamar-starkware itamar-starkware self-assigned this Dec 8, 2025
@reviewable-StarkWare
Copy link

This change is Reviewable

Copy link
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

@ArniStarkware ArniStarkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 4 files reviewed, 1 unresolved discussion (waiting on @itamar-starkware and @TzahiTaub)


crates/apollo_gateway/src/gateway.rs line 161 at r1 (raw file):

        let nonce = stateful_transaction_validator
            .extract_state_nonce_and_run_validations(&executable_tx, self.mempool_client.clone())
            .await?;

I didn't start looking at the PR yet.
I do like this interface, and it is clean and good (to say the least).

If it makes things simpler, we can:

Suggestion:

        let nonce = stateful_tx_validator_factory
            .instantiate_validator_extract_state_nonce_and_run_validations(self.state_reader_factory.clone(), &executable_tx, self.mempool_client.clone())
            .await?;

Copy link
Contributor

@ArniStarkware ArniStarkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 0 of 4 files reviewed, 1 unresolved discussion (waiting on @itamar-starkware and @TzahiTaub)


crates/apollo_gateway/src/gateway.rs line 161 at r1 (raw file):

Previously, ArniStarkware (Arnon Hod) wrote…

I didn't start looking at the PR yet.
I do like this interface, and it is clean and good (to say the least).

If it makes things simpler, we can:

For the record.

Copy link
Contributor

@ArniStarkware ArniStarkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArniStarkware reviewed 2 of 4 files at r1.
Reviewable status: 2 of 4 files reviewed, 1 unresolved discussion (waiting on @itamar-starkware and @TzahiTaub)

Copy link
Contributor

@ArniStarkware ArniStarkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 2 of 4 files reviewed, 3 unresolved discussions (waiting on @itamar-starkware and @TzahiTaub)


crates/apollo_gateway/src/stateful_transaction_validator.rs line 111 at r1 (raw file):

    // Consumed when running the CPU-heavy blockifier validation.
    state_reader_and_contract_manager:
        Option<StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>>>,

Connects to this comment

Suggestion:

    // TODO(Itamar): Fix this. The whole `StatefulTransactionValidator` is never used after `state_reader_and_contract_manager` is taken.
    // Make it non-optional and discard the instance after use.
    // Consumed when running the CPU-heavy blockifier validation.
    state_reader_and_contract_manager:
        Option<StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>>>,

crates/apollo_gateway/src/stateful_transaction_validator.rs line 113 at r1 (raw file):

        Option<StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>>>,
    gateway_fixed_block_state_reader: Box<dyn GatewayFixedBlockStateReader>,
}

Make the interface clear and safe.
(Not as important as the fields are not public.

Suggestion:

pub struct StatefulTransactionValidator {
    config: StatefulTransactionValidatorConfig,
    chain_info: ChainInfo,
    // Consumed when running the CPU-heavy blockifier validation.
    state_reader_and_contract_manager:
        Option<StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>>>,
    gateway_fixed_block_state_reader: Box<dyn GatewayFixedBlockStateReader>,
}

impl StatefulTransactionValidator {
    // Itamar - note `state_reader_and_contract_manager` is not optional.
    fn new(..., state_reader_and_contract_manager:
        StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>>, ...) -> Self {..}
    }
    
    fn take_state_reader_and_contract_manager(&mut self) -> StateReaderAndContractManager<Box<dyn GatewayStateReaderWithCompiledClasses>> {
        self.state_reader_and_contract_manager.take().expect("Validator was already consumed");
    }
}

@itamar-starkware itamar-starkware force-pushed the 12-08-apollo_gateway_make_statefultransactionvalidatortrait_async branch from 6f207af to 14dc6b0 Compare December 9, 2025 10:17
@itamar-starkware itamar-starkware force-pushed the 12-07-apollo_gateway_remove_processing_tx_block branch from bfe5849 to 1445e7c Compare December 9, 2025 10:17
Copy link
Contributor

@ArniStarkware ArniStarkware left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewable status: 1 of 4 files reviewed, 3 unresolved discussions (waiting on @itamar-starkware and @TzahiTaub)


crates/apollo_gateway/src/stateful_transaction_validator.rs line 113 at r1 (raw file):

Previously, ArniStarkware (Arnon Hod) wrote…

Make the interface clear and safe.
(Not as important as the fields are not public.

Note, both these functions are not public.

@ArniStarkware
Copy link
Contributor

crates/apollo_gateway/src/stateful_transaction_validator.rs line 306 at r2 (raw file):

    }

    async fn run_pre_validation_checks(

Document this function and/or rename it.

Suggestion:

    async fn extract_state_nonce_and_run_pre_validation_checks(

@ArniStarkware
Copy link
Contributor

crates/apollo_gateway/src/stateful_transaction_validator_test.rs line 53 at r2 (raw file):

        state_reader_and_contract_manager: None,
        gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block),
    };

Cool hack. We can now create a StatefulTransactionValidator without a state reader for testing, as the state reader is irrelevant in this context.

It does make me think that there should be a
StatefulTransactionPreValidator that would not have a state_reader_and_contract_manager...

Code quote:

    let stateful_validator = StatefulTransactionValidator {
        config: StatefulTransactionValidatorConfig::default(),
        chain_info: ChainInfo::create_for_testing(),
        state_reader_and_contract_manager: None,
        gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block),
    };

@itamar-starkware
Copy link
Contributor Author

crates/apollo_gateway/src/stateful_transaction_validator_test.rs line 352 at r1 (raw file):

    account_nonce: Nonce,
    max_allowed_nonce_gap: u32,
    expected_result_code: Result<(), StarknetErrorCode>,

offline discussion with Arni about this suggestion:

Suggestion:

expected_result_code: Result<Nonce, StarknetErrorCode>,

@itamar-starkware
Copy link
Contributor Author

crates/apollo_gateway/src/stateful_transaction_validator.rs line 306 at r2 (raw file):

Previously, ArniStarkware (Arnon Hod) wrote…

Document this function and/or rename it.

We decided to split into two functions here.
extract_state_nonce
run_pre_validation_checks

@itamar-starkware itamar-starkware force-pushed the 12-08-apollo_gateway_make_statefultransactionvalidatortrait_async branch from 14dc6b0 to 84b5660 Compare December 9, 2025 12:34
@itamar-starkware itamar-starkware force-pushed the 12-07-apollo_gateway_remove_processing_tx_block branch from 1445e7c to 16492e8 Compare December 9, 2025 12:34
@itamar-starkware itamar-starkware force-pushed the 12-08-apollo_gateway_make_statefultransactionvalidatortrait_async branch from 84b5660 to 820c1d6 Compare December 9, 2025 12:37
@itamar-starkware itamar-starkware force-pushed the 12-07-apollo_gateway_remove_processing_tx_block branch from 16492e8 to d50b76a Compare December 9, 2025 12:37
@itamar-starkware itamar-starkware force-pushed the 12-08-apollo_gateway_make_statefultransactionvalidatortrait_async branch from 820c1d6 to 7fc9b01 Compare December 9, 2025 12:49
@itamar-starkware
Copy link
Contributor Author

crates/apollo_gateway/src/stateful_transaction_validator.rs line 113 at r1 (raw file):

Previously, ArniStarkware (Arnon Hod) wrote…

Note, both these functions are not public.

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants