Skip to content

Commit 763126a

Browse files
committed
chore(sidecar): clean up RejectionError type
1 parent c2fce37 commit 763126a

File tree

5 files changed

+77
-106
lines changed

5 files changed

+77
-106
lines changed

bolt-sidecar/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,4 +116,4 @@ unnecessary_self_imports = "warn"
116116
use_self = "warn"
117117

118118
[features]
119-
keystore-tests = []
119+
keystore-tests = []

bolt-sidecar/src/api/commitments/firewall/processor.rs

Lines changed: 63 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ use crate::{
2323
api::commitments::{
2424
server::CommitmentEvent,
2525
spec::{
26-
CommitmentError, RejectionError, GET_METADATA_METHOD, GET_VERSION_METHOD,
27-
REQUEST_INCLUSION_METHOD,
26+
CommitmentError, GET_METADATA_METHOD, GET_VERSION_METHOD, REQUEST_INCLUSION_METHOD,
2827
},
2928
},
3029
common::BOLT_SIDECAR_VERSION,
@@ -279,82 +278,75 @@ impl CommitmentRequestProcessor {
279278
let rpc_url = self.url.clone();
280279

281280
trace!(?rpc_url, text, "received text message from websocket connection");
282-
// Create the channel to send and receive the commitment response
283281
let (tx, rx) = oneshot::channel();
284282

285-
let request = serde_json::from_str::<JsonRpcRequestUuid>(&text).map_err(|e| e.to_string());
286-
287-
// FIXME: still too nested, needs to be refactored.
288-
let response = match request {
289-
Err(e) => Err(e),
290-
Ok(request) => {
291-
let id = request.id;
292-
293-
match request.method.as_str() {
294-
GET_VERSION_METHOD => Ok(JsonResponse {
295-
id: Some(Value::String(id.to_string())),
296-
result: Value::String(BOLT_SIDECAR_VERSION.clone()),
297-
..Default::default()
298-
}),
299-
GET_METADATA_METHOD => Ok(JsonResponse {
300-
id: Some(Value::String(id.to_string())),
301-
result: serde_json::to_value(self.state.limits).expect("infallible"),
302-
..Default::default()
303-
}),
304-
REQUEST_INCLUSION_METHOD => {
305-
// Parse the inclusion request from the parameters
306-
let inclusion_request = serde_json::from_value::<InclusionRequest>(
307-
request.params.first().cloned().unwrap_or_default(),
308-
)
309-
.map_err(RejectionError::Json)
310-
.inspect_err(|err| error!(?err, "Failed to parse inclusion request"));
311-
312-
match inclusion_request {
313-
Err(e) => Ok(JsonResponse {
314-
id: Some(Value::String(id.to_string())),
315-
error: Some(e.into()),
316-
..Default::default()
317-
}),
318-
Ok(inclusion_request) => {
319-
let commitment_request =
320-
CommitmentRequest::Inclusion(inclusion_request);
321-
322-
let commitment_event =
323-
CommitmentEvent { request: commitment_request, response: tx };
324-
325-
if let Err(e) = self.api_events_tx.try_send(commitment_event) {
326-
error!(?e, "failed to send commitment event through channel");
327-
// NOTE: should we return an internal error to the RPC
328-
// here?
329-
return;
330-
}
331-
332-
// add the pending response to self buffer for later processing
333-
self.pending_commitment_responses
334-
.push(PendingCommitmentResponse::new(rx, id));
335-
336-
return;
337-
}
338-
}
339-
}
340-
other => Err(format!("unsupported method: {}", other)),
341-
}
283+
let request = match serde_json::from_str::<JsonRpcRequestUuid>(&text) {
284+
Ok(req) => req,
285+
Err(e) => {
286+
warn!(?e, ?rpc_url, "failed to parse JSON-RPC request");
287+
return;
342288
}
343289
};
344290

345-
match response {
346-
Ok(json_response) => {
347-
let message = Message::text(
348-
serde_json::to_string(&json_response).expect("to stringify version response"),
349-
);
291+
let id = request.id;
292+
let mut response = JsonResponse {
293+
id: Some(Value::String(id.to_string())),
294+
jsonrpc: "2.0".to_string(),
295+
..Default::default()
296+
};
350297

351-
// Push the message to the outgoing messages queue for later
352-
// processing
353-
self.outgoing_messages.push_back(message);
298+
match request.method.as_str() {
299+
GET_VERSION_METHOD => {
300+
response.result = Value::String(BOLT_SIDECAR_VERSION.clone());
301+
self.send_response(response);
354302
}
355-
Err(err) => {
356-
warn!(?err, ?rpc_url, "failed to parse JSON-RPC request");
303+
GET_METADATA_METHOD => {
304+
response.result = serde_json::to_value(self.state.limits).expect("infallible");
305+
self.send_response(response);
357306
}
358-
}
307+
REQUEST_INCLUSION_METHOD => {
308+
let Some(param) = request.params.first().cloned() else {
309+
response.error = Some(
310+
CommitmentError::InvalidParams("missing inclusion request".into()).into(),
311+
);
312+
self.send_response(response);
313+
return;
314+
};
315+
316+
let inclusion_request = match serde_json::from_value::<InclusionRequest>(param) {
317+
Ok(req) => req,
318+
Err(e) => {
319+
let msg = format!("failed to parse inclusion request: {}", e);
320+
error!(?e, "failed to parse inclusion request");
321+
response.error = Some(CommitmentError::InvalidParams(msg).into());
322+
self.send_response(response);
323+
return;
324+
}
325+
};
326+
327+
let commitment_request = CommitmentRequest::Inclusion(inclusion_request);
328+
let commitment_event =
329+
CommitmentEvent { request: commitment_request, response: tx };
330+
331+
if let Err(e) = self.api_events_tx.try_send(commitment_event) {
332+
error!(?e, "failed to send commitment event through channel");
333+
response.error = Some(CommitmentError::Internal.into());
334+
self.send_response(response);
335+
return;
336+
}
337+
338+
// Push the pending commitment response to the queue
339+
self.pending_commitment_responses.push(PendingCommitmentResponse::new(rx, id));
340+
}
341+
other => {
342+
warn!(?rpc_url, "unsupported method: {}", other);
343+
}
344+
};
345+
}
346+
347+
fn send_response(&mut self, response: JsonResponse) {
348+
let message =
349+
Message::text(serde_json::to_string(&response).expect("to stringify response"));
350+
self.outgoing_messages.push_back(message);
359351
}
360352
}

bolt-sidecar/src/api/commitments/server/handlers.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use crate::{
1616
api::commitments::{
1717
server::headers::auth_from_headers,
1818
spec::{
19-
CommitmentError, CommitmentsApi, RejectionError, GET_METADATA_METHOD,
20-
GET_VERSION_METHOD, REQUEST_INCLUSION_METHOD,
19+
CommitmentError, CommitmentsApi, GET_METADATA_METHOD, GET_VERSION_METHOD,
20+
REQUEST_INCLUSION_METHOD,
2121
},
2222
},
2323
common::BOLT_SIDECAR_VERSION,
@@ -80,12 +80,12 @@ pub async fn rpc_entrypoint(
8080
})?;
8181

8282
let Some(request_json) = payload.params.first().cloned() else {
83-
return Err(RejectionError::ValidationFailed("Bad params".to_string()).into());
83+
return Err(CommitmentError::InvalidParams("missing param".to_string()).into());
8484
};
8585

8686
// Parse the inclusion request from the parameters
8787
let mut inclusion_request = serde_json::from_value::<InclusionRequest>(request_json)
88-
.map_err(RejectionError::Json)
88+
.map_err(CommitmentError::InvalidJson)
8989
.inspect_err(|err| error!(?err, "Failed to parse inclusion request"))?;
9090

9191
debug!(?inclusion_request, "New inclusion request");

bolt-sidecar/src/api/commitments/spec.rs

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use alloy::primitives::SignatureError as AlloySignatureError;
22
use axum::{
33
body::Body,
4-
extract::rejection::JsonRejection,
54
http::{Response, StatusCode},
65
response::IntoResponse,
76
Json,
@@ -31,9 +30,6 @@ pub(super) const MAX_REQUEST_TIMEOUT: std::time::Duration = std::time::Duration:
3130
/// Error type for the commitments API.
3231
#[derive(Debug, Error)]
3332
pub enum CommitmentError {
34-
/// Request rejected.
35-
#[error("Request rejected: {0}")]
36-
Rejected(#[from] RejectionError),
3733
/// Consensus validation failed.
3834
#[error("Consensus validation error: {0}")]
3935
Consensus(#[from] ConsensusError),
@@ -63,15 +59,17 @@ pub enum CommitmentError {
6359
UnknownMethod,
6460
/// Invalid JSON.
6561
#[error(transparent)]
66-
InvalidJson(#[from] JsonRejection),
62+
InvalidJson(#[from] serde_json::Error),
63+
/// Invalid JSON-RPC request params.
64+
#[error("Invalid JSON-RPC request params: {0}")]
65+
InvalidParams(String),
6766
}
6867

6968
impl From<CommitmentError> for JsonError {
7069
fn from(err: CommitmentError) -> Self {
7170
// Reference: https://www.jsonrpc.org/specification#error_object
7271
// TODO: the custom defined ones should be clearly documented.
7372
match err {
74-
CommitmentError::Rejected(err) => err.into(),
7573
CommitmentError::Duplicate => Self::new(-32001, err.to_string()),
7674
CommitmentError::NoSignature => Self::new(-32002, err.to_string()),
7775
CommitmentError::InvalidSignature(err) => Self::new(-32003, err.to_string()),
@@ -83,6 +81,7 @@ impl From<CommitmentError> for JsonError {
8381
Self::new(-32600, format!("Invalid request: {err}"))
8482
}
8583
CommitmentError::UnknownMethod => Self::new(-32601, err.to_string()),
84+
CommitmentError::InvalidParams(err) => Self::new(-32602, err.to_string()),
8685
CommitmentError::Internal => Self::new(-32603, err.to_string()),
8786
}
8887
}
@@ -91,15 +90,15 @@ impl From<CommitmentError> for JsonError {
9190
impl From<&CommitmentError> for StatusCode {
9291
fn from(err: &CommitmentError) -> Self {
9392
match err {
94-
CommitmentError::Rejected(_)
95-
| CommitmentError::Duplicate
93+
CommitmentError::Duplicate
9694
| CommitmentError::NoSignature
9795
| CommitmentError::InvalidSignature(_)
9896
| CommitmentError::Signature(_)
9997
| CommitmentError::Consensus(_)
10098
| CommitmentError::Validation(_)
10199
| CommitmentError::MalformedHeader
102100
| CommitmentError::UnknownMethod
101+
| CommitmentError::InvalidParams(_)
103102
| CommitmentError::InvalidJson(_) => Self::BAD_REQUEST,
104103
CommitmentError::Internal => Self::INTERNAL_SERVER_ERROR,
105104
}
@@ -115,27 +114,6 @@ impl IntoResponse for CommitmentError {
115114
}
116115
}
117116

118-
/// Error indicating the rejection of a commitment request. This should
119-
/// be returned to the user.
120-
#[derive(Debug, Error)]
121-
pub enum RejectionError {
122-
/// State validation failed for this request.
123-
#[error("Validation failed: {0}")]
124-
ValidationFailed(String),
125-
/// JSON parsing error.
126-
#[error("JSON parsing error: {0}")]
127-
Json(#[from] serde_json::Error),
128-
}
129-
130-
impl From<RejectionError> for JsonError {
131-
fn from(err: RejectionError) -> Self {
132-
match err {
133-
RejectionError::ValidationFailed(err) => Self::new(-32600, err),
134-
RejectionError::Json(err) => Self::new(-32700, err.to_string()),
135-
}
136-
}
137-
}
138-
139117
/// Implements the commitments-API: <https://chainbound.github.io/bolt-docs/api/rpc>
140118
#[async_trait::async_trait]
141119
pub trait CommitmentsApi {

bolt-sidecar/src/primitives/commitment.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ impl CommitmentRequest {
8282
}
8383

8484
/// Request to include a transaction at a specific slot.
85-
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
85+
#[cfg_attr(test, derive(Default))]
86+
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8687
pub struct InclusionRequest {
8788
/// The consensus slot number at which the transaction should be included.
8889
pub slot: u64,

0 commit comments

Comments
 (0)