2019-01-09 23:49:50 +00:00
|
|
|
// Package blocks contains block processing libraries. These libraries
|
|
|
|
// process and verify block specific messages such as PoW receipt root,
|
|
|
|
// RANDAO, validator deposits, exits and slashing proofs.
|
2018-12-20 22:00:38 +00:00
|
|
|
package blocks
|
|
|
|
|
|
|
|
import (
|
2019-01-05 05:39:34 +00:00
|
|
|
"bytes"
|
2018-12-20 22:00:38 +00:00
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"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"
|
2019-01-05 05:39:34 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/shared/ssz"
|
2018-12-20 22:00:38 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var clock utils.Clock = &utils.RealClock{}
|
|
|
|
|
|
|
|
// NewGenesisBlock returns the canonical, genesis block for the beacon chain protocol.
|
|
|
|
func NewGenesisBlock(stateRoot []byte) *pb.BeaconBlock {
|
|
|
|
block := &pb.BeaconBlock{
|
2019-02-07 06:07:25 +00:00
|
|
|
Slot: params.BeaconConfig().GenesisSlot,
|
|
|
|
ParentRootHash32: params.BeaconConfig().ZeroHash[:],
|
2018-12-25 06:47:07 +00:00
|
|
|
StateRootHash32: stateRoot,
|
2019-02-07 06:07:25 +00:00
|
|
|
RandaoRevealHash32: params.BeaconConfig().ZeroHash[:],
|
|
|
|
Signature: params.BeaconConfig().EmptySignature,
|
2019-02-08 17:52:29 +00:00
|
|
|
Eth1Data: &pb.Eth1Data{
|
|
|
|
DepositRootHash32: params.BeaconConfig().ZeroHash[:],
|
|
|
|
BlockHash32: params.BeaconConfig().ZeroHash[:],
|
|
|
|
},
|
2018-12-25 06:47:07 +00:00
|
|
|
Body: &pb.BeaconBlockBody{
|
|
|
|
ProposerSlashings: []*pb.ProposerSlashing{},
|
2019-01-30 10:11:13 +00:00
|
|
|
AttesterSlashings: []*pb.AttesterSlashing{},
|
2018-12-25 06:47:07 +00:00
|
|
|
Attestations: []*pb.Attestation{},
|
|
|
|
Deposits: []*pb.Deposit{},
|
2019-02-18 16:52:16 +00:00
|
|
|
VoluntaryExits: []*pb.VoluntaryExit{},
|
2018-12-25 06:47:07 +00:00
|
|
|
},
|
2018-12-20 22:00:38 +00:00
|
|
|
}
|
|
|
|
return block
|
|
|
|
}
|
|
|
|
|
2019-02-05 17:55:15 +00:00
|
|
|
// BlockRoot returns the block root stored in the BeaconState for a given slot.
|
|
|
|
// It returns an error if the requested block root is not within the BeaconState.
|
2018-12-20 22:00:38 +00:00
|
|
|
// Spec pseudocode definition:
|
2019-02-05 17:55:15 +00:00
|
|
|
// def get_block_root(state: BeaconState, slot: int) -> Hash32:
|
|
|
|
// """
|
|
|
|
// returns the block root at a recent ``slot``.
|
|
|
|
// """
|
|
|
|
// assert state.slot <= slot + LATEST_BLOCK_ROOTS_LENGTH
|
|
|
|
// assert slot < state.slot
|
|
|
|
// return state.latest_block_roots[slot % LATEST_BLOCK_ROOTS_LENGTH]
|
2018-12-20 22:00:38 +00:00
|
|
|
func BlockRoot(state *pb.BeaconState, slot uint64) ([]byte, error) {
|
2019-02-15 23:19:36 +00:00
|
|
|
earliestSlot := state.Slot - params.BeaconConfig().LatestBlockRootsLength
|
2019-02-10 22:09:35 +00:00
|
|
|
|
2019-02-15 23:19:36 +00:00
|
|
|
if slot < earliestSlot || slot >= state.Slot {
|
2019-02-05 17:55:15 +00:00
|
|
|
return []byte{}, fmt.Errorf("slot %d is not within expected range of %d to %d",
|
2018-12-20 22:00:38 +00:00
|
|
|
slot,
|
|
|
|
earliestSlot,
|
2019-02-15 23:19:36 +00:00
|
|
|
state.Slot,
|
2018-12-20 22:00:38 +00:00
|
|
|
)
|
|
|
|
}
|
2019-02-15 23:19:36 +00:00
|
|
|
|
|
|
|
return state.LatestBlockRootHash32S[slot%params.BeaconConfig().LatestBlockRootsLength], nil
|
2018-12-20 22:00:38 +00:00
|
|
|
}
|
2018-12-27 06:48:09 +00:00
|
|
|
|
|
|
|
// ProcessBlockRoots processes the previous block root into the state, by appending it
|
|
|
|
// to the most recent block roots.
|
|
|
|
// Spec:
|
|
|
|
// Let previous_block_root be the tree_hash_root of the previous beacon block processed in the chain.
|
|
|
|
// Set state.latest_block_roots[(state.slot - 1) % LATEST_BLOCK_ROOTS_LENGTH] = previous_block_root.
|
|
|
|
// If state.slot % LATEST_BLOCK_ROOTS_LENGTH == 0 append merkle_root(state.latest_block_roots) to state.batched_block_roots.
|
|
|
|
func ProcessBlockRoots(state *pb.BeaconState, prevBlockRoot [32]byte) *pb.BeaconState {
|
2019-02-07 06:07:25 +00:00
|
|
|
state.LatestBlockRootHash32S[(state.Slot-1)%params.BeaconConfig().LatestBlockRootsLength] = prevBlockRoot[:]
|
|
|
|
if state.Slot%params.BeaconConfig().LatestBlockRootsLength == 0 {
|
2018-12-27 06:48:09 +00:00
|
|
|
merkleRoot := hashutil.MerkleRoot(state.LatestBlockRootHash32S)
|
|
|
|
state.BatchedBlockRootHash32S = append(state.BatchedBlockRootHash32S, merkleRoot)
|
|
|
|
}
|
|
|
|
return state
|
|
|
|
}
|
2018-12-28 07:29:02 +00:00
|
|
|
|
2019-01-19 02:57:51 +00:00
|
|
|
// BlockChildren obtains the blocks in a list of observed blocks which have the current
|
|
|
|
// beacon block's hash as their parent root hash.
|
2019-01-29 11:19:17 +00:00
|
|
|
//
|
|
|
|
// Spec pseudocode definition:
|
|
|
|
// Let get_children(store: Store, block: BeaconBlock) ->
|
|
|
|
// List[BeaconBlock] returns the child blocks of the given block.
|
2019-01-19 02:57:51 +00:00
|
|
|
func BlockChildren(block *pb.BeaconBlock, observedBlocks []*pb.BeaconBlock) ([]*pb.BeaconBlock, error) {
|
|
|
|
var children []*pb.BeaconBlock
|
2019-02-14 20:04:47 +00:00
|
|
|
root, err := ssz.TreeHash(block)
|
2019-01-19 02:57:51 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("could not hash block: %v", err)
|
|
|
|
}
|
|
|
|
for _, observed := range observedBlocks {
|
2019-02-14 20:04:47 +00:00
|
|
|
if bytes.Equal(observed.ParentRootHash32, root[:]) {
|
2019-01-19 02:57:51 +00:00
|
|
|
children = append(children, observed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return children, nil
|
|
|
|
}
|