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,