Skip to content

Commit

Permalink
switch to freezer
Browse files Browse the repository at this point in the history
  • Loading branch information
lightclient committed Mar 10, 2023
1 parent 00c27ff commit 3ae5a6c
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 31 deletions.
13 changes: 7 additions & 6 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,10 +380,14 @@ func exportHistory(ctx *cli.Context) error {
utils.Fatalf("This command requires an argument.")
}

stack, _ := makeConfigNode(ctx)
stack, config := makeConfigNode(ctx)
defer stack.Close()

chain, _ := utils.MakeChain(ctx, stack, true)
db, err := rawdb.NewChainFreezer(stack.ResolveAncient("chaindata", config.Eth.DatabaseFreezer), "eth/db/chaindata/", true)
if err != nil {
return err
}

start := time.Now()

first, ferr := strconv.ParseInt(ctx.Args().Get(1), 10, 64)
Expand All @@ -395,10 +399,7 @@ func exportHistory(ctx *cli.Context) error {
if first < 0 || last < 0 || step < 0 {
utils.Fatalf("Export error: block number and step must be greater than 0\n")
}
if head := chain.CurrentFastBlock(); uint64(last) > head.NumberU64() {
utils.Fatalf("Export error: block number %d larger than head block %d\n", uint64(last), head.NumberU64())
}
err := utils.ExportHistory(chain, ctx.Args().First(), uint64(first), uint64(last), uint64(step))
err = utils.ExportHistory(db, ctx.Args().First(), uint64(first), uint64(last), uint64(step))
if err != nil {
utils.Fatalf("Export error: %v\n", err)
}
Expand Down
93 changes: 69 additions & 24 deletions cmd/utils/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"errors"
"fmt"
"io"
"math/big"
"os"
"os/signal"
"path"
Expand All @@ -42,8 +43,8 @@ import (
"github.com/ethereum/go-ethereum/internal/era"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
"github.com/urfave/cli/v2"
)

Expand Down Expand Up @@ -290,16 +291,23 @@ func ExportAppendChain(blockchain *core.BlockChain, fn string, first uint64, las
return nil
}

func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) error {
func ExportHistory(db ethdb.AncientReader, dir string, first, last, step uint64) error {
log.Info("Exporting blockchain history", "dir", dir)
if head := bc.CurrentBlock().NumberU64(); head < last {
log.Warn("Last block beyond head, setting last = head", "head", head, "last", last)
last = head
frozen, err := db.Ancients()
if err != nil {
return err
}
if first > frozen {
return fmt.Errorf("First block beyond last frozen block (frozen %d, first %d)", frozen, first)
}
network := "unknown"
if name, ok := params.NetworkNames[bc.Config().ChainID.String()]; ok {
network = name
if last > frozen {
log.Warn("Last block beyond last frozen block, setting last = frozen", "frozen", frozen, "last", last)
last = frozen
}
network := "mainnet"
// if name, ok := params.NetworkNames[db.Config().ChainID.String()]; ok {
// network = name
// }
if err := os.MkdirAll(dir, os.ModePerm); err != nil {
return fmt.Errorf("error creating output directory: %w", err)
}
Expand All @@ -318,24 +326,61 @@ func ExportHistory(bc *core.BlockChain, dir string, first, last, step uint64) er
defer fh.Close()

w := era.NewBuilder(fh)
for j := uint64(0); j < step && j <= last-i; j++ {
for j := uint64(1); j < step && j <= last-i; j++ {
nr := i + j
block := bc.GetBlockByNumber(nr)
if block == nil {
return fmt.Errorf("export failed on #%d: not found", nr)
}
receipts := bc.GetReceiptsByHash(block.Hash())
if receipts == nil {
return fmt.Errorf("export failed on #%d: receipts not found", nr)
}
td := bc.GetTd(block.Hash(), block.NumberU64())
if td == nil {
return fmt.Errorf("export failed on #%d: total difficulty not found", nr)
}
if receipts == nil {
return fmt.Errorf("export failed on #%d: receipts not found", nr)

var (
header types.Header
body types.Body
receipts types.Receipts
td big.Int
)

err := db.ReadAncients(func(op ethdb.AncientReaderOp) error {
// header
data, _ := db.Ancient(rawdb.ChainFreezerHeaderTable, nr)
if len(data) == 0 {
return fmt.Errorf("export failed on #%d: not found", nr)
}
if err := rlp.DecodeBytes(data, &header); err != nil {
return fmt.Errorf("error decoding header %d: %w, %v", nr, err, data)
}

// body
data, _ = db.Ancient(rawdb.ChainFreezerBodiesTable, nr)
if len(data) == 0 {
return fmt.Errorf("export failed on #%d: not found", nr)
}
if err := rlp.DecodeBytes(data, &header); err != nil {
return fmt.Errorf("error decoding body %d: %w", nr, err)
}

// receipts
data, _ = db.Ancient(rawdb.ChainFreezerReceiptTable, nr)
if len(data) == 0 {
return fmt.Errorf("export failed on #%d: receipts not found", nr)
}
if err := rlp.DecodeBytes(data, &receipts); err != nil {
return fmt.Errorf("error decoding receipts %d: %w", nr, err)
}

// total difficulty
data, _ = db.Ancient(rawdb.ChainFreezerDifficultyTable, nr)
if len(data) == 0 {
return fmt.Errorf("export failed on #%d: total difficulty not found", nr)
}
if err := rlp.DecodeBytes(data, &td); err != nil {
return fmt.Errorf("error decoding total difficulty %d: %w", nr, err)
}

return nil
})
if err != nil {
return err
}
if err := w.Add(block, receipts, td); err != nil {

block := types.NewBlock(&header, body.Transactions, body.Uncles, receipts, trie.NewStackTrie(nil))
if err := w.Add(block, receipts, &td); err != nil {
return err
}
}
Expand Down
3 changes: 2 additions & 1 deletion core/rawdb/freezer.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type Freezer struct {
// NewChainFreezer is a small utility method around NewFreezer that sets the
// default parameters for the chain storage.
func NewChainFreezer(datadir string, namespace string, readonly bool) (*Freezer, error) {
return NewFreezer(datadir, namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
return NewFreezer(resolveChainFreezerDir(datadir), namespace, readonly, freezerTableSize, chainFreezerNoSnappy)
}

// NewFreezer creates a freezer instance for maintaining immutable ordered
Expand All @@ -91,6 +91,7 @@ func NewChainFreezer(datadir string, namespace string, readonly bool) (*Freezer,
// The 'tables' argument defines the data tables. If the value of a map
// entry is true, snappy compression is disabled for the table.
func NewFreezer(datadir string, namespace string, readonly bool, maxTableSize uint32, tables map[string]bool) (*Freezer, error) {
fmt.Println(datadir)
// Create the initial freezer object
var (
readMeter = metrics.NewRegisteredMeter(namespace+"ancient/read", nil)
Expand Down

0 comments on commit 3ae5a6c

Please sign in to comment.