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.
This commit is contained in:
Felix Lange 2015-03-18 13:36:48 +01:00
parent c298148a7f
commit b5b83db450
2 changed files with 34 additions and 30 deletions

View File

@ -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
} }

View File

@ -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 {