Skip to content

Commit 2a47106

Browse files
apollo_http_server: use allow new tx flag
1 parent 5906d70 commit 2a47106

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

crates/apollo_http_server/src/errors.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub enum HttpServerError {
2929
DecompressionError(#[from] CompressionError),
3030
#[error(transparent)]
3131
DeserializationError(#[from] serde_json::Error),
32+
#[error("Server is rejecting new transactions.")]
33+
DisabledError(),
3234
#[error(transparent)]
3335
GatewayClientError(#[from] Box<GatewayClientError>),
3436
}
@@ -41,6 +43,7 @@ impl IntoResponse for HttpServerError {
4143
}
4244
HttpServerError::DecompressionError(e) => compression_error_into_response(e),
4345
HttpServerError::DeserializationError(e) => serde_error_into_response(e),
46+
HttpServerError::DisabledError() => disabled_error_into_response(),
4447
HttpServerError::GatewayClientError(e) => gw_client_err_into_response(*e),
4548
}
4649
}
@@ -74,6 +77,19 @@ fn serde_error_into_response(err: serde_json::Error) -> Response {
7477
(response_code, response_body).into_response()
7578
}
7679

80+
fn disabled_error_into_response() -> Response {
81+
debug!("Server is configured to reject transactions.");
82+
let (response_code, starknet_error) = (
83+
StatusCode::SERVICE_UNAVAILABLE,
84+
StarknetError {
85+
code: StarknetErrorCode::UnknownErrorCode("Server unavailable.".to_string()),
86+
message: "Server unavailable.".to_string(),
87+
},
88+
);
89+
let response_body = serialize_error(&starknet_error);
90+
(response_code, response_body).into_response()
91+
}
92+
7793
fn gw_client_err_into_response(err: GatewayClientError) -> Response {
7894
let (response_code, deprecated_gateway_error) = match err {
7995
GatewayClientError::ClientError(e) => (

crates/apollo_http_server/src/http_server.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ async fn add_rpc_tx(
117117
Json(tx): Json<RpcTransaction>,
118118
) -> HttpServerResult<Json<GatewayOutput>> {
119119
debug!("ADD_TX_START: Http server received a new transaction.");
120+
121+
let dynamic_config = app_state.config_manager_client.get_http_server_dynamic_config().await?;
122+
check_new_transactions_are_allowed(dynamic_config.accept_new_txs)?;
123+
120124
ADDED_TRANSACTIONS_TOTAL.increment(1);
121125
add_tx_inner(app_state, headers, tx).await
122126
}
@@ -128,11 +132,12 @@ async fn add_tx(
128132
headers: HeaderMap,
129133
tx: String,
130134
) -> HttpServerResult<Json<GatewayOutput>> {
131-
ADDED_TRANSACTIONS_TOTAL.increment(1);
132135
debug!("ADD_TX_START: Http server received a new transaction.");
133136

134137
let dynamic_config = app_state.config_manager_client.get_http_server_dynamic_config().await?;
138+
check_new_transactions_are_allowed(dynamic_config.accept_new_txs)?;
135139

140+
ADDED_TRANSACTIONS_TOTAL.increment(1);
136141
let tx: DeprecatedGatewayTransactionV3 = match serde_json::from_str(&tx) {
137142
Ok(value) => value,
138143
Err(e) => {
@@ -154,6 +159,13 @@ async fn add_tx(
154159
add_tx_inner(app_state, headers, rpc_tx).await
155160
}
156161

162+
fn check_new_transactions_are_allowed(accept_new_txs: bool) -> HttpServerResult<()> {
163+
match accept_new_txs {
164+
true => Ok(()),
165+
false => Err(HttpServerError::DisabledError()),
166+
}
167+
}
168+
157169
#[allow(clippy::result_large_err)]
158170
fn validate_supported_tx_version_str(tx: &str) -> HttpServerResult<()> {
159171
// 1. Remove all whitespace

crates/apollo_http_server/src/http_server_test.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,26 @@ async fn to_bytes(res: Response) -> Bytes {
8888
res.into_body().collect().await.unwrap().to_bytes()
8989
}
9090

91+
#[rstest]
92+
#[tokio::test]
93+
/// Test that an HTTP server with a `allow_new_txs = false` config rejects new transactions.
94+
async fn allow_new_txs() {
95+
let index = 10;
96+
let tx = rpc_invoke_tx();
97+
98+
let mock_gateway_client = MockGatewayClient::new();
99+
let mock_config_manager_client = MockConfigManagerClient::new();
100+
101+
// TODO(Yael): avoid the hardcoded node offset index, consider dynamic allocation.
102+
let http_client =
103+
add_tx_http_client(mock_config_manager_client, mock_gateway_client, 1 + index).await;
104+
105+
// Send a transaction to the server.
106+
let response = http_client.add_tx(tx.clone()).await;
107+
let status = response.status();
108+
assert!(!status.is_success(), "{status:?}");
109+
}
110+
91111
#[tokio::test]
92112
async fn error_into_response() {
93113
let error = HttpServerError::DeserializationError(

0 commit comments

Comments
 (0)