Skip to content

Commit 858de21

Browse files
apollo_gateway: add mempool validations (#10436)
1 parent 857b9a3 commit 858de21

File tree

4 files changed

+49
-4
lines changed

4 files changed

+49
-4
lines changed

crates/apollo_gateway/src/gateway_test.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use apollo_mempool_types::communication::{
3232
MockMempoolClient,
3333
};
3434
use apollo_mempool_types::errors::MempoolError;
35-
use apollo_mempool_types::mempool_types::{AccountState, AddTransactionArgs};
35+
use apollo_mempool_types::mempool_types::{AccountState, AddTransactionArgs, ValidationArgs};
3636
use apollo_metrics::metrics::HistogramValue;
3737
use apollo_network_types::network_types::BroadcastedMessageMetadata;
3838
use apollo_test_utils::{get_rng, GetTestInstance};
@@ -165,6 +165,10 @@ impl MockDependencies {
165165
fn expect_add_tx(&mut self, args: AddTransactionArgsWrapper, result: MempoolClientResult<()>) {
166166
self.mock_mempool_client.expect_add_tx().once().with(eq(args)).return_once(|_| result);
167167
}
168+
169+
fn expect_validate_tx(&mut self, args: ValidationArgs, result: MempoolClientResult<()>) {
170+
self.mock_mempool_client.expect_validate_tx().once().with(eq(args)).return_once(|_| result);
171+
}
168172
}
169173

170174
fn account_contract() -> FeatureContract {
@@ -283,13 +287,16 @@ async fn setup_mock_state(
283287
tx: expected_internal_tx.clone(),
284288
account_state: AccountState { address, nonce: *input_tx.nonce() },
285289
};
290+
let validation_args = ValidationArgs::from(&mempool_add_tx_args);
286291
mock_dependencies.expect_add_tx(
287292
AddTransactionArgsWrapper {
288293
args: mempool_add_tx_args,
289294
p2p_message_metadata: p2p_message_metadata(),
290295
},
291296
expected_mempool_result,
292297
);
298+
299+
mock_dependencies.expect_validate_tx(validation_args, Ok(()))
293300
}
294301

295302
struct AddTxResults {

crates/apollo_gateway/src/stateful_transaction_validator.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use apollo_gateway_types::deprecated_gateway_error::{
88
};
99
use apollo_gateway_types::errors::GatewaySpecError;
1010
use apollo_mempool_types::communication::SharedMempoolClient;
11+
use apollo_mempool_types::mempool_types::ValidationArgs;
1112
use apollo_proc_macros::sequencer_latency_histogram;
1213
use async_trait::async_trait;
1314
use blockifier::blockifier::stateful_validator::{
@@ -165,6 +166,11 @@ impl<B: BlockifierStatefulValidatorTrait> StatefulTransactionValidator<B> {
165166
runtime: tokio::runtime::Handle,
166167
) -> StatefulTransactionValidatorResult<()> {
167168
self.validate_state_preconditions(executable_tx, account_nonce)?;
169+
runtime.block_on(validate_by_mempool(
170+
executable_tx,
171+
account_nonce,
172+
mempool_client.clone(),
173+
))?;
168174
self.run_validate_entry_point(executable_tx, account_nonce, mempool_client, runtime)?;
169175
Ok(())
170176
}
@@ -316,6 +322,19 @@ impl<B: BlockifierStatefulValidatorTrait> StatefulTransactionValidator<B> {
316322
}
317323
}
318324

325+
/// Perform transaction validation by the mempool.
326+
async fn validate_by_mempool(
327+
tx: &ExecutableTransaction,
328+
account_nonce: Nonce,
329+
mempool_client: SharedMempoolClient,
330+
) -> StatefulTransactionValidatorResult<()> {
331+
let validation_args = ValidationArgs::new(tx, account_nonce);
332+
mempool_client
333+
.validate_tx(validation_args)
334+
.await
335+
.map_err(|err| mempool_client_err_to_deprecated_gw_err(&tx.signature(), err))
336+
}
337+
319338
/// Check if validation of an invoke transaction should be skipped due to deploy_account not being
320339
/// processed yet. This feature is used to improve UX for users sending deploy_account + invoke at
321340
/// once.

crates/apollo_gateway/src/stateful_transaction_validator_test.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ async fn test_extract_state_nonce_and_run_validations(
134134
// The mempool does not have any transactions from the sender.
135135
Ok(false)
136136
});
137+
mock_mempool_client.expect_validate_tx().returning(|_| Ok(()));
137138
let mempool_client = Arc::new(mock_mempool_client);
138139
let runtime = tokio::runtime::Handle::current();
139140

@@ -347,10 +348,12 @@ async fn validate_resource_bounds(
347348
};
348349

349350
let result = tokio::task::spawn_blocking(move || {
351+
let mut mempool_client = MockMempoolClient::new();
352+
mempool_client.expect_validate_tx().returning(|_| Ok(()));
350353
stateful_validator.run_transaction_validations(
351354
&executable_tx,
352355
account_nonce,
353-
Arc::new(MockMempoolClient::new()),
356+
Arc::new(mempool_client),
354357
tokio::runtime::Handle::current(),
355358
)
356359
})
@@ -465,10 +468,12 @@ async fn run_transaction_validation_test(
465468
};
466469

467470
let result = tokio::task::spawn_blocking(move || {
471+
let mut mempool_client = MockMempoolClient::new();
472+
mempool_client.expect_validate_tx().returning(|_| Ok(()));
468473
stateful_validator.run_transaction_validations(
469474
&executable_tx,
470475
account_nonce,
471-
Arc::new(MockMempoolClient::new()),
476+
Arc::new(mempool_client),
472477
tokio::runtime::Handle::current(),
473478
)
474479
})

crates/apollo_mempool_types/src/mempool_types.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use indexmap::IndexSet;
66
use serde::{Deserialize, Serialize};
77
use starknet_api::block::GasPrice;
88
use starknet_api::core::{ContractAddress, Nonce};
9+
use starknet_api::executable_transaction::AccountTransaction;
910
use starknet_api::rpc_transaction::InternalRpcTransaction;
1011
use starknet_api::transaction::fields::Tip;
1112
use starknet_api::transaction::TransactionHash;
@@ -40,7 +41,7 @@ impl AddTransactionArgs {
4041
}
4142
}
4243

43-
#[derive(Clone, Debug, Serialize, Deserialize)]
44+
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
4445
pub struct ValidationArgs {
4546
pub address: ContractAddress,
4647
pub account_nonce: Nonce,
@@ -50,6 +51,19 @@ pub struct ValidationArgs {
5051
pub max_l2_gas_price: GasPrice,
5152
}
5253

54+
impl ValidationArgs {
55+
pub fn new(tx: &AccountTransaction, account_nonce: Nonce) -> Self {
56+
Self {
57+
address: tx.sender_address(),
58+
account_nonce,
59+
tx_hash: tx.tx_hash(),
60+
tx_nonce: tx.nonce(),
61+
tip: tx.tip(),
62+
max_l2_gas_price: tx.resource_bounds().get_l2_bounds().max_price_per_unit,
63+
}
64+
}
65+
}
66+
5367
impl From<&AddTransactionArgs> for ValidationArgs {
5468
fn from(args: &AddTransactionArgs) -> Self {
5569
Self {

0 commit comments

Comments
 (0)