Add SensitiveUrl
to redact user secrets from endpoints (#2326)
## Issue Addressed #2276 ## Proposed Changes Add the `SensitiveUrl` struct which wraps `Url` and implements custom `Display` and `Debug` traits to redact user secrets from being logged in eth1 endpoints, beacon node endpoints and metrics. ## Additional Info This also includes a small rewrite of the eth1 crate to make requests using `Url` instead of `&str`. Some error messages have also been changed to remove `Url` data.
This commit is contained in:
parent
2ccb358d87
commit
4cc613d644
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -25,6 +25,7 @@ dependencies = [
|
|||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"rayon",
|
"rayon",
|
||||||
"safe_arith",
|
"safe_arith",
|
||||||
|
"sensitive_url",
|
||||||
"slashing_protection",
|
"slashing_protection",
|
||||||
"slog",
|
"slog",
|
||||||
"slog-async",
|
"slog-async",
|
||||||
@ -650,6 +651,7 @@ dependencies = [
|
|||||||
"logging",
|
"logging",
|
||||||
"node_test_rig",
|
"node_test_rig",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"slasher",
|
"slasher",
|
||||||
"slog",
|
"slog",
|
||||||
@ -1896,6 +1898,7 @@ dependencies = [
|
|||||||
"merkle_proof",
|
"merkle_proof",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"slog",
|
"slog",
|
||||||
@ -1942,6 +1945,7 @@ dependencies = [
|
|||||||
"psutil",
|
"psutil",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"ring",
|
"ring",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_utils",
|
"serde_utils",
|
||||||
@ -2514,6 +2518,7 @@ dependencies = [
|
|||||||
"merkle_proof",
|
"merkle_proof",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"slog",
|
"slog",
|
||||||
@ -2844,6 +2849,7 @@ dependencies = [
|
|||||||
"lighthouse_version",
|
"lighthouse_version",
|
||||||
"network",
|
"network",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"slog",
|
"slog",
|
||||||
"slot_clock",
|
"slot_clock",
|
||||||
@ -3347,6 +3353,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"regex",
|
"regex",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"simple_logger",
|
"simple_logger",
|
||||||
@ -4189,6 +4196,7 @@ dependencies = [
|
|||||||
"futures 0.3.14",
|
"futures 0.3.14",
|
||||||
"genesis",
|
"genesis",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"types",
|
"types",
|
||||||
@ -5155,6 +5163,7 @@ dependencies = [
|
|||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
"remote_signer_test",
|
"remote_signer_test",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio 1.5.0",
|
"tokio 1.5.0",
|
||||||
"types",
|
"types",
|
||||||
@ -5171,6 +5180,7 @@ dependencies = [
|
|||||||
"remote_signer_client",
|
"remote_signer_client",
|
||||||
"remote_signer_consumer",
|
"remote_signer_consumer",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
@ -5499,6 +5509,14 @@ version = "0.7.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sensitive_url"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.125"
|
version = "1.0.125"
|
||||||
@ -5714,6 +5732,7 @@ dependencies = [
|
|||||||
"node_test_rig",
|
"node_test_rig",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rayon",
|
"rayon",
|
||||||
|
"sensitive_url",
|
||||||
"tokio 1.5.0",
|
"tokio 1.5.0",
|
||||||
"types",
|
"types",
|
||||||
"validator_client",
|
"validator_client",
|
||||||
@ -7052,6 +7071,7 @@ dependencies = [
|
|||||||
"ring",
|
"ring",
|
||||||
"safe_arith",
|
"safe_arith",
|
||||||
"scrypt",
|
"scrypt",
|
||||||
|
"sensitive_url",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -33,6 +33,7 @@ members = [
|
|||||||
"common/logging",
|
"common/logging",
|
||||||
"common/lru_cache",
|
"common/lru_cache",
|
||||||
"common/remote_signer_consumer",
|
"common/remote_signer_consumer",
|
||||||
|
"common/sensitive_url",
|
||||||
"common/slot_clock",
|
"common/slot_clock",
|
||||||
"common/task_executor",
|
"common/task_executor",
|
||||||
"common/test_random_derive",
|
"common/test_random_derive",
|
||||||
|
@ -34,6 +34,7 @@ slashing_protection = { path = "../validator_client/slashing_protection" }
|
|||||||
eth2 = {path = "../common/eth2"}
|
eth2 = {path = "../common/eth2"}
|
||||||
safe_arith = {path = "../consensus/safe_arith"}
|
safe_arith = {path = "../consensus/safe_arith"}
|
||||||
slot_clock = { path = "../common/slot_clock" }
|
slot_clock = { path = "../common/slot_clock" }
|
||||||
|
sensitive_url = { path = "../common/sensitive_url" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
@ -4,11 +4,12 @@ use clap::{App, Arg, ArgMatches};
|
|||||||
use environment::Environment;
|
use environment::Environment;
|
||||||
use eth2::{
|
use eth2::{
|
||||||
types::{GenesisData, StateId, ValidatorData, ValidatorId, ValidatorStatus},
|
types::{GenesisData, StateId, ValidatorData, ValidatorId, ValidatorStatus},
|
||||||
BeaconNodeHttpClient, Url,
|
BeaconNodeHttpClient,
|
||||||
};
|
};
|
||||||
use eth2_keystore::Keystore;
|
use eth2_keystore::Keystore;
|
||||||
use eth2_network_config::Eth2NetworkConfig;
|
use eth2_network_config::Eth2NetworkConfig;
|
||||||
use safe_arith::SafeArith;
|
use safe_arith::SafeArith;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use slot_clock::{SlotClock, SystemTimeSlotClock};
|
use slot_clock::{SlotClock, SystemTimeSlotClock};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -75,7 +76,7 @@ pub fn cli_run<E: EthSpec>(matches: &ArgMatches, env: Environment<E>) -> Result<
|
|||||||
let spec = env.eth2_config().spec.clone();
|
let spec = env.eth2_config().spec.clone();
|
||||||
let server_url: String = clap_utils::parse_required(matches, BEACON_SERVER_FLAG)?;
|
let server_url: String = clap_utils::parse_required(matches, BEACON_SERVER_FLAG)?;
|
||||||
let client = BeaconNodeHttpClient::new(
|
let client = BeaconNodeHttpClient::new(
|
||||||
Url::parse(&server_url)
|
SensitiveUrl::parse(&server_url)
|
||||||
.map_err(|e| format!("Failed to parse beacon http server: {:?}", e))?,
|
.map_err(|e| format!("Failed to parse beacon http server: {:?}", e))?,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -44,3 +44,4 @@ hyper = "0.14.4"
|
|||||||
lighthouse_version = { path = "../common/lighthouse_version" }
|
lighthouse_version = { path = "../common/lighthouse_version" }
|
||||||
hex = "0.4.2"
|
hex = "0.4.2"
|
||||||
slasher = { path = "../slasher" }
|
slasher = { path = "../slasher" }
|
||||||
|
sensitive_url = { path = "../common/sensitive_url" }
|
||||||
|
@ -34,3 +34,4 @@ lazy_static = "1.4.0"
|
|||||||
task_executor = { path = "../../common/task_executor" }
|
task_executor = { path = "../../common/task_executor" }
|
||||||
eth2 = { path = "../../common/eth2" }
|
eth2 = { path = "../../common/eth2" }
|
||||||
fallback = { path = "../../common/fallback" }
|
fallback = { path = "../../common/fallback" }
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
use futures::future::TryFutureExt;
|
use futures::future::TryFutureExt;
|
||||||
use reqwest::{header::CONTENT_TYPE, ClientBuilder, StatusCode};
|
use reqwest::{header::CONTENT_TYPE, ClientBuilder, StatusCode};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -79,7 +80,7 @@ impl FromStr for Eth1Id {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the eth1 network id of the given endpoint.
|
/// Get the eth1 network id of the given endpoint.
|
||||||
pub async fn get_network_id(endpoint: &str, timeout: Duration) -> Result<Eth1Id, String> {
|
pub async fn get_network_id(endpoint: &SensitiveUrl, timeout: Duration) -> Result<Eth1Id, String> {
|
||||||
let response_body = send_rpc_request(endpoint, "net_version", json!([]), timeout).await?;
|
let response_body = send_rpc_request(endpoint, "net_version", json!([]), timeout).await?;
|
||||||
Eth1Id::from_str(
|
Eth1Id::from_str(
|
||||||
response_result(&response_body)?
|
response_result(&response_body)?
|
||||||
@ -90,7 +91,7 @@ pub async fn get_network_id(endpoint: &str, timeout: Duration) -> Result<Eth1Id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the eth1 chain id of the given endpoint.
|
/// Get the eth1 chain id of the given endpoint.
|
||||||
pub async fn get_chain_id(endpoint: &str, timeout: Duration) -> Result<Eth1Id, String> {
|
pub async fn get_chain_id(endpoint: &SensitiveUrl, timeout: Duration) -> Result<Eth1Id, String> {
|
||||||
let response_body = send_rpc_request(endpoint, "eth_chainId", json!([]), timeout).await?;
|
let response_body = send_rpc_request(endpoint, "eth_chainId", json!([]), timeout).await?;
|
||||||
hex_to_u64_be(
|
hex_to_u64_be(
|
||||||
response_result(&response_body)?
|
response_result(&response_body)?
|
||||||
@ -111,7 +112,7 @@ pub struct Block {
|
|||||||
/// Returns the current block number.
|
/// Returns the current block number.
|
||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
pub async fn get_block_number(endpoint: &str, timeout: Duration) -> Result<u64, String> {
|
pub async fn get_block_number(endpoint: &SensitiveUrl, timeout: Duration) -> Result<u64, String> {
|
||||||
let response_body = send_rpc_request(endpoint, "eth_blockNumber", json!([]), timeout).await?;
|
let response_body = send_rpc_request(endpoint, "eth_blockNumber", json!([]), timeout).await?;
|
||||||
hex_to_u64_be(
|
hex_to_u64_be(
|
||||||
response_result(&response_body)?
|
response_result(&response_body)?
|
||||||
@ -126,7 +127,7 @@ pub async fn get_block_number(endpoint: &str, timeout: Duration) -> Result<u64,
|
|||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
pub async fn get_block(
|
pub async fn get_block(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
query: BlockQuery,
|
query: BlockQuery,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
) -> Result<Block, String> {
|
) -> Result<Block, String> {
|
||||||
@ -191,7 +192,7 @@ pub async fn get_block(
|
|||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
pub async fn get_deposit_count(
|
pub async fn get_deposit_count(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
address: &str,
|
address: &str,
|
||||||
block_number: u64,
|
block_number: u64,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
@ -229,7 +230,7 @@ pub async fn get_deposit_count(
|
|||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
pub async fn get_deposit_root(
|
pub async fn get_deposit_root(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
address: &str,
|
address: &str,
|
||||||
block_number: u64,
|
block_number: u64,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
@ -266,7 +267,7 @@ pub async fn get_deposit_root(
|
|||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
async fn call(
|
async fn call(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
address: &str,
|
address: &str,
|
||||||
hex_data: &str,
|
hex_data: &str,
|
||||||
block_number: u64,
|
block_number: u64,
|
||||||
@ -308,7 +309,7 @@ pub struct Log {
|
|||||||
///
|
///
|
||||||
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
/// Uses HTTP JSON RPC at `endpoint`. E.g., `http://localhost:8545`.
|
||||||
pub async fn get_deposit_logs_in_range(
|
pub async fn get_deposit_logs_in_range(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
address: &str,
|
address: &str,
|
||||||
block_height_range: Range<u64>,
|
block_height_range: Range<u64>,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
@ -353,7 +354,7 @@ pub async fn get_deposit_logs_in_range(
|
|||||||
///
|
///
|
||||||
/// Tries to receive the response and parse the body as a `String`.
|
/// Tries to receive the response and parse the body as a `String`.
|
||||||
pub async fn send_rpc_request(
|
pub async fn send_rpc_request(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
method: &str,
|
method: &str,
|
||||||
params: Value,
|
params: Value,
|
||||||
timeout: Duration,
|
timeout: Duration,
|
||||||
@ -374,7 +375,7 @@ pub async fn send_rpc_request(
|
|||||||
.timeout(timeout)
|
.timeout(timeout)
|
||||||
.build()
|
.build()
|
||||||
.expect("The builder should always build a client")
|
.expect("The builder should always build a client")
|
||||||
.post(endpoint)
|
.post(endpoint.full.clone())
|
||||||
.header(CONTENT_TYPE, "application/json")
|
.header(CONTENT_TYPE, "application/json")
|
||||||
.body(body)
|
.body(body)
|
||||||
.send()
|
.send()
|
||||||
|
@ -11,6 +11,7 @@ use crate::{
|
|||||||
use fallback::{Fallback, FallbackError};
|
use fallback::{Fallback, FallbackError};
|
||||||
use futures::future::TryFutureExt;
|
use futures::future::TryFutureExt;
|
||||||
use parking_lot::{RwLock, RwLockReadGuard};
|
use parking_lot::{RwLock, RwLockReadGuard};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use slog::{crit, debug, error, info, trace, warn, Logger};
|
use slog::{crit, debug, error, info, trace, warn, Logger};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
@ -26,6 +27,8 @@ use types::{ChainSpec, EthSpec, Unsigned};
|
|||||||
pub const DEFAULT_NETWORK_ID: Eth1Id = Eth1Id::Goerli;
|
pub const DEFAULT_NETWORK_ID: Eth1Id = Eth1Id::Goerli;
|
||||||
/// Indicates the default eth1 chain id we use for the deposit contract.
|
/// Indicates the default eth1 chain id we use for the deposit contract.
|
||||||
pub const DEFAULT_CHAIN_ID: Eth1Id = Eth1Id::Goerli;
|
pub const DEFAULT_CHAIN_ID: Eth1Id = Eth1Id::Goerli;
|
||||||
|
/// Indicates the default eth1 endpoint.
|
||||||
|
pub const DEFAULT_ETH1_ENDPOINT: &str = "http://localhost:8545";
|
||||||
|
|
||||||
const STANDARD_TIMEOUT_MILLIS: u64 = 15_000;
|
const STANDARD_TIMEOUT_MILLIS: u64 = 15_000;
|
||||||
|
|
||||||
@ -51,7 +54,7 @@ pub enum EndpointError {
|
|||||||
|
|
||||||
type EndpointState = Result<(), EndpointError>;
|
type EndpointState = Result<(), EndpointError>;
|
||||||
|
|
||||||
type EndpointWithState = (String, TRwLock<Option<EndpointState>>);
|
type EndpointWithState = (SensitiveUrl, TRwLock<Option<EndpointState>>);
|
||||||
|
|
||||||
/// A cache structure to lazily check usability of endpoints. An endpoint is usable if it is
|
/// A cache structure to lazily check usability of endpoints. An endpoint is usable if it is
|
||||||
/// reachable and has the correct network id and chain id. Emits a `WARN` log if a checked endpoint
|
/// reachable and has the correct network id and chain id. Emits a `WARN` log if a checked endpoint
|
||||||
@ -74,7 +77,10 @@ impl EndpointsCache {
|
|||||||
if let Some(result) = *value {
|
if let Some(result) = *value {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
crate::metrics::inc_counter_vec(&crate::metrics::ENDPOINT_REQUESTS, &[&endpoint.0]);
|
crate::metrics::inc_counter_vec(
|
||||||
|
&crate::metrics::ENDPOINT_REQUESTS,
|
||||||
|
&[&endpoint.0.to_string()],
|
||||||
|
);
|
||||||
let state = endpoint_state(
|
let state = endpoint_state(
|
||||||
&endpoint.0,
|
&endpoint.0,
|
||||||
&self.config_network_id,
|
&self.config_network_id,
|
||||||
@ -84,7 +90,10 @@ impl EndpointsCache {
|
|||||||
.await;
|
.await;
|
||||||
*value = Some(state);
|
*value = Some(state);
|
||||||
if state.is_err() {
|
if state.is_err() {
|
||||||
crate::metrics::inc_counter_vec(&crate::metrics::ENDPOINT_ERRORS, &[&endpoint.0]);
|
crate::metrics::inc_counter_vec(
|
||||||
|
&crate::metrics::ENDPOINT_ERRORS,
|
||||||
|
&[&endpoint.0.to_string()],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
}
|
}
|
||||||
@ -94,7 +103,7 @@ impl EndpointsCache {
|
|||||||
func: F,
|
func: F,
|
||||||
) -> Result<O, FallbackError<SingleEndpointError>>
|
) -> Result<O, FallbackError<SingleEndpointError>>
|
||||||
where
|
where
|
||||||
F: Fn(&'a str) -> R,
|
F: Fn(&'a SensitiveUrl) -> R,
|
||||||
R: Future<Output = Result<O, SingleEndpointError>>,
|
R: Future<Output = Result<O, SingleEndpointError>>,
|
||||||
{
|
{
|
||||||
let func = &func;
|
let func = &func;
|
||||||
@ -102,7 +111,7 @@ impl EndpointsCache {
|
|||||||
.first_success(|endpoint| async move {
|
.first_success(|endpoint| async move {
|
||||||
match self.state(endpoint).await {
|
match self.state(endpoint).await {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let endpoint_str = &endpoint.0;
|
let endpoint_str = &endpoint.0.to_string();
|
||||||
crate::metrics::inc_counter_vec(
|
crate::metrics::inc_counter_vec(
|
||||||
&crate::metrics::ENDPOINT_REQUESTS,
|
&crate::metrics::ENDPOINT_REQUESTS,
|
||||||
&[endpoint_str],
|
&[endpoint_str],
|
||||||
@ -131,7 +140,7 @@ impl EndpointsCache {
|
|||||||
/// Returns `Ok` if the endpoint is usable, i.e. is reachable and has a correct network id and
|
/// Returns `Ok` if the endpoint is usable, i.e. is reachable and has a correct network id and
|
||||||
/// chain id. Otherwise it returns `Err`.
|
/// chain id. Otherwise it returns `Err`.
|
||||||
async fn endpoint_state(
|
async fn endpoint_state(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
config_network_id: &Eth1Id,
|
config_network_id: &Eth1Id,
|
||||||
config_chain_id: &Eth1Id,
|
config_chain_id: &Eth1Id,
|
||||||
log: &Logger,
|
log: &Logger,
|
||||||
@ -140,7 +149,7 @@ async fn endpoint_state(
|
|||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"Error connecting to eth1 node endpoint";
|
"Error connecting to eth1 node endpoint";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"action" => "trying fallbacks"
|
"action" => "trying fallbacks"
|
||||||
);
|
);
|
||||||
EndpointError::NotReachable
|
EndpointError::NotReachable
|
||||||
@ -152,7 +161,7 @@ async fn endpoint_state(
|
|||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"Invalid eth1 network id on endpoint. Please switch to correct network id";
|
"Invalid eth1 network id on endpoint. Please switch to correct network id";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"action" => "trying fallbacks",
|
"action" => "trying fallbacks",
|
||||||
"expected" => format!("{:?}",config_network_id),
|
"expected" => format!("{:?}",config_network_id),
|
||||||
"received" => format!("{:?}",network_id),
|
"received" => format!("{:?}",network_id),
|
||||||
@ -168,7 +177,7 @@ async fn endpoint_state(
|
|||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"Remote eth1 node is not synced";
|
"Remote eth1 node is not synced";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"action" => "trying fallbacks"
|
"action" => "trying fallbacks"
|
||||||
);
|
);
|
||||||
return Err(EndpointError::FarBehind);
|
return Err(EndpointError::FarBehind);
|
||||||
@ -177,7 +186,7 @@ async fn endpoint_state(
|
|||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"Invalid eth1 chain id. Please switch to correct chain id on endpoint";
|
"Invalid eth1 chain id. Please switch to correct chain id on endpoint";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"action" => "trying fallbacks",
|
"action" => "trying fallbacks",
|
||||||
"expected" => format!("{:?}",config_chain_id),
|
"expected" => format!("{:?}",config_chain_id),
|
||||||
"received" => format!("{:?}", chain_id),
|
"received" => format!("{:?}", chain_id),
|
||||||
@ -198,7 +207,7 @@ pub enum HeadType {
|
|||||||
/// Returns the head block and the new block ranges relevant for deposits and the block cache
|
/// Returns the head block and the new block ranges relevant for deposits and the block cache
|
||||||
/// from the given endpoint.
|
/// from the given endpoint.
|
||||||
async fn get_remote_head_and_new_block_ranges(
|
async fn get_remote_head_and_new_block_ranges(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
service: &Service,
|
service: &Service,
|
||||||
node_far_behind_seconds: u64,
|
node_far_behind_seconds: u64,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
@ -218,7 +227,7 @@ async fn get_remote_head_and_new_block_ranges(
|
|||||||
warn!(
|
warn!(
|
||||||
service.log,
|
service.log,
|
||||||
"Eth1 endpoint is not synced";
|
"Eth1 endpoint is not synced";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"last_seen_block_unix_timestamp" => remote_head_block.timestamp,
|
"last_seen_block_unix_timestamp" => remote_head_block.timestamp,
|
||||||
"action" => "trying fallback"
|
"action" => "trying fallback"
|
||||||
);
|
);
|
||||||
@ -230,7 +239,7 @@ async fn get_remote_head_and_new_block_ranges(
|
|||||||
warn!(
|
warn!(
|
||||||
service.log,
|
service.log,
|
||||||
"Eth1 endpoint is not synced";
|
"Eth1 endpoint is not synced";
|
||||||
"endpoint" => endpoint,
|
"endpoint" => %endpoint,
|
||||||
"action" => "trying fallbacks"
|
"action" => "trying fallbacks"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -252,7 +261,7 @@ async fn get_remote_head_and_new_block_ranges(
|
|||||||
/// Returns the range of new block numbers to be considered for the given head type from the given
|
/// Returns the range of new block numbers to be considered for the given head type from the given
|
||||||
/// endpoint.
|
/// endpoint.
|
||||||
async fn relevant_new_block_numbers_from_endpoint(
|
async fn relevant_new_block_numbers_from_endpoint(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
service: &Service,
|
service: &Service,
|
||||||
head_type: HeadType,
|
head_type: HeadType,
|
||||||
) -> Result<Option<RangeInclusive<u64>>, SingleEndpointError> {
|
) -> Result<Option<RangeInclusive<u64>>, SingleEndpointError> {
|
||||||
@ -319,7 +328,7 @@ pub struct DepositCacheUpdateOutcome {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
/// An Eth1 node (e.g., Geth) running a HTTP JSON-RPC endpoint.
|
/// An Eth1 node (e.g., Geth) running a HTTP JSON-RPC endpoint.
|
||||||
pub endpoints: Vec<String>,
|
pub endpoints: Vec<SensitiveUrl>,
|
||||||
/// The address the `BlockCache` and `DepositCache` should assume is the canonical deposit contract.
|
/// The address the `BlockCache` and `DepositCache` should assume is the canonical deposit contract.
|
||||||
pub deposit_contract_address: String,
|
pub deposit_contract_address: String,
|
||||||
/// The eth1 network id where the deposit contract is deployed (Goerli/Mainnet).
|
/// The eth1 network id where the deposit contract is deployed (Goerli/Mainnet).
|
||||||
@ -383,7 +392,8 @@ impl Config {
|
|||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
endpoints: vec!["http://localhost:8545".into()],
|
endpoints: vec![SensitiveUrl::parse(DEFAULT_ETH1_ENDPOINT)
|
||||||
|
.expect("The default Eth1 endpoint must always be a valid URL.")],
|
||||||
deposit_contract_address: "0x0000000000000000000000000000000000000000".into(),
|
deposit_contract_address: "0x0000000000000000000000000000000000000000".into(),
|
||||||
network_id: DEFAULT_NETWORK_ID,
|
network_id: DEFAULT_NETWORK_ID,
|
||||||
chain_id: DEFAULT_CHAIN_ID,
|
chain_id: DEFAULT_CHAIN_ID,
|
||||||
@ -1137,7 +1147,7 @@ fn relevant_block_range(
|
|||||||
///
|
///
|
||||||
/// Performs three async calls to an Eth1 HTTP JSON RPC endpoint.
|
/// Performs three async calls to an Eth1 HTTP JSON RPC endpoint.
|
||||||
async fn download_eth1_block(
|
async fn download_eth1_block(
|
||||||
endpoint: &str,
|
endpoint: &SensitiveUrl,
|
||||||
cache: Arc<Inner>,
|
cache: Arc<Inner>,
|
||||||
block_number_opt: Option<u64>,
|
block_number_opt: Option<u64>,
|
||||||
) -> Result<Eth1Block, SingleEndpointError> {
|
) -> Result<Eth1Block, SingleEndpointError> {
|
||||||
@ -1182,6 +1192,12 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use types::MainnetEthSpec;
|
use types::MainnetEthSpec;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// Ensures the default config does not panic.
|
||||||
|
fn default_config() {
|
||||||
|
Config::default();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn serde_serialize() {
|
fn serde_serialize() {
|
||||||
let serialized =
|
let serialized =
|
||||||
|
@ -5,6 +5,7 @@ use eth1::{Config, Service};
|
|||||||
use eth1::{DepositCache, DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
|
use eth1::{DepositCache, DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
|
||||||
use eth1_test_rig::GanacheEth1Instance;
|
use eth1_test_rig::GanacheEth1Instance;
|
||||||
use merkle_proof::verify_merkle_proof;
|
use merkle_proof::verify_merkle_proof;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
use sloggers::{null::NullLoggerBuilder, Build};
|
use sloggers::{null::NullLoggerBuilder, Build};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
@ -53,7 +54,7 @@ fn random_deposit_data() -> DepositData {
|
|||||||
/// Blocking operation to get the deposit logs from the `deposit_contract`.
|
/// Blocking operation to get the deposit logs from the `deposit_contract`.
|
||||||
async fn blocking_deposit_logs(eth1: &GanacheEth1Instance, range: Range<u64>) -> Vec<Log> {
|
async fn blocking_deposit_logs(eth1: &GanacheEth1Instance, range: Range<u64>) -> Vec<Log> {
|
||||||
get_deposit_logs_in_range(
|
get_deposit_logs_in_range(
|
||||||
ð1.endpoint(),
|
&SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
|
||||||
ð1.deposit_contract.address(),
|
ð1.deposit_contract.address(),
|
||||||
range,
|
range,
|
||||||
timeout(),
|
timeout(),
|
||||||
@ -65,7 +66,7 @@ async fn blocking_deposit_logs(eth1: &GanacheEth1Instance, range: Range<u64>) ->
|
|||||||
/// Blocking operation to get the deposit root from the `deposit_contract`.
|
/// Blocking operation to get the deposit root from the `deposit_contract`.
|
||||||
async fn blocking_deposit_root(eth1: &GanacheEth1Instance, block_number: u64) -> Option<Hash256> {
|
async fn blocking_deposit_root(eth1: &GanacheEth1Instance, block_number: u64) -> Option<Hash256> {
|
||||||
get_deposit_root(
|
get_deposit_root(
|
||||||
ð1.endpoint(),
|
&SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
|
||||||
ð1.deposit_contract.address(),
|
ð1.deposit_contract.address(),
|
||||||
block_number,
|
block_number,
|
||||||
timeout(),
|
timeout(),
|
||||||
@ -77,7 +78,7 @@ async fn blocking_deposit_root(eth1: &GanacheEth1Instance, block_number: u64) ->
|
|||||||
/// Blocking operation to get the deposit count from the `deposit_contract`.
|
/// Blocking operation to get the deposit count from the `deposit_contract`.
|
||||||
async fn blocking_deposit_count(eth1: &GanacheEth1Instance, block_number: u64) -> Option<u64> {
|
async fn blocking_deposit_count(eth1: &GanacheEth1Instance, block_number: u64) -> Option<u64> {
|
||||||
get_deposit_count(
|
get_deposit_count(
|
||||||
ð1.endpoint(),
|
&SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
|
||||||
ð1.deposit_contract.address(),
|
ð1.deposit_contract.address(),
|
||||||
block_number,
|
block_number,
|
||||||
timeout(),
|
timeout(),
|
||||||
@ -119,7 +120,7 @@ mod eth1_cache {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: initial_block_number,
|
lowest_cached_block_number: initial_block_number,
|
||||||
follow_distance,
|
follow_distance,
|
||||||
@ -200,7 +201,7 @@ mod eth1_cache {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: get_block_number(&web3).await,
|
lowest_cached_block_number: get_block_number(&web3).await,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -255,7 +256,7 @@ mod eth1_cache {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: get_block_number(&web3).await,
|
lowest_cached_block_number: get_block_number(&web3).await,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -306,7 +307,7 @@ mod eth1_cache {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: get_block_number(&web3).await,
|
lowest_cached_block_number: get_block_number(&web3).await,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -359,7 +360,7 @@ mod deposit_tree {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
deposit_contract_deploy_block: start_block,
|
deposit_contract_deploy_block: start_block,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -440,7 +441,7 @@ mod deposit_tree {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
deposit_contract_deploy_block: start_block,
|
deposit_contract_deploy_block: start_block,
|
||||||
lowest_cached_block_number: start_block,
|
lowest_cached_block_number: start_block,
|
||||||
@ -582,7 +583,7 @@ mod http {
|
|||||||
|
|
||||||
async fn get_block(eth1: &GanacheEth1Instance, block_number: u64) -> Block {
|
async fn get_block(eth1: &GanacheEth1Instance, block_number: u64) -> Block {
|
||||||
eth1::http::get_block(
|
eth1::http::get_block(
|
||||||
ð1.endpoint(),
|
&SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap(),
|
||||||
BlockQuery::Number(block_number),
|
BlockQuery::Number(block_number),
|
||||||
timeout(),
|
timeout(),
|
||||||
)
|
)
|
||||||
@ -698,7 +699,7 @@ mod fast {
|
|||||||
let now = get_block_number(&web3).await;
|
let now = get_block_number(&web3).await;
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
deposit_contract_deploy_block: now,
|
deposit_contract_deploy_block: now,
|
||||||
lowest_cached_block_number: now,
|
lowest_cached_block_number: now,
|
||||||
@ -775,7 +776,7 @@ mod persist {
|
|||||||
|
|
||||||
let now = get_block_number(&web3).await;
|
let now = get_block_number(&web3).await;
|
||||||
let config = Config {
|
let config = Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
deposit_contract_deploy_block: now,
|
deposit_contract_deploy_block: now,
|
||||||
lowest_cached_block_number: now,
|
lowest_cached_block_number: now,
|
||||||
@ -885,7 +886,10 @@ mod fallbacks {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![endpoint1.endpoint(), endpoint2.endpoint()],
|
endpoints: vec![
|
||||||
|
SensitiveUrl::parse(endpoint1.endpoint().as_str()).unwrap(),
|
||||||
|
SensitiveUrl::parse(endpoint2.endpoint().as_str()).unwrap(),
|
||||||
|
],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: initial_block_number,
|
lowest_cached_block_number: initial_block_number,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -961,7 +965,10 @@ mod fallbacks {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![endpoint2.endpoint(), endpoint1.endpoint()],
|
endpoints: vec![
|
||||||
|
SensitiveUrl::parse(endpoint2.endpoint().as_str()).unwrap(),
|
||||||
|
SensitiveUrl::parse(endpoint1.endpoint().as_str()).unwrap(),
|
||||||
|
],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: initial_block_number,
|
lowest_cached_block_number: initial_block_number,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -1028,7 +1035,10 @@ mod fallbacks {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![endpoint2.endpoint(), endpoint1.endpoint()],
|
endpoints: vec![
|
||||||
|
SensitiveUrl::parse(endpoint2.endpoint().as_str()).unwrap(),
|
||||||
|
SensitiveUrl::parse(endpoint1.endpoint().as_str()).unwrap(),
|
||||||
|
],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: initial_block_number,
|
lowest_cached_block_number: initial_block_number,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
@ -1081,7 +1091,10 @@ mod fallbacks {
|
|||||||
|
|
||||||
let service = Service::new(
|
let service = Service::new(
|
||||||
Config {
|
Config {
|
||||||
endpoints: vec![endpoint1.endpoint(), endpoint2.endpoint()],
|
endpoints: vec![
|
||||||
|
SensitiveUrl::parse(endpoint1.endpoint().as_str()).unwrap(),
|
||||||
|
SensitiveUrl::parse(endpoint2.endpoint().as_str()).unwrap(),
|
||||||
|
],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
lowest_cached_block_number: initial_block_number,
|
lowest_cached_block_number: initial_block_number,
|
||||||
follow_distance: 0,
|
follow_distance: 0,
|
||||||
|
@ -7,6 +7,7 @@ edition = "2018"
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
eth1_test_rig = { path = "../../testing/eth1_test_rig" }
|
eth1_test_rig = { path = "../../testing/eth1_test_rig" }
|
||||||
tokio-compat-02 = "0.1"
|
tokio-compat-02 = "0.1"
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
futures = "0.3.7"
|
futures = "0.3.7"
|
||||||
|
@ -7,6 +7,7 @@ use environment::{Environment, EnvironmentBuilder};
|
|||||||
use eth1::{DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
|
use eth1::{DEFAULT_CHAIN_ID, DEFAULT_NETWORK_ID};
|
||||||
use eth1_test_rig::{DelayThenDeposit, GanacheEth1Instance};
|
use eth1_test_rig::{DelayThenDeposit, GanacheEth1Instance};
|
||||||
use genesis::{Eth1Config, Eth1GenesisService};
|
use genesis::{Eth1Config, Eth1GenesisService};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use state_processing::is_valid_genesis_state;
|
use state_processing::is_valid_genesis_state;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use tokio_compat_02::FutureExt;
|
use tokio_compat_02::FutureExt;
|
||||||
@ -46,7 +47,7 @@ fn basic() {
|
|||||||
|
|
||||||
let service = Eth1GenesisService::new(
|
let service = Eth1GenesisService::new(
|
||||||
Eth1Config {
|
Eth1Config {
|
||||||
endpoints: vec![eth1.endpoint()],
|
endpoints: vec![SensitiveUrl::parse(eth1.endpoint().as_str()).unwrap()],
|
||||||
deposit_contract_address: deposit_contract.address(),
|
deposit_contract_address: deposit_contract.address(),
|
||||||
deposit_contract_deploy_block: now,
|
deposit_contract_deploy_block: now,
|
||||||
lowest_cached_block_number: now,
|
lowest_cached_block_number: now,
|
||||||
|
@ -35,3 +35,4 @@ store = { path = "../store" }
|
|||||||
environment = { path = "../../lighthouse/environment" }
|
environment = { path = "../../lighthouse/environment" }
|
||||||
tree_hash = "0.1.1"
|
tree_hash = "0.1.1"
|
||||||
discv5 = { git = "https://github.com/sigp/discv5 ", rev = "02d2c896c66f8dc2b848c3996fedcd98e1dfec69", features = ["libp2p"] }
|
discv5 = { git = "https://github.com/sigp/discv5 ", rev = "02d2c896c66f8dc2b848c3996fedcd98e1dfec69", features = ["libp2p"] }
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
@ -8,7 +8,7 @@ use discv5::enr::{CombinedKey, EnrBuilder};
|
|||||||
use environment::null_logger;
|
use environment::null_logger;
|
||||||
use eth2::Error;
|
use eth2::Error;
|
||||||
use eth2::StatusCode;
|
use eth2::StatusCode;
|
||||||
use eth2::{types::*, BeaconNodeHttpClient, Url};
|
use eth2::{types::*, BeaconNodeHttpClient};
|
||||||
use eth2_libp2p::{
|
use eth2_libp2p::{
|
||||||
rpc::methods::MetaData,
|
rpc::methods::MetaData,
|
||||||
types::{EnrBitfield, SyncState},
|
types::{EnrBitfield, SyncState},
|
||||||
@ -18,6 +18,7 @@ use futures::stream::{Stream, StreamExt};
|
|||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
use http_api::{Config, Context};
|
use http_api::{Config, Context};
|
||||||
use network::NetworkMessage;
|
use network::NetworkMessage;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use slot_clock::SlotClock;
|
use slot_clock::SlotClock;
|
||||||
use state_processing::per_slot_processing;
|
use state_processing::per_slot_processing;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
@ -200,7 +201,7 @@ impl ApiTester {
|
|||||||
tokio::spawn(async { server.await });
|
tokio::spawn(async { server.await });
|
||||||
|
|
||||||
let client = BeaconNodeHttpClient::new(
|
let client = BeaconNodeHttpClient::new(
|
||||||
Url::parse(&format!(
|
SensitiveUrl::parse(&format!(
|
||||||
"http://{}:{}",
|
"http://{}:{}",
|
||||||
listening_socket.ip(),
|
listening_socket.ip(),
|
||||||
listening_socket.port()
|
listening_socket.port()
|
||||||
@ -307,7 +308,7 @@ impl ApiTester {
|
|||||||
tokio::spawn(async { server.await });
|
tokio::spawn(async { server.await });
|
||||||
|
|
||||||
let client = BeaconNodeHttpClient::new(
|
let client = BeaconNodeHttpClient::new(
|
||||||
Url::parse(&format!(
|
SensitiveUrl::parse(&format!(
|
||||||
"http://{}:{}",
|
"http://{}:{}",
|
||||||
listening_socket.ip(),
|
listening_socket.ip(),
|
||||||
listening_socket.port()
|
listening_socket.port()
|
||||||
|
@ -4,6 +4,7 @@ use client::{ClientConfig, ClientGenesis};
|
|||||||
use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR};
|
use directory::{DEFAULT_BEACON_NODE_DIR, DEFAULT_NETWORK_DIR, DEFAULT_ROOT_DIR};
|
||||||
use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized};
|
use eth2_libp2p::{multiaddr::Protocol, Enr, Multiaddr, NetworkConfig, PeerIdSerialized};
|
||||||
use eth2_network_config::{Eth2NetworkConfig, DEFAULT_HARDCODED_NETWORK};
|
use eth2_network_config::{Eth2NetworkConfig, DEFAULT_HARDCODED_NETWORK};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use slog::{info, warn, Logger};
|
use slog::{info, warn, Logger};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
@ -163,17 +164,21 @@ pub fn get_config<E: EthSpec>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Defines the URL to reach the eth1 node.
|
// Defines the URL to reach the eth1 node.
|
||||||
if let Some(val) = cli_args.value_of("eth1-endpoint") {
|
if let Some(endpoint) = cli_args.value_of("eth1-endpoint") {
|
||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"The --eth1-endpoint flag is deprecated";
|
"The --eth1-endpoint flag is deprecated";
|
||||||
"msg" => "please use --eth1-endpoints instead"
|
"msg" => "please use --eth1-endpoints instead"
|
||||||
);
|
);
|
||||||
client_config.sync_eth1_chain = true;
|
client_config.sync_eth1_chain = true;
|
||||||
client_config.eth1.endpoints = vec![val.to_string()];
|
client_config.eth1.endpoints = vec![SensitiveUrl::parse(endpoint)
|
||||||
} else if let Some(val) = cli_args.value_of("eth1-endpoints") {
|
.map_err(|e| format!("eth1-endpoint was an invalid URL: {:?}", e))?];
|
||||||
client_config.sync_eth1_chain = true;
|
} else if let Some(endpoints) = cli_args.value_of("eth1-endpoints") {
|
||||||
client_config.eth1.endpoints = val.split(',').map(String::from).collect();
|
client_config.eth1.endpoints = endpoints
|
||||||
|
.split(',')
|
||||||
|
.map(|s| SensitiveUrl::parse(s))
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.map_err(|e| format!("eth1-endpoints contains an invalid URL {:?}", e))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(val) = cli_args.value_of("eth1-blocks-per-log-query") {
|
if let Some(val) = cli_args.value_of("eth1-blocks-per-log-query") {
|
||||||
|
@ -21,6 +21,7 @@ libsecp256k1 = "0.3.5"
|
|||||||
ring = "0.16.19"
|
ring = "0.16.19"
|
||||||
bytes = "1.0.1"
|
bytes = "1.0.1"
|
||||||
account_utils = { path = "../../common/account_utils" }
|
account_utils = { path = "../../common/account_utils" }
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
eth2_ssz = "0.1.2"
|
eth2_ssz = "0.1.2"
|
||||||
eth2_ssz_derive = "0.1.0"
|
eth2_ssz_derive = "0.1.0"
|
||||||
futures-util = "0.3.8"
|
futures-util = "0.3.8"
|
||||||
|
@ -19,6 +19,7 @@ use futures_util::StreamExt;
|
|||||||
pub use reqwest;
|
pub use reqwest;
|
||||||
use reqwest::{IntoUrl, Response};
|
use reqwest::{IntoUrl, Response};
|
||||||
pub use reqwest::{StatusCode, Url};
|
pub use reqwest::{StatusCode, Url};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
use ssz::Decode;
|
use ssz::Decode;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
@ -36,7 +37,7 @@ pub enum Error {
|
|||||||
/// The server returned an error message where the body was unable to be parsed.
|
/// The server returned an error message where the body was unable to be parsed.
|
||||||
StatusCode(StatusCode),
|
StatusCode(StatusCode),
|
||||||
/// The supplied URL is badly formatted. It should look something like `http://127.0.0.1:5052`.
|
/// The supplied URL is badly formatted. It should look something like `http://127.0.0.1:5052`.
|
||||||
InvalidUrl(Url),
|
InvalidUrl(SensitiveUrl),
|
||||||
/// The supplied validator client secret is invalid.
|
/// The supplied validator client secret is invalid.
|
||||||
InvalidSecret(String),
|
InvalidSecret(String),
|
||||||
/// The server returned a response with an invalid signature. It may be an impostor.
|
/// The server returned a response with an invalid signature. It may be an impostor.
|
||||||
@ -81,7 +82,7 @@ impl fmt::Display for Error {
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct BeaconNodeHttpClient {
|
pub struct BeaconNodeHttpClient {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
server: Url,
|
server: SensitiveUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BeaconNodeHttpClient {
|
impl fmt::Display for BeaconNodeHttpClient {
|
||||||
@ -92,25 +93,25 @@ impl fmt::Display for BeaconNodeHttpClient {
|
|||||||
|
|
||||||
impl AsRef<str> for BeaconNodeHttpClient {
|
impl AsRef<str> for BeaconNodeHttpClient {
|
||||||
fn as_ref(&self) -> &str {
|
fn as_ref(&self) -> &str {
|
||||||
self.server.as_str()
|
self.server.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeaconNodeHttpClient {
|
impl BeaconNodeHttpClient {
|
||||||
pub fn new(server: Url) -> Self {
|
pub fn new(server: SensitiveUrl) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: reqwest::Client::new(),
|
client: reqwest::Client::new(),
|
||||||
server,
|
server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_components(server: Url, client: reqwest::Client) -> Self {
|
pub fn from_components(server: SensitiveUrl, client: reqwest::Client) -> Self {
|
||||||
Self { client, server }
|
Self { client, server }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the path with the standard `/eth1/v1` prefix applied.
|
/// Return the path with the standard `/eth1/v1` prefix applied.
|
||||||
fn eth_path(&self) -> Result<Url, Error> {
|
fn eth_path(&self) -> Result<Url, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
|
@ -214,7 +214,7 @@ impl BeaconNodeHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/health`
|
/// `GET lighthouse/health`
|
||||||
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -226,7 +226,7 @@ impl BeaconNodeHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/syncing`
|
/// `GET lighthouse/syncing`
|
||||||
pub async fn get_lighthouse_syncing(&self) -> Result<GenericResponse<SyncState>, Error> {
|
pub async fn get_lighthouse_syncing(&self) -> Result<GenericResponse<SyncState>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -246,7 +246,7 @@ impl BeaconNodeHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/proto_array`
|
/// `GET lighthouse/proto_array`
|
||||||
pub async fn get_lighthouse_proto_array(&self) -> Result<GenericResponse<ProtoArray>, Error> {
|
pub async fn get_lighthouse_proto_array(&self) -> Result<GenericResponse<ProtoArray>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -261,7 +261,7 @@ impl BeaconNodeHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
) -> Result<GenericResponse<GlobalValidatorInclusionData>, Error> {
|
) -> Result<GenericResponse<GlobalValidatorInclusionData>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -279,7 +279,7 @@ impl BeaconNodeHttpClient {
|
|||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
validator_id: ValidatorId,
|
validator_id: ValidatorId,
|
||||||
) -> Result<GenericResponse<Option<ValidatorInclusionData>>, Error> {
|
) -> Result<GenericResponse<Option<ValidatorInclusionData>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -295,7 +295,7 @@ impl BeaconNodeHttpClient {
|
|||||||
pub async fn get_lighthouse_eth1_syncing(
|
pub async fn get_lighthouse_eth1_syncing(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<GenericResponse<Eth1SyncStatusData>, Error> {
|
) -> Result<GenericResponse<Eth1SyncStatusData>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -310,7 +310,7 @@ impl BeaconNodeHttpClient {
|
|||||||
pub async fn get_lighthouse_eth1_block_cache(
|
pub async fn get_lighthouse_eth1_block_cache(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<GenericResponse<Vec<Eth1Block>>, Error> {
|
) -> Result<GenericResponse<Vec<Eth1Block>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -325,7 +325,7 @@ impl BeaconNodeHttpClient {
|
|||||||
pub async fn get_lighthouse_eth1_deposit_cache(
|
pub async fn get_lighthouse_eth1_deposit_cache(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<GenericResponse<Vec<DepositLog>>, Error> {
|
) -> Result<GenericResponse<Vec<DepositLog>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -341,7 +341,7 @@ impl BeaconNodeHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
state_id: &StateId,
|
state_id: &StateId,
|
||||||
) -> Result<Option<BeaconState<E>>, Error> {
|
) -> Result<Option<BeaconState<E>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -359,7 +359,7 @@ impl BeaconNodeHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/staking`
|
/// `GET lighthouse/staking`
|
||||||
pub async fn get_lighthouse_staking(&self) -> Result<bool, Error> {
|
pub async fn get_lighthouse_staking(&self) -> Result<bool, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
|
@ -8,6 +8,7 @@ use reqwest::{
|
|||||||
};
|
};
|
||||||
use ring::digest::{digest, SHA256};
|
use ring::digest::{digest, SHA256};
|
||||||
use secp256k1::{Message, PublicKey, Signature};
|
use secp256k1::{Message, PublicKey, Signature};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::{de::DeserializeOwned, Serialize};
|
use serde::{de::DeserializeOwned, Serialize};
|
||||||
|
|
||||||
pub use reqwest;
|
pub use reqwest;
|
||||||
@ -18,7 +19,7 @@ pub use reqwest::{Response, StatusCode, Url};
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ValidatorClientHttpClient {
|
pub struct ValidatorClientHttpClient {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
server: Url,
|
server: SensitiveUrl,
|
||||||
secret: ZeroizeString,
|
secret: ZeroizeString,
|
||||||
server_pubkey: PublicKey,
|
server_pubkey: PublicKey,
|
||||||
}
|
}
|
||||||
@ -53,7 +54,7 @@ pub fn parse_pubkey(secret: &str) -> Result<PublicKey, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ValidatorClientHttpClient {
|
impl ValidatorClientHttpClient {
|
||||||
pub fn new(server: Url, secret: String) -> Result<Self, Error> {
|
pub fn new(server: SensitiveUrl, secret: String) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
client: reqwest::Client::new(),
|
client: reqwest::Client::new(),
|
||||||
server,
|
server,
|
||||||
@ -63,7 +64,7 @@ impl ValidatorClientHttpClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_components(
|
pub fn from_components(
|
||||||
server: Url,
|
server: SensitiveUrl,
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
secret: String,
|
secret: String,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
@ -187,7 +188,7 @@ impl ValidatorClientHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/version`
|
/// `GET lighthouse/version`
|
||||||
pub async fn get_lighthouse_version(&self) -> Result<GenericResponse<VersionData>, Error> {
|
pub async fn get_lighthouse_version(&self) -> Result<GenericResponse<VersionData>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -199,7 +200,7 @@ impl ValidatorClientHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/health`
|
/// `GET lighthouse/health`
|
||||||
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
pub async fn get_lighthouse_health(&self) -> Result<GenericResponse<Health>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -211,7 +212,7 @@ impl ValidatorClientHttpClient {
|
|||||||
|
|
||||||
/// `GET lighthouse/spec`
|
/// `GET lighthouse/spec`
|
||||||
pub async fn get_lighthouse_spec(&self) -> Result<GenericResponse<YamlConfig>, Error> {
|
pub async fn get_lighthouse_spec(&self) -> Result<GenericResponse<YamlConfig>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -225,7 +226,7 @@ impl ValidatorClientHttpClient {
|
|||||||
pub async fn get_lighthouse_validators(
|
pub async fn get_lighthouse_validators(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<GenericResponse<Vec<ValidatorData>>, Error> {
|
) -> Result<GenericResponse<Vec<ValidatorData>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -240,7 +241,7 @@ impl ValidatorClientHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
validator_pubkey: &PublicKeyBytes,
|
validator_pubkey: &PublicKeyBytes,
|
||||||
) -> Result<Option<GenericResponse<ValidatorData>>, Error> {
|
) -> Result<Option<GenericResponse<ValidatorData>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -256,7 +257,7 @@ impl ValidatorClientHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
validators: Vec<ValidatorRequest>,
|
validators: Vec<ValidatorRequest>,
|
||||||
) -> Result<GenericResponse<PostValidatorsResponseData>, Error> {
|
) -> Result<GenericResponse<PostValidatorsResponseData>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -271,7 +272,7 @@ impl ValidatorClientHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
request: &CreateValidatorsMnemonicRequest,
|
request: &CreateValidatorsMnemonicRequest,
|
||||||
) -> Result<GenericResponse<Vec<CreatedValidator>>, Error> {
|
) -> Result<GenericResponse<Vec<CreatedValidator>>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -287,7 +288,7 @@ impl ValidatorClientHttpClient {
|
|||||||
&self,
|
&self,
|
||||||
request: &KeystoreValidatorsPostRequest,
|
request: &KeystoreValidatorsPostRequest,
|
||||||
) -> Result<GenericResponse<ValidatorData>, Error> {
|
) -> Result<GenericResponse<ValidatorData>, Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
@ -304,7 +305,7 @@ impl ValidatorClientHttpClient {
|
|||||||
voting_pubkey: &PublicKeyBytes,
|
voting_pubkey: &PublicKeyBytes,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
|
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
|
@ -13,3 +13,4 @@ reqwest = { version = "0.11.0", features = ["json"] }
|
|||||||
serde = { version = "1.0.116", features = ["derive"] }
|
serde = { version = "1.0.116", features = ["derive"] }
|
||||||
tokio = { version = "1.1.0", features = ["time"] }
|
tokio = { version = "1.1.0", features = ["time"] }
|
||||||
types = { path = "../../consensus/types" }
|
types = { path = "../../consensus/types" }
|
||||||
|
sensitive_url = { path = "../sensitive_url" }
|
||||||
|
@ -4,17 +4,18 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use reqwest::StatusCode;
|
use reqwest::StatusCode;
|
||||||
pub use reqwest::Url;
|
pub use reqwest::Url;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use types::{Domain, Fork, Hash256};
|
use types::{Domain, Fork, Hash256};
|
||||||
|
|
||||||
/// A wrapper around `reqwest::Client` which provides convenience methods
|
/// A wrapper around `reqwest::Client` which provides convenience methods
|
||||||
/// to interface with a BLS Remote Signer.
|
/// to interface with a BLS Remote Signer.
|
||||||
pub struct RemoteSignerHttpConsumer {
|
pub struct RemoteSignerHttpConsumer {
|
||||||
client: reqwest::Client,
|
client: reqwest::Client,
|
||||||
server: Url,
|
server: SensitiveUrl,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RemoteSignerHttpConsumer {
|
impl RemoteSignerHttpConsumer {
|
||||||
pub fn from_components(server: Url, client: reqwest::Client) -> Self {
|
pub fn from_components(server: SensitiveUrl, client: reqwest::Client) -> Self {
|
||||||
Self { client, server }
|
Self { client, server }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ impl RemoteSignerHttpConsumer {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut path = self.server.clone();
|
let mut path = self.server.full.clone();
|
||||||
path.path_segments_mut()
|
path.path_segments_mut()
|
||||||
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
.map_err(|()| Error::InvalidUrl(self.server.clone()))?
|
||||||
.push("sign")
|
.push("sign")
|
||||||
|
@ -20,10 +20,11 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! use remote_signer_consumer::RemoteSignerHttpConsumer;
|
//! use remote_signer_consumer::RemoteSignerHttpConsumer;
|
||||||
//! use reqwest::{ClientBuilder, Url};
|
//! use reqwest::ClientBuilder;
|
||||||
|
//! use sensitive_url::SensitiveUrl;
|
||||||
//! use tokio::time::Duration;
|
//! use tokio::time::Duration;
|
||||||
//!
|
//!
|
||||||
//! let url: Url = "http://127.0.0.1:9000".parse().unwrap();
|
//! let url = SensitiveUrl::parse("http://127.0.0.1:9000").unwrap();
|
||||||
//! let reqwest_client = ClientBuilder::new()
|
//! let reqwest_client = ClientBuilder::new()
|
||||||
//! .timeout(Duration::from_secs(2))
|
//! .timeout(Duration::from_secs(2))
|
||||||
//! .build()
|
//! .build()
|
||||||
@ -115,6 +116,7 @@ mod http_client;
|
|||||||
|
|
||||||
pub use http_client::RemoteSignerHttpConsumer;
|
pub use http_client::RemoteSignerHttpConsumer;
|
||||||
pub use reqwest::Url;
|
pub use reqwest::Url;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use types::{AttestationData, BeaconBlock, Domain, Epoch, EthSpec, Fork, Hash256, SignedRoot};
|
use types::{AttestationData, BeaconBlock, Domain, Epoch, EthSpec, Fork, Hash256, SignedRoot};
|
||||||
|
|
||||||
@ -125,7 +127,7 @@ pub enum Error {
|
|||||||
/// The server returned an error message where the body was able to be parsed.
|
/// The server returned an error message where the body was able to be parsed.
|
||||||
ServerMessage(String),
|
ServerMessage(String),
|
||||||
/// The supplied URL is badly formatted. It should look something like `http://127.0.0.1:5052`.
|
/// The supplied URL is badly formatted. It should look something like `http://127.0.0.1:5052`.
|
||||||
InvalidUrl(Url),
|
InvalidUrl(SensitiveUrl),
|
||||||
/// The supplied parameter is invalid.
|
/// The supplied parameter is invalid.
|
||||||
InvalidParameter(String),
|
InvalidParameter(String),
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
mod post {
|
mod post {
|
||||||
use remote_signer_consumer::{Error, RemoteSignerHttpConsumer};
|
use remote_signer_consumer::{Error, RemoteSignerHttpConsumer};
|
||||||
use remote_signer_test::*;
|
use remote_signer_test::*;
|
||||||
use reqwest::{ClientBuilder, Url};
|
use reqwest::ClientBuilder;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use tokio::time::Duration;
|
use tokio::time::Duration;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -53,7 +54,7 @@ mod post {
|
|||||||
let (test_signer, _tmp_dir) = set_up_api_test_signer_to_sign_message();
|
let (test_signer, _tmp_dir) = set_up_api_test_signer_to_sign_message();
|
||||||
|
|
||||||
let run_testcase = |u: &str| -> Result<String, String> {
|
let run_testcase = |u: &str| -> Result<String, String> {
|
||||||
let url: Url = u.parse().map_err(|e| format!("[ParseError] {:?}", e))?;
|
let url = SensitiveUrl::parse(u).map_err(|e| format!("{:?}", e))?;
|
||||||
|
|
||||||
let reqwest_client = ClientBuilder::new()
|
let reqwest_client = ClientBuilder::new()
|
||||||
.timeout(Duration::from_secs(12))
|
.timeout(Duration::from_secs(12))
|
||||||
@ -66,7 +67,7 @@ mod post {
|
|||||||
let signature = do_sign_request(&test_client, test_input);
|
let signature = do_sign_request(&test_client, test_input);
|
||||||
|
|
||||||
signature.map_err(|e| match e {
|
signature.map_err(|e| match e {
|
||||||
Error::InvalidUrl(message) => format!("[InvalidUrl] {:?}", message),
|
Error::InvalidUrl(message) => format!("{:?}", message),
|
||||||
Error::Reqwest(re) => {
|
Error::Reqwest(re) => {
|
||||||
if re.is_builder() {
|
if re.is_builder() {
|
||||||
format!("[Reqwest - Builder] {:?}", re.url().unwrap())
|
format!("[Reqwest - Builder] {:?}", re.url().unwrap())
|
||||||
@ -84,25 +85,22 @@ mod post {
|
|||||||
|
|
||||||
// url::parser::ParseError.
|
// url::parser::ParseError.
|
||||||
// These cases don't even make it to the step of building a RemoteSignerHttpConsumer.
|
// These cases don't even make it to the step of building a RemoteSignerHttpConsumer.
|
||||||
testcase("", "[ParseError] RelativeUrlWithoutBase");
|
testcase("", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase("/4/8/15/16/23/42", "[ParseError] RelativeUrlWithoutBase");
|
testcase("/4/8/15/16/23/42", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase("localhost", "[ParseError] RelativeUrlWithoutBase");
|
testcase("localhost", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase(":", "[ParseError] RelativeUrlWithoutBase");
|
testcase(":", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase("0.0:0", "[ParseError] RelativeUrlWithoutBase");
|
testcase("0.0:0", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase(":aa", "[ParseError] RelativeUrlWithoutBase");
|
testcase(":aa", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase("0:", "[ParseError] RelativeUrlWithoutBase");
|
testcase("0:", "ParseError(RelativeUrlWithoutBase)");
|
||||||
testcase("ftp://", "[ParseError] EmptyHost");
|
testcase("ftp://", "ParseError(EmptyHost)");
|
||||||
testcase("http://", "[ParseError] EmptyHost");
|
testcase("http://", "ParseError(EmptyHost)");
|
||||||
testcase("http://127.0.0.1:abcd", "[ParseError] InvalidPort");
|
testcase("http://127.0.0.1:abcd", "ParseError(InvalidPort)");
|
||||||
testcase("http://280.0.0.1", "[ParseError] InvalidIpv4Address");
|
testcase("http://280.0.0.1", "ParseError(InvalidIpv4Address)");
|
||||||
|
|
||||||
// `Error::InvalidUrl`.
|
// `Error::InvalidUrl`.
|
||||||
// The RemoteSignerHttpConsumer is created, but fails at `path_segments_mut()`.
|
// The RemoteSignerHttpConsumer is created, but fails at `path_segments_mut()`.
|
||||||
testcase(
|
testcase("localhost:abcd", "InvalidUrl(\"URL cannot be a base.\")");
|
||||||
"localhost:abcd",
|
testcase("localhost:", "InvalidUrl(\"URL cannot be a base.\")");
|
||||||
"[InvalidUrl] Url { scheme: \"localhost\", username: \"\", password: None, host: None, port: None, path: \"abcd\", query: None, fragment: None }",
|
|
||||||
);
|
|
||||||
testcase("localhost:", "[InvalidUrl] Url { scheme: \"localhost\", username: \"\", password: None, host: None, port: None, path: \"\", query: None, fragment: None }");
|
|
||||||
|
|
||||||
// `Reqwest::Error` of the `Builder` kind.
|
// `Reqwest::Error` of the `Builder` kind.
|
||||||
// POST is not made.
|
// POST is not made.
|
||||||
@ -130,7 +128,7 @@ mod post {
|
|||||||
let (test_signer, _tmp_dir) = set_up_api_test_signer_to_sign_message();
|
let (test_signer, _tmp_dir) = set_up_api_test_signer_to_sign_message();
|
||||||
|
|
||||||
let run_testcase = |u: &str| -> Result<String, String> {
|
let run_testcase = |u: &str| -> Result<String, String> {
|
||||||
let url: Url = u.parse().unwrap();
|
let url = SensitiveUrl::parse(u).unwrap();
|
||||||
|
|
||||||
let reqwest_client = ClientBuilder::new()
|
let reqwest_client = ClientBuilder::new()
|
||||||
.timeout(Duration::from_secs(12))
|
.timeout(Duration::from_secs(12))
|
||||||
|
11
common/sensitive_url/Cargo.toml
Normal file
11
common/sensitive_url/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[package]
|
||||||
|
name = "sensitive_url"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Mac L <mjladson@pm.me>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
url = "2.2.1"
|
||||||
|
serde = "1.0.116"
|
105
common/sensitive_url/src/lib.rs
Normal file
105
common/sensitive_url/src/lib.rs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
use std::fmt;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SensitiveError {
|
||||||
|
InvalidUrl(String),
|
||||||
|
ParseError(url::ParseError),
|
||||||
|
RedactError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapper around Url which provides a custom `Display` implementation to protect user secrets.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct SensitiveUrl {
|
||||||
|
pub full: Url,
|
||||||
|
pub redacted: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SensitiveUrl {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.redacted.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for SensitiveUrl {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.redacted.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRef<str> for SensitiveUrl {
|
||||||
|
fn as_ref(&self) -> &str {
|
||||||
|
self.redacted.as_str()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for SensitiveUrl {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.full.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for SensitiveUrl {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let s: String = Deserialize::deserialize(deserializer)?;
|
||||||
|
SensitiveUrl::parse(&s)
|
||||||
|
.map_err(|e| de::Error::custom(format!("Failed to deserialize sensitive URL {:?}", e)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensitiveUrl {
|
||||||
|
pub fn parse(url: &str) -> Result<Self, SensitiveError> {
|
||||||
|
let surl = Url::parse(url).map_err(SensitiveError::ParseError)?;
|
||||||
|
SensitiveUrl::new(surl)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(full: Url) -> Result<Self, SensitiveError> {
|
||||||
|
let mut redacted = full.clone();
|
||||||
|
redacted
|
||||||
|
.path_segments_mut()
|
||||||
|
.map_err(|_| SensitiveError::InvalidUrl("URL cannot be a base.".to_string()))?
|
||||||
|
.clear();
|
||||||
|
redacted.set_query(None);
|
||||||
|
|
||||||
|
if redacted.has_authority() {
|
||||||
|
redacted.set_username("").map_err(|_| {
|
||||||
|
SensitiveError::RedactError("Unable to redact username.".to_string())
|
||||||
|
})?;
|
||||||
|
redacted.set_password(None).map_err(|_| {
|
||||||
|
SensitiveError::RedactError("Unable to redact password.".to_string())
|
||||||
|
})?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
full,
|
||||||
|
redacted: redacted.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn redact_remote_url() {
|
||||||
|
let full = "https://project:secret@example.com/example?somequery";
|
||||||
|
let surl = SensitiveUrl::parse(full).unwrap();
|
||||||
|
assert_eq!(surl.to_string(), "https://example.com/");
|
||||||
|
assert_eq!(surl.full.to_string(), full);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn redact_localhost_url() {
|
||||||
|
let full = "http://localhost:5052/";
|
||||||
|
let surl = SensitiveUrl::parse(full).unwrap();
|
||||||
|
assert_eq!(surl.to_string(), "http://localhost:5052/");
|
||||||
|
assert_eq!(surl.full.to_string(), full);
|
||||||
|
}
|
||||||
|
}
|
@ -39,3 +39,4 @@ account_utils = { path = "../common/account_utils" }
|
|||||||
eth2_wallet = { path = "../crypto/eth2_wallet" }
|
eth2_wallet = { path = "../crypto/eth2_wallet" }
|
||||||
web3 = "0.14.0"
|
web3 = "0.14.0"
|
||||||
eth1_test_rig = { path = "../testing/eth1_test_rig" }
|
eth1_test_rig = { path = "../testing/eth1_test_rig" }
|
||||||
|
sensitive_url = { path = "../common/sensitive_url" }
|
||||||
|
@ -2,6 +2,7 @@ use clap::ArgMatches;
|
|||||||
use environment::Environment;
|
use environment::Environment;
|
||||||
use eth2_network_config::Eth2NetworkConfig;
|
use eth2_network_config::Eth2NetworkConfig;
|
||||||
use genesis::{Eth1Config, Eth1GenesisService};
|
use genesis::{Eth1Config, Eth1GenesisService};
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use ssz::Encode;
|
use ssz::Encode;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@ -50,7 +51,11 @@ pub fn run<T: EthSpec>(mut env: Environment<T>, matches: &ArgMatches<'_>) -> Res
|
|||||||
|
|
||||||
let mut config = Eth1Config::default();
|
let mut config = Eth1Config::default();
|
||||||
if let Some(v) = endpoints.clone() {
|
if let Some(v) = endpoints.clone() {
|
||||||
config.endpoints = v;
|
config.endpoints = v
|
||||||
|
.iter()
|
||||||
|
.map(|s| SensitiveUrl::parse(s))
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.map_err(|e| format!("Unable to parse eth1 endpoint URL: {:?}", e))?;
|
||||||
}
|
}
|
||||||
config.deposit_contract_address = format!("{:?}", spec.deposit_contract_address);
|
config.deposit_contract_address = format!("{:?}", spec.deposit_contract_address);
|
||||||
config.deposit_contract_deploy_block = eth2_network_config.deposit_contract_deploy_block;
|
config.deposit_contract_deploy_block = eth2_network_config.deposit_contract_deploy_block;
|
||||||
|
@ -18,3 +18,4 @@ genesis = { path = "../../beacon_node/genesis" }
|
|||||||
eth2 = { path = "../../common/eth2" }
|
eth2 = { path = "../../common/eth2" }
|
||||||
validator_client = { path = "../../validator_client" }
|
validator_client = { path = "../../validator_client" }
|
||||||
validator_dir = { path = "../../common/validator_dir", features = ["insecure_keys"] }
|
validator_dir = { path = "../../common/validator_dir", features = ["insecure_keys"] }
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
@ -4,10 +4,8 @@
|
|||||||
|
|
||||||
use beacon_node::ProductionBeaconNode;
|
use beacon_node::ProductionBeaconNode;
|
||||||
use environment::RuntimeContext;
|
use environment::RuntimeContext;
|
||||||
use eth2::{
|
use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient};
|
||||||
reqwest::{ClientBuilder, Url},
|
use sensitive_url::SensitiveUrl;
|
||||||
BeaconNodeHttpClient,
|
|
||||||
};
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
@ -68,9 +66,10 @@ impl<E: EthSpec> LocalBeaconNode<E> {
|
|||||||
.http_api_listen_addr()
|
.http_api_listen_addr()
|
||||||
.ok_or("A remote beacon node must have a http server")?;
|
.ok_or("A remote beacon node must have a http server")?;
|
||||||
|
|
||||||
let beacon_node_url: Url = format!("http://{}:{}", listen_addr.ip(), listen_addr.port())
|
let beacon_node_url: SensitiveUrl = SensitiveUrl::parse(
|
||||||
.parse()
|
format!("http://{}:{}", listen_addr.ip(), listen_addr.port()).as_str(),
|
||||||
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?;
|
)
|
||||||
|
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?;
|
||||||
let beacon_node_http_client = ClientBuilder::new()
|
let beacon_node_http_client = ClientBuilder::new()
|
||||||
.timeout(HTTP_TIMEOUT)
|
.timeout(HTTP_TIMEOUT)
|
||||||
.build()
|
.build()
|
||||||
|
@ -17,3 +17,4 @@ serde_json = "1.0.58"
|
|||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
tokio = { version = "1.1.0", features = ["time"] }
|
tokio = { version = "1.1.0", features = ["time"] }
|
||||||
types = { path = "../../consensus/types" }
|
types = { path = "../../consensus/types" }
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
use crate::*;
|
use crate::*;
|
||||||
use remote_signer_client::api_response::SignatureApiResponse;
|
use remote_signer_client::api_response::SignatureApiResponse;
|
||||||
use remote_signer_consumer::{Error, RemoteSignerHttpConsumer, RemoteSignerObject, Url};
|
use remote_signer_consumer::{Error, RemoteSignerHttpConsumer, RemoteSignerObject};
|
||||||
use reqwest::ClientBuilder;
|
use reqwest::ClientBuilder;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use tokio::runtime::Builder;
|
use tokio::runtime::Builder;
|
||||||
use tokio::time::Duration;
|
use tokio::time::Duration;
|
||||||
@ -15,7 +16,7 @@ pub fn set_up_test_consumer_with_timeout(
|
|||||||
test_signer_address: &str,
|
test_signer_address: &str,
|
||||||
timeout: u64,
|
timeout: u64,
|
||||||
) -> RemoteSignerHttpConsumer {
|
) -> RemoteSignerHttpConsumer {
|
||||||
let url: Url = test_signer_address.parse().unwrap();
|
let url = SensitiveUrl::parse(test_signer_address).unwrap();
|
||||||
let reqwest_client = ClientBuilder::new()
|
let reqwest_client = ClientBuilder::new()
|
||||||
.timeout(Duration::from_secs(timeout))
|
.timeout(Duration::from_secs(timeout))
|
||||||
.build()
|
.build()
|
||||||
|
@ -18,3 +18,4 @@ eth1_test_rig = { path = "../eth1_test_rig" }
|
|||||||
env_logger = "0.8.2"
|
env_logger = "0.8.2"
|
||||||
clap = "2.33.3"
|
clap = "2.33.3"
|
||||||
rayon = "1.4.1"
|
rayon = "1.4.1"
|
||||||
|
sensitive_url = { path = "../../common/sensitive_url" }
|
||||||
|
@ -10,6 +10,7 @@ use node_test_rig::{
|
|||||||
ClientGenesis, ValidatorFiles,
|
ClientGenesis, ValidatorFiles,
|
||||||
};
|
};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use std::cmp::max;
|
use std::cmp::max;
|
||||||
use std::net::{IpAddr, Ipv4Addr};
|
use std::net::{IpAddr, Ipv4Addr};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -84,7 +85,8 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
|||||||
let network_id = ganache_eth1_instance.ganache.network_id();
|
let network_id = ganache_eth1_instance.ganache.network_id();
|
||||||
let chain_id = ganache_eth1_instance.ganache.chain_id();
|
let chain_id = ganache_eth1_instance.ganache.chain_id();
|
||||||
let ganache = ganache_eth1_instance.ganache;
|
let ganache = ganache_eth1_instance.ganache;
|
||||||
let eth1_endpoint = ganache.endpoint();
|
let eth1_endpoint = SensitiveUrl::parse(ganache.endpoint().as_str())
|
||||||
|
.expect("Unable to parse ganache endpoint.");
|
||||||
let deposit_contract_address = deposit_contract.address();
|
let deposit_contract_address = deposit_contract.address();
|
||||||
|
|
||||||
// Start a timer that produces eth1 blocks on an interval.
|
// Start a timer that produces eth1 blocks on an interval.
|
||||||
@ -133,7 +135,10 @@ pub fn run_eth1_sim(matches: &ArgMatches) -> Result<(), String> {
|
|||||||
for i in 0..node_count - 1 {
|
for i in 0..node_count - 1 {
|
||||||
let mut config = beacon_config.clone();
|
let mut config = beacon_config.clone();
|
||||||
if i % 2 == 0 {
|
if i % 2 == 0 {
|
||||||
config.eth1.endpoints.insert(0, INVALID_ADDRESS.to_string());
|
config.eth1.endpoints.insert(
|
||||||
|
0,
|
||||||
|
SensitiveUrl::parse(INVALID_ADDRESS).expect("Unable to parse invalid address"),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
network.add_beacon_node(config).await?;
|
network.add_beacon_node(config).await?;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use node_test_rig::{
|
|||||||
ClientConfig, LocalBeaconNode, LocalValidatorClient, ValidatorConfig, ValidatorFiles,
|
ClientConfig, LocalBeaconNode, LocalValidatorClient, ValidatorConfig, ValidatorFiles,
|
||||||
};
|
};
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use std::{
|
use std::{
|
||||||
ops::Deref,
|
ops::Deref,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
@ -140,9 +141,12 @@ impl<E: EthSpec> LocalNetwork<E> {
|
|||||||
.expect("Must have http started")
|
.expect("Must have http started")
|
||||||
};
|
};
|
||||||
|
|
||||||
let beacon_node = format!("http://{}:{}", socket_addr.ip(), socket_addr.port());
|
let beacon_node = SensitiveUrl::parse(
|
||||||
|
format!("http://{}:{}", socket_addr.ip(), socket_addr.port()).as_str(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
validator_config.beacon_nodes = if invalid_first_beacon_node {
|
validator_config.beacon_nodes = if invalid_first_beacon_node {
|
||||||
vec![INVALID_ADDRESS.to_string(), beacon_node]
|
vec![SensitiveUrl::parse(INVALID_ADDRESS).unwrap(), beacon_node]
|
||||||
} else {
|
} else {
|
||||||
vec![beacon_node]
|
vec![beacon_node]
|
||||||
};
|
};
|
||||||
|
@ -63,3 +63,4 @@ scrypt = { version = "0.5.0", default-features = false }
|
|||||||
lighthouse_metrics = { path = "../common/lighthouse_metrics" }
|
lighthouse_metrics = { path = "../common/lighthouse_metrics" }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
fallback = { path = "../common/fallback" }
|
fallback = { path = "../common/fallback" }
|
||||||
|
sensitive_url = { path = "../common/sensitive_url" }
|
||||||
|
@ -7,6 +7,7 @@ use directory::{
|
|||||||
DEFAULT_VALIDATOR_DIR,
|
DEFAULT_VALIDATOR_DIR,
|
||||||
};
|
};
|
||||||
use eth2::types::Graffiti;
|
use eth2::types::Graffiti;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use slog::{info, warn, Logger};
|
use slog::{info, warn, Logger};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@ -26,7 +27,7 @@ pub struct Config {
|
|||||||
/// The http endpoints of the beacon node APIs.
|
/// The http endpoints of the beacon node APIs.
|
||||||
///
|
///
|
||||||
/// Should be similar to `["http://localhost:8080"]`
|
/// Should be similar to `["http://localhost:8080"]`
|
||||||
pub beacon_nodes: Vec<String>,
|
pub beacon_nodes: Vec<SensitiveUrl>,
|
||||||
/// If true, the validator client will still poll for duties and produce blocks even if the
|
/// If true, the validator client will still poll for duties and produce blocks even if the
|
||||||
/// beacon node is not synced at startup.
|
/// beacon node is not synced at startup.
|
||||||
pub allow_unsynced_beacon_node: bool,
|
pub allow_unsynced_beacon_node: bool,
|
||||||
@ -55,10 +56,13 @@ impl Default for Config {
|
|||||||
.join(DEFAULT_HARDCODED_NETWORK);
|
.join(DEFAULT_HARDCODED_NETWORK);
|
||||||
let validator_dir = base_dir.join(DEFAULT_VALIDATOR_DIR);
|
let validator_dir = base_dir.join(DEFAULT_VALIDATOR_DIR);
|
||||||
let secrets_dir = base_dir.join(DEFAULT_SECRET_DIR);
|
let secrets_dir = base_dir.join(DEFAULT_SECRET_DIR);
|
||||||
|
|
||||||
|
let beacon_nodes = vec![SensitiveUrl::parse(DEFAULT_BEACON_NODE)
|
||||||
|
.expect("beacon_nodes must always be a valid url.")];
|
||||||
Self {
|
Self {
|
||||||
validator_dir,
|
validator_dir,
|
||||||
secrets_dir,
|
secrets_dir,
|
||||||
beacon_nodes: vec![DEFAULT_BEACON_NODE.to_string()],
|
beacon_nodes,
|
||||||
allow_unsynced_beacon_node: false,
|
allow_unsynced_beacon_node: false,
|
||||||
disable_auto_discover: false,
|
disable_auto_discover: false,
|
||||||
init_slashing_protection: false,
|
init_slashing_protection: false,
|
||||||
@ -111,25 +115,31 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(beacon_nodes) = parse_optional::<String>(cli_args, "beacon-nodes")? {
|
if let Some(beacon_nodes) = parse_optional::<String>(cli_args, "beacon-nodes")? {
|
||||||
config.beacon_nodes = beacon_nodes.as_str().split(',').map(String::from).collect()
|
config.beacon_nodes = beacon_nodes
|
||||||
|
.split(',')
|
||||||
|
.map(|s| SensitiveUrl::parse(s))
|
||||||
|
.collect::<Result<_, _>>()
|
||||||
|
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?;
|
||||||
}
|
}
|
||||||
// To be deprecated.
|
// To be deprecated.
|
||||||
else if let Some(beacon_node) = parse_optional(cli_args, "beacon-node")? {
|
else if let Some(beacon_node) = parse_optional::<String>(cli_args, "beacon-node")? {
|
||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"The --beacon-node flag is deprecated";
|
"The --beacon-node flag is deprecated";
|
||||||
"msg" => "please use --beacon-nodes instead"
|
"msg" => "please use --beacon-nodes instead"
|
||||||
);
|
);
|
||||||
config.beacon_nodes = vec![beacon_node];
|
config.beacon_nodes = vec![SensitiveUrl::parse(&beacon_node)
|
||||||
|
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?];
|
||||||
}
|
}
|
||||||
// To be deprecated.
|
// To be deprecated.
|
||||||
else if let Some(server) = parse_optional(cli_args, "server")? {
|
else if let Some(server) = parse_optional::<String>(cli_args, "server")? {
|
||||||
warn!(
|
warn!(
|
||||||
log,
|
log,
|
||||||
"The --server flag is deprecated";
|
"The --server flag is deprecated";
|
||||||
"msg" => "please use --beacon-nodes instead"
|
"msg" => "please use --beacon-nodes instead"
|
||||||
);
|
);
|
||||||
config.beacon_nodes = vec![server];
|
config.beacon_nodes = vec![SensitiveUrl::parse(&server)
|
||||||
|
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?];
|
||||||
}
|
}
|
||||||
|
|
||||||
if cli_args.is_present("delete-lockfiles") {
|
if cli_args.is_present("delete-lockfiles") {
|
||||||
@ -227,3 +237,14 @@ impl Config {
|
|||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
// Ensures the default config does not panic.
|
||||||
|
fn default_config() {
|
||||||
|
Config::default();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -84,7 +84,7 @@ impl<E: EthSpec> ForkServiceBuilder<slot_clock::TestingSlotClock, E> {
|
|||||||
std::time::Duration::from_secs(42),
|
std::time::Duration::from_secs(42),
|
||||||
);
|
);
|
||||||
let candidates = vec![CandidateBeaconNode::new(eth2::BeaconNodeHttpClient::new(
|
let candidates = vec![CandidateBeaconNode::new(eth2::BeaconNodeHttpClient::new(
|
||||||
eth2::Url::parse("http://127.0.0.1").unwrap(),
|
sensitive_url::SensitiveUrl::parse("http://127.0.0.1").unwrap(),
|
||||||
))];
|
))];
|
||||||
let mut beacon_nodes = BeaconNodeFallback::new(candidates, spec, log.clone());
|
let mut beacon_nodes = BeaconNodeFallback::new(candidates, spec, log.clone());
|
||||||
beacon_nodes.set_slot_clock(slot_clock);
|
beacon_nodes.set_slot_clock(slot_clock);
|
||||||
|
@ -11,12 +11,10 @@ use account_utils::{
|
|||||||
};
|
};
|
||||||
use deposit_contract::decode_eth1_tx_data;
|
use deposit_contract::decode_eth1_tx_data;
|
||||||
use environment::null_logger;
|
use environment::null_logger;
|
||||||
use eth2::{
|
use eth2::lighthouse_vc::{http_client::ValidatorClientHttpClient, types::*};
|
||||||
lighthouse_vc::{http_client::ValidatorClientHttpClient, types::*},
|
|
||||||
Url,
|
|
||||||
};
|
|
||||||
use eth2_keystore::KeystoreBuilder;
|
use eth2_keystore::KeystoreBuilder;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
use sensitive_url::SensitiveUrl;
|
||||||
use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME};
|
use slashing_protection::{SlashingDatabase, SLASHING_PROTECTION_FILENAME};
|
||||||
use slot_clock::TestingSlotClock;
|
use slot_clock::TestingSlotClock;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
@ -33,7 +31,7 @@ type E = MainnetEthSpec;
|
|||||||
struct ApiTester {
|
struct ApiTester {
|
||||||
client: ValidatorClientHttpClient,
|
client: ValidatorClientHttpClient,
|
||||||
initialized_validators: Arc<RwLock<InitializedValidators>>,
|
initialized_validators: Arc<RwLock<InitializedValidators>>,
|
||||||
url: Url,
|
url: SensitiveUrl,
|
||||||
_server_shutdown: oneshot::Sender<()>,
|
_server_shutdown: oneshot::Sender<()>,
|
||||||
_validator_dir: TempDir,
|
_validator_dir: TempDir,
|
||||||
}
|
}
|
||||||
@ -117,7 +115,7 @@ impl ApiTester {
|
|||||||
|
|
||||||
tokio::spawn(async { server.await });
|
tokio::spawn(async { server.await });
|
||||||
|
|
||||||
let url = Url::parse(&format!(
|
let url = SensitiveUrl::parse(&format!(
|
||||||
"http://{}:{}",
|
"http://{}:{}",
|
||||||
listening_socket.ip(),
|
listening_socket.ip(),
|
||||||
listening_socket.port()
|
listening_socket.port()
|
||||||
|
@ -28,7 +28,7 @@ use clap::ArgMatches;
|
|||||||
use duties_service::DutiesService;
|
use duties_service::DutiesService;
|
||||||
use environment::RuntimeContext;
|
use environment::RuntimeContext;
|
||||||
use eth2::types::StateId;
|
use eth2::types::StateId;
|
||||||
use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient, StatusCode, Url};
|
use eth2::{reqwest::ClientBuilder, BeaconNodeHttpClient, StatusCode};
|
||||||
use fork_service::{ForkService, ForkServiceBuilder};
|
use fork_service::{ForkService, ForkServiceBuilder};
|
||||||
use http_api::ApiSecret;
|
use http_api::ApiSecret;
|
||||||
use initialized_validators::InitializedValidators;
|
use initialized_validators::InitializedValidators;
|
||||||
@ -209,13 +209,9 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
|||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let beacon_node_urls: Vec<Url> = config
|
let beacon_nodes: Vec<BeaconNodeHttpClient> = config
|
||||||
.beacon_nodes
|
.beacon_nodes
|
||||||
.iter()
|
.clone()
|
||||||
.map(|s| s.parse())
|
|
||||||
.collect::<Result<_, _>>()
|
|
||||||
.map_err(|e| format!("Unable to parse beacon node URL: {:?}", e))?;
|
|
||||||
let beacon_nodes: Vec<BeaconNodeHttpClient> = beacon_node_urls
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| {
|
.map(|url| {
|
||||||
let beacon_node_http_client = ClientBuilder::new()
|
let beacon_node_http_client = ClientBuilder::new()
|
||||||
|
Loading…
Reference in New Issue
Block a user