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) epochInfo = blck.getEpochInfo(state)
requiredSubnetIndex = requiredSubnetIndex =
compute_subnet_for_attestation( 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: if requiredSubnetIndex != topicCommitteeIndex:
debug "isValidAttestation: attestation's committee index not for the correct subnet", 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 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/blob/v0.12.1/specs/phase0/validator.md#broadcast-attestation
# https://github.com/ethereum/eth2.0-specs/pull/1876
func compute_subnet_for_attestation*( 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. # Compute the correct subnet for an attestation for Phase 0.
# Note, this mimics expected Phase 1 behavior where attestations will be # Note, this mimics expected Phase 1 behavior where attestations will be
# mapped to their shard subnet. # 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 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 = 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 # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#broadcast-attestation
func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64): func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64):
string = string =
# This is for subscribing or broadcasting manually to a known index. # This is for subscribing or broadcasting manually to a known index.
doAssert subnetIndex < ATTESTATION_SUBNET_COUNT
try: try:
&"/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz" &"/eth2/{$forkDigest}/beacon_attestation_{subnetIndex}/ssz"
except ValueError as e: 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 = func getAttestationTopic*(forkDigest: ForkDigest, attestation: Attestation, num_active_validators: uint64): string =
getAttestationTopic( getAttestationTopic(
forkDigest, 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 import
algorithm, options, sequtils, math, tables, sets, 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_shuffled_index
# https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/beacon-chain.md#compute_committee # 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 # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#validator-assignments
func get_committee_assignment*( func get_committee_assignment*(
state: BeaconState, epoch: Epoch, state: BeaconState, epoch: Epoch,
validator_indices: HashSet[ValidatorIndex]): validator_index: ValidatorIndex):
Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] {.used.} = Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] =
# Return the committee assignment in the ``epoch`` for ``validator_index``. # Return the committee assignment in the ``epoch`` for ``validator_index``.
# ``assignment`` returned is a tuple of the following form: # ``assignment`` returned is a tuple of the following form:
# * ``assignment[0]`` is the list of validators in the committee # * ``assignment[0]`` is the list of validators in the committee
# * ``assignment[1]`` is the index to which the committee is assigned # * ``assignment[1]`` is the index to which the committee is assigned
# * ``assignment[2]`` is the slot at which the committee is assigned # * ``assignment[2]`` is the slot at which the committee is assigned
# Return None if no assignment. # 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 let next_epoch = get_current_epoch(state) + 1
doAssert epoch <= next_epoch doAssert epoch <= next_epoch
@ -295,10 +292,32 @@ func get_committee_assignment*(
for index in 0 ..< get_committee_count_at_slot(state, slot): for index in 0 ..< get_committee_count_at_slot(state, slot):
let idx = index.CommitteeIndex let idx = index.CommitteeIndex
let committee = get_beacon_committee(state, slot, idx, cache) 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)) return some((committee, idx, slot))
none(tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: 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 # https://github.com/ethereum/eth2.0-specs/blob/v0.12.1/specs/phase0/validator.md#validator-assignments
func is_proposer( func is_proposer(
state: BeaconState, validator_index: ValidatorIndex): bool {.used.} = state: BeaconState, validator_index: ValidatorIndex): bool {.used.} =

View File

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

View File

@ -425,7 +425,7 @@ proc broadcastAggregatedAttestations(
proc handleValidatorDuties*( proc handleValidatorDuties*(
node: BeaconNode, lastSlot, slot: Slot) {.async.} = 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() var head = node.updateHead()
if node.attachedValidators.count == 0: if node.attachedValidators.count == 0:
# Nothing to do because we have no validator attached # 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/[beacon_chain_db, block_pool, extras],
../beacon_chain/spec/[crypto, datatypes, digest, helpers, ../beacon_chain/spec/[crypto, datatypes, digest, helpers,
state_transition, validator, presets], state_transition, validator, presets],
../beacon_chain/sszdump, ../beacon_chain/ssz/merkleization, ../beacon_chain/sszdump, ../research/simutils,
../research/simutils,
eth/db/[kvstore, kvstore_sqlite3] eth/db/[kvstore, kvstore_sqlite3]
type Timers = enum type Timers = enum

View File

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

View File

@ -22,7 +22,7 @@ proc addMockAttestations*(
sufficient_support = false sufficient_support = false
) = ) =
# We must be at the end of the epoch # 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 # Alias the attestations container
var attestations: ptr seq[PendingAttestation] var attestations: ptr seq[PendingAttestation]