have each validator randomly pick a stability subnet, per spec (#2194)

This commit is contained in:
tersec 2020-12-18 15:46:07 +01:00 committed by GitHub
parent 8cc7effe52
commit 048a67d525
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 25 deletions

View File

@ -359,11 +359,12 @@ proc installAttestationSubnetHandlers(node: BeaconNode, subnets: set[uint8])
await allFutures(attestationSubscriptions)
proc updateStabilitySubnetMetadata(node: BeaconNode, stabilitySubnet: uint64) =
proc updateStabilitySubnetMetadata(
node: BeaconNode, stabilitySubnets: set[uint8]) =
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/p2p-interface.md#metadata
node.network.metadata.seq_number += 1
for subnet in 0'u8 ..< ATTESTATION_SUBNET_COUNT:
node.network.metadata.attnets[subnet] = (subnet == stabilitySubnet)
node.network.metadata.attnets[subnet] = (subnet in stabilitySubnets)
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#phase-0-attestation-subnet-stability
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/p2p-interface.md#attestation-subnet-bitfield
@ -374,7 +375,11 @@ proc updateStabilitySubnetMetadata(node: BeaconNode, stabilitySubnet: uint64) =
# be the correct one and the ENR will not increase in size.
warn "Failed to update record on subnet cycle", error = res.error
else:
debug "Stability subnet changed, updated ENR attnets", stabilitySubnet
debug "Stability subnets changed, updated ENR attnets", stabilitySubnets
func getStabilitySubnets(stabilitySubnets: auto): set[uint8] =
for subnetInfo in stabilitySubnets:
result.incl subnetInfo.subnet
proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} =
static: doAssert RANDOM_SUBNETS_PER_VALIDATOR == 1
@ -394,7 +399,8 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} =
node.chainDag.headState.data.data, attachedValidators,
node.attestationSubnets, slot.epoch)
let prevStabilitySubnet = node.attestationSubnets.stabilitySubnet
let prevStabilitySubnets =
getStabilitySubnets(node.attestationSubnets.stabilitySubnets)
node.attestationSubnets = newAttestationSubnets
debug "Attestation subnets",
@ -403,9 +409,7 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} =
node.attestationSubnets.subscribedSubnets[1 - epochParity],
upcoming_subnets = node.attestationSubnets.subscribedSubnets[epochParity],
new_subnets = newSubnets,
stability_subnet = node.attestationSubnets.stabilitySubnet,
stability_subnet_expiration_epoch =
node.attestationSubnets.stabilitySubnetExpirationEpoch
stability_subnets = node.attestationSubnets.stabilitySubnets
block:
var unsubscriptions: seq[Future[void]] = @[]
@ -417,9 +421,11 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} =
await node.installAttestationSubnetHandlers(newSubnets)
let stabilitySubnet = node.attestationSubnets.stabilitySubnet
if stabilitySubnet != prevStabilitySubnet:
node.updateStabilitySubnetMetadata(stabilitySubnet)
let stabilitySubnets =
getStabilitySubnets(node.attestationSubnets.stabilitySubnets)
if stabilitySubnets != prevStabilitySubnets:
node.updateStabilitySubnetMetadata(stabilitySubnets)
proc getAttestationSubnetHandlers(node: BeaconNode): Future[void] =
var initialSubnets: set[uint8]
@ -432,11 +438,15 @@ proc getAttestationSubnetHandlers(node: BeaconNode): Future[void] =
# - Restarting the node with a presistent netkey
# - When going from synced -> syncing -> synced state
let wallEpoch = node.beaconClock.now().slotOrZero().epoch
node.attestationSubnets.stabilitySubnet = rand(ATTESTATION_SUBNET_COUNT - 1).uint64
node.attestationSubnets.stabilitySubnetExpirationEpoch =
wallEpoch + getStabilitySubnetLength()
node.updateStabilitySubnetMetadata(node.attestationSubnets.stabilitySubnet)
doAssert node.attestationSubnets.stabilitySubnets.len == 0
for _ in 0 ..< node.attachedValidators.count:
node.attestationSubnets.stabilitySubnets.add (
subnet: rand(ATTESTATION_SUBNET_COUNT - 1).uint8,
expiration: wallEpoch + getStabilitySubnetLength())
node.updateStabilitySubnetMetadata(
node.attestationSubnets.stabilitySubnets.getStabilitySubnets)
# Sets the "current" and "future" attestation subnets. One of these gets
# replaced by get_attestation_subnet_changes() immediately.
@ -465,6 +475,8 @@ proc removeMessageHandlers(node: BeaconNode): Future[void] =
node.attestationSubnets.subscribedSubnets[1] = {}
doAssert not node.getTopicSubscriptionEnabled()
node.attestationSubnets.stabilitySubnets.setLen(0)
var unsubscriptions = mapIt(
[getBeaconBlocksTopic(node.forkDigest),
getVoluntaryExitsTopic(node.forkDigest),

View File

@ -458,8 +458,7 @@ type
AttestationSubnets* = object
subscribedSubnets*: array[2, set[uint8]]
stabilitySubnet*: uint64
stabilitySubnetExpirationEpoch*: Epoch
stabilitySubnets*: seq[tuple[subnet: uint8, expiration: Epoch]]
# This matches the mutable state of the Solidity deposit contract
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/solidity_deposit_contract/deposit_contract.sol

View File

@ -132,12 +132,20 @@ proc get_attestation_subnet_changes*(
var attestationSubnets = prevAttestationSubnets
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#phase-0-attestation-subnet-stability
let prevStabilitySubnet = {attestationSubnets.stabilitySubnet.uint8}
if epoch >= attestationSubnets.stabilitySubnetExpirationEpoch:
attestationSubnets.stabilitySubnet =
rand(ATTESTATION_SUBNET_COUNT - 1).uint64
attestationSubnets.stabilitySubnetExpirationEpoch =
epoch + getStabilitySubnetLength()
var
prevStabilitySubnets: set[uint8] = {}
stabilitySet: set[uint8] = {}
for i in 0 ..< attestationSubnets.stabilitySubnets.len:
static: doAssert ATTESTATION_SUBNET_COUNT <= high(uint8)
prevStabilitySubnets.incl attestationSubnets.stabilitySubnets[i].subnet
if epoch >= attestationSubnets.stabilitySubnets[i].expiration:
attestationSubnets.stabilitySubnets[i].subnet =
rand(ATTESTATION_SUBNET_COUNT - 1).uint8
attestationSubnets.stabilitySubnets[i].expiration =
epoch + getStabilitySubnetLength()
stabilitySet.incl attestationSubnets.stabilitySubnets[i].subnet
var nextEpochSubnets: set[uint8]
for it in get_committee_assignments(
@ -148,16 +156,15 @@ proc get_attestation_subnet_changes*(
let
epochParity = epoch mod 2
stabilitySet = {attestationSubnets.stabilitySubnet.uint8}
currentEpochSubnets = attestationSubnets.subscribedSubnets[1 - epochParity]
expiringSubnets =
(prevStabilitySubnet +
(prevStabilitySubnets +
attestationSubnets.subscribedSubnets[epochParity]) -
nextEpochSubnets - currentEpochSubnets - stabilitySet
newSubnets =
(nextEpochSubnets + stabilitySet) -
(currentEpochSubnets + prevStabilitySubnet)
(currentEpochSubnets + prevStabilitySubnets)
doAssert newSubnets.len <= attachedValidators.len + 1