Save validators upon chainstart (#3295)

This commit is contained in:
terence tsao 2019-08-23 19:59:09 -06:00 committed by GitHub
parent a852d610e2
commit 5294caf5e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 15 deletions

View File

@ -111,7 +111,7 @@ func (c *ChainService) Start() {
subChainStart := c.web3Service.ChainStartFeed().Subscribe(c.chainStartChan)
go func() {
genesisTime := <-c.chainStartChan
c.processChainStartTime(genesisTime, subChainStart)
c.processChainStartTime(c.ctx, genesisTime, subChainStart)
return
}()
}
@ -119,9 +119,9 @@ func (c *ChainService) Start() {
// processChainStartTime initializes a series of deposits from the ChainStart deposits in the eth1
// deposit contract, initializes the beacon chain's state, and kicks off the beacon chain.
func (c *ChainService) processChainStartTime(genesisTime time.Time, chainStartSub event.Subscription) {
func (c *ChainService) processChainStartTime(ctx context.Context, genesisTime time.Time, chainStartSub event.Subscription) {
initialDeposits := c.web3Service.ChainStartDeposits()
if err := c.initializeBeaconChain(genesisTime, initialDeposits, c.web3Service.ChainStartETH1Data()); err != nil {
if err := c.initializeBeaconChain(ctx, genesisTime, initialDeposits, c.web3Service.ChainStartETH1Data()); err != nil {
log.Fatalf("Could not initialize beacon chain: %v", err)
}
c.stateInitializedFeed.Send(genesisTime)
@ -131,23 +131,31 @@ func (c *ChainService) processChainStartTime(genesisTime time.Time, chainStartSu
// initializes the state and genesis block of the beacon chain to persistent storage
// based on a genesis timestamp value obtained from the ChainStart event emitted
// by the ETH1.0 Deposit Contract and the POWChain service of the node.
func (c *ChainService) initializeBeaconChain(genesisTime time.Time, deposits []*ethpb.Deposit, eth1data *ethpb.Eth1Data) error {
func (c *ChainService) initializeBeaconChain(
ctx context.Context,
genesisTime time.Time,
deposits []*ethpb.Deposit,
eth1data *ethpb.Eth1Data) error {
_, span := trace.StartSpan(context.Background(), "beacon-chain.ChainService.initializeBeaconChain")
defer span.End()
log.Info("ChainStart time reached, starting the beacon chain!")
c.genesisTime = genesisTime
unixTime := uint64(genesisTime.Unix())
beaconState, err := state.GenesisBeaconState(deposits, unixTime, eth1data)
genesisState, err := state.GenesisBeaconState(deposits, unixTime, eth1data)
if err != nil {
return errors.Wrap(err, "could not initialize genesis state")
}
if err := c.forkChoiceStore.GenesisStore(c.ctx, beaconState); err != nil {
return errors.Wrap(err, "could not start gensis store for fork choice")
if err := c.saveGenesisValidators(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis validators")
}
c.canonicalRoots[beaconState.Slot] = c.FinalizedCheckpt().Root
if err := c.forkChoiceStore.GenesisStore(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not start genesis store for fork choice")
}
c.canonicalRoots[genesisState.Slot] = c.FinalizedCheckpt().Root
return nil
}
@ -244,6 +252,16 @@ func (c *ChainService) saveHead(ctx context.Context, b *ethpb.BeaconBlock, r [32
return nil
}
// This gets called when beacon chain is first initialized to save validator indices and pubkeys in db
func (c *ChainService) saveGenesisValidators(ctx context.Context, s *pb.BeaconState) error {
for i, v := range s.Validators {
if err := c.beaconDB.SaveValidatorIndex(ctx, bytesutil.ToBytes48(v.PublicKey), uint64(i)); err != nil {
return errors.Wrapf(err, "could not save validator index: %d", i)
}
}
return nil
}
// This checks if the block is from a competing chain, emits warning and updates metrics.
func isCompetingBlock(root []byte, slot uint64, headRoot []byte, headSlot uint64) {
if !bytes.Equal(root[:], headRoot) {
@ -261,8 +279,8 @@ func isCompetingBlock(root []byte, slot uint64, headRoot []byte, headSlot uint64
func isCompetingAtts(root []byte, headRoot []byte) {
if !bytes.Equal(root[:], headRoot) {
log.WithFields(logrus.Fields{
"attDataRoot": hex.EncodeToString(root[:]),
"headRoot": hex.EncodeToString(headRoot),
"attDataRoot": hex.EncodeToString(root[:]),
"headRoot": hex.EncodeToString(headRoot),
}).Warn("Calculated head diffs from new attestation")
competingAtts.Inc()
}

View File

@ -2,6 +2,7 @@ package blockchain
import (
"context"
"encoding/hex"
"errors"
"io/ioutil"
"math/big"
@ -17,11 +18,13 @@ import (
b "github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
testDB "github.com/prysmaticlabs/prysm/beacon-chain/db/testing"
"github.com/prysmaticlabs/prysm/beacon-chain/internal"
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/event"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/sirupsen/logrus"
@ -286,3 +289,29 @@ func TestChainStartStop_Initialized(t *testing.T) {
}
testutil.AssertLogsContain(t, hook, "Beacon chain data already exists, starting service")
}
func TestChainService_initializeBeaconChain(t *testing.T) {
db := testDB.SetupDB(t)
defer testDB.TeardownDB(t, db)
ctx := context.Background()
bc := setupBeaconChain(t, db)
// Set up 10 deposits pre chain start for validators to register
count := uint64(10)
deposits, _ := testutil.SetupInitialDeposits(t, count)
if err := bc.initializeBeaconChain(ctx, time.Unix(0, 0), deposits, &ethpb.Eth1Data{}); err != nil {
t.Fatal(err)
}
s, err := bc.beaconDB.State(ctx, bytesutil.ToBytes32(bc.canonicalRoots[0]))
if err != nil {
t.Fatal(err)
}
for _, v := range s.Validators {
if !db.HasValidatorIndex(ctx, bytesutil.ToBytes48(v.PublicKey)) {
t.Errorf("Validator %s missing from db", hex.EncodeToString(v.PublicKey))
}
}
}

View File

@ -51,4 +51,4 @@ func (ms *mockChainService) ReceiveAttestation(context.Context, *ethpb.Attestati
func (ms *mockChainService) ReceiveAttestationNoPubsub(context.Context, *ethpb.Attestation) error {
return nil
}
}

View File

@ -17,7 +17,6 @@ func TestValidateBeaconAttestation_ValidBlock(t *testing.T) {
p := p2ptest.NewTestP2P(t)
ctx := context.Background()
rs := &RegularSync{
db: db,
}
@ -64,12 +63,10 @@ func TestValidateBeaconAttestation_InvalidBlock(t *testing.T) {
p := p2ptest.NewTestP2P(t)
ctx := context.Background()
rs := &RegularSync{
db: db,
}
msg := &ethpb.Attestation{
Data: &ethpb.AttestationData{
BeaconBlockRoot: testutil.Random32Bytes(t),
@ -83,4 +80,3 @@ func TestValidateBeaconAttestation_InvalidBlock(t *testing.T) {
t.Error("Invalid beacon attestation was broadcast")
}
}