Skip to content

Commit acd77a9

Browse files
committed
all cmd changes to pass in functions in chaincmd
1 parent 091211d commit acd77a9

13 files changed

Lines changed: 131 additions & 209 deletions

File tree

cmd/era/main.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,15 @@ func open(ctx *cli.Context, epoch uint64) (*onedb.Era, error) {
170170
dir = ctx.String(dirFlag.Name)
171171
network = ctx.String(networkFlag.Name)
172172
)
173-
entries, err := onedb.ReadDir(dir, network)
173+
entries, err := era.ReadDir(dir, network)
174174
if err != nil {
175175
return nil, fmt.Errorf("error reading era dir: %w", err)
176176
}
177177
if epoch >= uint64(len(entries)) {
178178
return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
179179
}
180-
return onedb.Open(filepath.Join(dir, entries[epoch]))
180+
era, err := onedb.Open(filepath.Join(dir, entries[epoch]))
181+
return era.(*onedb.Era), err
181182
}
182183

183184
// 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 {
199200
reported = time.Now()
200201
)
201202

202-
entries, err := onedb.ReadDir(dir, network)
203+
entries, err := era.ReadDir(dir, network)
203204
if err != nil {
204205
return fmt.Errorf("error reading %s: %w", dir, err)
205206
}
@@ -214,18 +215,19 @@ func verify(ctx *cli.Context) error {
214215
err := func() error {
215216
name := entries[i]
216217
e, err := onedb.Open(filepath.Join(dir, name))
218+
eraPointer := e.(*onedb.Era)
217219
if err != nil {
218220
return fmt.Errorf("error opening era1 file %s: %w", name, err)
219221
}
220222
defer e.Close()
221223
// Read accumulator and check against expected.
222-
if got, err := e.Accumulator(); err != nil {
224+
if got, err := eraPointer.Accumulator(); err != nil {
223225
return fmt.Errorf("error retrieving accumulator for %s: %w", name, err)
224226
} else if got != want {
225227
return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want)
226228
}
227229
// Recompute accumulator.
228-
if err := checkAccumulator(e); err != nil {
230+
if err := checkAccumulator(eraPointer); err != nil {
229231
return fmt.Errorf("error verify era1 file %s: %w", name, err)
230232
}
231233
// Give the user some feedback that something is happening.

cmd/geth/chaincmd.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ import (
4343
"github.com/ethereum/go-ethereum/internal/debug"
4444
"github.com/ethereum/go-ethereum/internal/era"
4545
"github.com/ethereum/go-ethereum/internal/era/eradl"
46+
"github.com/ethereum/go-ethereum/internal/era/execdb"
47+
"github.com/ethereum/go-ethereum/internal/era/onedb"
4648
"github.com/ethereum/go-ethereum/internal/flags"
4749
"github.com/ethereum/go-ethereum/log"
4850
"github.com/ethereum/go-ethereum/node"
@@ -505,11 +507,11 @@ func importHistory(ctx *cli.Context) error {
505507
format := ctx.String(utils.EraFormatFlag.Name)
506508
switch format {
507509
case "era1", "era":
508-
if err := utils.ImportHistory(chain, dir, network, utils.Era1); err != nil {
510+
if err := utils.ImportHistory(chain, dir, network, onedb.From, onedb.NewIterator); err != nil {
509511
return err
510512
}
511513
case "erae":
512-
if err := utils.ImportHistory(chain, dir, network, utils.EraE); err != nil {
514+
if err := utils.ImportHistory(chain, dir, network, execdb.From, execdb.NewIterator); err != nil {
513515
return err
514516
}
515517
default:
@@ -550,11 +552,11 @@ func exportHistory(ctx *cli.Context) error {
550552
format := ctx.String(utils.EraFormatFlag.Get(ctx))
551553
switch format {
552554
case "era1", "era":
553-
if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxEra1Size), utils.Era1); err != nil {
555+
if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxSize), onedb.NewBuilder, onedb.Filename); err != nil {
554556
utils.Fatalf("Export error: %v\n", err)
555557
}
556558
case "erae":
557-
if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era2.MaxEraESize), utils.EraE); err != nil {
559+
if err := utils.ExportHistory(chain, dir, uint64(first), uint64(last), uint64(era.MaxSize), execdb.NewBuilder, execdb.Filename); err != nil {
558560
utils.Fatalf("Export error: %v\n", err)
559561
}
560562
default:

cmd/utils/cmd.go

Lines changed: 8 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import (
4343
"github.com/ethereum/go-ethereum/eth/ethconfig"
4444
"github.com/ethereum/go-ethereum/ethdb"
4545
"github.com/ethereum/go-ethereum/internal/debug"
46-
era2 "github.com/ethereum/go-ethereum/internal/era/execdb"
46+
"github.com/ethereum/go-ethereum/internal/era"
4747
"github.com/ethereum/go-ethereum/internal/era/onedb"
4848
"github.com/ethereum/go-ethereum/log"
4949
"github.com/ethereum/go-ethereum/node"
@@ -251,11 +251,11 @@ func readList(filename string) ([]string, error) {
251251
// ImportHistory imports Era1 files containing historical block information,
252252
// starting from genesis. The assumption is held that the provided chain
253253
// segment in Era1 file should all be canonical and verified.
254-
func ImportHistory(chain *core.BlockChain, dir string, network string) error {
254+
func ImportHistory(chain *core.BlockChain, dir string, network string, from era.FromFn, iterator era.NewIteratorFn) error {
255255
if chain.CurrentSnapBlock().Number.BitLen() != 0 {
256256
return errors.New("history import only supported when starting from genesis")
257257
}
258-
entries, err := onedb.ReadDir(dir, network)
258+
entries, err := era.ReadDir(dir, network)
259259
if err != nil {
260260
return fmt.Errorf("error reading %s: %w", dir, err)
261261
}
@@ -299,11 +299,11 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error {
299299
return fmt.Errorf("%s checksum mismatch: have %s want %s", file, got, want)
300300
}
301301
// Import all block data from Era1.
302-
e, err := onedb.From(f)
302+
e, err := from(f)
303303
if err != nil {
304304
return fmt.Errorf("error opening era: %w", err)
305305
}
306-
it, err := onedb.NewIterator(e)
306+
it, err := iterator(e)
307307
if err != nil {
308308
return fmt.Errorf("error creating iterator: %w", err)
309309
}
@@ -345,105 +345,6 @@ func ImportHistory(chain *core.BlockChain, dir string, network string) error {
345345
return nil
346346
}
347347

348-
// ImportHistoryEraE imports Era-E files containing historical block information,
349-
// starting from genesis. Currently this function follows the assumptions that the provided chain
350-
// segment in Era-E file should all be canonical and verified. In the future, this function will be
351-
// extended to support importing Era-E files with proof verification.
352-
func ImportHistoryEraE(chain *core.BlockChain, dir, network string) error {
353-
if chain.CurrentSnapBlock().Number.Sign() != 0 {
354-
return errors.New("history import only supported when starting from genesis")
355-
}
356-
357-
entries, err := era2.ReadDir(dir, network)
358-
if err != nil {
359-
return fmt.Errorf("reading %q: %w", dir, err)
360-
}
361-
checksums, err := readList(filepath.Join(dir, "checksums.txt"))
362-
if err != nil {
363-
return fmt.Errorf("reading checksums.txt: %w", err)
364-
}
365-
if len(entries) != len(checksums) {
366-
return fmt.Errorf("mismatch: %d erae files, %d checksums", len(entries), len(checksums))
367-
}
368-
369-
var (
370-
start = time.Now()
371-
reported = time.Now()
372-
imported int
373-
h = sha256.New()
374-
scratch bytes.Buffer
375-
)
376-
377-
for i, file := range entries {
378-
path := filepath.Join(dir, file)
379-
380-
// validate against checksum file in directory
381-
f, err := os.Open(path)
382-
if err != nil {
383-
return fmt.Errorf("open %s: %w", path, err)
384-
}
385-
if _, err := io.Copy(h, f); err != nil {
386-
f.Close()
387-
return fmt.Errorf("checksum %s: %w", path, err)
388-
}
389-
got := common.BytesToHash(h.Sum(scratch.Bytes()[:])).Hex()
390-
want := checksums[i]
391-
h.Reset()
392-
scratch.Reset()
393-
if got != want {
394-
f.Close()
395-
return fmt.Errorf("%s checksum mismatch: have %s want %s", file, got, want)
396-
}
397-
// rewind for reading
398-
if _, err := f.Seek(0, io.SeekStart); err != nil {
399-
f.Close()
400-
return fmt.Errorf("rewind %s: %w", file, err)
401-
}
402-
// import archive
403-
e, err := era2.From(f)
404-
if err != nil {
405-
f.Close()
406-
return fmt.Errorf("open erae %s: %w", file, err)
407-
}
408-
blockCount := e.Count()
409-
410-
for j := uint64(0); j < blockCount; j++ {
411-
hdr, err := e.GetHeader(e.Start() + j)
412-
if err != nil {
413-
return fmt.Errorf("header #%d: %w", hdr.Number.Uint64(), err)
414-
}
415-
if hdr.Number.Sign() == 0 { // skip genesis
416-
continue
417-
}
418-
body, err := e.GetBody(hdr.Number.Uint64())
419-
if err != nil {
420-
return fmt.Errorf("body #%d: %w", hdr.Number.Uint64(), err)
421-
}
422-
rcpts, err := e.GetReceipts(hdr.Number.Uint64(), 1)
423-
if err != nil {
424-
return fmt.Errorf("receipts #%d: %w", hdr.Number.Uint64(), err)
425-
}
426-
blk := types.NewBlockWithHeader(hdr).WithBody(*body)
427-
428-
enc := types.EncodeBlockReceiptLists(rcpts)
429-
if _, err := chain.InsertReceiptChain([]*types.Block{blk}, enc, ^uint64(0)); err != nil {
430-
return fmt.Errorf("insert #%d: %w", hdr.Number.Uint64(), err)
431-
}
432-
433-
imported++
434-
if time.Since(reported) >= 8*time.Second {
435-
log.Info("Importing Era‑E", "head", hdr.Number, "imported", imported, "elapsed", common.PrettyDuration(time.Since(start)))
436-
reported = time.Now()
437-
imported = 0
438-
}
439-
}
440-
f.Close()
441-
}
442-
443-
log.Info("Era‑E import complete", "duration", common.PrettyDuration(time.Since(start)))
444-
return nil
445-
}
446-
447348
func missingBlocks(chain *core.BlockChain, blocks []*types.Block) []*types.Block {
448349
head := chain.CurrentBlock()
449350
for i, block := range blocks {
@@ -514,7 +415,7 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
514415

515416
// ExportHistory exports blockchain history into the specified directory,
516417
// following the Era format.
517-
func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) error {
418+
func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64, builderfn era.NewBuilderFn, filename era.FilenameFn) error {
518419
log.Info("Exporting blockchain history", "dir", dir)
519420
if head := bc.CurrentBlock().Number.Uint64(); head < last {
520421
log.Warn("Last block beyond head, setting last = head", "head", head, "last", last)
@@ -543,7 +444,7 @@ func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) er
543444

544445
for batch := first; batch <= last; batch += step {
545446
idx := int(batch / step)
546-
tmpPath := filepath.Join(dir, onedb.Filename(network, idx, common.Hash{}))
447+
tmpPath := filepath.Join(dir, filename(network, idx, common.Hash{}))
547448

548449
if err := func() error {
549450
fh, err := os.Create(tmpPath)
@@ -552,7 +453,7 @@ func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) er
552453
}
553454
defer fh.Close()
554455

555-
bldr := onedb.NewBuilder(fh)
456+
bldr := builderfn(fh)
556457

557458
for j := uint64(0); j < step && batch+j <= last; j++ {
558459
n := batch + j

core/rawdb/eradb/eradb.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ func (db *Store) openEraFile(epoch uint64) (*onedb.Era, error) {
307307
return nil, fmt.Errorf("pre-merge era1 file has invalid boundary. %d %% %d != 0", e.Start(), era.MaxSize)
308308
}
309309
log.Debug("Opened era1 file", "epoch", epoch)
310-
return e, nil
310+
return e.(*onedb.Era), nil
311311
}
312312

313313
// doneWithFile signals that the caller has finished using a file.

internal/era/era.go

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
package era
22

33
import (
4+
"fmt"
45
"io"
56
"math/big"
7+
"os"
8+
"path"
9+
"strconv"
10+
"strings"
611

712
"github.com/ethereum/go-ethereum/common"
813
"github.com/ethereum/go-ethereum/core/types"
14+
// Removed import of internal/era to avoid import cycle and missing metadata error
915
)
1016

1117
// Type constants for the e2store entries in the Era1 and EraE formats.
@@ -36,12 +42,74 @@ type Iterator interface {
3642
Next() bool
3743
Number() uint64
3844
Block() (*types.Block, error)
45+
BlockAndReceipts() (*types.Block, types.Receipts, error)
3946
Receipts() (types.Receipts, error)
4047
Error() error
4148
}
4249

4350
// Builder represents the interface for various types of era formats.
4451
type Builder interface {
45-
Add(block *types.Block, receipts types.Receipts, td *big.Int, proof []byte) error
52+
Add(block *types.Block, receipts types.Receipts, td *big.Int, proof Proof) error
53+
AddRLP(header, body, receipts, proof []byte, number uint64, hash common.Hash, td, difficulty *big.Int) error
4654
Finalize() (common.Hash, error)
4755
}
56+
57+
// Era represents the interface for reading era data.
58+
type Era interface {
59+
Close() error
60+
Start() uint64
61+
Count() uint64
62+
GetBlockByNumber(num uint64) (*types.Block, error)
63+
GetRawBodyByNumber(num uint64) ([]byte, error)
64+
GetRawReceiptsByNumber(num uint64) ([]byte, error)
65+
}
66+
67+
// NewBuilderFn defines a function type for creating a new Builder.
68+
type NewBuilderFn func(w io.Writer) Builder
69+
70+
// FilenameFn defines a function type for generating a filename based on network, epoch, and root hash.
71+
type FilenameFn func(network string, epoch int, root common.Hash) string
72+
73+
// FromFn defines a function type for creating an Era from a ReadAtSeekCloser.
74+
type FromFn func(f ReadAtSeekCloser) (Era, error)
75+
76+
// NewIteratorFn defines a function type for creating a new Iterator from an Era.
77+
type NewIteratorFn func(e Era) (Iterator, error)
78+
79+
// ReadDir reads all the era1 files in a directory for a given network.
80+
// Format: <network>-<epoch>-<hexroot>.erae or <network>-<epoch>-<hexroot>.era1
81+
func ReadDir(dir, network string) ([]string, error) {
82+
entries, err := os.ReadDir(dir)
83+
var directoryExtension string
84+
if err != nil {
85+
return nil, fmt.Errorf("error reading directory %s: %w", dir, err)
86+
}
87+
var (
88+
next = uint64(0)
89+
eras []string
90+
)
91+
for i, entry := range entries {
92+
fileExtension := path.Ext(entry.Name())
93+
if i == 0 {
94+
directoryExtension = fileExtension
95+
} else if directoryExtension != fileExtension {
96+
return nil, fmt.Errorf("directory %s contains mixed era file formats", dir)
97+
}
98+
if fileExtension != ".erae" || fileExtension != ".era1" {
99+
continue
100+
}
101+
parts := strings.Split(entry.Name(), "-")
102+
if len(parts) != 3 || parts[0] != network {
103+
// Invalid era1 filename, skip.
104+
continue
105+
}
106+
if epoch, err := strconv.ParseUint(parts[1], 10, 64); err != nil {
107+
return nil, fmt.Errorf("malformed era filenames: %s", entry.Name())
108+
} else if epoch != next {
109+
return nil, fmt.Errorf("missing epoch %d", next)
110+
}
111+
next += 1
112+
eras = append(eras, entry.Name())
113+
}
114+
return eras, nil
115+
}

0 commit comments

Comments
 (0)