mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 12:57:18 +00:00
81c53c26fb
* Update seed domains (#3872) * Remove Transfers (#3870) * Remove active index roots and compact committee roots (#3869) * Update inclusion reward (#3886) * Alter proposer selection logic (#3884) * Fix early committee bias (#3888) * Remove shards and committees (#3896) * Epoch spec tests v0.9 (#3907) * Block spec test v0.9 (#3905) * rm'ed in protobuf * build proto * build proto * build proto * fix core package * Gazelle * Fixed all the tests * Fixed static test * Comment out spec test for now * One more skip * fix-roundRobinSync (#3862) * Starting but need new seed function * Revert initial sync * Updated Proposer Slashing * Fixed all tests * Lint * Update inclusion reward * Fill randao mixes with eth1 data hash * Test * Fixing test part1 * All tests passing * One last test * Updated config * Build proto * Proper skip message * Conflict and fmt * Removed crosslinks and shards. Built * Format and gazelle * Fixed all the block package tests * Fixed all the helper tests * All epoch package tests pass * All core package tests pass * Fixed operation tests * Started fixing rpc test * RPC tests passed! * Fixed all init sync tests * All tests pass * Fixed blockchain tests * Lint * Lint * Preston's feedback * Starting * Remove container * Fixed block spec tests * All passing except for block_processing test * Failing block processing test * Starting * Add AggregateAndProof * All mainnet test passes * Update deposit contract (#3906) * Proto spec tests v0.9 (#3908) * Starting * Add AggregateAndProof * Unskip block util tests (#3910) * rm'ed in protobuf * build proto * build proto * build proto * fix core package * Gazelle * Fixed all the tests * Fixed static test * Comment out spec test for now * One more skip * fix-roundRobinSync (#3862) * Starting but need new seed function * Revert initial sync * Updated Proposer Slashing * Fixed all tests * Lint * Update inclusion reward * Fill randao mixes with eth1 data hash * Test * Fixing test part1 * All tests passing * One last test * Updated config * Build proto * Proper skip message * Conflict and fmt * Removed crosslinks and shards. Built * Format and gazelle * Fixed all the block package tests * Fixed all the helper tests * All epoch package tests pass * All core package tests pass * Fixed operation tests * Started fixing rpc test * RPC tests passed! * Fixed all init sync tests * All tests pass * Fixed blockchain tests * Lint * Lint * Preston's feedback * Starting * Remove container * Fixed block spec tests * All passing except for block_processing test * Failing block processing test * Starting * Add AggregateAndProof * All mainnet test passes * Unskip block util tests * Slot processing spec test V0.9 (#3912) * Starting * Add AggregateAndProof * Unskip slot processing mainnet test * Unskip minimal spec test for finalization (#3920) * Remove outdated interop tests (#3922) * Rm outdated interop tests * Rm test runner * Gazelle * Update validator to use proposer slot (#3919) * Fix committee assignment (#3931) * Replace shard with committee index (#3930) * Conflict * Clean up (#3933) * Remove shard filter in db (#3936) * Remove lightouse compatibility test (#3939) * Update Committee Cache for v0.9 (#3948) * Updated committee cache * Removed shuffled indices cache * Started testing run time * Lint * Fixed test * Safeguard against nil head state * address edge case * add test * Fixed TestRoundRobinSync by doubling the epochs * Unskip TestProtoCompatability (#3958) * Unskip TestProtoCompatability * Update WORKSPACE * Fix minimal config (#3959) * fix minimal configs * fix hardcoded value in test * Simplify verify att time (#3961) * update readme for deposit contract, regen bindings for vyper 0.1.0b12 (#3963) * update readme for deposit contract, regen bindings * medium * Check nil base state (#3964) * Copy Block When Receiving it From Sync (#3966) * copy block * clone for other service methods too * Change logging of Bitfield (#3956) * change logging of bits * preston's review * Unskip Beacon Server Test (#3962) * run test till the end * fix up proto message types * fmt * resolve broken tests * better error handling * fixing new logic to use archived proposer info * fix up logic * clip using the max effective balance * broken build fix with num arg mismatch * amend archive * archival logic changed * rename test * archive both proposer and attester seeds * page size 100 * further experiments * further experimentation, archivedProposerIndex seems wrong * test passes * rem log * fix broken test * fix test * gaz * fix imports * ethapis
250 lines
8.8 KiB
Go
250 lines
8.8 KiB
Go
package helpers
|
|
|
|
import (
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
)
|
|
|
|
var activeIndicesCache = cache.NewActiveIndicesCache()
|
|
var activeCountCache = cache.NewActiveCountCache()
|
|
|
|
// IsActiveValidator returns the boolean value on whether the validator
|
|
// is active or not.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def is_active_validator(validator: Validator, epoch: Epoch) -> bool:
|
|
// """
|
|
// Check if ``validator`` is active.
|
|
// """
|
|
// return validator.activation_epoch <= epoch < validator.exit_epoch
|
|
func IsActiveValidator(validator *ethpb.Validator, epoch uint64) bool {
|
|
return validator.ActivationEpoch <= epoch &&
|
|
epoch < validator.ExitEpoch
|
|
}
|
|
|
|
// IsSlashableValidator returns the boolean value on whether the validator
|
|
// is slashable or not.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def is_slashable_validator(validator: Validator, epoch: Epoch) -> bool:
|
|
// """
|
|
// Check if ``validator`` is slashable.
|
|
// """
|
|
// return (
|
|
// validator.activation_epoch <= epoch < validator.withdrawable_epoch and
|
|
// validator.slashed is False
|
|
// )
|
|
func IsSlashableValidator(validator *ethpb.Validator, epoch uint64) bool {
|
|
active := validator.ActivationEpoch <= epoch
|
|
beforeWithdrawable := epoch < validator.WithdrawableEpoch
|
|
return beforeWithdrawable && active && !validator.Slashed
|
|
}
|
|
|
|
// ActiveValidatorIndices filters out active validators based on validator status
|
|
// and returns their indices in a list.
|
|
//
|
|
// WARNING: This method allocates a new copy of the validator index set and is
|
|
// considered to be very memory expensive. Avoid using this unless you really
|
|
// need the active validator indices for some specific reason.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_active_validator_indices(state: BeaconState, epoch: Epoch) -> Sequence[ValidatorIndex]:
|
|
// """
|
|
// Return the sequence of active validator indices at ``epoch``.
|
|
// """
|
|
// return [ValidatorIndex(i) for i, v in enumerate(state.validators) if is_active_validator(v, epoch)]
|
|
func ActiveValidatorIndices(state *pb.BeaconState, epoch uint64) ([]uint64, error) {
|
|
if featureconfig.Get().EnableNewCache {
|
|
activeIndices, err := committeeCache.ActiveIndices(epoch)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not interface with committee cache")
|
|
}
|
|
if activeIndices != nil {
|
|
return activeIndices, nil
|
|
}
|
|
}
|
|
|
|
indices, err := activeIndicesCache.ActiveIndicesInEpoch(epoch)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not retrieve active indices from cache")
|
|
}
|
|
if indices != nil {
|
|
return indices, nil
|
|
}
|
|
|
|
for i, v := range state.Validators {
|
|
if IsActiveValidator(v, epoch) {
|
|
indices = append(indices, uint64(i))
|
|
}
|
|
}
|
|
|
|
if err := activeIndicesCache.AddActiveIndicesList(&cache.ActiveIndicesByEpoch{
|
|
Epoch: epoch,
|
|
ActiveIndices: indices,
|
|
}); err != nil {
|
|
return nil, errors.Wrap(err, "could not save active indices for cache")
|
|
}
|
|
|
|
return indices, nil
|
|
}
|
|
|
|
// ActiveValidatorCount returns the number of active validators in the state
|
|
// at the given epoch.
|
|
func ActiveValidatorCount(state *pb.BeaconState, epoch uint64) (uint64, error) {
|
|
count, err := activeCountCache.ActiveCountInEpoch(epoch)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "could not retrieve active count from cache")
|
|
}
|
|
if count != params.BeaconConfig().FarFutureEpoch {
|
|
return count, nil
|
|
}
|
|
|
|
count = 0
|
|
for _, v := range state.Validators {
|
|
if IsActiveValidator(v, epoch) {
|
|
count++
|
|
}
|
|
}
|
|
|
|
if err := activeCountCache.AddActiveCount(&cache.ActiveCountByEpoch{
|
|
Epoch: epoch,
|
|
ActiveCount: count,
|
|
}); err != nil {
|
|
return 0, errors.Wrap(err, "could not save active count for cache")
|
|
}
|
|
|
|
return count, nil
|
|
}
|
|
|
|
// DelayedActivationExitEpoch takes in epoch number and returns when
|
|
// the validator is eligible for activation and exit.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def compute_activation_exit_epoch(epoch: Epoch) -> Epoch:
|
|
// """
|
|
// Return the epoch during which validator activations and exits initiated in ``epoch`` take effect.
|
|
// """
|
|
// return Epoch(epoch + 1 + ACTIVATION_EXIT_DELAY)
|
|
func DelayedActivationExitEpoch(epoch uint64) uint64 {
|
|
return epoch + 1 + params.BeaconConfig().MaxSeedLookhead
|
|
}
|
|
|
|
// ValidatorChurnLimit returns the number of validators that are allowed to
|
|
// enter and exit validator pool for an epoch.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_validator_churn_limit(state: BeaconState) -> uint64:
|
|
// """
|
|
// Return the validator churn limit for the current epoch.
|
|
// """
|
|
// active_validator_indices = get_active_validator_indices(state, get_current_epoch(state))
|
|
// return max(MIN_PER_EPOCH_CHURN_LIMIT, len(active_validator_indices) // CHURN_LIMIT_QUOTIENT)
|
|
func ValidatorChurnLimit(state *pb.BeaconState) (uint64, error) {
|
|
validatorCount, err := ActiveValidatorCount(state, CurrentEpoch(state))
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "could not get validator count")
|
|
}
|
|
churnLimit := validatorCount / params.BeaconConfig().ChurnLimitQuotient
|
|
if churnLimit < params.BeaconConfig().MinPerEpochChurnLimit {
|
|
churnLimit = params.BeaconConfig().MinPerEpochChurnLimit
|
|
}
|
|
return churnLimit, nil
|
|
}
|
|
|
|
// BeaconProposerIndex returns proposer index of a current slot.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_beacon_proposer_index(state: BeaconState) -> ValidatorIndex:
|
|
// """
|
|
// Return the beacon proposer index at the current slot.
|
|
// """
|
|
// epoch = get_current_epoch(state)
|
|
// seed = hash(get_seed(state, epoch, DOMAIN_BEACON_PROPOSER) + int_to_bytes(state.slot, length=8))
|
|
// indices = get_active_validator_indices(state, epoch)
|
|
// return compute_proposer_index(state, indices, seed)
|
|
func BeaconProposerIndex(state *pb.BeaconState) (uint64, error) {
|
|
e := CurrentEpoch(state)
|
|
|
|
seed, err := Seed(state, e, params.BeaconConfig().DomainBeaconProposer)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "could not generate seed")
|
|
}
|
|
|
|
seedWithSlot := append(seed[:], bytesutil.Bytes8(state.Slot)...)
|
|
seedWithSlotHash := hashutil.Hash(seedWithSlot)
|
|
|
|
indices, err := ActiveValidatorIndices(state, e)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "could not get active indices")
|
|
}
|
|
|
|
return ComputeProposerIndex(state, indices, seedWithSlotHash)
|
|
}
|
|
|
|
// ComputeProposerIndex returns the index sampled by effective balance, which is used to calculate proposer.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def compute_proposer_index(state: BeaconState, indices: Sequence[ValidatorIndex], seed: Hash) -> ValidatorIndex:
|
|
// """
|
|
// Return from ``indices`` a random index sampled by effective balance.
|
|
// """
|
|
// assert len(indices) > 0
|
|
// MAX_RANDOM_BYTE = 2**8 - 1
|
|
// i = 0
|
|
// while True:
|
|
// candidate_index = indices[compute_shuffled_index(ValidatorIndex(i % len(indices)), len(indices), seed)]
|
|
// random_byte = hash(seed + int_to_bytes(i // 32, length=8))[i % 32]
|
|
// effective_balance = state.validators[candidate_index].effective_balance
|
|
// if effective_balance * MAX_RANDOM_BYTE >= MAX_EFFECTIVE_BALANCE * random_byte:
|
|
// return ValidatorIndex(candidate_index)
|
|
// i += 1
|
|
func ComputeProposerIndex(state *pb.BeaconState, indices []uint64, seed [32]byte) (uint64, error) {
|
|
length := uint64(len(indices))
|
|
if length == 0 {
|
|
return 0, errors.New("empty indices list")
|
|
}
|
|
maxRandomByte := uint64(1<<8 - 1)
|
|
|
|
for i := uint64(0); ; i++ {
|
|
candidateIndex, err := ComputeShuffledIndex(i%length, length, seed, true)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
b := append(seed[:], bytesutil.Bytes8(i/32)...)
|
|
randomByte := hashutil.Hash(b)[i%32]
|
|
effectiveBal := state.Validators[candidateIndex].EffectiveBalance
|
|
if effectiveBal*maxRandomByte >= params.BeaconConfig().MaxEffectiveBalance*uint64(randomByte) {
|
|
return candidateIndex, nil
|
|
}
|
|
}
|
|
}
|
|
|
|
// Domain returns the domain version for BLS private key to sign and verify.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_domain(state: BeaconState,
|
|
// domain_type: int,
|
|
// message_epoch: Epoch=None) -> int:
|
|
// """
|
|
// Return the signature domain (fork version concatenated with domain type) of a message.
|
|
// """
|
|
// epoch = get_current_epoch(state) if message_epoch is None else message_epoch
|
|
// fork_version = state.fork.previous_version if epoch < state.fork.epoch else state.fork.current_version
|
|
// return bls_domain(domain_type, fork_version)
|
|
func Domain(fork *pb.Fork, epoch uint64, domainType []byte) uint64 {
|
|
var forkVersion []byte
|
|
if epoch < fork.Epoch {
|
|
forkVersion = fork.PreviousVersion
|
|
} else {
|
|
forkVersion = fork.CurrentVersion
|
|
}
|
|
return bls.Domain(domainType, forkVersion)
|
|
}
|