diff --git a/bolt-sidecar/src/api/commitments/handlers.rs b/bolt-sidecar/src/api/commitments/handlers.rs index d9dce6e0..d9cbd541 100644 --- a/bolt-sidecar/src/api/commitments/handlers.rs +++ b/bolt-sidecar/src/api/commitments/handlers.rs @@ -21,7 +21,7 @@ use super::{ jsonrpc::{JsonPayload, JsonResponse}, server::CommitmentsApiInner, spec::{ - CommitmentError, CommitmentsApi, RejectionError, GET_VERSION_METHOD, + CommitmentError, CommitmentsApi, RejectionError, GET_METADATA_METHOD, GET_VERSION_METHOD, REQUEST_INCLUSION_METHOD, }, }; @@ -45,6 +45,15 @@ pub async fn rpc_entrypoint( })) } + GET_METADATA_METHOD => { + let response = JsonResponse { + id: payload.id, + result: serde_json::to_value(api.limits()).expect("infallible"), + ..Default::default() + }; + Ok(Json(response)) + } + REQUEST_INCLUSION_METHOD => { // Validate the authentication header and extract the signer and signature let (signer, signature) = auth_from_headers(&headers).inspect_err(|e| { diff --git a/bolt-sidecar/src/api/commitments/server.rs b/bolt-sidecar/src/api/commitments/server.rs index 42c4a427..bd99d9c1 100644 --- a/bolt-sidecar/src/api/commitments/server.rs +++ b/bolt-sidecar/src/api/commitments/server.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashSet, fmt, future::Future, net::{SocketAddr, ToSocketAddrs}, @@ -7,7 +6,6 @@ use std::{ sync::Arc, }; -use alloy::primitives::Address; use axum::{ middleware, routing::{get, post}, @@ -22,6 +20,7 @@ use tracing::{error, info}; use crate::{ api::commitments::handlers, + config::limits::LimitsOpts, primitives::{ commitment::{InclusionCommitment, SignedCommitment}, CommitmentRequest, InclusionRequest, @@ -49,15 +48,19 @@ pub struct CommitmentEvent { pub struct CommitmentsApiInner { /// Event notification channel events: mpsc::Sender, - /// Optional whitelist of ECDSA public keys - #[allow(unused)] - whitelist: Option>, + /// The sidecar's operating limits that should be exposed in a metadata endpoint + limits: LimitsOpts, } impl CommitmentsApiInner { - /// Create a new API server with an optional whitelist of ECDSA public keys. - pub fn new(events: mpsc::Sender) -> Self { - Self { events, whitelist: None } + /// Creates a new instance of the commitments API handler. + pub fn new(events: mpsc::Sender, limits: LimitsOpts) -> Self { + Self { events, limits } + } + + /// Returns the operating limits for the sidecar. + pub fn limits(&self) -> LimitsOpts { + self.limits } } @@ -119,8 +122,8 @@ impl CommitmentsApiServer { } /// Runs the JSON-RPC server, sending events to the provided channel. - pub async fn run(&mut self, events_tx: mpsc::Sender) { - let api = Arc::new(CommitmentsApiInner::new(events_tx)); + pub async fn run(&mut self, events_tx: mpsc::Sender, limits: LimitsOpts) { + let api = Arc::new(CommitmentsApiInner::new(events_tx, limits)); let router = make_router(api); @@ -188,7 +191,7 @@ mod test { let (events_tx, _) = mpsc::channel(1); - server.run(events_tx).await; + server.run(events_tx, LimitsOpts::default()).await; let addr = server.local_addr(); let sk = SecretKey::random(&mut rand::thread_rng()); @@ -230,7 +233,7 @@ mod test { let (events_tx, mut events) = mpsc::channel(1); - server.run(events_tx).await; + server.run(events_tx, LimitsOpts::default()).await; let addr = server.local_addr(); let sk = SecretKey::random(&mut rand::thread_rng()); @@ -281,4 +284,41 @@ mod test { rx.await.unwrap(); } + + #[tokio::test] + async fn test_request_metadata() { + let _ = tracing_subscriber::fmt::try_init(); + + let mut server = CommitmentsApiServer::new("0.0.0.0:0"); + + let (events_tx, _) = mpsc::channel(1); + + server.run(events_tx, LimitsOpts::default()).await; + let addr = server.local_addr(); + + let payload = json!({ + "jsonrpc": "2.0", + "id": 1, + "method": "bolt_metadata", + "params": [] + }); + + let url = format!("http://{addr}"); + + let client = reqwest::Client::new(); + + let response = client + .post(url) + .json(&payload) + .send() + .await + .unwrap() + .json::() + .await + .unwrap(); + + let limits: LimitsOpts = serde_json::from_value(response.result).unwrap(); + + assert_eq!(limits, LimitsOpts::default()); + } } diff --git a/bolt-sidecar/src/api/commitments/spec.rs b/bolt-sidecar/src/api/commitments/spec.rs index 3402caa1..49e8fb61 100644 --- a/bolt-sidecar/src/api/commitments/spec.rs +++ b/bolt-sidecar/src/api/commitments/spec.rs @@ -15,6 +15,8 @@ pub(super) const GET_VERSION_METHOD: &str = "bolt_getVersion"; pub(super) const REQUEST_INCLUSION_METHOD: &str = "bolt_requestInclusion"; +pub(super) const GET_METADATA_METHOD: &str = "bolt_metadata"; + pub(super) const MAX_REQUEST_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(6); /// Error type for the commitments API. diff --git a/bolt-sidecar/src/config/limits.rs b/bolt-sidecar/src/config/limits.rs index 8511c76b..3d825be9 100644 --- a/bolt-sidecar/src/config/limits.rs +++ b/bolt-sidecar/src/config/limits.rs @@ -1,7 +1,6 @@ use std::num::NonZero; use clap::Parser; -use serde::Deserialize; /// Default max commitments to accept per block. pub const DEFAULT_MAX_COMMITMENTS: usize = 128; @@ -13,7 +12,8 @@ pub const DEFAULT_MAX_COMMITTED_GAS: u64 = 10_000_000; pub const DEFAULT_MIN_PRIORITY_FEE: u128 = 1_000_000_000; // 1 Gwei /// Limits for the sidecar. -#[derive(Debug, Parser, Clone, Copy, Deserialize)] +#[cfg_attr(test, derive(PartialEq))] +#[derive(Debug, Parser, Clone, Copy, serde::Serialize, serde::Deserialize)] pub struct LimitsOpts { /// Max number of commitments to accept per block #[clap( diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index 1a72df0b..c326ea55 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -227,7 +227,7 @@ impl SidecarDriver { // start the commitments api server let api_addr = format!("0.0.0.0:{}", opts.port); let (api_events_tx, api_events_rx) = mpsc::channel(1024); - CommitmentsApiServer::new(api_addr).run(api_events_tx).await; + CommitmentsApiServer::new(api_addr).run(api_events_tx, opts.limits).await; let unsafe_skip_consensus_checks = opts.unsafe_disable_consensus_checks;