Skip to content

Commit e1eb34a

Browse files
committed
updated cmd/era
1 parent 7834a74 commit e1eb34a

File tree

3 files changed

+102
-29
lines changed

3 files changed

+102
-29
lines changed

cmd/era/main.go

Lines changed: 90 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/ethereum/go-ethereum/common"
3131
"github.com/ethereum/go-ethereum/core/types"
3232
"github.com/ethereum/go-ethereum/internal/era"
33+
"github.com/ethereum/go-ethereum/internal/era/execdb"
3334
"github.com/ethereum/go-ethereum/internal/era/onedb"
3435
"github.com/ethereum/go-ethereum/internal/ethapi"
3536
"github.com/ethereum/go-ethereum/internal/flags"
@@ -132,7 +133,7 @@ func block(ctx *cli.Context) error {
132133
return nil
133134
}
134135

135-
// info prints some high-level information about the era1 file.
136+
// info prints some high-level information about the era file.
136137
func info(ctx *cli.Context) error {
137138
epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
138139
if err != nil {
@@ -143,42 +144,63 @@ func info(ctx *cli.Context) error {
143144
return err
144145
}
145146
defer e.Close()
146-
acc, err := e.Accumulator()
147-
if err != nil {
148-
return fmt.Errorf("error reading accumulator: %w", err)
147+
var (
148+
accHex string
149+
tdStr string
150+
)
151+
if acc, err := e.Accumulator(); err == nil {
152+
accHex = acc.Hex()
149153
}
150-
td, err := e.InitialTD()
151-
if err != nil {
152-
return fmt.Errorf("error reading total difficulty: %w", err)
154+
if td, err := e.InitialTD(); err == nil {
155+
tdStr = td.String()
153156
}
154157
info := struct {
155-
Accumulator common.Hash `json:"accumulator"`
156-
TotalDifficulty *big.Int `json:"totalDifficulty"`
157-
StartBlock uint64 `json:"startBlock"`
158-
Count uint64 `json:"count"`
158+
Accumulator string `json:"accumulator,omitempty"`
159+
TotalDifficulty string `json:"totalDifficulty,omitempty"`
160+
StartBlock uint64 `json:"startBlock"`
161+
Count uint64 `json:"count"`
159162
}{
160-
acc, td, e.Start(), e.Count(),
163+
accHex, tdStr, e.Start(), e.Count(),
161164
}
162165
b, _ := json.MarshalIndent(info, "", " ")
163166
fmt.Println(string(b))
164167
return nil
165168
}
166169

167-
// open opens an era1 file at a certain epoch.
168-
func open(ctx *cli.Context, epoch uint64) (*onedb.Era, error) {
169-
var (
170-
dir = ctx.String(dirFlag.Name)
171-
network = ctx.String(networkFlag.Name)
172-
)
170+
// open opens an era file at a certain epoch.
171+
func open(ctx *cli.Context, epoch uint64) (era.Era, error) {
172+
dir := ctx.String(dirFlag.Name)
173+
network := ctx.String(networkFlag.Name)
174+
173175
entries, err := era.ReadDir(dir, network)
174176
if err != nil {
175177
return nil, fmt.Errorf("error reading era dir: %w", err)
176178
}
177179
if epoch >= uint64(len(entries)) {
178180
return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
179181
}
180-
era, err := onedb.Open(filepath.Join(dir, entries[epoch]))
181-
return era.(*onedb.Era), err
182+
path := filepath.Join(dir, entries[epoch])
183+
return openByPath(path)
184+
}
185+
186+
// openByPath tries to open a single file as either eraE or era1 based on extension,
187+
// falling back to the other reader if needed.
188+
func openByPath(path string) (era.Era, error) {
189+
switch strings.ToLower(filepath.Ext(path)) {
190+
case ".erae":
191+
if e, err := execdb.Open(path); err != nil {
192+
return nil, err
193+
} else {
194+
return e, nil
195+
}
196+
case ".era1":
197+
if e, err := onedb.Open(path); err != nil {
198+
return nil, err
199+
} else {
200+
return e, nil
201+
}
202+
}
203+
return nil, fmt.Errorf("unsupported or unreadable era file: %s", path)
182204
}
183205

184206
// verify checks each era1 file in a directory to ensure it is well-formed and
@@ -205,29 +227,68 @@ func verify(ctx *cli.Context) error {
205227
return fmt.Errorf("error reading %s: %w", dir, err)
206228
}
207229

208-
if len(entries) != len(roots) {
209-
return errors.New("number of era1 files should match the number of accumulator hashes")
230+
// Build the verification list respecting the rule:
231+
// era1: must have accumulator, always verify
232+
// erae: verify only if accumulator exists (pre-merge)
233+
234+
// Build list of files to verify.
235+
verify := make([]string, 0, len(entries))
236+
237+
for _, name := range entries {
238+
path := filepath.Join(dir, name)
239+
ext := strings.ToLower(filepath.Ext(name))
240+
241+
switch ext {
242+
case ".era1":
243+
e, err := onedb.Open(path)
244+
if err != nil {
245+
return fmt.Errorf("error opening era1 file %s: %w", name, err)
246+
}
247+
_, accErr := e.Accumulator()
248+
e.Close()
249+
if accErr != nil {
250+
return fmt.Errorf("era1 file %s missing accumulator: %w", name, accErr)
251+
}
252+
verify = append(verify, path)
253+
254+
case ".erae":
255+
e, err := execdb.Open(path)
256+
if err != nil {
257+
return fmt.Errorf("error opening erae file %s: %w", name, err)
258+
}
259+
_, accErr := e.Accumulator()
260+
e.Close()
261+
if accErr == nil {
262+
verify = append(verify, path) // pre-merge only
263+
}
264+
default:
265+
return fmt.Errorf("unsupported era file: %s", name)
266+
}
267+
}
268+
269+
if len(verify) != len(roots) {
270+
return fmt.Errorf("mismatch between eras to verify (%d) and provided roots (%d)", len(verify), len(roots))
210271
}
211272

212273
// Verify each epoch matches the expected root.
213274
for i, want := range roots {
214275
// Wrap in function so defers don't stack.
215276
err := func() error {
216-
name := entries[i]
217-
e, err := onedb.Open(filepath.Join(dir, name))
218-
eraPointer := e.(*onedb.Era)
277+
path := verify[i]
278+
name := filepath.Base(path)
279+
e, err := openByPath(path)
219280
if err != nil {
220-
return fmt.Errorf("error opening era1 file %s: %w", name, err)
281+
return fmt.Errorf("error opening era file %s: %w", name, err)
221282
}
222283
defer e.Close()
223284
// Read accumulator and check against expected.
224-
if got, err := eraPointer.Accumulator(); err != nil {
285+
if got, err := e.Accumulator(); err != nil {
225286
return fmt.Errorf("error retrieving accumulator for %s: %w", name, err)
226287
} else if got != want {
227288
return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want)
228289
}
229290
// Recompute accumulator.
230-
if err := checkAccumulator(eraPointer); err != nil {
291+
if err := checkAccumulator(e); err != nil {
231292
return fmt.Errorf("error verify era1 file %s: %w", name, err)
232293
}
233294
// Give the user some feedback that something is happening.
@@ -246,7 +307,7 @@ func verify(ctx *cli.Context) error {
246307
}
247308

248309
// checkAccumulator verifies the accumulator matches the data in the Era.
249-
func checkAccumulator(e *onedb.Era) error {
310+
func checkAccumulator(e era.Era) error {
250311
var (
251312
err error
252313
want common.Hash

internal/era/era.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ type Era interface {
6363
GetBlockByNumber(num uint64) (*types.Block, error)
6464
GetRawBodyByNumber(num uint64) ([]byte, error)
6565
GetRawReceiptsByNumber(num uint64) ([]byte, error)
66+
InitialTD() (*big.Int, error)
67+
Accumulator() (common.Hash, error)
6668
}
6769

6870
// ReadDir reads all the era1 files in a directory for a given network.

internal/era/execdb/reader.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,16 @@ func (e *Era) InitialTD() (*big.Int, error) {
227227
return td.Sub(td, header.Difficulty), nil
228228
}
229229

230+
// Accumulator reads the accumulator entry in the EraE file if it exists.
231+
// Note that one premerge erae files will contain an accumulator entry.
232+
func (e *Era) Accumulator() (common.Hash, error) {
233+
entry, err := e.s.Find(era.TypeAccumulator)
234+
if err != nil {
235+
return common.Hash{}, err
236+
}
237+
return common.BytesToHash(entry.Value), nil
238+
}
239+
230240
// loadIndex loads in the index table containing all offsets and caches it.
231241
func (e *Era) loadIndex() error {
232242
var err error

0 commit comments

Comments
 (0)