Skip to content

Commit 24e941d

Browse files
Update to spec v0.9.1 (#597)
* Update to spec v0.9.0 * Update to v0.9.1 * Bump spec tags for v0.9.1 * Formatting, fix CI failures * Resolve accidental KeyPair merge conflict * Document new BeaconState functions * Fix incorrect cache drops in `advance_caches` * Update fork choice for v0.9.1 * Clean up some FIXMEs * Fix a few docs/logs
1 parent b7a0feb commit 24e941d

File tree

105 files changed

+1211
-2940
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+1211
-2940
lines changed

.gitlab-ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ default:
44
image: 'sigp/lighthouse:latest'
55
cache:
66
paths:
7-
- tests/ef_tests/*-v0.8.3.tar.gz
7+
- tests/ef_tests/*-v0.9.1.tar.gz
88

99
stages:
1010
- test
@@ -47,7 +47,7 @@ test-ef-fake-crypto:
4747
GIT_SUBMODULE_STRATEGY: normal
4848
script:
4949
- make make-ef-tests
50-
- cargo test --manifest-path tests/ef_tests/Cargo.toml --release --features ef_tests fake_crypto
50+
- cargo test --manifest-path tests/ef_tests/Cargo.toml --release --features ef_tests,fake_crypto
5151

5252
documentation:
5353
stage: document

beacon_node/beacon_chain/src/beacon_chain.rs

Lines changed: 91 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use ssz::Encode;
1616
use state_processing::per_block_processing::{
1717
errors::{
1818
AttestationValidationError, AttesterSlashingValidationError, DepositValidationError,
19-
ExitValidationError, ProposerSlashingValidationError, TransferValidationError,
19+
ExitValidationError, ProposerSlashingValidationError,
2020
},
2121
verify_attestation_for_state, VerifySignatures,
2222
};
@@ -218,6 +218,44 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
218218
ReverseBlockRootIterator::new((head.beacon_block_root, head.beacon_block.slot), iter)
219219
}
220220

221+
/// Traverse backwards from `block_root` to find the block roots of its ancestors.
222+
///
223+
/// ## Notes
224+
///
225+
/// `slot` always decreases by `1`.
226+
/// - Skipped slots contain the root of the closest prior
227+
/// non-skipped slot (identical to the way they are stored in `state.block_roots`) .
228+
/// - Iterator returns `(Hash256, Slot)`.
229+
/// - The provided `block_root` is included as the first item in the iterator.
230+
pub fn rev_iter_block_roots_from(
231+
&self,
232+
block_root: Hash256,
233+
) -> Result<ReverseBlockRootIterator<T::EthSpec, T::Store>, Error> {
234+
let block = self
235+
.get_block(&block_root)?
236+
.ok_or_else(|| Error::MissingBeaconBlock(block_root))?;
237+
let state = self
238+
.get_state(&block.state_root)?
239+
.ok_or_else(|| Error::MissingBeaconState(block.state_root))?;
240+
let iter = BlockRootsIterator::owned(self.store.clone(), state);
241+
Ok(ReverseBlockRootIterator::new(
242+
(block_root, block.slot),
243+
iter,
244+
))
245+
}
246+
247+
/// Traverse backwards from `block_root` to find the root of the ancestor block at `slot`.
248+
pub fn get_ancestor_block_root(
249+
&self,
250+
block_root: Hash256,
251+
slot: Slot,
252+
) -> Result<Option<Hash256>, Error> {
253+
Ok(self
254+
.rev_iter_block_roots_from(block_root)?
255+
.find(|(_, ancestor_slot)| *ancestor_slot == slot)
256+
.map(|(ancestor_block_root, _)| ancestor_block_root))
257+
}
258+
221259
/// Iterates across all `(state_root, slot)` pairs from the head of the chain (inclusive) to
222260
/// the earliest reachable ancestor (may or may not be genesis).
223261
///
@@ -248,6 +286,18 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
248286
Ok(self.store.get(block_root)?)
249287
}
250288

289+
/// Returns the state at the given root, if any.
290+
///
291+
/// ## Errors
292+
///
293+
/// May return a database error.
294+
pub fn get_state(
295+
&self,
296+
state_root: &Hash256,
297+
) -> Result<Option<BeaconState<T::EthSpec>>, Error> {
298+
Ok(self.store.get(state_root)?)
299+
}
300+
251301
/// Returns a `Checkpoint` representing the head block and state. Contains the "best block";
252302
/// the head of the canonical `BeaconChain`.
253303
///
@@ -385,15 +435,15 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
385435
}
386436

387437
state
388-
.get_beacon_proposer_index(slot, RelativeEpoch::Current, &self.spec)
438+
.get_beacon_proposer_index(slot, &self.spec)
389439
.map_err(Into::into)
390440
}
391441

392-
/// Returns the attestation slot and shard for a given validator index.
442+
/// Returns the attestation slot and committee index for a given validator index.
393443
///
394444
/// Information is read from the current state, so only information from the present and prior
395445
/// epoch is available.
396-
pub fn validator_attestation_slot_and_shard(
446+
pub fn validator_attestation_slot_and_index(
397447
&self,
398448
validator_index: usize,
399449
epoch: Epoch,
@@ -420,25 +470,25 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
420470
if let Some(attestation_duty) =
421471
state.get_attestation_duties(validator_index, RelativeEpoch::Current)?
422472
{
423-
Ok(Some((attestation_duty.slot, attestation_duty.shard)))
473+
Ok(Some((attestation_duty.slot, attestation_duty.index)))
424474
} else {
425475
Ok(None)
426476
}
427477
}
428478

429-
/// Produce an `AttestationData` that is valid for the given `slot` `shard`.
479+
/// Produce an `AttestationData` that is valid for the given `slot`, `index`.
430480
///
431481
/// Always attests to the canonical chain.
432482
pub fn produce_attestation_data(
433483
&self,
434-
shard: u64,
435484
slot: Slot,
485+
index: CommitteeIndex,
436486
) -> Result<AttestationData, Error> {
437487
let state = self.state_at_slot(slot)?;
438488
let head = self.head();
439489

440490
self.produce_attestation_data_for_block(
441-
shard,
491+
index,
442492
head.beacon_block_root,
443493
head.beacon_block.slot,
444494
&state,
@@ -451,7 +501,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
451501
/// function should be used as it attests to the canonical chain.
452502
pub fn produce_attestation_data_for_block(
453503
&self,
454-
shard: u64,
504+
index: CommitteeIndex,
455505
head_block_root: Hash256,
456506
head_block_slot: Slot,
457507
state: &BeaconState<T::EthSpec>,
@@ -492,18 +542,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
492542
root: target_root,
493543
};
494544

495-
let parent_crosslink = state.get_current_crosslink(shard)?;
496-
let crosslink = Crosslink {
497-
shard,
498-
parent_root: Hash256::from_slice(&parent_crosslink.tree_hash_root()),
499-
start_epoch: parent_crosslink.end_epoch,
500-
end_epoch: std::cmp::min(
501-
target.epoch,
502-
parent_crosslink.end_epoch + self.spec.max_epochs_per_crosslink,
503-
),
504-
data_root: Hash256::zero(),
505-
};
506-
507545
// Collect some metrics.
508546
metrics::inc_counter(&metrics::ATTESTATION_PRODUCTION_SUCCESSES);
509547
metrics::stop_timer(timer);
@@ -512,15 +550,16 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
512550
self.log,
513551
"Produced beacon attestation data";
514552
"beacon_block_root" => format!("{}", head_block_root),
515-
"shard" => shard,
516-
"slot" => state.slot
553+
"slot" => state.slot,
554+
"index" => index
517555
);
518556

519557
Ok(AttestationData {
558+
slot: state.slot,
559+
index,
520560
beacon_block_root: head_block_root,
521561
source: state.current_justified_checkpoint.clone(),
522562
target,
523-
crosslink,
524563
})
525564
}
526565

@@ -549,7 +588,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
549588
self.log,
550589
"Beacon attestation imported";
551590
"target_epoch" => attestation.data.target.epoch,
552-
"shard" => attestation.data.crosslink.shard,
591+
"index" => attestation.data.index,
553592
);
554593
let _ = self
555594
.event_handler
@@ -668,16 +707,14 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
668707

669708
state.build_committee_cache(RelativeEpoch::Current, &self.spec)?;
670709

671-
let attestation_slot = state.get_attestation_data_slot(&attestation.data)?;
672-
673710
// Reject any attestation where the `state` loaded from `data.beacon_block_root`
674711
// has a higher slot than the attestation.
675712
//
676713
// Permitting this would allow for attesters to vote on _future_ slots.
677-
if state.slot > attestation_slot {
714+
if state.slot > attestation.data.slot {
678715
Ok(AttestationProcessingOutcome::AttestsToFutureState {
679716
state: state.slot,
680-
attestation: attestation_slot,
717+
attestation: attestation.data.slot,
681718
})
682719
} else {
683720
self.process_attestation_for_state_and_block(
@@ -776,20 +813,27 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
776813

777814
Ok(AttestationProcessingOutcome::Invalid(e))
778815
} else {
779-
// Provide the attestation to fork choice, updating the validator latest messages but
780-
// _without_ finding and updating the head.
781-
if let Err(e) = self
782-
.fork_choice
783-
.process_attestation(&state, &attestation, block)
816+
// If the attestation is from the current or previous epoch, supply it to the fork
817+
// choice. This is FMD GHOST.
818+
let current_epoch = self.epoch()?;
819+
if attestation.data.target.epoch == current_epoch
820+
|| attestation.data.target.epoch == current_epoch - 1
784821
{
785-
error!(
786-
self.log,
787-
"Add attestation to fork choice failed";
788-
"fork_choice_integrity" => format!("{:?}", self.fork_choice.verify_integrity()),
789-
"beacon_block_root" => format!("{}", attestation.data.beacon_block_root),
790-
"error" => format!("{:?}", e)
791-
);
792-
return Err(e.into());
822+
// Provide the attestation to fork choice, updating the validator latest messages but
823+
// _without_ finding and updating the head.
824+
if let Err(e) = self
825+
.fork_choice
826+
.process_attestation(&state, &attestation, block)
827+
{
828+
error!(
829+
self.log,
830+
"Add attestation to fork choice failed";
831+
"fork_choice_integrity" => format!("{:?}", self.fork_choice.verify_integrity()),
832+
"beacon_block_root" => format!("{}", attestation.data.beacon_block_root),
833+
"error" => format!("{:?}", e)
834+
);
835+
return Err(e.into());
836+
}
793837
}
794838

795839
// Provide the valid attestation to op pool, which may choose to retain the
@@ -829,22 +873,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
829873
}
830874
}
831875

832-
/// Accept some transfer and queue it for inclusion in an appropriate block.
833-
pub fn process_transfer(&self, transfer: Transfer) -> Result<(), TransferValidationError> {
834-
match self.wall_clock_state() {
835-
Ok(state) => self.op_pool.insert_transfer(transfer, &state, &self.spec),
836-
Err(e) => {
837-
error!(
838-
&self.log,
839-
"Unable to process transfer";
840-
"error" => format!("{:?}", e),
841-
"reason" => "no state"
842-
);
843-
Ok(())
844-
}
845-
}
846-
}
847-
848876
/// Accept some proposer slashing and queue it for inclusion in an appropriate block.
849877
pub fn process_proposer_slashing(
850878
&self,
@@ -905,7 +933,7 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
905933
self.log,
906934
"Beacon block imported";
907935
"block_root" => format!("{:?}", block_root),
908-
"block_slot" => format!("{:?}", block_root),
936+
"block_slot" => format!("{:?}", block.slot.as_u64()),
909937
);
910938
let _ = self.event_handler.register(EventKind::BeaconBlockImported {
911939
block_root: *block_root,
@@ -1115,7 +1143,10 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
11151143
metrics::start_timer(&metrics::BLOCK_PROCESSING_FORK_CHOICE_REGISTER);
11161144

11171145
// Register the new block with the fork choice service.
1118-
if let Err(e) = self.fork_choice.process_block(&state, &block, block_root) {
1146+
if let Err(e) = self
1147+
.fork_choice
1148+
.process_block(self, &state, &block, block_root)
1149+
{
11191150
error!(
11201151
self.log,
11211152
"Add block to fork choice failed";
@@ -1230,7 +1261,6 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
12301261
.deposits_for_block_inclusion(&state, &self.spec)?
12311262
.into(),
12321263
voluntary_exits: self.op_pool.get_voluntary_exits(&state, &self.spec).into(),
1233-
transfers: self.op_pool.get_transfers(&state, &self.spec).into(),
12341264
},
12351265
};
12361266

beacon_node/beacon_chain/src/builder.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,12 @@ where
231231
.genesis_block_root
232232
.ok_or_else(|| "fork_choice_backend requires a genesis_block_root")?;
233233

234-
self.fork_choice = Some(ForkChoice::new(store, backend, genesis_block_root));
234+
self.fork_choice = Some(ForkChoice::new(
235+
store,
236+
backend,
237+
genesis_block_root,
238+
self.spec.genesis_slot,
239+
));
235240

236241
Ok(self)
237242
}

beacon_node/beacon_chain/src/errors.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ macro_rules! easy_from_to {
1818
#[derive(Debug, PartialEq)]
1919
pub enum BeaconChainError {
2020
InsufficientValidators,
21-
BadRecentBlockRoots,
2221
UnableToReadSlot,
2322
RevertedFinalizedEpoch {
2423
previous_epoch: Epoch,

beacon_node/beacon_chain/src/eth1_chain.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ mod test {
487487
let keypair = generate_deterministic_keypair(i as usize);
488488
let mut builder =
489489
TestingDepositBuilder::new(keypair.pk.clone(), spec.max_effective_balance);
490-
builder.sign(&DepositTestTask::Valid, &keypair, spec);
490+
builder.sign(DepositTestTask::Valid, &keypair, spec);
491491
let deposit_data = builder.build().data;
492492

493493
DepositLog {

0 commit comments

Comments
 (0)