Skip to content

Commit 939ed31

Browse files
fix nil-ptr in DumpBeaconBlocks (#19532)
``` panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x1b469aa] goroutine 13874 [running]: github.com/erigontech/erigon/db/snapcfg.MergeLimitFromCfg(...) github.com/erigontech/erigon/db/snapcfg/util.go:456 github.com/erigontech/erigon/db/snapshotsync/freezeblocks.chooseSegmentEnd(0x1959420, 0x1960950, 0x0?, 0x0?) github.com/erigontech/erigon/db/snapshotsync/freezeblocks/block_snapshots.go:132 +0x2a github.com/erigontech/erigon/db/snapshotsync/freezeblocks.DumpBeaconBlocks({_, _}, {_, _}, _, _, _, {{0xc001a16f50, 0xc}, {0xc001a16f50, ...}, ...}, ...) github.com/erigontech/erigon/db/snapshotsync/freezeblocks/caplin_snapshots.go:600 +0x179 github.com/erigontech/erigon/cl/antiquary.(*Antiquary).antiquate(0xc0f4c34488) github.com/erigontech/erigon/cl/antiquary/antiquary.go:315 +0x3a8 github.com/erigontech/erigon/cl/antiquary.(*Antiquary).Loop(0xc0f4c34488) github.com/erigontech/erigon/cl/antiquary/antiquary.go:257 +0x13b8 github.com/erigontech/erigon/cmd/caplin/caplin1.RunCaplinService.func3() github.com/erigontech/erigon/cmd/caplin/caplin1/run.go:450 +0xe7 created by github.com/erigontech/erigon/cmd/caplin/caplin1.RunCaplinService in goroutine 779 github.com/erigontech/erigon/cmd/caplin/caplin1/run.go:443 +0x31ae ```
1 parent f3c7817 commit 939ed31

File tree

6 files changed

+56
-32
lines changed

6 files changed

+56
-32
lines changed

cmd/downloader/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ func Downloader(cmd *cobra.Command, logger log.Logger) error {
363363
d.InitBackgroundLogger(true)
364364
if seedbox {
365365
var downloadItems []*downloaderproto.DownloadItem
366-
snapCfg, _ := snapcfg.KnownCfg(chain)
366+
snapCfg := snapcfg.KnownCfgOrDevnet(chain)
367367
for _, it := range snapCfg.Preverified.Items {
368368
downloadItems = append(downloadItems, &downloaderproto.DownloadItem{
369369
Path: it.Name,

db/downloader/downloadercfg/downloadercfg.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,8 @@ func New(
308308
// LoadSnapshotsHashes checks local preverified.toml. If file exists, used local hashes.
309309
// If there are no such file, try to fetch hashes from the web and create local file.
310310
func LoadSnapshotsHashes(ctx context.Context, dirs datadir.Dirs, chainName string) error {
311-
if _, known := snapcfg.KnownCfg(chainName); !known {
311+
cfg, known := snapcfg.KnownCfg(chainName)
312+
if !known {
312313
log.Root().Warn("No snapshot hashes for chain", "chain", chainName)
313314
return nil
314315
}
@@ -333,7 +334,6 @@ func LoadSnapshotsHashes(ctx context.Context, dirs datadir.Dirs, chainName strin
333334
return fmt.Errorf("failed to fetch remote snapshot hashes for chain %s", chainName)
334335
}
335336
}
336-
cfg, _ := snapcfg.KnownCfg(chainName)
337337
cfg.Local = exists
338338
return nil
339339
}

db/downloader/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ func seedableSegmentFiles(dir string, chainName string, skipSeedableCheck bool)
7979
return nil, err
8080
}
8181

82-
segConfig, _ := snapcfg.KnownCfg(chainName)
82+
segConfig := snapcfg.KnownCfgOrDevnet(chainName)
8383

8484
res := make([]string, 0, len(files))
8585
for _, fPath := range files {

db/snapcfg/util.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -444,32 +444,10 @@ func RegisterKnownTypes(networkName string, types []snaptype.Type) {
444444

445445
var knownTypes = map[string][]snaptype.Type{}
446446

447-
func Seedable(networkName string, info snaptype.FileInfo) bool {
448-
if networkName == "" {
449-
return false
450-
}
451-
snapCfg, _ := KnownCfg(networkName)
452-
return snapCfg.Seedable(info)
453-
}
454-
455447
func MergeLimitFromCfg(cfg *Cfg, snapType snaptype.Enum, fromBlock uint64) uint64 {
456448
return cfg.MergeLimit(snapType, fromBlock)
457449
}
458450

459-
func MaxSeedableSegment(chain string, dir string) uint64 {
460-
var _max uint64
461-
segConfig, _ := KnownCfg(chain)
462-
if list, err := snaptype.Segments(dir); err == nil {
463-
for _, info := range list {
464-
if segConfig.Seedable(info) && info.Type.Enum() == snaptype.MinCoreEnum && info.To > _max {
465-
_max = info.To
466-
}
467-
}
468-
}
469-
470-
return _max
471-
}
472-
473451
var oldMergeSteps = append([]uint64{snaptype.Erigon2OldMergeLimit}, snaptype.MergeSteps...)
474452

475453
func MergeStepsFromCfg(cfg *Cfg, snapType snaptype.Enum, fromBlock uint64) []uint64 {

db/snapshotsync/freezeblocks/caplin_snapshots.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -590,14 +590,14 @@ func DumpBlobSidecarsRange(ctx context.Context, db kv.RoDB, storage blob_storage
590590
}
591591

592592
func DumpBeaconBlocks(ctx context.Context, db kv.RoDB, fromSlot, toSlot uint64, salt uint32, dirs datadir.Dirs, workers int, lvl log.Lvl, logger log.Logger) error {
593-
cfg, _ := snapcfg.KnownCfg("")
594-
for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BeaconBlocks, nil) {
593+
cfg := snapcfg.KnownCfgOrDevnet("")
594+
for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BeaconBlocks, cfg) {
595595
blocksPerFile := snapcfg.MergeLimitFromCfg(cfg, snaptype.CaplinEnums.BeaconBlocks, i)
596596

597597
if toSlot-i < blocksPerFile {
598598
break
599599
}
600-
to := chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BeaconBlocks, nil)
600+
to := chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BeaconBlocks, cfg)
601601
logger.Log(lvl, "Dumping beacon blocks", "from", i, "to", to)
602602
if err := dumpBeaconBlocksRange(ctx, db, i, to, salt, dirs, workers, lvl, logger); err != nil {
603603
return err
@@ -609,14 +609,14 @@ func DumpBeaconBlocks(ctx context.Context, db kv.RoDB, fromSlot, toSlot uint64,
609609
type BlobCountBySlotFn func(slot uint64) (uint64, error)
610610

611611
func DumpBlobsSidecar(ctx context.Context, blobStorage blob_storage.BlobStorage, db kv.RoDB, fromSlot, toSlot uint64, salt uint32, dirs datadir.Dirs, compressWorkers int, blobCountFn BlobCountBySlotFn, lvl log.Lvl, logger log.Logger) error {
612-
cfg, _ := snapcfg.KnownCfg("")
613-
for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BlobSidecars, nil) {
612+
cfg := snapcfg.KnownCfgOrDevnet("")
613+
for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BlobSidecars, cfg) {
614614
blocksPerFile := snapcfg.MergeLimitFromCfg(cfg, snaptype.CaplinEnums.BlobSidecars, i)
615615

616616
if toSlot-i < blocksPerFile {
617617
break
618618
}
619-
to := chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BlobSidecars, nil)
619+
to := chooseSegmentEnd(i, toSlot, snaptype.CaplinEnums.BlobSidecars, cfg)
620620
logger.Log(lvl, "Dumping blobs sidecars", "from", i, "to", to)
621621
if err := DumpBlobSidecarsRange(ctx, db, blobStorage, i, to, salt, dirs, compressWorkers, blobCountFn, lvl, logger); err != nil {
622622
return err
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright 2024 The Erigon Authors
2+
// This file is part of Erigon.
3+
//
4+
// Erigon is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// Erigon is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with Erigon. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package freezeblocks
18+
19+
import (
20+
"context"
21+
"testing"
22+
23+
"github.com/stretchr/testify/require"
24+
25+
"github.com/erigontech/erigon/common/log/v3"
26+
"github.com/erigontech/erigon/db/datadir"
27+
"github.com/erigontech/erigon/db/kv/dbcfg"
28+
"github.com/erigontech/erigon/db/kv/memdb"
29+
"github.com/erigontech/erigon/db/snaptype"
30+
)
31+
32+
// TestDumpBeaconBlocksNoPanic is a higher-level regression test: the production
33+
// panic occurred inside DumpBeaconBlocks when chooseSegmentEnd was called with
34+
// nil snCfg. This test uses toSlot=CaplinMergeLimit so the loop body executes
35+
// (doesn't break early), exercising the exact code path that panicked.
36+
func TestDumpBeaconBlocksNoPanic(t *testing.T) {
37+
db := memdb.NewTestDB(t, dbcfg.ChainDB)
38+
dirs := datadir.New(t.TempDir())
39+
40+
// toSlot == CaplinMergeLimit: toSlot-fromSlot is not < blocksPerFile,
41+
// so the loop reaches chooseSegmentEnd and dumpBeaconBlocksRange.
42+
// Before the fix this panicked; now it returns an error (no snap dir / empty db).
43+
require.NotPanics(t, func() {
44+
_ = DumpBeaconBlocks(context.Background(), db, 0, snaptype.CaplinMergeLimit, 0, dirs, 1, log.LvlDebug, log.New())
45+
})
46+
}

0 commit comments

Comments
 (0)