mirror of
https://github.com/sigp/lighthouse.git
synced 2026-06-29 10:54:24 +00:00
Merge remote-tracking branch 'origin/unstable' into tree-states
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use crate::ForkChoiceStore;
|
||||
use crate::{ForkChoiceStore, InvalidationOperation};
|
||||
use proto_array::{Block as ProtoBlock, ExecutionStatus, ProtoArrayForkChoice};
|
||||
use ssz_derive::{Decode, Encode};
|
||||
use std::cmp::Ordering;
|
||||
@@ -241,6 +241,14 @@ pub enum AttestationFromBlock {
|
||||
False,
|
||||
}
|
||||
|
||||
/// Parameters which are cached between calls to `Self::get_head`.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ForkchoiceUpdateParameters {
|
||||
pub head_root: Hash256,
|
||||
pub head_hash: Option<ExecutionBlockHash>,
|
||||
pub finalized_hash: Option<ExecutionBlockHash>,
|
||||
}
|
||||
|
||||
/// Provides an implementation of "Ethereum 2.0 Phase 0 -- Beacon Chain Fork Choice":
|
||||
///
|
||||
/// https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/fork-choice.md#ethereum-20-phase-0----beacon-chain-fork-choice
|
||||
@@ -258,6 +266,8 @@ pub struct ForkChoice<T, E> {
|
||||
proto_array: ProtoArrayForkChoice,
|
||||
/// Attestations that arrived at the current slot and must be queued for later processing.
|
||||
queued_attestations: Vec<QueuedAttestation>,
|
||||
/// Stores a cache of the values required to be sent to the execution layer.
|
||||
forkchoice_update_parameters: Option<ForkchoiceUpdateParameters>,
|
||||
_phantom: PhantomData<E>,
|
||||
}
|
||||
|
||||
@@ -332,6 +342,7 @@ where
|
||||
fc_store,
|
||||
proto_array,
|
||||
queued_attestations: vec![],
|
||||
forkchoice_update_parameters: None,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
@@ -349,10 +360,20 @@ where
|
||||
fc_store,
|
||||
proto_array,
|
||||
queued_attestations,
|
||||
forkchoice_update_parameters: None,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns cached information that can be used to issue a `forkchoiceUpdated` message to an
|
||||
/// execution engine.
|
||||
///
|
||||
/// These values are updated each time `Self::get_head` is called. May return `None` if
|
||||
/// `Self::get_head` has not yet been called.
|
||||
pub fn get_forkchoice_update_parameters(&self) -> Option<ForkchoiceUpdateParameters> {
|
||||
self.forkchoice_update_parameters
|
||||
}
|
||||
|
||||
/// Returns the block root of an ancestor of `block_root` at the given `slot`. (Note: `slot` refers
|
||||
/// to the block that is *returned*, not the one that is supplied.)
|
||||
///
|
||||
@@ -414,18 +435,29 @@ where
|
||||
|
||||
let store = &mut self.fc_store;
|
||||
|
||||
// FIXME(sproul): plumb VList through fork choice
|
||||
let justified_balances = store.justified_balances().to_vec();
|
||||
let head_root = self.proto_array.find_head::<E>(
|
||||
*store.justified_checkpoint(),
|
||||
*store.finalized_checkpoint(),
|
||||
store.justified_balances(),
|
||||
store.proposer_boost_root(),
|
||||
spec,
|
||||
)?;
|
||||
|
||||
self.proto_array
|
||||
.find_head::<E>(
|
||||
*store.justified_checkpoint(),
|
||||
*store.finalized_checkpoint(),
|
||||
&justified_balances,
|
||||
store.proposer_boost_root(),
|
||||
spec,
|
||||
)
|
||||
.map_err(Into::into)
|
||||
// Cache some values for the next forkchoiceUpdate call to the execution layer.
|
||||
let head_hash = self
|
||||
.get_block(&head_root)
|
||||
.and_then(|b| b.execution_status.block_hash());
|
||||
let finalized_root = self.finalized_checkpoint().root;
|
||||
let finalized_hash = self
|
||||
.get_block(&finalized_root)
|
||||
.and_then(|b| b.execution_status.block_hash());
|
||||
self.forkchoice_update_parameters = Some(ForkchoiceUpdateParameters {
|
||||
head_root,
|
||||
head_hash,
|
||||
finalized_hash,
|
||||
});
|
||||
|
||||
Ok(head_root)
|
||||
}
|
||||
|
||||
/// Returns `true` if the given `store` should be updated to set
|
||||
@@ -483,11 +515,10 @@ where
|
||||
/// See `ProtoArrayForkChoice::process_execution_payload_invalidation` for documentation.
|
||||
pub fn on_invalid_execution_payload(
|
||||
&mut self,
|
||||
head_block_root: Hash256,
|
||||
latest_valid_ancestor_root: Option<ExecutionBlockHash>,
|
||||
op: &InvalidationOperation,
|
||||
) -> Result<(), Error<T::Error>> {
|
||||
self.proto_array
|
||||
.process_execution_payload_invalidation(head_block_root, latest_valid_ancestor_root)
|
||||
.process_execution_payload_invalidation(op)
|
||||
.map_err(Error::FailedToProcessInvalidExecutionPayload)
|
||||
}
|
||||
|
||||
@@ -931,6 +962,54 @@ where
|
||||
.is_descendant(self.fc_store.finalized_checkpoint().root, block_root)
|
||||
}
|
||||
|
||||
/// Returns `Ok(false)` if a block is not viable to be imported optimistically.
|
||||
///
|
||||
/// ## Notes
|
||||
///
|
||||
/// Equivalent to the function with the same name in the optimistic sync specs:
|
||||
///
|
||||
/// https://github.com/ethereum/consensus-specs/blob/dev/sync/optimistic.md#helpers
|
||||
pub fn is_optimistic_candidate_block(
|
||||
&self,
|
||||
current_slot: Slot,
|
||||
block_slot: Slot,
|
||||
block_parent_root: &Hash256,
|
||||
spec: &ChainSpec,
|
||||
) -> Result<bool, Error<T::Error>> {
|
||||
// If the block is sufficiently old, import it.
|
||||
if block_slot + spec.safe_slots_to_import_optimistically <= current_slot {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// If the justified block has execution enabled, then optimistically import any block.
|
||||
if self
|
||||
.get_justified_block()?
|
||||
.execution_status
|
||||
.is_execution_enabled()
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
// If the parent block has execution enabled, always import the block.
|
||||
//
|
||||
// TODO(bellatrix): this condition has not yet been merged into the spec.
|
||||
//
|
||||
// See:
|
||||
//
|
||||
// https://github.com/ethereum/consensus-specs/pull/2844
|
||||
if self
|
||||
.proto_array
|
||||
.get_block(block_parent_root)
|
||||
.map_or(false, |parent| {
|
||||
parent.execution_status.is_execution_enabled()
|
||||
})
|
||||
{
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
/// Return the current finalized checkpoint.
|
||||
pub fn finalized_checkpoint(&self) -> Checkpoint {
|
||||
*self.fc_store.finalized_checkpoint()
|
||||
@@ -1005,6 +1084,7 @@ where
|
||||
fc_store,
|
||||
proto_array,
|
||||
queued_attestations: persisted.queued_attestations,
|
||||
forkchoice_update_parameters: None,
|
||||
_phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,4 +6,4 @@ pub use crate::fork_choice::{
|
||||
PayloadVerificationStatus, PersistedForkChoice, QueuedAttestation,
|
||||
};
|
||||
pub use fork_choice_store::ForkChoiceStore;
|
||||
pub use proto_array::Block as ProtoBlock;
|
||||
pub use proto_array::{Block as ProtoBlock, InvalidationOperation};
|
||||
|
||||
@@ -4,6 +4,7 @@ mod no_votes;
|
||||
mod votes;
|
||||
|
||||
use crate::proto_array_fork_choice::{Block, ExecutionStatus, ProtoArrayForkChoice};
|
||||
use crate::InvalidationOperation;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use types::{
|
||||
AttestationShufflingId, Checkpoint, Epoch, EthSpec, ExecutionBlockHash, Hash256,
|
||||
@@ -238,12 +239,22 @@ impl ForkChoiceTestDefinition {
|
||||
Operation::InvalidatePayload {
|
||||
head_block_root,
|
||||
latest_valid_ancestor_root,
|
||||
} => fork_choice
|
||||
.process_execution_payload_invalidation(
|
||||
head_block_root,
|
||||
latest_valid_ancestor_root,
|
||||
)
|
||||
.unwrap(),
|
||||
} => {
|
||||
let op = if let Some(latest_valid_ancestor) = latest_valid_ancestor_root {
|
||||
InvalidationOperation::InvalidateMany {
|
||||
head_block_root,
|
||||
always_invalidate_head: true,
|
||||
latest_valid_ancestor,
|
||||
}
|
||||
} else {
|
||||
InvalidationOperation::InvalidateOne {
|
||||
block_root: head_block_root,
|
||||
}
|
||||
};
|
||||
fork_choice
|
||||
.process_execution_payload_invalidation(&op)
|
||||
.unwrap()
|
||||
}
|
||||
Operation::AssertWeight { block_root, weight } => assert_eq!(
|
||||
fork_choice.get_weight(&block_root).unwrap(),
|
||||
weight,
|
||||
|
||||
@@ -4,6 +4,7 @@ mod proto_array;
|
||||
mod proto_array_fork_choice;
|
||||
mod ssz_container;
|
||||
|
||||
pub use crate::proto_array::InvalidationOperation;
|
||||
pub use crate::proto_array_fork_choice::{Block, ExecutionStatus, ProtoArrayForkChoice};
|
||||
pub use error::Error;
|
||||
|
||||
|
||||
@@ -15,6 +15,56 @@ use types::{
|
||||
four_byte_option_impl!(four_byte_option_usize, usize);
|
||||
four_byte_option_impl!(four_byte_option_checkpoint, Checkpoint);
|
||||
|
||||
/// Defines an operation which may invalidate the `execution_status` of some nodes.
|
||||
pub enum InvalidationOperation {
|
||||
/// Invalidate only `block_root` and it's descendants. Don't invalidate any ancestors.
|
||||
InvalidateOne { block_root: Hash256 },
|
||||
/// Invalidate blocks between `head_block_root` and `latest_valid_ancestor`.
|
||||
///
|
||||
/// If the `latest_valid_ancestor` is known to fork choice, invalidate all blocks between
|
||||
/// `head_block_root` and `latest_valid_ancestor`. The `head_block_root` will be invalidated,
|
||||
/// whilst the `latest_valid_ancestor` will not.
|
||||
///
|
||||
/// If `latest_valid_ancestor` is *not* known to fork choice, only invalidate the
|
||||
/// `head_block_root` if `always_invalidate_head == true`.
|
||||
InvalidateMany {
|
||||
head_block_root: Hash256,
|
||||
always_invalidate_head: bool,
|
||||
latest_valid_ancestor: ExecutionBlockHash,
|
||||
},
|
||||
}
|
||||
|
||||
impl InvalidationOperation {
|
||||
pub fn block_root(&self) -> Hash256 {
|
||||
match self {
|
||||
InvalidationOperation::InvalidateOne { block_root } => *block_root,
|
||||
InvalidationOperation::InvalidateMany {
|
||||
head_block_root, ..
|
||||
} => *head_block_root,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn latest_valid_ancestor(&self) -> Option<ExecutionBlockHash> {
|
||||
match self {
|
||||
InvalidationOperation::InvalidateOne { .. } => None,
|
||||
InvalidationOperation::InvalidateMany {
|
||||
latest_valid_ancestor,
|
||||
..
|
||||
} => Some(*latest_valid_ancestor),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invalidate_block_root(&self) -> bool {
|
||||
match self {
|
||||
InvalidationOperation::InvalidateOne { .. } => true,
|
||||
InvalidationOperation::InvalidateMany {
|
||||
always_invalidate_head,
|
||||
..
|
||||
} => *always_invalidate_head,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Encode, Decode, Serialize, Deserialize)]
|
||||
pub struct ProtoNode {
|
||||
/// The `slot` is not necessary for `ProtoArray`, it just exists so external components can
|
||||
@@ -328,43 +378,15 @@ impl ProtoArray {
|
||||
}
|
||||
}
|
||||
|
||||
/// Invalidate the relevant ancestors and descendants of a block with an invalid execution
|
||||
/// payload.
|
||||
/// Invalidate zero or more blocks, as specified by the `InvalidationOperation`.
|
||||
///
|
||||
/// The `head_block_root` should be the beacon block root of the block with the invalid
|
||||
/// execution payload, _or_ its parent where the block with the invalid payload has not yet
|
||||
/// been applied to `self`.
|
||||
///
|
||||
/// The `latest_valid_hash` should be the hash of most recent *valid* execution payload
|
||||
/// contained in an ancestor block of `head_block_root`.
|
||||
///
|
||||
/// This function will invalidate:
|
||||
///
|
||||
/// * The block matching `head_block_root` _unless_ that block has a payload matching `latest_valid_hash`.
|
||||
/// * All ancestors of `head_block_root` back to the block with payload matching
|
||||
/// `latest_valid_hash` (endpoint > exclusive). In the case where the `head_block_root` is the parent
|
||||
/// of the invalid block and itself matches `latest_valid_hash`, no ancestors will be invalidated.
|
||||
/// * All descendants of `latest_valid_hash` if supplied and consistent with `head_block_root`,
|
||||
/// or else all descendants of `head_block_root`.
|
||||
///
|
||||
/// ## Details
|
||||
///
|
||||
/// If `head_block_root` is not known to fork choice, an error is returned.
|
||||
///
|
||||
/// If `latest_valid_hash` is `Some(hash)` where `hash` is either not known to fork choice
|
||||
/// (perhaps it's junk or pre-finalization), then only the `head_block_root` block will be
|
||||
/// invalidated (no ancestors). No error will be returned in this case.
|
||||
///
|
||||
/// If `latest_valid_hash` is `Some(hash)` where `hash` is a known ancestor of
|
||||
/// `head_block_root`, then all blocks between `head_block_root` and `latest_valid_hash` will
|
||||
/// be invalidated. Additionally, all blocks that descend from a newly-invalidated block will
|
||||
/// also be invalidated.
|
||||
/// See the documentation of `InvalidationOperation` for usage.
|
||||
pub fn propagate_execution_payload_invalidation(
|
||||
&mut self,
|
||||
head_block_root: Hash256,
|
||||
latest_valid_ancestor_hash: Option<ExecutionBlockHash>,
|
||||
op: &InvalidationOperation,
|
||||
) -> Result<(), Error> {
|
||||
let mut invalidated_indices: HashSet<usize> = <_>::default();
|
||||
let head_block_root = op.block_root();
|
||||
|
||||
/*
|
||||
* Step 1:
|
||||
@@ -379,7 +401,8 @@ impl ProtoArray {
|
||||
.ok_or(Error::NodeUnknown(head_block_root))?;
|
||||
|
||||
// Try to map the ancestor payload *hash* to an ancestor beacon block *root*.
|
||||
let latest_valid_ancestor_root = latest_valid_ancestor_hash
|
||||
let latest_valid_ancestor_root = op
|
||||
.latest_valid_ancestor()
|
||||
.and_then(|hash| self.execution_block_hash_to_beacon_block_root(&hash));
|
||||
|
||||
// Set to `true` if both conditions are satisfied:
|
||||
@@ -414,7 +437,7 @@ impl ProtoArray {
|
||||
// an invalid justified checkpoint.
|
||||
if !latest_valid_ancestor_is_descendant && node.root != head_block_root {
|
||||
break;
|
||||
} else if Some(hash) == latest_valid_ancestor_hash {
|
||||
} else if op.latest_valid_ancestor() == Some(hash) {
|
||||
// If the `best_child` or `best_descendant` of the latest valid hash was
|
||||
// invalidated, set those fields to `None`.
|
||||
//
|
||||
@@ -444,36 +467,44 @@ impl ProtoArray {
|
||||
ExecutionStatus::Irrelevant(_) => break,
|
||||
}
|
||||
|
||||
match &node.execution_status {
|
||||
// It's illegal for an execution client to declare that some previously-valid block
|
||||
// is now invalid. This is a consensus failure on their behalf.
|
||||
ExecutionStatus::Valid(hash) => {
|
||||
return Err(Error::ValidExecutionStatusBecameInvalid {
|
||||
block_root: node.root,
|
||||
payload_block_hash: *hash,
|
||||
})
|
||||
}
|
||||
ExecutionStatus::Unknown(hash) => {
|
||||
node.execution_status = ExecutionStatus::Invalid(*hash);
|
||||
// Only invalidate the head block if either:
|
||||
//
|
||||
// - The head block was specifically indicated to be invalidated.
|
||||
// - The latest valid hash is a known ancestor.
|
||||
if node.root != head_block_root
|
||||
|| op.invalidate_block_root()
|
||||
|| latest_valid_ancestor_is_descendant
|
||||
{
|
||||
match &node.execution_status {
|
||||
// It's illegal for an execution client to declare that some previously-valid block
|
||||
// is now invalid. This is a consensus failure on their behalf.
|
||||
ExecutionStatus::Valid(hash) => {
|
||||
return Err(Error::ValidExecutionStatusBecameInvalid {
|
||||
block_root: node.root,
|
||||
payload_block_hash: *hash,
|
||||
})
|
||||
}
|
||||
ExecutionStatus::Unknown(hash) => {
|
||||
invalidated_indices.insert(index);
|
||||
node.execution_status = ExecutionStatus::Invalid(*hash);
|
||||
|
||||
// It's impossible for an invalid block to lead to a "best" block, so set these
|
||||
// fields to `None`.
|
||||
//
|
||||
// Failing to set these values will result in `Self::node_leads_to_viable_head`
|
||||
// returning `false` for *valid* ancestors of invalid blocks.
|
||||
node.best_child = None;
|
||||
node.best_descendant = None;
|
||||
// It's impossible for an invalid block to lead to a "best" block, so set these
|
||||
// fields to `None`.
|
||||
//
|
||||
// Failing to set these values will result in `Self::node_leads_to_viable_head`
|
||||
// returning `false` for *valid* ancestors of invalid blocks.
|
||||
node.best_child = None;
|
||||
node.best_descendant = None;
|
||||
}
|
||||
// The block is already invalid, but keep going backwards to ensure all ancestors
|
||||
// are updated.
|
||||
ExecutionStatus::Invalid(_) => (),
|
||||
// This block is pre-merge, therefore it has no execution status. Nor do its
|
||||
// ancestors.
|
||||
ExecutionStatus::Irrelevant(_) => break,
|
||||
}
|
||||
// The block is already invalid, but keep going backwards to ensure all ancestors
|
||||
// are updated.
|
||||
ExecutionStatus::Invalid(_) => (),
|
||||
// This block is pre-merge, therefore it has no execution status. Nor do its
|
||||
// ancestors.
|
||||
ExecutionStatus::Irrelevant(_) => break,
|
||||
}
|
||||
|
||||
invalidated_indices.insert(index);
|
||||
|
||||
if let Some(parent_index) = node.parent {
|
||||
index = parent_index
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::error::Error;
|
||||
use crate::proto_array::{ProposerBoost, ProtoArray};
|
||||
use crate::proto_array::{InvalidationOperation, Iter, ProposerBoost, ProtoArray};
|
||||
use crate::ssz_container::SszContainer;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use ssz::{Decode, Encode};
|
||||
@@ -40,6 +40,10 @@ pub enum ExecutionStatus {
|
||||
}
|
||||
|
||||
impl ExecutionStatus {
|
||||
pub fn is_execution_enabled(&self) -> bool {
|
||||
!matches!(self, ExecutionStatus::Irrelevant(_))
|
||||
}
|
||||
|
||||
pub fn irrelevant() -> Self {
|
||||
ExecutionStatus::Irrelevant(false)
|
||||
}
|
||||
@@ -187,11 +191,10 @@ impl ProtoArrayForkChoice {
|
||||
/// See `ProtoArray::propagate_execution_payload_invalidation` for documentation.
|
||||
pub fn process_execution_payload_invalidation(
|
||||
&mut self,
|
||||
head_block_root: Hash256,
|
||||
latest_valid_ancestor_root: Option<ExecutionBlockHash>,
|
||||
op: &InvalidationOperation,
|
||||
) -> Result<(), String> {
|
||||
self.proto_array
|
||||
.propagate_execution_payload_invalidation(head_block_root, latest_valid_ancestor_root)
|
||||
.propagate_execution_payload_invalidation(op)
|
||||
.map_err(|e| format!("Failed to process invalid payload: {:?}", e))
|
||||
}
|
||||
|
||||
@@ -341,6 +344,11 @@ impl ProtoArrayForkChoice {
|
||||
}
|
||||
}
|
||||
|
||||
/// See `ProtoArray::iter_nodes`
|
||||
pub fn iter_nodes<'a>(&'a self, block_root: &Hash256) -> Iter<'a> {
|
||||
self.proto_array.iter_nodes(block_root)
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> Vec<u8> {
|
||||
SszContainer::from(self).as_ssz_bytes()
|
||||
}
|
||||
|
||||
@@ -333,10 +333,10 @@ pub fn partially_verify_execution_payload<T: EthSpec>(
|
||||
);
|
||||
}
|
||||
block_verify!(
|
||||
payload.random == *state.get_randao_mix(state.current_epoch())?,
|
||||
payload.prev_randao == *state.get_randao_mix(state.current_epoch())?,
|
||||
BlockProcessingError::ExecutionRandaoMismatch {
|
||||
expected: *state.get_randao_mix(state.current_epoch())?,
|
||||
found: payload.random,
|
||||
found: payload.prev_randao,
|
||||
}
|
||||
);
|
||||
|
||||
@@ -372,7 +372,7 @@ pub fn process_execution_payload<T: EthSpec>(
|
||||
state_root: payload.state_root,
|
||||
receipts_root: payload.receipts_root,
|
||||
logs_bloom: payload.logs_bloom.clone(),
|
||||
random: payload.random,
|
||||
prev_randao: payload.prev_randao,
|
||||
block_number: payload.block_number,
|
||||
gas_limit: payload.gas_limit,
|
||||
gas_used: payload.gas_used,
|
||||
|
||||
@@ -39,7 +39,7 @@ derivative = "2.1.1"
|
||||
rusqlite = { version = "0.25.3", features = ["bundled"], optional = true }
|
||||
arbitrary = { version = "1.0", features = ["derive"], optional = true }
|
||||
eth2_serde_utils = "0.1.1"
|
||||
regex = "1.3.9"
|
||||
regex = "1.5.5"
|
||||
lazy_static = "1.4.0"
|
||||
parking_lot = "0.11.1"
|
||||
itertools = "0.10.0"
|
||||
|
||||
@@ -146,6 +146,7 @@ pub struct ChainSpec {
|
||||
pub terminal_total_difficulty: Uint256,
|
||||
pub terminal_block_hash: ExecutionBlockHash,
|
||||
pub terminal_block_hash_activation_epoch: Epoch,
|
||||
pub safe_slots_to_import_optimistically: u64,
|
||||
|
||||
/*
|
||||
* Networking
|
||||
@@ -558,6 +559,7 @@ impl ChainSpec {
|
||||
.expect("addition does not overflow"),
|
||||
terminal_block_hash: ExecutionBlockHash::zero(),
|
||||
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
|
||||
safe_slots_to_import_optimistically: 128u64,
|
||||
|
||||
/*
|
||||
* Network specific
|
||||
@@ -755,6 +757,7 @@ impl ChainSpec {
|
||||
.expect("addition does not overflow"),
|
||||
terminal_block_hash: ExecutionBlockHash::zero(),
|
||||
terminal_block_hash_activation_epoch: Epoch::new(u64::MAX),
|
||||
safe_slots_to_import_optimistically: 128u64,
|
||||
|
||||
/*
|
||||
* Network specific
|
||||
@@ -798,6 +801,10 @@ pub struct Config {
|
||||
// TODO(merge): remove this default
|
||||
#[serde(default = "default_terminal_block_hash_activation_epoch")]
|
||||
pub terminal_block_hash_activation_epoch: Epoch,
|
||||
// TODO(merge): remove this default
|
||||
#[serde(default = "default_safe_slots_to_import_optimistically")]
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub safe_slots_to_import_optimistically: u64,
|
||||
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
min_genesis_active_validator_count: u64,
|
||||
@@ -885,6 +892,10 @@ fn default_terminal_block_hash_activation_epoch() -> Epoch {
|
||||
Epoch::new(u64::MAX)
|
||||
}
|
||||
|
||||
fn default_safe_slots_to_import_optimistically() -> u64 {
|
||||
128u64
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
let chain_spec = MainnetEthSpec::default_spec();
|
||||
@@ -942,6 +953,7 @@ impl Config {
|
||||
terminal_total_difficulty: spec.terminal_total_difficulty,
|
||||
terminal_block_hash: spec.terminal_block_hash,
|
||||
terminal_block_hash_activation_epoch: spec.terminal_block_hash_activation_epoch,
|
||||
safe_slots_to_import_optimistically: spec.safe_slots_to_import_optimistically,
|
||||
|
||||
min_genesis_active_validator_count: spec.min_genesis_active_validator_count,
|
||||
min_genesis_time: spec.min_genesis_time,
|
||||
@@ -992,6 +1004,7 @@ impl Config {
|
||||
terminal_total_difficulty,
|
||||
terminal_block_hash,
|
||||
terminal_block_hash_activation_epoch,
|
||||
safe_slots_to_import_optimistically,
|
||||
min_genesis_active_validator_count,
|
||||
min_genesis_time,
|
||||
genesis_fork_version,
|
||||
@@ -1047,6 +1060,7 @@ impl Config {
|
||||
terminal_total_difficulty,
|
||||
terminal_block_hash,
|
||||
terminal_block_hash_activation_epoch,
|
||||
safe_slots_to_import_optimistically,
|
||||
..chain_spec.clone()
|
||||
})
|
||||
}
|
||||
@@ -1157,14 +1171,13 @@ mod tests {
|
||||
#[cfg(test)]
|
||||
mod yaml_tests {
|
||||
use super::*;
|
||||
use std::fs::OpenOptions;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[test]
|
||||
fn minimal_round_trip() {
|
||||
// create temp file
|
||||
let tmp_file = NamedTempFile::new().expect("failed to create temp file");
|
||||
let writer = OpenOptions::new()
|
||||
let writer = File::options()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.open(tmp_file.as_ref())
|
||||
@@ -1175,7 +1188,7 @@ mod yaml_tests {
|
||||
// write fresh minimal config to file
|
||||
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
|
||||
|
||||
let reader = OpenOptions::new()
|
||||
let reader = File::options()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.open(tmp_file.as_ref())
|
||||
@@ -1188,7 +1201,7 @@ mod yaml_tests {
|
||||
#[test]
|
||||
fn mainnet_round_trip() {
|
||||
let tmp_file = NamedTempFile::new().expect("failed to create temp file");
|
||||
let writer = OpenOptions::new()
|
||||
let writer = File::options()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.open(tmp_file.as_ref())
|
||||
@@ -1197,7 +1210,7 @@ mod yaml_tests {
|
||||
let yamlconfig = Config::from_chain_spec::<MainnetEthSpec>(&mainnet_spec);
|
||||
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
|
||||
|
||||
let reader = OpenOptions::new()
|
||||
let reader = File::options()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.open(tmp_file.as_ref())
|
||||
@@ -1234,6 +1247,7 @@ mod yaml_tests {
|
||||
#TERMINAL_TOTAL_DIFFICULTY: 115792089237316195423570985008687907853269984665640564039457584007913129638911
|
||||
#TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000001
|
||||
#TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551614
|
||||
#SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY: 2
|
||||
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16384
|
||||
MIN_GENESIS_TIME: 1606824000
|
||||
GENESIS_FORK_VERSION: 0x00000000
|
||||
@@ -1273,6 +1287,10 @@ mod yaml_tests {
|
||||
chain_spec.terminal_block_hash_activation_epoch,
|
||||
default_terminal_block_hash_activation_epoch()
|
||||
);
|
||||
assert_eq!(
|
||||
chain_spec.safe_slots_to_import_optimistically,
|
||||
default_safe_slots_to_import_optimistically()
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
chain_spec.bellatrix_fork_epoch,
|
||||
|
||||
@@ -92,13 +92,13 @@ impl ConfigAndPreset {
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::MainnetEthSpec;
|
||||
use std::fs::OpenOptions;
|
||||
use std::fs::File;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[test]
|
||||
fn extra_fields_round_trip() {
|
||||
let tmp_file = NamedTempFile::new().expect("failed to create temp file");
|
||||
let writer = OpenOptions::new()
|
||||
let writer = File::options()
|
||||
.read(false)
|
||||
.write(true)
|
||||
.open(tmp_file.as_ref())
|
||||
@@ -116,7 +116,7 @@ mod test {
|
||||
|
||||
serde_yaml::to_writer(writer, &yamlconfig).expect("failed to write or serialize");
|
||||
|
||||
let reader = OpenOptions::new()
|
||||
let reader = File::options()
|
||||
.read(true)
|
||||
.write(false)
|
||||
.open(tmp_file.as_ref())
|
||||
|
||||
@@ -23,7 +23,7 @@ pub struct ExecutionPayload<T: EthSpec> {
|
||||
pub receipts_root: Hash256,
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub logs_bloom: FixedVector<u8, T::BytesPerLogsBloom>,
|
||||
pub random: Hash256,
|
||||
pub prev_randao: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub block_number: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
|
||||
@@ -17,7 +17,7 @@ pub struct ExecutionPayloadHeader<T: EthSpec> {
|
||||
pub receipts_root: Hash256,
|
||||
#[serde(with = "ssz_types::serde_utils::hex_fixed_vec")]
|
||||
pub logs_bloom: FixedVector<u8, T::BytesPerLogsBloom>,
|
||||
pub random: Hash256,
|
||||
pub prev_randao: Hash256,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub block_number: u64,
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
|
||||
@@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||
#[derive(PartialEq, Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ProposerPreparationData {
|
||||
/// The validators index.
|
||||
#[serde(with = "eth2_serde_utils::quoted_u64")]
|
||||
pub validator_index: u64,
|
||||
/// The fee-recipient address.
|
||||
pub fee_recipient: Address,
|
||||
|
||||
Reference in New Issue
Block a user