Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initial simple/naive attestation aggregation #629

Merged
merged 6 commits into from
Dec 13, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions beacon_chain/attestation_aggregation.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# 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.

# 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
# 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 -- mostly doesn't belong here, so
# while TODO, isn't TODO for this module.

import
options,
./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

const
# https://github.com/ethereum/eth2.0-specs/blob/v0.9.2/specs/networking/p2p-interface.md#configuration
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):
ValidatorSig =
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

proc aggregate_attestations*(
pool: AttestationPool, state: BeaconState, index: uint64,
privkey: ValidatorPrivKey): Option[AggregateAndProof] =
# TODO alias CommitteeIndex to actual type then convert various uint64's here

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)

let attestation_data =
makeAttestationData(state, slot, index, get_block_root_at_slot(state, slot))

# 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)
8 changes: 7 additions & 1 deletion beacon_chain/spec/crypto.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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())

Expand All @@ -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,
Expand Down Expand Up @@ -314,4 +321,3 @@ proc toGaugeValue*(hash: Eth2Digest): int64 =

template fromSszBytes*(T: type BlsValue, bytes: openarray[byte]): auto =
fromBytes(T, bytes)

6 changes: 6 additions & 0 deletions beacon_chain/spec/datatypes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ 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
aggregator_index*: uint64
aggregate*: Attestation
selection_proof*: ValidatorSig

# TODO to be replaced with some magic hash caching
HashedBeaconState* = object
data*: BeaconState
Expand Down