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:
Jimmy Chen
2023-06-27 08:38:54 +10:00
81 changed files with 1675 additions and 1243 deletions

View File

@@ -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.
*/

View File

@@ -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
*/

View File

@@ -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| {

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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(

View File

@@ -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,