mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-06 22:23:56 -05:00
113 lines
3.0 KiB
Go
113 lines
3.0 KiB
Go
package genesis
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
|
|
"github.com/OffchainLabs/prysm/v7/config/params"
|
|
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Initialize is mainly exported for the node initialization process to specify providers of the genesis data
|
|
// and the path to the local storage location via cli flags.
|
|
func Initialize(ctx context.Context, dir string, providers ...Provider) error {
|
|
emb, ok := embeddedGenesisData[params.BeaconConfig().ConfigName]
|
|
if ok {
|
|
setPkgVar(emb, true)
|
|
return nil
|
|
}
|
|
gd, err := FindStateFile(dir)
|
|
if err == nil {
|
|
setPkgVar(gd, true)
|
|
return nil
|
|
}
|
|
if !errors.Is(err, ErrGenesisFileNotFound) {
|
|
return err
|
|
}
|
|
return initializeFromProviders(ctx, dir, providers...)
|
|
}
|
|
|
|
func initializeFromProviders(ctx context.Context, dir string, providers ...Provider) error {
|
|
for _, get := range providers {
|
|
gs, err := get.Genesis(ctx)
|
|
if err != nil {
|
|
log.WithField("provider", fmt.Sprintf("%T", get)).Warn("genesis provider failed")
|
|
continue
|
|
}
|
|
gd, err := newGenesisData(gs, dir)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "new genesis data")
|
|
}
|
|
return Store(gd)
|
|
}
|
|
return ErrGenesisStateNotInitialized
|
|
}
|
|
|
|
func newGenesisData(st state.BeaconState, dir string) (GenesisData, error) {
|
|
if state.IsNil(st) {
|
|
return GenesisData{}, ErrGenesisStateNotInitialized
|
|
}
|
|
if dir == "" {
|
|
return GenesisData{}, ErrFilePathUnset
|
|
}
|
|
return GenesisData{
|
|
FileDir: dir,
|
|
State: st,
|
|
ValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot()),
|
|
Time: st.GenesisTime(),
|
|
}, nil
|
|
}
|
|
|
|
// FindStateFile searches for a valid genesis state file in the specified directory.
|
|
func FindStateFile(dir string) (GenesisData, error) {
|
|
if dir == "" {
|
|
return GenesisData{}, ErrFilePathUnset
|
|
}
|
|
files, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
return GenesisData{}, fmt.Errorf("%w: %w", ErrGenesisFileNotFound, err)
|
|
}
|
|
for _, f := range files {
|
|
gd, err := tryParseFname(dir, f)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
return gd, nil
|
|
}
|
|
return GenesisData{}, ErrGenesisFileNotFound
|
|
}
|
|
|
|
func tryParseFname(dir string, f os.DirEntry) (GenesisData, error) {
|
|
gd := GenesisData{FileDir: dir}
|
|
if f.IsDir() {
|
|
return gd, ErrNotGenesisStateFile
|
|
}
|
|
extParts := strings.Split(f.Name(), ".")
|
|
if len(extParts) != 2 || extParts[1] != "ssz" {
|
|
return gd, ErrNotGenesisStateFile
|
|
}
|
|
parts := strings.Split(extParts[0], "-")
|
|
if len(parts) != 3 || parts[genesisPart] != "genesis" {
|
|
return gd, ErrNotGenesisStateFile
|
|
}
|
|
ts, err := strconv.ParseInt(parts[timePart], 10, 64)
|
|
if err != nil {
|
|
return gd, errors.Wrap(err, "parse genesis time")
|
|
}
|
|
if ts < 0 {
|
|
return gd, errors.New("genesis time cannot be negative")
|
|
}
|
|
gd.Time = time.Unix(ts, 0)
|
|
if err := hexutil.UnmarshalFixedText("genesis_validators_root", []byte(parts[gvrPart]), gd.ValidatorsRoot[:]); err != nil {
|
|
return gd, errors.Wrap(err, "unmarshal genesis validators root")
|
|
}
|
|
return gd, nil
|
|
}
|