Merge remote-tracking branch 'origin/unstable' into tree-states

This commit is contained in:
Michael Sproul
2022-05-24 10:01:05 +10:00
237 changed files with 8506 additions and 3598 deletions

View File

@@ -27,8 +27,10 @@ slot_clock = { path = "../../common/slot_clock" }
eth2_ssz = "0.4.1"
bs58 = "0.4.0"
futures = "0.3.8"
parking_lot = "0.11.0"
execution_layer = {path = "../execution_layer"}
parking_lot = "0.12.0"
safe_arith = {path = "../../consensus/safe_arith"}
task_executor = { path = "../../common/task_executor" }
[dev-dependencies]
@@ -36,6 +38,7 @@ store = { path = "../store" }
environment = { path = "../../lighthouse/environment" }
tree_hash = "0.4.1"
sensitive_url = { path = "../../common/sensitive_url" }
logging = { path = "../../common/logging" }
[[test]]
name = "bn_http_api_tests"

View File

@@ -7,7 +7,7 @@ use state_processing::{
per_epoch_processing::EpochProcessingSummary, BlockReplayError, BlockReplayer,
};
use std::sync::Arc;
use types::{BeaconState, BeaconStateError, EthSpec, Hash256, SignedBeaconBlock};
use types::{BeaconState, BeaconStateError, EthSpec, Hash256};
use warp_utils::reject::{beacon_chain_error, custom_bad_request, custom_server_error};
const MAX_REQUEST_RANGE_EPOCHS: usize = 100;
@@ -112,7 +112,7 @@ pub fn get_attestation_performance<T: BeaconChainTypes>(
)
})?;
let first_block = chain
.get_block(first_block_root)
.get_blinded_block(first_block_root)
.and_then(|maybe_block| {
maybe_block.ok_or(BeaconChainError::MissingBeaconBlock(*first_block_root))
})
@@ -120,7 +120,7 @@ pub fn get_attestation_performance<T: BeaconChainTypes>(
// Load the block of the prior slot which will be used to build the starting state.
let prior_block = chain
.get_block(&first_block.parent_root())
.get_blinded_block(&first_block.parent_root())
.and_then(|maybe_block| {
maybe_block
.ok_or_else(|| BeaconChainError::MissingBeaconBlock(first_block.parent_root()))
@@ -197,13 +197,13 @@ pub fn get_attestation_performance<T: BeaconChainTypes>(
.iter()
.map(|root| {
chain
.get_block(root)
.get_blinded_block(root)
.and_then(|maybe_block| {
maybe_block.ok_or(BeaconChainError::MissingBeaconBlock(*root))
})
.map_err(beacon_chain_error)
})
.collect::<Result<Vec<SignedBeaconBlock<T::EthSpec>>, _>>()?;
.collect::<Result<Vec<_>, _>>()?;
replayer = replayer
.apply_blocks(blocks, None)

View File

@@ -1,7 +1,7 @@
use beacon_chain::{BeaconChain, BeaconChainTypes, WhenSlotSkipped};
use eth2::types::BlockId as CoreBlockId;
use std::str::FromStr;
use types::{Hash256, SignedBeaconBlock, Slot};
use types::{BlindedPayload, Hash256, SignedBeaconBlock, Slot};
/// Wraps `eth2::types::BlockId` and provides a simple way to obtain a block or root for a given
/// `BlockId`.
@@ -52,7 +52,55 @@ impl BlockId {
}
/// Return the `SignedBeaconBlock` identified by `self`.
pub fn block<T: BeaconChainTypes>(
pub fn blinded_block<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<SignedBeaconBlock<T::EthSpec, BlindedPayload<T::EthSpec>>, warp::Rejection> {
match &self.0 {
CoreBlockId::Head => chain
.head_beacon_block()
.map(Into::into)
.map_err(warp_utils::reject::beacon_chain_error),
CoreBlockId::Slot(slot) => {
let root = self.root(chain)?;
chain
.get_blinded_block(&root)
.map_err(warp_utils::reject::beacon_chain_error)
.and_then(|block_opt| match block_opt {
Some(block) => {
if block.slot() != *slot {
return Err(warp_utils::reject::custom_not_found(format!(
"slot {} was skipped",
slot
)));
}
Ok(block)
}
None => Err(warp_utils::reject::custom_not_found(format!(
"beacon block with root {}",
root
))),
})
}
_ => {
let root = self.root(chain)?;
chain
.get_blinded_block(&root)
.map_err(warp_utils::reject::beacon_chain_error)
.and_then(|root_opt| {
root_opt.ok_or_else(|| {
warp_utils::reject::custom_not_found(format!(
"beacon block with root {}",
root
))
})
})
}
}
}
/// Return the `SignedBeaconBlock` identified by `self`.
pub async fn full_block<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<SignedBeaconBlock<T::EthSpec>, warp::Rejection> {
@@ -64,6 +112,7 @@ impl BlockId {
let root = self.root(chain)?;
chain
.get_block(&root)
.await
.map_err(warp_utils::reject::beacon_chain_error)
.and_then(|block_opt| match block_opt {
Some(block) => {
@@ -85,6 +134,7 @@ impl BlockId {
let root = self.root(chain)?;
chain
.get_block(&root)
.await
.map_err(warp_utils::reject::beacon_chain_error)
.and_then(|root_opt| {
root_opt.ok_or_else(|| {

View File

@@ -10,8 +10,8 @@ use std::collections::{HashMap, HashSet};
use std::marker::PhantomData;
use std::sync::Arc;
use types::{
BeaconCommittee, BeaconState, BeaconStateError, ChainSpec, Epoch, EthSpec, Hash256,
OwnedBeaconCommittee, RelativeEpoch, SignedBeaconBlock, Slot,
BeaconCommittee, BeaconState, BeaconStateError, BlindedPayload, ChainSpec, Epoch, EthSpec,
Hash256, OwnedBeaconCommittee, RelativeEpoch, SignedBeaconBlock, Slot,
};
use warp_utils::reject::{beacon_chain_error, custom_bad_request, custom_server_error};
@@ -104,7 +104,7 @@ impl<T: EthSpec> PackingEfficiencyHandler<T> {
fn apply_block(
&mut self,
block: &SignedBeaconBlock<T>,
block: &SignedBeaconBlock<T, BlindedPayload<T>>,
) -> Result<usize, PackingEfficiencyError> {
let block_body = block.message().body();
let attestations = block_body.attestations();
@@ -251,7 +251,7 @@ pub fn get_block_packing_efficiency<T: BeaconChainTypes>(
.ok_or_else(|| custom_server_error("no blocks were loaded".to_string()))?;
let first_block = chain
.get_block(first_block_root)
.get_blinded_block(first_block_root)
.and_then(|maybe_block| {
maybe_block.ok_or(BeaconChainError::MissingBeaconBlock(*first_block_root))
})
@@ -309,7 +309,7 @@ pub fn get_block_packing_efficiency<T: BeaconChainTypes>(
};
let pre_block_hook = |_state: &mut BeaconState<T::EthSpec>,
block: &SignedBeaconBlock<T::EthSpec>|
block: &SignedBeaconBlock<_, BlindedPayload<_>>|
-> Result<(), PackingEfficiencyError> {
let slot = block.slot();
@@ -363,13 +363,13 @@ pub fn get_block_packing_efficiency<T: BeaconChainTypes>(
.iter()
.map(|root| {
chain
.get_block(root)
.get_blinded_block(root)
.and_then(|maybe_block| {
maybe_block.ok_or(BeaconChainError::MissingBeaconBlock(*root))
})
.map_err(beacon_chain_error)
})
.collect::<Result<Vec<SignedBeaconBlock<T::EthSpec>>, _>>()?;
.collect::<Result<Vec<_>, _>>()?;
replayer = replayer
.apply_blocks(blocks, None)

View File

@@ -2,17 +2,19 @@ use beacon_chain::store::{metadata::CURRENT_SCHEMA_VERSION, AnchorInfo};
use beacon_chain::{BeaconChain, BeaconChainTypes};
use eth2::lighthouse::DatabaseInfo;
use std::sync::Arc;
use types::SignedBeaconBlock;
use types::SignedBlindedBeaconBlock;
pub fn info<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
) -> Result<DatabaseInfo, warp::Rejection> {
let store = &chain.store;
let split = store.get_split_info();
let config = store.get_config().clone();
let anchor = store.get_anchor_info();
Ok(DatabaseInfo {
schema_version: CURRENT_SCHEMA_VERSION.as_u64(),
config,
split,
anchor,
})
@@ -20,10 +22,10 @@ pub fn info<T: BeaconChainTypes>(
pub fn historical_blocks<T: BeaconChainTypes>(
chain: Arc<BeaconChain<T>>,
blocks: Vec<SignedBeaconBlock<T::EthSpec>>,
blocks: Vec<SignedBlindedBeaconBlock<T::EthSpec>>,
) -> Result<AnchorInfo, warp::Rejection> {
chain
.import_historical_block_batch(&blocks)
.import_historical_block_batch(blocks)
.map_err(warp_utils::reject::beacon_chain_error)?;
let anchor = chain.store.get_anchor_info().ok_or_else(|| {

View File

@@ -45,10 +45,12 @@ use std::sync::Arc;
use tokio::sync::mpsc::UnboundedSender;
use tokio_stream::{wrappers::BroadcastStream, StreamExt};
use types::{
Attestation, AttesterSlashing, BeaconStateError, CommitteeCache, ConfigAndPreset, Epoch,
EthSpec, ForkName, ProposerPreparationData, ProposerSlashing, RelativeEpoch, Signature,
SignedAggregateAndProof, SignedBeaconBlock, SignedContributionAndProof, SignedVoluntaryExit,
Slot, SyncCommitteeMessage, SyncContributionData,
Attestation, AttesterSlashing, BeaconBlockBodyMerge, BeaconBlockMerge, BeaconStateError,
BlindedPayload, CommitteeCache, ConfigAndPreset, Epoch, EthSpec, ForkName, FullPayload,
ProposerPreparationData, ProposerSlashing, RelativeEpoch, Signature, SignedAggregateAndProof,
SignedBeaconBlock, SignedBeaconBlockMerge, SignedBlindedBeaconBlock,
SignedContributionAndProof, SignedVoluntaryExit, Slot, SyncCommitteeMessage,
SyncContributionData,
};
use version::{
add_consensus_version_header, fork_versioned_response, inconsistent_fork_rejection,
@@ -825,10 +827,10 @@ pub fn serve<T: BeaconChainTypes>(
(None, None) => chain
.head_beacon_block()
.map_err(warp_utils::reject::beacon_chain_error)
.map(|block| (block.canonical_root(), block))?,
.map(|block| (block.canonical_root(), block.into()))?,
// Only the parent root parameter, do a forwards-iterator lookup.
(None, Some(parent_root)) => {
let parent = BlockId::from_root(parent_root).block(&chain)?;
let parent = BlockId::from_root(parent_root).blinded_block(&chain)?;
let (root, _slot) = chain
.forwards_iter_block_roots(parent.slot())
.map_err(warp_utils::reject::beacon_chain_error)?
@@ -846,14 +848,14 @@ pub fn serve<T: BeaconChainTypes>(
})?;
BlockId::from_root(root)
.block(&chain)
.blinded_block(&chain)
.map(|block| (root, block))?
}
// Slot is supplied, search by slot and optionally filter by
// parent root.
(Some(slot), parent_root_opt) => {
let root = BlockId::from_slot(slot).root(&chain)?;
let block = BlockId::from_root(root).block(&chain)?;
let block = BlockId::from_root(root).blinded_block(&chain)?;
// If the parent root was supplied, check that it matches the block
// obtained via a slot lookup.
@@ -898,7 +900,7 @@ pub fn serve<T: BeaconChainTypes>(
.and_then(|block_id: BlockId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
let root = block_id.root(&chain)?;
let block = BlockId::from_root(root).block(&chain)?;
let block = BlockId::from_root(root).blinded_block(&chain)?;
let canonical = chain
.block_root_at_slot(block.slot(), WhenSlotSkipped::None)
@@ -1022,6 +1024,116 @@ pub fn serve<T: BeaconChainTypes>(
},
);
/*
* beacon/blocks
*/
// POST beacon/blocks
let post_beacon_blinded_blocks = eth1_v1
.and(warp::path("beacon"))
.and(warp::path("blinded_blocks"))
.and(warp::path::end())
.and(warp::body::json())
.and(chain_filter.clone())
.and(network_tx_filter.clone())
.and(log_filter.clone())
.and_then(
|block: SignedBeaconBlock<T::EthSpec, BlindedPayload<_>>,
chain: Arc<BeaconChain<T>>,
network_tx: UnboundedSender<NetworkMessage<T::EthSpec>>,
_log: Logger| {
blocking_json_task(move || {
if let Some(el) = chain.execution_layer.as_ref() {
//FIXME(sean): we may not always receive the payload in this response because it
// should be the relay's job to propogate the block. However, since this block is
// already signed and sent this might be ok (so long as the relay validates
// the block before revealing the payload).
//FIXME(sean) additionally, this endpoint should serve blocks prior to Bellatrix, and should
// be able to support the normal block proposal flow, because at some point full block endpoints
// will be deprecated from the beacon API. This will entail creating full blocks in
// `validator/blinded_blocks`, caching their payloads, and transforming them into blinded
// blocks. We will access the payload of those blocks here. This flow should happen if the
// execution layer has no payload builders or if we have not yet finalized post-merge transition.
let payload = el
.block_on(|el| el.propose_blinded_beacon_block(&block))
.map_err(|e| {
warp_utils::reject::custom_server_error(format!(
"proposal failed: {:?}",
e
))
})?;
let new_block = SignedBeaconBlock::Merge(SignedBeaconBlockMerge {
message: BeaconBlockMerge {
slot: block.message().slot(),
proposer_index: block.message().proposer_index(),
parent_root: block.message().parent_root(),
state_root: block.message().state_root(),
body: BeaconBlockBodyMerge {
randao_reveal: block.message().body().randao_reveal().clone(),
eth1_data: block.message().body().eth1_data().clone(),
graffiti: *block.message().body().graffiti(),
proposer_slashings: block
.message()
.body()
.proposer_slashings()
.clone(),
attester_slashings: block
.message()
.body()
.attester_slashings()
.clone(),
attestations: block.message().body().attestations().clone(),
deposits: block.message().body().deposits().clone(),
voluntary_exits: block
.message()
.body()
.voluntary_exits()
.clone(),
sync_aggregate: block
.message()
.body()
.sync_aggregate()
.unwrap()
.clone(),
execution_payload: payload.into(),
},
},
signature: block.signature().clone(),
});
// Send the block, regardless of whether or not it is valid. The API
// specification is very clear that this is the desired behaviour.
publish_pubsub_message(
&network_tx,
PubsubMessage::BeaconBlock(Box::new(new_block.clone())),
)?;
match chain.process_block(new_block) {
Ok(_) => {
// Update the head since it's likely this block will become the new
// head.
chain
.fork_choice()
.map_err(warp_utils::reject::beacon_chain_error)?;
Ok(())
}
Err(e) => {
let msg = format!("{:?}", e);
Err(warp_utils::reject::broadcast_without_import(msg))
}
}
} else {
Err(warp_utils::reject::custom_server_error(
"no execution layer found".to_string(),
))
}
})
},
);
let block_id_or_err = warp::path::param::<BlockId>().or_else(|_| async {
Err(warp_utils::reject::custom_bad_request(
"Invalid block ID".to_string(),
@@ -1050,8 +1162,8 @@ pub fn serve<T: BeaconChainTypes>(
block_id: BlockId,
chain: Arc<BeaconChain<T>>,
accept_header: Option<api_types::Accept>| {
blocking_task(move || {
let block = block_id.block(&chain)?;
async move {
let block = block_id.full_block(&chain).await?;
let fork_name = block
.fork_name(&chain.spec)
.map_err(inconsistent_fork_rejection)?;
@@ -1070,7 +1182,7 @@ pub fn serve<T: BeaconChainTypes>(
.map(|res| warp::reply::json(&res).into_response()),
}
.map(|resp| add_consensus_version_header(resp, fork_name))
})
}
},
);
@@ -1096,7 +1208,7 @@ pub fn serve<T: BeaconChainTypes>(
.and_then(|block_id: BlockId, chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
block_id
.block(&chain)
.blinded_block(&chain)
.map(|block| block.message().body().attestations().clone())
.map(api_types::GenericResponse::from)
})
@@ -1899,7 +2011,69 @@ pub fn serve<T: BeaconChainTypes>(
};
let (block, _) = chain
.produce_block_with_verification(
.produce_block_with_verification::<FullPayload<T::EthSpec>>(
randao_reveal,
slot,
query.graffiti.map(Into::into),
randao_verification,
)
.map_err(warp_utils::reject::block_production_error)?;
let fork_name = block
.to_ref()
.fork_name(&chain.spec)
.map_err(inconsistent_fork_rejection)?;
fork_versioned_response(endpoint_version, fork_name, block)
})
},
);
// GET validator/blinded_blocks/{slot}
let get_validator_blinded_blocks = any_version
.and(warp::path("validator"))
.and(warp::path("blinded_blocks"))
.and(warp::path::param::<Slot>().or_else(|_| async {
Err(warp_utils::reject::custom_bad_request(
"Invalid slot".to_string(),
))
}))
.and(warp::path::end())
.and(not_while_syncing_filter.clone())
.and(warp::query::<api_types::ValidatorBlocksQuery>())
.and(chain_filter.clone())
.and_then(
|endpoint_version: EndpointVersion,
slot: Slot,
query: api_types::ValidatorBlocksQuery,
chain: Arc<BeaconChain<T>>| {
blocking_json_task(move || {
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_with_verification::<BlindedPayload<T::EthSpec>>(
randao_reveal,
slot,
query.graffiti.map(Into::into),
@@ -1965,6 +2139,12 @@ pub fn serve<T: BeaconChainTypes>(
query.slot,
&query.attestation_data_root,
)
.map_err(|e| {
warp_utils::reject::custom_bad_request(format!(
"unable to fetch aggregate: {:?}",
e
))
})?
.map(api_types::GenericResponse::from)
.ok_or_else(|| {
warp_utils::reject::custom_not_found(
@@ -2607,7 +2787,7 @@ pub fn serve<T: BeaconChainTypes>(
.and(chain_filter.clone())
.and(log_filter.clone())
.and_then(
|blocks: Vec<SignedBeaconBlock<T::EthSpec>>,
|blocks: Vec<SignedBlindedBeaconBlock<T::EthSpec>>,
chain: Arc<BeaconChain<T>>,
log: Logger| {
info!(
@@ -2766,6 +2946,7 @@ pub fn serve<T: BeaconChainTypes>(
.or(get_node_peer_count.boxed())
.or(get_validator_duties_proposer.boxed())
.or(get_validator_blocks.boxed())
.or(get_validator_blinded_blocks.boxed())
.or(get_validator_attestation_data.boxed())
.or(get_validator_aggregate_attestation.boxed())
.or(get_validator_sync_committee_contribution.boxed())
@@ -2791,6 +2972,7 @@ pub fn serve<T: BeaconChainTypes>(
.or(warp::post().and(
post_beacon_blocks
.boxed()
.or(post_beacon_blinded_blocks.boxed())
.or(post_beacon_pool_attestations.boxed())
.or(post_beacon_pool_attester_slashings.boxed())
.or(post_beacon_pool_proposer_slashings.boxed())

View File

@@ -1,7 +1,9 @@
//! Generic tests that make use of the (newer) `InteractiveApiTester`
use crate::common::*;
use beacon_chain::test_utils::{AttestationStrategy, BlockStrategy};
use eth2::types::DepositContractData;
use types::{EthSpec, MainnetEthSpec};
use tree_hash::TreeHash;
use types::{EthSpec, FullPayload, MainnetEthSpec, Slot};
type E = MainnetEthSpec;
@@ -30,3 +32,96 @@ async fn deposit_contract_custom_network() {
assert_eq!(result, expected);
}
// Test that running fork choice before proposing results in selection of the correct head.
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
pub async fn fork_choice_before_proposal() {
// Validator count needs to be at least 32 or proposer boost gets set to 0 when computing
// `validator_count // 32`.
let validator_count = 32;
let all_validators = (0..validator_count).collect::<Vec<_>>();
let num_initial: u64 = 31;
let tester = InteractiveTester::<E>::new(None, validator_count).await;
let harness = &tester.harness;
// Create some chain depth.
harness.advance_slot();
harness.extend_chain(
num_initial as usize,
BlockStrategy::OnCanonicalHead,
AttestationStrategy::AllValidators,
);
// We set up the following block graph, where B is a block that is temporarily orphaned by C,
// but is then reinstated and built upon by D.
//
// A | B | - | D |
// ^ | - | C |
let slot_a = Slot::new(num_initial);
let slot_b = slot_a + 1;
let slot_c = slot_a + 2;
let slot_d = slot_a + 3;
let state_a = harness.get_current_state();
let (block_b, state_b) = harness.make_block(state_a.clone(), slot_b);
let block_root_b = harness.process_block(slot_b, block_b).unwrap();
// Create attestations to B but keep them in reserve until after C has been processed.
let attestations_b = harness.make_attestations(
&all_validators,
&state_b,
state_b.tree_hash_root(),
block_root_b,
slot_b,
);
let (block_c, state_c) = harness.make_block(state_a, slot_c);
let block_root_c = harness.process_block(slot_c, block_c.clone()).unwrap();
// Create attestations to C from a small number of validators and process them immediately.
let attestations_c = harness.make_attestations(
&all_validators[..validator_count / 2],
&state_c,
state_c.tree_hash_root(),
block_root_c,
slot_c,
);
harness.process_attestations(attestations_c);
// Apply the attestations to B, but don't re-run fork choice.
harness.process_attestations(attestations_b);
// Due to proposer boost, the head should be C during slot C.
assert_eq!(
harness.chain.head_info().unwrap().block_root,
block_root_c.into()
);
// Ensure that building a block via the HTTP API re-runs fork choice and builds block D upon B.
// Manually prod the per-slot task, because the slot timer doesn't run in the background in
// these tests.
harness.advance_slot();
harness.chain.per_slot_task();
let proposer_index = state_b
.get_beacon_proposer_index(slot_d, &harness.chain.spec)
.unwrap();
let randao_reveal = harness
.sign_randao_reveal(&state_b, proposer_index, slot_d)
.into();
let block_d = tester
.client
.get_validator_blocks::<E, FullPayload<E>>(slot_d, &randao_reveal, None)
.await
.unwrap()
.data;
// Head is now B.
assert_eq!(
harness.chain.head_info().unwrap().block_root,
block_root_b.into()
);
// D's parent is B.
assert_eq!(block_d.parent_root(), block_root_b.into());
}

View File

@@ -20,6 +20,7 @@ use slot_clock::SlotClock;
use state_processing::per_slot_processing;
use std::convert::TryInto;
use std::sync::Arc;
use task_executor::test_utils::TestRuntime;
use tokio::sync::{mpsc, oneshot};
use tokio::time::Duration;
use tree_hash::TreeHash;
@@ -63,6 +64,7 @@ struct ApiTester {
network_rx: mpsc::UnboundedReceiver<NetworkMessage<E>>,
local_enr: Enr,
external_peer_id: PeerId,
_runtime: TestRuntime,
}
impl ApiTester {
@@ -121,8 +123,7 @@ impl ApiTester {
harness.chain.slot().unwrap(),
)
.into_iter()
.map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation))
.flatten()
.flat_map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation))
.collect::<Vec<_>>();
assert!(
@@ -186,7 +187,7 @@ impl ApiTester {
external_peer_id,
} = create_api_server(chain.clone(), log).await;
tokio::spawn(server);
harness.runtime.task_executor.spawn(server, "api_server");
let client = BeaconNodeHttpClient::new(
SensitiveUrl::parse(&format!(
@@ -213,6 +214,7 @@ impl ApiTester {
network_rx,
local_enr,
external_peer_id,
_runtime: harness.runtime,
}
}
@@ -244,8 +246,7 @@ impl ApiTester {
harness.chain.slot().unwrap(),
)
.into_iter()
.map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation))
.flatten()
.flat_map(|vec| vec.into_iter().map(|(attestation, _subnet_id)| attestation))
.collect::<Vec<_>>();
let attester_slashing = harness.make_attester_slashing(vec![0, 1]);
@@ -265,7 +266,7 @@ impl ApiTester {
external_peer_id,
} = create_api_server(chain.clone(), log).await;
tokio::spawn(server);
harness.runtime.task_executor.spawn(server, "api_server");
let client = BeaconNodeHttpClient::new(
SensitiveUrl::parse(&format!(
@@ -292,6 +293,7 @@ impl ApiTester {
network_rx,
local_enr,
external_peer_id,
_runtime: harness.runtime,
}
}
@@ -762,9 +764,9 @@ impl ApiTester {
}
}
fn get_block(&self, block_id: BlockId) -> Option<SignedBeaconBlock<E>> {
let root = self.get_block_root(block_id);
root.and_then(|root| self.chain.get_block(&root).unwrap())
async fn get_block(&self, block_id: BlockId) -> Option<SignedBeaconBlock<E>> {
let root = self.get_block_root(block_id)?;
self.chain.get_block(&root).await.unwrap()
}
pub async fn test_beacon_headers_all_slots(self) -> Self {
@@ -859,7 +861,11 @@ impl ApiTester {
}
}
let block_opt = block_root_opt.and_then(|root| self.chain.get_block(&root).unwrap());
let block_opt = if let Some(root) = block_root_opt {
self.chain.get_block(&root).await.unwrap()
} else {
None
};
if block_opt.is_none() && result.is_none() {
continue;
@@ -945,7 +951,7 @@ impl ApiTester {
pub async fn test_beacon_blocks(self) -> Self {
for block_id in self.interesting_block_ids() {
let expected = self.get_block(block_id);
let expected = self.get_block(block_id).await;
if let BlockId::Slot(slot) = block_id {
if expected.is_none() {
@@ -1030,6 +1036,7 @@ impl ApiTester {
let expected = self
.get_block(block_id)
.await
.map(|block| block.message().body().attestations().clone().into());
if let BlockId::Slot(slot) = block_id {
@@ -1902,7 +1909,7 @@ impl ApiTester {
let block = self
.client
.get_validator_blocks::<E>(slot, &randao_reveal, None)
.get_validator_blocks::<E, FullPayload<E>>(slot, &randao_reveal, None)
.await
.unwrap()
.data;
@@ -1925,7 +1932,12 @@ impl ApiTester {
let block = self
.client
.get_validator_blocks_with_verify_randao::<E>(slot, None, None, Some(false))
.get_validator_blocks_with_verify_randao::<E, FullPayload<E>>(
slot,
None,
None,
Some(false),
)
.await
.unwrap()
.data;
@@ -1976,13 +1988,13 @@ impl ApiTester {
// Check failure with no `verify_randao` passed.
self.client
.get_validator_blocks::<E>(slot, &bad_randao_reveal, None)
.get_validator_blocks::<E, FullPayload<E>>(slot, &bad_randao_reveal, None)
.await
.unwrap_err();
// Check failure with `verify_randao=true`.
self.client
.get_validator_blocks_with_verify_randao::<E>(
.get_validator_blocks_with_verify_randao::<E, FullPayload<E>>(
slot,
Some(&bad_randao_reveal),
None,
@@ -1993,14 +2005,16 @@ impl ApiTester {
// Check failure with no randao reveal provided.
self.client
.get_validator_blocks_with_verify_randao::<E>(slot, None, None, None)
.get_validator_blocks_with_verify_randao::<E, FullPayload<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>(
.get_validator_blocks_with_verify_randao::<E, FullPayload<E>>(
slot,
Some(&bad_randao_reveal),
None,
@@ -2378,8 +2392,7 @@ impl ApiTester {
.unwrap();
let attesting_validators: Vec<usize> = committees
.into_iter()
.map(|committee| committee.committee.iter().cloned())
.flatten()
.flat_map(|committee| committee.committee.iter().cloned())
.collect();
// All attesters should now be considered live
let expected = expected