Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP API Template #9

Merged
merged 1 commit into from
Oct 1, 2024
Merged
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
2,498 changes: 2,396 additions & 102 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
members = [
"anchor",
"anchor/client",
"anchor/http_api",
]
resolver = "2"

Expand All @@ -11,19 +12,21 @@ edition = "2021"

[workspace.dependencies]
client = { path = "anchor/client" }
http_api = { path = "anchor/http_api" }
task_executor = { git = "https://github.com/sigp/lighthouse", branch = "anchor", default-features = false, features = ["tracing"] }
sensitive_url = { git = "https://github.com/sigp/lighthouse", branch = "anchor"}
slot_clock = { git = "https://github.com/sigp/lighthouse", branch = "anchor"}
async-channel = "1.9"
axum = "0.7.7"
clap = "4.5.15"
dirs = "5.0.1"
ethereum_hashing = "0.7.0"
futures = "0.3.30"
# dirs = "3"
hyper = "1.4"
serde = { version = "1.0.208", features = ["derive"] }
tokio = { version = "1.39.2", features = ["rt", "rt-multi-thread", "time", "signal", "macros"] }
tracing = "0.1.40"
git-version = "0.3.9"
target_info = "0.1.0"
tracing-subscriber = { version = "0.3", features = ["fmt"] }

[profile.maxperf]
inherits = "release"
Expand Down
4 changes: 1 addition & 3 deletions anchor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,12 @@ sensitive_url = { workspace = true }
async-channel = { workspace = true }
clap = { workspace = true }
dirs = { workspace = true }
ethereum_hashing = { workspace = true }
futures = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
git-version = { workspace = true }
target_info = { workspace = true }
client = { workspace = true }
tracing-subscriber = { workspace = true }

[dev-dependencies]
regex = "1.10.6"
11 changes: 11 additions & 0 deletions anchor/client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,19 @@ path = "src/lib.rs"

[dependencies]
task_executor = { workspace = true }
http_api = { workspace = true }
clap = { workspace = true }
serde = { workspace = true }
sensitive_url = { workspace = true }
dirs = { workspace = true }
hyper = { workspace = true }
tracing = { workspace = true }
# Local dependencies
fdlimit = "0.3"
ethereum_hashing = "0.7.0"
git-version = "0.3.9"
target_info = "0.1.0"

[dev-dependencies]
regex = "1.11"

File renamed without changes.
58 changes: 46 additions & 12 deletions anchor/src/cli.rs → anchor/client/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn cli_app() -> Command {
.next_line_help(true)
.term_width(80)
.about(
"Anchor is a rust-based SSV client. Currently under active developement and should not be used for production."
"Anchor is a rust-based SSV client. Currently under active developement and should NOT be used for production."
)
.long_version(LONG_VERSION.as_str())
.display_order(0)
Expand Down Expand Up @@ -76,6 +76,49 @@ pub fn cli_app() -> Command {
.action(ArgAction::Set)
.display_order(0)
)
/* External APIs */
.arg(
Arg::new("beacon-nodes")
.long("beacon-nodes")
.value_name("NETWORK_ADDRESSES")
.help("Comma-separated addresses to one or more beacon node HTTP APIs. \
Default is http://localhost:5052."
)
.action(ArgAction::Set)
.display_order(0)
)
.arg(
Arg::new("execution-nodes")
.long("beacon-nodes")
.value_name("NETWORK_ADDRESSES")
.help("Comma-separated addresses to one or more beacon node HTTP APIs. \
Default is http://localhost:8545."
)
.action(ArgAction::Set)
.display_order(0)
)
.arg(
Arg::new("beacon-nodes-tls-certs")
.long("beacon-nodes-tls-certs")
.value_name("CERTIFICATE-FILES")
.action(ArgAction::Set)
.help("Comma-separated paths to custom TLS certificates to use when connecting \
to a beacon node (and/or proposer node). These certificates must be in PEM format and are used \
in addition to the OS trust store. Commas must only be used as a \
delimiter, and must not be part of the certificate path.")
.display_order(0)
)
.arg(
Arg::new("execution-nodes-tls-certs")
.long("execution-nodes-tls-certs")
.value_name("CERTIFICATE-FILES")
.action(ArgAction::Set)
.help("Comma-separated paths to custom TLS certificates to use when connecting \
to an exection node. These certificates must be in PEM format and are used \
in addition to the OS trust store. Commas must only be used as a \
delimiter, and must not be part of the certificate path.")
.display_order(0)
)
/* REST API related arguments */
.arg(
Arg::new("http")
Expand Down Expand Up @@ -106,17 +149,6 @@ pub fn cli_app() -> Command {
.requires("unencrypted-http-transport")
.display_order(0)
)
.arg(
Arg::new("unencrypted-http-transport")
.long("unencrypted-http-transport")
.help("This is a safety flag to ensure that the user is aware that the http \
transport is unencrypted and using a custom HTTP address is unsafe.")
.action(ArgAction::SetTrue)
.help_heading(FLAG_HEADER)
.requires("http-address")
.hide(true)
.display_order(0)
)
.arg(
Arg::new("http-port")
.long("http-port")
Expand Down Expand Up @@ -157,6 +189,7 @@ pub fn cli_app() -> Command {
.default_value_if("metrics", ArgPredicate::IsPresent, "127.0.0.1")
.action(ArgAction::Set)
.display_order(0)
.hide(true)
)
.arg(
Arg::new("metrics-port")
Expand All @@ -167,6 +200,7 @@ pub fn cli_app() -> Command {
.default_value_if("metrics", ArgPredicate::IsPresent, "5064")
.action(ArgAction::Set)
.display_order(0)
.hide(true)
)
}

Expand Down
31 changes: 25 additions & 6 deletions anchor/client/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ use clap::ArgMatches;
use sensitive_url::SensitiveUrl;
use serde::{Deserialize, Serialize};
use std::fs;
use std::net::IpAddr;
use std::path::PathBuf;
use std::str::FromStr;

pub const DEFAULT_BEACON_NODE: &str = "http://localhost:5052/";
pub const DEFAULT_EXECUTION_NODE: &str = "http://localhost:8545/";
/// The default Data directory, relative to the users home directory
pub const DEFAULT_ROOT_DIR: &str = ".anchor";
/// Default network, used to partition the data storage
Expand All @@ -27,17 +29,21 @@ pub struct Config {
///
/// Should be similar to `["http://localhost:8080"]`
pub beacon_nodes: Vec<SensitiveUrl>,
/// The http endpoints of the execution node APIs.
pub execution_nodes: Vec<SensitiveUrl>,
/// beacon node is not synced at startup.
pub allow_unsynced_beacon_node: bool,
/// Configuration for the HTTP REST API.
// TODO:
// pub http_api: http_api::Config,
pub http_api: http_api::Config,
/// Configuration for the HTTP REST API.
// TODO:
// pub http_metrics: http_metrics::Config,
/// A list of custom certificates that the validator client will additionally use when
/// connecting to a beacon node over SSL/TLS.
pub beacon_nodes_tls_certs: Option<Vec<PathBuf>>,
/// A list of custom certificates that the validator client will additionally use when
/// connecting to an execution node over SSL/TLS.
pub execution_nodes_tls_certs: Option<Vec<PathBuf>>,
}

impl Default for Config {
Expand All @@ -53,14 +59,18 @@ impl Default for Config {

let beacon_nodes = vec![SensitiveUrl::parse(DEFAULT_BEACON_NODE)
.expect("beacon_nodes must always be a valid url.")];
let execution_nodes = vec![SensitiveUrl::parse(DEFAULT_EXECUTION_NODE)
.expect("execution_nodes must always be a valid url.")];
Self {
data_dir,
secrets_dir,
beacon_nodes,
execution_nodes,
allow_unsynced_beacon_node: false,
// http_api: <_>::default(),
http_api: <_>::default(),
// http_metrics: <_>::default(),
beacon_nodes_tls_certs: None,
execution_nodes_tls_certs: None,
}
}
}
Expand Down Expand Up @@ -102,16 +112,26 @@ pub fn from_cli(cli_args: &ArgMatches) -> Result<Config, String> {
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?;
}

if let Some(execution_nodes) = parse_optional::<String>(cli_args, "execution-nodes")? {
config.execution_nodes = execution_nodes
.split(',')
.map(SensitiveUrl::parse)
.collect::<Result<_, _>>()
.map_err(|e| format!("Unable to parse execution node URL: {:?}", e))?;
}

if let Some(tls_certs) = parse_optional::<String>(cli_args, "beacon-nodes-tls-certs")? {
config.beacon_nodes_tls_certs = Some(tls_certs.split(',').map(PathBuf::from).collect());
}

if let Some(tls_certs) = parse_optional::<String>(cli_args, "execution-nodes-tls-certs")? {
config.execution_nodes_tls_certs = Some(tls_certs.split(',').map(PathBuf::from).collect());
}

/*
* Http API server
*/
// TODO:

/*
if cli_args.get_flag("http") {
config.http_api.enabled = true;
}
Expand Down Expand Up @@ -143,7 +163,6 @@ pub fn from_cli(cli_args: &ArgMatches) -> Result<Config, String> {

config.http_api.allow_origin = Some(allow_origin.to_string());
}
*/

/*
* Prometheus metrics HTTP server
Expand Down
63 changes: 35 additions & 28 deletions anchor/client/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,46 @@
// use tracing::{debug, info};

mod cli;
pub mod config;
mod version;

pub use cli::cli_app;
use config::Config;
use task_executor::TaskExecutor;
use tracing::{debug, error, info};

pub struct Client {}

impl Client {
/// Instantiates the Anchor client
pub async fn new(_executor: TaskExecutor, _config: Config) -> Result<Self, String> {
/*
// Attempt to raise soft fd limit. The behavior is OS specific:
// `linux` - raise soft fd limit to hard
// `macos` - raise soft fd limit to `min(kernel limit, hard fd limit)`
// `windows` & rest - noop
match fdlimit::raise_fd_limit().map_err(|e| format!("Unable to raise fd limit: {}", e))? {
fdlimit::Outcome::LimitRaised { from, to } => {
debug!(
"old_limit" = from,
"new_limit" = to
"Raised soft open file descriptor resource limit"
);
}
fdlimit::Outcome::Unsupported => {
debug!("Raising soft open file descriptor resource limit is not supported");
}
};

info!(
"beacon_nodes" = format!("{:?}", &config.beacon_nodes),
"validator_dir" = format!("{:?}", config.validator_dir),
"Starting validator client"
/// Runs the Anchor Client
pub async fn run(_executor: TaskExecutor, config: Config) -> Result<(), String> {
// Attempt to raise soft fd limit. The behavior is OS specific:
// `linux` - raise soft fd limit to hard
// `macos` - raise soft fd limit to `min(kernel limit, hard fd limit)`
// `windows` & rest - noop
match fdlimit::raise_fd_limit().map_err(|e| format!("Unable to raise fd limit: {}", e))? {
fdlimit::Outcome::LimitRaised { from, to } => {
debug!(
old_limit = from,
new_limit = to,
"Raised soft open file descriptor resource limit"
);
}
fdlimit::Outcome::Unsupported => {
debug!("Raising soft open file descriptor resource limit is not supported");
}
};

info!(
beacon_nodes = format!("{:?}", &config.beacon_nodes),
execution_nodes = format!("{:?}", &config.execution_nodes),
data_dir = format!("{:?}", config.data_dir),
"Starting the Anchor client"
);

/*
// Optionally start the metrics server.

let http_metrics_ctx = if config.http_metrics.enabled {
let shared = http_metrics::Shared {
validator_store: None,
Expand Down Expand Up @@ -64,11 +70,12 @@ impl Client {
None
};
*/
Ok(Client {})
}

/// Executes the main client logic
pub async fn run(&mut self) -> Result<(), String> {
// Optionally run the http_api server
if let Err(error) = http_api::run(config.http_api).await {
error!(error, "Failed to run HTTP API");
return Err("HTTP API Failed".to_string());
}
Ok(())
}
}
File renamed without changes.
17 changes: 17 additions & 0 deletions anchor/http_api/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "http_api"
version = "0.1.0"
edition = { workspace = true }
authors = ["Sigma Prime <contact@sigmaprime.io>"]

[lib]
name = "http_api"
path = "src/lib.rs"

[dependencies]
task_executor = { workspace = true }
axum = { workspace = true }
slot_clock = { workspace = true }
serde = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
24 changes: 24 additions & 0 deletions anchor/http_api/src/config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//! Configuration for Anchor's HTTP API

use serde::{Deserialize, Serialize};
use std::net::{IpAddr, Ipv4Addr};

/// Configuration for the HTTP server.
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub enabled: bool,
pub listen_addr: IpAddr,
pub listen_port: u16,
pub allow_origin: Option<String>,
}

impl Default for Config {
fn default() -> Self {
Self {
enabled: false,
listen_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
listen_port: 5062,
allow_origin: None,
}
}
}
Loading