mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-20 21:34:46 +00:00
Merge remote-tracking branch 'origin/deneb-free-blobs' into tree-states
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use crate::block_verification_types::{AsBlock, RpcBlock};
|
||||
use crate::observed_operations::ObservationOutcome;
|
||||
pub use crate::persisted_beacon_chain::PersistedBeaconChain;
|
||||
pub use crate::{
|
||||
@@ -14,6 +15,8 @@ use crate::{
|
||||
StateSkipConfig,
|
||||
};
|
||||
use bls::get_withdrawal_credentials;
|
||||
use eth2::types::SignedBlockContentsTuple;
|
||||
use execution_layer::test_utils::generate_genesis_header;
|
||||
use execution_layer::{
|
||||
auth::JwtKey,
|
||||
test_utils::{
|
||||
@@ -25,26 +28,31 @@ use execution_layer::{
|
||||
use futures::channel::mpsc::Receiver;
|
||||
pub use genesis::{interop_genesis_state_with_eth1, DEFAULT_ETH1_BLOCK_HASH};
|
||||
use int_to_bytes::int_to_bytes32;
|
||||
use kzg::{Kzg, TrustedSetup};
|
||||
use merkle_proof::MerkleTree;
|
||||
use operation_pool::ReceivedPreCapella;
|
||||
use parking_lot::Mutex;
|
||||
use parking_lot::RwLockWriteGuard;
|
||||
use parking_lot::{Mutex, RwLock};
|
||||
use rand::rngs::StdRng;
|
||||
use rand::Rng;
|
||||
use rand::SeedableRng;
|
||||
use rayon::prelude::*;
|
||||
use sensitive_url::SensitiveUrl;
|
||||
use slog::Logger;
|
||||
use slog::{o, Drain, Logger};
|
||||
use slog_async::Async;
|
||||
use slog_term::{FullFormat, TermDecorator};
|
||||
use slot_clock::{SlotClock, TestingSlotClock};
|
||||
use state_processing::per_block_processing::compute_timestamp_at_slot;
|
||||
use state_processing::state_advance::complete_state_advance;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use store::{config::StoreConfig, HotColdDB, ItemStore, LevelDB, MemoryStore};
|
||||
use task_executor::TaskExecutor;
|
||||
use task_executor::{test_utils::TestRuntime, ShutdownReason};
|
||||
use tree_hash::TreeHash;
|
||||
use types::sync_selection_proof::SyncSelectionProof;
|
||||
@@ -54,7 +62,7 @@ use types::{typenum::U4294967296, *};
|
||||
// 4th September 2019
|
||||
pub const HARNESS_GENESIS_TIME: u64 = 1_567_552_690;
|
||||
// Environment variable to read if `fork_from_env` feature is enabled.
|
||||
const FORK_NAME_ENV_VAR: &str = "FORK_NAME";
|
||||
pub const FORK_NAME_ENV_VAR: &str = "FORK_NAME";
|
||||
|
||||
// Default target aggregators to set during testing, this ensures an aggregator at each slot.
|
||||
//
|
||||
@@ -186,11 +194,12 @@ impl<E: EthSpec> Builder<EphemeralHarnessType<E>> {
|
||||
.unwrap(),
|
||||
);
|
||||
let mutator = move |builder: BeaconChainBuilder<_>| {
|
||||
let header = generate_genesis_header::<E>(builder.get_spec(), false);
|
||||
let genesis_state = interop_genesis_state_with_eth1::<E>(
|
||||
&validator_keypairs,
|
||||
HARNESS_GENESIS_TIME,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
None,
|
||||
header,
|
||||
builder.get_spec(),
|
||||
)
|
||||
.expect("should generate interop state");
|
||||
@@ -247,11 +256,12 @@ impl<E: EthSpec> Builder<DiskHarnessType<E>> {
|
||||
.expect("cannot build without validator keypairs");
|
||||
|
||||
let mutator = move |builder: BeaconChainBuilder<_>| {
|
||||
let header = generate_genesis_header::<E>(builder.get_spec(), false);
|
||||
let genesis_state = interop_genesis_state_with_eth1::<E>(
|
||||
&validator_keypairs,
|
||||
HARNESS_GENESIS_TIME,
|
||||
Hash256::from_slice(DEFAULT_ETH1_BLOCK_HASH),
|
||||
None,
|
||||
header,
|
||||
builder.get_spec(),
|
||||
)
|
||||
.expect("should generate interop state");
|
||||
@@ -314,6 +324,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn withdrawal_keypairs(mut self, withdrawal_keypairs: Vec<Option<Keypair>>) -> Self {
|
||||
self.withdrawal_keypairs = withdrawal_keypairs;
|
||||
self
|
||||
}
|
||||
|
||||
/// Initializes the BLS withdrawal keypairs for `num_keypairs` validators to
|
||||
/// the "determistic" values, regardless of wether or not the validator has
|
||||
/// a BLS or execution address in the genesis deposits.
|
||||
@@ -329,11 +344,6 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
pub fn withdrawal_keypairs(mut self, withdrawal_keypairs: Vec<Option<Keypair>>) -> Self {
|
||||
self.withdrawal_keypairs = withdrawal_keypairs;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn default_spec(self) -> Self {
|
||||
self.spec_or_default(None)
|
||||
}
|
||||
@@ -382,7 +392,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn execution_layer(mut self, urls: &[&str]) -> Self {
|
||||
pub fn execution_layer_from_urls(mut self, urls: &[&str]) -> Self {
|
||||
assert!(
|
||||
self.execution_layer.is_none(),
|
||||
"execution layer already defined"
|
||||
@@ -411,6 +421,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
pub fn execution_layer(mut self, el: Option<ExecutionLayer<E>>) -> Self {
|
||||
self.execution_layer = el;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn recalculate_fork_times_with_genesis(mut self, genesis_time: u64) -> Self {
|
||||
let mock = self
|
||||
.mock_execution_layer
|
||||
@@ -424,6 +439,9 @@ where
|
||||
spec.capella_fork_epoch.map(|epoch| {
|
||||
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
|
||||
});
|
||||
mock.server.execution_block_generator().cancun_time = spec.deneb_fork_epoch.map(|epoch| {
|
||||
genesis_time + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
@@ -433,17 +451,10 @@ where
|
||||
}
|
||||
|
||||
pub fn mock_execution_layer_with_config(mut self, builder_threshold: Option<u128>) -> Self {
|
||||
let spec = self.spec.clone().expect("cannot build without spec");
|
||||
let shanghai_time = spec.capella_fork_epoch.map(|epoch| {
|
||||
HARNESS_GENESIS_TIME + spec.seconds_per_slot * E::slots_per_epoch() * epoch.as_u64()
|
||||
});
|
||||
let mock = MockExecutionLayer::new(
|
||||
let mock = mock_execution_layer_from_parts::<E>(
|
||||
self.spec.as_ref().expect("cannot build without spec"),
|
||||
self.runtime.task_executor.clone(),
|
||||
DEFAULT_TERMINAL_BLOCK,
|
||||
shanghai_time,
|
||||
builder_threshold,
|
||||
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
|
||||
spec,
|
||||
);
|
||||
self.execution_layer = Some(mock.el.clone());
|
||||
self.mock_execution_layer = Some(mock);
|
||||
@@ -476,6 +487,10 @@ where
|
||||
.validator_keypairs
|
||||
.expect("cannot build without validator keypairs");
|
||||
let chain_config = self.chain_config.unwrap_or_default();
|
||||
let trusted_setup: TrustedSetup =
|
||||
serde_json::from_reader(eth2_network_config::get_trusted_setup::<E::Kzg>())
|
||||
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
|
||||
.unwrap();
|
||||
|
||||
let mut builder = BeaconChainBuilder::new(self.eth_spec_instance)
|
||||
.logger(log.clone())
|
||||
@@ -496,7 +511,8 @@ where
|
||||
log.clone(),
|
||||
5,
|
||||
)))
|
||||
.monitor_validators(true, vec![], DEFAULT_INDIVIDUAL_TRACKING_THRESHOLD, log);
|
||||
.monitor_validators(true, vec![], DEFAULT_INDIVIDUAL_TRACKING_THRESHOLD, log)
|
||||
.trusted_setup(trusted_setup);
|
||||
|
||||
builder = if let Some(mutator) = self.initial_mutator {
|
||||
mutator(builder)
|
||||
@@ -532,11 +548,42 @@ where
|
||||
runtime: self.runtime,
|
||||
mock_execution_layer: self.mock_execution_layer,
|
||||
mock_builder: None,
|
||||
blob_signature_cache: <_>::default(),
|
||||
rng: make_rng(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mock_execution_layer_from_parts<T: EthSpec>(
|
||||
spec: &ChainSpec,
|
||||
task_executor: TaskExecutor,
|
||||
builder_threshold: Option<u128>,
|
||||
) -> MockExecutionLayer<T> {
|
||||
let shanghai_time = spec.capella_fork_epoch.map(|epoch| {
|
||||
HARNESS_GENESIS_TIME + spec.seconds_per_slot * T::slots_per_epoch() * epoch.as_u64()
|
||||
});
|
||||
let cancun_time = spec.deneb_fork_epoch.map(|epoch| {
|
||||
HARNESS_GENESIS_TIME + spec.seconds_per_slot * T::slots_per_epoch() * epoch.as_u64()
|
||||
});
|
||||
|
||||
let trusted_setup: TrustedSetup =
|
||||
serde_json::from_reader(eth2_network_config::get_trusted_setup::<T::Kzg>())
|
||||
.map_err(|e| format!("Unable to read trusted setup file: {}", e))
|
||||
.expect("should have trusted setup");
|
||||
let kzg = Kzg::new_from_trusted_setup(trusted_setup).expect("should create kzg");
|
||||
|
||||
MockExecutionLayer::new(
|
||||
task_executor,
|
||||
DEFAULT_TERMINAL_BLOCK,
|
||||
shanghai_time,
|
||||
cancun_time,
|
||||
builder_threshold,
|
||||
Some(JwtKey::from_slice(&DEFAULT_JWT_SECRET).unwrap()),
|
||||
spec.clone(),
|
||||
Some(kzg),
|
||||
)
|
||||
}
|
||||
|
||||
/// A testing harness which can instantiate a `BeaconChain` and populate it with blocks and
|
||||
/// attestations.
|
||||
///
|
||||
@@ -558,9 +605,29 @@ pub struct BeaconChainHarness<T: BeaconChainTypes> {
|
||||
pub mock_execution_layer: Option<MockExecutionLayer<T::EthSpec>>,
|
||||
pub mock_builder: Option<Arc<MockBuilder<T::EthSpec>>>,
|
||||
|
||||
/// Cache for blob signature because we don't need them for import, but we do need them
|
||||
/// to test gossip validation. We always make them during block production but drop them
|
||||
/// before storing them in the db.
|
||||
pub blob_signature_cache: Arc<RwLock<HashMap<BlobSignatureKey, Signature>>>,
|
||||
|
||||
pub rng: Mutex<StdRng>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct BlobSignatureKey {
|
||||
block_root: Hash256,
|
||||
blob_index: u64,
|
||||
}
|
||||
|
||||
impl BlobSignatureKey {
|
||||
pub fn new(block_root: Hash256, blob_index: u64) -> Self {
|
||||
Self {
|
||||
block_root,
|
||||
blob_index,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type CommitteeAttestations<E> = Vec<(Attestation<E>, SubnetId)>;
|
||||
pub type HarnessAttestations<E> =
|
||||
Vec<(CommitteeAttestations<E>, Option<SignedAggregateAndProof<E>>)>;
|
||||
@@ -635,6 +702,20 @@ where
|
||||
mock_builder_server
|
||||
}
|
||||
|
||||
pub fn get_head_block(&self) -> RpcBlock<E> {
|
||||
let block = self.chain.head_beacon_block();
|
||||
let block_root = block.canonical_root();
|
||||
let blobs = self.chain.get_blobs(&block_root).unwrap();
|
||||
RpcBlock::new(block, Some(blobs)).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_full_block(&self, block_root: &Hash256) -> RpcBlock<E> {
|
||||
let block = self.chain.get_blinded_block(block_root).unwrap().unwrap();
|
||||
let full_block = self.chain.store.make_full_block(block_root, block).unwrap();
|
||||
let blobs = self.chain.get_blobs(block_root).unwrap();
|
||||
RpcBlock::new(Arc::new(full_block), Some(blobs)).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_all_validators(&self) -> Vec<usize> {
|
||||
(0..self.validator_keypairs.len()).collect()
|
||||
}
|
||||
@@ -742,9 +823,28 @@ where
|
||||
&self,
|
||||
state: BeaconState<E>,
|
||||
slot: Slot,
|
||||
) -> (SignedBlindedBeaconBlock<E>, BeaconState<E>) {
|
||||
) -> (
|
||||
SignedBlockContentsTuple<E, BlindedPayload<E>>,
|
||||
BeaconState<E>,
|
||||
) {
|
||||
let (unblinded, new_state) = self.make_block(state, slot).await;
|
||||
(unblinded.into(), new_state)
|
||||
let maybe_blinded_blob_sidecars = unblinded.1.map(|blob_sidecar_list| {
|
||||
VariableList::new(
|
||||
blob_sidecar_list
|
||||
.into_iter()
|
||||
.map(|blob_sidecar| {
|
||||
let blinded_sidecar: BlindedBlobSidecar = blob_sidecar.message.into();
|
||||
SignedSidecar {
|
||||
message: Arc::new(blinded_sidecar),
|
||||
signature: blob_sidecar.signature,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
((unblinded.0.into(), maybe_blinded_blob_sidecars), new_state)
|
||||
}
|
||||
|
||||
/// Returns a newly created block, signed by the proposer for the given slot.
|
||||
@@ -752,7 +852,7 @@ where
|
||||
&self,
|
||||
mut state: BeaconState<E>,
|
||||
slot: Slot,
|
||||
) -> (SignedBeaconBlock<E>, BeaconState<E>) {
|
||||
) -> (SignedBlockContentsTuple<E, FullPayload<E>>, BeaconState<E>) {
|
||||
assert_ne!(slot, 0, "can't produce a block at slot 0");
|
||||
assert!(slot >= state.slot());
|
||||
|
||||
@@ -770,7 +870,7 @@ where
|
||||
|
||||
let randao_reveal = self.sign_randao_reveal(&state, proposer_index, slot);
|
||||
|
||||
let (block, state) = self
|
||||
let (block, state, maybe_blob_sidecars) = self
|
||||
.chain
|
||||
.produce_block_on_state(
|
||||
state,
|
||||
@@ -790,7 +890,18 @@ where
|
||||
&self.spec,
|
||||
);
|
||||
|
||||
(signed_block, state)
|
||||
let block_contents: SignedBlockContentsTuple<E, FullPayload<E>> = match &signed_block {
|
||||
SignedBeaconBlock::Base(_)
|
||||
| SignedBeaconBlock::Altair(_)
|
||||
| SignedBeaconBlock::Merge(_)
|
||||
| SignedBeaconBlock::Capella(_) => (signed_block, None),
|
||||
SignedBeaconBlock::Deneb(_) => (
|
||||
signed_block,
|
||||
maybe_blob_sidecars.map(|blobs| self.sign_blobs(blobs, &state, proposer_index)),
|
||||
),
|
||||
};
|
||||
|
||||
(block_contents, state)
|
||||
}
|
||||
|
||||
/// Useful for the `per_block_processing` tests. Creates a block, and returns the state after
|
||||
@@ -799,7 +910,7 @@ where
|
||||
&self,
|
||||
mut state: BeaconState<E>,
|
||||
slot: Slot,
|
||||
) -> (SignedBeaconBlock<E>, BeaconState<E>) {
|
||||
) -> (SignedBlockContentsTuple<E, FullPayload<E>>, BeaconState<E>) {
|
||||
assert_ne!(slot, 0, "can't produce a block at slot 0");
|
||||
assert!(slot >= state.slot());
|
||||
|
||||
@@ -819,7 +930,7 @@ where
|
||||
|
||||
let pre_state = state.clone();
|
||||
|
||||
let (block, state) = self
|
||||
let (block, state, maybe_blob_sidecars) = self
|
||||
.chain
|
||||
.produce_block_on_state(
|
||||
state,
|
||||
@@ -839,7 +950,40 @@ where
|
||||
&self.spec,
|
||||
);
|
||||
|
||||
(signed_block, pre_state)
|
||||
let block_contents: SignedBlockContentsTuple<E, FullPayload<E>> = match &signed_block {
|
||||
SignedBeaconBlock::Base(_)
|
||||
| SignedBeaconBlock::Altair(_)
|
||||
| SignedBeaconBlock::Merge(_)
|
||||
| SignedBeaconBlock::Capella(_) => (signed_block, None),
|
||||
SignedBeaconBlock::Deneb(_) => {
|
||||
if let Some(blobs) = maybe_blob_sidecars {
|
||||
let signed_blobs: SignedSidecarList<E, BlobSidecar<E>> = Vec::from(blobs)
|
||||
.into_iter()
|
||||
.map(|blob| {
|
||||
blob.sign(
|
||||
&self.validator_keypairs[proposer_index].sk,
|
||||
&state.fork(),
|
||||
state.genesis_validators_root(),
|
||||
&self.spec,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let mut guard = self.blob_signature_cache.write();
|
||||
for blob in &signed_blobs {
|
||||
guard.insert(
|
||||
BlobSignatureKey::new(blob.message.block_root, blob.message.index),
|
||||
blob.signature.clone(),
|
||||
);
|
||||
}
|
||||
(signed_block, Some(signed_blobs))
|
||||
} else {
|
||||
(signed_block, None)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(block_contents, pre_state)
|
||||
}
|
||||
|
||||
/// Create a randao reveal for a block at `slot`.
|
||||
@@ -876,6 +1020,35 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
/// Sign blobs, and cache their signatures.
|
||||
pub fn sign_blobs(
|
||||
&self,
|
||||
blobs: BlobSidecarList<E>,
|
||||
state: &BeaconState<E>,
|
||||
proposer_index: usize,
|
||||
) -> SignedSidecarList<E, BlobSidecar<E>> {
|
||||
let signed_blobs: SignedSidecarList<E, BlobSidecar<E>> = Vec::from(blobs)
|
||||
.into_iter()
|
||||
.map(|blob| {
|
||||
blob.sign(
|
||||
&self.validator_keypairs[proposer_index].sk,
|
||||
&state.fork(),
|
||||
state.genesis_validators_root(),
|
||||
&self.spec,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.into();
|
||||
let mut guard = self.blob_signature_cache.write();
|
||||
for blob in &signed_blobs {
|
||||
guard.insert(
|
||||
BlobSignatureKey::new(blob.message.block_root, blob.message.index),
|
||||
blob.signature.clone(),
|
||||
);
|
||||
}
|
||||
signed_blobs
|
||||
}
|
||||
|
||||
/// Produces an "unaggregated" attestation for the given `slot` and `index` that attests to
|
||||
/// `beacon_block_root`. The provided `state` should match the `block.state_root` for the
|
||||
/// `block` identified by `beacon_block_root`.
|
||||
@@ -1512,14 +1685,13 @@ where
|
||||
|
||||
pub fn make_voluntary_exit(&self, validator_index: u64, epoch: Epoch) -> SignedVoluntaryExit {
|
||||
let sk = &self.validator_keypairs[validator_index as usize].sk;
|
||||
let fork = self.chain.canonical_head.cached_head().head_fork();
|
||||
let genesis_validators_root = self.chain.genesis_validators_root;
|
||||
|
||||
VoluntaryExit {
|
||||
epoch,
|
||||
validator_index,
|
||||
}
|
||||
.sign(sk, &fork, genesis_validators_root, &self.chain.spec)
|
||||
.sign(sk, genesis_validators_root, &self.chain.spec)
|
||||
}
|
||||
|
||||
pub fn add_proposer_slashing(&self, validator_index: u64) -> Result<(), String> {
|
||||
@@ -1628,11 +1800,12 @@ where
|
||||
state: BeaconState<E>,
|
||||
slot: Slot,
|
||||
block_modifier: impl FnOnce(&mut BeaconBlock<E>),
|
||||
) -> (SignedBeaconBlock<E>, BeaconState<E>) {
|
||||
) -> (SignedBlockContentsTuple<E, FullPayload<E>>, BeaconState<E>) {
|
||||
assert_ne!(slot, 0, "can't produce a block at slot 0");
|
||||
assert!(slot >= state.slot());
|
||||
|
||||
let (block, state) = self.make_block_return_pre_state(state, slot).await;
|
||||
let ((block, blobs), state) = self.make_block_return_pre_state(state, slot).await;
|
||||
|
||||
let (mut block, _) = block.deconstruct();
|
||||
|
||||
block_modifier(&mut block);
|
||||
@@ -1645,7 +1818,7 @@ where
|
||||
state.genesis_validators_root(),
|
||||
&self.spec,
|
||||
);
|
||||
(signed_block, state)
|
||||
((signed_block, blobs), state)
|
||||
}
|
||||
|
||||
pub fn make_deposits<'a>(
|
||||
@@ -1725,37 +1898,59 @@ where
|
||||
&self,
|
||||
slot: Slot,
|
||||
block_root: Hash256,
|
||||
block: SignedBeaconBlock<E>,
|
||||
block_contents: SignedBlockContentsTuple<E, FullPayload<E>>,
|
||||
) -> Result<SignedBeaconBlockHash, BlockError<E>> {
|
||||
self.set_current_slot(slot);
|
||||
let (block, blobs) = block_contents;
|
||||
// Note: we are just dropping signatures here and skipping signature verification.
|
||||
let blobs_without_signatures = blobs.map(|blobs| {
|
||||
VariableList::from(
|
||||
blobs
|
||||
.into_iter()
|
||||
.map(|blob| blob.message)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
let block_hash: SignedBeaconBlockHash = self
|
||||
.chain
|
||||
.process_block(
|
||||
block_root,
|
||||
Arc::new(block),
|
||||
RpcBlock::new(Arc::new(block), blobs_without_signatures).unwrap(),
|
||||
NotifyExecutionLayer::Yes,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.into();
|
||||
.try_into()
|
||||
.unwrap();
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
Ok(block_hash)
|
||||
}
|
||||
|
||||
pub async fn process_block_result(
|
||||
&self,
|
||||
block: SignedBeaconBlock<E>,
|
||||
block_contents: SignedBlockContentsTuple<E, FullPayload<E>>,
|
||||
) -> Result<SignedBeaconBlockHash, BlockError<E>> {
|
||||
let (block, blobs) = block_contents;
|
||||
// Note: we are just dropping signatures here and skipping signature verification.
|
||||
let blobs_without_signatures = blobs.map(|blobs| {
|
||||
VariableList::from(
|
||||
blobs
|
||||
.into_iter()
|
||||
.map(|blob| blob.message)
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
});
|
||||
let block_hash: SignedBeaconBlockHash = self
|
||||
.chain
|
||||
.process_block(
|
||||
block.canonical_root(),
|
||||
Arc::new(block),
|
||||
RpcBlock::new(Arc::new(block), blobs_without_signatures).unwrap(),
|
||||
NotifyExecutionLayer::Yes,
|
||||
|| Ok(()),
|
||||
)
|
||||
.await?
|
||||
.into();
|
||||
.try_into()
|
||||
.expect("block blobs are available");
|
||||
self.chain.recompute_head_at_current_slot().await;
|
||||
Ok(block_hash)
|
||||
}
|
||||
@@ -1815,13 +2010,25 @@ where
|
||||
&self,
|
||||
slot: Slot,
|
||||
state: BeaconState<E>,
|
||||
) -> Result<(SignedBeaconBlockHash, SignedBeaconBlock<E>, BeaconState<E>), BlockError<E>> {
|
||||
) -> Result<
|
||||
(
|
||||
SignedBeaconBlockHash,
|
||||
SignedBlockContentsTuple<E, FullPayload<E>>,
|
||||
BeaconState<E>,
|
||||
),
|
||||
BlockError<E>,
|
||||
> {
|
||||
self.set_current_slot(slot);
|
||||
let (block, new_state) = self.make_block(state, slot).await;
|
||||
let (block_contents, new_state) = self.make_block(state, slot).await;
|
||||
|
||||
let block_hash = self
|
||||
.process_block(slot, block.canonical_root(), block.clone())
|
||||
.process_block(
|
||||
slot,
|
||||
block_contents.0.canonical_root(),
|
||||
block_contents.clone(),
|
||||
)
|
||||
.await?;
|
||||
Ok((block_hash, block, new_state))
|
||||
Ok((block_hash, block_contents, new_state))
|
||||
}
|
||||
|
||||
pub fn attest_block(
|
||||
@@ -1875,7 +2082,7 @@ where
|
||||
sync_committee_strategy: SyncCommitteeStrategy,
|
||||
) -> Result<(SignedBeaconBlockHash, BeaconState<E>), BlockError<E>> {
|
||||
let (block_hash, block, state) = self.add_block_at_slot(slot, state).await?;
|
||||
self.attest_block(&state, state_root, block_hash, &block, validators);
|
||||
self.attest_block(&state, state_root, block_hash, &block.0, validators);
|
||||
|
||||
if sync_committee_strategy == SyncCommitteeStrategy::AllValidators
|
||||
&& state.current_sync_committee().is_ok()
|
||||
@@ -2073,8 +2280,9 @@ where
|
||||
chain_dump
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|checkpoint| checkpoint.beacon_state.finalized_checkpoint().root.into())
|
||||
.filter(|block_hash| *block_hash != Hash256::zero().into())
|
||||
.map(|checkpoint| checkpoint.beacon_state.finalized_checkpoint().root)
|
||||
.filter(|block_hash| *block_hash != Hash256::zero())
|
||||
.map(|hash| hash.into())
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -2286,3 +2494,15 @@ pub struct MakeAttestationOptions {
|
||||
/// Fork to use for signing attestations.
|
||||
pub fork: Fork,
|
||||
}
|
||||
|
||||
pub fn build_log(level: slog::Level, enabled: bool) -> Logger {
|
||||
let decorator = TermDecorator::new().build();
|
||||
let drain = FullFormat::new(decorator).build().fuse();
|
||||
let drain = Async::new(drain).build().fuse();
|
||||
|
||||
if enabled {
|
||||
Logger::root(drain.filter_level(level).fuse(), o!())
|
||||
} else {
|
||||
Logger::root(drain.filter(|_| false).fuse(), o!())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user