mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-08 18:51:19 +00:00
174 lines
5.7 KiB
Go
174 lines
5.7 KiB
Go
package state
|
|
|
|
import (
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/incentives"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/types"
|
|
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/utils"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
)
|
|
|
|
// NewStateTransition computes the new beacon state, given the previous beacon state
|
|
// and a beacon block. This method is called during a cycle transition.
|
|
// We also check for validator set change transition and compute for new
|
|
// committees if necessary during this transition.
|
|
func NewStateTransition(
|
|
st *types.BeaconState,
|
|
block *types.Block,
|
|
blockVoteCache utils.BlockVoteCache,
|
|
) (*types.BeaconState, error) {
|
|
var lastStateRecalculationSlotCycleBack uint64
|
|
var err error
|
|
|
|
newState := st.CopyState()
|
|
justifiedStreak := st.JustifiedStreak()
|
|
justifiedSlot := st.LastJustifiedSlot()
|
|
finalizedSlot := st.LastFinalizedSlot()
|
|
timeSinceFinality := block.SlotNumber() - newState.LastFinalizedSlot()
|
|
recentBlockHashes := st.RecentBlockHashes()
|
|
newState.SetValidators(v.CopyValidators(newState.Validators()))
|
|
|
|
if st.LastStateRecalculationSlot() < params.BeaconConfig().CycleLength {
|
|
lastStateRecalculationSlotCycleBack = 0
|
|
} else {
|
|
lastStateRecalculationSlotCycleBack = st.LastStateRecalculationSlot() - params.BeaconConfig().CycleLength
|
|
}
|
|
|
|
// walk through all the slots from LastStateRecalculationSlot - cycleLength to
|
|
// LastStateRecalculationSlot - 1.
|
|
for i := uint64(0); i < params.BeaconConfig().CycleLength; i++ {
|
|
var blockVoteBalance uint64
|
|
|
|
slot := lastStateRecalculationSlotCycleBack + i
|
|
blockHash := recentBlockHashes[i]
|
|
|
|
blockVoteBalance, validators := incentives.TallyVoteBalances(
|
|
blockHash,
|
|
blockVoteCache,
|
|
newState.Validators(),
|
|
v.ActiveValidatorIndices(newState.Validators()),
|
|
v.TotalActiveValidatorDeposit(newState.Validators()),
|
|
timeSinceFinality,
|
|
)
|
|
|
|
newState.SetValidators(validators)
|
|
|
|
justifiedSlot, finalizedSlot, justifiedStreak = FinalizeAndJustifySlots(
|
|
slot,
|
|
justifiedSlot,
|
|
finalizedSlot,
|
|
justifiedStreak,
|
|
blockVoteBalance,
|
|
v.TotalActiveValidatorDeposit(st.Validators()),
|
|
)
|
|
}
|
|
|
|
crossLinks, err := crossLinkCalculations(
|
|
newState,
|
|
st.PendingAttestations(),
|
|
block.SlotNumber(),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newState.SetCrossLinks(crossLinks)
|
|
|
|
newState.SetLastJustifiedSlot(justifiedSlot)
|
|
newState.SetLastFinalizedSlot(finalizedSlot)
|
|
newState.SetJustifiedStreak(justifiedStreak)
|
|
newState.SetLastStateRecalculationSlot(newState.LastStateRecalculationSlot() + params.BeaconConfig().CycleLength)
|
|
|
|
// Exit the validators when their balance fall below min online deposit size.
|
|
newState.SetValidators(v.CheckValidatorMinDeposit(newState.Validators(), block.SlotNumber()))
|
|
|
|
// Entering new validator set change transition.
|
|
if newState.IsValidatorSetChange(block.SlotNumber()) {
|
|
newState.SetValidatorSetChangeSlot(newState.LastStateRecalculationSlot())
|
|
shardAndCommitteesForSlots, err := validatorSetRecalculations(
|
|
newState.ShardAndCommitteesForSlots(),
|
|
newState.Validators(),
|
|
block.ParentHash(),
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
newState.SetShardAndCommitteesForSlots(shardAndCommitteesForSlots)
|
|
|
|
period := block.SlotNumber() / params.BeaconConfig().MinWithdrawalPeriod
|
|
totalPenalties := newState.PenalizedETH(period)
|
|
newState.SetValidators(v.ChangeValidators(block.SlotNumber(), totalPenalties, newState.Validators()))
|
|
}
|
|
|
|
return newState, nil
|
|
}
|
|
|
|
// crossLinkCalculations checks if the proposed shard block has recevied
|
|
// 2/3 of the votes. If yes, we update crosslink record to point to
|
|
// the proposed shard block with latest beacon chain slot numbers.
|
|
func crossLinkCalculations(
|
|
st *types.BeaconState,
|
|
pendingAttestations []*pb.AggregatedAttestation,
|
|
currentSlot uint64,
|
|
) ([]*pb.CrosslinkRecord, error) {
|
|
slot := st.LastStateRecalculationSlot() + params.BeaconConfig().CycleLength
|
|
crossLinkRecords := st.Crosslinks()
|
|
for _, attestation := range pendingAttestations {
|
|
shardCommittees, err := v.GetShardAndCommitteesForSlot(
|
|
st.ShardAndCommitteesForSlots(),
|
|
st.LastStateRecalculationSlot(),
|
|
attestation.GetSlot(),
|
|
)
|
|
indices, err := v.AttesterIndices(shardCommittees, attestation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
totalBalance, voteBalance, err := v.VotedBalanceInAttestation(st.Validators(), indices, attestation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
newValidatorSet, err := incentives.ApplyCrosslinkRewardsAndPenalties(
|
|
crossLinkRecords,
|
|
currentSlot,
|
|
indices,
|
|
attestation,
|
|
st.Validators(),
|
|
v.TotalActiveValidatorDeposit(st.Validators()),
|
|
totalBalance,
|
|
voteBalance,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
st.SetValidators(newValidatorSet)
|
|
crossLinkRecords = UpdateCrosslinks(slot, voteBalance, totalBalance, attestation, crossLinkRecords)
|
|
}
|
|
return crossLinkRecords, nil
|
|
}
|
|
|
|
// validatorSetRecalculation recomputes the validator set.
|
|
func validatorSetRecalculations(
|
|
shardAndCommittesForSlots []*pb.ShardAndCommitteeArray,
|
|
validators []*pb.ValidatorRecord,
|
|
seed [32]byte,
|
|
) ([]*pb.ShardAndCommitteeArray, error) {
|
|
lastSlot := len(shardAndCommittesForSlots) - 1
|
|
lastCommitteeFromLastSlot := len(shardAndCommittesForSlots[lastSlot].ArrayShardAndCommittee) - 1
|
|
crosslinkLastShard := shardAndCommittesForSlots[lastSlot].ArrayShardAndCommittee[lastCommitteeFromLastSlot].Shard
|
|
crosslinkNextShard := (crosslinkLastShard + 1) % params.BeaconConfig().ShardCount
|
|
|
|
newShardCommitteeArray, err := v.ShuffleValidatorsToCommittees(
|
|
seed,
|
|
validators,
|
|
crosslinkNextShard,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return append(shardAndCommittesForSlots[params.BeaconConfig().CycleLength:], newShardCommitteeArray...), nil
|
|
}
|