mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-07 10:12:19 +00:00
145 lines
5.6 KiB
Go
145 lines
5.6 KiB
Go
package state
|
|
|
|
import (
|
|
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
pbcomm "github.com/prysmaticlabs/prysm/proto/common"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
)
|
|
|
|
// NewGenesisBeaconState initializes the beacon chain state for slot 0.
|
|
func NewGenesisBeaconState(genesisValidatorRegistry []*pb.ValidatorRecord) (*pb.BeaconState, error) {
|
|
// We seed the genesis state with a bunch of validators to
|
|
// bootstrap the system.
|
|
var err error
|
|
if genesisValidatorRegistry == nil {
|
|
genesisValidatorRegistry = v.InitialValidatorRegistry()
|
|
|
|
}
|
|
// Bootstrap attester indices for slots, each slot contains an array of attester indices.
|
|
shardAndCommitteesForSlots, err := v.InitialShardAndCommitteesForSlots(genesisValidatorRegistry)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Bootstrap cross link records.
|
|
var crosslinks []*pb.CrosslinkRecord
|
|
for i := uint64(0); i < params.BeaconConfig().ShardCount; i++ {
|
|
crosslinks = append(crosslinks, &pb.CrosslinkRecord{
|
|
ShardBlockRootHash32: make([]byte, 0, 32),
|
|
Slot: 0,
|
|
})
|
|
}
|
|
|
|
var latestBlockHashes [][]byte
|
|
for i := 0; i < 2*int(params.BeaconConfig().CycleLength); i++ {
|
|
latestBlockHashes = append(latestBlockHashes, make([]byte, 0, 32))
|
|
}
|
|
|
|
return &pb.BeaconState{
|
|
ValidatorRegistry: genesisValidatorRegistry,
|
|
ValidatorRegistryLastChangeSlot: 0,
|
|
ValidatorRegistryExitCount: 0,
|
|
ValidatorRegistryDeltaChainTipHash32: make([]byte, 0, 32),
|
|
RandaoMixHash32: make([]byte, 0, 32),
|
|
NextSeedHash32: make([]byte, 0, 32),
|
|
ShardAndCommitteesAtSlots: shardAndCommitteesForSlots,
|
|
PersistentCommittees: []*pbcomm.Uint32List{},
|
|
PersistentCommitteeReassignments: []*pb.ShardReassignmentRecord{},
|
|
PreviousJustifiedSlot: 0,
|
|
JustifiedSlot: 0,
|
|
JustifiedSlotBitfield: 0,
|
|
FinalizedSlot: 0,
|
|
LatestCrosslinks: crosslinks,
|
|
LastStateRecalculationSlot: 0,
|
|
LatestBlockRootHash32S: latestBlockHashes,
|
|
LatestPenalizedExitBalances: []uint64{},
|
|
LatestAttestations: []*pb.PendingAttestationRecord{},
|
|
ProcessedPowReceiptRootHash32: []byte{},
|
|
CandidatePowReceiptRoots: []*pb.CandidatePoWReceiptRootRecord{},
|
|
GenesisTime: 0,
|
|
ForkData: &pb.ForkData{
|
|
PreForkVersion: params.BeaconConfig().InitialForkVersion,
|
|
PostForkVersion: params.BeaconConfig().InitialForkVersion,
|
|
ForkSlot: params.BeaconConfig().InitialForkSlot,
|
|
},
|
|
Slot: 0,
|
|
}, nil
|
|
}
|
|
|
|
// CalculateNewBlockHashes builds a new slice of recent block hashes with the
|
|
// provided block and the parent slot number.
|
|
//
|
|
// The algorithm is:
|
|
// 1) shift the array by block.SlotNumber - parentSlot (i.e. truncate the
|
|
// first by the number of slots that have occurred between the block and
|
|
// its parent).
|
|
//
|
|
// 2) fill the array with the parent block hash for all values between the parent
|
|
// slot and the block slot.
|
|
//
|
|
// Computation of the state hash depends on this feature that slots with
|
|
// missing blocks have the block hash of the next block hash in the chain.
|
|
//
|
|
// For example, if we have a segment of recent block hashes that look like this
|
|
// [0xF, 0x7, 0x0, 0x0, 0x5]
|
|
//
|
|
// Where 0x0 is an empty or missing hash where no block was produced in the
|
|
// alloted slot. When storing the list (or at least when computing the hash of
|
|
// the active state), the list should be back-filled as such:
|
|
//
|
|
// [0xF, 0x7, 0x5, 0x5, 0x5]
|
|
func CalculateNewBlockHashes(state *pb.BeaconState, block *pb.BeaconBlock, parentSlot uint64) ([][]byte, error) {
|
|
distance := block.GetSlot() - parentSlot
|
|
existing := state.GetLatestBlockRootHash32S()
|
|
update := existing[distance:]
|
|
for len(update) < 2*int(params.BeaconConfig().CycleLength) {
|
|
update = append(update, block.GetParentRootHash32())
|
|
}
|
|
return update, nil
|
|
}
|
|
|
|
// IsValidatorSetChange checks if a validator set change transition can be processed. At that point,
|
|
// validator shuffle will occur.
|
|
func IsValidatorSetChange(state *pb.BeaconState, slotNumber uint64) bool {
|
|
if state.GetFinalizedSlot() <= state.GetValidatorRegistryLastChangeSlot() {
|
|
return false
|
|
}
|
|
if slotNumber-state.GetValidatorRegistryLastChangeSlot() < params.BeaconConfig().MinValidatorSetChangeInterval {
|
|
return false
|
|
}
|
|
|
|
shardProcessed := map[uint64]bool{}
|
|
for _, shardAndCommittee := range state.GetShardAndCommitteesAtSlots() {
|
|
for _, committee := range shardAndCommittee.ArrayShardAndCommittee {
|
|
shardProcessed[committee.Shard] = true
|
|
}
|
|
}
|
|
|
|
crosslinks := state.GetLatestCrosslinks()
|
|
for shard := range shardProcessed {
|
|
if state.GetValidatorRegistryLastChangeSlot() >= crosslinks[shard].Slot {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
// ClearAttestations removes attestations older than last state recalculation slot.
|
|
func ClearAttestations(state *pb.BeaconState, lastStateRecalc uint64) []*pb.PendingAttestationRecord {
|
|
existing := state.GetLatestAttestations()
|
|
updatedAttestations := make([]*pb.PendingAttestationRecord, 0, len(existing))
|
|
for _, a := range existing {
|
|
if a.GetData().GetSlot() >= lastStateRecalc {
|
|
updatedAttestations = append(updatedAttestations, a)
|
|
}
|
|
}
|
|
return updatedAttestations
|
|
}
|
|
|
|
// IsCycleTransition checks if a new cycle has been reached. At that point,
|
|
// a new state transition will occur in the beacon chain.
|
|
func IsCycleTransition(lastRecalcSlot uint64, slotNumber uint64) bool {
|
|
return slotNumber >= lastRecalcSlot+params.BeaconConfig().CycleLength
|
|
}
|