Embedded mainnet genesis state + load genesis.ssz from file (#8614)

* Update rules_go and fix proto conflicts

* gaz

* Update generated code

* First pass inclusion of using baked states

* more emptypb fixes

* remove testnet genesis files, only embed mainnet

* Refactoring for SaveGenesisData, fix tests that use mainnet config but do not support mainnet genesis values

* a bit more refactoring, load genesis from a file. Needs tests still

* Add method to ensure an embedded genesis file also has the appropriate genesis block

* gofmt

* more clear error

* Check genesis fork version to ensure testnet config matches genesis file

* viz

* test for SaveGenesisData

* More genesis db method tests

* Merge

* Minor tweaks, lint, fmt, etc

* Add more test to genesis db methods

* Revert beacon-chain/state/stateV0/BUILD.bazel

* Update beacon-chain/db/iface/errors.go

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>

* PR feedback

* Update beacon-chain/db/kv/genesis.go

Co-authored-by: terence tsao <terence@prysmaticlabs.com>

* fmt.Errorf works better for nil errors

Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
Co-authored-by: terence tsao <terence@prysmaticlabs.com>
This commit is contained in:
Preston Van Loon 2021-03-18 16:00:00 -05:00 committed by GitHub
parent a921455836
commit e477fdfd6d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 520 additions and 74 deletions

View File

@ -27,7 +27,6 @@ go_library(
deps = [
"//beacon-chain/cache:go_default_library",
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/feed:go_default_library",
"//beacon-chain/core/feed/state:go_default_library",
@ -84,6 +83,7 @@ go_test(
"checktags_test.go",
"head_test.go",
"info_test.go",
"init_test.go",
"metrics_test.go",
"process_attestation_test.go",
"process_block_test.go",
@ -130,6 +130,7 @@ go_test(
srcs = [
"chain_info_norace_test.go",
"checktags_test.go",
"init_test.go",
"receive_block_test.go",
"service_norace_test.go",
],

View File

@ -0,0 +1,12 @@
package blockchain
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -15,7 +15,6 @@ import (
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/core/feed"
statefeed "github.com/prysmaticlabs/prysm/beacon-chain/core/feed/state"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
@ -32,7 +31,6 @@ import (
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stategen"
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/slotutil"
@ -336,38 +334,20 @@ func (s *Service) Status() error {
// This gets called when beacon chain is first initialized to save genesis data (state, block, and more) in db.
func (s *Service) saveGenesisData(ctx context.Context, genesisState iface.BeaconState) error {
stateRoot, err := genesisState.HashTreeRoot(ctx)
if err != nil {
return err
if err := s.cfg.BeaconDB.SaveGenesisData(ctx, genesisState); err != nil {
return errors.Wrap(err, "could not save genesis data")
}
genesisBlk, err := s.cfg.BeaconDB.GenesisBlock(ctx)
if err != nil || genesisBlk == nil {
return fmt.Errorf("could not load genesis block: %v", err)
}
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get genesis block root")
}
s.genesisRoot = genesisBlkRoot
if err := s.cfg.BeaconDB.SaveBlock(ctx, genesisBlk); err != nil {
return errors.Wrap(err, "could not save genesis block")
}
if err := s.cfg.BeaconDB.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis state")
}
if err := s.cfg.BeaconDB.SaveStateSummary(ctx, &pb.StateSummary{
Slot: 0,
Root: genesisBlkRoot[:],
}); err != nil {
return err
}
s.cfg.StateGen.SaveFinalizedState(0, genesisBlkRoot, genesisState)
if err := s.cfg.BeaconDB.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save head block root")
}
if err := s.cfg.BeaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis block root")
}
s.cfg.StateGen.SaveFinalizedState(0 /*slot*/, genesisBlkRoot, genesisState)
// Finalized checkpoint at genesis is a zero hash.
genesisCheckpoint := genesisState.FinalizedCheckpoint()
@ -392,7 +372,6 @@ func (s *Service) saveGenesisData(ctx context.Context, genesisState iface.Beacon
}
s.setHead(genesisBlkRoot, genesisBlk, genesisState)
return nil
}

View File

@ -22,3 +22,7 @@ type HeadAccessDatabase = iface.HeadAccessDatabase
// key-value or relational database in practice. This is the full database interface which should
// not be used often. Prefer a more restrictive interface in this package.
type Database = iface.Database
// ErrExistingGenesisState is an error when the user attempts to save a different genesis state
// when one already exists in a database.
var ErrExistingGenesisState = iface.ErrExistingGenesisState

View File

@ -2,7 +2,10 @@ load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["interface.go"],
srcs = [
"errors.go",
"interface.go",
],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/db/iface",
# Other packages must use github.com/prysmaticlabs/prysm/beacon-chain/db.Database alias.
visibility = ["//beacon-chain/db:__subpackages__"],

View File

@ -0,0 +1,11 @@
package iface
import (
"errors"
)
var (
// ErrExistingGenesisState is an error when the user attempts to save a different genesis state
// when one already exists in a database.
ErrExistingGenesisState = errors.New("genesis state exists already in the DB")
)

View File

@ -99,6 +99,11 @@ type HeadAccessDatabase interface {
// Block related methods.
HeadBlock(ctx context.Context) (*eth.SignedBeaconBlock, error)
SaveHeadBlockRoot(ctx context.Context, blockRoot [32]byte) error
// Genesis operations.
LoadGenesis(ctx context.Context, r io.Reader) error
SaveGenesisData(ctx context.Context, state iface.BeaconState) error
EnsureEmbeddedGenesis(ctx context.Context) error
}
// Database interface with full access.

View File

@ -2,6 +2,7 @@ package kafka
import (
"context"
"io"
"github.com/ethereum/go-ethereum/common"
types "github.com/prysmaticlabs/eth2-types"
@ -266,3 +267,18 @@ func (e Exporter) RunMigrations(ctx context.Context) error {
func (e Exporter) CleanUpDirtyStates(ctx context.Context, slotsPerArchivedPoint types.Slot) error {
return e.db.RunMigrations(ctx)
}
// LoadGenesisFromFile -- passthrough
func (e Exporter) LoadGenesis(ctx context.Context, r io.Reader) error {
return e.db.LoadGenesis(ctx, r)
}
// SaveGenesisData -- passthrough
func (e Exporter) SaveGenesisData(ctx context.Context, state iface.BeaconState) error {
return e.db.SaveGenesisData(ctx, state)
}
// EnsureEmbeddedGenesis -- passthrough.
func (e Exporter) EnsureEmbeddedGenesis(ctx context.Context) error {
return e.db.EnsureEmbeddedGenesis(ctx)
}

View File

@ -11,6 +11,7 @@ go_library(
"deposit_contract.go",
"encoding.go",
"finalized_block_roots.go",
"genesis.go",
"kv.go",
"log.go",
"migration.go",
@ -32,9 +33,11 @@ go_library(
"//tools:__subpackages__",
],
deps = [
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/db/iface:go_default_library",
"//beacon-chain/state/genesis:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//beacon-chain/state/stateV0:go_default_library",
"//proto/beacon/db:go_default_library",
@ -70,6 +73,8 @@ go_test(
"deposit_contract_test.go",
"encoding_test.go",
"finalized_block_roots_test.go",
"genesis_test.go",
"init_test.go",
"kv_test.go",
"migration_archived_index_test.go",
"migration_block_slot_index_test.go",
@ -80,9 +85,11 @@ go_test(
"state_test.go",
"utils_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
deps = [
"//beacon-chain/db/filters:go_default_library",
"//beacon-chain/db/iface:go_default_library",
"//beacon-chain/state/interface:go_default_library",
"//proto/beacon/db:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
@ -97,6 +104,7 @@ go_test(
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@in_gopkg_d4l3k_messagediff_v1//:go_default_library",
"@io_bazel_rules_go//go/tools/bazel:go_default_library",
"@io_etcd_go_bbolt//:go_default_library",
],
)

View File

@ -0,0 +1,115 @@
package kv
import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
dbIface "github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
state "github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
// SaveGenesisData bootstraps the beaconDB with a given genesis state.
func (s *Store) SaveGenesisData(ctx context.Context, genesisState iface.BeaconState) error {
stateRoot, err := genesisState.HashTreeRoot(ctx)
if err != nil {
return err
}
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get genesis block root")
}
if err := s.SaveBlock(ctx, genesisBlk); err != nil {
return errors.Wrap(err, "could not save genesis block")
}
if err := s.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis state")
}
if err := s.SaveStateSummary(ctx, &pbp2p.StateSummary{
Slot: 0,
Root: genesisBlkRoot[:],
}); err != nil {
return err
}
if err := s.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save head block root")
}
if err := s.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis block root")
}
return nil
}
// LoadGenesisFromFile loads a genesis state from a given file path, if no genesis exists already.
func (s *Store) LoadGenesis(ctx context.Context, r io.Reader) error {
b, err := ioutil.ReadAll(r)
if err != nil {
return err
}
st := &pbp2p.BeaconState{}
if err := st.UnmarshalSSZ(b); err != nil {
return err
}
gs, err := state.InitializeFromProtoUnsafe(st)
if err != nil {
return err
}
existing, err := s.GenesisState(ctx)
if err != nil {
return err
}
// If some different genesis state existed already, return an error. The same genesis state is
// considered a no-op.
if existing != nil {
a, err := existing.HashTreeRoot(ctx)
if err != nil {
return err
}
b, err := gs.HashTreeRoot(ctx)
if err != nil {
return err
}
if a == b {
return nil
}
return dbIface.ErrExistingGenesisState
}
if !bytes.Equal(gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion) {
return fmt.Errorf("loaded genesis fork version (%#x) does not match config genesis "+
"fork version (%#x)", gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion)
}
return s.SaveGenesisData(ctx, gs)
}
// EnsureEmbeddedGenesis checks that a genesis block has been generated when an embedded genesis
// state is used. If a genesis block does not exist, but a genesis state does, then we should call
// SaveGenesisData on the existing genesis state.
func (s *Store) EnsureEmbeddedGenesis(ctx context.Context) error {
gb, err := s.GenesisBlock(ctx)
if err != nil {
return err
}
if gb != nil {
return nil
}
gs, err := s.GenesisState(ctx)
if err != nil {
return err
}
if gs != nil {
return s.SaveGenesisData(ctx, gs)
}
return nil
}

View File

@ -0,0 +1,117 @@
package kv
import (
"context"
"os"
"testing"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/prysmaticlabs/prysm/beacon-chain/db/iface"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/testutil"
"github.com/prysmaticlabs/prysm/shared/testutil/assert"
)
func TestStore_SaveGenesisData(t *testing.T) {
ctx := context.Background()
db := setupDB(t)
gs, err := testutil.NewBeaconState()
assert.NoError(t, err)
assert.NoError(t, db.SaveGenesisData(ctx, gs))
testGenesisDataSaved(t, db)
}
func testGenesisDataSaved(t *testing.T, db iface.Database) {
ctx := context.Background()
gb, err := db.GenesisBlock(ctx)
assert.NoError(t, err)
assert.NotNil(t, gb)
gbHTR, err := gb.Block.HashTreeRoot()
assert.NoError(t, err)
gss, err := db.StateSummary(ctx, gbHTR)
assert.NoError(t, err)
assert.NotNil(t, gss)
head, err := db.HeadBlock(ctx)
assert.NoError(t, err)
assert.NotNil(t, head)
headHTR, err := head.Block.HashTreeRoot()
assert.NoError(t, err)
assert.Equal(t, gbHTR, headHTR, "head block does not match genesis block")
}
func TestLoadGenesisFromFile(t *testing.T) {
fp := "testdata/mainnet.genesis.ssz"
rfp, err := bazel.Runfile(fp)
if err == nil {
fp = rfp
}
r, err := os.Open(fp)
assert.NoError(t, err)
defer func() {
assert.NoError(t, r.Close())
}()
db := setupDB(t)
assert.NoError(t, db.LoadGenesis(context.Background(), r))
testGenesisDataSaved(t, db)
// Loading the same genesis again should not throw an error
_, err = r.Seek(0, 0)
assert.NoError(t, err)
assert.NoError(t, db.LoadGenesis(context.Background(), r))
}
func TestLoadGenesisFromFile_mismatchedForkVersion(t *testing.T) {
fp := "testdata/altona.genesis.ssz"
rfp, err := bazel.Runfile(fp)
if err == nil {
fp = rfp
}
r, err := os.Open(fp)
assert.NoError(t, err)
defer func() {
assert.NoError(t, r.Close())
}()
// Loading a genesis with the wrong fork version as beacon config should throw an error.
db := setupDB(t)
assert.ErrorContains(t, "does not match config genesis fork version", db.LoadGenesis(context.Background(), r))
}
func TestEnsureEmbeddedGenesis(t *testing.T) {
// Embedded Genesis works with Mainnet config
params.SetupTestConfigCleanup(t)
cfg := params.BeaconConfig()
cfg.ConfigName = params.ConfigNames[params.Mainnet]
params.OverrideBeaconConfig(cfg)
ctx := context.Background()
db := setupDB(t)
gb, err := db.GenesisBlock(ctx)
assert.NoError(t, err)
if gb != nil {
t.Fatal("Genesis block exists already")
}
gs, err := db.GenesisState(ctx)
assert.NoError(t, err)
assert.NotNil(t, gs, "an embedded genesis state does not exist")
assert.NoError(t, db.EnsureEmbeddedGenesis(ctx))
gb, err = db.GenesisBlock(ctx)
assert.NoError(t, err)
assert.NotNil(t, gb)
testGenesisDataSaved(t, db)
}

View File

@ -0,0 +1,12 @@
package kv
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -8,10 +8,13 @@ import (
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/beacon-chain/state/genesis"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/bytesutil"
"github.com/prysmaticlabs/prysm/shared/params"
"github.com/prysmaticlabs/prysm/shared/traceutil"
bolt "go.etcd.io/bbolt"
"go.opencensus.io/trace"
)
@ -42,8 +45,19 @@ func (s *Store) State(ctx context.Context, blockRoot [32]byte) (iface.BeaconStat
func (s *Store) GenesisState(ctx context.Context) (iface.BeaconState, error) {
ctx, span := trace.StartSpan(ctx, "BeaconDB.GenesisState")
defer span.End()
cached, err := genesis.State(params.BeaconConfig().ConfigName)
if err != nil {
traceutil.AnnotateError(span, err)
return nil, err
}
span.AddAttributes(trace.BoolAttribute("cache_hit", cached != nil))
if cached != nil {
return cached, nil
}
var st *pb.BeaconState
err := s.db.View(func(tx *bolt.Tx) error {
err = s.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)

Binary file not shown.

Binary file not shown.

View File

@ -10,7 +10,6 @@ go_library(
visibility = ["//beacon-chain:__subpackages__"],
deps = [
"//beacon-chain/cache/depositcache:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//beacon-chain/db:go_default_library",
"//beacon-chain/powchain:go_default_library",
"//beacon-chain/state/interface:go_default_library",
@ -19,7 +18,6 @@ go_library(
"//shared:go_default_library",
"//shared/interop:go_default_library",
"//shared/slotutil:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prysmaticlabs_eth2_types//:go_default_library",
"@com_github_prysmaticlabs_ethereumapis//eth/v1alpha1:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",

View File

@ -9,11 +9,9 @@ import (
"math/big"
"time"
"github.com/pkg/errors"
types "github.com/prysmaticlabs/eth2-types"
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
"github.com/prysmaticlabs/prysm/beacon-chain/cache/depositcache"
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
"github.com/prysmaticlabs/prysm/beacon-chain/db"
"github.com/prysmaticlabs/prysm/beacon-chain/powchain"
iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
@ -172,42 +170,11 @@ func (s *Service) NonFinalizedDeposits(_ context.Context, _ *big.Int) []*ethpb.D
}
func (s *Service) saveGenesisState(ctx context.Context, genesisState iface.BeaconState) error {
s.chainStartDeposits = make([]*ethpb.Deposit, genesisState.NumValidators())
stateRoot, err := genesisState.HashTreeRoot(ctx)
if err != nil {
if err := s.beaconDB.SaveGenesisData(ctx, genesisState); err != nil {
return err
}
genesisBlk := blocks.NewGenesisBlock(stateRoot[:])
genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot()
if err != nil {
return errors.Wrap(err, "could not get genesis block root")
}
if err := s.beaconDB.SaveBlock(ctx, genesisBlk); err != nil {
return errors.Wrap(err, "could not save genesis block")
}
if err := s.beaconDB.SaveStateSummary(ctx, &pb.StateSummary{
Slot: 0,
Root: genesisBlkRoot[:],
}); err != nil {
return err
}
if err := s.beaconDB.SaveState(ctx, genesisState, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis state")
}
if err := s.beaconDB.SaveGenesisBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save genesis block root")
}
if err := s.beaconDB.SaveHeadBlockRoot(ctx, genesisBlkRoot); err != nil {
return errors.Wrap(err, "could not save head block root")
}
genesisCheckpoint := &ethpb.Checkpoint{Root: genesisBlkRoot[:]}
if err := s.beaconDB.SaveJustifiedCheckpoint(ctx, genesisCheckpoint); err != nil {
return errors.Wrap(err, "could not save justified checkpoint")
}
if err := s.beaconDB.SaveFinalizedCheckpoint(ctx, genesisCheckpoint); err != nil {
return errors.Wrap(err, "could not save finalized checkpoint")
}
s.chainStartDeposits = make([]*ethpb.Deposit, genesisState.NumValidators())
for i := types.ValidatorIndex(0); uint64(i) < uint64(genesisState.NumValidators()); i++ {
pk := genesisState.PubkeyAtIndex(i)

View File

@ -343,6 +343,31 @@ func (b *BeaconNode) startDB(cliCtx *cli.Context) error {
}
b.depositCache = depositCache
if cliCtx.IsSet(flags.GenesisStatePath.Name) {
r, err := os.Open(cliCtx.String(flags.GenesisStatePath.Name))
if err != nil {
return err
}
defer func() {
if err := r.Close(); err != nil {
log.WithError(err).Error("Failed to close genesis file")
}
}()
if err := b.db.LoadGenesis(b.ctx, r); err != nil {
if err == db.ErrExistingGenesisState {
return errors.New("Genesis state flag specified but a genesis state " +
"exists already. Run again with --clear-db and/or ensure you are using the " +
"appropriate testnet flag to load the given genesis state.")
}
return errors.Wrap(err, "could not load genesis from file")
}
}
if err := b.db.EnsureEmbeddedGenesis(b.ctx); err != nil {
return err
}
return nil
}

View File

@ -61,6 +61,7 @@ go_test(
"block_cache_test.go",
"block_reader_test.go",
"deposit_test.go",
"init_test.go",
"log_processing_test.go",
"powchain_test.go",
"service_test.go",

View File

@ -0,0 +1,12 @@
package powchain
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -70,6 +70,7 @@ go_test(
"blocks_test.go",
"committees_test.go",
"config_test.go",
"init_test.go",
"slashings_test.go",
"validators_stream_test.go",
"validators_test.go",

View File

@ -0,0 +1,12 @@
package beacon
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -56,6 +56,7 @@ go_test(
srcs = [
"blocks_test.go",
"config_test.go",
"init_test.go",
"pool_test.go",
"server_test.go",
"state_test.go",

View File

@ -0,0 +1,12 @@
package beaconv1
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -0,0 +1,25 @@
load("@io_bazel_rules_go//go:def.bzl", "go_test")
load("@prysm//tools/go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["genesis.go"],
embedsrcs = ["mainnet.ssz.snappy"],
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/state/genesis",
visibility = ["//beacon-chain/db:__subpackages__"],
deps = [
"//beacon-chain/state/stateV0:go_default_library",
"//proto/beacon/p2p/v1:go_default_library",
"//shared/params:go_default_library",
"@com_github_golang_snappy//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["genesis_test.go"],
deps = [
":go_default_library",
"//shared/params:go_default_library",
],
)

View File

@ -0,0 +1,39 @@
package genesis
import (
_ "embed"
"github.com/golang/snappy"
state "github.com/prysmaticlabs/prysm/beacon-chain/state/stateV0"
pbp2p "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
"github.com/prysmaticlabs/prysm/shared/params"
)
var (
//go:embed mainnet.ssz.snappy
mainnetRawSSZCompressed []byte // 1.8Mb
)
// State returns a copy of the genesis state from a hardcoded value.
func State(name string) (*state.BeaconState, error) {
switch name {
case params.ConfigNames[params.Mainnet]:
return load(mainnetRawSSZCompressed)
default:
// No state found.
return nil, nil
}
}
// load a compressed ssz state file into a beacon state struct.
func load(b []byte) (*state.BeaconState, error) {
st := &pbp2p.BeaconState{}
b, err := snappy.Decode(nil /*dst*/, b)
if err != nil {
return nil, err
}
if err := st.UnmarshalSSZ(b); err != nil {
return nil, err
}
return state.InitializeFromProtoUnsafe(st)
}

View File

@ -0,0 +1,32 @@
package genesis_test
import (
"testing"
"github.com/prysmaticlabs/prysm/beacon-chain/state/genesis"
"github.com/prysmaticlabs/prysm/shared/params"
)
func TestGenesisState(t *testing.T) {
tests := []struct {
name params.ConfigName
}{
{
name: params.Mainnet,
},
}
for _, tt := range tests {
t.Run(params.ConfigNames[tt.name], func(t *testing.T) {
st, err := genesis.State(params.ConfigNames[tt.name])
if err != nil {
t.Fatal(err)
}
if st == nil {
t.Fatal("nil state")
}
if st.NumValidators() <= 0 {
t.Error("No validators present in state")
}
})
}
}

Binary file not shown.

View File

@ -48,6 +48,7 @@ go_test(
"epoch_boundary_state_cache_test.go",
"getter_test.go",
"hot_state_cache_test.go",
"init_test.go",
"migrate_test.go",
"replay_test.go",
"service_test.go",

View File

@ -0,0 +1,12 @@
package stategen
import (
"github.com/prysmaticlabs/prysm/shared/params"
)
func init() {
// Override network name so that hardcoded genesis files are not loaded.
cfg := params.BeaconConfig()
cfg.ConfigName = "test"
params.OverrideBeaconConfig(cfg)
}

View File

@ -166,4 +166,10 @@ var (
Usage: "Sets the maximum number of headers that a deposit log query can fetch.",
Value: uint64(1000),
}
// GenesisStatePath defines a flag to start the beacon chain from a give genesis state file.
GenesisStatePath = &cli.StringFlag{
Name: "genesis-state",
Usage: "Load a genesis state from ssz file. Testnet genesis files can be found in the " +
"eth2-clients/eth2-testnets repository on github.",
}
)

View File

@ -7,8 +7,10 @@ import (
var (
// InteropGenesisStateFlag defines a flag for the beacon node to load genesis state via file.
InteropGenesisStateFlag = &cli.StringFlag{
Name: "interop-genesis-state",
Usage: "The genesis state file (.SSZ) to load from",
Name: "interop-genesis-state",
Usage: "The genesis state file (.SSZ) to load from. Note: loading from an interop genesis " +
"state does not use a web3 connection to read any deposits. This interop " +
"functionality should not be used with public testnets.",
}
// InteropMockEth1DataVotesFlag enables mocking the eth1 proof-of-work chain data put into blocks by proposers.
InteropMockEth1DataVotesFlag = &cli.BoolFlag{

View File

@ -60,6 +60,7 @@ var appFlags = []cli.Flag{
flags.NetworkID,
flags.WeakSubjectivityCheckpt,
flags.Eth1HeaderReqLimit,
flags.GenesisStatePath,
cmd.EnableBackupWebhookFlag,
cmd.BackupWebhookOutputDir,
cmd.MinimalConfigFlag,

View File

@ -119,6 +119,7 @@ var appHelpFlagGroups = []flagGroup{
flags.NetworkID,
flags.WeakSubjectivityCheckpt,
flags.Eth1HeaderReqLimit,
flags.GenesisStatePath,
},
},
{

View File

@ -1,7 +1,7 @@
package params
const (
Mainnet configName = iota
Mainnet ConfigName = iota
EndToEnd
Pyrmont
Toledo
@ -9,7 +9,7 @@ const (
)
// ConfigNames provides network configuration names.
var ConfigNames = map[configName]string{
var ConfigNames = map[ConfigName]string{
Mainnet: "mainnet",
EndToEnd: "end-to-end",
Pyrmont: "pyrmont",
@ -17,4 +17,5 @@ var ConfigNames = map[configName]string{
Prater: "prater",
}
type configName = int
// ConfigName enum describes the type of known network in use.
type ConfigName = int