don't register exited or slashed validators with the builder api (#3473)
## Issue Addressed #3465 ## Proposed Changes Filter out any validator registrations for validators that are not `active` or `pending`. I'm adding this filtering the beacon node because all the information is readily available there. In other parts of the VC we are usually sending per-validator requests based on duties from the BN. And duties will only be provided for active validators so we don't have this type of filtering elsewhere in the VC. Co-authored-by: realbigsean <sean@sigmaprime.io>
This commit is contained in:
parent
8c69d57c2c
commit
cb132c622d
@ -25,6 +25,7 @@ use beacon_chain::{
|
||||
BeaconChainTypes, ProduceBlockVerification, WhenSlotSkipped,
|
||||
};
|
||||
pub use block_id::BlockId;
|
||||
use eth2::types::ValidatorStatus;
|
||||
use eth2::types::{self as api_types, EndpointVersion, ValidatorId};
|
||||
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
||||
use lighthouse_version::version_with_platform;
|
||||
@ -2481,19 +2482,47 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
"count" => register_val_data.len(),
|
||||
);
|
||||
|
||||
let preparation_data = register_val_data
|
||||
.iter()
|
||||
let head_snapshot = chain.head_snapshot();
|
||||
let spec = &chain.spec;
|
||||
|
||||
let (preparation_data, filtered_registration_data): (
|
||||
Vec<ProposerPreparationData>,
|
||||
Vec<SignedValidatorRegistrationData>,
|
||||
) = register_val_data
|
||||
.into_iter()
|
||||
.filter_map(|register_data| {
|
||||
chain
|
||||
.validator_index(®ister_data.message.pubkey)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|validator_index| ProposerPreparationData {
|
||||
validator_index: validator_index as u64,
|
||||
fee_recipient: register_data.message.fee_recipient,
|
||||
.and_then(|validator_index| {
|
||||
let validator = head_snapshot
|
||||
.beacon_state
|
||||
.get_validator(validator_index)
|
||||
.ok()?;
|
||||
let validator_status = ValidatorStatus::from_validator(
|
||||
validator,
|
||||
current_epoch,
|
||||
spec.far_future_epoch,
|
||||
)
|
||||
.superstatus();
|
||||
let is_active_or_pending =
|
||||
matches!(validator_status, ValidatorStatus::Pending)
|
||||
|| matches!(validator_status, ValidatorStatus::Active);
|
||||
|
||||
// Filter out validators who are not 'active' or 'pending'.
|
||||
is_active_or_pending.then(|| {
|
||||
(
|
||||
ProposerPreparationData {
|
||||
validator_index: validator_index as u64,
|
||||
fee_recipient: register_data.message.fee_recipient,
|
||||
},
|
||||
register_data,
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
.unzip();
|
||||
|
||||
// Update the prepare beacon proposer cache based on this request.
|
||||
execution_layer
|
||||
@ -2522,11 +2551,11 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
info!(
|
||||
log,
|
||||
"Forwarding register validator request to connected builder";
|
||||
"count" => register_val_data.len(),
|
||||
"count" => filtered_registration_data.len(),
|
||||
);
|
||||
|
||||
builder
|
||||
.post_builder_validators(®ister_val_data)
|
||||
.post_builder_validators(&filtered_registration_data)
|
||||
.await
|
||||
.map(|resp| warp::reply::json(&resp))
|
||||
.map_err(|e| {
|
||||
|
@ -2459,6 +2459,93 @@ impl ApiTester {
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_post_validator_register_validator_slashed(self) -> Self {
|
||||
// slash a validator
|
||||
self.client
|
||||
.post_beacon_pool_attester_slashings(&self.attester_slashing)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
self.harness
|
||||
.extend_chain(
|
||||
1,
|
||||
BlockStrategy::OnCanonicalHead,
|
||||
AttestationStrategy::AllValidators,
|
||||
)
|
||||
.await;
|
||||
|
||||
let mut registrations = vec![];
|
||||
let mut fee_recipients = vec![];
|
||||
|
||||
let genesis_epoch = self.chain.spec.genesis_slot.epoch(E::slots_per_epoch());
|
||||
let fork = Fork {
|
||||
current_version: self.chain.spec.genesis_fork_version,
|
||||
previous_version: self.chain.spec.genesis_fork_version,
|
||||
epoch: genesis_epoch,
|
||||
};
|
||||
|
||||
let expected_gas_limit = 11_111_111;
|
||||
|
||||
for (val_index, keypair) in self.validator_keypairs().iter().enumerate() {
|
||||
let pubkey = keypair.pk.compress();
|
||||
let fee_recipient = Address::from_low_u64_be(val_index as u64);
|
||||
|
||||
let data = ValidatorRegistrationData {
|
||||
fee_recipient,
|
||||
gas_limit: expected_gas_limit,
|
||||
timestamp: 0,
|
||||
pubkey,
|
||||
};
|
||||
|
||||
let domain = self.chain.spec.get_domain(
|
||||
genesis_epoch,
|
||||
Domain::ApplicationMask(ApplicationDomain::Builder),
|
||||
&fork,
|
||||
Hash256::zero(),
|
||||
);
|
||||
let message = data.signing_root(domain);
|
||||
let signature = keypair.sk.sign(message);
|
||||
|
||||
let signed = SignedValidatorRegistrationData {
|
||||
message: data,
|
||||
signature,
|
||||
};
|
||||
|
||||
fee_recipients.push(fee_recipient);
|
||||
registrations.push(signed);
|
||||
}
|
||||
|
||||
self.client
|
||||
.post_validator_register_validator(®istrations)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
for (val_index, (_, fee_recipient)) in self
|
||||
.chain
|
||||
.head_snapshot()
|
||||
.beacon_state
|
||||
.validators()
|
||||
.into_iter()
|
||||
.zip(fee_recipients.into_iter())
|
||||
.enumerate()
|
||||
{
|
||||
let actual = self
|
||||
.chain
|
||||
.execution_layer
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_suggested_fee_recipient(val_index as u64)
|
||||
.await;
|
||||
if val_index == 0 || val_index == 1 {
|
||||
assert_eq!(actual, Address::from_low_u64_be(val_index as u64));
|
||||
} else {
|
||||
assert_eq!(actual, fee_recipient);
|
||||
}
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
// Helper function for tests that require a valid RANDAO signature.
|
||||
async fn get_test_randao(&self, slot: Slot, epoch: Epoch) -> (u64, SignatureBytes) {
|
||||
let fork = self.chain.canonical_head.cached_head().head_fork();
|
||||
@ -3964,6 +4051,14 @@ async fn post_validator_register_validator() {
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn post_validator_register_validator_slashed() {
|
||||
ApiTester::new()
|
||||
.await
|
||||
.test_post_validator_register_validator_slashed()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn post_validator_register_valid() {
|
||||
ApiTester::new_mev_tester()
|
||||
|
Loading…
Reference in New Issue
Block a user