core: use package rlp to encode blocks

This also changes the chain export format so there is no
enclosing list around the blocks, which enables streaming export.
pull/532/head
Felix Lange 10 years ago
parent c298148a7f
commit b5b83db450
  1. 37
      cmd/utils/cmd.go
  2. 27
      core/chain_manager.go

@ -23,14 +23,15 @@ package utils
import ( import (
"fmt" "fmt"
"io"
"os" "os"
"os/signal" "os/signal"
"regexp" "regexp"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
) )
@ -152,29 +153,35 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {
} }
defer fh.Close() defer fh.Close()
var blocks types.Blocks
if err := rlp.Decode(fh, &blocks); err != nil {
return err
}
chainmgr.Reset() chainmgr.Reset()
if err := chainmgr.InsertChain(blocks); err != nil { stream := rlp.NewStream(fh)
return err var i int
for ; ; i++ {
var b types.Block
err := stream.Decode(&b)
if err == io.EOF {
break
} else if err != nil {
return fmt.Errorf("at block %d: %v", i, err)
}
if err := chainmgr.InsertChain(types.Blocks{b}); err != nil {
return fmt.Errorf("invalid block %d: %v", i, err)
}
} }
fmt.Printf("imported %d blocks\n", len(blocks)) fmt.Printf("imported %d blocks\n", i)
return nil return nil
} }
func ExportChain(chainmgr *core.ChainManager, fn string) error { func ExportChain(chainmgr *core.ChainManager, fn string) error {
fmt.Printf("exporting blockchain '%s'\n", fn) fmt.Printf("exporting blockchain '%s'\n", fn)
fh, err := os.OpenFile(fn, os.O_WRONLY|os.O_TRUNC, os.ModePerm)
data := chainmgr.Export() if err != nil {
return err
if err := common.WriteFile(fn, data); err != nil { }
defer fh.Close()
if err := chainmgr.Export(fh); err != nil {
return err return err
} }
fmt.Printf("exported blockchain\n") fmt.Printf("exported blockchain\n")
return nil return nil
} }

@ -3,6 +3,7 @@ package core
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"math/big" "math/big"
"sync" "sync"
@ -254,22 +255,20 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
bc.currentBlock = bc.genesisBlock bc.currentBlock = bc.genesisBlock
} }
func (self *ChainManager) Export() []byte { // Export writes the active chain to the given writer.
func (self *ChainManager) Export(w io.Writer) error {
self.mu.RLock() self.mu.RLock()
defer self.mu.RUnlock() defer self.mu.RUnlock()
chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number)
blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1)
for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) { for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) {
blocks[block.NumberU64()] = block if err := block.EncodeRLP(w); err != nil {
return err
}
} }
return nil
return common.Encode(blocks)
} }
func (bc *ChainManager) insert(block *types.Block) { func (bc *ChainManager) insert(block *types.Block) {
//encodedBlock := common.Encode(block)
bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes()) bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes())
bc.currentBlock = block bc.currentBlock = block
bc.lastBlockHash = block.Hash() bc.lastBlockHash = block.Hash()
@ -279,10 +278,9 @@ func (bc *ChainManager) insert(block *types.Block) {
} }
func (bc *ChainManager) write(block *types.Block) { func (bc *ChainManager) write(block *types.Block) {
encodedBlock := common.Encode(block.RlpDataForStorage()) enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
key := append(blockHashPre, block.Hash().Bytes()...) key := append(blockHashPre, block.Hash().Bytes()...)
bc.blockDb.Put(key, encodedBlock) bc.blockDb.Put(key, enc)
} }
// Accessors // Accessors
@ -324,13 +322,12 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
if len(data) == 0 { if len(data) == 0 {
return nil return nil
} }
var block types.Block var block types.StorageBlock
if err := rlp.Decode(bytes.NewReader(data), &block); err != nil { if err := rlp.Decode(bytes.NewReader(data), &block); err != nil {
fmt.Println(err) chainlogger.Errorf("invalid block RLP for hash %x: %v", hash, err)
return nil return nil
} }
return (*types.Block)(&block)
return &block
} }
func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {

Loading…
Cancel
Save