Merge branch 'unstable' into merge-unstable-to-deneb-20230808

# Conflicts:
#	Cargo.lock
#	beacon_node/beacon_chain/src/lib.rs
#	beacon_node/execution_layer/src/engine_api.rs
#	beacon_node/execution_layer/src/engine_api/http.rs
#	beacon_node/execution_layer/src/test_utils/mod.rs
#	beacon_node/lighthouse_network/src/rpc/codec/ssz_snappy.rs
#	beacon_node/lighthouse_network/src/rpc/handler.rs
#	beacon_node/lighthouse_network/src/rpc/protocol.rs
#	beacon_node/lighthouse_network/src/service/utils.rs
#	beacon_node/lighthouse_network/tests/rpc_tests.rs
#	beacon_node/network/Cargo.toml
#	beacon_node/network/src/network_beacon_processor/tests.rs
#	lcli/src/parse_ssz.rs
#	scripts/cross/Dockerfile
#	validator_client/src/block_service.rs
#	validator_client/src/validator_store.rs
This commit is contained in:
Jimmy Chen
2023-08-08 17:02:51 +10:00
161 changed files with 8729 additions and 3368 deletions
+1
View File
@@ -42,6 +42,7 @@ operation_pool = { path = "../operation_pool" }
sensitive_url = { path = "../../common/sensitive_url" }
unused_port = {path = "../../common/unused_port"}
store = { path = "../store" }
bytes = "1.1.0"
[dev-dependencies]
environment = { path = "../../lighthouse/environment" }
+2 -4
View File
@@ -1,9 +1,7 @@
//! Contains the handler for the `GET validator/duties/attester/{epoch}` endpoint.
use crate::state_id::StateId;
use beacon_chain::{
BeaconChain, BeaconChainError, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
};
use beacon_chain::{BeaconChain, BeaconChainError, BeaconChainTypes};
use eth2::types::{self as api_types};
use slot_clock::SlotClock;
use state_processing::state_advance::partial_state_advance;
@@ -32,7 +30,7 @@ pub fn attester_duties<T: BeaconChainTypes>(
// will equal `current_epoch + 1`
let tolerant_current_epoch = chain
.slot_clock
.now_with_future_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)
.now_with_future_tolerance(chain.spec.maximum_gossip_clock_disparity())
.ok_or_else(|| warp_utils::reject::custom_server_error("unable to read slot clock".into()))?
.epoch(T::EthSpec::slots_per_epoch());
+225 -1
View File
@@ -30,6 +30,7 @@ use beacon_chain::{
BeaconChainTypes, ProduceBlockVerification, WhenSlotSkipped,
};
pub use block_id::BlockId;
use bytes::Bytes;
use directory::DEFAULT_ROOT_DIR;
use eth2::types::{
self as api_types, BroadcastValidation, EndpointVersion, ForkChoice, ForkChoiceNode,
@@ -1236,6 +1237,41 @@ pub fn serve<T: BeaconChainTypes>(
},
);
let post_beacon_blocks_ssz = eth_v1
.and(warp::path("beacon"))
.and(warp::path("blocks"))
.and(warp::path::end())
.and(warp::body::bytes())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.and_then(
|block_bytes: Bytes,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
let block_contents = match SignedBlockContents::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
) {
Ok(data) => data,
Err(e) => {
return Err(warp_utils::reject::custom_bad_request(format!("{:?}", e)))
}
};
publish_blocks::publish_block(
None,
ProvenancedBlock::local(block_contents),
chain,
&network_tx,
log,
BroadcastValidation::default(),
)
.await
.map(|()| warp::reply().into_response())
},
);
let post_beacon_blocks_v2 = eth_v2
.and(warp::path("beacon"))
.and(warp::path("blocks"))
@@ -1274,6 +1310,57 @@ pub fn serve<T: BeaconChainTypes>(
},
);
let post_beacon_blocks_v2_ssz = eth_v2
.and(warp::path("beacon"))
.and(warp::path("blocks"))
.and(warp::query::<api_types::BroadcastValidationQuery>())
.and(warp::path::end())
.and(warp::body::bytes())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.then(
|validation_level: api_types::BroadcastValidationQuery,
block_bytes: Bytes,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
let block_contents = match SignedBlockContents::<T::EthSpec>::from_ssz_bytes(
&block_bytes,
&chain.spec,
) {
Ok(data) => data,
Err(_) => {
return warp::reply::with_status(
StatusCode::BAD_REQUEST,
eth2::StatusCode::BAD_REQUEST,
)
.into_response();
}
};
match publish_blocks::publish_block(
None,
ProvenancedBlock::local(block_contents),
chain,
&network_tx,
log,
validation_level.broadcast_validation,
)
.await
{
Ok(()) => warp::reply().into_response(),
Err(e) => match warp_utils::reject::handle_rejection(e).await {
Ok(reply) => reply.into_response(),
Err(_) => warp::reply::with_status(
StatusCode::INTERNAL_SERVER_ERROR,
eth2::StatusCode::INTERNAL_SERVER_ERROR,
)
.into_response(),
},
}
},
);
/*
* beacon/blocks
*/
@@ -1304,6 +1391,42 @@ pub fn serve<T: BeaconChainTypes>(
},
);
// POST beacon/blocks
let post_beacon_blinded_blocks_ssz = eth_v1
.and(warp::path("beacon"))
.and(warp::path("blinded_blocks"))
.and(warp::path::end())
.and(warp::body::bytes())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.and_then(
|block_bytes: Bytes,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
let block =
match SignedBlockContents::<T::EthSpec, BlindedPayload<_>>::from_ssz_bytes(
&block_bytes,
&chain.spec,
) {
Ok(data) => data,
Err(e) => {
return Err(warp_utils::reject::custom_bad_request(format!("{:?}", e)))
}
};
publish_blocks::publish_blinded_block(
block,
chain,
&network_tx,
log,
BroadcastValidation::default(),
)
.await
.map(|()| warp::reply().into_response())
},
);
let post_beacon_blinded_blocks_v2 = eth_v2
.and(warp::path("beacon"))
.and(warp::path("blinded_blocks"))
@@ -1341,6 +1464,57 @@ pub fn serve<T: BeaconChainTypes>(
},
);
let post_beacon_blinded_blocks_v2_ssz = eth_v2
.and(warp::path("beacon"))
.and(warp::path("blinded_blocks"))
.and(warp::query::<api_types::BroadcastValidationQuery>())
.and(warp::path::end())
.and(warp::body::bytes())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.then(
|validation_level: api_types::BroadcastValidationQuery,
block_bytes: Bytes,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
log: Logger| async move {
let block =
match SignedBlockContents::<T::EthSpec, BlindedPayload<_>>::from_ssz_bytes(
&block_bytes,
&chain.spec,
) {
Ok(data) => data,
Err(_) => {
return warp::reply::with_status(
StatusCode::BAD_REQUEST,
eth2::StatusCode::BAD_REQUEST,
)
.into_response();
}
};
match publish_blocks::publish_blinded_block(
block,
chain,
&network_tx,
log,
validation_level.broadcast_validation,
)
.await
{
Ok(()) => warp::reply().into_response(),
Err(e) => match warp_utils::reject::handle_rejection(e).await {
Ok(reply) => reply.into_response(),
Err(_) => warp::reply::with_status(
StatusCode::INTERNAL_SERVER_ERROR,
eth2::StatusCode::INTERNAL_SERVER_ERROR,
)
.into_response(),
},
}
},
);
let block_id_or_err = warp::path::param::<BlockId>().or_else(|_| async {
Err(warp_utils::reject::custom_bad_request(
"Invalid block ID".to_string(),
@@ -2741,6 +2915,7 @@ pub fn serve<T: BeaconChainTypes>(
fork_versioned_response(endpoint_version, fork_name, block_contents?)
.map(|response| warp::reply::json(&response).into_response())
.map(|res| add_consensus_version_header(res, fork_name))
},
);
@@ -2798,6 +2973,7 @@ pub fn serve<T: BeaconChainTypes>(
// Pose as a V2 endpoint so we return the fork `version`.
fork_versioned_response(V2, fork_name, block)
.map(|response| warp::reply::json(&response).into_response())
.map(|res| add_consensus_version_header(res, fork_name))
},
);
@@ -3345,6 +3521,45 @@ pub fn serve<T: BeaconChainTypes>(
},
);
// POST vaidator/liveness/{epoch}
let post_validator_liveness_epoch = eth_v1
.and(warp::path("validator"))
.and(warp::path("liveness"))
.and(warp::path::param::<Epoch>())
.and(warp::path::end())
.and(warp::body::json())
.and(chain_filter.clone())
.and_then(
|epoch: Epoch, indices: Vec<u64>, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
// Ensure the request is for either the current, previous or next epoch.
let current_epoch = chain
.epoch()
.map_err(warp_utils::reject::beacon_chain_error)?;
let prev_epoch = current_epoch.saturating_sub(Epoch::new(1));
let next_epoch = current_epoch.saturating_add(Epoch::new(1));
if epoch < prev_epoch || epoch > next_epoch {
return Err(warp_utils::reject::custom_bad_request(format!(
"request epoch {} is more than one epoch from the current epoch {}",
epoch, current_epoch
)));
}
let liveness: Vec<api_types::StandardLivenessResponseData> = indices
.iter()
.cloned()
.map(|index| {
let is_live = chain.validator_seen_at_epoch(index as usize, epoch);
api_types::StandardLivenessResponseData { index, is_live }
})
.collect();
Ok(api_types::GenericResponse::from(liveness))
})
},
);
// POST lighthouse/liveness
let post_lighthouse_liveness = warp::path("lighthouse")
.and(warp::path("liveness"))
@@ -3967,7 +4182,15 @@ pub fn serve<T: BeaconChainTypes>(
.boxed()
.uor(
warp::post().and(
post_beacon_blocks
warp::header::exact("Content-Type", "application/octet-stream")
// Routes which expect `application/octet-stream` go within this `and`.
.and(
post_beacon_blocks_ssz
.uor(post_beacon_blocks_v2_ssz)
.uor(post_beacon_blinded_blocks_ssz)
.uor(post_beacon_blinded_blocks_v2_ssz),
)
.uor(post_beacon_blocks)
.uor(post_beacon_blinded_blocks)
.uor(post_beacon_blocks_v2)
.uor(post_beacon_blinded_blocks_v2)
@@ -3987,6 +4210,7 @@ pub fn serve<T: BeaconChainTypes>(
.uor(post_validator_sync_committee_subscriptions)
.uor(post_validator_prepare_beacon_proposer)
.uor(post_validator_register_validator)
.uor(post_validator_liveness_epoch)
.uor(post_lighthouse_liveness)
.uor(post_lighthouse_database_reconstruct)
.uor(post_lighthouse_block_rewards)
+2 -2
View File
@@ -3,7 +3,7 @@
use crate::state_id::StateId;
use beacon_chain::{
beacon_proposer_cache::{compute_proposer_duties_from_head, ensure_state_is_in_epoch},
BeaconChain, BeaconChainError, BeaconChainTypes, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
BeaconChain, BeaconChainError, BeaconChainTypes,
};
use eth2::types::{self as api_types};
use safe_arith::SafeArith;
@@ -33,7 +33,7 @@ pub fn proposer_duties<T: BeaconChainTypes>(
// will equal `current_epoch + 1`
let tolerant_current_epoch = chain
.slot_clock
.now_with_future_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)
.now_with_future_tolerance(chain.spec.maximum_gossip_clock_disparity())
.ok_or_else(|| warp_utils::reject::custom_server_error("unable to read slot clock".into()))?
.epoch(T::EthSpec::slots_per_epoch());
+2 -2
View File
@@ -6,7 +6,7 @@ use beacon_chain::sync_committee_verification::{
};
use beacon_chain::{
validator_monitor::timestamp_now, BeaconChain, BeaconChainError, BeaconChainTypes,
StateSkipConfig, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
StateSkipConfig,
};
use eth2::types::{self as api_types};
use lighthouse_network::PubsubMessage;
@@ -85,7 +85,7 @@ fn duties_from_state_load<T: BeaconChainTypes>(
let current_epoch = chain.epoch()?;
let tolerant_current_epoch = chain
.slot_clock
.now_with_future_tolerance(MAXIMUM_GOSSIP_CLOCK_DISPARITY)
.now_with_future_tolerance(chain.spec.maximum_gossip_clock_disparity())
.ok_or(BeaconChainError::UnableToReadSlot)?
.epoch(T::EthSpec::slots_per_epoch());
+4 -7
View File
@@ -7,12 +7,9 @@ use directory::DEFAULT_ROOT_DIR;
use eth2::{BeaconNodeHttpClient, Timeouts};
use lighthouse_network::{
discv5::enr::{CombinedKey, EnrBuilder},
libp2p::{
core::connection::ConnectionId,
swarm::{
behaviour::{ConnectionEstablished, FromSwarm},
NetworkBehaviour,
},
libp2p::swarm::{
behaviour::{ConnectionEstablished, FromSwarm},
ConnectionId, NetworkBehaviour,
},
rpc::methods::{MetaData, MetaDataV2},
types::{EnrAttestationBitfield, EnrSyncCommitteeBitfield, SyncState},
@@ -167,7 +164,7 @@ pub async fn create_api_server_on_port<T: BeaconChainTypes>(
local_addr: EXTERNAL_ADDR.parse().unwrap(),
send_back_addr: EXTERNAL_ADDR.parse().unwrap(),
};
let connection_id = ConnectionId::new(1);
let connection_id = ConnectionId::new_unchecked(1);
pm.on_swarm_event(FromSwarm::ConnectionEstablished(ConnectionEstablished {
peer_id,
connection_id,
@@ -182,6 +182,48 @@ pub async fn gossip_full_pass() {
.block_is_known_to_fork_choice(&block.canonical_root()));
}
// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=gossip`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn gossip_full_pass_ssz() {
/* this test targets gossip-level validation */
let validation_level: Option<BroadcastValidation> = Some(BroadcastValidation::Gossip);
// Validator count needs to be at least 32 or proposer boost gets set to 0 when computing
// `validator_count // 32`.
let validator_count = 64;
let num_initial: u64 = 31;
let tester = InteractiveTester::<E>::new(None, validator_count).await;
// Create some chain depth.
tester.harness.advance_slot();
tester
.harness
.extend_chain(
num_initial as usize,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
)
.await;
tester.harness.advance_slot();
let slot_a = Slot::new(num_initial);
let slot_b = slot_a + 1;
let state_a = tester.harness.get_current_state();
let (block, _): (SignedBeaconBlock<E>, _) = tester.harness.make_block(state_a, slot_b).await;
let response: Result<(), eth2::Error> = tester
.client
.post_beacon_blocks_v2_ssz(&block, validation_level)
.await;
assert!(response.is_ok());
assert!(tester
.harness
.chain
.block_is_known_to_fork_choice(&block.canonical_root()));
}
/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn consensus_invalid() {
@@ -836,6 +878,49 @@ pub async fn blinded_gossip_full_pass() {
.block_is_known_to_fork_choice(&block.canonical_root()));
}
// This test checks that a block that is valid from both a gossip and consensus perspective is accepted when using `broadcast_validation=gossip`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn blinded_gossip_full_pass_ssz() {
/* this test targets gossip-level validation */
let validation_level: Option<BroadcastValidation> = Some(BroadcastValidation::Gossip);
// Validator count needs to be at least 32 or proposer boost gets set to 0 when computing
// `validator_count // 32`.
let validator_count = 64;
let num_initial: u64 = 31;
let tester = InteractiveTester::<E>::new(None, validator_count).await;
// Create some chain depth.
tester.harness.advance_slot();
tester
.harness
.extend_chain(
num_initial as usize,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
)
.await;
tester.harness.advance_slot();
let slot_a = Slot::new(num_initial);
let slot_b = slot_a + 1;
let state_a = tester.harness.get_current_state();
let (block, _): (SignedBlindedBeaconBlock<E>, _) =
tester.harness.make_blinded_block(state_a, slot_b).await;
let response: Result<(), eth2::Error> = tester
.client
.post_beacon_blinded_blocks_v2_ssz(&block, validation_level)
.await;
assert!(response.is_ok());
assert!(tester
.harness
.chain
.block_is_known_to_fork_choice(&block.canonical_root()));
}
/// This test checks that a block that is **invalid** from a gossip perspective gets rejected when using `broadcast_validation=consensus`.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn blinded_consensus_invalid() {
+210 -5
View File
@@ -1,7 +1,7 @@
use beacon_chain::test_utils::RelativeSyncCommittee;
use beacon_chain::{
test_utils::{AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType},
BeaconChain, StateSkipConfig, WhenSlotSkipped, MAXIMUM_GOSSIP_CLOCK_DISPARITY,
BeaconChain, StateSkipConfig, WhenSlotSkipped,
};
use environment::null_logger;
use eth2::{
@@ -1251,6 +1251,22 @@ impl ApiTester {
self
}
pub async fn test_post_beacon_blocks_ssz_valid(mut self) -> Self {
let next_block = &self.next_block;
self.client
.post_beacon_blocks_ssz(next_block)
.await
.unwrap();
assert!(
self.network_rx.network_recv.recv().await.is_some(),
"valid blocks should be sent to network"
);
self
}
pub async fn test_post_beacon_blocks_invalid(mut self) -> Self {
let block = self
.harness
@@ -1278,6 +1294,29 @@ impl ApiTester {
self
}
pub async fn test_post_beacon_blocks_ssz_invalid(mut self) -> Self {
let block = self
.harness
.make_block_with_modifier(
self.harness.get_current_state(),
self.harness.get_current_slot(),
|b| {
*b.state_root_mut() = Hash256::zero();
},
)
.await
.0;
assert!(self.client.post_beacon_blocks_ssz(&block).await.is_err());
assert!(
self.network_rx.network_recv.recv().await.is_some(),
"gossip valid blocks should be sent to network"
);
self
}
pub async fn test_beacon_blocks(self) -> Self {
for block_id in self.interesting_block_ids() {
let expected = block_id
@@ -2282,7 +2321,9 @@ impl ApiTester {
.unwrap();
self.chain.slot_clock.set_current_time(
current_epoch_start - MAXIMUM_GOSSIP_CLOCK_DISPARITY - Duration::from_millis(1),
current_epoch_start
- self.chain.spec.maximum_gossip_clock_disparity()
- Duration::from_millis(1),
);
let dependent_root = self
@@ -2319,9 +2360,9 @@ impl ApiTester {
"should not get attester duties outside of tolerance"
);
self.chain
.slot_clock
.set_current_time(current_epoch_start - MAXIMUM_GOSSIP_CLOCK_DISPARITY);
self.chain.slot_clock.set_current_time(
current_epoch_start - self.chain.spec.maximum_gossip_clock_disparity(),
);
self.client
.get_validator_duties_proposer(current_epoch)
@@ -2554,6 +2595,66 @@ impl ApiTester {
}
}
pub async fn test_blinded_block_production_ssz<Payload: AbstractExecPayload<E>>(&self) {
let fork = self.chain.canonical_head.cached_head().head_fork();
let genesis_validators_root = self.chain.genesis_validators_root;
for _ in 0..E::slots_per_epoch() * 3 {
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 randao_reveal = {
let domain = self.chain.spec.get_domain(
epoch,
Domain::Randao,
&fork,
genesis_validators_root,
);
let message = epoch.signing_root(domain);
sk.sign(message).into()
};
let block = self
.client
.get_validator_blinded_blocks::<E, Payload>(slot, &randao_reveal, None)
.await
.unwrap()
.data;
let signed_block = block.sign(&sk, &fork, genesis_validators_root, &self.chain.spec);
self.client
.post_beacon_blinded_blocks_ssz(&signed_block)
.await
.unwrap();
// This converts the generic `Payload` to a concrete type for comparison.
let head_block = SignedBeaconBlock::from(signed_block.clone());
assert_eq!(head_block, signed_block);
self.chain.slot_clock.set_slot(slot.as_u64() + 1);
}
}
pub async fn test_blinded_block_production_no_verify_randao<Payload: AbstractExecPayload<E>>(
self,
) -> Self {
@@ -2997,6 +3098,69 @@ impl ApiTester {
self
}
pub async fn test_post_validator_liveness_epoch(self) -> Self {
let epoch = self.chain.epoch().unwrap();
let head_state = self.chain.head_beacon_state_cloned();
let indices = (0..head_state.validators().len())
.map(|i| i as u64)
.collect::<Vec<_>>();
// Construct the expected response
let expected: Vec<StandardLivenessResponseData> = head_state
.validators()
.iter()
.enumerate()
.map(|(index, _)| StandardLivenessResponseData {
index: index as u64,
is_live: false,
})
.collect();
let result = self
.client
.post_validator_liveness_epoch(epoch, indices.clone())
.await
.unwrap()
.data;
assert_eq!(result, expected);
// Attest to the current slot
self.client
.post_beacon_pool_attestations(self.attestations.as_slice())
.await
.unwrap();
let result = self
.client
.post_validator_liveness_epoch(epoch, indices.clone())
.await
.unwrap()
.data;
let committees = head_state
.get_beacon_committees_at_slot(self.chain.slot().unwrap())
.unwrap();
let attesting_validators: Vec<usize> = committees
.into_iter()
.flat_map(|committee| committee.committee.iter().cloned())
.collect();
// All attesters should now be considered live
let expected = expected
.into_iter()
.map(|mut a| {
if attesting_validators.contains(&(a.index as usize)) {
a.is_live = true;
}
a
})
.collect::<Vec<_>>();
assert_eq!(result, expected);
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();
@@ -4409,6 +4573,22 @@ async fn post_beacon_blocks_valid() {
ApiTester::new().await.test_post_beacon_blocks_valid().await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_beacon_blocks_ssz_valid() {
ApiTester::new()
.await
.test_post_beacon_blocks_ssz_valid()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_post_beacon_blocks_ssz_invalid() {
ApiTester::new()
.await
.test_post_beacon_blocks_ssz_invalid()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_beacon_blocks_invalid() {
ApiTester::new()
@@ -4605,6 +4785,14 @@ async fn blinded_block_production_full_payload_premerge() {
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn blinded_block_production_ssz_full_payload_premerge() {
ApiTester::new()
.await
.test_blinded_block_production_ssz::<FullPayload<_>>()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn blinded_block_production_with_skip_slots_full_payload_premerge() {
ApiTester::new()
@@ -4614,6 +4802,15 @@ async fn blinded_block_production_with_skip_slots_full_payload_premerge() {
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn blinded_block_production_ssz_with_skip_slots_full_payload_premerge() {
ApiTester::new()
.await
.skip_slots(E::slots_per_epoch() * 2)
.test_blinded_block_production_ssz::<FullPayload<_>>()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn blinded_block_production_no_verify_randao_full_payload_premerge() {
ApiTester::new()
@@ -4891,6 +5088,14 @@ async fn builder_works_post_capella() {
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn post_validator_liveness_epoch() {
ApiTester::new()
.await
.test_post_validator_liveness_epoch()
.await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn lighthouse_endpoints() {
ApiTester::new()