From b5b83db450974f70f4bc25f280cc6ec9193f8e19 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Wed, 18 Mar 2015 13:36:48 +0100 Subject: [PATCH] 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. --- cmd/utils/cmd.go | 37 ++++++++++++++++++++++--------------- core/chain_manager.go | 27 ++++++++++++--------------- 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go index 74fd5334e9..66e89abefa 100644 --- a/cmd/utils/cmd.go +++ b/cmd/utils/cmd.go @@ -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) + } + 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 } 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 } diff --git a/core/chain_manager.go b/core/chain_manager.go index 5316a34230..0608054285 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -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 {