From 2a3694991305aefff6c27d6f77ab2cd6472e56e5 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 10 Aug 2020 15:21:31 +0200 Subject: [PATCH] use epochcache for attesting (#1478) --- beacon_chain/block_pools/spec_cache.nim | 30 ++++++++++- beacon_chain/validator_duties.nim | 70 +++++++++++++++---------- beacon_chain/validator_pool.nim | 4 +- 3 files changed, 74 insertions(+), 30 deletions(-) diff --git a/beacon_chain/block_pools/spec_cache.nim b/beacon_chain/block_pools/spec_cache.nim index 3930bc6a8..3fec5b3c1 100644 --- a/beacon_chain/block_pools/spec_cache.nim +++ b/beacon_chain/block_pools/spec_cache.nim @@ -12,7 +12,7 @@ import beaconstate, crypto, datatypes, digest, helpers, presets, signatures, validator], ../extras, - ./block_pools_types + ./block_pools_types, ./chain_dag # Spec functions implemented based on cached values instead of the full state func count_active_validators*(epochInfo: EpochRef): uint64 = @@ -122,3 +122,31 @@ proc is_valid_indexed_attestation*( return false true + +func makeAttestationData*( + epochRef: EpochRef, bs: BlockSlot, + committee_index: uint64): AttestationData = + ## Create an attestation / vote for the block `bs` using the + ## data in `epochRef` to fill in the rest of the fields. + ## `epochRef` is the epoch information corresponding to the `bs` advanced to + ## the slot we're attesting to. + + let + slot = bs.slot + current_epoch = slot.compute_epoch_at_slot() + epoch_boundary_slot = compute_start_slot_at_epoch(current_epoch) + epoch_boundary_block = bs.blck.atSlot(epoch_boundary_slot) + + doAssert current_epoch == epochRef.epoch + + # https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/validator.md#attestation-data + AttestationData( + slot: slot, + index: committee_index, + beacon_block_root: bs.blck.root, + source: epochRef.current_justified_checkpoint, + target: Checkpoint( + epoch: current_epoch, + root: epoch_boundary_block.blck.root + ) + ) diff --git a/beacon_chain/validator_duties.nim b/beacon_chain/validator_duties.nim index 9006c1bae..42f1ba283 100644 --- a/beacon_chain/validator_duties.nim +++ b/beacon_chain/validator_duties.nim @@ -18,7 +18,7 @@ import eth/[keys, async_utils], eth/p2p/discoveryv5/[protocol, enr], # Local modules - spec/[datatypes, digest, crypto, beaconstate, helpers, validator, network], + spec/[datatypes, digest, crypto, helpers, validator, network], spec/state_transition, conf, time, validator_pool, attestation_pool, block_pools/[spec_cache, chain_dag, clearance], @@ -60,11 +60,29 @@ proc addLocalValidators*(node: BeaconNode) = info "Local validators attached ", count = node.attachedValidators.count +proc getAttachedValidator*(node: BeaconNode, + pubkey: ValidatorPubKey): AttachedValidator = + node.attachedValidators.getValidator(pubkey) + proc getAttachedValidator*(node: BeaconNode, state: BeaconState, idx: ValidatorIndex): AttachedValidator = - let validatorKey = state.validators[idx].pubkey.initPubKey - node.attachedValidators.getValidator(validatorKey) + if idx < state.validators.len.ValidatorIndex: + node.getAttachedValidator(state.validators[idx].pubkey) + else: + warn "Validator index out of bounds", + idx, stateSlot = state.slot, validators = state.validators.len + nil + +proc getAttachedValidator*(node: BeaconNode, + epochRef: EpochRef, + idx: ValidatorIndex): AttachedValidator = + if idx < epochRef.validator_keys.len.ValidatorIndex: + node.getAttachedValidator(epochRef.validator_keys[idx]) + else: + warn "Validator index out of bounds", + idx, epoch = epochRef.epoch, validators = epochRef.validator_keys.len + nil proc isSynced*(node: BeaconNode, head: BlockRef): bool = ## TODO This function is here as a placeholder for some better heurestics to @@ -318,32 +336,30 @@ proc handleAttestations(node: BeaconNode, head: BlockRef, slot: Slot) = # In case blocks went missing, this means advancing past the latest block # using empty slots as fillers. # https://github.com/ethereum/eth2.0-specs/blob/v0.12.2/specs/phase0/validator.md#validator-assignments - # TODO we could cache the validator assignment since it's valid for the entire - # epoch since it doesn't change, but that has to be weighed against - # the complexity of handling forks correctly - instead, we use an adapted - # version here that calculates the committee for a single slot only - node.chainDag.withState(node.chainDag.tmpState, attestationHead): - var cache = getEpochCache(attestationHead.blck, state) - let - committees_per_slot = - get_committee_count_per_slot(state, slot.epoch, cache) - num_active_validators = - count_active_validators(state, slot.compute_epoch_at_slot, cache) + let + epochRef = node.chainDag.getEpochRef( + attestationHead.blck, slot.compute_epoch_at_slot()) + committees_per_slot = + get_committee_count_per_slot(epochRef) + num_active_validators = count_active_validators(epochRef) + fork = node.chainDag.headState.data.data.fork + genesis_validators_root = + node.chainDag.headState.data.data.genesis_validators_root - for committee_index in 0'u64..