Skip to content

Commit 9ab780d

Browse files
committed
Add endpoint
1 parent 8d0d154 commit 9ab780d

File tree

6 files changed

+75
-4
lines changed

6 files changed

+75
-4
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/eth2/src/lighthouse_vc/types.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,13 @@ pub struct SingleExportKeystoresResponse {
198198
pub struct SetGraffitiRequest {
199199
pub graffiti: GraffitiString,
200200
}
201+
202+
#[derive(Serialize, Deserialize, Debug)]
203+
pub struct UpdateCandidatesRequest {
204+
pub beacon_nodes: Vec<String>,
205+
}
206+
207+
#[derive(Serialize, Deserialize, Debug)]
208+
pub struct UpdateCandidatesResponse {
209+
pub new_beacon_nodes_list: Vec<String>,
210+
}

validator_client/beacon_node_fallback/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ strum = { workspace = true }
2020
tokio = { workspace = true }
2121
types = { workspace = true }
2222
validator_metrics = { workspace = true }
23+
sensitive_url = { workspace = true }

validator_client/beacon_node_fallback/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,13 +465,13 @@ impl<T: SlotClock, E: EthSpec> BeaconNodeFallback<T, E> {
465465
/// Update the list of candidates with a new list.
466466
/// Returns `Ok(new_list)` if the update was successful.
467467
/// Returns `Err(some_err)` if the list is empty.
468-
pub async fn replace_candidates(
468+
pub async fn update_candidates_list(
469469
&self,
470470
new_list: Vec<SensitiveUrl>,
471471
use_long_timeouts: bool,
472472
) -> Result<Vec<SensitiveUrl>, String> {
473473
if new_list.is_empty() {
474-
return Err("Beacon Node list cannot be empty".to_string());
474+
return Err("list cannot be empty".to_string());
475475
}
476476

477477
let timeouts: Timeouts = if new_list.len() == 1 || use_long_timeouts {

validator_client/http_api/src/lib.rs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,21 @@ use account_utils::{
2020
};
2121
pub use api_secret::ApiSecret;
2222
use beacon_node_fallback::CandidateInfo;
23+
use core::convert::Infallible;
2324
use create_validator::{
2425
create_validators_mnemonic, create_validators_web3signer, get_voting_password_storage,
2526
};
2627
use eth2::lighthouse_vc::{
2728
std_types::{AuthResponse, GetFeeRecipientResponse, GetGasLimitResponse},
2829
types::{
2930
self as api_types, GenericResponse, GetGraffitiResponse, Graffiti, PublicKey,
30-
PublicKeyBytes, SetGraffitiRequest,
31+
PublicKeyBytes, SetGraffitiRequest, UpdateCandidatesRequest, UpdateCandidatesResponse,
3132
},
3233
};
3334
use lighthouse_version::version_with_platform;
3435
use logging::SSELoggingComponents;
3536
use parking_lot::RwLock;
37+
use sensitive_url::SensitiveUrl;
3638
use serde::{Deserialize, Serialize};
3739
use slog::{crit, info, warn, Logger};
3840
use slot_clock::SlotClock;
@@ -49,7 +51,8 @@ use tokio_stream::{wrappers::BroadcastStream, StreamExt};
4951
use types::{ChainSpec, ConfigAndPreset, EthSpec};
5052
use validator_dir::Builder as ValidatorDirBuilder;
5153
use validator_services::block_service::BlockService;
52-
use warp::{sse::Event, Filter};
54+
use warp::{reply::Response, sse::Event, Filter};
55+
use warp_utils::reject::convert_rejection;
5356
use warp_utils::task::blocking_json_task;
5457

5558
#[derive(Debug)]
@@ -99,6 +102,7 @@ pub struct Config {
99102
pub allow_origin: Option<String>,
100103
pub allow_keystore_export: bool,
101104
pub store_passwords_in_secrets_dir: bool,
105+
pub bn_long_timeouts: bool,
102106
}
103107

104108
impl Default for Config {
@@ -110,6 +114,7 @@ impl Default for Config {
110114
allow_origin: None,
111115
allow_keystore_export: false,
112116
store_passwords_in_secrets_dir: false,
117+
bn_long_timeouts: false,
113118
}
114119
}
115120
}
@@ -136,6 +141,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
136141
let config = &ctx.config;
137142
let allow_keystore_export = config.allow_keystore_export;
138143
let store_passwords_in_secrets_dir = config.store_passwords_in_secrets_dir;
144+
let use_long_timeouts = config.bn_long_timeouts;
139145
let log = ctx.log.clone();
140146

141147
// Configure CORS.
@@ -835,6 +841,57 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
835841
})
836842
});
837843

844+
// POST /lighthouse/update_beacon_nodes
845+
let post_lighthouse_update_beacon_nodes = warp::path("lighthouse")
846+
.and(warp::path("update_beacon_nodes"))
847+
.and(warp::path::end())
848+
.and(warp::body::json())
849+
.and(block_service_filter.clone())
850+
.then(
851+
move |request: UpdateCandidatesRequest, block_service: BlockService<T, E>| async move {
852+
async fn parse_urls(urls: &[String]) -> Result<Vec<SensitiveUrl>, Response> {
853+
match urls
854+
.iter()
855+
.map(|url| SensitiveUrl::parse(url).map_err(|e| e.to_string()))
856+
.collect()
857+
{
858+
Ok(sensitive_urls) => Ok(sensitive_urls),
859+
Err(_) => Err(convert_rejection::<Infallible>(Err(
860+
warp_utils::reject::custom_bad_request(
861+
"one or more urls could not be parsed".to_string(),
862+
),
863+
))
864+
.await),
865+
}
866+
}
867+
868+
let beacons: Vec<SensitiveUrl> = match parse_urls(&request.beacon_nodes).await {
869+
Ok(new_beacons) => {
870+
match block_service
871+
.beacon_nodes
872+
.update_candidates_list(new_beacons, use_long_timeouts)
873+
.await
874+
{
875+
Ok(beacons) => beacons,
876+
Err(e) => {
877+
return convert_rejection::<Infallible>(Err(
878+
warp_utils::reject::custom_bad_request(e.to_string()),
879+
))
880+
.await
881+
}
882+
}
883+
}
884+
Err(e) => return e,
885+
};
886+
887+
let response: UpdateCandidatesResponse = UpdateCandidatesResponse {
888+
new_beacon_nodes_list: beacons.iter().map(|surl| surl.to_string()).collect(),
889+
};
890+
891+
blocking_json_task(move || Ok(api_types::GenericResponse::from(response))).await
892+
},
893+
);
894+
838895
// Standard key-manager endpoints.
839896
let eth_v1 = warp::path("eth").and(warp::path("v1"));
840897
let std_keystores = eth_v1.and(warp::path("keystores")).and(warp::path::end());
@@ -1322,6 +1379,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
13221379
.or(post_std_keystores)
13231380
.or(post_std_remotekeys)
13241381
.or(post_graffiti)
1382+
.or(post_lighthouse_update_beacon_nodes)
13251383
.recover(warp_utils::reject::handle_rejection),
13261384
))
13271385
.or(warp::patch()

validator_client/http_api/src/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ impl ApiTester {
177177
allow_origin: None,
178178
allow_keystore_export: true,
179179
store_passwords_in_secrets_dir: false,
180+
bn_long_timeouts: false,
180181
}
181182
}
182183

0 commit comments

Comments
 (0)