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

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

@ -3,6 +3,7 @@ package core
import (
"bytes"
"fmt"
"io"
"math/big"
"sync"
@ -254,22 +255,20 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
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()
defer self.mu.RUnlock()
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) {
blocks[block.NumberU64()] = block
if err := block.EncodeRLP(w); err != nil {
return err
}
return common.Encode(blocks)
}
return nil
}
func (bc *ChainManager) insert(block *types.Block) {
//encodedBlock := common.Encode(block)
bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes())
bc.currentBlock = block
bc.lastBlockHash = block.Hash()
@ -279,10 +278,9 @@ func (bc *ChainManager) insert(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()...)
bc.blockDb.Put(key, encodedBlock)
bc.blockDb.Put(key, enc)
}
// Accessors
@ -324,13 +322,12 @@ func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
if len(data) == 0 {
return nil
}
var block types.Block
var block types.StorageBlock
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 &block
return (*types.Block)(&block)
}
func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {