diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index c417d4dca..5f5f7435b 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -359,12 +359,11 @@ proc installAttestationSubnetHandlers(node: BeaconNode, subnets: set[uint8]) await allFutures(attestationSubscriptions) -proc updateStabilitySubnetMetadata( - node: BeaconNode, stabilitySubnets: set[uint8]) = +proc updateStabilitySubnetMetadata(node: BeaconNode, stabilitySubnet: uint64) = # 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 in stabilitySubnets) + node.network.metadata.attnets[subnet] = (subnet == stabilitySubnet) # 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 @@ -375,11 +374,7 @@ proc updateStabilitySubnetMetadata( # 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 subnets changed, updated ENR attnets", stabilitySubnets - -func getStabilitySubnets(stabilitySubnets: auto): set[uint8] = - for subnetInfo in stabilitySubnets: - result.incl subnetInfo.subnet + debug "Stability subnet changed, updated ENR attnets", stabilitySubnet proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} = static: doAssert RANDOM_SUBNETS_PER_VALIDATOR == 1 @@ -399,8 +394,7 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} = node.chainDag.headState.data.data, attachedValidators, node.attestationSubnets, slot.epoch) - let prevStabilitySubnets = - getStabilitySubnets(node.attestationSubnets.stabilitySubnets) + let prevStabilitySubnet = node.attestationSubnets.stabilitySubnet node.attestationSubnets = newAttestationSubnets debug "Attestation subnets", @@ -409,7 +403,9 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} = node.attestationSubnets.subscribedSubnets[1 - epochParity], upcoming_subnets = node.attestationSubnets.subscribedSubnets[epochParity], new_subnets = newSubnets, - stability_subnets = node.attestationSubnets.stabilitySubnets + stability_subnet = node.attestationSubnets.stabilitySubnet, + stability_subnet_expiration_epoch = + node.attestationSubnets.stabilitySubnetExpirationEpoch block: var unsubscriptions: seq[Future[void]] = @[] @@ -421,11 +417,9 @@ proc cycleAttestationSubnets(node: BeaconNode, slot: Slot) {.async.} = await node.installAttestationSubnetHandlers(newSubnets) - let stabilitySubnets = - getStabilitySubnets(node.attestationSubnets.stabilitySubnets) - - if stabilitySubnets != prevStabilitySubnets: - node.updateStabilitySubnetMetadata(stabilitySubnets) + let stabilitySubnet = node.attestationSubnets.stabilitySubnet + if stabilitySubnet != prevStabilitySubnet: + node.updateStabilitySubnetMetadata(stabilitySubnet) proc getAttestationSubnetHandlers(node: BeaconNode): Future[void] = var initialSubnets: set[uint8] @@ -438,15 +432,11 @@ 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() - 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) + node.updateStabilitySubnetMetadata(node.attestationSubnets.stabilitySubnet) # Sets the "current" and "future" attestation subnets. One of these gets # replaced by get_attestation_subnet_changes() immediately. @@ -475,8 +465,6 @@ 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), diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index deada60c9..766de946e 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -458,7 +458,8 @@ type AttestationSubnets* = object subscribedSubnets*: array[2, set[uint8]] - stabilitySubnets*: seq[tuple[subnet: uint8, expiration: Epoch]] + stabilitySubnet*: uint64 + stabilitySubnetExpirationEpoch*: 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 diff --git a/beacon_chain/spec/network.nim b/beacon_chain/spec/network.nim index d6ced036e..64d6404b3 100644 --- a/beacon_chain/spec/network.nim +++ b/beacon_chain/spec/network.nim @@ -132,20 +132,12 @@ 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 - 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 + let prevStabilitySubnet = {attestationSubnets.stabilitySubnet.uint8} + if epoch >= attestationSubnets.stabilitySubnetExpirationEpoch: + attestationSubnets.stabilitySubnet = + rand(ATTESTATION_SUBNET_COUNT - 1).uint64 + attestationSubnets.stabilitySubnetExpirationEpoch = + epoch + getStabilitySubnetLength() var nextEpochSubnets: set[uint8] for it in get_committee_assignments( @@ -156,15 +148,16 @@ proc get_attestation_subnet_changes*( let epochParity = epoch mod 2 + stabilitySet = {attestationSubnets.stabilitySubnet.uint8} currentEpochSubnets = attestationSubnets.subscribedSubnets[1 - epochParity] expiringSubnets = - (prevStabilitySubnets + + (prevStabilitySubnet + attestationSubnets.subscribedSubnets[epochParity]) - nextEpochSubnets - currentEpochSubnets - stabilitySet newSubnets = (nextEpochSubnets + stabilitySet) - - (currentEpochSubnets + prevStabilitySubnets) + (currentEpochSubnets + prevStabilitySubnet) doAssert newSubnets.len <= attachedValidators.len + 1