2018-12-20 22:00:38 +00:00
|
|
|
package blocks
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2018-12-27 03:15:12 +00:00
|
|
|
"github.com/gogo/protobuf/proto"
|
2018-12-20 22:00:38 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/utils"
|
|
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
|
|
)
|
|
|
|
|
|
|
|
var clock utils.Clock = &utils.RealClock{}
|
|
|
|
|
2018-12-27 03:15:12 +00:00
|
|
|
// Hash a beacon block data structure.
|
|
|
|
func Hash(block *pb.BeaconBlock) ([32]byte, error) {
|
|
|
|
data, err := proto.Marshal(block)
|
|
|
|
if err != nil {
|
|
|
|
return [32]byte{}, fmt.Errorf("could not marshal block proto data: %v", err)
|
|
|
|
}
|
|
|
|
return hashutil.Hash(data), nil
|
|
|
|
}
|
|
|
|
|
2018-12-20 22:00:38 +00:00
|
|
|
// NewGenesisBlock returns the canonical, genesis block for the beacon chain protocol.
|
|
|
|
func NewGenesisBlock(stateRoot []byte) *pb.BeaconBlock {
|
|
|
|
block := &pb.BeaconBlock{
|
2018-12-25 06:47:07 +00:00
|
|
|
Slot: params.BeaconConfig().InitialSlotNumber,
|
|
|
|
ParentRootHash32: params.BeaconConfig().ZeroHash[:],
|
|
|
|
StateRootHash32: stateRoot,
|
|
|
|
RandaoRevealHash32: params.BeaconConfig().ZeroHash[:],
|
|
|
|
Signature: params.BeaconConfig().EmptySignature,
|
|
|
|
Body: &pb.BeaconBlockBody{
|
|
|
|
ProposerSlashings: []*pb.ProposerSlashing{},
|
|
|
|
CasperSlashings: []*pb.CasperSlashing{},
|
|
|
|
Attestations: []*pb.Attestation{},
|
|
|
|
Deposits: []*pb.Deposit{},
|
|
|
|
Exits: []*pb.Exit{},
|
|
|
|
},
|
2018-12-20 22:00:38 +00:00
|
|
|
}
|
|
|
|
return block
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsRandaoValid verifies the validity of randao from block by comparing it with
|
|
|
|
// the proposer's randao from the beacon state.
|
|
|
|
func IsRandaoValid(blockRandao []byte, stateRandao []byte) bool {
|
|
|
|
var h [32]byte
|
|
|
|
copy(h[:], stateRandao)
|
|
|
|
return hashutil.Hash(blockRandao) == h
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsSlotValid compares the slot to the system clock to determine if the block is valid.
|
|
|
|
func IsSlotValid(slot uint64, genesisTime time.Time) bool {
|
|
|
|
slotDuration := time.Duration(slot*params.BeaconConfig().SlotDuration) * time.Second
|
|
|
|
validTimeThreshold := genesisTime.Add(slotDuration)
|
|
|
|
return clock.Now().After(validTimeThreshold)
|
|
|
|
}
|
|
|
|
|
|
|
|
// BlockRoot returns the block hash from input slot, the block hashes
|
|
|
|
// are stored in BeaconState.
|
|
|
|
//
|
|
|
|
// Spec pseudocode definition:
|
|
|
|
// def get_block_root(state: BeaconState, slot: int) -> Hash32:
|
|
|
|
// """
|
|
|
|
// Returns the block hash at a recent ``slot``.
|
|
|
|
// """
|
|
|
|
// earliest_slot_in_array = state.slot - len(state.latest_block_roots)
|
|
|
|
// assert earliest_slot_in_array <= slot < state.slot
|
|
|
|
// return state.latest_block_roots[slot - earliest_slot_in_array]
|
|
|
|
func BlockRoot(state *pb.BeaconState, slot uint64) ([]byte, error) {
|
|
|
|
var earliestSlot uint64
|
|
|
|
|
|
|
|
// If the state slot is less than the length of state block root list, then
|
|
|
|
// the earliestSlot would result in a negative number. Therefore we should
|
|
|
|
// default earliestSlot = 0 in this case.
|
|
|
|
if state.Slot > uint64(len(state.LatestBlockRootHash32S)) {
|
|
|
|
earliestSlot = state.Slot - uint64(len(state.LatestBlockRootHash32S))
|
|
|
|
}
|
|
|
|
|
|
|
|
if slot < earliestSlot || slot >= state.Slot {
|
|
|
|
return []byte{}, fmt.Errorf("slot %d out of bounds: %d <= slot < %d",
|
|
|
|
slot,
|
|
|
|
earliestSlot,
|
|
|
|
state.Slot,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
return state.LatestBlockRootHash32S[slot-earliestSlot], nil
|
|
|
|
}
|