mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 11:46:44 +00:00
updated cmd/era
This commit is contained in:
parent
295b33b708
commit
4a4a1892e3
3 changed files with 102 additions and 29 deletions
119
cmd/era/main.go
119
cmd/era/main.go
|
|
@ -30,6 +30,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/era"
|
"github.com/ethereum/go-ethereum/internal/era"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/era/execdb"
|
||||||
"github.com/ethereum/go-ethereum/internal/era/onedb"
|
"github.com/ethereum/go-ethereum/internal/era/onedb"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/internal/flags"
|
"github.com/ethereum/go-ethereum/internal/flags"
|
||||||
|
|
@ -132,7 +133,7 @@ func block(ctx *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// info prints some high-level information about the era1 file.
|
// info prints some high-level information about the era file.
|
||||||
func info(ctx *cli.Context) error {
|
func info(ctx *cli.Context) error {
|
||||||
epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
|
epoch, err := strconv.ParseUint(ctx.Args().First(), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -143,33 +144,34 @@ func info(ctx *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer e.Close()
|
defer e.Close()
|
||||||
acc, err := e.Accumulator()
|
var (
|
||||||
if err != nil {
|
accHex string
|
||||||
return fmt.Errorf("error reading accumulator: %w", err)
|
tdStr string
|
||||||
|
)
|
||||||
|
if acc, err := e.Accumulator(); err == nil {
|
||||||
|
accHex = acc.Hex()
|
||||||
}
|
}
|
||||||
td, err := e.InitialTD()
|
if td, err := e.InitialTD(); err == nil {
|
||||||
if err != nil {
|
tdStr = td.String()
|
||||||
return fmt.Errorf("error reading total difficulty: %w", err)
|
|
||||||
}
|
}
|
||||||
info := struct {
|
info := struct {
|
||||||
Accumulator common.Hash `json:"accumulator"`
|
Accumulator string `json:"accumulator,omitempty"`
|
||||||
TotalDifficulty *big.Int `json:"totalDifficulty"`
|
TotalDifficulty string `json:"totalDifficulty,omitempty"`
|
||||||
StartBlock uint64 `json:"startBlock"`
|
StartBlock uint64 `json:"startBlock"`
|
||||||
Count uint64 `json:"count"`
|
Count uint64 `json:"count"`
|
||||||
}{
|
}{
|
||||||
acc, td, e.Start(), e.Count(),
|
accHex, tdStr, e.Start(), e.Count(),
|
||||||
}
|
}
|
||||||
b, _ := json.MarshalIndent(info, "", " ")
|
b, _ := json.MarshalIndent(info, "", " ")
|
||||||
fmt.Println(string(b))
|
fmt.Println(string(b))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// open opens an era1 file at a certain epoch.
|
// open opens an era file at a certain epoch.
|
||||||
func open(ctx *cli.Context, epoch uint64) (*onedb.Era, error) {
|
func open(ctx *cli.Context, epoch uint64) (era.Era, error) {
|
||||||
var (
|
dir := ctx.String(dirFlag.Name)
|
||||||
dir = ctx.String(dirFlag.Name)
|
network := ctx.String(networkFlag.Name)
|
||||||
network = ctx.String(networkFlag.Name)
|
|
||||||
)
|
|
||||||
entries, err := era.ReadDir(dir, network)
|
entries, err := era.ReadDir(dir, network)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading era dir: %w", err)
|
return nil, fmt.Errorf("error reading era dir: %w", err)
|
||||||
|
|
@ -177,8 +179,28 @@ func open(ctx *cli.Context, epoch uint64) (*onedb.Era, error) {
|
||||||
if epoch >= uint64(len(entries)) {
|
if epoch >= uint64(len(entries)) {
|
||||||
return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
|
return nil, fmt.Errorf("epoch out-of-bounds: last %d, want %d", len(entries)-1, epoch)
|
||||||
}
|
}
|
||||||
era, err := onedb.Open(filepath.Join(dir, entries[epoch]))
|
path := filepath.Join(dir, entries[epoch])
|
||||||
return era.(*onedb.Era), err
|
return openByPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
// openByPath tries to open a single file as either eraE or era1 based on extension,
|
||||||
|
// falling back to the other reader if needed.
|
||||||
|
func openByPath(path string) (era.Era, error) {
|
||||||
|
switch strings.ToLower(filepath.Ext(path)) {
|
||||||
|
case ".erae":
|
||||||
|
if e, err := execdb.Open(path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
case ".era1":
|
||||||
|
if e, err := onedb.Open(path); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
return e, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("unsupported or unreadable era file: %s", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify checks each era1 file in a directory to ensure it is well-formed and
|
// 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 {
|
||||||
return fmt.Errorf("error reading %s: %w", dir, err)
|
return fmt.Errorf("error reading %s: %w", dir, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(entries) != len(roots) {
|
// Build the verification list respecting the rule:
|
||||||
return errors.New("number of era1 files should match the number of accumulator hashes")
|
// era1: must have accumulator, always verify
|
||||||
|
// erae: verify only if accumulator exists (pre-merge)
|
||||||
|
|
||||||
|
// Build list of files to verify.
|
||||||
|
verify := make([]string, 0, len(entries))
|
||||||
|
|
||||||
|
for _, name := range entries {
|
||||||
|
path := filepath.Join(dir, name)
|
||||||
|
ext := strings.ToLower(filepath.Ext(name))
|
||||||
|
|
||||||
|
switch ext {
|
||||||
|
case ".era1":
|
||||||
|
e, err := onedb.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error opening era1 file %s: %w", name, err)
|
||||||
|
}
|
||||||
|
_, accErr := e.Accumulator()
|
||||||
|
e.Close()
|
||||||
|
if accErr != nil {
|
||||||
|
return fmt.Errorf("era1 file %s missing accumulator: %w", name, accErr)
|
||||||
|
}
|
||||||
|
verify = append(verify, path)
|
||||||
|
|
||||||
|
case ".erae":
|
||||||
|
e, err := execdb.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error opening erae file %s: %w", name, err)
|
||||||
|
}
|
||||||
|
_, accErr := e.Accumulator()
|
||||||
|
e.Close()
|
||||||
|
if accErr == nil {
|
||||||
|
verify = append(verify, path) // pre-merge only
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported era file: %s", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(verify) != len(roots) {
|
||||||
|
return fmt.Errorf("mismatch between eras to verify (%d) and provided roots (%d)", len(verify), len(roots))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify each epoch matches the expected root.
|
// Verify each epoch matches the expected root.
|
||||||
for i, want := range roots {
|
for i, want := range roots {
|
||||||
// Wrap in function so defers don't stack.
|
// Wrap in function so defers don't stack.
|
||||||
err := func() error {
|
err := func() error {
|
||||||
name := entries[i]
|
path := verify[i]
|
||||||
e, err := onedb.Open(filepath.Join(dir, name))
|
name := filepath.Base(path)
|
||||||
eraPointer := e.(*onedb.Era)
|
e, err := openByPath(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error opening era1 file %s: %w", name, err)
|
return fmt.Errorf("error opening era file %s: %w", name, err)
|
||||||
}
|
}
|
||||||
defer e.Close()
|
defer e.Close()
|
||||||
// Read accumulator and check against expected.
|
// Read accumulator and check against expected.
|
||||||
if got, err := eraPointer.Accumulator(); err != nil {
|
if got, err := e.Accumulator(); err != nil {
|
||||||
return fmt.Errorf("error retrieving accumulator for %s: %w", name, err)
|
return fmt.Errorf("error retrieving accumulator for %s: %w", name, err)
|
||||||
} else if got != want {
|
} else if got != want {
|
||||||
return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want)
|
return fmt.Errorf("invalid root %s: got %s, want %s", name, got, want)
|
||||||
}
|
}
|
||||||
// Recompute accumulator.
|
// Recompute accumulator.
|
||||||
if err := checkAccumulator(eraPointer); err != nil {
|
if err := checkAccumulator(e); err != nil {
|
||||||
return fmt.Errorf("error verify era1 file %s: %w", name, err)
|
return fmt.Errorf("error verify era1 file %s: %w", name, err)
|
||||||
}
|
}
|
||||||
// Give the user some feedback that something is happening.
|
// Give the user some feedback that something is happening.
|
||||||
|
|
@ -246,7 +307,7 @@ func verify(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkAccumulator verifies the accumulator matches the data in the Era.
|
// checkAccumulator verifies the accumulator matches the data in the Era.
|
||||||
func checkAccumulator(e *onedb.Era) error {
|
func checkAccumulator(e era.Era) error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
want common.Hash
|
want common.Hash
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ type Era interface {
|
||||||
GetBlockByNumber(num uint64) (*types.Block, error)
|
GetBlockByNumber(num uint64) (*types.Block, error)
|
||||||
GetRawBodyByNumber(num uint64) ([]byte, error)
|
GetRawBodyByNumber(num uint64) ([]byte, error)
|
||||||
GetRawReceiptsByNumber(num uint64) ([]byte, error)
|
GetRawReceiptsByNumber(num uint64) ([]byte, error)
|
||||||
|
InitialTD() (*big.Int, error)
|
||||||
|
Accumulator() (common.Hash, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadDir reads all the era1 files in a directory for a given network.
|
// ReadDir reads all the era1 files in a directory for a given network.
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,16 @@ func (e *Era) InitialTD() (*big.Int, error) {
|
||||||
return td.Sub(td, header.Difficulty), nil
|
return td.Sub(td, header.Difficulty), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulator reads the accumulator entry in the EraE file if it exists.
|
||||||
|
// Note that one premerge erae files will contain an accumulator entry.
|
||||||
|
func (e *Era) Accumulator() (common.Hash, error) {
|
||||||
|
entry, err := e.s.Find(era.TypeAccumulator)
|
||||||
|
if err != nil {
|
||||||
|
return common.Hash{}, err
|
||||||
|
}
|
||||||
|
return common.BytesToHash(entry.Value), nil
|
||||||
|
}
|
||||||
|
|
||||||
// loadIndex loads in the index table containing all offsets and caches it.
|
// loadIndex loads in the index table containing all offsets and caches it.
|
||||||
func (e *Era) loadIndex() error {
|
func (e *Era) loadIndex() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue