diff --git a/Cargo.lock b/Cargo.lock index 75f9412..f2de28b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4523,6 +4523,7 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", + "serde", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9fcd2db..de5619b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ tracing = "0.1.37" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tree_hash = "0.6.0" tree_hash_derive = "0.6.0" -url = "2.5.0" +url = { version="2.5.0", features=["serde"] } [dev-dependencies] diff --git a/README.md b/README.md index ecb6f0b..9d9b438 100644 --- a/README.md +++ b/README.md @@ -40,15 +40,23 @@ To execute the forward service, use the following command: Example `configuration.toml`: ```toml -beacon-urls = ["beacon-url-1", "beacon-url-2"] +beacon-nodes = ["beacon-url-1", "beacon-url-2"] -[[lookahead-providers-relays]] +[[lookahead]] chain-id = 1 -relay-urls = ["relay-1", "relay-2"] +relays = ["relay-1", "relay-2"] -[[lookahead-providers-relays]] +[[lookahead]] +url-provider = "lookahead" chain-id = 2 -relay-urls = ["relay-3"] +relays = ["relay-3"] +[[lookahead.registry]] +"0x8248efd1f054fcccd090879c4011ed91ee9f9d0db5ad125ae1af74fdd33de809ddc882400d99b5184ca065d4570df8cc" = "http://a-preconfer-url.xyz" ``` +### Details +- url-provider: Specifies the source of the URL. It can be either lookahead or url-mapping. + - If set to **lookahead**, the URL is derived from the lookahead entry. + - If set to **url-mapping**, the URL is determined by looking up the public keys between the lookahead entry public key and the map provided in registry. + Make sure to provide the necessary beacon and relay URLs in the configuration file. \ No newline at end of file diff --git a/config.example.toml b/config.example.toml index c154a7d..edb8644 100644 --- a/config.example.toml +++ b/config.example.toml @@ -1,5 +1,8 @@ -beacon-urls = ["https:://beacon-url"] +beacon-nodes = ["https:://beacon-url"] -[[lookahead-providers-relays]] +[[lookahead]] +url-provider = "lookahead" chain-id = 1 -relay-urls = ["https://relay-url"] \ No newline at end of file +relays = [] +[[lookahead.registry]] +"0x8248efd1f054fcccd090879c4011ed91ee9f9d0db5ad125ae1af74fdd33de809ddc882400d99b5184ca065d4570df8cc" = "http://a-preconfer-url.xyz" \ No newline at end of file diff --git a/src/config.rs b/src/config.rs index 9081b87..41d8fbb 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,22 +1,63 @@ use std::{fs, path::Path}; +use alloy::rpc::types::beacon::BlsPublicKey; use eyre::{Result, WrapErr}; -use serde::Deserialize; +use hashbrown::HashMap; +use serde::{Deserialize, Deserializer}; +use url::Url; #[derive(Debug, Deserialize)] -pub struct Config { - #[serde(rename = "lookahead-providers-relays")] - pub lookahead_providers_relays: Vec, - #[serde(rename = "beacon-urls")] - pub beacon_urls: Vec, +#[serde(rename_all = "kebab-case")] +pub enum Provider { + Lookahead, + Registry, } #[derive(Debug, Deserialize)] -pub struct LookaheadProvider { - #[serde(rename = "chain-id")] +pub struct Config { + #[serde(rename = "lookahead")] + pub lookaheads: Vec, + #[serde(rename = "beacon-nodes")] + pub beacon_nodes: Vec, +} + +#[derive(Debug)] +pub struct Lookahead { pub chain_id: u16, - #[serde(rename = "relay-urls")] - pub relay_urls: Vec, + pub relays: Vec, + pub registry: Option>, + pub provider: Provider, +} + +impl<'de> Deserialize<'de> for Lookahead { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(rename_all = "kebab-case")] + struct LookaheadHelper { + chain_id: u16, + relays: Vec, + registry: Option>, + url_provider: Provider, + } + + let helper = LookaheadHelper::deserialize(deserializer)?; + + if matches!(helper.url_provider, Provider::Registry) && helper.registry.is_none() { + return Err(serde::de::Error::custom( + "registry map is mandatory when url-provider is set to registry", + )); + } + + Ok(Lookahead { + chain_id: helper.chain_id, + relays: helper.relays, + registry: helper.registry, + provider: helper.url_provider, + }) + } } impl Config { @@ -25,3 +66,83 @@ impl Config { toml::from_str(&toml_str).wrap_err("could not parse configuration file") } } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + #[test] + fn test_deserialize_config() { + let data = r#" + beacon-nodes = ["node1", "node2"] + [[lookahead]] + chain-id = 1 + url-provider = "lookahead" + relays = ["relay1", "relay2"] + [lookahead.registry] + "0x8248efd1f054fcccd090879c4011ed91ee9f9d0db5ad125ae1af74fdd33de809ddc882400d99b5184ca065d4570df8cc" = "localhost:21009" + "#; + + let expected_registry = { + let mut registry = HashMap::new(); + registry.insert(BlsPublicKey::from_str("0x8248efd1f054fcccd090879c4011ed91ee9f9d0db5ad125ae1af74fdd33de809ddc882400d99b5184ca065d4570df8cc").unwrap(), Url::from_str("localhost:21009").unwrap()); + registry + }; + + let expected_lookahead = Lookahead { + chain_id: 1, + relays: vec!["relay1".to_string(), "relay2".to_string()], + registry: Some(expected_registry), + provider: Provider::Lookahead, + }; + + let _expected_config = Config { + lookaheads: vec![expected_lookahead], + beacon_nodes: vec!["node1".to_string(), "node2".to_string()], + }; + + let config: Config = toml::from_str(data).unwrap(); + assert!(matches!(config, _expected_config)); + } + + #[test] + fn test_deserialize_config_no_lookahead_registry() { + let data = r#" + beacon-nodes = ["node1", "node2"] + [[lookahead]] + chain-id = 1 + url-provider = "lookahead" + relays = ["relay1", "relay2"] + "#; + + let expected_lookahead = Lookahead { + chain_id: 1, + relays: vec!["relay1".to_string(), "relay2".to_string()], + registry: None, + provider: Provider::Lookahead, + }; + + let _expected_config = Config { + lookaheads: vec![expected_lookahead], + beacon_nodes: vec!["node1".to_string(), "node2".to_string()], + }; + + let config: Config = toml::from_str(data).unwrap(); + assert!(matches!(config, _expected_config)); + } + + #[test] + fn test_fail_if_wrong_registry_combination() { + let data = r#" + beacon-nodes = ["node1", "node2"] + [[lookahead]] + chain-id = 1 + url-provider = "registry" + relays = ["relay1", "relay2"] + "#; + let config: Result = toml::from_str(data).wrap_err("error parsing config"); + assert!(config.is_err()); + } +} diff --git a/src/forward_service.rs b/src/forward_service.rs index 92e254a..2c98b76 100644 --- a/src/forward_service.rs +++ b/src/forward_service.rs @@ -21,10 +21,12 @@ use reqwest_tracing::{ }; use tokio::task::JoinHandle; use tower_http::trace::TraceLayer; -use tracing::Span; +use tracing::{error, Span}; +use url::Url; use crate::lookahead::LookaheadManager; +#[derive(Debug)] pub(crate) struct SharedState { managers: HashMap, client: ClientWithMiddleware, @@ -94,7 +96,7 @@ impl RpcForward { fn router(shared_state: SharedState) -> Router { Router::new() - .route("/:scan_id", post(scan_id_forward_request)) + .route("/:chain_id", post(scan_id_forward_request)) .route("/", post(forward_request)) .layer(TraceLayer::new_for_http()) .with_state(Arc::new(shared_state)) @@ -107,32 +109,38 @@ async fn scan_id_forward_request( body: Bytes, ) -> Result { if let Some(manager) = state.managers.get(&chain_id) { - if let Some(entry) = manager.get_next_elected_preconfer() { - match inner_forward_request(&state.client, &entry.url, body, headers).await { + match manager.get_url() { + Ok(url) => match inner_forward_request(&state.client, url, body, headers).await { Ok(res) => Ok(res), - Err(_) => Err(( - StatusCode::INTERNAL_SERVER_ERROR, - "error while forwarding request".to_string(), - )), + Err(err) => { + error!(name: "inner_forward_request", "{:?}", err); + Err(( + StatusCode::INTERNAL_SERVER_ERROR, + "error while forwarding request".to_string(), + )) + } + }, + Err(err) => { + error!(name: "manager.get_url", "{:?}", err); + Err((StatusCode::INTERNAL_SERVER_ERROR, err.to_string())) } - } else { - Err(( - StatusCode::INTERNAL_SERVER_ERROR, - format!("no preconfer has been elected for chain_id {}", chain_id), - )) } } else { - Err((StatusCode::BAD_REQUEST, format!("no lookahead provider found for id {}", chain_id))) + error!(name: "managers.get", "no lookahead provider found for chain-id {}", chain_id); + Err(( + StatusCode::BAD_REQUEST, + format!("no lookahead provider found for chain-id {}", chain_id), + )) } } async fn forward_request(State(_state): State>) -> impl IntoResponse { - (StatusCode::BAD_REQUEST, "missing chain_id parameter") + (StatusCode::BAD_REQUEST, "missing chain-id parameter") } async fn inner_forward_request( client: &ClientWithMiddleware, - to_addr: &str, + to_addr: Url, bytes: Bytes, headers: HeaderMap, ) -> Result { @@ -144,10 +152,13 @@ async fn inner_forward_request( #[cfg(test)] mod test { use std::{ + default::Default, + str::FromStr, sync::{Arc, Mutex}, time::Duration, }; + use alloy::rpc::types::beacon::{constants::BLS_PUBLIC_KEY_BYTES_LEN, BlsPublicKey}; use axum::{ extract::State, http::HeaderMap, @@ -160,72 +171,112 @@ mod test { use eyre::Result; use hashbrown::HashMap; use http::{HeaderValue, StatusCode}; + use tokio::task::JoinHandle; + use url::Url; use crate::{ forward_service::{router, SharedState}, - lookahead::{Lookahead, LookaheadEntry, LookaheadManager, LookaheadProvider}, + lookahead::{Lookahead, LookaheadEntry, LookaheadManager, LookaheadProvider, UrlProvider}, + preconf::election::{PreconferElection, SignedPreconferElection}, }; struct DummySharedState { cnt: i32, } + #[derive(Default)] + struct TestBuilder { + managers: Option>, + test_service: Option, + forward_service: u16, + } + + struct BuilderOutput { + _fwd_service: Option>, + _test_service: Option>, + } + + impl TestBuilder { + async fn build(self) -> Result { + let fwd_service = match self.managers { + None => None, + Some(managers) => Some(tokio::spawn(async move { + let router = router(SharedState::new(managers).unwrap()); + let listener = tokio::net::TcpListener::bind(format!( + "localhost:{}", + self.forward_service + )) + .await + .unwrap(); + axum::serve(listener, router).await.unwrap(); + })), + }; + + let test_service = match self.test_service { + None => None, + Some(port) => Some(tokio::spawn(async move { + let dst = Arc::new(Mutex::new(DummySharedState { cnt: 0 })); + let router: Router = Router::new() + .route("/", post(handle_request)) + .route("/cnt", get(counter)) + .with_state(dst); + let listener = + tokio::net::TcpListener::bind(format!("localhost:{}", port)).await.unwrap(); + axum::serve(listener, router).await.unwrap(); + })), + }; + tokio::time::sleep(Duration::from_secs(1)).await; + Ok(BuilderOutput { _fwd_service: fwd_service, _test_service: test_service }) + } + } #[tokio::test] async fn test_missing_chain_id() -> Result<()> { - tokio::spawn(async move { - let manager = LookaheadManager::new( - Lookahead { map: DashMap::new().into() }, - LookaheadProvider::None, - ); - let mut managers = HashMap::new(); - managers.insert(1u16, manager); - let router = router(SharedState::new(managers).unwrap()); - let listener = tokio::net::TcpListener::bind("localhost:12001").await.unwrap(); - axum::serve(listener, router).await.unwrap(); - }); - tokio::time::sleep(Duration::from_secs(1)).await; + let manager: LookaheadManager = Default::default(); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = + TestBuilder { managers: Some(managers), test_service: None, forward_service: 12001 } + .build() + .await?; let res = reqwest::Client::new().post("http://localhost:12001").send().await.unwrap(); assert_eq!(res.status(), StatusCode::BAD_REQUEST); - assert_eq!(res.text().await.unwrap(), "missing chain_id parameter"); + assert_eq!(res.text().await.unwrap(), "missing chain-id parameter"); Ok(()) } #[tokio::test] async fn test_invalid_chain_id() -> Result<()> { - tokio::spawn(async move { - let manager = LookaheadManager::new( - Lookahead { map: DashMap::new().into() }, - LookaheadProvider::None, - ); - let mut managers = HashMap::new(); - managers.insert(1u16, manager); - let router = router(SharedState::new(managers).unwrap()); - let listener = tokio::net::TcpListener::bind("localhost:12002").await.unwrap(); - axum::serve(listener, router).await.unwrap(); - }); - tokio::time::sleep(Duration::from_secs(1)).await; + let manager: LookaheadManager = Default::default(); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = + TestBuilder { managers: Some(managers), test_service: None, forward_service: 12002 } + .build() + .await?; let res = reqwest::Client::new().post("http://localhost:12002/2").send().await.unwrap(); assert_eq!(res.status(), StatusCode::BAD_REQUEST); - assert_eq!(res.text().await.unwrap(), "no lookahead provider found for id 2"); + assert_eq!(res.text().await.unwrap(), "no lookahead provider found for chain-id 2"); Ok(()) } #[tokio::test] async fn test_unavailable_forwarded_service() -> Result<()> { - tokio::spawn(async move { - let map = Arc::new(DashMap::new()); - map.insert(0, LookaheadEntry { - url: "http://not-a-valid-url".into(), - ..Default::default() - }); - let manager = LookaheadManager::new(Lookahead { map }, LookaheadProvider::None); - let mut managers = HashMap::new(); - managers.insert(1u16, manager); - let router = router(SharedState::new(managers).unwrap()); - let listener = tokio::net::TcpListener::bind("localhost:12003").await.unwrap(); - axum::serve(listener, router).await.unwrap(); + let map = Arc::new(DashMap::new()); + map.insert(0, LookaheadEntry { + url: "http://not-a-valid-url".into(), + ..Default::default() }); - tokio::time::sleep(Duration::from_secs(1)).await; + let manager = LookaheadManager::new( + Lookahead { map }, + LookaheadProvider::None, + UrlProvider::LookaheadEntry, + ); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = + TestBuilder { managers: Some(managers), test_service: None, forward_service: 12003 } + .build() + .await?; let res = reqwest::Client::new().post("http://localhost:12003/1").send().await.unwrap(); assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); Ok(()) @@ -233,46 +284,130 @@ mod test { #[tokio::test] async fn test_forward_request() -> Result<()> { - tokio::spawn(async move { - let dst = Arc::new(Mutex::new(DummySharedState { cnt: 0 })); - let router: Router = Router::new() - .route("/", post(handle_request)) - .route("/cnt", get(counter)) - .with_state(dst); - let listener = tokio::net::TcpListener::bind("localhost:12004").await.unwrap(); - axum::serve(listener, router).await.unwrap(); + let map = Arc::new(DashMap::new()); + map.insert(0, LookaheadEntry { + url: "http://localhost:12004".into(), + ..Default::default() }); - tokio::spawn(async move { - let map = Arc::new(DashMap::new()); - map.insert(0, LookaheadEntry { - url: "http://localhost:12004".into(), + let manager = LookaheadManager::new( + Lookahead { map }, + LookaheadProvider::None, + UrlProvider::LookaheadEntry, + ); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = TestBuilder { + managers: Some(managers), + test_service: Some(12004), + forward_service: 12005, + } + .build() + .await?; + + batch_requests(12005, 10).await?; + + let cnt_res = reqwest::get("http://localhost:12004/cnt").await.unwrap(); + assert_eq!(StatusCode::OK, cnt_res.status()); + assert_eq!(cnt_res.text().await.unwrap(), "10"); + Ok(()) + } + + #[tokio::test] + async fn test_url_map_request() -> Result<()> { + let map = Arc::new(DashMap::new()); + let signature: BlsPublicKey = BlsPublicKey::from([42u8; BLS_PUBLIC_KEY_BYTES_LEN]); + let mut url_mapping = HashMap::new(); + url_mapping.insert(signature, Url::from_str("http://localhost:12006").unwrap()); + map.insert(0, LookaheadEntry { + url: "".into(), + election: SignedPreconferElection { + message: PreconferElection { + preconfer_pubkey: signature.clone(), + ..Default::default() + }, ..Default::default() - }); - let manager = LookaheadManager::new(Lookahead { map }, LookaheadProvider::None); - let mut managers = HashMap::new(); - managers.insert(1u16, manager); - let router = router(SharedState::new(managers).unwrap()); - let listener = tokio::net::TcpListener::bind("localhost:12005").await.unwrap(); - axum::serve(listener, router).await.unwrap(); + }, }); - tokio::time::sleep(Duration::from_secs(1)).await; - for _ in 0..10 { + let manager = LookaheadManager::new( + Lookahead { map }, + LookaheadProvider::None, + UrlProvider::UrlMap(url_mapping), + ); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = TestBuilder { + managers: Some(managers), + test_service: Some(12006), + forward_service: 12007, + } + .build() + .await?; + + batch_requests(12007, 10).await?; + + let cnt_res = reqwest::get("http://localhost:12006/cnt").await.unwrap(); + assert_eq!(StatusCode::OK, cnt_res.status()); + assert_eq!(cnt_res.text().await.unwrap(), "10"); + Ok(()) + } + + #[tokio::test] + async fn test_no_pubkey() -> Result<()> { + let signature: BlsPublicKey = BlsPublicKey::from([42u8; BLS_PUBLIC_KEY_BYTES_LEN]); + let map = Arc::new(DashMap::new()); + let mut provider = HashMap::new(); + provider.insert(signature, Url::from_str("http://localhost:12010/1").unwrap()); + map.insert(0, LookaheadEntry { url: "".into(), ..Default::default() }); + let manager = LookaheadManager::new( + Lookahead { map }, + LookaheadProvider::None, + UrlProvider::UrlMap(provider), + ); + let mut managers = HashMap::new(); + managers.insert(1u16, manager); + let _handlers = + TestBuilder { managers: Some(managers), test_service: None, forward_service: 12008 } + .build() + .await?; + let res = reqwest::Client::new().post("http://localhost:12008/1").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); + assert_eq!( + res.text().await.unwrap(), + format!( + "could not find key for pubkey {}", + BlsPublicKey::from([0u8; BLS_PUBLIC_KEY_BYTES_LEN]).to_string() + ) + ); + Ok(()) + } + + #[tokio::test] + async fn test_chain_id_not_found() -> Result<()> { + let mut managers = HashMap::new(); + managers.insert(2, LookaheadManager::default()); + let _handlers = + TestBuilder { managers: Some(managers), test_service: None, forward_service: 12009 } + .build() + .await?; + let res = reqwest::Client::new().post("http://localhost:12009/2").send().await.unwrap(); + assert_eq!(res.status(), StatusCode::INTERNAL_SERVER_ERROR); + assert_eq!(res.text().await.unwrap(), "no lookahead provider found"); + Ok(()) + } + + async fn batch_requests(port: u16, no_requests: u16) -> Result<()> { + for _ in 0..no_requests { let mut headers = HeaderMap::new(); headers.insert("Content-Type", HeaderValue::from_str("application/json").unwrap()); let res = reqwest::Client::new() - .post("http://localhost:12005/1") + .post(format!("http://localhost:{}/1", port)) .body("dummy plain body") .headers(headers) .headers(HeaderMap::new()) .send() - .await - .unwrap(); + .await?; assert_eq!(res.status(), StatusCode::OK); } - - let cnt_res = reqwest::get("http://localhost:12004/cnt").await.unwrap(); - assert_eq!(StatusCode::OK, cnt_res.status()); - assert_eq!(cnt_res.text().await.unwrap(), "10"); Ok(()) } diff --git a/src/lookahead/manager.rs b/src/lookahead/manager.rs index 0e909b8..a85579d 100644 --- a/src/lookahead/manager.rs +++ b/src/lookahead/manager.rs @@ -1,8 +1,11 @@ -use alloy::rpc::types::beacon::events::HeadEvent; +use std::str::FromStr; + +use alloy::rpc::types::beacon::{events::HeadEvent, BlsPublicKey}; use dashmap::DashMap; -use eyre::{bail, Result}; +use eyre::{bail, ContextCompat, Result, WrapErr}; use hashbrown::HashMap; use tokio::sync::broadcast; +use url::Url; use super::{ provider::LookaheadProvider, Lookahead, LookaheadEntry, LookaheadProviderOptions, @@ -10,23 +13,47 @@ use super::{ }; use crate::config::Config; +#[derive(Debug)] /// Manages the state of the lookahead provider. enum LookaheadProviderManager { Initialized(LookaheadProvider), Running, } +#[derive(Debug, Clone)] +pub enum UrlProvider { + LookaheadEntry, + UrlMap(HashMap), +} + +#[derive(Debug)] /// Manages the lookahead for preconfer elections. pub struct LookaheadManager { lookahead: Lookahead, provider_manager: Option, + url_provider: UrlProvider, +} + +impl Default for LookaheadManager { + fn default() -> Self { + Self { + lookahead: Lookahead { map: DashMap::new().into() }, + provider_manager: Some(LookaheadProviderManager::Initialized(LookaheadProvider::None)), + url_provider: UrlProvider::LookaheadEntry, + } + } } impl LookaheadManager { - pub fn new(lookahead: Lookahead, lookahead_provider: LookaheadProvider) -> Self { + pub fn new( + lookahead: Lookahead, + lookahead_provider: LookaheadProvider, + url_provider: UrlProvider, + ) -> Self { Self { lookahead, provider_manager: Some(LookaheadProviderManager::Initialized(lookahead_provider)), + url_provider, } } @@ -47,9 +74,26 @@ impl LookaheadManager { } } - pub fn get_next_elected_preconfer(&self) -> Option { + fn get_next_elected_preconfer(&self) -> Option { self.lookahead.get_next_elected_preconfer() } + + pub fn get_url(&self) -> Result { + match self.get_next_elected_preconfer() { + None => bail!("no lookahead provider found"), + Some(entry) => match &self.url_provider { + UrlProvider::LookaheadEntry => { + Ok(Url::from_str(&entry.url).wrap_err("not a valid url")?) + } + UrlProvider::UrlMap(m) => { + let pub_key = entry.election.preconfer_pubkey(); + m.get(&pub_key) + .cloned() + .wrap_err(format!("could not find key for pubkey {}", pub_key)) + } + }, + } + } } /// BBuilds a map of lookahead managers from the configuration, keyed by the chain-id. @@ -59,18 +103,24 @@ pub fn lookahead_managers_from_config( ) -> HashMap { // build managers from relay lookahead providers let mut map = HashMap::new(); - for r_c in config.lookahead_providers_relays { + for r_c in config.lookaheads { let lookahead = Lookahead { map: DashMap::new().into() }; let provider = LookaheadProviderOptions { head_event_receiver: Some(beacon_tx.subscribe()), relay_provider: Some(RelayLookaheadProvider::new( lookahead.clone(), - r_c.relay_urls, + r_c.relays, HashMap::new(), )), } .build_relay_provider(); - map.insert(r_c.chain_id, LookaheadManager::new(lookahead, provider)); + let url_provider = match r_c.provider { + crate::config::Provider::Lookahead => UrlProvider::LookaheadEntry, + crate::config::Provider::Registry => { + UrlProvider::UrlMap(r_c.registry.expect("registry is empty")) + } + }; + map.insert(r_c.chain_id, LookaheadManager::new(lookahead, provider, url_provider)); } map } diff --git a/src/lookahead/provider.rs b/src/lookahead/provider.rs index 2294044..53c960a 100644 --- a/src/lookahead/provider.rs +++ b/src/lookahead/provider.rs @@ -14,6 +14,7 @@ use crate::{ relay_client::{RelayClient, RelayClientConfig}, }; +#[derive(Debug)] struct LookaheadContext { /// Current slot of the `LookaheadProvider` head_slot: u64, @@ -22,6 +23,7 @@ struct LookaheadContext { curr_lookahead_epoch: u64, } +#[derive(Debug)] /// The relay lookahead provider keeps track of the lookahead, i.e. the slot -> preconfer map. /// It builds this progressively by querying relays for preconfers for a given slot. /// Preconf lookahead is guaranteed at epoch time. So we fetch for epoch + 1 at slot > 1 in the @@ -190,6 +192,7 @@ impl LookaheadProviderOptions { } } +#[derive(Debug)] /// `LookaheadProvider` is an enumeration representing the implemented lookahead providers /// to fetch upcoming lookahead entries from different sources. pub enum LookaheadProvider { diff --git a/src/main.rs b/src/main.rs index 7c1fb9f..fb6d8d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,7 +45,7 @@ async fn main() -> Result<()> { Commands::Forward { port } => { let config = Config::from_file(&cli.config)?; let (beacon_tx, _beacon_rx) = broadcast::channel(16); - let client = MultiBeaconClient::from_endpoint_strs(&config.beacon_urls); + let client = MultiBeaconClient::from_endpoint_strs(&config.beacon_nodes); client.subscribe_to_head_events(beacon_tx.clone()).await; let listening_addr = format!("0.0.0.0:{}", port.unwrap_or(8000)); diff --git a/src/preconf/constraints.rs b/src/preconf/constraints.rs index 2307419..b4f30c5 100644 --- a/src/preconf/constraints.rs +++ b/src/preconf/constraints.rs @@ -59,7 +59,6 @@ mod tests { }; let s = serde_json::to_string(&singed_constraints).unwrap(); - let encode = alloy::primitives::hex::encode(s); - println!("{}", encode); + let _encode = alloy::primitives::hex::encode(s); } }