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

Add proto_array fork choice #804

Merged
merged 88 commits into from Jan 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
92e7b60
Start implementing proto_array
paulhauner Jan 6, 2020
c5ee929
Add progress
paulhauner Jan 7, 2020
4579c8c
Add unfinished progress
paulhauner Jan 7, 2020
aea40ca
Add further progress
paulhauner Jan 11, 2020
32c21da
Add progress
paulhauner Jan 11, 2020
e771cff
Add tree filtering
paulhauner Jan 11, 2020
6ef1488
Add half-finished modifications
paulhauner Jan 12, 2020
c1c70f1
Add refactored version
paulhauner Jan 12, 2020
812be82
Tidy, add incomplete LmdGhost impl
paulhauner Jan 12, 2020
beb5122
Move impls in LmdGhost trait def
paulhauner Jan 12, 2020
d7761ec
Remove old reduced_tree fork choice
paulhauner Jan 13, 2020
120bcfa
Combine two functions in to `compute_deltas`
paulhauner Jan 13, 2020
899e8c7
Start testing
paulhauner Jan 13, 2020
8f72c09
Add more compute_deltas tests
paulhauner Jan 13, 2020
c927481
Add fork choice testing
paulhauner Jan 13, 2020
3853af1
Add more fork choice testing
paulhauner Jan 13, 2020
5da9ddd
Add more fork choice tests
paulhauner Jan 13, 2020
092b0e5
Add more testing to proto-array
paulhauner Jan 13, 2020
4324ce3
Remove old tests
paulhauner Jan 13, 2020
1eee093
Modify tests
paulhauner Jan 13, 2020
374877c
Add more tests
paulhauner Jan 13, 2020
d856f34
Add more testing
paulhauner Jan 13, 2020
0ad7990
Add comments and fixes
paulhauner Jan 13, 2020
cc7f8fe
Re-organise crate
paulhauner Jan 13, 2020
6bb453f
Tidy, finish pruning tests
paulhauner Jan 14, 2020
512b7fe
Add ssz encoding, other pub fns
paulhauner Jan 14, 2020
0f9d0ff
Rename lmd_ghost > proto_array_fork_choice
paulhauner Jan 14, 2020
b8d33ae
Integrate proto_array into lighthouse
paulhauner Jan 14, 2020
486c74f
Merge branch 'master' into proto-array + more changes
paulhauner Jan 14, 2020
6f51db3
Add first pass at fixing filter
paulhauner Jan 15, 2020
90b5782
Clean out old comments
paulhauner Jan 15, 2020
029fb24
Add more comments
paulhauner Jan 15, 2020
cba0d9a
Attempt to fix prune error
paulhauner Jan 15, 2020
61c8781
Adjust TODO
paulhauner Jan 15, 2020
fbfe77b
Fix test compile errors
paulhauner Jan 15, 2020
76d7122
Add extra justification change check
paulhauner Jan 15, 2020
ea19227
Merge branch 'master' into proto-array
paulhauner Jan 15, 2020
1ef3fa3
Update cargo.lock
paulhauner Jan 15, 2020
a73aa5d
Fix fork choice test compile errors
paulhauner Jan 15, 2020
85e761e
Most remove ffg_update_required
paulhauner Jan 15, 2020
2366c9a
Fix bug with epoch of attestation votes
paulhauner Jan 15, 2020
5cbb34c
Start adding new test format
paulhauner Jan 15, 2020
d8afb0f
Make fork choice tests declarative
paulhauner Jan 16, 2020
c33d358
Create test def concept
paulhauner Jan 16, 2020
72dc6db
Move test defs into crate
paulhauner Jan 16, 2020
4a60c06
Add binary, re-org crate
paulhauner Jan 16, 2020
62ea066
Shuffle files
paulhauner Jan 16, 2020
2052bcb
Start adding ffg tests
paulhauner Jan 16, 2020
2df7137
Add more fork choice tests
paulhauner Jan 16, 2020
9d295b7
Add fork choice JSON dumping
paulhauner Jan 16, 2020
f136d38
Add more detail to best node error
paulhauner Jan 16, 2020
272c16c
Ensure fin+just checkpoints from from same block
paulhauner Jan 17, 2020
991223d
Rename JustificationManager
paulhauner Jan 17, 2020
b55687c
Move checkpoint manager into own file
paulhauner Jan 17, 2020
cd5c8a3
Tidy
paulhauner Jan 17, 2020
0cd7ae5
Add targetted logging for sneaky sync bug
AgeManning Jan 17, 2020
52dfb61
Fix justified balances bug
paulhauner Jan 17, 2020
fd0a1c4
Add cache metrics
paulhauner Jan 17, 2020
cf72a6c
Add metrics for log levels
paulhauner Jan 17, 2020
7194764
Fix bug in checkpoint manager
paulhauner Jan 17, 2020
268dd06
Merge branch 'sync-bug-finder' into proto-array
paulhauner Jan 17, 2020
10d37b2
Fix compile error in fork choice tests
paulhauner Jan 17, 2020
c546cab
Ignore duplicate blocks in fork choice
paulhauner Jan 19, 2020
eabc2ed
Add block to fock choice before db
paulhauner Jan 19, 2020
dcea0b5
Rename on_new_block fn
paulhauner Jan 19, 2020
6908b7c
Fix spec inconsistency in `CheckpointManager`
paulhauner Jan 19, 2020
c3969e2
Remove BlockRootTree
paulhauner Jan 21, 2020
3a1e999
Merge branch 'proto-array' of github.com:sigp/lighthouse into proto-a…
paulhauner Jan 24, 2020
aa0e9a4
Merge branch 'master' into proto-array
paulhauner Jan 24, 2020
cc11e52
Remove old reduced_tree code fragment
paulhauner Jan 27, 2020
8a61904
Add API endpoint for fork choice
paulhauner Jan 27, 2020
e1ebdf3
Add more ffg tests
paulhauner Jan 27, 2020
7b7982f
Remove block_root_tree reminents
paulhauner Jan 27, 2020
4da401f
Ensure effective balances are used
paulhauner Jan 27, 2020
43b0a63
Remove old debugging code, fix API fault
paulhauner Jan 27, 2020
ed59327
Add check to ensure parent block is in fork choice
paulhauner Jan 28, 2020
bb93b08
Update readme dates
paulhauner Jan 28, 2020
26e7f2a
Fix readme
paulhauner Jan 28, 2020
3c6c89c
Tidy checkpoint manager
paulhauner Jan 28, 2020
23b33e1
Remove fork choice yaml files from repo
paulhauner Jan 28, 2020
98ed038
Remove fork choice yaml from repo
paulhauner Jan 28, 2020
023ce33
General tidy
paulhauner Jan 28, 2020
e1c32e1
Address majority of Michael's comments
paulhauner Jan 29, 2020
d726248
Tidy bin/lib business
paulhauner Jan 29, 2020
986468a
Remove dangling file
paulhauner Jan 29, 2020
e8007b0
Merge branch 'master' into proto-array
paulhauner Jan 29, 2020
876edff
Undo changes for rpc/handler from master
paulhauner Jan 29, 2020
242ba3a
Revert "Undo changes for rpc/handler from master"
paulhauner Jan 29, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 18 additions & 24 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[workspace]
members = [
"eth2/lmd_ghost",
"eth2/proto_array_fork_choice",
"eth2/operation_pool",
"eth2/state_processing",
"eth2/types",
Expand Down
9 changes: 4 additions & 5 deletions README.md
Expand Up @@ -49,11 +49,10 @@ Current development overview:

- ~~**April 2019**: Inital single-client testnets.~~
- ~~**September 2019**: Inter-operability with other Ethereum 2.0 clients.~~
- **Q4 2019**: `lighthouse-0.0.1` release: All major phase 0
features implemented.
- **Q4 2019**: Public, multi-client testnet with user-facing functionality.
- **Q4 2019**: Third-party security review.
- **Q1 2020**: Production Beacon Chain testnet (tentative).
- ~~ **Q1 2020**: `lighthouse-0.1.0` release: All major phase 0 features implemented.~~
- **Q1 2020**: Public, multi-client testnet with user-facing functionality.
- **Q2 2020**: Third-party security review.
- **Q3 2020**: Production Beacon Chain testnet (tentative).


## Documentation
Expand Down
2 changes: 1 addition & 1 deletion beacon_node/beacon_chain/Cargo.toml
Expand Up @@ -33,14 +33,14 @@ eth2_ssz_derive = "0.1.0"
state_processing = { path = "../../eth2/state_processing" }
tree_hash = "0.1.0"
types = { path = "../../eth2/types" }
lmd_ghost = { path = "../../eth2/lmd_ghost" }
eth1 = { path = "../eth1" }
websocket_server = { path = "../websocket_server" }
futures = "0.1.25"
exit-future = "0.1.3"
genesis = { path = "../genesis" }
integer-sqrt = "0.1"
rand = "0.7.2"
proto_array_fork_choice = { path = "../../eth2/proto_array_fork_choice" }

[dev-dependencies]
tempfile = "3.1.0"
Expand Down
91 changes: 46 additions & 45 deletions beacon_node/beacon_chain/src/beacon_chain.rs
Expand Up @@ -8,7 +8,6 @@ use crate::head_tracker::HeadTracker;
use crate::metrics;
use crate::persisted_beacon_chain::{PersistedBeaconChain, BEACON_CHAIN_DB_KEY};
use crate::timeout_rw_lock::TimeoutRwLock;
use lmd_ghost::LmdGhost;
use operation_pool::{OperationPool, PersistedOperationPool};
use slog::{debug, error, info, trace, warn, Logger};
use slot_clock::SlotClock;
Expand All @@ -32,7 +31,7 @@ use std::time::{Duration, Instant};
use store::iter::{
BlockRootsIterator, ReverseBlockRootIterator, ReverseStateRootIterator, StateRootsIterator,
};
use store::{BlockRootTree, Error as DBError, Migrate, Store};
use store::{Error as DBError, Migrate, Store};
use tree_hash::TreeHash;
use types::*;

Expand All @@ -59,8 +58,11 @@ const HEAD_LOCK_TIMEOUT: Duration = Duration::from_secs(1);
pub enum BlockProcessingOutcome {
/// Block was valid and imported into the block graph.
Processed { block_root: Hash256 },
/// The blocks parent_root is unknown.
ParentUnknown { parent: Hash256 },
/// The parent block was unknown.
ParentUnknown {
parent: Hash256,
reference_location: &'static str,
},
/// The block slot is greater than the present slot.
FutureSlot {
present_slot: Slot,
Expand Down Expand Up @@ -116,7 +118,6 @@ pub trait BeaconChainTypes: Send + Sync + 'static {
type Store: store::Store<Self::EthSpec>;
type StoreMigrator: store::Migrate<Self::Store, Self::EthSpec>;
type SlotClock: slot_clock::SlotClock;
type LmdGhost: LmdGhost<Self::Store, Self::EthSpec>;
type Eth1Chain: Eth1ChainBackend<Self::EthSpec, Self::Store>;
type EthSpec: types::EthSpec;
type EventHandler: EventHandler<Self::EthSpec>;
Expand Down Expand Up @@ -150,8 +151,6 @@ pub struct BeaconChain<T: BeaconChainTypes> {
pub(crate) head_tracker: HeadTracker,
/// Provides a small cache of `BeaconState` and `BeaconBlock`.
pub(crate) checkpoint_cache: CheckPointCache<T::EthSpec>,
/// Cache of block roots for all known forks post-finalization.
pub block_root_tree: Arc<BlockRootTree>,
/// Logging to CLI, etc.
pub(crate) log: Logger,
}
Expand Down Expand Up @@ -192,7 +191,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
ssz_head_tracker: self.head_tracker.to_ssz_container(),
fork_choice: self.fork_choice.as_ssz_container(),
eth1_cache: self.eth1_chain.as_ref().map(|x| x.as_ssz_container()),
block_root_tree: self.block_root_tree.as_ssz_container(),
};

let key = Hash256::from_slice(&BEACON_CHAIN_DB_KEY.as_bytes());
Expand Down Expand Up @@ -1063,14 +1061,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
{
// Provide the attestation to fork choice, updating the validator latest messages but
// _without_ finding and updating the head.
if let Err(e) = self
.fork_choice
.process_attestation(&state, &attestation, block)
{
if let Err(e) = self.fork_choice.process_attestation(&state, &attestation) {
error!(
self.log,
"Add attestation to fork choice failed";
"fork_choice_integrity" => format!("{:?}", self.fork_choice.verify_integrity()),
"beacon_block_root" => format!("{}", attestation.data.beacon_block_root),
"error" => format!("{:?}", e)
);
Expand Down Expand Up @@ -1232,6 +1226,23 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
});
}

// Reject any block if its parent is not known to fork choice.
//
// A block that is not in fork choice is either:
//
// - Not yet imported: we should reject this block because we should only import a child
// after its parent has been fully imported.
// - Pre-finalized: if the parent block is _prior_ to finalization, we should ignore it
// because it will revert finalization. Note that the finalized block is stored in fork
// choice, so we will not reject any child of the finalized block (this is relevant during
// genesis).
if !self.fork_choice.contains_block(&block.parent_root) {
return Ok(BlockProcessingOutcome::ParentUnknown {
parent: block.parent_root,
reference_location: "fork_choice",
});
}

let block_root_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_BLOCK_ROOT);

let block_root = block.canonical_root();
Expand All @@ -1252,8 +1263,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
}

// Check if the block is already known. We know it is post-finalization, so it is
// sufficient to check the block root tree.
if self.block_root_tree.is_known_block_root(&block_root) {
// sufficient to check the fork choice.
if self.fork_choice.contains_block(&block_root) {
return Ok(BlockProcessingOutcome::BlockIsAlreadyKnown);
}

Expand All @@ -1269,6 +1280,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
None => {
return Ok(BlockProcessingOutcome::ParentUnknown {
parent: block.parent_root,
reference_location: "database",
});
}
};
Expand Down Expand Up @@ -1363,6 +1375,24 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
});
}

let fork_choice_register_timer =
metrics::start_timer(&metrics::BLOCK_PROCESSING_FORK_CHOICE_REGISTER);

// Register the new block with the fork choice service.
if let Err(e) = self
.fork_choice
.process_block(self, &state, &block, block_root)
{
error!(
self.log,
"Add block to fork choice failed";
"block_root" => format!("{}", block_root),
"error" => format!("{:?}", e),
)
}

metrics::stop_timer(fork_choice_register_timer);

let db_write_timer = metrics::start_timer(&metrics::BLOCK_PROCESSING_DB_WRITE);

// Store all the states between the parent block state and this blocks slot before storing
Expand Down Expand Up @@ -1392,30 +1422,8 @@ impl<T: BeaconChainTypes> BeaconChain<T> {

metrics::stop_timer(db_write_timer);

self.block_root_tree
.add_block_root(block_root, block.parent_root, block.slot)?;

self.head_tracker.register_block(block_root, &block);

let fork_choice_register_timer =
metrics::start_timer(&metrics::BLOCK_PROCESSING_FORK_CHOICE_REGISTER);

// Register the new block with the fork choice service.
if let Err(e) = self
.fork_choice
.process_block(self, &state, &block, block_root)
{
error!(
self.log,
"Add block to fork choice failed";
"fork_choice_integrity" => format!("{:?}", self.fork_choice.verify_integrity()),
"block_root" => format!("{}", block_root),
"error" => format!("{:?}", e),
)
}

metrics::stop_timer(fork_choice_register_timer);

metrics::inc_counter(&metrics::BLOCK_PROCESSING_SUCCESSES);
metrics::observe(
&metrics::OPERATIONS_PER_BLOCK_ATTESTATION,
Expand Down Expand Up @@ -1706,8 +1714,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
new_epoch: new_finalized_epoch,
})
} else {
self.fork_choice
.process_finalization(&finalized_block, finalized_block_root)?;
self.fork_choice.prune()?;

let finalized_state = self
.get_state_caching_only_with_committee_caches(
Expand All @@ -1726,12 +1733,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
max_finality_distance,
);

// Prune in-memory block root tree.
self.block_root_tree.prune_to(
finalized_block_root,
self.heads().into_iter().map(|(block_root, _)| block_root),
);

let _ = self.event_handler.register(EventKind::BeaconFinalization {
epoch: new_finalized_epoch,
root: finalized_block_root,
Expand Down