Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Add finalized to HTTP API responses #3753

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ee990af
Add finalized flag to /eth/v2/beacon/blocks/{block_id}
danielrachi1 Nov 29, 2022
4f8a14e
Add finalized flag to beacon/blocks/{block_id}/root
danielrachi1 Nov 29, 2022
d4fb8e1
fix is_finalized function
danielrachi1 Nov 30, 2022
c827f29
replace is_finalized (BlockId) for is_finalized_block (BeaconChain)
danielrachi1 Nov 30, 2022
5679214
delete is_finalized function
danielrachi1 Nov 30, 2022
953ea6d
Add finalized flag to beacon/blocks/{block_id}/attestations
danielrachi1 Nov 30, 2022
9c60a65
Add finalized flag to beacon/blinded_blocks/{block_id}
danielrachi1 Nov 30, 2022
c020bef
implement is_finalized_state in BeaconChain
danielrachi1 Dec 3, 2022
948ce11
Add finalized flag to beacon/states/{state_id}/*
danielrachi1 Dec 3, 2022
baf1d16
Add finalized flag to GET beacon/headers and GET beacon/headers/{bloc…
danielrachi1 Dec 4, 2022
79fd163
Add finalized flag to GET debug/beacon/states/{state_id}
danielrachi1 Dec 4, 2022
5024517
Remove execution_optimistic_fork_versioned_response
danielrachi1 Dec 16, 2022
6e8be18
Proper error handling for the finalized flag
danielrachi1 Dec 16, 2022
5802d05
Update BeaconNodeHttpClient to handle finalized responses
danielrachi1 Dec 18, 2022
d3eb156
Add tests for the finalized flag
danielrachi1 Dec 18, 2022
5e049e1
fix tests
danielrachi1 Dec 21, 2022
3da1985
StateId::root() now returns info about finalization
danielrachi1 Jan 29, 2023
e483075
StateId::map_state_and_execution_optimistic passes the finalized status
danielrachi1 Jan 30, 2023
1deb787
`BlockId::root` returns info about finalization
danielrachi1 Jan 30, 2023
b49f80b
fix justified finalization response
danielrachi1 Jan 30, 2023
3f07b7e
update tests
danielrachi1 Jan 30, 2023
b0366ee
Replace .state call for .map_state_and_execution_optimistic
danielrachi1 Feb 17, 2023
11cd2ee
Fix .map_state_and_execution_optimistic() function name
danielrachi1 Feb 27, 2023
787b00e
Solve merge conflicts (Merge `unstable` into `add_finalized_flag`)
danielrachi1 Feb 27, 2023
566bb66
Merge branch 'unstable' of github.com:sigp/lighthouse into add_finali…
danielrachi1 Mar 14, 2023
1bc5b97
Merge remote-tracking branch 'origin/unstable' into add_finalized_flag
michaelsproul Mar 30, 2023
5e2be5f
A few clean-ups and optimisations
michaelsproul Mar 30, 2023
51465c5
Fix tests
michaelsproul Mar 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
485 changes: 328 additions & 157 deletions Cargo.lock

Large diffs are not rendered by default.

40 changes: 40 additions & 0 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,46 @@ pub struct BeaconChain<T: BeaconChainTypes> {
type BeaconBlockAndState<T, Payload> = (BeaconBlock<T, Payload>, BeaconState<T>);

impl<T: BeaconChainTypes> BeaconChain<T> {
/// Checks if a block is finalized.
/// The finalization check is done with the block slot. The block root is used to verify that
/// the finalized slot is in the canonical chain.
pub fn is_finalized_block(
&self,
block_root: &Hash256,
block_slot: Slot,
) -> Result<bool, Error> {
let finalized_slot = self
.canonical_head
.cached_head()
.finalized_checkpoint()
.epoch
.start_slot(T::EthSpec::slots_per_epoch());
let is_canonical = self
.block_root_at_slot(block_slot, WhenSlotSkipped::None)?
.map_or(false, |canonical_root| block_root == &canonical_root);
Ok(block_slot <= finalized_slot && is_canonical)
}

/// Checks if a state is finalized.
/// The finalization check is done with the slot. The state root is used to verify that
/// the finalized state is in the canonical chain.
pub fn is_finalized_state(
&self,
state_root: &Hash256,
state_slot: Slot,
) -> Result<bool, Error> {
let finalized_slot = self
.canonical_head
.cached_head()
.finalized_checkpoint()
.epoch
.start_slot(T::EthSpec::slots_per_epoch());
let is_canonical = self
.state_root_at_slot(state_slot)?
.map_or(false, |canonical_root| state_root == &canonical_root);
Ok(state_slot <= finalized_slot && is_canonical)
}

/// Persists the head tracker and fork choice.
///
/// We do it atomically even though no guarantees need to be made about blocks from
Expand Down
6 changes: 4 additions & 2 deletions beacon_node/http_api/src/attester_duties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,10 @@ fn compute_historic_attester_duties<T: BeaconChainTypes>(
)?;
(state, execution_optimistic)
} else {
StateId::from_slot(request_epoch.start_slot(T::EthSpec::slots_per_epoch()))
.state(chain)?
let (state, execution_optimistic, _finalized) =
StateId::from_slot(request_epoch.start_slot(T::EthSpec::slots_per_epoch()))
.state(chain)?;
(state, execution_optimistic)
};

// Sanity-check the state lookup.
Expand Down
45 changes: 34 additions & 11 deletions beacon_node/http_api/src/block_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ use eth2::types::BlockId as CoreBlockId;
use std::fmt;
use std::str::FromStr;
use std::sync::Arc;
use types::{Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot};
use types::{EthSpec, Hash256, SignedBeaconBlock, SignedBlindedBeaconBlock, Slot};

/// Wraps `eth2::types::BlockId` and provides a simple way to obtain a block or root for a given
/// `BlockId`.
#[derive(Debug)]
pub struct BlockId(pub CoreBlockId);

type Finalized = bool;

impl BlockId {
pub fn from_slot(slot: Slot) -> Self {
Self(CoreBlockId::Slot(slot))
Expand All @@ -24,7 +26,7 @@ impl BlockId {
pub fn root<T: BeaconChainTypes>(
&self,
chain: &BeaconChain<T>,
) -> Result<(Hash256, ExecutionOptimistic), warp::Rejection> {
) -> Result<(Hash256, ExecutionOptimistic, Finalized), warp::Rejection> {
match &self.0 {
CoreBlockId::Head => {
let (cached_head, execution_status) = chain
Expand All @@ -34,22 +36,23 @@ impl BlockId {
Ok((
cached_head.head_block_root(),
execution_status.is_optimistic_or_invalid(),
false,
))
}
CoreBlockId::Genesis => Ok((chain.genesis_block_root, false)),
CoreBlockId::Genesis => Ok((chain.genesis_block_root, false, true)),
CoreBlockId::Finalized => {
let finalized_checkpoint =
chain.canonical_head.cached_head().finalized_checkpoint();
let (_slot, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, finalized_checkpoint)?;
Ok((finalized_checkpoint.root, execution_optimistic))
Ok((finalized_checkpoint.root, execution_optimistic, true))
}
CoreBlockId::Justified => {
let justified_checkpoint =
chain.canonical_head.cached_head().justified_checkpoint();
let (_slot, execution_optimistic) =
checkpoint_slot_and_execution_optimistic(chain, justified_checkpoint)?;
Ok((justified_checkpoint.root, execution_optimistic))
Ok((justified_checkpoint.root, execution_optimistic, false))
}
CoreBlockId::Slot(slot) => {
let execution_optimistic = chain
Expand All @@ -66,7 +69,14 @@ impl BlockId {
))
})
})?;
Ok((root, execution_optimistic))
let finalized = *slot
<= chain
.canonical_head
.cached_head()
.finalized_checkpoint()
.epoch
.start_slot(T::EthSpec::slots_per_epoch());
Ok((root, execution_optimistic, finalized))
}
CoreBlockId::Root(root) => {
// This matches the behaviour of other consensus clients (e.g. Teku).
Expand All @@ -88,7 +98,20 @@ impl BlockId {
.is_optimistic_or_invalid_block(root)
.map_err(BeaconChainError::ForkChoiceError)
.map_err(warp_utils::reject::beacon_chain_error)?;
Ok((*root, execution_optimistic))
let blinded_block = chain
.get_blinded_block(root)
.map_err(warp_utils::reject::beacon_chain_error)?
.ok_or_else(|| {
warp_utils::reject::custom_not_found(format!(
"beacon block with root {}",
root
))
})?;
let block_slot = blinded_block.slot();
let finalized = chain
.is_finalized_block(root, block_slot)
.map_err(warp_utils::reject::beacon_chain_error)?;
Ok((*root, execution_optimistic, finalized))
} else {
Err(warp_utils::reject::custom_not_found(format!(
"beacon block with root {}",
Expand Down Expand Up @@ -116,7 +139,7 @@ impl BlockId {
))
}
CoreBlockId::Slot(slot) => {
let (root, execution_optimistic) = self.root(chain)?;
let (root, execution_optimistic, _finalized) = self.root(chain)?;
chain
.get_blinded_block(&root)
.map_err(warp_utils::reject::beacon_chain_error)
Expand All @@ -137,7 +160,7 @@ impl BlockId {
})
}
_ => {
let (root, execution_optimistic) = self.root(chain)?;
let (root, execution_optimistic, _finalized) = self.root(chain)?;
let block = chain
.get_blinded_block(&root)
.map_err(warp_utils::reject::beacon_chain_error)
Expand Down Expand Up @@ -171,7 +194,7 @@ impl BlockId {
))
}
CoreBlockId::Slot(slot) => {
let (root, execution_optimistic) = self.root(chain)?;
let (root, execution_optimistic, _finalized) = self.root(chain)?;
chain
.get_block(&root)
.await
Expand All @@ -193,7 +216,7 @@ impl BlockId {
})
}
_ => {
let (root, execution_optimistic) = self.root(chain)?;
let (root, execution_optimistic, _finalized) = self.root(chain)?;
chain
.get_block(&root)
.await
Expand Down
Loading