mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-26 05:17:22 +00:00
6e2b6229fe
This reverts commit 085b45626e
.
187 lines
6.4 KiB
Go
187 lines
6.4 KiB
Go
package casper
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/params"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared"
|
|
)
|
|
|
|
const bitsInByte = 8
|
|
|
|
// ActiveValidatorIndices filters out active validators based on start and end dynasty
|
|
// and returns their indices in a list.
|
|
func ActiveValidatorIndices(validators []*pb.ValidatorRecord, dynasty uint64) []uint32 {
|
|
var indices []uint32
|
|
for i := 0; i < len(validators); i++ {
|
|
if validators[i].StartDynasty <= dynasty && dynasty < validators[i].EndDynasty {
|
|
indices = append(indices, uint32(i))
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
// ExitedValidatorIndices filters out exited validators based on start and end dynasty
|
|
// and returns their indices in a list.
|
|
func ExitedValidatorIndices(validators []*pb.ValidatorRecord, dynasty uint64) []uint32 {
|
|
var indices []uint32
|
|
for i := 0; i < len(validators); i++ {
|
|
if validators[i].StartDynasty < dynasty && validators[i].EndDynasty <= dynasty {
|
|
indices = append(indices, uint32(i))
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
// QueuedValidatorIndices filters out queued validators based on start and end dynasty
|
|
// and returns their indices in a list.
|
|
func QueuedValidatorIndices(validators []*pb.ValidatorRecord, dynasty uint64) []uint32 {
|
|
var indices []uint32
|
|
for i := 0; i < len(validators); i++ {
|
|
if validators[i].StartDynasty > dynasty {
|
|
indices = append(indices, uint32(i))
|
|
}
|
|
}
|
|
return indices
|
|
}
|
|
|
|
// GetShardAndCommitteesForSlot returns the attester set of a given slot.
|
|
func GetShardAndCommitteesForSlot(shardCommittees []*pb.ShardAndCommitteeArray, lastStateRecalc uint64, slot uint64) (*pb.ShardAndCommitteeArray, error) {
|
|
if lastStateRecalc < params.GetConfig().CycleLength {
|
|
lastStateRecalc = 0
|
|
} else {
|
|
lastStateRecalc = lastStateRecalc - params.GetConfig().CycleLength
|
|
}
|
|
|
|
lowerBound := lastStateRecalc
|
|
upperBound := lastStateRecalc + params.GetConfig().CycleLength*2
|
|
if !(slot >= lowerBound && slot < upperBound) {
|
|
return nil, fmt.Errorf("cannot return attester set of given slot, input slot %v has to be in between %v and %v",
|
|
slot,
|
|
lowerBound,
|
|
upperBound,
|
|
)
|
|
}
|
|
|
|
return shardCommittees[slot-lastStateRecalc], nil
|
|
}
|
|
|
|
// AreAttesterBitfieldsValid validates that the length of the attester bitfield matches the attester indices
|
|
// defined in the Crystallized State.
|
|
func AreAttesterBitfieldsValid(attestation *pb.AggregatedAttestation, attesterIndices []uint32) bool {
|
|
// Validate attester bit field has the correct length.
|
|
if shared.BitLength(len(attesterIndices)) != len(attestation.AttesterBitfield) {
|
|
log.Debugf("attestation has incorrect bitfield length. Found %v, expected %v",
|
|
len(attestation.AttesterBitfield), shared.BitLength(len(attesterIndices)))
|
|
return false
|
|
}
|
|
|
|
// Valid attestation can not have non-zero trailing bits.
|
|
lastBit := len(attesterIndices)
|
|
remainingBits := lastBit % bitsInByte
|
|
if remainingBits == 0 {
|
|
return true
|
|
}
|
|
|
|
for i := 0; i < bitsInByte-remainingBits; i++ {
|
|
if shared.CheckBit(attestation.AttesterBitfield, lastBit+i) {
|
|
log.Debugf("attestation has non-zero trailing bits")
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// ProposerShardAndIndex returns the index and the shardID of a proposer from a given slot.
|
|
func ProposerShardAndIndex(shardCommittees []*pb.ShardAndCommitteeArray, lastStateRecalc uint64, slot uint64) (uint64, uint64, error) {
|
|
slotCommittees, err := GetShardAndCommitteesForSlot(
|
|
shardCommittees,
|
|
lastStateRecalc,
|
|
slot)
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
|
|
proposerShardID := slotCommittees.ArrayShardAndCommittee[0].ShardId
|
|
proposerIndex := slot % uint64(len(slotCommittees.ArrayShardAndCommittee[0].Committee))
|
|
return proposerShardID, proposerIndex, nil
|
|
}
|
|
|
|
// ValidatorIndex returns the index of the validator given an input public key.
|
|
func ValidatorIndex(pubKey []byte, dynasty uint64, validators []*pb.ValidatorRecord) (uint32, error) {
|
|
activeValidators := ActiveValidatorIndices(validators, dynasty)
|
|
|
|
for _, index := range activeValidators {
|
|
if bytes.Equal(validators[index].PublicKey, pubKey) {
|
|
return index, nil
|
|
}
|
|
}
|
|
|
|
return 0, fmt.Errorf("can't find validator index for public key %d", pubKey)
|
|
}
|
|
|
|
// ValidatorShardID returns the shard ID of the validator currently participates in.
|
|
func ValidatorShardID(pubKey []byte, dynasty uint64, validators []*pb.ValidatorRecord, shardCommittees []*pb.ShardAndCommitteeArray) (uint64, error) {
|
|
index, err := ValidatorIndex(pubKey, dynasty, validators)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
for _, slotCommittee := range shardCommittees {
|
|
for _, committee := range slotCommittee.ArrayShardAndCommittee {
|
|
for _, validator := range committee.Committee {
|
|
if validator == index {
|
|
return committee.ShardId, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0, fmt.Errorf("can't find shard ID for validator with public key %x", pubKey)
|
|
}
|
|
|
|
// ValidatorSlotAndResponsibility returns a validator's assingned slot number
|
|
// and whether it should act as an attester or proposer.
|
|
func ValidatorSlotAndResponsibility(pubKey []byte, dynasty uint64, validators []*pb.ValidatorRecord, shardCommittees []*pb.ShardAndCommitteeArray) (uint64, string, error) {
|
|
index, err := ValidatorIndex(pubKey, dynasty, validators)
|
|
if err != nil {
|
|
return 0, "", err
|
|
}
|
|
|
|
for slot, slotCommittee := range shardCommittees {
|
|
for i, committee := range slotCommittee.ArrayShardAndCommittee {
|
|
for v, validator := range committee.Committee {
|
|
if i == 0 && v == slot%len(committee.Committee) && validator == index {
|
|
return uint64(slot), "proposer", nil
|
|
}
|
|
if validator == index {
|
|
return uint64(slot), "attester", nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0, "", fmt.Errorf("can't find slot number for validator with public key %d", pubKey)
|
|
}
|
|
|
|
// TotalActiveValidatorDeposit returns the total deposited amount in wei for all active validators.
|
|
func TotalActiveValidatorDeposit(dynasty uint64, validators []*pb.ValidatorRecord) uint64 {
|
|
var totalDeposit uint64
|
|
activeValidators := ActiveValidatorIndices(validators, dynasty)
|
|
|
|
for _, index := range activeValidators {
|
|
totalDeposit += validators[index].GetBalance()
|
|
}
|
|
return totalDeposit
|
|
}
|
|
|
|
// TotalActiveValidatorDepositInEth returns the total deposited amount in ETH for all active validators.
|
|
func TotalActiveValidatorDepositInEth(dynasty uint64, validators []*pb.ValidatorRecord) uint64 {
|
|
totalDeposit := TotalActiveValidatorDeposit(dynasty, validators)
|
|
depositInEth := totalDeposit / uint64(params.GetConfig().EtherDenomination)
|
|
|
|
return depositInEth
|
|
}
|