update compute_subnet_for_attestation() to use https://github.com/ethereum/eth2.0-specs/pull/1876 signature, which isn't in v0.12.1, which works with lookahead (#1346)

This commit is contained in:
tersec 2020-07-22 08:04:21 +00:00 committed by GitHub
parent 4a9a7be271
commit 6b77f3dda5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 47 additions and 25 deletions

View File

@ -171,7 +171,9 @@ proc isValidAttestation*(
epochInfo = blck.getEpochInfo(state)
requiredSubnetIndex =
compute_subnet_for_attestation(
epochInfo.shuffled_active_validator_indices.len.uint64, attestation)
get_committee_count_at_slot(
epochInfo.shuffled_active_validator_indices.len.uint64),
attestation.data.slot, attestation.data.index.CommitteeIndex)
if requiredSubnetIndex != topicCommitteeIndex:
debug "isValidAttestation: attestation's committee index not for the correct subnet",

View File

@ -58,26 +58,27 @@ func getAggregateAndProofsTopic*(forkDigest: ForkDigest): string =
raiseAssert e.msg
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#broadcast-attestation
# https://github.com/ethereum/eth2.0-specs/pull/1876
func compute_subnet_for_attestation*(
num_active_validators: uint64, attestation: Attestation): uint64 =
committees_per_slot: uint64, slot: Slot, committee_index: CommitteeIndex):
uint64 =
# Compute the correct subnet for an attestation for Phase 0.
# Note, this mimics expected Phase 1 behavior where attestations will be
# mapped to their shard subnet.
#
# The spec version has params (state: BeaconState, attestation: Attestation),
# but it's only to call get_committee_count_at_slot(), which needs only epoch
# and the number of active validators.
let
slots_since_epoch_start = attestation.data.slot mod SLOTS_PER_EPOCH
slots_since_epoch_start = slot mod SLOTS_PER_EPOCH
committees_since_epoch_start =
get_committee_count_at_slot(num_active_validators) * slots_since_epoch_start
committees_per_slot * slots_since_epoch_start
(committees_since_epoch_start + attestation.data.index) mod ATTESTATION_SUBNET_COUNT
(committees_since_epoch_start + committee_index.uint64) mod
ATTESTATION_SUBNET_COUNT
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#broadcast-attestation
func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
string =
# This is for subscribing or broadcasting manually to a known index.
doAssert subnetIndex < ATTESTATION_SUBNET_COUNT
try:
&"/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz"
except ValueError as e:
@ -86,4 +87,6 @@ func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
func getAttestationTopic*(forkDigest: ForkDigest, attestation: Attestation, num_active_validators: uint64): string =
getAttestationTopic(
forkDigest,
compute_subnet_for_attestation(num_active_validators, attestation))
compute_subnet_for_attestation(
get_committee_count_at_slot(num_active_validators),
attestation.data.slot, attestation.data.index.CommitteeIndex))

View File

@ -10,7 +10,7 @@
import
algorithm, options, sequtils, math, tables, sets,
./datatypes, ./digest, ./helpers
./datatypes, ./digest, ./helpers, ./network
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_shuffled_index
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_committee
@ -274,17 +274,14 @@ func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache):
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#validator-assignments
func get_committee_assignment*(
state: BeaconState, epoch: Epoch,
validator_indices: HashSet[ValidatorIndex]):
Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] {.used.} =
validator_index: ValidatorIndex):
Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] =
# Return the committee assignment in the ``epoch`` for ``validator_index``.
# ``assignment`` returned is a tuple of the following form:
# * ``assignment[0]`` is the list of validators in the committee
# * ``assignment[1]`` is the index to which the committee is assigned
# * ``assignment[2]`` is the slot at which the committee is assigned
# Return None if no assignment.
#
# Slightly adapted from spec version to support multiple validator indices,
# since each beacon_node supports many validators.
let next_epoch = get_current_epoch(state) + 1
doAssert epoch <= next_epoch
@ -295,10 +292,32 @@ func get_committee_assignment*(
for index in 0 ..< get_committee_count_at_slot(state, slot):
let idx = index.CommitteeIndex
let committee = get_beacon_committee(state, slot, idx, cache)
if not disjoint(validator_indices, toHashSet(committee)):
if validator_index in committee:
return some((committee, idx, slot))
none(tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot])
func get_committee_assignments*(
state: BeaconState, epoch: Epoch,
validator_indices: HashSet[ValidatorIndex]):
seq[tuple[subnetIndex: uint64, slot: Slot]] =
let next_epoch = get_current_epoch(state) + 1
doAssert epoch <= next_epoch
var cache = StateCache()
let start_slot = compute_start_slot_at_epoch(epoch)
# get_committee_count_at_slot is constant throughout an epoch
let committee_count_at_slot = get_committee_count_at_slot(state, start_slot)
for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH:
for index in 0 ..< committee_count_at_slot:
let idx = index.CommitteeIndex
if not disjoint(validator_indices,
get_beacon_committee(state, slot, idx, cache).toHashSet):
result.add(
(compute_subnet_for_attestation(committee_count_at_slot, slot, idx),
slot))
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#validator-assignments
func is_proposer(
state: BeaconState, validator_index: ValidatorIndex): bool {.used.} =

View File

@ -7,7 +7,7 @@
import
# Standard library
tables, strutils, parseutils, sequtils, sets,
tables, strutils, parseutils, sequtils,
# Nimble packages
stew/[byteutils, objects],
@ -356,8 +356,7 @@ proc installValidatorApiHandlers*(rpcServer: RpcServer, node: BeaconNode) =
let idx = state.validators.asSeq.findIt(it.pubKey == pubkey)
if idx == -1:
continue
let ca = state.get_committee_assignment(
epoch, toHashSet([idx.ValidatorIndex]))
let ca = state.get_committee_assignment(epoch, idx.ValidatorIndex)
if ca.isSome:
result.add((public_key: pubkey,
committee_index: ca.get.b,

View File

@ -425,7 +425,7 @@ proc broadcastAggregatedAttestations(
proc handleValidatorDuties*(
node: BeaconNode, lastSlot, slot: Slot) {.async.} =
## Perform validator duties - create blocks, vote and aggreagte existing votes
## Perform validator duties - create blocks, vote and aggregate existing votes
var head = node.updateHead()
if node.attachedValidators.count == 0:
# Nothing to do because we have no validator attached

View File

@ -4,8 +4,7 @@
../beacon_chain/[beacon_chain_db, block_pool, extras],
../beacon_chain/spec/[crypto, datatypes, digest, helpers,
state_transition, validator, presets],
../beacon_chain/sszdump, ../beacon_chain/ssz/merkleization,
../research/simutils,
../beacon_chain/sszdump, ../research/simutils,
eth/db/[kvstore, kvstore_sqlite3]
type Timers = enum

View File

@ -151,7 +151,7 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
flushFile(stdout)
if (state[].data.slot) mod SLOTS_PER_EPOCH == 0:
if (state[].data.slot).isEpoch:
echo &" slot: {shortLog(state[].data.slot)} ",
&"epoch: {shortLog(state[].data.slot.compute_epoch_at_slot)}"

View File

@ -22,7 +22,7 @@ proc addMockAttestations*(
sufficient_support = false
) =
# We must be at the end of the epoch
doAssert (state.slot + 1) mod SLOTS_PER_EPOCH == 0
doAssert (state.slot + 1).isEpoch
# Alias the attestations container
var attestations: ptr seq[PendingAttestation]