mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 04:47:18 +00:00
77 lines
2.7 KiB
Go
77 lines
2.7 KiB
Go
|
package attestationutil
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"sort"
|
||
|
|
||
|
"github.com/pkg/errors"
|
||
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
||
|
"github.com/prysmaticlabs/go-bitfield"
|
||
|
"go.opencensus.io/trace"
|
||
|
)
|
||
|
|
||
|
// ConvertToIndexed converts attestation to (almost) indexed-verifiable form.
|
||
|
//
|
||
|
// Note about spec pseudocode definition. The state was used by get_attesting_indices to determine
|
||
|
// the attestation committee. Now that we provide this as an argument, we no longer need to provide
|
||
|
// a state.
|
||
|
//
|
||
|
// Spec pseudocode definition:
|
||
|
// def get_indexed_attestation(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
|
||
|
// """
|
||
|
// Return the indexed attestation corresponding to ``attestation``.
|
||
|
// """
|
||
|
// attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bits)
|
||
|
//
|
||
|
// return IndexedAttestation(
|
||
|
// attesting_indices=sorted(attesting_indices),
|
||
|
// data=attestation.data,
|
||
|
// signature=attestation.signature,
|
||
|
// )
|
||
|
func ConvertToIndexed(ctx context.Context, attestation *ethpb.Attestation, committee []uint64) (*ethpb.IndexedAttestation, error) {
|
||
|
ctx, span := trace.StartSpan(ctx, "core.ConvertToIndexed")
|
||
|
defer span.End()
|
||
|
|
||
|
attIndices, err := AttestingIndices(attestation.AggregationBits, committee)
|
||
|
if err != nil {
|
||
|
return nil, errors.Wrap(err, "could not get attesting indices")
|
||
|
}
|
||
|
|
||
|
sort.Slice(attIndices, func(i, j int) bool {
|
||
|
return attIndices[i] < attIndices[j]
|
||
|
})
|
||
|
inAtt := ðpb.IndexedAttestation{
|
||
|
Data: attestation.Data,
|
||
|
Signature: attestation.Signature,
|
||
|
AttestingIndices: attIndices,
|
||
|
}
|
||
|
return inAtt, nil
|
||
|
}
|
||
|
|
||
|
// AttestingIndices returns the attesting participants indices from the attestation data. The
|
||
|
// committee is provided as an argument rather than a direct implementation from the spec definition.
|
||
|
// Having the committee as an argument allows for re-use of beacon committees when possible.
|
||
|
//
|
||
|
// Spec pseudocode definition:
|
||
|
// def get_attesting_indices(state: BeaconState,
|
||
|
// data: AttestationData,
|
||
|
// bits: Bitlist[MAX_VALIDATORS_PER_COMMITTEE]) -> Set[ValidatorIndex]:
|
||
|
// """
|
||
|
// Return the set of attesting indices corresponding to ``data`` and ``bits``.
|
||
|
// """
|
||
|
// committee = get_beacon_committee(state, data.slot, data.index)
|
||
|
// return set(index for i, index in enumerate(committee) if bits[i])
|
||
|
func AttestingIndices(bf bitfield.Bitfield, committee []uint64) ([]uint64, error) {
|
||
|
indices := make([]uint64, 0, len(committee))
|
||
|
indicesSet := make(map[uint64]bool)
|
||
|
for i, idx := range committee {
|
||
|
if !indicesSet[idx] {
|
||
|
if bf.BitAt(uint64(i)) {
|
||
|
indices = append(indices, idx)
|
||
|
}
|
||
|
}
|
||
|
indicesSet[idx] = true
|
||
|
}
|
||
|
return indices, nil
|
||
|
}
|