From 23b504597c837f27ca1ccb7d26abeb97014ff127 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Fri, 6 Dec 2019 13:05:00 +0100 Subject: [PATCH 1/6] initially implement specified attestation aggregation functions and data structures --- .../naive_attestation_aggregation.nim | 28 +++++++++++++++++++ beacon_chain/spec/crypto.nim | 8 +++++- beacon_chain/spec/datatypes.nim | 5 ++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 beacon_chain/naive_attestation_aggregation.nim diff --git a/beacon_chain/naive_attestation_aggregation.nim b/beacon_chain/naive_attestation_aggregation.nim new file mode 100644 index 0000000000..2b327f57f4 --- /dev/null +++ b/beacon_chain/naive_attestation_aggregation.nim @@ -0,0 +1,28 @@ +import + sequtils, + ./spec/[datatypes, crypto, digest, helpers, validator], + ./ssz + +# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection +func get_slot_signature(state: BeaconState, slot: Slot, privkey: ValidatorPrivKey): + ValidatorSig = + # TODO privkey is int in spec, but bls_sign wants a ValidatorPrivKey + let domain = + get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot)) + bls_sign(privkey, hash_tree_root(slot).data, domain) + +# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection +func is_aggregator(state: BeaconState, slot: Slot, index: uint64, + slot_signature: ValidatorSig): bool = + # TODO index is a CommitteeIndex, aka uint64 + var cache = get_empty_per_epoch_cache() + + let + committee = get_beacon_committee(state, slot, index, cache) + modulo = max(1, len(committee) div TARGET_AGGREGATORS_PER_COMMITTEE).uint64 + bytes_to_int(eth2hash(slot_signature.getBytes).data[0..7]) mod modulo == 0 + +# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregate-signature-1 +func get_aggregate_signature(attestations: seq[Attestation]): ValidatorSig = + let signatures = mapIt(attestations, it.signature) + bls_aggregate_signatures(signatures) diff --git a/beacon_chain/spec/crypto.nim b/beacon_chain/spec/crypto.nim index 4bbba19f0a..3d237451b8 100644 --- a/beacon_chain/spec/crypto.nim +++ b/beacon_chain/spec/crypto.nim @@ -151,6 +151,9 @@ func init(T: type VerKey): VerKey = func init(T: type SigKey): SigKey = result.point.inf() +func init(T: type Signature): Signature = + result.point.inf() + func combine*[T](values: openarray[BlsValue[T]]): BlsValue[T] = result = BlsValue[T](kind: Real, blsValue: T.init()) @@ -165,6 +168,10 @@ func combine*[T](x: var BlsValue[T], other: BlsValue[T]) = func bls_aggregate_pubkeys*(keys: openArray[ValidatorPubKey]): ValidatorPubKey = keys.combine() +# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/bls_signature.md#bls_aggregate_signatures +func bls_aggregate_signatures*(keys: openArray[ValidatorSig]): ValidatorSig = + keys.combine() + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/bls_signature.md#bls_verify func bls_verify*( pubkey: ValidatorPubKey, msg: openArray[byte], sig: ValidatorSig, @@ -314,4 +321,3 @@ proc toGaugeValue*(hash: Eth2Digest): int64 = template fromSszBytes*(T: type BlsValue, bytes: openarray[byte]): auto = fromBytes(T, bytes) - diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index e5a316bfc2..8c30eb1072 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -320,6 +320,11 @@ type deposit_count*: uint64 block_hash*: Eth2Digest + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregateandproof + AggregateAndProof* = object + index: uint64 + selection_proof: ValidatorSig + # TODO to be replaced with some magic hash caching HashedBeaconState* = object data*: BeaconState From 641aaf5cdcf73d6cc23f0cc7954c9cea909280f1 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Fri, 6 Dec 2019 16:05:11 +0100 Subject: [PATCH 2/6] outline general flow of naive attestation aggregation --- .../naive_attestation_aggregation.nim | 56 ++++++++++++++++++- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/beacon_chain/naive_attestation_aggregation.nim b/beacon_chain/naive_attestation_aggregation.nim index 2b327f57f4..3384d5277e 100644 --- a/beacon_chain/naive_attestation_aggregation.nim +++ b/beacon_chain/naive_attestation_aggregation.nim @@ -1,8 +1,21 @@ +# beacon_chain +# Copyright (c) 2018-2019 Status Research & Development GmbH +# Licensed and distributed under either of +# * MIT license (license terms in the root directory or at http://opensource.org/licenses/MIT). +# * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). +# at your option. This file may not be copied, modified, or distributed except according to those terms. + import - sequtils, + options, sequtils, ./spec/[datatypes, crypto, digest, helpers, validator], ./ssz +# TODO add tests +# TODO gossipsub validation lives somewhere, maybe here +# https://github.com/status-im/nim-beacon-chain/issues/122#issuecomment-562479965 +# it's conceptually separate, sort of, but depends on beaconstate, so isn't a +# pure libp2p thing. + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection func get_slot_signature(state: BeaconState, slot: Slot, privkey: ValidatorPrivKey): ValidatorSig = @@ -23,6 +36,45 @@ func is_aggregator(state: BeaconState, slot: Slot, index: uint64, bytes_to_int(eth2hash(slot_signature.getBytes).data[0..7]) mod modulo == 0 # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregate-signature-1 -func get_aggregate_signature(attestations: seq[Attestation]): ValidatorSig = +func get_aggregate_signature(attestations: openarray[Attestation]): ValidatorSig = let signatures = mapIt(attestations, it.signature) bls_aggregate_signatures(signatures) + +func should_aggregate( + state: BeaconState, index: uint64, privkey: ValidatorPrivKey): bool = + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection + # A validator is selected to aggregate based upon the return value of + # is_aggregator(). + let slot = state.slot - 1 # TODO this isn't correct + + # the "Construct aggregate" section seems to suggest it's from a previous + # slot. + doAssert slot < state.slot + is_aggregator(state, slot, index, get_slot_signature(state, slot, privkey)) + +func aggregate_attestations_naively*( + state: BeaconState, index: uint64, privkey: ValidatorPrivKey): + Option[Attestation] = + # Keep this code opt-in with clean entry point; if there's a part that + # mutates state, split that off and keep this separate. + # TODO alias CommitteeIndex to actual type then convert various uint64's here + # to it + + # If the validator is selected to aggregate (`is_aggregator()`), they + # construct an aggregate attestation + if not should_aggregate(state, index, privkey): + return none(Attestation) + + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#construct-aggregate + # Collect attestations seen via gossip during the slot that have an + # equivalent attestation_data to that constructed by the validator, + # and create an aggregate_attestation: Attestation with the following fields. + var aggregate_attestation = Attestation( + ) + + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregate-signature-1 + # Set aggregate_attestation.signature = aggregate_signature where + # aggregate_signature is obtained from get_aggregate_signature(...). + aggregate_attestation.signature = get_aggregate_signature([]) + + some(aggregate_attestation) From 369bb9ab6ab27e26a21001b9d46183b10002e7f8 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Fri, 6 Dec 2019 17:01:48 +0100 Subject: [PATCH 3/6] fix AggregateAndProof definition --- beacon_chain/naive_attestation_aggregation.nim | 1 + beacon_chain/spec/datatypes.nim | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/beacon_chain/naive_attestation_aggregation.nim b/beacon_chain/naive_attestation_aggregation.nim index 3384d5277e..86df98ea33 100644 --- a/beacon_chain/naive_attestation_aggregation.nim +++ b/beacon_chain/naive_attestation_aggregation.nim @@ -59,6 +59,7 @@ func aggregate_attestations_naively*( # mutates state, split that off and keep this separate. # TODO alias CommitteeIndex to actual type then convert various uint64's here # to it + # TODO return Option[AggregateAndProof] maybe # If the validator is selected to aggregate (`is_aggregator()`), they # construct an aggregate attestation diff --git a/beacon_chain/spec/datatypes.nim b/beacon_chain/spec/datatypes.nim index 8c30eb1072..706670eeb0 100644 --- a/beacon_chain/spec/datatypes.nim +++ b/beacon_chain/spec/datatypes.nim @@ -322,8 +322,9 @@ type # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregateandproof AggregateAndProof* = object - index: uint64 - selection_proof: ValidatorSig + aggregator_index*: uint64 + aggregate*: Attestation + selection_proof*: ValidatorSig # TODO to be replaced with some magic hash caching HashedBeaconState* = object From 65c7c8128dfa76c3dde5ad04324e55fb15ffaf79 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 9 Dec 2019 21:24:39 +0100 Subject: [PATCH 4/6] roadmap rest of naive attestation aggregation --- ...gation.nim => attestation_aggregation.nim} | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) rename beacon_chain/{naive_attestation_aggregation.nim => attestation_aggregation.nim} (53%) diff --git a/beacon_chain/naive_attestation_aggregation.nim b/beacon_chain/attestation_aggregation.nim similarity index 53% rename from beacon_chain/naive_attestation_aggregation.nim rename to beacon_chain/attestation_aggregation.nim index 86df98ea33..b7232cfb9b 100644 --- a/beacon_chain/naive_attestation_aggregation.nim +++ b/beacon_chain/attestation_aggregation.nim @@ -5,10 +5,30 @@ # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. +# Mostly TODOs at this point, but basically, called every 1/3 + expected +# network + attestation pool lag to collect attestations, if one wants a +# maximally updated pool (but could also just only aggregate to previous +# slots, safer probably), check for some fixed slot offset to past for a +# locally attached validator (externally-to-this-module supplied), run a +# set of supplied algorithms (already implemented) to check if that is a +# matching pair. Aggregation itself's already implemented in attestation +# pool, so this is mostly (a) selection of when to aggregate, (b) change +# of validation, (c) and specific sending deadlines with slots. +# +# The other part is arguably part of attestation pool -- the validation's +# something that should be happing on receipt, not aggregation per se. In +# that part, check that messages conform -- so, check for each type +# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/networking/p2p-interface.md#topics-and-messages +# specifies. So by the time this calls attestation pool, all validation's +# already done. +# +# Finally, some of the filtering's libp2p stuff. Consistency checks between +# topic/message types and GOSSIP_MAX_SIZE. + import options, sequtils, ./spec/[datatypes, crypto, digest, helpers, validator], - ./ssz + ./attestation_pool, ./beacon_node_types, ./ssz # TODO add tests # TODO gossipsub validation lives somewhere, maybe here @@ -45,24 +65,36 @@ func should_aggregate( # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection # A validator is selected to aggregate based upon the return value of # is_aggregator(). - let slot = state.slot - 1 # TODO this isn't correct - - # the "Construct aggregate" section seems to suggest it's from a previous - # slot. + #const use_offset = ATTESTATION_PROPAGATION_SLOT_RANGE - 3 + #TODO implement this constant + # just pick some fixed time offset in past after which we should have gotten + # all attestations -- in principle, if we trust that we get attestations the + # slot get sent within SECONDS_PER_SLOT / 3, can use current slot, but seems + # risky. initally aim for one or two slots back to try to be currentand keep + # away from anything too near edge of ATTESTATION_PROPAGATION_SLOT_RANGE. + # + # static: + # doAssert use_offset > 0 + let slot = state.slot - 2 + if slot < 0: + return + # TODO aggregate_and_proof.aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate_and_proof.aggregate.data.slot doAssert slot < state.slot is_aggregator(state, slot, index, get_slot_signature(state, slot, privkey)) -func aggregate_attestations_naively*( - state: BeaconState, index: uint64, privkey: ValidatorPrivKey): - Option[Attestation] = +proc aggregate_attestations*( + pool: AttestationPool, state: BeaconState, index: uint64, + privkey: ValidatorPrivKey): Option[Attestation] = # Keep this code opt-in with clean entry point; if there's a part that # mutates state, split that off and keep this separate. # TODO alias CommitteeIndex to actual type then convert various uint64's here - # to it - # TODO return Option[AggregateAndProof] maybe + # TODO return Option[AggregateAndProof] # If the validator is selected to aggregate (`is_aggregator()`), they # construct an aggregate attestation + let slot = state.slot - 2 + # TODO as before, check sanity here against (1) constant ATTESTATION_PROPAGATION_SLOT_RANGE + # and (2) genesis slot if not should_aggregate(state, index, privkey): return none(Attestation) @@ -70,12 +102,15 @@ func aggregate_attestations_naively*( # Collect attestations seen via gossip during the slot that have an # equivalent attestation_data to that constructed by the validator, # and create an aggregate_attestation: Attestation with the following fields. - var aggregate_attestation = Attestation( - ) - - # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregate-signature-1 - # Set aggregate_attestation.signature = aggregate_signature where - # aggregate_signature is obtained from get_aggregate_signature(...). - aggregate_attestation.signature = get_aggregate_signature([]) + # TODO set slot here and tell should_aggregate + let attestations = getAttestationsForBlock(pool, state, slot) + # TODO it's a greedy set packing algorithm to avoid overlap + # make sure this works here or change it (both places maybe?) + # TODO scan for matching attestationdata; already aggregated + # SECONDS_PER_SLOT / 3 in: initial aggregation TODO adjust this elsewhere + # SECONDS_PER_SLOT * 2 / 3 + # TODO obviously wrong, but define check against attestation_data first + # also, this should be AggregateAndProof apparently, indeed. + let aggregate_attestation = attestations[0] some(aggregate_attestation) From d0b23534232884766f6d2494470fef9674fd85bb Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 10 Dec 2019 14:44:22 +0100 Subject: [PATCH 5/6] fix return type to properly construct AggregateAndProof; check ATTESTATION_PROPAGATION_SLOT_RANGE as required, maintaining consistent slot offset --- beacon_chain/attestation_aggregation.nim | 84 +++++++++--------------- 1 file changed, 31 insertions(+), 53 deletions(-) diff --git a/beacon_chain/attestation_aggregation.nim b/beacon_chain/attestation_aggregation.nim index b7232cfb9b..99cdd56090 100644 --- a/beacon_chain/attestation_aggregation.nim +++ b/beacon_chain/attestation_aggregation.nim @@ -26,20 +26,24 @@ # topic/message types and GOSSIP_MAX_SIZE. import - options, sequtils, + options, ./spec/[datatypes, crypto, digest, helpers, validator], ./attestation_pool, ./beacon_node_types, ./ssz -# TODO add tests # TODO gossipsub validation lives somewhere, maybe here +# TODO add tests, especially for validation # https://github.com/status-im/nim-beacon-chain/issues/122#issuecomment-562479965 # it's conceptually separate, sort of, but depends on beaconstate, so isn't a # pure libp2p thing. +const + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/networking/p2p-interface.md#configuration + ATTESTATION_PROPAGATION_SLOT_RANGE* = 32 + GOSSIP_MAX_SIZE = 1048576 + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection func get_slot_signature(state: BeaconState, slot: Slot, privkey: ValidatorPrivKey): ValidatorSig = - # TODO privkey is int in spec, but bls_sign wants a ValidatorPrivKey let domain = get_domain(state, DOMAIN_BEACON_ATTESTER, compute_epoch_at_slot(slot)) bls_sign(privkey, hash_tree_root(slot).data, domain) @@ -55,62 +59,36 @@ func is_aggregator(state: BeaconState, slot: Slot, index: uint64, modulo = max(1, len(committee) div TARGET_AGGREGATORS_PER_COMMITTEE).uint64 bytes_to_int(eth2hash(slot_signature.getBytes).data[0..7]) mod modulo == 0 -# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregate-signature-1 -func get_aggregate_signature(attestations: openarray[Attestation]): ValidatorSig = - let signatures = mapIt(attestations, it.signature) - bls_aggregate_signatures(signatures) - -func should_aggregate( - state: BeaconState, index: uint64, privkey: ValidatorPrivKey): bool = - # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection - # A validator is selected to aggregate based upon the return value of - # is_aggregator(). - #const use_offset = ATTESTATION_PROPAGATION_SLOT_RANGE - 3 - #TODO implement this constant - # just pick some fixed time offset in past after which we should have gotten - # all attestations -- in principle, if we trust that we get attestations the - # slot get sent within SECONDS_PER_SLOT / 3, can use current slot, but seems - # risky. initally aim for one or two slots back to try to be currentand keep - # away from anything too near edge of ATTESTATION_PROPAGATION_SLOT_RANGE. - # - # static: - # doAssert use_offset > 0 - let slot = state.slot - 2 - if slot < 0: - return - # TODO aggregate_and_proof.aggregate.data.slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= current_slot >= aggregate_and_proof.aggregate.data.slot - doAssert slot < state.slot - is_aggregator(state, slot, index, get_slot_signature(state, slot, privkey)) - proc aggregate_attestations*( pool: AttestationPool, state: BeaconState, index: uint64, - privkey: ValidatorPrivKey): Option[Attestation] = - # Keep this code opt-in with clean entry point; if there's a part that - # mutates state, split that off and keep this separate. + privkey: ValidatorPrivKey): Option[AggregateAndProof] = # TODO alias CommitteeIndex to actual type then convert various uint64's here - # TODO return Option[AggregateAndProof] - # If the validator is selected to aggregate (`is_aggregator()`), they - # construct an aggregate attestation - let slot = state.slot - 2 - # TODO as before, check sanity here against (1) constant ATTESTATION_PROPAGATION_SLOT_RANGE - # and (2) genesis slot - if not should_aggregate(state, index, privkey): - return none(Attestation) + let + slot = state.slot - 2 + slot_signature = get_slot_signature(state, slot, privkey) + + if slot < 0: + return none(AggregateAndProof) + doAssert slot + ATTESTATION_PROPAGATION_SLOT_RANGE >= state.slot + doAssert state.slot >= slot + + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection + if not is_aggregator(state, slot, index, slot_signature): + return none(AggregateAndProof) # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#construct-aggregate - # Collect attestations seen via gossip during the slot that have an - # equivalent attestation_data to that constructed by the validator, - # and create an aggregate_attestation: Attestation with the following fields. - # TODO set slot here and tell should_aggregate let attestations = getAttestationsForBlock(pool, state, slot) - # TODO it's a greedy set packing algorithm to avoid overlap - # make sure this works here or change it (both places maybe?) - # TODO scan for matching attestationdata; already aggregated + + var correct_attestation_data: AttestationData + + for attestation in attestations: + if attestation.data == correct_attestation_data: + return some(AggregateAndProof( + aggregator_index: index, + aggregate: attestation, + selection_proof: slot_signature)) + + none(AggregateAndProof) # SECONDS_PER_SLOT / 3 in: initial aggregation TODO adjust this elsewhere # SECONDS_PER_SLOT * 2 / 3 - - # TODO obviously wrong, but define check against attestation_data first - # also, this should be AggregateAndProof apparently, indeed. - let aggregate_attestation = attestations[0] - some(aggregate_attestation) From 87d0f58c0b726bd3209872f19166686fc1143a3f Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Tue, 10 Dec 2019 15:21:07 +0100 Subject: [PATCH 6/6] properly construct attestation data for selected slot --- beacon_chain/attestation_aggregation.nim | 38 ++++++++++-------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/beacon_chain/attestation_aggregation.nim b/beacon_chain/attestation_aggregation.nim index 99cdd56090..b9c58520d1 100644 --- a/beacon_chain/attestation_aggregation.nim +++ b/beacon_chain/attestation_aggregation.nim @@ -5,15 +5,9 @@ # * Apache v2 license (license terms in the root directory or at http://www.apache.org/licenses/LICENSE-2.0). # at your option. This file may not be copied, modified, or distributed except according to those terms. -# Mostly TODOs at this point, but basically, called every 1/3 + expected -# network + attestation pool lag to collect attestations, if one wants a -# maximally updated pool (but could also just only aggregate to previous -# slots, safer probably), check for some fixed slot offset to past for a -# locally attached validator (externally-to-this-module supplied), run a -# set of supplied algorithms (already implemented) to check if that is a -# matching pair. Aggregation itself's already implemented in attestation -# pool, so this is mostly (a) selection of when to aggregate, (b) change -# of validation, (c) and specific sending deadlines with slots. +# Have an an aggregated aggregation ready for broadcast at +# SECONDS_PER_SLOT * 2 / 3, i.e. 2/3 through relevant slot +# intervals. # # The other part is arguably part of attestation pool -- the validation's # something that should be happing on receipt, not aggregation per se. In @@ -23,23 +17,21 @@ # already done. # # Finally, some of the filtering's libp2p stuff. Consistency checks between -# topic/message types and GOSSIP_MAX_SIZE. +# topic/message types and GOSSIP_MAX_SIZE -- mostly doesn't belong here, so +# while TODO, isn't TODO for this module. import options, - ./spec/[datatypes, crypto, digest, helpers, validator], + ./spec/[beaconstate, datatypes, crypto, digest, helpers, validator], ./attestation_pool, ./beacon_node_types, ./ssz # TODO gossipsub validation lives somewhere, maybe here # TODO add tests, especially for validation # https://github.com/status-im/nim-beacon-chain/issues/122#issuecomment-562479965 -# it's conceptually separate, sort of, but depends on beaconstate, so isn't a -# pure libp2p thing. const # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/networking/p2p-interface.md#configuration - ATTESTATION_PROPAGATION_SLOT_RANGE* = 32 - GOSSIP_MAX_SIZE = 1048576 + ATTESTATION_PROPAGATION_SLOT_RANGE = 32 # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregation-selection func get_slot_signature(state: BeaconState, slot: Slot, privkey: ValidatorPrivKey): @@ -77,18 +69,18 @@ proc aggregate_attestations*( if not is_aggregator(state, slot, index, slot_signature): return none(AggregateAndProof) - # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#construct-aggregate - let attestations = getAttestationsForBlock(pool, state, slot) - - var correct_attestation_data: AttestationData + let attestation_data = + makeAttestationData(state, slot, index, get_block_root_at_slot(state, slot)) - for attestation in attestations: - if attestation.data == correct_attestation_data: + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#construct-aggregate + for attestation in getAttestationsForBlock(pool, state, slot): + if attestation.data == attestation_data: + # https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/validator/0_beacon-chain-validator.md#aggregateandproof return some(AggregateAndProof( aggregator_index: index, aggregate: attestation, selection_proof: slot_signature)) + # TODO in catch-up mode, we could get here, so probably shouldn't assert + doAssert false none(AggregateAndProof) - # SECONDS_PER_SLOT / 3 in: initial aggregation TODO adjust this elsewhere - # SECONDS_PER_SLOT * 2 / 3