diff --git a/beacon_chain/spec/beaconstate.nim b/beacon_chain/spec/beaconstate.nim index 1aa9ae4f0..81a2d31cf 100644 --- a/beacon_chain/spec/beaconstate.nim +++ b/beacon_chain/spec/beaconstate.nim @@ -8,7 +8,7 @@ {.push raises: [Defect].} import - std/[algorithm, intsets, math, options, sequtils, tables], + std/[algorithm, collections/heapqueue, math, options, sequtils, tables], stew/assign2, json_serialization/std/sets, chronicles, @@ -475,35 +475,12 @@ proc is_valid_indexed_attestation*( ok() -# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_attesting_indices -iterator get_attesting_indices*(bits: CommitteeValidatorsBits, - committee: openArray[ValidatorIndex]): - ValidatorIndex = - if bits.len == committee.len: - for i, index in committee: - if bits[i]: - yield index - else: - # This shouldn't happen if one begins with a valid BeaconState and applies - # valid updates, but one can construct a BeaconState where it does. Do not - # do anything here since the PendingAttestation wouldn't have made it past - # https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#attestations - # which checks len(attestation.aggregation_bits) == len(committee) that in - # nimbus-eth2 lives in check_attestation(...). - # Addresses https://github.com/status-im/nimbus-eth2/issues/922 - - trace "get_attesting_indices: inconsistent aggregation and committee length" - -func get_attesting_indices*(bits: CommitteeValidatorsBits, - committee: openArray[ValidatorIndex]): IntSet = - for idx in get_attesting_indices(bits, committee): - result.incl idx.int - # https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_attesting_indices iterator get_attesting_indices*(state: BeaconState, data: AttestationData, bits: CommitteeValidatorsBits, cache: var StateCache): ValidatorIndex = + ## Return the set of attesting indices corresponding to ``data`` and ``bits``. if bits.lenu64 != get_beacon_committee_len(state, data.slot, data.index.CommitteeIndex, cache): trace "get_attesting_indices: inconsistent aggregation and committee length" else: @@ -513,28 +490,30 @@ iterator get_attesting_indices*(state: BeaconState, yield index inc i -# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_attesting_indices -func get_attesting_indices*(state: BeaconState, - data: AttestationData, - bits: CommitteeValidatorsBits, - cache: var StateCache): IntSet = - # Return the set of attesting indices corresponding to ``data`` and ``bits``. +iterator get_sorted_attesting_indices*(state: BeaconState, + data: AttestationData, + bits: CommitteeValidatorsBits, + cache: var StateCache): ValidatorIndex = + var heap = initHeapQueue[ValidatorIndex]() for index in get_attesting_indices(state, data, bits, cache): - result.incl index.int + heap.push(index) + + while heap.len > 0: + yield heap.pop() + +func get_sorted_attesting_indices_list*( + state: BeaconState, data: AttestationData, bits: CommitteeValidatorsBits, + cache: var StateCache): List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE] = + for index in get_sorted_attesting_indices(state, data, bits, cache): + result.add index.uint64 # https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/beacon-chain.md#get_indexed_attestation func get_indexed_attestation(state: BeaconState, attestation: Attestation, cache: var StateCache): IndexedAttestation = ## Return the indexed attestation corresponding to ``attestation``. - let - attesting_indices = - get_attesting_indices( - state, attestation.data, attestation.aggregation_bits, cache) - IndexedAttestation( - attesting_indices: - List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init( - sorted(mapIt(attesting_indices.toSeq, it.uint64), system.cmp)), + attesting_indices: get_sorted_attesting_indices_list( + state, attestation.data, attestation.aggregation_bits, cache), data: attestation.data, signature: attestation.signature ) @@ -542,15 +521,9 @@ func get_indexed_attestation(state: BeaconState, attestation: Attestation, func get_indexed_attestation(state: BeaconState, attestation: TrustedAttestation, cache: var StateCache): TrustedIndexedAttestation = ## Return the indexed attestation corresponding to ``attestation``. - let - attesting_indices = - get_attesting_indices( - state, attestation.data, attestation.aggregation_bits, cache) - TrustedIndexedAttestation( - attesting_indices: - List[uint64, Limit MAX_VALIDATORS_PER_COMMITTEE].init( - sorted(mapIt(attesting_indices.toSeq, it.uint64), system.cmp)), + attesting_indices: get_sorted_attesting_indices_list( + state, attestation.data, attestation.aggregation_bits, cache), data: attestation.data, signature: attestation.signature ) diff --git a/beacon_chain/spec/network.nim b/beacon_chain/spec/network.nim index c79cdff0a..b727ba362 100644 --- a/beacon_chain/spec/network.nim +++ b/beacon_chain/spec/network.nim @@ -86,6 +86,7 @@ func getAttestationTopic*(forkDigest: ForkDigest, subnetIndex: uint64): except ValueError as e: raiseAssert e.msg +# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#validator-assignments iterator get_committee_assignments*( state: BeaconState, epoch: Epoch, validator_indices: IntSet, diff --git a/beacon_chain/spec/validator.nim b/beacon_chain/spec/validator.nim index 56d88f0ed..80abedc2d 100644 --- a/beacon_chain/spec/validator.nim +++ b/beacon_chain/spec/validator.nim @@ -369,31 +369,3 @@ func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache, slot: func get_beacon_proposer_index*(state: BeaconState, cache: var StateCache): Option[ValidatorIndex] = get_beacon_proposer_index(state, cache, state.slot) - -# https://github.com/ethereum/eth2.0-specs/blob/v1.0.0/specs/phase0/validator.md#validator-assignments -func get_committee_assignment*( - state: BeaconState, epoch: Epoch, - validator_index: ValidatorIndex): - Option[tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]] = - ## Return the committee assignment in the ``epoch`` for ``validator_index``. - ## ``assignment`` returned is a tuple of the following form: - ## * ``assignment[0]`` is the list of validators in the committee - ## * ``assignment[1]`` is the index to which the committee is assigned - ## * ``assignment[2]`` is the slot at which the committee is assigned - ## Return None if no assignment. - let next_epoch = get_current_epoch(state) + 1 - doAssert epoch <= next_epoch - - var cache = StateCache() - - let - start_slot = compute_start_slot_at_epoch(epoch) - committee_count_per_slot = - get_committee_count_per_slot(state, epoch, cache) - for slot in start_slot ..< start_slot + SLOTS_PER_EPOCH: - for index in 0'u64 ..< committee_count_per_slot: - let idx = index.CommitteeIndex - let committee = get_beacon_committee(state, slot, idx, cache) - if validator_index in committee: - return some((committee, idx, slot)) - none(tuple[a: seq[ValidatorIndex], b: CommitteeIndex, c: Slot]) diff --git a/tests/mocking/mock_attestations.nim b/tests/mocking/mock_attestations.nim index dcfb0a7b9..cff17849a 100644 --- a/tests/mocking/mock_attestations.nim +++ b/tests/mocking/mock_attestations.nim @@ -58,16 +58,15 @@ proc mockAttestationData( proc signMockAttestation*(state: BeaconState, attestation: var Attestation) = var cache = StateCache() - let participants = get_attesting_indices( - state, - attestation.data, - attestation.aggregation_bits, - cache - ) var agg {.noInit.}: AggregateSignature var first_iter = true # Can't do while loop on hashset - for validator_index in participants: + for validator_index in get_attesting_indices( + state, + attestation.data, + attestation.aggregation_bits, + cache + ): let sig = get_attestation_signature( state.fork, state.genesis_validators_root, attestation.data, MockPrivKeys[validator_index]