diff --git a/cl/beacon/handler/config.go b/cl/beacon/handler/config.go
index 4716f0abaea..41e051df183 100644
--- a/cl/beacon/handler/config.go
+++ b/cl/beacon/handler/config.go
@@ -41,10 +41,10 @@ func (a *ApiHandler) getDepositContract(w http.ResponseWriter, r *http.Request)
func (a *ApiHandler) getForkSchedule(w http.ResponseWriter, r *http.Request) (*beaconhttp.BeaconResponse, error) {
response := []cltypes.Fork{}
// create first response (unordered and incomplete)
- for currentVersion, epoch := range a.beaconChainCfg.ForkVersionSchedule {
+ for currentVersion, entry := range a.beaconChainCfg.ForkVersionSchedule {
response = append(response, cltypes.Fork{
CurrentVersion: currentVersion,
- Epoch: epoch,
+ Epoch: entry.Epoch,
})
}
// Sort the responses by epoch
diff --git a/cl/clparams/config.go b/cl/clparams/config.go
index 179d6457e68..dd11c6f56af 100644
--- a/cl/clparams/config.go
+++ b/cl/clparams/config.go
@@ -33,6 +33,7 @@ import (
"github.com/erigontech/erigon-lib/chain/networkname"
libcommon "github.com/erigontech/erigon-lib/common"
+ "github.com/erigontech/erigon/cl/beacon/beacon_router_configuration"
"github.com/erigontech/erigon/cl/utils"
)
@@ -51,6 +52,32 @@ type CaplinConfig struct {
MevRelayUrl string
// EnableValidatorMonitor is used to enable the validator monitor metrics and corresponding logs
EnableValidatorMonitor bool
+
+ // Devnets config
+ CustomConfigPath string
+ CustomGenesisStatePath string
+
+ // Network stuff
+ CaplinDiscoveryAddr string
+ CaplinDiscoveryPort uint64
+ CaplinDiscoveryTCPPort uint64
+ SentinelAddr string
+ SentinelPort uint64
+ // Erigon Sync
+ LoopBlockLimit uint64
+ // Beacon API router configuration
+ BeaconAPIRouter beacon_router_configuration.RouterConfiguration
+
+ BootstrapNodes []string
+ StaticPeers []string
+}
+
+func (c CaplinConfig) IsDevnet() bool {
+ return c.CustomConfigPath != "" || c.CustomGenesisStatePath != ""
+}
+
+func (c CaplinConfig) HaveInvalidDevnetParams() bool {
+ return c.CustomConfigPath == "" || c.CustomGenesisStatePath == ""
}
func (c CaplinConfig) RelayUrlExist() bool {
@@ -65,6 +92,8 @@ const (
SepoliaNetwork NetworkType = 11155111
GnosisNetwork NetworkType = 100
ChiadoNetwork NetworkType = 10200
+
+ CustomNetwork NetworkType = -1
)
const (
@@ -158,9 +187,8 @@ type NetworkConfig struct {
SyncCommsSubnetKey string // SyncCommsSubnetKey is the ENR key of the sync committee subnet bitfield in the enr.
MinimumPeersInSubnetSearch uint64 // PeersInSubnetSearch is the required amount of peers that we need to be able to lookup in a subnet search.
- ContractDeploymentBlock uint64 // the eth1 block in which the deposit contract is deployed.
- BootNodes []string
- StaticPeers []string
+ BootNodes []string
+ StaticPeers []string
}
var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig{
@@ -180,7 +208,6 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
MinimumPeersInSubnetSearch: 20,
- ContractDeploymentBlock: 11184524,
BootNodes: MainnetBootstrapNodes,
},
@@ -200,7 +227,6 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
MinimumPeersInSubnetSearch: 20,
- ContractDeploymentBlock: 1273020,
BootNodes: SepoliaBootstrapNodes,
},
@@ -220,7 +246,6 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
MinimumPeersInSubnetSearch: 20,
- ContractDeploymentBlock: 19475089,
BootNodes: GnosisBootstrapNodes,
},
@@ -240,7 +265,6 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
MinimumPeersInSubnetSearch: 20,
- ContractDeploymentBlock: 155530,
BootNodes: ChiadoBootstrapNodes,
},
@@ -260,7 +284,6 @@ var NetworkConfigs map[NetworkType]NetworkConfig = map[NetworkType]NetworkConfig
AttSubnetKey: "attnets",
SyncCommsSubnetKey: "syncnets",
MinimumPeersInSubnetSearch: 20,
- ContractDeploymentBlock: 155530,
BootNodes: HoleskyBootstrapNodes,
},
}
@@ -315,6 +338,11 @@ func (v ConfigForkVersion) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"0x%08x\"", v)), nil
}
+type VersionScheduleEntry struct {
+ Epoch uint64 `yaml:"EPOCH" json:"EPOCH,string"`
+ StateVersion StateVersion
+}
+
// BeaconChainConfig contains constant configs for node to participate in beacon chain.
type BeaconChainConfig struct {
// Constants (non-configurable)
@@ -443,8 +471,7 @@ type BeaconChainConfig struct {
ElectraForkVersion ConfigForkVersion `yaml:"ELECTRA_FORK_VERSION" spec:"true" json:"ELECTRA_FORK_VERSION"` // ElectraForkVersion is used to represent the fork version for Electra.
ElectraForkEpoch uint64 `yaml:"ELECTRA_FORK_EPOCH" spec:"true" json:"ELECTRA_FORK_EPOCH,string"` // ElectraForkEpoch is used to represent the assigned fork epoch for Electra.
- ForkVersionSchedule map[libcommon.Bytes4]uint64 `json:"-"` // Schedule of fork epochs by version.
- ForkVersionNames map[libcommon.Bytes4]string `json:"-"` // Human-readable names of fork versions.
+ ForkVersionSchedule map[libcommon.Bytes4]VersionScheduleEntry `json:"-"` // Schedule of fork epochs by version.
// New values introduced in Altair hard fork 1.
// Participation flag indices.
@@ -546,31 +573,19 @@ func (b *BeaconChainConfig) GetCurrentStateVersion(epoch uint64) StateVersion {
// InitializeForkSchedule initializes the schedules forks baked into the config.
func (b *BeaconChainConfig) InitializeForkSchedule() {
b.ForkVersionSchedule = configForkSchedule(b)
- b.ForkVersionNames = configForkNames(b)
}
-func configForkSchedule(b *BeaconChainConfig) map[libcommon.Bytes4]uint64 {
- fvs := map[libcommon.Bytes4]uint64{}
- fvs[utils.Uint32ToBytes4(uint32(b.GenesisForkVersion))] = 0
- fvs[utils.Uint32ToBytes4(uint32(b.AltairForkVersion))] = b.AltairForkEpoch
- fvs[utils.Uint32ToBytes4(uint32(b.BellatrixForkVersion))] = b.BellatrixForkEpoch
- fvs[utils.Uint32ToBytes4(uint32(b.CapellaForkVersion))] = b.CapellaForkEpoch
- fvs[utils.Uint32ToBytes4(uint32(b.DenebForkVersion))] = b.DenebForkEpoch
- fvs[utils.Uint32ToBytes4(uint32(b.ElectraForkVersion))] = b.ElectraForkEpoch
+func configForkSchedule(b *BeaconChainConfig) map[libcommon.Bytes4]VersionScheduleEntry {
+ fvs := map[libcommon.Bytes4]VersionScheduleEntry{}
+ fvs[utils.Uint32ToBytes4(uint32(b.GenesisForkVersion))] = VersionScheduleEntry{b.GenesisSlot / b.SlotsPerEpoch, Phase0Version}
+ fvs[utils.Uint32ToBytes4(uint32(b.AltairForkVersion))] = VersionScheduleEntry{b.AltairForkEpoch, AltairVersion}
+ fvs[utils.Uint32ToBytes4(uint32(b.BellatrixForkVersion))] = VersionScheduleEntry{b.BellatrixForkEpoch, BellatrixVersion}
+ fvs[utils.Uint32ToBytes4(uint32(b.CapellaForkVersion))] = VersionScheduleEntry{b.CapellaForkEpoch, CapellaVersion}
+ fvs[utils.Uint32ToBytes4(uint32(b.DenebForkVersion))] = VersionScheduleEntry{b.DenebForkEpoch, DenebVersion}
+ fvs[utils.Uint32ToBytes4(uint32(b.ElectraForkVersion))] = VersionScheduleEntry{b.ElectraForkEpoch, ElectraVersion}
return fvs
}
-func configForkNames(b *BeaconChainConfig) map[libcommon.Bytes4]string {
- fvn := map[libcommon.Bytes4]string{}
- fvn[utils.Uint32ToBytes4(uint32(b.GenesisForkVersion))] = "phase0"
- fvn[utils.Uint32ToBytes4(uint32(b.AltairForkVersion))] = "altair"
- fvn[utils.Uint32ToBytes4(uint32(b.BellatrixForkVersion))] = "bellatrix"
- fvn[utils.Uint32ToBytes4(uint32(b.CapellaForkVersion))] = "capella"
- fvn[utils.Uint32ToBytes4(uint32(b.DenebForkVersion))] = "deneb"
- fvn[utils.Uint32ToBytes4(uint32(b.ElectraForkVersion))] = "electra"
- return fvn
-}
-
func (b *BeaconChainConfig) ParticipationWeights() []uint64 {
return []uint64{
b.TimelySourceWeight,
diff --git a/cl/cltypes/eth1_block.go b/cl/cltypes/eth1_block.go
index c2686a3a0e2..5463e0992cb 100644
--- a/cl/cltypes/eth1_block.go
+++ b/cl/cltypes/eth1_block.go
@@ -361,7 +361,7 @@ func (b *Eth1Block) RlpHeader(parentRoot *libcommon.Hash) (*types.Header, error)
// If the header hash does not match the block hash, return an error.
if header.Hash() != b.BlockHash {
- return nil, fmt.Errorf("cannot derive rlp header: mismatching hash: %s != %s", header.Hash(), b.BlockHash)
+ return nil, fmt.Errorf("cannot derive rlp header: mismatching hash: %s != %s, %d", header.Hash(), b.BlockHash, header.Number)
}
return header, nil
diff --git a/cl/persistence/block_store.go b/cl/persistence/block_store.go
deleted file mode 100644
index b7cb1e422a2..00000000000
--- a/cl/persistence/block_store.go
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2024 The Erigon Authors
-// This file is part of Erigon.
-//
-// Erigon is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Erigon is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with Erigon. If not, see .
-
-package persistence
-
-import (
- "context"
- "time"
-
- "github.com/erigontech/erigon-lib/kv"
- "github.com/erigontech/erigon/cl/cltypes"
- "github.com/erigontech/erigon/cl/rpc"
- "github.com/erigontech/erigon/cl/sentinel/peers"
-)
-
-var _ BlockSource = (*BeaconRpcSource)(nil)
-
-type BeaconRpcSource struct {
- rpc *rpc.BeaconRpcP2P
-}
-
-func (b *BeaconRpcSource) SaveBlocks(ctx context.Context, blocks *peers.PeeredObject[*cltypes.SignedBeaconBlock]) error {
- // it is a no-op because there is no need to do this
- return nil
-}
-
-func NewBeaconRpcSource(rpc *rpc.BeaconRpcP2P) *BeaconRpcSource {
- return &BeaconRpcSource{
- rpc: rpc,
- }
-}
-
-func (*BeaconRpcSource) GetBlock(ctx context.Context, tx kv.Tx, slot uint64) (*peers.PeeredObject[*cltypes.SignedBeaconBlock], error) {
- panic("unimplemented")
-}
-
-func (b *BeaconRpcSource) GetRange(ctx context.Context, _ kv.Tx, from uint64, count uint64) (*peers.PeeredObject[[]*cltypes.SignedBeaconBlock], error) {
- if count == 0 {
- return nil, nil
- }
- var responses *peers.PeeredObject[[]*cltypes.SignedBeaconBlock]
- reqInterval := time.NewTicker(200 * time.Millisecond)
- doneRespCh := make(chan *peers.PeeredObject[[]*cltypes.SignedBeaconBlock], 1)
- defer reqInterval.Stop()
-
- for {
- select {
- case <-reqInterval.C:
- go func() {
- responses, pid, err := b.rpc.SendBeaconBlocksByRangeReq(ctx, from, count)
- if err != nil {
- return
- }
- select {
- case doneRespCh <- &peers.PeeredObject[[]*cltypes.SignedBeaconBlock]{Data: responses, Peer: pid}:
- default:
- }
- }()
- case <-ctx.Done():
- return nil, ctx.Err()
- case responses = <-doneRespCh:
- return responses, nil
- }
- }
-}
-
-// a noop for rpc source since we always return new data
-func (b *BeaconRpcSource) PurgeRange(ctx context.Context, _ kv.Tx, from uint64, count uint64) error {
- return nil
-}
diff --git a/cl/persistence/format/snapshot_format/blocks.go b/cl/persistence/format/snapshot_format/blocks.go
index 976213c685b..e69c6fc60b0 100644
--- a/cl/persistence/format/snapshot_format/blocks.go
+++ b/cl/persistence/format/snapshot_format/blocks.go
@@ -32,6 +32,7 @@ import (
type ExecutionBlockReaderByNumber interface {
Transactions(number uint64, hash libcommon.Hash) (*solid.TransactionsSSZ, error)
Withdrawals(number uint64, hash libcommon.Hash) (*solid.ListSSZ[*cltypes.Withdrawal], error)
+ SetBeaconChainConfig(beaconCfg *clparams.BeaconChainConfig)
}
var buffersPool = sync.Pool{
diff --git a/cl/persistence/format/snapshot_format/getters/execution_snapshot.go b/cl/persistence/format/snapshot_format/getters/execution_snapshot.go
index 53aa85eb6b8..8ce03f04eb8 100644
--- a/cl/persistence/format/snapshot_format/getters/execution_snapshot.go
+++ b/cl/persistence/format/snapshot_format/getters/execution_snapshot.go
@@ -40,8 +40,12 @@ type ExecutionSnapshotReader struct {
db kv.RoDB
}
-func NewExecutionSnapshotReader(ctx context.Context, beaconCfg *clparams.BeaconChainConfig, blockReader services.FullBlockReader, db kv.RoDB) *ExecutionSnapshotReader {
- return &ExecutionSnapshotReader{ctx: ctx, beaconCfg: beaconCfg, blockReader: blockReader, db: db}
+func NewExecutionSnapshotReader(ctx context.Context, blockReader services.FullBlockReader, db kv.RoDB) *ExecutionSnapshotReader {
+ return &ExecutionSnapshotReader{ctx: ctx, blockReader: blockReader, db: db}
+}
+
+func (r *ExecutionSnapshotReader) SetBeaconChainConfig(beaconCfg *clparams.BeaconChainConfig) {
+ r.beaconCfg = beaconCfg
}
func (r *ExecutionSnapshotReader) Transactions(number uint64, hash libcommon.Hash) (*solid.TransactionsSSZ, error) {
diff --git a/cl/persistence/format/snapshot_format/test_util.go b/cl/persistence/format/snapshot_format/test_util.go
index 66482fbead3..3d436ff56b7 100644
--- a/cl/persistence/format/snapshot_format/test_util.go
+++ b/cl/persistence/format/snapshot_format/test_util.go
@@ -18,6 +18,7 @@ package snapshot_format
import (
libcommon "github.com/erigontech/erigon-lib/common"
+ "github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/cl/cltypes"
"github.com/erigontech/erigon/cl/cltypes/solid"
)
@@ -33,3 +34,6 @@ func (t *MockBlockReader) Withdrawals(number uint64, hash libcommon.Hash) (*soli
func (t *MockBlockReader) Transactions(number uint64, hash libcommon.Hash) (*solid.TransactionsSSZ, error) {
return t.Block.Transactions, nil
}
+
+func (t *MockBlockReader) SetBeaconChainConfig(*clparams.BeaconChainConfig) {
+}
diff --git a/cl/persistence/genesisdb/genesis_db.go b/cl/persistence/genesisdb/genesis_db.go
new file mode 100644
index 00000000000..b25b4d8588d
--- /dev/null
+++ b/cl/persistence/genesisdb/genesis_db.go
@@ -0,0 +1,71 @@
+package genesisdb
+
+import (
+ "fmt"
+
+ "github.com/erigontech/erigon/cl/clparams"
+ "github.com/erigontech/erigon/cl/phase1/core/state"
+ "github.com/erigontech/erigon/cl/utils"
+ "github.com/spf13/afero"
+)
+
+const genesisStateFileName = "genesis_state.ssz_snappy"
+
+/*
+* GenesisDB only keeps track of one file
+* genesis_state.ssz_snappy
+* This DB is static and only used to store the genesis state, it is write-once and read-always.
+ */
+type genesisDB struct {
+ fs afero.Fs // Use afero to make it easier to test.
+ beaconConfig *clparams.BeaconChainConfig
+}
+
+func NewGenesisDB(beaconConfig *clparams.BeaconChainConfig, genesisDBPath string) GenesisDB {
+ return &genesisDB{
+ fs: afero.NewBasePathFs(afero.NewOsFs(), genesisDBPath),
+ beaconConfig: beaconConfig,
+ }
+}
+
+func (g *genesisDB) IsInitialized() (bool, error) {
+ return afero.Exists(g.fs, genesisStateFileName)
+}
+
+func (g *genesisDB) Initialize(state *state.CachingBeaconState) error {
+ initialized, err := g.IsInitialized()
+ if err != nil {
+ return err
+ }
+ // No need to initialize.
+ if initialized || state == nil {
+ return nil
+ }
+ enc, err := state.EncodeSSZ(nil)
+ if err != nil {
+ return err
+ }
+ return afero.WriteFile(g.fs, genesisStateFileName, utils.CompressSnappy(enc), 0644)
+}
+
+func (g *genesisDB) ReadGenesisState() (*state.CachingBeaconState, error) {
+ enc, err := afero.ReadFile(g.fs, genesisStateFileName)
+ if err != nil {
+ return nil, err
+ }
+
+ decompressedEnc, err := utils.DecompressSnappy(enc)
+ if err != nil {
+ return nil, err
+ }
+
+ st := state.New(g.beaconConfig)
+ slot, err := utils.ExtractSlotFromSerializedBeaconState(decompressedEnc)
+ if err != nil {
+ return nil, fmt.Errorf("could not deserialize state slot: %s", err)
+ }
+ if err := st.DecodeSSZ(decompressedEnc, int(g.beaconConfig.GetCurrentStateVersion(slot/g.beaconConfig.SlotsPerEpoch))); err != nil {
+ return nil, fmt.Errorf("could not deserialize state: %s", err)
+ }
+ return st, nil
+}
diff --git a/cl/persistence/genesisdb/interface.go b/cl/persistence/genesisdb/interface.go
new file mode 100644
index 00000000000..a88b22f2422
--- /dev/null
+++ b/cl/persistence/genesisdb/interface.go
@@ -0,0 +1,13 @@
+package genesisdb
+
+import "github.com/erigontech/erigon/cl/phase1/core/state"
+
+type GenesisDB interface {
+ // Initialize initializes the genesis database, with either a given genesis state or the hardcoded databases.
+ Initialize(state *state.CachingBeaconState) error
+
+ IsInitialized() (bool, error)
+
+ // ReadGenesisState returns the genesis state.
+ ReadGenesisState() (*state.CachingBeaconState, error)
+}
diff --git a/cl/persistence/interface.go b/cl/persistence/interface.go
deleted file mode 100644
index 9371ca5604a..00000000000
--- a/cl/persistence/interface.go
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2024 The Erigon Authors
-// This file is part of Erigon.
-//
-// Erigon is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// Erigon is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with Erigon. If not, see .
-
-package persistence
-
-import (
- "context"
-
- "github.com/erigontech/erigon-lib/kv"
- "github.com/erigontech/erigon/cl/cltypes"
- "github.com/erigontech/erigon/cl/sentinel/peers"
-)
-
-type BlockSource interface {
- GetRange(ctx context.Context, tx kv.Tx, from uint64, count uint64) (*peers.PeeredObject[[]*cltypes.SignedBeaconBlock], error)
- PurgeRange(ctx context.Context, tx kv.Tx, from uint64, count uint64) error
- GetBlock(ctx context.Context, tx kv.Tx, slot uint64) (*peers.PeeredObject[*cltypes.SignedBeaconBlock], error)
-}
-
-type BeaconChainWriter interface {
- WriteBlock(ctx context.Context, tx kv.RwTx, block *cltypes.SignedBeaconBlock, canonical bool) error
-}
-
-type BeaconChainDatabase interface {
- BlockSource
- BeaconChainWriter
-}
diff --git a/cl/phase1/core/checkpoint_sync/local_checkpoint_syncer.go b/cl/phase1/core/checkpoint_sync/local_checkpoint_syncer.go
index c264fb7cd79..41c716a3479 100644
--- a/cl/phase1/core/checkpoint_sync/local_checkpoint_syncer.go
+++ b/cl/phase1/core/checkpoint_sync/local_checkpoint_syncer.go
@@ -39,7 +39,7 @@ func (l *LocalCheckpointSyncer) GetLatestBeaconState(ctx context.Context) (*stat
beaconCfg := l.genesisState.BeaconConfig()
bs := state.New(beaconCfg)
- slot, err := extractSlotFromSerializedBeaconState(decompressedSnappy)
+ slot, err := utils.ExtractSlotFromSerializedBeaconState(decompressedSnappy)
if err != nil {
return nil, fmt.Errorf("could not deserialize state slot: %s", err)
}
diff --git a/cl/phase1/core/checkpoint_sync/remote_checkpoint_sync.go b/cl/phase1/core/checkpoint_sync/remote_checkpoint_sync.go
index cbb54c81c9f..c3d25f56a7a 100644
--- a/cl/phase1/core/checkpoint_sync/remote_checkpoint_sync.go
+++ b/cl/phase1/core/checkpoint_sync/remote_checkpoint_sync.go
@@ -2,7 +2,6 @@ package checkpoint_sync
import (
"context"
- "encoding/binary"
"errors"
"fmt"
"io"
@@ -11,6 +10,7 @@ import (
"github.com/erigontech/erigon-lib/log/v3"
"github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/cl/phase1/core/state"
+ "github.com/erigontech/erigon/cl/utils"
)
// RemoteCheckpointSync is a CheckpointSyncer that fetches the checkpoint state from a remote endpoint.
@@ -26,13 +26,6 @@ func NewRemoteCheckpointSync(beaconConfig *clparams.BeaconChainConfig, net clpar
}
}
-func extractSlotFromSerializedBeaconState(beaconState []byte) (uint64, error) {
- if len(beaconState) < 48 {
- return 0, errors.New("checkpoint sync read failed, too short")
- }
- return binary.LittleEndian.Uint64(beaconState[40:48]), nil
-}
-
func (r *RemoteCheckpointSync) GetLatestBeaconState(ctx context.Context) (*state.CachingBeaconState, error) {
uris := clparams.GetAllCheckpointSyncEndpoints(r.net)
if len(uris) == 0 {
@@ -65,7 +58,7 @@ func (r *RemoteCheckpointSync) GetLatestBeaconState(ctx context.Context) (*state
return nil, fmt.Errorf("checkpoint sync read failed %s", err)
}
- epoch, err := extractSlotFromSerializedBeaconState(marshaled)
+ epoch, err := utils.ExtractSlotFromSerializedBeaconState(marshaled)
if err != nil {
return nil, fmt.Errorf("checkpoint sync read failed %s", err)
}
diff --git a/cl/phase1/core/checkpoint_sync/util.go b/cl/phase1/core/checkpoint_sync/util.go
index c23f8424133..43dd2563b21 100644
--- a/cl/phase1/core/checkpoint_sync/util.go
+++ b/cl/phase1/core/checkpoint_sync/util.go
@@ -2,32 +2,28 @@ package checkpoint_sync
import (
"context"
+ "fmt"
"github.com/erigontech/erigon-lib/common/datadir"
- "github.com/erigontech/erigon-lib/log/v3"
"github.com/erigontech/erigon/cl/clparams"
- "github.com/erigontech/erigon/cl/clparams/initial_state"
+ "github.com/erigontech/erigon/cl/persistence/genesisdb"
"github.com/erigontech/erigon/cl/phase1/core/state"
"github.com/spf13/afero"
)
// ReadOrFetchLatestBeaconState reads the latest beacon state from disk or fetches it from the network.
-func ReadOrFetchLatestBeaconState(ctx context.Context, dirs datadir.Dirs, beaconCfg *clparams.BeaconChainConfig, caplinConfig clparams.CaplinConfig) (*state.CachingBeaconState, error) {
+func ReadOrFetchLatestBeaconState(ctx context.Context, dirs datadir.Dirs, beaconCfg *clparams.BeaconChainConfig, caplinConfig clparams.CaplinConfig, genesisDB genesisdb.GenesisDB) (*state.CachingBeaconState, error) {
var syncer CheckpointSyncer
- remoteSync := !caplinConfig.DisabledCheckpointSync
+ remoteSync := !caplinConfig.DisabledCheckpointSync && !caplinConfig.IsDevnet()
- if !initial_state.IsGenesisStateSupported(caplinConfig.NetworkId) && !remoteSync {
- log.Warn("Local checkpoint sync is not supported for this network, falling back to remote sync")
- remoteSync = true
- }
if remoteSync {
syncer = NewRemoteCheckpointSync(beaconCfg, caplinConfig.NetworkId)
} else {
aferoFs := afero.NewOsFs()
- genesisState, err := initial_state.GetGenesisState(caplinConfig.NetworkId)
+ genesisState, err := genesisDB.ReadGenesisState()
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("could not read genesis state: %w", err)
}
syncer = NewLocalCheckpointSyncer(genesisState, afero.NewBasePathFs(aferoFs, dirs.CaplinLatest))
}
diff --git a/cl/phase1/execution_client/block_collector/block_collector.go b/cl/phase1/execution_client/block_collector/block_collector.go
index 1dd01fa67cc..10f011afad1 100644
--- a/cl/phase1/execution_client/block_collector/block_collector.go
+++ b/cl/phase1/execution_client/block_collector/block_collector.go
@@ -114,6 +114,10 @@ func (b *blockCollector) Flush(ctx context.Context) error {
b.logger.Warn("bad blocks segment received", "err", err)
return err
}
+ // We expect the genesis to be present in DB already
+ if executionPayload.BlockNumber == 0 {
+ return nil
+ }
header, err := executionPayload.RlpHeader(&parentRoot)
if err != nil {
b.logger.Warn("bad blocks segment received", "err", err)
diff --git a/cl/phase1/network/beacon_downloader.go b/cl/phase1/network/beacon_downloader.go
index ce7b951cc89..a97d57d8949 100644
--- a/cl/phase1/network/beacon_downloader.go
+++ b/cl/phase1/network/beacon_downloader.go
@@ -84,9 +84,12 @@ Loop:
if len(atomicResp.Load().(peerAndBlocks).blocks) > 0 {
return
}
+ var reqSlot uint64
+ if f.highestSlotProcessed > 2 {
+ reqSlot = f.highestSlotProcessed - 2
+ }
// this is so we do not get stuck on a side-fork
- responses, peerId, err := f.rpc.SendBeaconBlocksByRangeReq(ctx, f.highestSlotProcessed-2, count)
-
+ responses, peerId, err := f.rpc.SendBeaconBlocksByRangeReq(ctx, reqSlot, count)
if err != nil {
return
}
diff --git a/cl/phase1/stages/clstages.go b/cl/phase1/stages/clstages.go
index 1ddb16acefb..915c3bb657c 100644
--- a/cl/phase1/stages/clstages.go
+++ b/cl/phase1/stages/clstages.go
@@ -236,6 +236,10 @@ func ConsensusClStages(ctx context.Context,
if err != nil {
return err
}
+ if cfg.state.Slot() == 0 {
+ cfg.state = nil // Release the state
+ return nil
+ }
startingSlot := cfg.state.LatestBlockHeader().Slot
downloader := network2.NewBackwardBeaconDownloader(ctx, cfg.rpc, cfg.executionClient, cfg.indiciesDB)
diff --git a/cl/sentinel/gossip.go b/cl/sentinel/gossip.go
index 3c83050d6ba..0c1af7d4c05 100644
--- a/cl/sentinel/gossip.go
+++ b/cl/sentinel/gossip.go
@@ -531,9 +531,12 @@ type GossipSubscription struct {
stopCh chan struct{}
closeOnce sync.Once
+ lock sync.Mutex
}
func (sub *GossipSubscription) checkIfTopicNeedsToEnabledOrDisabled() {
+ sub.lock.Lock()
+ defer sub.lock.Unlock()
var err error
expirationTime := sub.expiration.Load().(time.Time)
if sub.subscribed.Load() && time.Now().After(expirationTime) {
@@ -569,8 +572,12 @@ func (sub *GossipSubscription) OverwriteSubscriptionExpiry(expiry time.Time) {
// calls the cancel func for the subscriber and closes the topic and sub
func (s *GossipSubscription) Close() {
+ s.lock.Lock()
+ defer s.lock.Unlock()
s.closeOnce.Do(func() {
- close(s.stopCh)
+ if s.stopCh != nil {
+ close(s.stopCh)
+ }
if s.cf != nil {
s.cf()
}
diff --git a/cl/sentinel/service/start.go b/cl/sentinel/service/start.go
index 5df3ee9c2a1..b61a097c8f6 100644
--- a/cl/sentinel/service/start.go
+++ b/cl/sentinel/service/start.go
@@ -45,7 +45,6 @@ type ServerConfig struct {
Network string
Addr string
Creds credentials.TransportCredentials
- Validator bool
InitialStatus *cltypes.Status
}
@@ -76,7 +75,6 @@ func createSentinel(
indiciesDB kv.RwDB,
forkChoiceReader forkchoice.ForkChoiceStorageReader,
ethClock eth_clock.EthereumClock,
- validatorTopics bool,
logger log.Logger) (*sentinel.Sentinel, error) {
sent, err := sentinel.New(
context.Background(),
@@ -156,7 +154,6 @@ func StartSentinelService(
indiciesDB,
forkChoiceReader,
ethClock,
- srvCfg.Validator,
logger,
)
if err != nil {
diff --git a/cl/utils/bytes.go b/cl/utils/bytes.go
index e6c2ac25ff6..b9a77940523 100644
--- a/cl/utils/bytes.go
+++ b/cl/utils/bytes.go
@@ -18,6 +18,7 @@ package utils
import (
"encoding/binary"
+ "errors"
"math/bits"
"github.com/erigontech/erigon-lib/types/ssz"
@@ -155,3 +156,10 @@ func MergeBitlists(a, b []byte) {
a[i] |= b[i]
}
}
+
+func ExtractSlotFromSerializedBeaconState(beaconState []byte) (uint64, error) {
+ if len(beaconState) < 48 {
+ return 0, errors.New("checkpoint sync read failed, too short")
+ }
+ return binary.LittleEndian.Uint64(beaconState[40:48]), nil
+}
diff --git a/cl/utils/eth_clock/ethereum_clock.go b/cl/utils/eth_clock/ethereum_clock.go
index de7f38d900a..159b9bbcd67 100644
--- a/cl/utils/eth_clock/ethereum_clock.go
+++ b/cl/utils/eth_clock/ethereum_clock.go
@@ -48,15 +48,19 @@ type EthereumClock interface {
}
type forkNode struct {
- epoch uint64
- version [4]byte
+ epoch uint64
+ stateVersion clparams.StateVersion
+ version [4]byte
}
-func forkList(schedule map[common.Bytes4]uint64) (f []forkNode) {
- for version, epoch := range schedule {
- f = append(f, forkNode{epoch: epoch, version: version})
+func forkList(schedule map[common.Bytes4]clparams.VersionScheduleEntry) (f []forkNode) {
+ for version, entry := range schedule {
+ f = append(f, forkNode{epoch: entry.Epoch, version: version, stateVersion: entry.StateVersion})
}
sort.Slice(f, func(i, j int) bool {
+ if f[i].epoch == f[j].epoch {
+ return f[i].stateVersion < f[j].stateVersion
+ }
return f[i].epoch < f[j].epoch
})
return
diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go
index bdfd69ea4f4..9aecbfd135e 100644
--- a/cmd/capcli/cli.go
+++ b/cmd/capcli/cli.go
@@ -566,7 +566,8 @@ func (r *RetrieveHistoricalState) Run(ctx *Context) error {
var bor *freezeblocks.BorRoSnapshots
blockReader := freezeblocks.NewBlockReader(allSnapshots, bor)
- eth1Getter := getters.NewExecutionSnapshotReader(ctx, beaconConfig, blockReader, db)
+ eth1Getter := getters.NewExecutionSnapshotReader(ctx, blockReader, db)
+ eth1Getter.SetBeaconChainConfig(beaconConfig)
csn := freezeblocks.NewCaplinSnapshots(ethconfig.BlocksFreezing{}, beaconConfig, dirs, log.Root())
if err := csn.ReopenFolder(); err != nil {
return err
diff --git a/cmd/caplin/caplin1/run.go b/cmd/caplin/caplin1/run.go
index ca569eb3511..7ceb9a305c3 100644
--- a/cmd/caplin/caplin1/run.go
+++ b/cmd/caplin/caplin1/run.go
@@ -18,7 +18,9 @@ package caplin1
import (
"context"
+ "errors"
"fmt"
+ "math"
"os"
"path"
"time"
@@ -57,8 +59,10 @@ import (
"github.com/erigontech/erigon/cl/persistence/beacon_indicies"
"github.com/erigontech/erigon/cl/persistence/blob_storage"
"github.com/erigontech/erigon/cl/persistence/format/snapshot_format"
+ "github.com/erigontech/erigon/cl/persistence/genesisdb"
state_accessors "github.com/erigontech/erigon/cl/persistence/state"
"github.com/erigontech/erigon/cl/persistence/state/historical_states_reader"
+ "github.com/erigontech/erigon/cl/phase1/core/checkpoint_sync"
"github.com/erigontech/erigon/cl/phase1/core/state"
"github.com/erigontech/erigon/cl/phase1/execution_client"
"github.com/erigontech/erigon/cl/phase1/forkchoice"
@@ -111,21 +115,114 @@ func OpenCaplinDatabase(ctx context.Context,
{ // start ticking forkChoice
go func() {
<-ctx.Done()
- db.Close() // close sql database here
+ db.Close()
blobDB.Close() // close blob database here
}()
}
return db, blob_storage.NewBlobStore(blobDB, afero.NewBasePathFs(afero.NewOsFs(), blobDir), blobPruneDistance, beaconConfig, ethClock), nil
}
-func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngine, config *ethconfig.Config, networkConfig *clparams.NetworkConfig,
- beaconConfig *clparams.BeaconChainConfig, ethClock eth_clock.EthereumClock, state *state.CachingBeaconState, dirs datadir.Dirs, eth1Getter snapshot_format.ExecutionBlockReaderByNumber,
- snDownloader proto_downloader.DownloaderClient, indexDB kv.RwDB, blobStorage blob_storage.BlobStorage, creds credentials.TransportCredentials, snBuildSema *semaphore.Weighted, caplinOptions ...CaplinOption) error {
+func RunCaplinService(ctx context.Context, engine execution_client.ExecutionEngine, config clparams.CaplinConfig,
+ dirs datadir.Dirs, eth1Getter snapshot_format.ExecutionBlockReaderByNumber,
+ snDownloader proto_downloader.DownloaderClient, creds credentials.TransportCredentials, snBuildSema *semaphore.Weighted) error {
+
var (
- backfilling = config.CaplinConfig.Backfilling
- blobBackfilling = config.CaplinConfig.BlobBackfilling
- states = config.CaplinConfig.Archive
+ backfilling = config.Backfilling
+ blobBackfilling = config.BlobBackfilling
+ states = config.Archive
)
+ var networkConfig *clparams.NetworkConfig
+ var beaconConfig *clparams.BeaconChainConfig
+
+ var err error
+
+ var genesisState *state.CachingBeaconState
+ var genesisDb genesisdb.GenesisDB
+
+ if config.IsDevnet() {
+ config.NetworkId = clparams.CustomNetwork // Force custom network
+ if config.HaveInvalidDevnetParams() {
+ return errors.New("devnet config and genesis state paths must be set together")
+ }
+ networkConfig, _ = clparams.GetConfigsByNetwork(clparams.MainnetNetwork)
+ tmp, err := clparams.CustomConfig(config.CustomConfigPath)
+ if err != nil {
+ return err
+ }
+ beaconConfig = &tmp
+ genesisDb = genesisdb.NewGenesisDB(beaconConfig, dirs.CaplinGenesis)
+
+ stateBytes, err := os.ReadFile(config.CustomGenesisStatePath)
+ if err != nil {
+ return fmt.Errorf("could not read provided genesis state file: %s", err)
+ }
+ genesisState = state.New(beaconConfig)
+
+ if genesisState.DecodeSSZ(stateBytes, int(beaconConfig.GetCurrentStateVersion(beaconConfig.GenesisEpoch))); err != nil {
+ return fmt.Errorf("could not decode genesis state: %s", err)
+ }
+ } else {
+ networkConfig, beaconConfig = clparams.GetConfigsByNetwork(config.NetworkId)
+ genesisDb = genesisdb.NewGenesisDB(beaconConfig, dirs.CaplinGenesis)
+
+ isGenesisDBInitialized, err := genesisDb.IsInitialized()
+ if err != nil {
+ return err
+ }
+
+ // If genesis state is provided and is hardcoded, use it
+ if initial_state.IsGenesisStateSupported(config.NetworkId) && !isGenesisDBInitialized {
+ genesisState, err = initial_state.GetGenesisState(config.NetworkId)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
+ if config.NetworkId == clparams.CustomNetwork {
+ config.NetworkId = clparams.NetworkType(beaconConfig.DepositNetworkID)
+ }
+
+ if len(config.BootstrapNodes) > 0 {
+ networkConfig.BootNodes = config.BootstrapNodes
+ }
+
+ if len(config.StaticPeers) > 0 {
+ networkConfig.StaticPeers = config.StaticPeers
+ }
+
+ genesisDb.Initialize(genesisState)
+
+ state, err := checkpoint_sync.ReadOrFetchLatestBeaconState(ctx, dirs, beaconConfig, config, genesisDb)
+ if err != nil {
+ return err
+ }
+ ethClock := eth_clock.NewEthereumClock(state.GenesisTime(), state.GenesisValidatorsRoot(), beaconConfig)
+
+ pruneBlobDistance := uint64(128600)
+ if config.BlobBackfilling || config.BlobPruningDisabled {
+ pruneBlobDistance = math.MaxUint64
+ }
+
+ indexDB, blobStorage, err := OpenCaplinDatabase(ctx, beaconConfig, ethClock, dirs.CaplinIndexing, dirs.CaplinBlobs, engine, false, pruneBlobDistance)
+ if err != nil {
+ return err
+ }
+
+ caplinOptions := []CaplinOption{}
+ if config.BeaconAPIRouter.Builder {
+ if config.RelayUrlExist() {
+ caplinOptions = append(caplinOptions, WithBuilder(config.MevRelayUrl, beaconConfig))
+ } else {
+ log.Warn("builder api enable but relay url not set. Skipping builder mode")
+ config.BeaconAPIRouter.Builder = false
+ }
+ }
+ log.Info("Starting caplin")
+
+ if eth1Getter != nil {
+ eth1Getter.SetBeaconChainConfig(beaconConfig)
+ }
ctx, cn := context.WithCancel(ctx)
defer cn()
@@ -145,7 +242,7 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
caplinFcuPath := path.Join(dirs.Tmp, "caplin-forkchoice")
os.RemoveAll(caplinFcuPath)
- err := os.MkdirAll(caplinFcuPath, 0o755)
+ err = os.MkdirAll(caplinFcuPath, 0o755)
if err != nil {
return err
}
@@ -155,9 +252,9 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
syncContributionPool := sync_contribution_pool.NewSyncContributionPool(beaconConfig)
emitters := beaconevents.NewEventEmitter()
aggregationPool := aggregation.NewAggregationPool(ctx, beaconConfig, networkConfig, ethClock)
- validatorMonitor := monitor.NewValidatorMonitor(config.CaplinConfig.EnableValidatorMonitor, ethClock, beaconConfig, syncedDataManager)
+ validatorMonitor := monitor.NewValidatorMonitor(config.EnableValidatorMonitor, ethClock, beaconConfig, syncedDataManager)
forkChoice, err := forkchoice.NewForkChoiceStore(
- ethClock, state, engine, pool, fork_graph.NewForkGraphDisk(state, fcuFs, config.BeaconRouter, emitters),
+ ethClock, state, engine, pool, fork_graph.NewForkGraphDisk(state, fcuFs, config.BeaconAPIRouter, emitters),
emitters, syncedDataManager, blobStorage, validatorMonitor)
if err != nil {
logger.Error("Could not create forkchoice", "err", err)
@@ -188,10 +285,9 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
EnableBlocks: true,
ActiveIndicies: uint64(len(activeIndicies)),
}, rcsn, blobStorage, indexDB, &service.ServerConfig{
- Network: "tcp",
- Addr: fmt.Sprintf("%s:%d", config.SentinelAddr, config.SentinelPort),
- Creds: creds,
- Validator: config.BeaconRouter.Validator,
+ Network: "tcp",
+ Addr: fmt.Sprintf("%s:%d", config.SentinelAddr, config.SentinelPort),
+ Creds: creds,
InitialStatus: &cltypes.Status{
ForkDigest: forkDigest,
FinalizedRoot: state.FinalizedCheckpoint().BlockRoot(),
@@ -274,11 +370,7 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
return err
}
}
- // get the initial state
- genesisState, err := initial_state.GetGenesisState(clparams.NetworkType(beaconConfig.DepositNetworkID))
- if err != nil {
- return err
- }
+
antiq := antiquary.NewAntiquary(ctx, blobStorage, genesisState, vTables, beaconConfig, dirs, snDownloader, indexDB, csn, rcsn, logger, states, backfilling, blobBackfilling, snBuildSema)
// Create the antiquary
go func() {
@@ -293,7 +385,7 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
statesReader := historical_states_reader.NewHistoricalStatesReader(beaconConfig, rcsn, vTables, genesisState)
validatorParameters := validator_params.NewValidatorParams()
- if config.BeaconRouter.Active {
+ if config.BeaconAPIRouter.Active {
apiHandler := handler.NewApiHandler(
logger,
networkConfig,
@@ -307,7 +399,7 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
statesReader,
sentinel,
params.GitTag,
- &config.BeaconRouter,
+ &config.BeaconAPIRouter,
emitters,
blobStorage,
csn,
@@ -329,8 +421,8 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
)
go beacon.ListenAndServe(&beacon.LayeredBeaconHandler{
ArchiveApi: apiHandler,
- }, config.BeaconRouter)
- log.Info("Beacon API started", "addr", config.BeaconRouter.Address)
+ }, config.BeaconAPIRouter)
+ log.Info("Beacon API started", "addr", config.BeaconAPIRouter.Address)
}
stageCfg := stages.ClStagesCfg(
@@ -346,7 +438,7 @@ func RunCaplinPhase1(ctx context.Context, engine execution_client.ExecutionEngin
csn,
rcsn,
dirs,
- uint64(config.LoopBlockLimit),
+ config.LoopBlockLimit,
backfilling,
blobBackfilling,
syncedDataManager,
diff --git a/cmd/caplin/caplincli/config.go b/cmd/caplin/caplincli/config.go
index 5b2129da027..7976b0cef0a 100644
--- a/cmd/caplin/caplincli/config.go
+++ b/cmd/caplin/caplincli/config.go
@@ -28,7 +28,6 @@ import (
"github.com/erigontech/erigon-lib/common/datadir"
"github.com/erigontech/erigon-lib/log/v3"
"github.com/erigontech/erigon/cl/clparams"
- "github.com/erigontech/erigon/cl/phase1/core/state"
"github.com/erigontech/erigon/cmd/caplin/caplinflags"
"github.com/erigontech/erigon/cmd/sentinel/sentinelcli"
"github.com/erigontech/erigon/cmd/utils"
@@ -40,28 +39,25 @@ type CaplinCliCfg struct {
Chaindata string `json:"chaindata"`
ErigonPrivateApi string `json:"erigon_private_api"`
- TransitionChain bool `json:"transition_chain"`
- InitialSync bool `json:"initial_sync"`
AllowedEndpoints []string `json:"endpoints"`
BeaconApiReadTimeout time.Duration `json:"beacon_api_read_timeout"`
BeaconApiWriteTimeout time.Duration `json:"beacon_api_write_timeout"`
BeaconAddr string `json:"beacon_addr"`
BeaconProtocol string `json:"beacon_protocol"`
- RecordMode bool `json:"record_mode"`
- RecordDir string `json:"record_dir"`
DataDir string `json:"data_dir"`
RunEngineAPI bool `json:"run_engine_api"`
EngineAPIAddr string `json:"engine_api_addr"`
EngineAPIPort int `json:"engine_api_port"`
MevRelayUrl string `json:"mev_relay_url"`
+ CustomConfig string `json:"custom_config"`
+ CustomGenesisState string `json:"custom_genesis_state"`
JwtSecret []byte
AllowedMethods []string `json:"allowed_methods"`
AllowedOrigins []string `json:"allowed_origins"`
AllowCredentials bool `json:"allow_credentials"`
- InitalState *state.CachingBeaconState
- Dirs datadir.Dirs
+ Dirs datadir.Dirs
}
func SetupCaplinCli(ctx *cli.Context) (cfg *CaplinCliCfg, err error) {
@@ -73,22 +69,6 @@ func SetupCaplinCli(ctx *cli.Context) (cfg *CaplinCliCfg, err error) {
cfg.ErigonPrivateApi = ctx.String(caplinflags.ErigonPrivateApiFlag.Name)
- //T TODO(Giulio2002): Refactor later
- // if ctx.String(sentinelflags.BeaconConfigFlag.Name) != "" {
- // var stateByte []byte
- // // Now parse genesis time and genesis fork
- // if *cfg.GenesisCfg, stateByte, err = clparams.ParseGenesisSSZToGenesisConfig(
- // ctx.String(sentinelflags.GenesisSSZFlag.Name),
- // cfg.BeaconCfg.GetCurrentStateVersion(0)); err != nil {
- // return nil, err
- // }
-
- // cfg.InitalState = state.New(cfg.BeaconCfg)
- // if cfg.InitalState.DecodeSSZ(stateByte, int(cfg.BeaconCfg.GetCurrentStateVersion(0))); err != nil {
- // return nil, err
- // }
- // }
-
cfg.AllowedEndpoints = ctx.StringSlice(utils.BeaconAPIFlag.Name)
cfg.BeaconApiReadTimeout = time.Duration(ctx.Uint64(caplinflags.BeaconApiReadTimeout.Name)) * time.Second
@@ -98,8 +78,7 @@ func SetupCaplinCli(ctx *cli.Context) (cfg *CaplinCliCfg, err error) {
cfg.AllowedMethods = ctx.StringSlice(utils.BeaconApiAllowMethodsFlag.Name)
cfg.AllowedOrigins = ctx.StringSlice(utils.BeaconApiAllowOriginsFlag.Name)
cfg.BeaconProtocol = "tcp"
- cfg.RecordMode = ctx.Bool(caplinflags.RecordModeFlag.Name)
- cfg.RecordDir = ctx.String(caplinflags.RecordModeDir.Name)
+
cfg.DataDir = ctx.String(utils.DataDirFlag.Name)
cfg.Dirs = datadir.New(cfg.DataDir)
@@ -122,10 +101,12 @@ func SetupCaplinCli(ctx *cli.Context) (cfg *CaplinCliCfg, err error) {
cfg.Chaindata = ctx.String(caplinflags.ChaindataFlag.Name)
- cfg.TransitionChain = ctx.Bool(caplinflags.TransitionChainFlag.Name)
- cfg.InitialSync = ctx.Bool(caplinflags.InitSyncFlag.Name)
cfg.MevRelayUrl = ctx.String(caplinflags.MevRelayUrl.Name)
+ // Custom Chain
+ cfg.CustomConfig = ctx.String(caplinflags.CustomConfig.Name)
+ cfg.CustomGenesisState = ctx.String(caplinflags.CustomGenesisState.Name)
+
return cfg, err
}
diff --git a/cmd/caplin/caplinflags/flags.go b/cmd/caplin/caplinflags/flags.go
index b9ec72af1c8..022f1d83004 100644
--- a/cmd/caplin/caplinflags/flags.go
+++ b/cmd/caplin/caplinflags/flags.go
@@ -28,16 +28,14 @@ var CliFlags = []cli.Flag{
&BeaconApiPort,
&BeaconApiAddr,
&ChaindataFlag,
- &BeaconDBModeFlag,
- &TransitionChainFlag,
&InitSyncFlag,
- &RecordModeDir,
- &RecordModeFlag,
&RunEngineAPI,
&EngineApiHostFlag,
&EngineApiPortFlag,
&MevRelayUrl,
&JwtSecret,
+ &CustomConfig,
+ &CustomGenesisState,
&utils.DataDirFlag,
&utils.BeaconApiAllowCredentialsFlag,
&utils.BeaconApiAllowMethodsFlag,
@@ -51,11 +49,6 @@ var (
Usage: "chaindata of database",
Value: "",
}
- NoBeaconApi = cli.BoolFlag{
- Name: "no-beacon-api",
- Usage: "turn off the beacon api",
- Value: false,
- }
BeaconApiReadTimeout = cli.Uint64Flag{
Name: "beacon.api.read.timeout",
Usage: "Sets the seconds for a read time out in the beacon api",
@@ -76,30 +69,13 @@ var (
Usage: "sets the port to listen for beacon api requests",
Value: 5555,
}
- BeaconDBModeFlag = cli.StringFlag{
- Name: "beacon-db-mode",
- Usage: "level of storing on beacon chain, minimal(only 500k blocks stored), full (all blocks stored), light (no blocks stored)",
- Value: "full",
- }
- TransitionChainFlag = cli.BoolFlag{
- Name: "transition-chain",
- Usage: "enable chain transition",
- }
+
InitSyncFlag = cli.BoolFlag{
Value: false,
Name: "initial-sync",
Usage: "use initial-sync",
}
- RecordModeFlag = cli.BoolFlag{
- Value: false,
- Name: "record-mode",
- Usage: "enable/disable record mode",
- }
- RecordModeDir = cli.StringFlag{
- Value: "caplin-recordings",
- Name: "record-dir",
- Usage: "directory for states and block recordings",
- }
+
ErigonPrivateApiFlag = cli.StringFlag{
Name: "private.api.addr",
Usage: "connect to existing erigon instance",
@@ -130,4 +106,14 @@ var (
Usage: "Http URL of the MEV relay",
Value: "",
}
+ CustomConfig = cli.StringFlag{
+ Name: "custom-config",
+ Usage: "Path to custom config file",
+ Value: "",
+ }
+ CustomGenesisState = cli.StringFlag{
+ Name: "custom-genesis-state",
+ Usage: "Path to custom genesis state file",
+ Value: "",
+ }
)
diff --git a/cmd/caplin/main.go b/cmd/caplin/main.go
index 0d25632e5df..ca94f0a43e2 100644
--- a/cmd/caplin/main.go
+++ b/cmd/caplin/main.go
@@ -30,11 +30,7 @@ import (
"github.com/erigontech/erigon-lib/log/v3"
"github.com/erigontech/erigon/cl/beacon/beacon_router_configuration"
"github.com/erigontech/erigon/cl/clparams"
- "github.com/erigontech/erigon/cl/phase1/core/checkpoint_sync"
- "github.com/erigontech/erigon/cl/phase1/core/state"
execution_client2 "github.com/erigontech/erigon/cl/phase1/execution_client"
- "github.com/erigontech/erigon/cl/utils/eth_clock"
- "github.com/erigontech/erigon/eth/ethconfig"
"github.com/erigontech/erigon/cmd/caplin/caplin1"
"github.com/erigontech/erigon/cmd/caplin/caplincli"
@@ -89,39 +85,6 @@ func runCaplinNode(cliCtx *cli.Context) error {
// Either start from genesis or a checkpoint
ctx, cn := context.WithCancel(cliCtx.Context)
defer cn()
- var state *state.CachingBeaconState
- if cfg.InitialSync {
- state = cfg.InitalState
- } else {
- state, err = checkpoint_sync.NewRemoteCheckpointSync(cfg.BeaconCfg, cfg.NetworkType).GetLatestBeaconState(ctx)
- if err != nil {
- return err
- }
- }
-
- ethClock := eth_clock.NewEthereumClock(state.GenesisTime(), state.GenesisValidatorsRoot(), cfg.BeaconCfg)
-
- // sentinel, err := service.StartSentinelService(&sentinel.SentinelConfig{
- // IpAddr: cfg.Addr,
- // Port: int(cfg.Port),
- // TCPPort: cfg.ServerTcpPort,
- // GenesisConfig: cfg.GenesisCfg,
- // NetworkConfig: cfg.NetworkCfg,
- // BeaconConfig: cfg.BeaconCfg,
- // NoDiscovery: cfg.NoDiscovery,
- // EnableBlocks: true,
- // }, nil, nil, &service.ServerConfig{Network: cfg.ServerProtocol, Addr: cfg.ServerAddr}, nil, &cltypes.Status{
- // ForkDigest: forkDigest,
- // FinalizedRoot: state.FinalizedCheckpoint().BlockRoot(),
- // FinalizedEpoch: state.FinalizedCheckpoint().Epoch(),
- // HeadSlot: state.FinalizedCheckpoint().Epoch() * cfg.BeaconCfg.SlotsPerEpoch,
- // HeadRoot: state.FinalizedCheckpoint().BlockRoot(),
- // }, log.Root())
- // if err != nil {
- // log.Error("Could not start sentinel", "err", err)
- // }
-
- // log.Info("Sentinel started", "addr", cfg.ServerAddr)
if err != nil {
log.Error("[Checkpoint Sync] Failed", "reason", err)
@@ -136,31 +99,23 @@ func runCaplinNode(cliCtx *cli.Context) error {
log.Info("Started Engine API RPC Client", "addr", cfg.EngineAPIAddr)
executionEngine = cc
}
-
- indiciesDB, blobStorage, err := caplin1.OpenCaplinDatabase(ctx, cfg.BeaconCfg, ethClock, cfg.Dirs.CaplinIndexing, cfg.Dirs.CaplinBlobs, executionEngine, false, 100_000)
+ chainName := cliCtx.String(utils.ChainFlag.Name)
+ _, _, networkId, err := clparams.GetConfigsByNetworkName(chainName)
if err != nil {
- return err
+ log.Info("Could not get network id from chain name, setting it to custom network id")
+ networkId = clparams.CustomNetwork
}
blockSnapBuildSema := semaphore.NewWeighted(int64(dbg.BuildSnapshotAllowance))
- var options []caplin1.CaplinOption
- // builder option
- if rcfg.Builder {
- if cfg.MevRelayUrl == "" {
- log.Warn("builder mode requires mev_relay_url, but it is not set. Skipping builder mode")
- rcfg.Builder = false
- } else {
- log.Info("Starting with builder mode")
- options = append(options, caplin1.WithBuilder(cfg.MevRelayUrl, cfg.BeaconCfg))
- }
- }
-
- return caplin1.RunCaplinPhase1(ctx, executionEngine, ðconfig.Config{
+ return caplin1.RunCaplinService(ctx, executionEngine, clparams.CaplinConfig{
CaplinDiscoveryAddr: cfg.Addr,
CaplinDiscoveryPort: uint64(cfg.Port),
CaplinDiscoveryTCPPort: uint64(cfg.ServerTcpPort),
- BeaconRouter: rcfg,
- CaplinConfig: clparams.CaplinConfig{},
- }, cfg.NetworkCfg, cfg.BeaconCfg, ethClock, state, cfg.Dirs, nil, nil, indiciesDB, blobStorage, nil, blockSnapBuildSema, options...)
+ BeaconAPIRouter: rcfg,
+ NetworkId: networkId,
+ MevRelayUrl: cfg.MevRelayUrl,
+ CustomConfigPath: cfg.CustomConfig,
+ CustomGenesisStatePath: cfg.CustomGenesisState,
+ }, cfg.Dirs, nil, nil, nil, blockSnapBuildSema)
}
diff --git a/cmd/sentinel/main.go b/cmd/sentinel/main.go
index 6416044190f..c8996173d72 100644
--- a/cmd/sentinel/main.go
+++ b/cmd/sentinel/main.go
@@ -23,12 +23,14 @@ import (
"github.com/erigontech/erigon-lib/common/disk"
"github.com/erigontech/erigon-lib/common/mem"
+ "github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/cl/phase1/core/checkpoint_sync"
"github.com/erigontech/erigon/cl/sentinel"
"github.com/erigontech/erigon/cl/sentinel/service"
"github.com/erigontech/erigon/cl/utils/eth_clock"
"github.com/erigontech/erigon/cmd/sentinel/sentinelcli"
"github.com/erigontech/erigon/cmd/sentinel/sentinelflags"
+ "github.com/erigontech/erigon/cmd/utils"
"github.com/urfave/cli/v2"
@@ -56,11 +58,24 @@ func runSentinelNode(cliCtx *cli.Context) error {
log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(cfg.LogLvl), log.StderrHandler))
log.Info("[Sentinel] running sentinel with configuration", "cfg", cfg)
+ chainName := cliCtx.String(utils.ChainFlag.Name)
+ networkCfg, beaconCfg, networkType, err := clparams.GetConfigsByNetworkName(chainName)
+ if err != nil {
+ return err
+ }
+
+ if len(cfg.Bootnodes) > 0 {
+ networkCfg.BootNodes = cfg.Bootnodes
+ }
+ if len(cfg.StaticPeers) > 0 {
+ networkCfg.StaticPeers = cfg.StaticPeers
+ }
+
// setup periodic logging and prometheus updates
go mem.LogMemStats(cliCtx.Context, log.Root())
go disk.UpdateDiskStats(cliCtx.Context, log.Root())
- bs, err := checkpoint_sync.NewRemoteCheckpointSync(cfg.BeaconCfg, cfg.NetworkType).GetLatestBeaconState(cliCtx.Context)
+ bs, err := checkpoint_sync.NewRemoteCheckpointSync(beaconCfg, networkType).GetLatestBeaconState(cliCtx.Context)
if err != nil {
return err
}
@@ -68,12 +83,12 @@ func runSentinelNode(cliCtx *cli.Context) error {
IpAddr: cfg.Addr,
Port: int(cfg.Port),
TCPPort: cfg.ServerTcpPort,
- NetworkConfig: cfg.NetworkCfg,
- BeaconConfig: cfg.BeaconCfg,
+ NetworkConfig: networkCfg,
+ BeaconConfig: beaconCfg,
NoDiscovery: cfg.NoDiscovery,
LocalDiscovery: cfg.LocalDiscovery,
EnableBlocks: false,
- }, nil, nil, nil, &service.ServerConfig{Network: cfg.ServerProtocol, Addr: cfg.ServerAddr}, eth_clock.NewEthereumClock(bs.GenesisTime(), bs.GenesisValidatorsRoot(), cfg.BeaconCfg), nil, log.Root())
+ }, nil, nil, nil, &service.ServerConfig{Network: cfg.ServerProtocol, Addr: cfg.ServerAddr}, eth_clock.NewEthereumClock(bs.GenesisTime(), bs.GenesisValidatorsRoot(), beaconCfg), nil, log.Root())
if err != nil {
log.Error("[Sentinel] Could not start sentinel", "err", err)
return err
diff --git a/cmd/sentinel/sentinelcli/cliSettings.go b/cmd/sentinel/sentinelcli/cliSettings.go
index 0a155340d9d..ea96c86bd2b 100644
--- a/cmd/sentinel/sentinelcli/cliSettings.go
+++ b/cmd/sentinel/sentinelcli/cliSettings.go
@@ -17,12 +17,9 @@
package sentinelcli
import (
- "errors"
"fmt"
- "github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/cmd/sentinel/sentinelflags"
- "github.com/erigontech/erigon/cmd/utils"
"github.com/erigontech/erigon-lib/common"
@@ -34,37 +31,21 @@ import (
)
type SentinelCliCfg struct {
- BeaconCfg *clparams.BeaconChainConfig
- NetworkCfg *clparams.NetworkConfig
- NetworkType clparams.NetworkType
- Port uint `json:"port"`
- Addr string `json:"address"`
- ServerAddr string `json:"server_addr"`
- ServerProtocol string `json:"server_protocol"`
- ServerTcpPort uint `json:"server_tcp_port"`
- LogLvl uint `json:"log_level"`
- NoDiscovery bool `json:"no_discovery"`
- LocalDiscovery bool `json:"local_discovery"`
+ Port uint `json:"port"`
+ Addr string `json:"address"`
+ ServerAddr string `json:"server_addr"`
+ ServerProtocol string `json:"server_protocol"`
+ ServerTcpPort uint `json:"server_tcp_port"`
+ LogLvl uint `json:"log_level"`
+ NoDiscovery bool `json:"no_discovery"`
+ LocalDiscovery bool `json:"local_discovery"`
+ Bootnodes []string `json:"bootnodes"`
+ StaticPeers []string `json:"static_peers"`
}
func SetupSentinelCli(ctx *cli.Context) (*SentinelCliCfg, error) {
cfg := &SentinelCliCfg{}
- chainName := ctx.String(utils.ChainFlag.Name)
- var err error
- cfg.NetworkCfg, cfg.BeaconCfg, cfg.NetworkType, err = clparams.GetConfigsByNetworkName(chainName)
- if err != nil {
- return nil, err
- }
- if ctx.String(sentinelflags.BeaconConfigFlag.Name) != "" {
- cfg.BeaconCfg = new(clparams.BeaconChainConfig)
- if *cfg.BeaconCfg, err = clparams.CustomConfig(ctx.String(sentinelflags.BeaconConfigFlag.Name)); err != nil {
- return nil, err
- }
- if ctx.String(sentinelflags.GenesisSSZFlag.Name) == "" {
- return nil, errors.New("no genesis file provided")
- }
- }
cfg.ServerAddr = fmt.Sprintf("%s:%d", ctx.String(sentinelflags.SentinelServerAddr.Name), ctx.Int(sentinelflags.SentinelServerPort.Name))
cfg.ServerProtocol = "tcp"
@@ -80,10 +61,10 @@ func SetupSentinelCli(ctx *cli.Context) (*SentinelCliCfg, error) {
// Process bootnodes
if ctx.String(sentinelflags.BootnodesFlag.Name) != "" {
- cfg.NetworkCfg.BootNodes = common.CliString2Array(ctx.String(sentinelflags.BootnodesFlag.Name))
+ cfg.Bootnodes = common.CliString2Array(ctx.String(sentinelflags.BootnodesFlag.Name))
}
if ctx.String(sentinelflags.SentinelStaticPeersFlag.Name) != "" {
- cfg.NetworkCfg.StaticPeers = common.CliString2Array(ctx.String(sentinelflags.SentinelStaticPeersFlag.Name))
+ cfg.StaticPeers = common.CliString2Array(ctx.String(sentinelflags.SentinelStaticPeersFlag.Name))
}
return cfg, nil
}
diff --git a/cmd/sentinel/sentinelflags/flags.go b/cmd/sentinel/sentinelflags/flags.go
index 5d885483827..f1e4c2a73f1 100644
--- a/cmd/sentinel/sentinelflags/flags.go
+++ b/cmd/sentinel/sentinelflags/flags.go
@@ -31,8 +31,6 @@ var CliFlags = []cli.Flag{
&SentinelTcpPort,
&NoDiscovery,
&BootnodesFlag,
- &BeaconConfigFlag,
- &GenesisSSZFlag,
&SentinelStaticPeersFlag,
}
@@ -77,16 +75,7 @@ var (
Usage: "Comma separated enode URLs for P2P discovery bootstrap",
Value: "",
}
- BeaconConfigFlag = cli.StringFlag{
- Name: "beacon-config",
- Usage: "Path to beacon config",
- Value: "",
- }
- GenesisSSZFlag = cli.StringFlag{
- Name: "genesis-ssz",
- Usage: "Path to genesis ssz",
- Value: "",
- }
+
SentinelStaticPeersFlag = cli.StringFlag{
Name: "sentinel.staticpeers",
Usage: "connect to comma-separated Consensus static peers",
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 4d7cff453de..ca5cc62061c 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -871,6 +871,11 @@ var (
Usage: "Port for sentinel",
Value: 7777,
}
+ SentinelBootnodes = cli.StringSliceFlag{
+ Name: "sentinel.bootnodes",
+ Usage: "Comma separated enode URLs for P2P discovery bootstrap",
+ Value: cli.NewStringSlice(),
+ }
OtsSearchMaxCapFlag = cli.Uint64Flag{
Name: "ots.search.max.pagesize",
@@ -1025,6 +1030,16 @@ var (
Usage: "set the cors' allow origins",
Value: cli.NewStringSlice(),
}
+ CaplinCustomConfigFlag = cli.StringFlag{
+ Name: "caplin.custom-config",
+ Usage: "set the custom config for caplin",
+ Value: "",
+ }
+ CaplinCustomGenesisFlag = cli.StringFlag{
+ Name: "caplin.custom-genesis",
+ Usage: "set the custom genesis for caplin",
+ Value: "",
+ }
DiagDisabledFlag = cli.BoolFlag{
Name: "diagnostics.disabled",
Usage: "Disable diagnostics",
@@ -1679,18 +1694,18 @@ func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {
func setBeaconAPI(ctx *cli.Context, cfg *ethconfig.Config) error {
allowed := ctx.StringSlice(BeaconAPIFlag.Name)
- if err := cfg.BeaconRouter.UnwrapEndpointsList(allowed); err != nil {
+ if err := cfg.CaplinConfig.BeaconAPIRouter.UnwrapEndpointsList(allowed); err != nil {
return err
}
- cfg.BeaconRouter.Protocol = ctx.String(BeaconApiProtocolFlag.Name)
- cfg.BeaconRouter.Address = fmt.Sprintf("%s:%d", ctx.String(BeaconApiAddrFlag.Name), ctx.Int(BeaconApiPortFlag.Name))
- cfg.BeaconRouter.ReadTimeTimeout = time.Duration(ctx.Uint64(BeaconApiReadTimeoutFlag.Name)) * time.Second
- cfg.BeaconRouter.WriteTimeout = time.Duration(ctx.Uint64(BeaconApiWriteTimeoutFlag.Name)) * time.Second
- cfg.BeaconRouter.IdleTimeout = time.Duration(ctx.Uint64(BeaconApiIdleTimeoutFlag.Name)) * time.Second
- cfg.BeaconRouter.AllowedMethods = ctx.StringSlice(BeaconApiAllowMethodsFlag.Name)
- cfg.BeaconRouter.AllowedOrigins = ctx.StringSlice(BeaconApiAllowOriginsFlag.Name)
- cfg.BeaconRouter.AllowCredentials = ctx.Bool(BeaconApiAllowCredentialsFlag.Name)
+ cfg.CaplinConfig.BeaconAPIRouter.Protocol = ctx.String(BeaconApiProtocolFlag.Name)
+ cfg.CaplinConfig.BeaconAPIRouter.Address = fmt.Sprintf("%s:%d", ctx.String(BeaconApiAddrFlag.Name), ctx.Int(BeaconApiPortFlag.Name))
+ cfg.CaplinConfig.BeaconAPIRouter.ReadTimeTimeout = time.Duration(ctx.Uint64(BeaconApiReadTimeoutFlag.Name)) * time.Second
+ cfg.CaplinConfig.BeaconAPIRouter.WriteTimeout = time.Duration(ctx.Uint64(BeaconApiWriteTimeoutFlag.Name)) * time.Second
+ cfg.CaplinConfig.BeaconAPIRouter.IdleTimeout = time.Duration(ctx.Uint64(BeaconApiIdleTimeoutFlag.Name)) * time.Second
+ cfg.CaplinConfig.BeaconAPIRouter.AllowedMethods = ctx.StringSlice(BeaconApiAllowMethodsFlag.Name)
+ cfg.CaplinConfig.BeaconAPIRouter.AllowedOrigins = ctx.StringSlice(BeaconApiAllowOriginsFlag.Name)
+ cfg.CaplinConfig.BeaconAPIRouter.AllowCredentials = ctx.Bool(BeaconApiAllowCredentialsFlag.Name)
return nil
}
@@ -1707,6 +1722,8 @@ func setCaplin(ctx *cli.Context, cfg *ethconfig.Config) {
if checkpointUrls := ctx.StringSlice(CaplinCheckpointSyncUrlFlag.Name); len(checkpointUrls) > 0 {
clparams.ConfigurableCheckpointsURLs = checkpointUrls
}
+ cfg.CaplinConfig.CustomConfigPath = ctx.String(CaplinCustomConfigFlag.Name)
+ cfg.CaplinConfig.CustomGenesisStatePath = ctx.String(CaplinCustomGenesisFlag.Name)
}
func setSilkworm(ctx *cli.Context, cfg *ethconfig.Config) {
@@ -1767,11 +1784,12 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
// SetEthConfig applies eth-related command line flags to the config.
func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.Config, logger log.Logger) {
- cfg.CaplinDiscoveryAddr = ctx.String(CaplinDiscoveryAddrFlag.Name)
- cfg.CaplinDiscoveryPort = ctx.Uint64(CaplinDiscoveryPortFlag.Name)
- cfg.CaplinDiscoveryTCPPort = ctx.Uint64(CaplinDiscoveryTCPPortFlag.Name)
- cfg.SentinelAddr = ctx.String(SentinelAddrFlag.Name)
- cfg.SentinelPort = ctx.Uint64(SentinelPortFlag.Name)
+ cfg.CaplinConfig.CaplinDiscoveryAddr = ctx.String(CaplinDiscoveryAddrFlag.Name)
+ cfg.CaplinConfig.CaplinDiscoveryPort = ctx.Uint64(CaplinDiscoveryPortFlag.Name)
+ cfg.CaplinConfig.CaplinDiscoveryTCPPort = ctx.Uint64(CaplinDiscoveryTCPPortFlag.Name)
+ cfg.CaplinConfig.SentinelAddr = ctx.String(SentinelAddrFlag.Name)
+ cfg.CaplinConfig.SentinelPort = ctx.Uint64(SentinelPortFlag.Name)
+ cfg.CaplinConfig.BootstrapNodes = ctx.StringSlice(SentinelBootnodes.Name)
chain := ctx.String(ChainFlag.Name) // mainnet by default
if ctx.IsSet(NetworkIdFlag.Name) {
@@ -1905,7 +1923,7 @@ func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.C
cfg.TxPool.OverridePragueTime = cfg.OverridePragueTime
}
- if clparams.EmbeddedSupported(cfg.NetworkID) {
+ if clparams.EmbeddedSupported(cfg.NetworkID) || cfg.CaplinConfig.IsDevnet() {
cfg.InternalCL = !ctx.Bool(ExternalConsensusFlag.Name)
}
diff --git a/core/genesis_write.go b/core/genesis_write.go
index 3833519e92b..2ac83c64453 100644
--- a/core/genesis_write.go
+++ b/core/genesis_write.go
@@ -94,7 +94,7 @@ func CommitGenesisBlockWithOverride(db kv.RwDB, genesis *types.Genesis, override
}
func WriteGenesisBlock(tx kv.RwTx, genesis *types.Genesis, overridePragueTime *big.Int, dirs datadir.Dirs, logger log.Logger) (*chain.Config, *types.Block, error) {
- if err := rawdb.WriteGenesis(tx, genesis); err != nil {
+ if err := rawdb.WriteGenesisIfNotExist(tx, genesis); err != nil {
return nil, nil, err
}
diff --git a/core/rawdb/accessors_metadata.go b/core/rawdb/accessors_metadata.go
index 4d36344bf71..d8e7ab6d65b 100644
--- a/core/rawdb/accessors_metadata.go
+++ b/core/rawdb/accessors_metadata.go
@@ -86,7 +86,15 @@ func DeleteChainConfig(db kv.Deleter, hash libcommon.Hash) error {
return db.Delete(kv.ConfigTable, hash[:])
}
-func WriteGenesis(db kv.Putter, g *types.Genesis) error {
+func WriteGenesisIfNotExist(db kv.RwTx, g *types.Genesis) error {
+ has, err := db.Has(kv.ConfigTable, kv.GenesisKey)
+ if err != nil {
+ return err
+ }
+ if has {
+ return nil
+ }
+
// Marshal json g
val, err := json.Marshal(g)
if err != nil {
diff --git a/erigon-lib/common/datadir/dirs.go b/erigon-lib/common/datadir/dirs.go
index d8020dd6b62..05566da536b 100644
--- a/erigon-lib/common/datadir/dirs.go
+++ b/erigon-lib/common/datadir/dirs.go
@@ -48,6 +48,7 @@ type Dirs struct {
CaplinBlobs string
CaplinIndexing string
CaplinLatest string
+ CaplinGenesis string
}
func New(datadir string) Dirs {
@@ -77,11 +78,12 @@ func New(datadir string) Dirs {
CaplinBlobs: filepath.Join(datadir, "caplin", "blobs"),
CaplinIndexing: filepath.Join(datadir, "caplin", "indexing"),
CaplinLatest: filepath.Join(datadir, "caplin", "latest"),
+ CaplinGenesis: filepath.Join(datadir, "caplin", "genesis"),
}
dir.MustExist(dirs.Chaindata, dirs.Tmp,
dirs.SnapIdx, dirs.SnapHistory, dirs.SnapDomain, dirs.SnapAccessors,
- dirs.Downloader, dirs.TxPool, dirs.Nodes, dirs.CaplinBlobs, dirs.CaplinIndexing, dirs.CaplinLatest)
+ dirs.Downloader, dirs.TxPool, dirs.Nodes, dirs.CaplinBlobs, dirs.CaplinIndexing, dirs.CaplinLatest, dirs.CaplinGenesis)
return dirs
}
diff --git a/eth/backend.go b/eth/backend.go
index 9eb37b0c834..ed6eb63d72f 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -25,7 +25,6 @@ import (
"errors"
"fmt"
"io/fs"
- "math"
"math/big"
"net"
"os"
@@ -83,9 +82,7 @@ import (
"github.com/erigontech/erigon-lib/wrap"
"github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/cl/persistence/format/snapshot_format/getters"
- "github.com/erigontech/erigon/cl/phase1/core/checkpoint_sync"
executionclient "github.com/erigontech/erigon/cl/phase1/execution_client"
- "github.com/erigontech/erigon/cl/utils/eth_clock"
"github.com/erigontech/erigon/cmd/caplin/caplin1"
"github.com/erigontech/erigon/cmd/rpcdaemon/cli"
"github.com/erigontech/erigon/common/debug"
@@ -351,8 +348,11 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger
}
chainKv = backend.chainDB //nolint
- if err := backend.setUpSnapDownloader(ctx, config.Downloader); err != nil {
- return nil, err
+ // Can happen in some configurations
+ if config.Downloader.ChainName != "" {
+ if err := backend.setUpSnapDownloader(ctx, config.Downloader); err != nil {
+ return nil, err
+ }
}
kvRPC := remotedbserver.NewKvServer(ctx, backend.chainDB, allSnapshots, allBorSnapshots, agg, logger)
@@ -937,46 +937,13 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger
false,
config.Miner.EnabledPOS)
backend.engineBackendRPC = engineBackendRPC
-
// If we choose not to run a consensus layer, run our embedded.
- if config.InternalCL && clparams.EmbeddedSupported(config.NetworkID) {
- networkCfg, beaconCfg := clparams.GetConfigsByNetwork(clparams.NetworkType(config.NetworkID))
- if err != nil {
- return nil, err
- }
-
+ if config.InternalCL && (clparams.EmbeddedSupported(config.NetworkID) || config.CaplinConfig.IsDevnet()) {
config.CaplinConfig.NetworkId = clparams.NetworkType(config.NetworkID)
- state, err := checkpoint_sync.ReadOrFetchLatestBeaconState(ctx, dirs, beaconCfg, config.CaplinConfig)
- if err != nil {
- return nil, err
- }
- ethClock := eth_clock.NewEthereumClock(state.GenesisTime(), state.GenesisValidatorsRoot(), beaconCfg)
-
- pruneBlobDistance := uint64(128600)
- if config.CaplinConfig.BlobBackfilling || config.CaplinConfig.BlobPruningDisabled {
- pruneBlobDistance = math.MaxUint64
- }
-
- indiciesDB, blobStorage, err := caplin1.OpenCaplinDatabase(ctx, beaconCfg, ethClock, dirs.CaplinIndexing, dirs.CaplinBlobs, executionEngine, false, pruneBlobDistance)
- if err != nil {
- return nil, err
- }
-
+ config.CaplinConfig.LoopBlockLimit = uint64(config.LoopBlockLimit)
go func() {
- caplinOpt := []caplin1.CaplinOption{}
- if config.BeaconRouter.Builder {
- if config.CaplinConfig.RelayUrlExist() {
- caplinOpt = append(caplinOpt, caplin1.WithBuilder(config.CaplinConfig.MevRelayUrl, beaconCfg))
- } else {
- log.Warn("builder api enable but relay url not set. Skipping builder mode")
- config.BeaconRouter.Builder = false
- }
- }
- log.Info("Starting caplin")
- eth1Getter := getters.NewExecutionSnapshotReader(ctx, beaconCfg, blockReader, backend.chainDB)
- if err := caplin1.RunCaplinPhase1(ctx, executionEngine, config, networkCfg, beaconCfg, ethClock,
- state, dirs, eth1Getter, backend.downloaderClient, indiciesDB, blobStorage, creds,
- blockSnapBuildSema, caplinOpt...); err != nil {
+ eth1Getter := getters.NewExecutionSnapshotReader(ctx, blockReader, backend.chainDB)
+ if err := caplin1.RunCaplinService(ctx, executionEngine, config.CaplinConfig, dirs, eth1Getter, backend.downloaderClient, creds, blockSnapBuildSema); err != nil {
logger.Error("could not start caplin", "err", err)
}
ctxCancel()
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index f1d90c25141..48f8dfafb8a 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -36,7 +36,6 @@ import (
"github.com/erigontech/erigon-lib/common/datadir"
"github.com/erigontech/erigon-lib/downloader/downloadercfg"
"github.com/erigontech/erigon-lib/txpool/txpoolcfg"
- "github.com/erigontech/erigon/cl/beacon/beacon_router_configuration"
"github.com/erigontech/erigon/cl/clparams"
"github.com/erigontech/erigon/consensus/ethash/ethashcfg"
"github.com/erigontech/erigon/core/types"
@@ -189,7 +188,6 @@ type Config struct {
Snapshot BlocksFreezing
Downloader *downloadercfg.Cfg
- BeaconRouter beacon_router_configuration.RouterConfiguration
CaplinConfig clparams.CaplinConfig
Dirs datadir.Dirs
@@ -241,12 +239,7 @@ type Config struct {
// Ethstats service
Ethstats string
// Consensus layer
- InternalCL bool
- CaplinDiscoveryAddr string
- CaplinDiscoveryPort uint64
- CaplinDiscoveryTCPPort uint64
- SentinelAddr string
- SentinelPort uint64
+ InternalCL bool
OverridePragueTime *big.Int `toml:",omitempty"`
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index ddbdba296de..aa9549b0c67 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -85,7 +85,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.BadBlockHash = c.BadBlockHash
enc.Snapshot = c.Snapshot
enc.Downloader = c.Downloader
- enc.BeaconRouter = c.BeaconRouter
+ enc.CaplinConfig.BeaconAPIRouter = c.CaplinConfig.BeaconAPIRouter
enc.CaplinConfig = c.CaplinConfig
enc.Dirs = c.Dirs
enc.ExternalSnapshotDownloaderAddr = c.ExternalSnapshotDownloaderAddr
@@ -108,11 +108,11 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.PolygonSyncStage = c.PolygonSyncStage
enc.Ethstats = c.Ethstats
enc.InternalCL = c.InternalCL
- enc.CaplinDiscoveryAddr = c.CaplinDiscoveryAddr
- enc.CaplinDiscoveryPort = c.CaplinDiscoveryPort
- enc.CaplinDiscoveryTCPPort = c.CaplinDiscoveryTCPPort
- enc.SentinelAddr = c.SentinelAddr
- enc.SentinelPort = c.SentinelPort
+ enc.CaplinConfig.CaplinDiscoveryAddr = c.CaplinConfig.CaplinDiscoveryAddr
+ enc.CaplinConfig.CaplinDiscoveryPort = c.CaplinConfig.CaplinDiscoveryPort
+ enc.CaplinConfig.CaplinDiscoveryTCPPort = c.CaplinConfig.CaplinDiscoveryTCPPort
+ enc.CaplinConfig.SentinelAddr = c.CaplinConfig.SentinelAddr
+ enc.CaplinConfig.SentinelPort = c.CaplinConfig.SentinelPort
enc.OverridePragueTime = c.OverridePragueTime
enc.SilkwormExecution = c.SilkwormExecution
enc.SilkwormRpcDaemon = c.SilkwormRpcDaemon
@@ -217,7 +217,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
c.Downloader = dec.Downloader
}
if dec.BeaconRouter != nil {
- c.BeaconRouter = *dec.BeaconRouter
+ c.CaplinConfig.BeaconAPIRouter = *dec.BeaconRouter
}
if dec.CaplinConfig != nil {
c.CaplinConfig = *dec.CaplinConfig
@@ -286,19 +286,19 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
c.InternalCL = *dec.InternalCL
}
if dec.CaplinDiscoveryAddr != nil {
- c.CaplinDiscoveryAddr = *dec.CaplinDiscoveryAddr
+ c.CaplinConfig.CaplinDiscoveryAddr = *dec.CaplinDiscoveryAddr
}
if dec.CaplinDiscoveryPort != nil {
- c.CaplinDiscoveryPort = *dec.CaplinDiscoveryPort
+ c.CaplinConfig.CaplinDiscoveryPort = *dec.CaplinDiscoveryPort
}
if dec.CaplinDiscoveryTCPPort != nil {
- c.CaplinDiscoveryTCPPort = *dec.CaplinDiscoveryTCPPort
+ c.CaplinConfig.CaplinDiscoveryTCPPort = *dec.CaplinDiscoveryTCPPort
}
if dec.SentinelAddr != nil {
- c.SentinelAddr = *dec.SentinelAddr
+ c.CaplinConfig.SentinelAddr = *dec.SentinelAddr
}
if dec.SentinelPort != nil {
- c.SentinelPort = *dec.SentinelPort
+ c.CaplinConfig.SentinelPort = *dec.SentinelPort
}
if dec.OverridePragueTime != nil {
c.OverridePragueTime = dec.OverridePragueTime
diff --git a/eth/stagedsync/exec3.go b/eth/stagedsync/exec3.go
index 340d3b7e1ba..54a6a816fef 100644
--- a/eth/stagedsync/exec3.go
+++ b/eth/stagedsync/exec3.go
@@ -779,6 +779,8 @@ Loop:
HistoryExecution: offsetFromBlockBeginning > 0 && txIndex < int(offsetFromBlockBeginning),
BlockReceipts: receipts,
+
+ Config: chainConfig,
}
if cfg.genesis != nil {
txTask.Config = cfg.genesis.Config
diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go
index 1edd6924754..3dc887a5b20 100644
--- a/turbo/cli/default_flags.go
+++ b/turbo/cli/default_flags.go
@@ -184,6 +184,7 @@ var DefaultFlags = []cli.Flag{
&utils.CaplinCheckpointSyncUrlFlag,
&utils.SentinelAddrFlag,
&utils.SentinelPortFlag,
+ &utils.SentinelBootnodes,
&utils.OtsSearchMaxCapFlag,
@@ -217,6 +218,8 @@ var DefaultFlags = []cli.Flag{
&utils.CaplinArchiveFlag,
&utils.CaplinMevRelayUrl,
&utils.CaplinValidatorMonitorFlag,
+ &utils.CaplinCustomConfigFlag,
+ &utils.CaplinCustomGenesisFlag,
&utils.TrustedSetupFile,
&utils.RPCSlowFlag,