mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
Save genesis state in DB (#3359)
* Done * Test * Fixed test * emit state initialized
This commit is contained in:
committed by
Preston Van Loon
parent
1f0aad31d2
commit
f0332e1131
@@ -99,6 +99,14 @@ func (c *ChainService) Start() {
|
||||
if beaconState != nil {
|
||||
log.Info("Beacon chain data already exists, starting service")
|
||||
c.genesisTime = time.Unix(int64(beaconState.GenesisTime), 0)
|
||||
genesisState, err := c.beaconDB.GenesisState(c.ctx)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not retrieve genesis state from db: %v", err)
|
||||
}
|
||||
if err := c.forkChoiceStore.GenesisStore(c.ctx, genesisState); err != nil {
|
||||
log.Fatalf("Could not start fork choice service: %v", err)
|
||||
}
|
||||
c.stateInitializedFeed.Send(c.genesisTime)
|
||||
} else {
|
||||
log.Info("Waiting for ChainStart log from the Validator Deposit Contract to start the beacon chain...")
|
||||
if c.web3Service == nil {
|
||||
@@ -158,10 +166,13 @@ func (c *ChainService) initializeBeaconChain(
|
||||
return errors.Wrap(err, "could not start genesis store for fork choice")
|
||||
}
|
||||
|
||||
if err := c.beaconDB.SaveGenesisBlockRoot(ctx, bytesutil.ToBytes32(c.FinalizedCheckpt().Root)); err != nil {
|
||||
return errors.Wrap(err, "could save genesis block root")
|
||||
}
|
||||
|
||||
c.headBlock = genesisBlk
|
||||
c.headState = genesisState
|
||||
c.canonicalRoots[genesisState.Slot] = c.FinalizedCheckpt().Root
|
||||
c.canonicalRoots[genesisState.Slot] = c.FinalizedCheckpt().Root
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -281,6 +281,9 @@ func TestChainStartStop_Initialized(t *testing.T) {
|
||||
if err := db.SaveHeadBlockRoot(ctx, blkRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveGenesisBlockRoot(ctx, blkRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := db.SaveState(ctx, &pb.BeaconState{Slot: 1}, blkRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -154,6 +154,11 @@ func (db *BeaconDB) SaveHeadBlockRoot(_ context.Context, root [32]byte) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// SaveGenesisBlockRoot is not implemented.
|
||||
func (db *BeaconDB) SaveGenesisBlockRoot(_ context.Context, root [32]byte) error {
|
||||
return errors.New("not implemented")
|
||||
}
|
||||
|
||||
// SaveBlocks in db.
|
||||
func (db *BeaconDB) SaveBlocks(ctx context.Context, blocks []*ethpb.BeaconBlock) error {
|
||||
for _, blk := range blocks {
|
||||
|
||||
@@ -43,6 +43,7 @@ type Database interface {
|
||||
SaveBlock(ctx context.Context, block *ethpb.BeaconBlock) error
|
||||
SaveBlocks(ctx context.Context, blocks []*ethpb.BeaconBlock) error
|
||||
SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error
|
||||
SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) error
|
||||
// Validator related methods.
|
||||
ValidatorLatestVote(ctx context.Context, validatorIdx uint64) (*pb.ValidatorLatestVote, error)
|
||||
HasValidatorLatestVote(ctx context.Context, validatorIdx uint64) bool
|
||||
@@ -55,6 +56,7 @@ type Database interface {
|
||||
// State related methods.
|
||||
State(ctx context.Context, blockRoot [32]byte) (*pb.BeaconState, error)
|
||||
HeadState(ctx context.Context) (*pb.BeaconState, error)
|
||||
GenesisState(ctx context.Context) (*pb.BeaconState, error)
|
||||
SaveState(ctx context.Context, state *pb.BeaconState, blockRoot [32]byte) error
|
||||
// Slashing operations.
|
||||
ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*ethpb.ProposerSlashing, error)
|
||||
|
||||
@@ -259,6 +259,16 @@ func (k *Store) SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error
|
||||
})
|
||||
}
|
||||
|
||||
// SaveGenesisBlockRoot to the db.
|
||||
func (k *Store) SaveGenesisBlockRoot(ctx context.Context, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveGenesisBlockRoot")
|
||||
defer span.End()
|
||||
return k.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(blocksBucket)
|
||||
return bucket.Put(genesisBlockRootKey, blockRoot[:])
|
||||
})
|
||||
}
|
||||
|
||||
// fetchBlockRootsBySlotRange looks into a boltDB bucket and performs a binary search
|
||||
// range scan using sorted left-padded byte keys using a start slot and an end slot.
|
||||
// If both the start and end slot are the same, and are 0, the function returns nil.
|
||||
|
||||
@@ -26,5 +26,6 @@ var (
|
||||
|
||||
// Specific item keys.
|
||||
headBlockRootKey = []byte("head-root")
|
||||
genesisBlockRootKey = []byte("genesis-root")
|
||||
depositContractAddressKey = []byte("deposit-contract")
|
||||
)
|
||||
|
||||
@@ -54,6 +54,30 @@ func (k *Store) HeadState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
return s, err
|
||||
}
|
||||
|
||||
// GenesisState returns the genesis state in beacon chain.
|
||||
func (k *Store) GenesisState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.GenesisState")
|
||||
defer span.End()
|
||||
var s *pb.BeaconState
|
||||
err := k.db.View(func(tx *bolt.Tx) error {
|
||||
// Retrieve genesis block's signing root from blocks bucket,
|
||||
// to look up what the genesis state is.
|
||||
bucket := tx.Bucket(blocksBucket)
|
||||
genesisBlockRoot := bucket.Get(genesisBlockRootKey)
|
||||
|
||||
bucket = tx.Bucket(stateBucket)
|
||||
enc := bucket.Get(genesisBlockRoot)
|
||||
if enc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
s, err = createState(enc)
|
||||
return err
|
||||
})
|
||||
return s, err
|
||||
}
|
||||
|
||||
// SaveState stores a state to the db using block's signing root which was used to generate the state.
|
||||
func (k *Store) SaveState(ctx context.Context, state *pb.BeaconState, blockRoot [32]byte) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveState")
|
||||
|
||||
@@ -75,3 +75,41 @@ func TestHeadState_CanSaveRetrieve(t *testing.T) {
|
||||
t.Error("unsaved head state should've been nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenesisState_CanSaveRetrieve(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
defer teardownDB(t, db)
|
||||
|
||||
s := &pb.BeaconState{Slot: 1}
|
||||
headRoot := [32]byte{'B'}
|
||||
|
||||
if err := db.SaveGenesisBlockRoot(context.Background(), headRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := db.SaveState(context.Background(), s, headRoot); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
savedGenesisS, err := db.GenesisState(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(s, savedGenesisS) {
|
||||
t.Error("did not retrieve saved state")
|
||||
}
|
||||
|
||||
if err := db.SaveGenesisBlockRoot(context.Background(), [32]byte{'C'}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
savedGenesisS, err = db.HeadState(context.Background())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if savedGenesisS != nil {
|
||||
t.Error("unsaved genesis state should've been nil")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +150,11 @@ func (db *BeaconDB) HeadState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
return beaconState, err
|
||||
}
|
||||
|
||||
// GenesisState is not implemented.
|
||||
func (db *BeaconDB) GenesisState(ctx context.Context) (*pb.BeaconState, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// HeadStateRoot returns the root of the current state from the db.
|
||||
func (db *BeaconDB) HeadStateRoot() [32]byte {
|
||||
return db.stateHash
|
||||
|
||||
Reference in New Issue
Block a user