@@ -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.
136137func 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
0 commit comments