mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-09 19:51:47 +00:00
[SQUASHED] Optionally skip RANDAO verif during block production (#3116)
This commit is contained in:
@@ -23,7 +23,7 @@ use beacon_chain::{
|
||||
observed_operations::ObservationOutcome,
|
||||
validator_monitor::{get_block_delay_ms, timestamp_now},
|
||||
AttestationError as AttnError, BeaconChain, BeaconChainError, BeaconChainTypes,
|
||||
HeadSafetyStatus, WhenSlotSkipped,
|
||||
HeadSafetyStatus, ProduceBlockVerification, WhenSlotSkipped,
|
||||
};
|
||||
use block_id::BlockId;
|
||||
use eth2::types::{self as api_types, EndpointVersion, ValidatorId};
|
||||
@@ -46,7 +46,7 @@ use tokio::sync::mpsc::UnboundedSender;
|
||||
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
|
||||
use types::{
|
||||
Attestation, AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch,
|
||||
EthSpec, ForkName, ProposerPreparationData, ProposerSlashing, RelativeEpoch,
|
||||
EthSpec, ForkName, ProposerPreparationData, ProposerSlashing, RelativeEpoch, Signature,
|
||||
SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, SignedVoluntaryExit,
|
||||
Slot, SyncCommitteeMessage, SyncContributionData,
|
||||
};
|
||||
@@ -1872,15 +1872,39 @@ pub fn serve<T: BeaconChainTypes>(
|
||||
query: api_types::ValidatorBlocksQuery,
|
||||
chain: Arc<BeaconChain<T>>| {
|
||||
blocking_json_task(move || {
|
||||
let randao_reveal = (&query.randao_reveal).try_into().map_err(|e| {
|
||||
warp_utils::reject::custom_bad_request(format!(
|
||||
"randao reveal is not valid BLS signature: {:?}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let randao_reveal = query.randao_reveal.as_ref().map_or_else(
|
||||
|| {
|
||||
if query.verify_randao {
|
||||
Err(warp_utils::reject::custom_bad_request(
|
||||
"randao_reveal is mandatory unless verify_randao=false".into(),
|
||||
))
|
||||
} else {
|
||||
Ok(Signature::empty())
|
||||
}
|
||||
},
|
||||
|sig_bytes| {
|
||||
sig_bytes.try_into().map_err(|e| {
|
||||
warp_utils::reject::custom_bad_request(format!(
|
||||
"randao reveal is not a valid BLS signature: {:?}",
|
||||
e
|
||||
))
|
||||
})
|
||||
},
|
||||
)?;
|
||||
|
||||
let randao_verification = if query.verify_randao {
|
||||
ProduceBlockVerification::VerifyRandao
|
||||
} else {
|
||||
ProduceBlockVerification::NoVerification
|
||||
};
|
||||
|
||||
let (block, _) = chain
|
||||
.produce_block(randao_reveal, slot, query.graffiti.map(Into::into))
|
||||
.produce_block_with_verification(
|
||||
randao_reveal,
|
||||
slot,
|
||||
query.graffiti.map(Into::into),
|
||||
randao_verification,
|
||||
)
|
||||
.map_err(warp_utils::reject::block_production_error)?;
|
||||
let fork_name = block
|
||||
.to_ref()
|
||||
|
||||
@@ -1919,6 +1919,104 @@ impl ApiTester {
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_block_production_no_verify_randao(self) -> Self {
|
||||
for _ in 0..E::slots_per_epoch() {
|
||||
let slot = self.chain.slot().unwrap();
|
||||
|
||||
let block = self
|
||||
.client
|
||||
.get_validator_blocks_with_verify_randao::<E>(slot, None, None, Some(false))
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
assert_eq!(block.slot(), slot);
|
||||
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_block_production_verify_randao_invalid(self) -> Self {
|
||||
let fork = self.chain.head_info().unwrap().fork;
|
||||
let genesis_validators_root = self.chain.genesis_validators_root;
|
||||
|
||||
for _ in 0..E::slots_per_epoch() {
|
||||
let slot = self.chain.slot().unwrap();
|
||||
let epoch = self.chain.epoch().unwrap();
|
||||
|
||||
let proposer_pubkey_bytes = self
|
||||
.client
|
||||
.get_validator_duties_proposer(epoch)
|
||||
.await
|
||||
.unwrap()
|
||||
.data
|
||||
.into_iter()
|
||||
.find(|duty| duty.slot == slot)
|
||||
.map(|duty| duty.pubkey)
|
||||
.unwrap();
|
||||
let proposer_pubkey = (&proposer_pubkey_bytes).try_into().unwrap();
|
||||
|
||||
let sk = self
|
||||
.validator_keypairs
|
||||
.iter()
|
||||
.find(|kp| kp.pk == proposer_pubkey)
|
||||
.map(|kp| kp.sk.clone())
|
||||
.unwrap();
|
||||
|
||||
let bad_randao_reveal = {
|
||||
let domain = self.chain.spec.get_domain(
|
||||
epoch,
|
||||
Domain::Randao,
|
||||
&fork,
|
||||
genesis_validators_root,
|
||||
);
|
||||
let message = (epoch + 1).signing_root(domain);
|
||||
sk.sign(message).into()
|
||||
};
|
||||
|
||||
// Check failure with no `verify_randao` passed.
|
||||
self.client
|
||||
.get_validator_blocks::<E>(slot, &bad_randao_reveal, None)
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Check failure with `verify_randao=true`.
|
||||
self.client
|
||||
.get_validator_blocks_with_verify_randao::<E>(
|
||||
slot,
|
||||
Some(&bad_randao_reveal),
|
||||
None,
|
||||
Some(true),
|
||||
)
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Check failure with no randao reveal provided.
|
||||
self.client
|
||||
.get_validator_blocks_with_verify_randao::<E>(slot, None, None, None)
|
||||
.await
|
||||
.unwrap_err();
|
||||
|
||||
// Check success with `verify_randao=false`.
|
||||
let block = self
|
||||
.client
|
||||
.get_validator_blocks_with_verify_randao::<E>(
|
||||
slot,
|
||||
Some(&bad_randao_reveal),
|
||||
None,
|
||||
Some(false),
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.data;
|
||||
|
||||
assert_eq!(block.slot(), slot);
|
||||
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn test_get_validator_attestation_data(self) -> Self {
|
||||
let mut state = self.chain.head_beacon_state().unwrap();
|
||||
let slot = state.slot();
|
||||
@@ -2770,6 +2868,22 @@ async fn block_production_with_skip_slots() {
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn block_production_no_verify_randao() {
|
||||
ApiTester::new()
|
||||
.await
|
||||
.test_block_production_no_verify_randao()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn block_production_verify_randao_invalid() {
|
||||
ApiTester::new()
|
||||
.await
|
||||
.test_block_production_verify_randao_invalid()
|
||||
.await;
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn get_validator_attestation_data() {
|
||||
ApiTester::new()
|
||||
|
||||
Reference in New Issue
Block a user