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,
|
BeaconChainTypes, ProduceBlockVerification, WhenSlotSkipped,
|
||||||
};
|
};
|
||||||
pub use block_id::BlockId;
|
pub use block_id::BlockId;
|
||||||
|
use eth2::types::ValidatorStatus;
|
||||||
use eth2::types::{self as api_types, EndpointVersion, ValidatorId};
|
use eth2::types::{self as api_types, EndpointVersion, ValidatorId};
|
||||||
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
use lighthouse_network::{types::SyncState, EnrExt, NetworkGlobals, PeerId, PubsubMessage};
|
||||||
use lighthouse_version::version_with_platform;
|
use lighthouse_version::version_with_platform;
|
||||||
@ -2481,19 +2482,47 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
"count" => register_val_data.len(),
|
"count" => register_val_data.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let preparation_data = register_val_data
|
let head_snapshot = chain.head_snapshot();
|
||||||
.iter()
|
let spec = &chain.spec;
|
||||||
|
|
||||||
|
let (preparation_data, filtered_registration_data): (
|
||||||
|
Vec<ProposerPreparationData>,
|
||||||
|
Vec<SignedValidatorRegistrationData>,
|
||||||
|
) = register_val_data
|
||||||
|
.into_iter()
|
||||||
.filter_map(|register_data| {
|
.filter_map(|register_data| {
|
||||||
chain
|
chain
|
||||||
.validator_index(®ister_data.message.pubkey)
|
.validator_index(®ister_data.message.pubkey)
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|validator_index| ProposerPreparationData {
|
.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,
|
validator_index: validator_index as u64,
|
||||||
fee_recipient: register_data.message.fee_recipient,
|
fee_recipient: register_data.message.fee_recipient,
|
||||||
|
},
|
||||||
|
register_data,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
})
|
||||||
|
.unzip();
|
||||||
|
|
||||||
// Update the prepare beacon proposer cache based on this request.
|
// Update the prepare beacon proposer cache based on this request.
|
||||||
execution_layer
|
execution_layer
|
||||||
@ -2522,11 +2551,11 @@ pub fn serve<T: BeaconChainTypes>(
|
|||||||
info!(
|
info!(
|
||||||
log,
|
log,
|
||||||
"Forwarding register validator request to connected builder";
|
"Forwarding register validator request to connected builder";
|
||||||
"count" => register_val_data.len(),
|
"count" => filtered_registration_data.len(),
|
||||||
);
|
);
|
||||||
|
|
||||||
builder
|
builder
|
||||||
.post_builder_validators(®ister_val_data)
|
.post_builder_validators(&filtered_registration_data)
|
||||||
.await
|
.await
|
||||||
.map(|resp| warp::reply::json(&resp))
|
.map(|resp| warp::reply::json(&resp))
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
|
@ -2459,6 +2459,93 @@ impl ApiTester {
|
|||||||
self
|
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.
|
// Helper function for tests that require a valid RANDAO signature.
|
||||||
async fn get_test_randao(&self, slot: Slot, epoch: Epoch) -> (u64, SignatureBytes) {
|
async fn get_test_randao(&self, slot: Slot, epoch: Epoch) -> (u64, SignatureBytes) {
|
||||||
let fork = self.chain.canonical_head.cached_head().head_fork();
|
let fork = self.chain.canonical_head.cached_head().head_fork();
|
||||||
@ -3964,6 +4051,14 @@ async fn post_validator_register_validator() {
|
|||||||
.await;
|
.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)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn post_validator_register_valid() {
|
async fn post_validator_register_valid() {
|
||||||
ApiTester::new_mev_tester()
|
ApiTester::new_mev_tester()
|
||||||
|
Loading…
Reference in New Issue
Block a user