From 272dcd5c4384ba5c9b8d15fdfc2818ab1c92c336 Mon Sep 17 00:00:00 2001 From: shantichanal <158101918+shantichanal@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:58:41 +0200 Subject: [PATCH] all cmd changes to pass in functions in chaincmd --- cmd/era/main.go | 12 +-- cmd/geth/chaincmd.go | 10 ++- cmd/utils/cmd.go | 115 ++--------------------------- core/rawdb/eradb/eradb.go | 2 +- internal/era/era.go | 70 +++++++++++++++++- internal/era/execdb/builder.go | 16 +++- internal/era/execdb/era_test.go | 4 +- internal/era/execdb/iterator.go | 4 +- internal/era/execdb/reader.go | 46 ++---------- internal/era/onedb/builder.go | 9 ++- internal/era/onedb/builder_test.go | 10 ++- internal/era/onedb/iterator.go | 4 +- internal/era/onedb/reader.go | 38 +--------- 13 files changed, 131 insertions(+), 209 deletions(-) diff --git a/cmd/era/main.go b/cmd/era/main.go index e0ae8a18cd..bd5844eff2 100644 --- a/cmd/era/main.go +++ b/cmd/era/main.go @@ -170,14 +170,15 @@ func open(ctx *cli.Context, epoch uint64) (*onedb.Era, error) { dir = ctx.String(dirFlag.Name) network = ctx.String(networkFlag.Name) ) - entries, err := onedb.ReadDir(dir, network) + entries, err := era.ReadDir(dir, network) if err != nil { return nil, fmt.Errorf("error reading era dir: %w", err) } if epoch >= uint64(len(entries)) { return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch) } - return onedb.Open(filepath.Join(dir, entries[epoch])) + era, err := onedb.Open(filepath.Join(dir, entries[epoch])) + return era.(*onedb.Era), err } // verify checks each era1 file in a directory to ensure it is well-formed and @@ -199,7 +200,7 @@ func verify(ctx *cli.Context) error { reported = time.Now() ) - entries, err := onedb.ReadDir(dir, network) + entries, err := era.ReadDir(dir, network) if err != nil { return fmt.Errorf("error reading %s: %w", dir, err) } @@ -214,18 +215,19 @@ func verify(ctx *cli.Context) error { err := func() error { name := entries[i] e, err := onedb.Open(filepath.Join(dir, name)) + eraPointer := e.(*onedb.Era) if err != nil { return fmt.Errorf("error opening era1 file %s: %w", name, err) } defer e.Close() // Read accumulator and check against expected. - if got, err := e.Accumulator(); err != nil { + if got, err := eraPointer.Accumulator(); err != nil { return fmt.Errorf("error retrieving accumulator for %s: %w", name, err) } else if got != want { return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want) } // Recompute accumulator. - if err := checkAccumulator(e); err != nil { + if err := checkAccumulator(eraPointer); err != nil { return fmt.Errorf("error verify era1 file %s: %w", name, err) } // Give the user some feedback that something is happening. diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 1ef0ffebe2..2638560db2 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -43,6 +43,8 @@ import ( "github.com/ethereum/go-ethereum/internal/debug" "github.com/ethereum/go-ethereum/internal/era" "github.com/ethereum/go-ethereum/internal/era/eradl" + "github.com/ethereum/go-ethereum/internal/era/execdb" + "github.com/ethereum/go-ethereum/internal/era/onedb" "github.com/ethereum/go-ethereum/internal/flags" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -518,11 +520,11 @@ func importHistory(ctx *cli.Context) error { format := ctx.String(utils.EraFormatFlag.Name) switch format { case "era1", "era": - if err := utils.ImportHistory(chain, dir, network, utils.Era1); err != nil { + if err := utils.ImportHistory(chain, dir, network, onedb.From, onedb.NewIterator); err != nil { return err } case "erae": - if err := utils.ImportHistory(chain, dir, network, utils.EraE); err != nil { + if err := utils.ImportHistory(chain, dir, network, execdb.From, execdb.NewIterator); err != nil { return err } default: @@ -563,11 +565,11 @@ func exportHistory(ctx *cli.Context) error { format := ctx.String(utils.EraFormatFlag.Get(ctx)) switch format { case "era1", "era": - if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxEra1Size), utils.Era1); err != nil { + if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxSize), onedb.NewBuilder, onedb.Filename); err != nil { utils.Fatalf("Export error: %v\n", err) } case "erae": - if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era2.MaxEraESize), utils.EraE); err != nil { + if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxSize), execdb.NewBuilder, execdb.Filename); err != nil { utils.Fatalf("Export error: %v\n", err) } default: diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 400fb92fd0..2be60426d5 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -44,7 +44,7 @@ import ( "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/internal/debug" - era2 "github.com/ethereum/go-ethereum/internal/era/execdb" + "github.com/ethereum/go-ethereum/internal/era" "github.com/ethereum/go-ethereum/internal/era/onedb" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" @@ -253,11 +253,11 @@ func readList(filename string) ([]string, error) { // ImportHistory imports Era1 files containing historical block information, // starting from genesis. The assumption is held that the provided chain // segment in Era1 file should all be canonical and verified. -func ImportHistory(chain *core.BlockChain, dir string, network string) error { +func ImportHistory(chain *core.BlockChain, dir string, network string, from era.FromFn, iterator era.NewIteratorFn) error { if chain.CurrentSnapBlock().Number.BitLen() != 0 { return errors.New("history import only supported when starting from genesis") } - entries, err := onedb.ReadDir(dir, network) + entries, err := era.ReadDir(dir, network) if err != nil { return fmt.Errorf("error reading %s: %w", dir, err) } @@ -301,11 +301,11 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error { return fmt.Errorf("%s checksum mismatch: have %s want %s", file, got, want) } // Import all block data from Era1. - e, err := onedb.From(f) + e, err := from(f) if err != nil { return fmt.Errorf("error opening era: %w", err) } - it, err := onedb.NewIterator(e) + it, err := iterator(e) if err != nil { return fmt.Errorf("error creating iterator: %w", err) } @@ -347,105 +347,6 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error { return nil } -// ImportHistoryEraE imports Era-E files containing historical block information, -// starting from genesis. Currently this function follows the assumptions that the provided chain -// segment in Era-E file should all be canonical and verified. In the future, this function will be -// extended to support importing Era-E files with proof verification. -func ImportHistoryEraE(chain *core.BlockChain, dir, network string) error { - if chain.CurrentSnapBlock().Number.Sign() != 0 { - return errors.New("history import only supported when starting from genesis") - } - - entries, err := era2.ReadDir(dir, network) - if err != nil { - return fmt.Errorf("reading %q: %w", dir, err) - } - checksums, err := readList(filepath.Join(dir, "checksums.txt")) - if err != nil { - return fmt.Errorf("reading checksums.txt: %w", err) - } - if len(entries) != len(checksums) { - return fmt.Errorf("mismatch: %d erae files, %d checksums", len(entries), len(checksums)) - } - - var ( - start = time.Now() - reported = time.Now() - imported int - h = sha256.New() - scratch bytes.Buffer - ) - - for i, file := range entries { - path := filepath.Join(dir, file) - - // validate against checksum file in directory - f, err := os.Open(path) - if err != nil { - return fmt.Errorf("open %s: %w", path, err) - } - if _, err := io.Copy(h, f); err != nil { - f.Close() - return fmt.Errorf("checksum %s: %w", path, err) - } - got := common.BytesToHash(h.Sum(scratch.Bytes()[:])).Hex() - want := checksums[i] - h.Reset() - scratch.Reset() - if got != want { - f.Close() - return fmt.Errorf("%s checksum mismatch: have %s want %s", file, got, want) - } - // rewind for reading - if _, err := f.Seek(0, io.SeekStart); err != nil { - f.Close() - return fmt.Errorf("rewind %s: %w", file, err) - } - // import archive - e, err := era2.From(f) - if err != nil { - f.Close() - return fmt.Errorf("open erae %s: %w", file, err) - } - blockCount := e.Count() - - for j := uint64(0); j < blockCount; j++ { - hdr, err := e.GetHeader(e.Start() + j) - if err != nil { - return fmt.Errorf("header #%d: %w", hdr.Number.Uint64(), err) - } - if hdr.Number.Sign() == 0 { // skip genesis - continue - } - body, err := e.GetBody(hdr.Number.Uint64()) - if err != nil { - return fmt.Errorf("body #%d: %w", hdr.Number.Uint64(), err) - } - rcpts, err := e.GetReceipts(hdr.Number.Uint64(), 1) - if err != nil { - return fmt.Errorf("receipts #%d: %w", hdr.Number.Uint64(), err) - } - blk := types.NewBlockWithHeader(hdr).WithBody(*body) - - enc := types.EncodeBlockReceiptLists(rcpts) - if _, err := chain.InsertReceiptChain([]*types.Block{blk}, enc, ^uint64(0)); err != nil { - return fmt.Errorf("insert #%d: %w", hdr.Number.Uint64(), err) - } - - imported++ - if time.Since(reported) >= 8*time.Second { - log.Info("Importing Era‑E", "head", hdr.Number, "imported", imported, "elapsed", common.PrettyDuration(time.Since(start))) - reported = time.Now() - imported = 0 - } - } - f.Close() - } - - log.Info("Era‑E import complete", "duration", common.PrettyDuration(time.Since(start))) - return nil -} - func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block { head := chain.CurrentBlock() for i, block := range blocks { @@ -516,7 +417,7 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las // ExportHistory exports blockchain history into the specified directory, // following the Era format. -func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) error { +func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64, builderfn era.NewBuilderFn, filename era.FilenameFn) error { log.Info("Exporting blockchain history", "dir", dir) if head := bc.CurrentBlock().Number.Uint64(); head < last { log.Warn("Last block beyond head, setting last = head", "head", head, "last", last) @@ -545,7 +446,7 @@ func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) er for batch := first; batch <= last; batch += step { idx := int(batch / step) - tmpPath := filepath.Join(dir, onedb.Filename(network, idx, common.Hash{})) + tmpPath := filepath.Join(dir, filename(network, idx, common.Hash{})) if err := func() error { fh, err := os.Create(tmpPath) @@ -554,7 +455,7 @@ func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) er } defer fh.Close() - bldr := onedb.NewBuilder(fh) + bldr := builderfn(fh) for j := uint64(0); j < step && batch+j <= last; j++ { n := batch + j diff --git a/core/rawdb/eradb/eradb.go b/core/rawdb/eradb/eradb.go index 391c22b1a0..d715c824ed 100644 --- a/core/rawdb/eradb/eradb.go +++ b/core/rawdb/eradb/eradb.go @@ -308,7 +308,7 @@ func (db *Store) openEraFile(epoch uint64) (*onedb.Era, error) { return nil, fmt.Errorf("pre-merge era1 file has invalid boundary. %d %% %d != 0", e.Start(), era.MaxSize) } log.Debug("Opened era1 file", "epoch", epoch) - return e, nil + return e.(*onedb.Era), nil } // doneWithFile signals that the caller has finished using a file. diff --git a/internal/era/era.go b/internal/era/era.go index cab3f458a4..14811939a6 100644 --- a/internal/era/era.go +++ b/internal/era/era.go @@ -1,11 +1,17 @@ package era import ( + "fmt" "io" "math/big" + "os" + "path" + "strconv" + "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" + // Removed import of internal/era to avoid import cycle and missing metadata error ) // Type constants for the e2store entries in the Era1 and EraE formats. @@ -36,12 +42,74 @@ type Iterator interface { Next() bool Number() uint64 Block() (*types.Block, error) + BlockAndReceipts() (*types.Block, types.Receipts, error) Receipts() (types.Receipts, error) Error() error } // Builder represents the interface for various types of era formats. type Builder interface { - Add(block *types.Block, receipts types.Receipts, td *big.Int, proof []byte) error + Add(block *types.Block, receipts types.Receipts, td *big.Int, proof Proof) error + AddRLP(header, body, receipts, proof []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error Finalize() (common.Hash, error) } + +// Era represents the interface for reading era data. +type Era interface { + Close() error + Start() uint64 + Count() uint64 + GetBlockByNumber(num uint64) (*types.Block, error) + GetRawBodyByNumber(num uint64) ([]byte, error) + GetRawReceiptsByNumber(num uint64) ([]byte, error) +} + +// NewBuilderFn defines a function type for creating a new Builder. +type NewBuilderFn func(w io.Writer) Builder + +// FilenameFn defines a function type for generating a filename based on network, epoch, and root hash. +type FilenameFn func(network string, epoch int, root common.Hash) string + +// FromFn defines a function type for creating an Era from a ReadAtSeekCloser. +type FromFn func(f ReadAtSeekCloser) (Era, error) + +// NewIteratorFn defines a function type for creating a new Iterator from an Era. +type NewIteratorFn func(e Era) (Iterator, error) + +// ReadDir reads all the era1 files in a directory for a given network. +// Format: --.erae or --.era1 +func ReadDir(dir, network string) ([]string, error) { + entries, err := os.ReadDir(dir) + var directoryExtension string + if err != nil { + return nil, fmt.Errorf("error reading directory %s: %w", dir, err) + } + var ( + next = uint64(0) + eras []string + ) + for i, entry := range entries { + fileExtension := path.Ext(entry.Name()) + if i == 0 { + directoryExtension = fileExtension + } else if directoryExtension != fileExtension { + return nil, fmt.Errorf("directory %s contains mixed era file formats", dir) + } + if fileExtension != ".erae" || fileExtension != ".era1" { + continue + } + parts := strings.Split(entry.Name(), "-") + if len(parts) != 3 || parts[0] != network { + // Invalid era1 filename, skip. + continue + } + if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil { + return nil, fmt.Errorf("malformed era filenames: %s", entry.Name()) + } else if epoch != next { + return nil, fmt.Errorf("missing epoch %d", next) + } + next += 1 + eras = append(eras, entry.Name()) + } + return eras, nil +} diff --git a/internal/era/execdb/builder.go b/internal/era/execdb/builder.go index 91a4fd24cb..101e09cd56 100644 --- a/internal/era/execdb/builder.go +++ b/internal/era/execdb/builder.go @@ -51,9 +51,11 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/history" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/era" "github.com/ethereum/go-ethereum/internal/era/e2store" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" "github.com/golang/snappy" ) @@ -91,7 +93,7 @@ type Builder struct { } // NewBuilder returns a new Builder instance. -func NewBuilder(w io.Writer) *Builder { +func NewBuilder(w io.Writer) era.Builder { tmp := bytes.NewBuffer(nil) return &Builder{ w: e2store.NewWriter(w), @@ -137,12 +139,15 @@ func (b *Builder) Add(block *types.Block, receipts types.Receipts, td *big.Int, return b.AddRLP( eh, eb, er, ep, header.Number.Uint64(), - header.Hash(), td, + header.Hash(), td, nil, ) } // AddRLP takes the RLP encoded block components and writes them to the underlying e2store file. -func (b *Builder) AddRLP(headerRLP []byte, bodyRLP []byte, receipts []byte, proof []byte, blockNum uint64, blockHash common.Hash, td *big.Int) error { +func (b *Builder) AddRLP(headerRLP []byte, bodyRLP []byte, receipts []byte, proof []byte, blockNum uint64, blockHash common.Hash, td, difficulty *big.Int) error { + if difficulty != nil { + return fmt.Errorf("block difficulty not allowed in erae format") + } if len(b.buff.headers) >= era.MaxSize { return fmt.Errorf("exceeds max size %d", era.MaxSize) } @@ -156,6 +161,11 @@ func (b *Builder) AddRLP(headerRLP []byte, bodyRLP []byte, receipts []byte, proo b.buff.proofs = append(b.buff.proofs, proof) } + mergeblock := history.PrunePoints[params.MainnetGenesisHash] + if mergeblock != nil && blockNum <= mergeblock.BlockNumber { + b.buff.tds = append(b.buff.tds, new(big.Int).Set(td)) + } + // Write Era2 version before writing any blocks. if b.startNum == nil { b.startNum = new(uint64) diff --git a/internal/era/execdb/era_test.go b/internal/era/execdb/era_test.go index 513708be00..f9ccc35254 100644 --- a/internal/era/execdb/era_test.go +++ b/internal/era/execdb/era_test.go @@ -139,7 +139,7 @@ func TestEra2Builder(t *testing.T) { t.Fatalf("body %d mismatch", i) } - rawBody, err := era.GetRawBodyFrameByNumber(bn) + rawBody, err := era.GetRawBodyByNumber(bn) if err != nil { t.Fatalf("raw body %d: %v", i, err) } @@ -153,7 +153,7 @@ func TestEra2Builder(t *testing.T) { t.Fatalf("body frame %d mismatch", i) } - rawRcpt, err := era.GetRawReceiptsFrameByNumber(bn) + rawRcpt, err := era.GetRawReceiptsByNumber(bn) if err != nil { t.Fatalf("raw receipts %d: %v", i, err) } diff --git a/internal/era/execdb/iterator.go b/internal/era/execdb/iterator.go index 767110e7b0..539311f334 100644 --- a/internal/era/execdb/iterator.go +++ b/internal/era/execdb/iterator.go @@ -35,8 +35,8 @@ type Iterator struct { // NewIterator returns a header/body/receipt iterator over the archive. // Call Next immediately to position on the first block. -func NewIterator(e *Era) (*Iterator, error) { - inner, err := NewRawIterator(e) +func NewIterator(e era.Era) (era.Iterator, error) { + inner, err := NewRawIterator(e.(*Era)) if err != nil { return nil, err } diff --git a/internal/era/execdb/reader.go b/internal/era/execdb/reader.go index c6b0d4f3f4..30c99a46be 100644 --- a/internal/era/execdb/reader.go +++ b/internal/era/execdb/reader.go @@ -22,10 +22,7 @@ import ( "io" "math/big" "os" - "path" "slices" - "strconv" - "strings" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -72,7 +69,7 @@ func (e *Era) Close() error { } // From returns an Era backed by f. -func From(f era.ReadAtSeekCloser) (*Era, error) { +func From(f era.ReadAtSeekCloser) (era.Era, error) { e := &Era{f: f, s: e2store.NewReader(f)} if err := e.loadIndex(); err != nil { f.Close() @@ -81,37 +78,6 @@ func From(f era.ReadAtSeekCloser) (*Era, error) { return e, nil } -// ReadDir reads all the era1 files in a directory for a given network. -// Format: --.erae -func ReadDir(dir, network string) ([]string, error) { - entries, err := os.ReadDir(dir) - if err != nil { - return nil, fmt.Errorf("error reading directory %s: %w", dir, err) - } - var ( - next = uint64(0) - eras []string - ) - for _, entry := range entries { - if path.Ext(entry.Name()) != ".erae" { - continue - } - parts := strings.Split(entry.Name(), "-") - if len(parts) != 3 || parts[0] != network { - // Invalid era1 filename, skip. - continue - } - if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil { - return nil, fmt.Errorf("malformed era1 filename: %s", entry.Name()) - } else if epoch != next { - return nil, fmt.Errorf("missing epoch %d", next) - } - next += 1 - eras = append(eras, entry.Name()) - } - return eras, nil -} - // Start retrieves the starting block number. func (e *Era) Start() uint64 { return e.m.start @@ -185,8 +151,8 @@ func (e *Era) getTD(blockNum uint64) (*big.Int, error) { return td, nil } -// GetRawBodyFrameByNumber retrieves the raw body frame in bytes of a specific block. -func (e *Era) GetRawBodyFrameByNumber(blockNum uint64) ([]byte, error) { +// GetRawBodyByNumber returns the RLP-encoded body for the given block number. +func (e *Era) GetRawBodyByNumber(blockNum uint64) ([]byte, error) { off, err := e.bodyOff(blockNum) if err != nil { return nil, err @@ -198,8 +164,8 @@ func (e *Era) GetRawBodyFrameByNumber(blockNum uint64) ([]byte, error) { return io.ReadAll(r) } -// GetRawReceiptsFrameByNumber retrieves the raw receipts frame in bytes of a specific block. -func (e *Era) GetRawReceiptsFrameByNumber(blockNum uint64) ([]byte, error) { +// GetRawReceiptsByNumber returns the RLP-encoded receipts for the given block number. +func (e *Era) GetRawReceiptsByNumber(blockNum uint64) ([]byte, error) { off, err := e.receiptOff(blockNum) if err != nil { return nil, err @@ -211,7 +177,7 @@ func (e *Era) GetRawReceiptsFrameByNumber(blockNum uint64) ([]byte, error) { return io.ReadAll(r) } -// GetRawProofFrameByNumber retrieves the raw proof frame in bytes of a specific block proof. +// GetRawProofFrameByNumber returns the RLP-encoded receipts for the given block number. func (e *Era) GetRawProofFrameByNumber(blockNum uint64) ([]byte, error) { off, err := e.proofOff(blockNum) if err != nil { diff --git a/internal/era/onedb/builder.go b/internal/era/onedb/builder.go index b07ed328a7..948d1f446e 100644 --- a/internal/era/onedb/builder.go +++ b/internal/era/onedb/builder.go @@ -86,7 +86,7 @@ type Builder struct { } // NewBuilder returns a new Builder instance. -func NewBuilder(w io.Writer) *Builder { +func NewBuilder(w io.Writer) era.Builder { buf := bytes.NewBuffer(nil) return &Builder{ w: e2store.NewWriter(w), @@ -113,12 +113,15 @@ func (b *Builder) Add(block *types.Block, receipts types.Receipts, td *big.Int, if err != nil { return err } - return b.AddRLP(eh, eb, er, block.NumberU64(), block.Hash(), td, block.Difficulty()) + return b.AddRLP(eh, eb, er, nil, block.NumberU64(), block.Hash(), td, block.Difficulty()) } // AddRLP writes a compressed block entry and compressed receipts entry to the // underlying e2store file. -func (b *Builder) AddRLP(header, body, receipts []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error { +func (b *Builder) AddRLP(header, body, receipts, proof []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error { + if proof != nil { + return fmt.Errorf("proof not allowed in era1 format") + } // Write Era1 version entry before first block. if b.startNum == nil { n, err := b.w.Write(era.TypeVersion, nil) diff --git a/internal/era/onedb/builder_test.go b/internal/era/onedb/builder_test.go index b1d9a539d6..0e64f68481 100644 --- a/internal/era/onedb/builder_test.go +++ b/internal/era/onedb/builder_test.go @@ -67,7 +67,7 @@ func TestEra1Builder(t *testing.T) { hash = common.Hash{byte(i)} td = chain.tds[i] ) - if err = builder.AddRLP(header, body, receipts, uint64(i), hash, td, big.NewInt(1)); err != nil { + if err = builder.AddRLP(header, body, receipts, nil, uint64(i), hash, td, big.NewInt(1)); err != nil { t.Fatalf("error adding entry: %v", err) } } @@ -83,7 +83,11 @@ func TestEra1Builder(t *testing.T) { t.Fatalf("failed to open era: %v", err) } defer e.Close() - it, err := NewRawIterator(e) + eraPtr, ok := e.(*Era) + if !ok { + t.Fatalf("failed to assert *Era type") + } + it, err := NewRawIterator(eraPtr) if err != nil { t.Fatalf("failed to make iterator: %s", err) } @@ -120,7 +124,7 @@ func TestEra1Builder(t *testing.T) { if !bytes.Equal(rawReceipts, chain.receipts[i]) { t.Fatalf("mismatched receipts: want %s, got %s", chain.receipts[i], rawReceipts) } - receipts, err := getReceiptsByNumber(e, i) + receipts, err := getReceiptsByNumber(eraPtr, i) if err != nil { t.Fatalf("error reading receipts: %v", err) } diff --git a/internal/era/onedb/iterator.go b/internal/era/onedb/iterator.go index 558581e32b..b80fbabbc5 100644 --- a/internal/era/onedb/iterator.go +++ b/internal/era/onedb/iterator.go @@ -34,8 +34,8 @@ type Iterator struct { // NewIterator returns a new Iterator instance. Next must be immediately // called on new iterators to load the first item. -func NewIterator(e *Era) (*Iterator, error) { - inner, err := NewRawIterator(e) +func NewIterator(e era.Era) (era.Iterator, error) { + inner, err := NewRawIterator(e.(*Era)) if err != nil { return nil, err } diff --git a/internal/era/onedb/reader.go b/internal/era/onedb/reader.go index 9c66642b8b..1748627850 100644 --- a/internal/era/onedb/reader.go +++ b/internal/era/onedb/reader.go @@ -22,10 +22,7 @@ import ( "io" "math/big" "os" - "path" "slices" - "strconv" - "strings" "sync" "github.com/ethereum/go-ethereum/common" @@ -42,37 +39,6 @@ func Filename(network string, epoch int, root common.Hash) string { return fmt.Sprintf("%s-%05d-%s.era1", network, epoch, root.Hex()[2:10]) } -// ReadDir reads all the era1 files in a directory for a given network. -// Format: --.era1 -func ReadDir(dir, network string) ([]string, error) { - entries, err := os.ReadDir(dir) - if err != nil { - return nil, fmt.Errorf("error reading directory %s: %w", dir, err) - } - var ( - next = uint64(0) - eras []string - ) - for _, entry := range entries { - if path.Ext(entry.Name()) != ".era1" { - continue - } - parts := strings.Split(entry.Name(), "-") - if len(parts) != 3 || parts[0] != network { - // Invalid era1 filename, skip. - continue - } - if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil { - return nil, fmt.Errorf("malformed era1 filename: %s", entry.Name()) - } else if epoch != next { - return nil, fmt.Errorf("missing epoch %d", next) - } - next += 1 - eras = append(eras, entry.Name()) - } - return eras, nil -} - type ReadAtSeekCloser interface { io.ReaderAt io.Seeker @@ -89,7 +55,7 @@ type Era struct { } // From returns an Era backed by f. -func From(f ReadAtSeekCloser) (*Era, error) { +func From(f era.ReadAtSeekCloser) (era.Era, error) { m, err := readMetadata(f) if err != nil { return nil, err @@ -103,7 +69,7 @@ func From(f ReadAtSeekCloser) (*Era, error) { } // Open returns an Era backed by the given filename. -func Open(filename string) (*Era, error) { +func Open(filename string) (era.Era, error) { f, err := os.Open(filename) if err != nil { return nil, err