mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 05:48:31 +00:00
Merge branch 'unstable' into deneb-merge-from-unstable-20230627
# Conflicts: # beacon_node/beacon_chain/src/beacon_chain.rs # beacon_node/beacon_chain/src/block_verification.rs # beacon_node/beacon_chain/src/lib.rs # beacon_node/beacon_chain/src/test_utils.rs # beacon_node/beacon_chain/tests/block_verification.rs # beacon_node/beacon_chain/tests/store_tests.rs # beacon_node/beacon_chain/tests/tests.rs # beacon_node/http_api/src/publish_blocks.rs # beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs # beacon_node/lighthouse_network/src/rpc/methods.rs # beacon_node/lighthouse_network/src/rpc/outbound.rs # beacon_node/lighthouse_network/src/rpc/protocol.rs # beacon_node/lighthouse_network/src/service/api_types.rs # beacon_node/network/src/beacon_processor/worker/gossip_methods.rs # beacon_node/network/src/beacon_processor/worker/rpc_methods.rs # beacon_node/network/src/beacon_processor/worker/sync_methods.rs # beacon_node/network/src/sync/block_lookups/single_block_lookup.rs # beacon_node/network/src/sync/network_context.rs # beacon_node/network/src/sync/range_sync/batch.rs # beacon_node/network/src/sync/range_sync/chain.rs # common/eth2/src/types.rs # consensus/fork_choice/src/fork_choice.rs
This commit is contained in:
@@ -333,6 +333,16 @@ pub fn cli_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.default_value("true")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("validator-registration-batch-size")
|
||||
.long("validator-registration-batch-size")
|
||||
.value_name("INTEGER")
|
||||
.help("Defines the number of validators per \
|
||||
validator/register_validator request sent to the BN. This value \
|
||||
can be reduced to avoid timeouts from builders.")
|
||||
.default_value("500")
|
||||
.takes_value(true),
|
||||
)
|
||||
/*
|
||||
* Experimental/development options.
|
||||
*/
|
||||
|
||||
@@ -77,6 +77,8 @@ pub struct Config {
|
||||
pub disable_run_on_all: bool,
|
||||
/// Enables a service which attempts to measure latency between the VC and BNs.
|
||||
pub enable_latency_measurement_service: bool,
|
||||
/// Defines the number of validators per `validator/register_validator` request sent to the BN.
|
||||
pub validator_registration_batch_size: usize,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
@@ -117,6 +119,7 @@ impl Default for Config {
|
||||
gas_limit: None,
|
||||
disable_run_on_all: false,
|
||||
enable_latency_measurement_service: true,
|
||||
validator_registration_batch_size: 500,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -380,6 +383,12 @@ impl Config {
|
||||
config.enable_latency_measurement_service =
|
||||
parse_optional(cli_args, "latency-measurement-service")?.unwrap_or(true);
|
||||
|
||||
config.validator_registration_batch_size =
|
||||
parse_required(cli_args, "validator-registration-batch-size")?;
|
||||
if config.validator_registration_batch_size == 0 {
|
||||
return Err("validator-registration-batch-size cannot be 0".to_string());
|
||||
}
|
||||
|
||||
/*
|
||||
* Experimental
|
||||
*/
|
||||
|
||||
@@ -357,7 +357,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
||||
.and(warp::path("graffiti"))
|
||||
.and(warp::path::end())
|
||||
.and(validator_store_filter.clone())
|
||||
.and(graffiti_file_filter)
|
||||
.and(graffiti_file_filter.clone())
|
||||
.and(graffiti_flag_filter)
|
||||
.and(signer.clone())
|
||||
.and(log_filter.clone())
|
||||
@@ -617,18 +617,27 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
||||
.and(warp::path::end())
|
||||
.and(warp::body::json())
|
||||
.and(validator_store_filter.clone())
|
||||
.and(graffiti_file_filter)
|
||||
.and(signer.clone())
|
||||
.and(task_executor_filter.clone())
|
||||
.and_then(
|
||||
|validator_pubkey: PublicKey,
|
||||
body: api_types::ValidatorPatchRequest,
|
||||
validator_store: Arc<ValidatorStore<T, E>>,
|
||||
graffiti_file: Option<GraffitiFile>,
|
||||
signer,
|
||||
task_executor: TaskExecutor| {
|
||||
blocking_signed_json_task(signer, move || {
|
||||
if body.graffiti.is_some() && graffiti_file.is_some() {
|
||||
return Err(warp_utils::reject::custom_bad_request(
|
||||
"Unable to update graffiti as the \"--graffiti-file\" flag is set"
|
||||
.to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
let maybe_graffiti = body.graffiti.clone().map(Into::into);
|
||||
let initialized_validators_rw_lock = validator_store.initialized_validators();
|
||||
let mut initialized_validators = initialized_validators_rw_lock.write();
|
||||
|
||||
match (
|
||||
initialized_validators.is_enabled(&validator_pubkey),
|
||||
initialized_validators.validator(&validator_pubkey.compress()),
|
||||
@@ -641,7 +650,8 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
||||
if Some(is_enabled) == body.enabled
|
||||
&& initialized_validator.get_gas_limit() == body.gas_limit
|
||||
&& initialized_validator.get_builder_proposals()
|
||||
== body.builder_proposals =>
|
||||
== body.builder_proposals
|
||||
&& initialized_validator.get_graffiti() == maybe_graffiti =>
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
@@ -654,6 +664,7 @@ pub fn serve<T: 'static + SlotClock + Clone, E: EthSpec>(
|
||||
body.enabled,
|
||||
body.gas_limit,
|
||||
body.builder_proposals,
|
||||
body.graffiti,
|
||||
),
|
||||
)
|
||||
.map_err(|e| {
|
||||
|
||||
@@ -28,12 +28,14 @@ use slot_clock::{SlotClock, TestingSlotClock};
|
||||
use std::future::Future;
|
||||
use std::marker::PhantomData;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use task_executor::TaskExecutor;
|
||||
use tempfile::{tempdir, TempDir};
|
||||
use tokio::runtime::Runtime;
|
||||
use tokio::sync::oneshot;
|
||||
use types::graffiti::GraffitiString;
|
||||
|
||||
const PASSWORD_BYTES: &[u8] = &[42, 50, 37];
|
||||
pub const TEST_DEFAULT_FEE_RECIPIENT: Address = Address::repeat_byte(42);
|
||||
@@ -533,7 +535,7 @@ impl ApiTester {
|
||||
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
|
||||
|
||||
self.client
|
||||
.patch_lighthouse_validators(&validator.voting_pubkey, Some(enabled), None, None)
|
||||
.patch_lighthouse_validators(&validator.voting_pubkey, Some(enabled), None, None, None)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -575,7 +577,13 @@ impl ApiTester {
|
||||
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
|
||||
|
||||
self.client
|
||||
.patch_lighthouse_validators(&validator.voting_pubkey, None, Some(gas_limit), None)
|
||||
.patch_lighthouse_validators(
|
||||
&validator.voting_pubkey,
|
||||
None,
|
||||
Some(gas_limit),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -602,6 +610,7 @@ impl ApiTester {
|
||||
None,
|
||||
None,
|
||||
Some(builder_proposals),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -620,6 +629,34 @@ impl ApiTester {
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn set_graffiti(self, index: usize, graffiti: &str) -> Self {
|
||||
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
|
||||
let graffiti_str = GraffitiString::from_str(graffiti).unwrap();
|
||||
self.client
|
||||
.patch_lighthouse_validators(
|
||||
&validator.voting_pubkey,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
Some(graffiti_str),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn assert_graffiti(self, index: usize, graffiti: &str) -> Self {
|
||||
let validator = &self.client.get_lighthouse_validators().await.unwrap().data[index];
|
||||
let graffiti_str = GraffitiString::from_str(graffiti).unwrap();
|
||||
assert_eq!(
|
||||
self.validator_store.graffiti(&validator.voting_pubkey),
|
||||
Some(graffiti_str.into())
|
||||
);
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
struct HdValidatorScenario {
|
||||
@@ -723,7 +760,13 @@ fn routes_with_invalid_auth() {
|
||||
.await
|
||||
.test_with_invalid_auth(|client| async move {
|
||||
client
|
||||
.patch_lighthouse_validators(&PublicKeyBytes::empty(), Some(false), None, None)
|
||||
.patch_lighthouse_validators(
|
||||
&PublicKeyBytes::empty(),
|
||||
Some(false),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
})
|
||||
.await
|
||||
@@ -931,6 +974,41 @@ fn validator_builder_proposals() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validator_graffiti() {
|
||||
let runtime = build_runtime();
|
||||
let weak_runtime = Arc::downgrade(&runtime);
|
||||
runtime.block_on(async {
|
||||
ApiTester::new(weak_runtime)
|
||||
.await
|
||||
.create_hd_validators(HdValidatorScenario {
|
||||
count: 2,
|
||||
specify_mnemonic: false,
|
||||
key_derivation_path_offset: 0,
|
||||
disabled: vec![],
|
||||
})
|
||||
.await
|
||||
.assert_enabled_validators_count(2)
|
||||
.assert_validators_count(2)
|
||||
.set_graffiti(0, "Mr F was here")
|
||||
.await
|
||||
.assert_graffiti(0, "Mr F was here")
|
||||
.await
|
||||
// Test setting graffiti while the validator is disabled
|
||||
.set_validator_enabled(0, false)
|
||||
.await
|
||||
.assert_enabled_validators_count(1)
|
||||
.assert_validators_count(2)
|
||||
.set_graffiti(0, "Mr F was here again")
|
||||
.await
|
||||
.set_validator_enabled(0, true)
|
||||
.await
|
||||
.assert_enabled_validators_count(2)
|
||||
.assert_graffiti(0, "Mr F was here again")
|
||||
.await
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keystore_validator_creation() {
|
||||
let runtime = build_runtime();
|
||||
|
||||
@@ -468,7 +468,7 @@ fn import_and_delete_conflicting_web3_signer_keystores() {
|
||||
for pubkey in &pubkeys {
|
||||
tester
|
||||
.client
|
||||
.patch_lighthouse_validators(pubkey, Some(false), None, None)
|
||||
.patch_lighthouse_validators(pubkey, Some(false), None, None, None)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use types::graffiti::GraffitiString;
|
||||
use types::{Address, Graffiti, Keypair, PublicKey, PublicKeyBytes};
|
||||
use url::{ParseError, Url};
|
||||
use validator_dir::Builder as ValidatorDirBuilder;
|
||||
@@ -147,6 +148,10 @@ impl InitializedValidator {
|
||||
pub fn get_index(&self) -> Option<u64> {
|
||||
self.index
|
||||
}
|
||||
|
||||
pub fn get_graffiti(&self) -> Option<Graffiti> {
|
||||
self.graffiti
|
||||
}
|
||||
}
|
||||
|
||||
fn open_keystore(path: &Path) -> Result<Keystore, Error> {
|
||||
@@ -671,8 +676,8 @@ impl InitializedValidators {
|
||||
self.validators.get(public_key)
|
||||
}
|
||||
|
||||
/// Sets the `InitializedValidator` and `ValidatorDefinition` `enabled`, `gas_limit`, and `builder_proposals`
|
||||
/// values.
|
||||
/// Sets the `InitializedValidator` and `ValidatorDefinition` `enabled`, `gas_limit`,
|
||||
/// `builder_proposals`, and `graffiti` values.
|
||||
///
|
||||
/// ## Notes
|
||||
///
|
||||
@@ -682,7 +687,7 @@ impl InitializedValidators {
|
||||
///
|
||||
/// If a `gas_limit` is included in the call to this function, it will also be updated and saved
|
||||
/// to disk. If `gas_limit` is `None` the `gas_limit` *will not* be unset in `ValidatorDefinition`
|
||||
/// or `InitializedValidator`. The same logic applies to `builder_proposals`.
|
||||
/// or `InitializedValidator`. The same logic applies to `builder_proposals` and `graffiti`.
|
||||
///
|
||||
/// Saves the `ValidatorDefinitions` to file, even if no definitions were changed.
|
||||
pub async fn set_validator_definition_fields(
|
||||
@@ -691,6 +696,7 @@ impl InitializedValidators {
|
||||
enabled: Option<bool>,
|
||||
gas_limit: Option<u64>,
|
||||
builder_proposals: Option<bool>,
|
||||
graffiti: Option<GraffitiString>,
|
||||
) -> Result<(), Error> {
|
||||
if let Some(def) = self
|
||||
.definitions
|
||||
@@ -708,6 +714,9 @@ impl InitializedValidators {
|
||||
if let Some(builder_proposals) = builder_proposals {
|
||||
def.builder_proposals = Some(builder_proposals);
|
||||
}
|
||||
if let Some(graffiti) = graffiti.clone() {
|
||||
def.graffiti = Some(graffiti);
|
||||
}
|
||||
}
|
||||
|
||||
self.update_validators().await?;
|
||||
@@ -723,6 +732,9 @@ impl InitializedValidators {
|
||||
if let Some(builder_proposals) = builder_proposals {
|
||||
val.builder_proposals = Some(builder_proposals);
|
||||
}
|
||||
if let Some(graffiti) = graffiti {
|
||||
val.graffiti = Some(graffiti.into());
|
||||
}
|
||||
}
|
||||
|
||||
self.definitions
|
||||
|
||||
@@ -487,6 +487,7 @@ impl<T: EthSpec> ProductionValidatorClient<T> {
|
||||
.beacon_nodes(beacon_nodes.clone())
|
||||
.runtime_context(context.service_context("preparation".into()))
|
||||
.builder_registration_timestamp_override(config.builder_registration_timestamp_override)
|
||||
.validator_registration_batch_size(config.validator_registration_batch_size)
|
||||
.build()?;
|
||||
|
||||
let sync_committee_service = SyncCommitteeService::new(
|
||||
|
||||
@@ -23,9 +23,6 @@ const PROPOSER_PREPARATION_LOOKAHEAD_EPOCHS: u64 = 2;
|
||||
/// Number of epochs to wait before re-submitting validator registration.
|
||||
const EPOCHS_PER_VALIDATOR_REGISTRATION_SUBMISSION: u64 = 1;
|
||||
|
||||
/// The number of validator registrations to include per request to the beacon node.
|
||||
const VALIDATOR_REGISTRATION_BATCH_SIZE: usize = 500;
|
||||
|
||||
/// Builds an `PreparationService`.
|
||||
pub struct PreparationServiceBuilder<T: SlotClock + 'static, E: EthSpec> {
|
||||
validator_store: Option<Arc<ValidatorStore<T, E>>>,
|
||||
@@ -33,6 +30,7 @@ pub struct PreparationServiceBuilder<T: SlotClock + 'static, E: EthSpec> {
|
||||
beacon_nodes: Option<Arc<BeaconNodeFallback<T, E>>>,
|
||||
context: Option<RuntimeContext<E>>,
|
||||
builder_registration_timestamp_override: Option<u64>,
|
||||
validator_registration_batch_size: Option<usize>,
|
||||
}
|
||||
|
||||
impl<T: SlotClock + 'static, E: EthSpec> PreparationServiceBuilder<T, E> {
|
||||
@@ -43,6 +41,7 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationServiceBuilder<T, E> {
|
||||
beacon_nodes: None,
|
||||
context: None,
|
||||
builder_registration_timestamp_override: None,
|
||||
validator_registration_batch_size: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +73,14 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationServiceBuilder<T, E> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn validator_registration_batch_size(
|
||||
mut self,
|
||||
validator_registration_batch_size: usize,
|
||||
) -> Self {
|
||||
self.validator_registration_batch_size = Some(validator_registration_batch_size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> Result<PreparationService<T, E>, String> {
|
||||
Ok(PreparationService {
|
||||
inner: Arc::new(Inner {
|
||||
@@ -91,6 +98,9 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationServiceBuilder<T, E> {
|
||||
.ok_or("Cannot build PreparationService without runtime_context")?,
|
||||
builder_registration_timestamp_override: self
|
||||
.builder_registration_timestamp_override,
|
||||
validator_registration_batch_size: self.validator_registration_batch_size.ok_or(
|
||||
"Cannot build PreparationService without validator_registration_batch_size",
|
||||
)?,
|
||||
validator_registration_cache: RwLock::new(HashMap::new()),
|
||||
}),
|
||||
})
|
||||
@@ -107,6 +117,7 @@ pub struct Inner<T, E: EthSpec> {
|
||||
// Used to track unpublished validator registration changes.
|
||||
validator_registration_cache:
|
||||
RwLock<HashMap<ValidatorRegistrationKey, SignedValidatorRegistrationData>>,
|
||||
validator_registration_batch_size: usize,
|
||||
}
|
||||
|
||||
#[derive(Hash, Eq, PartialEq, Debug, Clone)]
|
||||
@@ -447,7 +458,7 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationService<T, E> {
|
||||
}
|
||||
|
||||
if !signed.is_empty() {
|
||||
for batch in signed.chunks(VALIDATOR_REGISTRATION_BATCH_SIZE) {
|
||||
for batch in signed.chunks(self.validator_registration_batch_size) {
|
||||
match self
|
||||
.beacon_nodes
|
||||
.first_success(
|
||||
@@ -462,7 +473,7 @@ impl<T: SlotClock + 'static, E: EthSpec> PreparationService<T, E> {
|
||||
Ok(()) => info!(
|
||||
log,
|
||||
"Published validator registrations to the builder network";
|
||||
"count" => registration_data_len,
|
||||
"count" => batch.len(),
|
||||
),
|
||||
Err(e) => warn!(
|
||||
log,
|
||||
|
||||
Reference in New Issue
Block a user