use epochref for get_committee_assignments() to avoid repeated shuffling (#2463)

* use epochref for get_committee_assignments() to avoid repeated shuffling

* remove unnecessary imports and StateCache() construction
This commit is contained in:
tersec 2021-03-30 15:01:47 +00:00 committed by GitHub
parent a9938a2067
commit bd8b60f8c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 30 additions and 36 deletions

View File

@ -8,10 +8,10 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
std/[algorithm, sequtils], std/[algorithm, intsets, sequtils],
chronicles, chronicles,
../spec/[ ../spec/[
crypto, datatypes, digest, helpers, presets, signatures, crypto, datatypes, digest, helpers, network, presets, signatures,
validator], validator],
../extras, ../extras,
./block_pools_types, ./blockchain_dag ./block_pools_types, ./blockchain_dag
@ -193,3 +193,26 @@ func makeAttestationData*(
root: epoch_boundary_block.blck.root root: epoch_boundary_block.blck.root
) )
) )
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/validator.md#validator-assignments
iterator get_committee_assignments*(
epochRef: EpochRef, epoch: Epoch, validator_indices: IntSet):
tuple[validatorIndices: IntSet,
committeeIndex: CommitteeIndex,
subnetIndex: uint8, slot: Slot] =
let
committees_per_slot = get_committee_count_per_slot(epochRef)
start_slot = compute_start_slot_at_epoch(epoch)
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
for index in 0'u64 ..< committees_per_slot:
let
idx = index.CommitteeIndex
includedIndices =
toIntSet(get_beacon_committee(epochRef, slot, idx)) *
validator_indices
if includedIndices.len > 0:
yield (
includedIndices, idx,
compute_subnet_for_attestation(committees_per_slot, slot, idx).uint8,
slot)

View File

@ -463,8 +463,6 @@ proc updateSubscriptionSchedule(node: BeaconNode, epoch: Epoch) {.async.} =
attachedValidators = node.getAttachedValidators() attachedValidators = node.getAttachedValidators()
validatorIndices = toIntSet(toSeq(attachedValidators.keys())) validatorIndices = toIntSet(toSeq(attachedValidators.keys()))
var cache = StateCache()
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/validator.md#lookahead # https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/validator.md#lookahead
# Only subscribe when this node should aggregate; libp2p broadcasting works # Only subscribe when this node should aggregate; libp2p broadcasting works
# on subnet topics regardless. # on subnet topics regardless.
@ -496,8 +494,7 @@ proc updateSubscriptionSchedule(node: BeaconNode, epoch: Epoch) {.async.} =
static: doAssert SLOTS_PER_EPOCH <= 32 static: doAssert SLOTS_PER_EPOCH <= 32
for (validatorIndices, committeeIndex, subnetIndex, slot) in for (validatorIndices, committeeIndex, subnetIndex, slot) in
get_committee_assignments( get_committee_assignments(epochRef, epoch, validatorIndices):
node.chainDag.headState.data.data, epoch, validatorIndices, cache):
doAssert compute_epoch_at_slot(slot) == epoch doAssert compute_epoch_at_slot(slot) == epoch
@ -653,14 +650,13 @@ proc getInitialAttestationSubnets(node: BeaconNode): Table[uint8, Slot] =
wallEpoch = node.beaconClock.now().slotOrZero().epoch wallEpoch = node.beaconClock.now().slotOrZero().epoch
validatorIndices = toIntSet(toSeq(node.getAttachedValidators().keys())) validatorIndices = toIntSet(toSeq(node.getAttachedValidators().keys()))
var cache = StateCache()
template mergeAttestationSubnets(epoch: Epoch) = template mergeAttestationSubnets(epoch: Epoch) =
# TODO when https://github.com/nim-lang/Nim/issues/15972 and # TODO when https://github.com/nim-lang/Nim/issues/15972 and
# https://github.com/nim-lang/Nim/issues/16217 are fixed, in # https://github.com/nim-lang/Nim/issues/16217 are fixed, in
# Nimbus's Nim, use (_, _, subnetIndex, slot). # Nimbus's Nim, use (_, _, subnetIndex, slot).
let epochRef = node.chainDag.getEpochRef(node.chainDag.head, epoch)
for (_, ci, subnetIndex, slot) in get_committee_assignments( for (_, ci, subnetIndex, slot) in get_committee_assignments(
node.chainDag.headState.data.data, epoch, validatorIndices, cache): epochRef, epoch, validatorIndices):
result.withValue(subnetIndex, v) do: result.withValue(subnetIndex, v) do:
v[] = max(v[], slot + 1) v[] = max(v[], slot + 1)
do: do:

View File

@ -8,8 +8,8 @@
{.push raises: [Defect].} {.push raises: [Defect].}
import import
std/[intsets, strformat], std/strformat,
./datatypes, ./helpers, ./validator ./datatypes
const const
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/p2p-interface.md#topics-and-messages # https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/p2p-interface.md#topics-and-messages
@ -85,28 +85,3 @@ func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
&"/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz" &"/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz"
except ValueError as e: except ValueError as e:
raiseAssert e.msg raiseAssert e.msg
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/validator.md#validator-assignments
iterator get_committee_assignments*(
state: BeaconState, epoch: Epoch,
validator_indices: IntSet,
cache: var StateCache):
tuple[validatorIndices: IntSet,
committeeIndex: CommitteeIndex,
subnetIndex: uint8, slot: Slot] =
let
committees_per_slot = get_committee_count_per_slot(state, epoch, cache)
start_slot = compute_start_slot_at_epoch(epoch)
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
for index in 0'u64 ..< committees_per_slot:
let
idx = index.CommitteeIndex
includedIndices =
toIntSet(get_beacon_committee(state, slot, idx, cache)) *
validator_indices
if includedIndices.len > 0:
yield (
includedIndices, idx,
compute_subnet_for_attestation(committees_per_slot, slot, idx).uint8,
slot)