Fix attestation prod. target roots change

This commit is contained in:
Paul Hauner
2019-08-10 17:47:34 +10:00
parent 963fb7bc87
commit 04bef689e3
3 changed files with 50 additions and 15 deletions

View File

@@ -450,8 +450,9 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
pub fn produce_attestation_data(&self, shard: u64) -> Result<AttestationData, Error> {
let state = self.state.read();
let head_block_root = self.head().beacon_block_root;
let head_block_slot = self.head().beacon_block.slot;
self.produce_attestation_data_for_block(shard, head_block_root, &*state)
self.produce_attestation_data_for_block(shard, head_block_root, head_block_slot, &*state)
}
/// Produce an `AttestationData` that attests to the chain denoted by `block_root` and `state`.
@@ -462,18 +463,39 @@ impl<T: BeaconChainTypes> BeaconChain<T> {
&self,
shard: u64,
head_block_root: Hash256,
head_block_slot: Slot,
state: &BeaconState<T::EthSpec>,
) -> Result<AttestationData, Error> {
// Collect some metrics.
self.metrics.attestation_production_requests.inc();
let timer = self.metrics.attestation_production_times.start_timer();
let slots_per_epoch = T::EthSpec::slots_per_epoch();
let current_epoch_start_slot = state.current_epoch().start_slot(slots_per_epoch);
// The `target_root` is the root of the first block of the current epoch.
let target_root = self
.rev_iter_block_roots()
.find(|(_root, slot)| *slot % T::EthSpec::slots_per_epoch() == 0)
.map(|(root, _slot)| root)
.ok_or_else(|| Error::UnableToFindTargetRoot(self.head().beacon_state.slot))?;
//
// The `state` does not know the root of the block for it's current slot (it only knows
// about blocks from prior slots). This creates an edge-case when the state is on the first
// slot of the epoch -- we're unable to obtain the `target_root` because it is not a prior
// root.
//
// This edge case is handled in two ways:
//
// - If the head block is on the same slot as the state, we use it's root.
// - Otherwise, assume the current slot has been skipped and use the block root from the
// prior slot.
//
// For all other cases, we simply read the `target_root` from `state.latest_block_roots`.
let target_root = if state.slot == current_epoch_start_slot {
if head_block_slot == current_epoch_start_slot {
head_block_root
} else {
*state.get_block_root(current_epoch_start_slot - 1)?
}
} else {
*state.get_block_root(current_epoch_start_slot)?
};
let target = Checkpoint {
epoch: state.current_epoch(),