Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions based/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion based/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ alloy-signer = "1.0.41"
alloy-signer-local = "1.0.41"
alloy-transport = "1.0.41"
alloy-transport-http = "1.0.41"

arc-cell = "0.3.3"
auto_impl = "1.3.0"
axum = { version = "0.8.1", features = ["macros", "ws"] }

backtrace = "0.3.73"
bitflags = "2.6.0"
bop-common = { path = "crates/common" }
Expand All @@ -45,6 +46,7 @@ hickory-resolver = "=0.25.0-alpha.5" # Use the exact version reth expects
http = "1.3.1"
hyper = "1.5.2"
jsonrpsee = { version = "0.26", features = ["http-client", "macros", "server", "jsonrpsee-client-transport"] }
jsonwebtoken = { version = "9.3" }
metrics = "0.24.1"
metrics-exporter-prometheus = "0.16.2"
mio = { features = ["net", "os-poll"], version = "1.0.4" }
Expand Down
6 changes: 4 additions & 2 deletions based/bin/gateway/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ fn run(mut args: GatewayArgs) -> eyre::Result<()> {
let simulator_vsync_window = Duration::from_micros(args.vsync_window_us as u64);

let root_peer_url = args.gossip_root_peer_url.clone();
let gossip_signer_private_key = args.gossip_signer_private_key().map(|key| ECDSASigner::new(key).unwrap());
let gossip_signer_private_key =
args.gossip_signer_private_key().map(|key| ECDSASigner::new(key).unwrap()).unwrap_or_else(ECDSASigner::random);
let gateway_address = gossip_signer_private_key.address;

std::thread::scope(|s| {
let rt: Arc<Runtime> = tokio::runtime::Builder::new_current_thread()
Expand All @@ -106,7 +108,7 @@ fn run(mut args: GatewayArgs) -> eyre::Result<()> {

s.spawn({
let rt = rt.clone();
start_rpc(&args, &spine, &rt, frag_broadcast_tx.clone(), args.da_config.clone());
start_rpc(&args, &spine, &rt, frag_broadcast_tx.clone(), args.da_config.clone(), gateway_address);
move || rt.block_on(wait_for_signal())
});

Expand Down
27 changes: 16 additions & 11 deletions based/bin/gateway_registry/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use std::{
time::Duration,
};

use alloy_primitives::{Address, B256, U256};
use alloy_primitives::{Address, U256};
use alloy_provider::{Provider, RootProvider};
use bop_common::{
api::RegistryApiServer,
Expand Down Expand Up @@ -108,19 +108,19 @@ enum RegistryError {
}
type Result<T> = std::result::Result<T, RegistryError>;

fn refresh_gateway_clients(path: impl AsRef<Path>) -> Result<Vec<(Url, Address, B256)>> {
fn refresh_gateway_clients(path: impl AsRef<Path>) -> Result<Vec<(Url, Address)>> {
Ok(serde_json::from_reader(std::fs::File::open(path.as_ref())?)?)
}

fn write_gateway_clients(path: Arc<PathBuf>, clients: &[(Url, Address, B256)]) {
fn write_gateway_clients(path: Arc<PathBuf>, clients: &[(Url, Address)]) {
let _ = std::fs::write(Arc::unwrap_or_clone(path), serde_json::to_string(clients).unwrap());
}

#[derive(Clone)]
pub struct RegistryServer {
eth_client: RootProvider,
// url, address, jwt secret
gateway_clients: Arc<RwLock<Vec<(Url, Address, B256)>>>,
// url, address
gateway_clients: Arc<RwLock<Vec<(Url, Address)>>>,
gateway_update_blocks: u64,
registry_path: Arc<PathBuf>,

Expand Down Expand Up @@ -190,7 +190,7 @@ impl RegistryServer {
#[async_trait]
impl RegistryApiServer for RegistryServer {
#[tracing::instrument(skip_all, err, ret(level = Level::DEBUG))]
async fn get_future_gateway(&self, n_blocks_into_the_future: u64) -> RpcResult<(u64, Url, Address, B256)> {
async fn get_future_gateway(&self, n_blocks_into_the_future: u64) -> RpcResult<(u64, Url, Address)> {
// let curblock = self.eth_client.block_number().await?;
let curblock = if !self.use_mock_blocknumber {
self.eth_client
Expand All @@ -210,26 +210,31 @@ impl RegistryApiServer for RegistryServer {
n_blocks_into_the_future;

let id = (target_block / self.gateway_update_blocks) as usize;
let (url, address, jwt_in_b256) = gateways[id % n_gateways].clone();
let (url, address) = gateways[id % n_gateways].clone();
tracing::debug!("serving future gateway for block {target_block}: url={url}, address={address}",);
Ok((target_block, url, address, jwt_in_b256))
Ok((target_block, url, address))
}

#[tracing::instrument(skip_all, err, ret(level = Level::DEBUG))]
async fn registered_gateways(&self) -> RpcResult<Vec<(Url, Address, B256)>> {
async fn registered_gateways(&self) -> RpcResult<Vec<(Url, Address)>> {
Ok(self.gateway_clients.read().clone())
}

#[tracing::instrument(skip_all, err, ret(level = Level::DEBUG))]
async fn register_gateway(&self, gateway: (Url, Address, B256)) -> RpcResult<()> {
async fn register_gateway(&self, gateway: (Url, Address)) -> RpcResult<()> {
let mut gateways = self.gateway_clients.read().clone();
if !gateways.iter().any(|g| g.0.host() == gateway.0.host() || g.2 == gateway.2) {
if !gateways.iter().any(|g| g.0.host() == gateway.0.host() || g.1 == gateway.1) {
gateways.push(gateway);
write_gateway_clients(self.registry_path.clone(), &gateways);
*self.gateway_clients.write() = gateways;
}
Ok(())
}

#[tracing::instrument(skip_all, ret(level = Level::DEBUG))]
async fn gateway_update_blocks(&self) -> RpcResult<u64> {
Ok(self.gateway_update_blocks)
}
}

#[tokio::main]
Expand Down
2 changes: 1 addition & 1 deletion based/bin/overseer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ impl OverseerConnections {
}

pub fn current_gateway(&self) -> Result<(Url, Address), ClientError> {
self.runtime.block_on(self.client_portal.current_gateway()).map(|(_, url, address, _)| (url, address))
self.runtime.block_on(self.client_portal.current_gateway()).map(|(_, url, address)| (url, address))
}

pub fn peers_based_op_node(&self) -> Result<Vec<OpPeerInfo>, ClientError> {
Expand Down
1 change: 1 addition & 0 deletions based/bin/portal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ version.workspace = true
alloy-eips.workspace = true
alloy-primitives.workspace = true
alloy-rpc-types.workspace = true
arc-cell.workspace = true
bop-common.workspace = true
bop-metrics.workspace = true
clap.workspace = true
Expand Down
27 changes: 25 additions & 2 deletions based/bin/portal/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::path::PathBuf;
use std::{fs, path::PathBuf};

use bop_common::config::{LoggingConfig, LoggingFlags};
use bop_common::{
config::{LoggingConfig, LoggingFlags},
signing::ECDSASigner,
};
use clap::Parser;
use reqwest::Url;
use reth_rpc_layer::JwtSecret;
Expand Down Expand Up @@ -40,6 +43,9 @@ pub struct PortalArgs {
/// Timeout for gateway requests in milliseconds
#[arg(long = "gateway.timeout_ms", default_value_t = 100)]
pub gateway_timeout_ms: u64,
/// Signing key used to authenticate with gateways (hex string or path to file containing hex)
#[arg(long = "gateway.signing-key")]
pub gateway_signing_key: String,

/// Enable debug logging
#[arg(long)]
Expand Down Expand Up @@ -88,6 +94,10 @@ impl PortalArgs {
.or_else(|_| JwtSecret::from_file(std::path::Path::new(&self.config_dir.join("jwt"))))
.expect("Please set the --fallback.jwt flag manually, or generate and place a jwt file in the config dir")
}

pub fn gateway_signer(&self) -> eyre::Result<ECDSASigner> {
parse_signing_key(&self.gateway_signing_key)
}
}

impl From<&PortalArgs> for LoggingConfig {
Expand All @@ -106,3 +116,16 @@ impl From<&PortalArgs> for LoggingConfig {
}
}
}

fn parse_signing_key(input: &str) -> eyre::Result<ECDSASigner> {
let trimmed = input.trim();
let normalized = trimmed.trim_start_matches("0x");
match ECDSASigner::try_from_hex(normalized) {
Ok(signer) => Ok(signer),
Err(_) => {
let contents = fs::read_to_string(trimmed)?;
let key = contents.trim().trim_start_matches("0x");
ECDSASigner::try_from_hex(key).map_err(|err| eyre::eyre!("failed to parse gateway signing key: {err}"))
}
}
}
Loading
Loading