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:
parent
c298148a7f
commit
b5b83db450
@ -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…
Reference in New Issue
Block a user