mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-29 14:48:28 +00:00
83 lines
2.7 KiB
Go
83 lines
2.7 KiB
Go
package blockchain
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/db"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
)
|
|
|
|
// VoteCount determines the number of votes on a beacon block by counting the number
|
|
// of target blocks that have such beacon block as a common ancestor.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_vote_count(block: BeaconBlock) -> int:
|
|
// return sum(
|
|
// get_effective_balance(start_state.validator_balances[validator_index]) // FORK_CHOICE_BALANCE_INCREMENT
|
|
// for validator_index, target in attestation_targets
|
|
// if get_ancestor(store, target, block.slot) == block
|
|
// )
|
|
func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]*pb.BeaconBlock, beaconDB *db.BeaconDB) (int, error) {
|
|
balances := 0
|
|
for validatorIndex, targetBlock := range targets {
|
|
ancestor, err := BlockAncestor(targetBlock, block.Slot, beaconDB)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
// This covers the following case, we start at B5, and want to process B6 and B7
|
|
// B6 can be processed, B7 can not be processed because it's pointed to the
|
|
// block older than current block 5.
|
|
// B4 - B5 - B6
|
|
// \ - - - - - B7
|
|
if ancestor == nil {
|
|
continue
|
|
}
|
|
ancestorRoot, err := hashutil.HashBeaconBlock(ancestor)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
blockRoot, err := hashutil.HashBeaconBlock(block)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
if blockRoot == ancestorRoot {
|
|
balances += int(helpers.EffectiveBalance(state, validatorIndex))
|
|
}
|
|
}
|
|
return balances, nil
|
|
}
|
|
|
|
// BlockAncestor obtains the ancestor at of a block at a certain slot.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def get_ancestor(store: Store, block: BeaconBlock, slot: Slot) -> BeaconBlock:
|
|
// """
|
|
// Get the ancestor of ``block`` with slot number ``slot``; return ``None`` if not found.
|
|
// """
|
|
// if block.slot == slot:
|
|
// return block
|
|
// elif block.slot < slot:
|
|
// return None
|
|
// else:
|
|
// return get_ancestor(store, store.get_parent(block), slot)
|
|
func BlockAncestor(block *pb.BeaconBlock, slot uint64, beaconDB *db.BeaconDB) (*pb.BeaconBlock, error) {
|
|
if block.Slot == slot {
|
|
return block, nil
|
|
}
|
|
if block.Slot < slot {
|
|
return nil, nil
|
|
}
|
|
parentHash := bytesutil.ToBytes32(block.ParentRootHash32)
|
|
parent, err := beaconDB.Block(parentHash)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get parent block: %v", err)
|
|
}
|
|
if parent == nil {
|
|
return nil, fmt.Errorf("parent block does not exist: %v", err)
|
|
}
|
|
return BlockAncestor(parent, slot, beaconDB)
|
|
}
|