Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable Fork Choice Feature Flag #4574

Merged
merged 15 commits into from Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 19 additions & 16 deletions beacon-chain/blockchain/receive_attestation.go
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/featureconfig"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/slotutil"
"github.com/sirupsen/logrus"
Expand All @@ -37,25 +38,27 @@ func (s *Service) ReceiveAttestationNoPubsub(ctx context.Context, att *ethpb.Att
}

// Run fork choice for head block after updating fork choice store.
headRoot, err := s.forkChoiceStore.Head(ctx)
if err != nil {
return errors.Wrap(err, "could not get head from fork choice service")
}
// Only save head if it's different than the current head.
cachedHeadRoot, err := s.HeadRoot(ctx)
if err != nil {
return errors.Wrap(err, "could not get head root from cache")
}
if !bytes.Equal(headRoot, cachedHeadRoot) {
signed, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(headRoot))
if !featureconfig.Get().DisableForkChoice {
headRoot, err := s.forkChoiceStore.Head(ctx)
if err != nil {
return errors.Wrap(err, "could not compute state from block head")
return errors.Wrap(err, "could not get head from fork choice service")
}
if signed == nil || signed.Block == nil {
return errors.New("nil head block")
// Only save head if it's different than the current head.
cachedHeadRoot, err := s.HeadRoot(ctx)
if err != nil {
return errors.Wrap(err, "could not get head root from cache")
}
if err := s.saveHead(ctx, signed, bytesutil.ToBytes32(headRoot)); err != nil {
return errors.Wrap(err, "could not save head")
if !bytes.Equal(headRoot, cachedHeadRoot) {
signed, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(headRoot))
if err != nil {
return errors.Wrap(err, "could not compute state from block head")
}
if signed == nil || signed.Block == nil {
return errors.New("nil head block")
}
if err := s.saveHead(ctx, signed, bytesutil.ToBytes32(headRoot)); err != nil {
return errors.Wrap(err, "could not save head")
}
}
}

Expand Down
46 changes: 25 additions & 21 deletions beacon-chain/blockchain/receive_block.go
Expand Up @@ -80,31 +80,35 @@ func (s *Service) ReceiveBlockNoPubsub(ctx context.Context, block *ethpb.SignedB
return errors.Wrap(err, "could not get signing root on received block")
}

// Run fork choice after applying state transition on the new block.
headRoot, err := s.forkChoiceStore.Head(ctx)
if err != nil {
return errors.Wrap(err, "could not get head from fork choice service")
}

// Only save head if it's different than the current head.
cachedHeadRoot, err := s.HeadRoot(ctx)
if err != nil {
return errors.Wrap(err, "could not get head root from cache")
}
if !bytes.Equal(headRoot, cachedHeadRoot) {
signedHeadBlock, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(headRoot))
if err != nil {
return errors.Wrap(err, "could not compute state from block head")
if featureconfig.Get().DisableForkChoice {
if err := s.saveHead(ctx, blockCopy, root); err != nil {
return errors.Wrap(err, "could not save head")
}
if signedHeadBlock == nil || signedHeadBlock.Block == nil {
return errors.New("nil head block")
} else {
// Run fork choice after applying state transition on the new block.
headRoot, err := s.forkChoiceStore.Head(ctx)
if err != nil {
return errors.Wrap(err, "could not get head from fork choice service")
}

if err := s.saveHead(ctx, signedHeadBlock, bytesutil.ToBytes32(headRoot)); err != nil {
return errors.Wrap(err, "could not save head")
// Only save head if it's different than the current head.
cachedHeadRoot, err := s.HeadRoot(ctx)
if err != nil {
return errors.Wrap(err, "could not get head root from cache")
}
if !bytes.Equal(headRoot, cachedHeadRoot) {
signedHeadBlock, err := s.beaconDB.Block(ctx, bytesutil.ToBytes32(headRoot))
if err != nil {
return errors.Wrap(err, "could not compute state from block head")
}
if signedHeadBlock == nil || signedHeadBlock.Block == nil {
return errors.New("nil head block")
}
if err := s.saveHead(ctx, signedHeadBlock, bytesutil.ToBytes32(headRoot)); err != nil {
return errors.Wrap(err, "could not save head")
}
isCompetingBlock(root[:], blockCopy.Block.Slot, headRoot, signedHeadBlock.Block.Slot)
}

isCompetingBlock(root[:], blockCopy.Block.Slot, headRoot, signedHeadBlock.Block.Slot)
}

// Send notification of the processed block to the state feed.
Expand Down
9 changes: 9 additions & 0 deletions shared/featureconfig/config.go
Expand Up @@ -37,6 +37,11 @@ type Flags struct {
KafkaBootstrapServers string // KafkaBootstrapServers to find kafka servers to stream blocks, attestations, etc.
BlockDoubleProposals bool // BlockDoubleProposals prevents the validator client from signing any proposals that would be considered a slashable offense.

// DisableForkChoice disables using LMD-GHOST fork choice to update
// the head of the chain based on attestations and instead accepts any valid received block
// as the chain head. UNSAFE, use with caution.
DisableForkChoice bool

// Cache toggles.
EnableAttestationCache bool // EnableAttestationCache; see https://github.com/prysmaticlabs/prysm/issues/3106.
EnableSSZCache bool // EnableSSZCache see https://github.com/prysmaticlabs/prysm/pull/4558.
Expand Down Expand Up @@ -79,6 +84,10 @@ func ConfigureBeaconChain(ctx *cli.Context) {
log.Warn("Writing SSZ states and blocks after state transitions")
cfg.WriteSSZStateTransitions = true
}
if ctx.GlobalBool(disableForkChoiceUnsafeFlag.Name) {
log.Warn("UNSAFE: Disabled fork choice for updating chain head")
cfg.DisableForkChoice = true
}
if ctx.GlobalBool(enableAttestationCacheFlag.Name) {
log.Warn("Enabled unsafe attestation cache")
cfg.EnableAttestationCache = true
Expand Down
8 changes: 8 additions & 0 deletions shared/featureconfig/flags.go
Expand Up @@ -13,6 +13,13 @@ var (
Name: "interop-write-ssz-state-transitions",
Usage: "Write ssz states to disk after attempted state transition",
}
// disableForkChoiceUnsafeFlag disables using the LMD-GHOST fork choice to update
// the head of the chain based on attestations and instead accepts any valid received block
// as the chain head. UNSAFE, use with caution.
disableForkChoiceUnsafeFlag = cli.BoolFlag{
Name: "disable-fork-choice-unsafe",
Usage: "UNSAFE: disable fork choice for determining head of the beacon chain.",
}
// enableAttestationCacheFlag see https://github.com/prysmaticlabs/prysm/issues/3106.
enableAttestationCacheFlag = cli.BoolFlag{
Name: "enable-attestation-cache",
Expand Down Expand Up @@ -200,6 +207,7 @@ var BeaconChainFlags = append(deprecatedFlags, []cli.Flag{
noGenesisDelayFlag,
minimalConfigFlag,
writeSSZStateTransitionsFlag,
disableForkChoiceUnsafeFlag,
enableSSZCache,
enableAttestationCacheFlag,
enableEth1DataVoteCacheFlag,
Expand Down