mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-12 12:40:05 +00:00
Optimize Counting Target Votes using Ancestor Cache (#2279)
* use committee cache in UpdateLatestAttestation * fmt * gaz * fixed existing tests * verify cache miss works * gaz * added test for committee hit and update attestation target * verify cache miss works * Update beacon-chain/core/helpers/committee.go Co-Authored-By: terenc3t <terence@prysmaticlabs.com> * rm declaring err * add feature flag * fork choice vote count to use cached ancestor * comments * fmt * spelling and grammer * no extra space * renamed vars & added a test for cache miss * lint * add cache hit test case : ) * gaz * Remove Enableblock, it was a copy/paste typo * refactor cached ancestor blk getter into its own function
This commit is contained in:
parent
a42bdc4b6f
commit
cc730d17af
@ -11,6 +11,7 @@ go_library(
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/attestation:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
@ -42,6 +43,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//beacon-chain/attestation:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/core/blocks:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/state:go_default_library",
|
||||
|
@ -6,10 +6,12 @@ import (
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
"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/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
"go.opencensus.io/trace"
|
||||
@ -21,6 +23,7 @@ var (
|
||||
Help: "The number of chain reorganization events that have happened in the fork choice rule",
|
||||
})
|
||||
)
|
||||
var blkAncestorCache = cache.NewBlockAncestorCache()
|
||||
|
||||
// ForkChoice interface defines the methods for applying fork choice rule
|
||||
// operations to the blockchain.
|
||||
@ -316,10 +319,21 @@ func (c *ChainService) attestationTargets(ctx context.Context, state *pb.BeaconS
|
||||
// )
|
||||
func VoteCount(block *pb.BeaconBlock, state *pb.BeaconState, targets map[uint64]*pb.BeaconBlock, beaconDB *db.BeaconDB) (int, error) {
|
||||
balances := 0
|
||||
var ancestor *pb.BeaconBlock
|
||||
var err error
|
||||
|
||||
for validatorIndex, targetBlock := range targets {
|
||||
ancestor, err := BlockAncestor(targetBlock, block.Slot, beaconDB)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
if featureconfig.FeatureConfig().EnableBlockAncestorCache {
|
||||
ancestor, err = cachedAncestorBlock(targetBlock, block.Slot, beaconDB)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else {
|
||||
// if block ancestor cache was not enabled, retrieve the ancestor recursively.
|
||||
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
|
||||
@ -374,3 +388,36 @@ func BlockAncestor(block *pb.BeaconBlock, slot uint64, beaconDB *db.BeaconDB) (*
|
||||
}
|
||||
return BlockAncestor(parent, slot, beaconDB)
|
||||
}
|
||||
|
||||
// cachedAncestorBlock retrieves the cached ancestor block from block ancestor cache,
|
||||
// if it's not there it looks up the block tree get it and cache it.
|
||||
func cachedAncestorBlock(targetBlk *pb.BeaconBlock, height uint64, beaconDB *db.BeaconDB) (*pb.BeaconBlock, error) {
|
||||
var ancestor *pb.BeaconBlock
|
||||
|
||||
// check if the ancestor block of from a given block height was cached.
|
||||
targetHash, err := hashutil.HashBeaconBlock(targetBlk)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cachedAncestorBlock, err := blkAncestorCache.AncestorBySlot(targetHash[:], height)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
if cachedAncestorBlock != nil {
|
||||
return cachedAncestorBlock.Block, nil
|
||||
}
|
||||
|
||||
// add the ancestor to the cache if it was not cached.
|
||||
ancestor, err = BlockAncestor(targetBlk, height, beaconDB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := blkAncestorCache.AddBlockAncestor(&cache.AncestorInfo{
|
||||
Hash: targetHash[:],
|
||||
Height: height,
|
||||
Block: ancestor,
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ancestor, nil
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/attestation"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
||||
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/core/state"
|
||||
@ -19,6 +20,7 @@ import (
|
||||
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
||||
"github.com/prysmaticlabs/prysm/shared/bls"
|
||||
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/featureconfig"
|
||||
"github.com/prysmaticlabs/prysm/shared/forkutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
||||
"github.com/prysmaticlabs/prysm/shared/params"
|
||||
@ -76,13 +78,13 @@ func TestApplyForkChoice_SetsCanonicalHead(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
hook := logTest.NewGlobal()
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
beaconDb := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDb)
|
||||
attsService := attestation.NewAttestationService(
|
||||
context.Background(),
|
||||
&attestation.Config{BeaconDB: db})
|
||||
&attestation.Config{BeaconDB: beaconDb})
|
||||
|
||||
chainService := setupBeaconChain(t, db, attsService)
|
||||
chainService := setupBeaconChain(t, beaconDb, attsService)
|
||||
if err := chainService.beaconDB.SaveBlock(
|
||||
genesis); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -97,7 +99,7 @@ func TestApplyForkChoice_SetsCanonicalHead(t *testing.T) {
|
||||
}
|
||||
unixTime := uint64(time.Now().Unix())
|
||||
deposits, _ := setupInitialDeposits(t, 100)
|
||||
if err := db.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
if err := beaconDb.InitializeState(context.Background(), unixTime, deposits, &pb.Eth1Data{}); err != nil {
|
||||
t.Fatalf("Could not initialize beacon state to disk: %v", err)
|
||||
}
|
||||
|
||||
@ -196,13 +198,13 @@ func TestAttestationTargets_RetrieveWorks(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
pubKey := []byte{'A'}
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
ValidatorRegistry: []*pb.Validator{{
|
||||
Pubkey: pubKey,
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch}},
|
||||
}
|
||||
|
||||
if err := beaconDB.SaveState(ctx, state); err != nil {
|
||||
if err := beaconDB.SaveState(ctx, beaconState); err != nil {
|
||||
t.Fatalf("could not save state: %v", err)
|
||||
}
|
||||
|
||||
@ -227,7 +229,7 @@ func TestAttestationTargets_RetrieveWorks(t *testing.T) {
|
||||
attsService.InsertAttestationIntoStore(pubKey48, att)
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB, attsService)
|
||||
attestationTargets, err := chainService.attestationTargets(ctx, state)
|
||||
attestationTargets, err := chainService.attestationTargets(ctx, beaconState)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get attestation targets: %v", err)
|
||||
}
|
||||
@ -243,7 +245,7 @@ func TestBlockChildren_2InARow(t *testing.T) {
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB, nil)
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 3,
|
||||
}
|
||||
|
||||
@ -260,7 +262,7 @@ func TestBlockChildren_2InARow(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -275,7 +277,7 @@ func TestBlockChildren_2InARow(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -286,11 +288,11 @@ func TestBlockChildren_2InARow(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, state.Slot)
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, beaconState.Slot)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get block children: %v", err)
|
||||
}
|
||||
@ -309,7 +311,7 @@ func TestBlockChildren_ChainSplits(t *testing.T) {
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB, nil)
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 10,
|
||||
}
|
||||
|
||||
@ -328,7 +330,7 @@ func TestBlockChildren_ChainSplits(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -339,7 +341,7 @@ func TestBlockChildren_ChainSplits(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -350,7 +352,7 @@ func TestBlockChildren_ChainSplits(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -361,11 +363,11 @@ func TestBlockChildren_ChainSplits(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block4); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, state.Slot)
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, beaconState.Slot)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get block children: %v", err)
|
||||
}
|
||||
@ -384,7 +386,7 @@ func TestBlockChildren_SkipSlots(t *testing.T) {
|
||||
|
||||
chainService := setupBeaconChain(t, beaconDB, nil)
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 10,
|
||||
}
|
||||
|
||||
@ -401,7 +403,7 @@ func TestBlockChildren_SkipSlots(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -416,7 +418,7 @@ func TestBlockChildren_SkipSlots(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block5); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block5, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block5, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -427,11 +429,11 @@ func TestBlockChildren_SkipSlots(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block9); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block9, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block9, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, state.Slot)
|
||||
childrenBlock, err := chainService.blockChildren(ctx, block1, beaconState.Slot)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not get block children: %v", err)
|
||||
}
|
||||
@ -448,7 +450,7 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 10,
|
||||
ValidatorBalances: []uint64{params.BeaconConfig().MaxDepositAmount},
|
||||
ValidatorRegistry: []*pb.Validator{{}},
|
||||
@ -469,7 +471,7 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -480,7 +482,7 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -489,7 +491,7 @@ func TestLMDGhost_TrivialHeadUpdate(t *testing.T) {
|
||||
voteTargets[0] = block2
|
||||
|
||||
// LMDGhost should pick block 2.
|
||||
head, err := chainService.lmdGhost(ctx, block1, state, voteTargets)
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -503,7 +505,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 10,
|
||||
ValidatorBalances: []uint64{
|
||||
params.BeaconConfig().MaxDepositAmount,
|
||||
@ -530,7 +532,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -541,7 +543,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -552,7 +554,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -563,7 +565,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block4); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -574,7 +576,7 @@ func TestLMDGhost_3WayChainSplitsSameHeight(t *testing.T) {
|
||||
voteTargets[2] = block4
|
||||
voteTargets[3] = block4
|
||||
// LMDGhost should pick block 4.
|
||||
head, err := chainService.lmdGhost(ctx, block1, state, voteTargets)
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -588,7 +590,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: 10,
|
||||
ValidatorBalances: []uint64{
|
||||
params.BeaconConfig().MaxDepositAmount,
|
||||
@ -614,7 +616,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block1); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block1, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -629,7 +631,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block2); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block2, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -644,7 +646,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block3); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block3, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -659,7 +661,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block4); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block4, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -670,7 +672,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block5); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block5, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block5, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -681,7 +683,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
if err = chainService.beaconDB.SaveBlock(block6); err != nil {
|
||||
t.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block6, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block6, beaconState); err != nil {
|
||||
t.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -691,7 +693,7 @@ func TestLMDGhost_2WayChainSplitsDiffHeight(t *testing.T) {
|
||||
voteTargets[1] = block5
|
||||
voteTargets[2] = block5
|
||||
// LMDGhost should pick block 5.
|
||||
head, err := chainService.lmdGhost(ctx, block1, state, voteTargets)
|
||||
head, err := chainService.lmdGhost(ctx, block1, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -719,7 +721,7 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
|
||||
// Construct 8 blocks. (Epoch length = 8)
|
||||
epochLength := uint64(8)
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: epochLength,
|
||||
ValidatorBalances: balances,
|
||||
}
|
||||
@ -734,7 +736,7 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(genesis); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -747,7 +749,7 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(block); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
root, err = hashutil.HashBeaconBlock(block)
|
||||
@ -762,7 +764,7 @@ func BenchmarkLMDGhost_8Slots_8Validators(b *testing.B) {
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := chainService.lmdGhost(ctx, genesis, state, voteTargets)
|
||||
_, err := chainService.lmdGhost(ctx, genesis, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
b.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -790,7 +792,7 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
|
||||
// Construct 8 blocks. (Epoch length = 8)
|
||||
epochLength := uint64(8)
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: epochLength,
|
||||
ValidatorBalances: balances,
|
||||
}
|
||||
@ -805,7 +807,7 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(genesis); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -818,7 +820,7 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(block); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
root, err = hashutil.HashBeaconBlock(block)
|
||||
@ -833,7 +835,7 @@ func BenchmarkLMDGhost_32Slots_8Validators(b *testing.B) {
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := chainService.lmdGhost(ctx, genesis, state, voteTargets)
|
||||
_, err := chainService.lmdGhost(ctx, genesis, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
b.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -859,7 +861,7 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
|
||||
// Construct 64 blocks. (Epoch length = 64)
|
||||
epochLength := uint64(32)
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: epochLength,
|
||||
ValidatorBalances: balances,
|
||||
}
|
||||
@ -874,7 +876,7 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(genesis); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -887,7 +889,7 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(block); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
root, err = hashutil.HashBeaconBlock(block)
|
||||
@ -902,7 +904,7 @@ func BenchmarkLMDGhost_32Slots_64Validators(b *testing.B) {
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := chainService.lmdGhost(ctx, genesis, state, voteTargets)
|
||||
_, err := chainService.lmdGhost(ctx, genesis, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
b.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -928,7 +930,7 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
|
||||
// Construct 64 blocks. (Epoch length = 64)
|
||||
epochLength := uint64(64)
|
||||
state := &pb.BeaconState{
|
||||
beaconState := &pb.BeaconState{
|
||||
Slot: epochLength,
|
||||
ValidatorBalances: balances,
|
||||
}
|
||||
@ -943,7 +945,7 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(genesis); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, genesis, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
|
||||
@ -956,7 +958,7 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
if err = chainService.beaconDB.SaveBlock(block); err != nil {
|
||||
b.Fatalf("Could not save block: %v", err)
|
||||
}
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, state); err != nil {
|
||||
if err = chainService.beaconDB.UpdateChainHead(ctx, block, beaconState); err != nil {
|
||||
b.Fatalf("Could update chain head: %v", err)
|
||||
}
|
||||
root, err = hashutil.HashBeaconBlock(block)
|
||||
@ -971,7 +973,7 @@ func BenchmarkLMDGhost_64Slots_16384Validators(b *testing.B) {
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := chainService.lmdGhost(ctx, genesis, state, voteTargets)
|
||||
_, err := chainService.lmdGhost(ctx, genesis, beaconState, voteTargets)
|
||||
if err != nil {
|
||||
b.Fatalf("Could not run LMD GHOST: %v", err)
|
||||
}
|
||||
@ -1028,11 +1030,11 @@ func setupBeaconChainBenchmark(b *testing.B, faultyPoWClient bool, beaconDB *db.
|
||||
|
||||
func TestUpdateFFGCheckPts_NewJustifiedSlot(t *testing.T) {
|
||||
genesisSlot := params.BeaconConfig().GenesisSlot
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
chainSvc := setupBeaconChain(t, db, nil)
|
||||
chainSvc := setupBeaconChain(t, beaconDB, nil)
|
||||
gBlockRoot, gBlock, gState, privKeys := setupFFGTest(t)
|
||||
if err := chainSvc.beaconDB.SaveBlock(gBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -1104,9 +1106,9 @@ func TestUpdateFFGCheckPts_NewJustifiedSlot(t *testing.T) {
|
||||
|
||||
func TestUpdateFFGCheckPts_NewFinalizedSlot(t *testing.T) {
|
||||
genesisSlot := params.BeaconConfig().GenesisSlot
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
chainSvc := setupBeaconChain(t, db, nil)
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
chainSvc := setupBeaconChain(t, beaconDB, nil)
|
||||
ctx := context.Background()
|
||||
|
||||
gBlockRoot, gBlock, gState, privKeys := setupFFGTest(t)
|
||||
@ -1187,11 +1189,11 @@ func TestUpdateFFGCheckPts_NewFinalizedSlot(t *testing.T) {
|
||||
|
||||
func TestUpdateFFGCheckPts_NewJustifiedSkipSlot(t *testing.T) {
|
||||
genesisSlot := params.BeaconConfig().GenesisSlot
|
||||
db := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, db)
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
ctx := context.Background()
|
||||
|
||||
chainSvc := setupBeaconChain(t, db, nil)
|
||||
chainSvc := setupBeaconChain(t, beaconDB, nil)
|
||||
gBlockRoot, gBlock, gState, privKeys := setupFFGTest(t)
|
||||
if err := chainSvc.beaconDB.SaveBlock(gBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -1318,3 +1320,109 @@ func setupFFGTest(t *testing.T) ([32]byte, *pb.BeaconBlock, *pb.BeaconState, []*
|
||||
}
|
||||
return gBlockRoot, gBlock, gState, privKeys
|
||||
}
|
||||
|
||||
func TestVoteCount_CacheEnabledAndMiss(t *testing.T) {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
EnableBlockAncestorCache: true,
|
||||
})
|
||||
|
||||
beaconDB := internal.SetupDB(t)
|
||||
defer internal.TeardownDB(t, beaconDB)
|
||||
genesisBlock := b.NewGenesisBlock([]byte("stateroot"))
|
||||
genesisRoot, err := hashutil.HashBeaconBlock(genesisBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconDB.SaveBlock(genesisBlock); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
potentialHead := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 5,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
potentialHead2 := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 6,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
// We store these potential heads in the DB.
|
||||
if err := beaconDB.SaveBlock(potentialHead); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := beaconDB.SaveBlock(potentialHead2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
beaconState := &pb.BeaconState{ValidatorBalances: []uint64{1e9, 1e9}}
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets[1] = potentialHead2
|
||||
count, err := VoteCount(genesisBlock, beaconState, voteTargets, beaconDB)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not fetch vote balances: %v", err)
|
||||
}
|
||||
if count != 2e9 {
|
||||
t.Errorf("Expected total balances 2e9, received %d", count)
|
||||
}
|
||||
|
||||
// Verify block ancestor was correctly cached.
|
||||
h, _ := hashutil.HashBeaconBlock(potentialHead)
|
||||
cachedInfo, err := blkAncestorCache.AncestorBySlot(h[:], genesisBlock.Slot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Verify the cached block ancestor is genesis block.
|
||||
h, _ = hashutil.HashBeaconBlock(cachedInfo.Block)
|
||||
if h != genesisRoot {
|
||||
t.Error("could not retrieve the correct ancestor block")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVoteCount_CacheEnabledAndHit(t *testing.T) {
|
||||
featureconfig.InitFeatureConfig(&featureconfig.FeatureFlagConfig{
|
||||
EnableBlockAncestorCache: true,
|
||||
})
|
||||
|
||||
genesisBlock := b.NewGenesisBlock([]byte("stateroot"))
|
||||
genesisRoot, err := hashutil.HashBeaconBlock(genesisBlock)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
potentialHead := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 5,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
pHeadHash, _ := hashutil.HashBeaconBlock(potentialHead)
|
||||
potentialHead2 := &pb.BeaconBlock{
|
||||
Slot: params.BeaconConfig().GenesisSlot + 6,
|
||||
ParentRootHash32: genesisRoot[:],
|
||||
}
|
||||
pHeadHash2, _ := hashutil.HashBeaconBlock(potentialHead2)
|
||||
|
||||
beaconState := &pb.BeaconState{ValidatorBalances: []uint64{1e9, 1e9}}
|
||||
voteTargets := make(map[uint64]*pb.BeaconBlock)
|
||||
voteTargets[0] = potentialHead
|
||||
voteTargets[1] = potentialHead2
|
||||
|
||||
aInfo := &cache.AncestorInfo{
|
||||
Height: genesisBlock.Slot,
|
||||
Hash: pHeadHash[:],
|
||||
Block: genesisBlock,
|
||||
}
|
||||
// Presave cached ancestor blocks before running vote count.
|
||||
if err := blkAncestorCache.AddBlockAncestor(aInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
aInfo.Hash = pHeadHash2[:]
|
||||
if err := blkAncestorCache.AddBlockAncestor(aInfo); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
count, err := VoteCount(genesisBlock, beaconState, voteTargets, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not fetch vote balances: %v", err)
|
||||
}
|
||||
if count != 2e9 {
|
||||
t.Errorf("Expected total balances 2e9, received %d", count)
|
||||
}
|
||||
}
|
||||
|
@ -29,8 +29,9 @@ type FeatureFlagConfig struct {
|
||||
EnableComputeStateRoot bool // EnableComputeStateRoot implementation on server side.
|
||||
EnableCrosslinks bool // EnableCrosslinks in epoch processing.
|
||||
EnableCheckBlockStateRoot bool // EnableCheckBlockStateRoot in block processing.
|
||||
EnableHistoricalStatePruning bool // EnableHistoricalStatePruning when updatifinalized states.
|
||||
EnableHistoricalStatePruning bool // EnableHistoricalStatePruning when updating finalized states.
|
||||
EnableCommitteesCache bool // EnableCommitteesCache for state transition.
|
||||
EnableBlockAncestorCache bool //EnableBlockAncestorCache for fork choice optimization.
|
||||
}
|
||||
|
||||
var featureConfig *FeatureFlagConfig
|
||||
@ -73,6 +74,10 @@ func ConfigureBeaconFeatures(ctx *cli.Context) {
|
||||
log.Info("Enabled committees cache")
|
||||
cfg.EnableCommitteesCache = true
|
||||
}
|
||||
if ctx.GlobalBool(EnableBlockAncestorCacheFlag.Name) {
|
||||
log.Info("Enabled block ancestor cache")
|
||||
cfg.EnableBlockAncestorCache = true
|
||||
}
|
||||
|
||||
InitFeatureConfig(cfg)
|
||||
}
|
||||
|
@ -30,6 +30,12 @@ var (
|
||||
Name: "enable-committees-cache",
|
||||
Usage: "Enable crosslink committees cache for state transition, default is disabled.",
|
||||
}
|
||||
// EnableBlockAncestorCacheFlag enables block ancestor cache for LMD GHOST fork choice optimization. I
|
||||
// it is disabled by default.
|
||||
EnableBlockAncestorCacheFlag = cli.BoolFlag{
|
||||
Name: "enable-block-ancestor-cache",
|
||||
Usage: "Enable block ancestor cache for fork choice optimization, default is disabled.",
|
||||
}
|
||||
// EnableCheckBlockStateRootFlag check block state root in block processing. It is disabled by default.
|
||||
EnableCheckBlockStateRootFlag = cli.BoolFlag{
|
||||
Name: "enable-check-block-state-root",
|
||||
@ -52,4 +58,5 @@ var BeaconChainFlags = []cli.Flag{
|
||||
EnableCommitteesCacheFlag,
|
||||
EnableCheckBlockStateRootFlag,
|
||||
EnableHistoricalStatePruningFlag,
|
||||
EnableBlockAncestorCacheFlag,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user