aboutsummaryrefslogtreecommitdiffstats
path: root/core/chain_manager.go
diff options
context:
space:
mode:
Diffstat (limited to 'core/chain_manager.go')
-rw-r--r--core/chain_manager.go132
1 files changed, 64 insertions, 68 deletions
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 3c5eb0e8a..fc1d1304f 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -1,23 +1,24 @@
// Copyright 2014 The go-ethereum Authors
-// This file is part of go-ethereum.
+// This file is part of the go-ethereum library.
//
-// go-ethereum is free software: you can redistribute it and/or modify
+// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
-// go-ethereum is distributed in the hope that it will be useful,
+// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
-// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
+// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package core implements the Ethereum consensus protocol.
package core
import (
+ "errors"
"fmt"
"io"
"math/big"
@@ -34,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/rlp"
"github.com/hashicorp/golang-lru"
)
@@ -42,10 +42,9 @@ var (
chainlogger = logger.NewLogger("CHAIN")
jsonlogger = logger.NewJsonLogger()
- blockHashPre = []byte("block-hash-")
- blockNumPre = []byte("block-num-")
-
blockInsertTimer = metrics.NewTimer("chain/inserts")
+
+ ErrNoGenesis = errors.New("Genesis not found in chain")
)
const (
@@ -74,13 +73,11 @@ type ChainManager struct {
lastBlockHash common.Hash
currentGasLimit *big.Int
- transState *state.StateDB
- txState *state.ManagedState
-
cache *lru.Cache // cache is the LRU caching
futureBlocks *lru.Cache // future blocks are blocks added for later processing
- quit chan struct{}
+ quit chan struct{}
+ running int32 // running must be called automically
// procInterrupt must be atomically called
procInterrupt int32 // interrupt signaler for block processing
wg sync.WaitGroup
@@ -88,25 +85,34 @@ type ChainManager struct {
pow pow.PoW
}
-func NewChainManager(genesis *types.Block, blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) {
+func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) {
cache, _ := lru.New(blockCacheLimit)
bc := &ChainManager{
- blockDb: blockDb,
- stateDb: stateDb,
- extraDb: extraDb,
- genesisBlock: GenesisBlock(42, stateDb),
- eventMux: mux,
- quit: make(chan struct{}),
- cache: cache,
- pow: pow,
- }
- // Check the genesis block given to the chain manager. If the genesis block mismatches block number 0
- // throw an error. If no block or the same block's found continue.
- if g := bc.GetBlockByNumber(0); g != nil && g.Hash() != genesis.Hash() {
- return nil, fmt.Errorf("Genesis mismatch. Maybe different nonce (%d vs %d)? %x / %x", g.Nonce(), genesis.Nonce(), g.Hash().Bytes()[:4], genesis.Hash().Bytes()[:4])
- }
- bc.genesisBlock = genesis
- bc.setLastState()
+ blockDb: blockDb,
+ stateDb: stateDb,
+ extraDb: extraDb,
+ eventMux: mux,
+ quit: make(chan struct{}),
+ cache: cache,
+ pow: pow,
+ }
+
+ bc.genesisBlock = bc.GetBlockByNumber(0)
+ if bc.genesisBlock == nil {
+ reader, err := NewDefaultGenesisReader()
+ if err != nil {
+ return nil, err
+ }
+ bc.genesisBlock, err = WriteGenesisBlock(stateDb, blockDb, reader)
+ if err != nil {
+ return nil, err
+ }
+ glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
+ }
+
+ if err := bc.setLastState(); err != nil {
+ return nil, err
+ }
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
for hash, _ := range BadHashes {
@@ -122,9 +128,7 @@ func NewChainManager(genesis *types.Block, blockDb, stateDb, extraDb common.Data
}
}
- bc.transState = bc.State().Copy()
// Take ownership of this particular state
- bc.txState = state.ManageState(bc.State().Copy())
bc.futureBlocks, _ = lru.New(maxFutureBlocks)
bc.makeCache()
@@ -146,9 +150,6 @@ func (bc *ChainManager) SetHead(head *types.Block) {
bc.currentBlock = head
bc.makeCache()
- statedb := state.New(head.Root(), bc.stateDb)
- bc.txState = state.ManageState(statedb)
- bc.transState = statedb.Copy()
bc.setTotalDifficulty(head.Td)
bc.insert(head)
bc.setLastState()
@@ -197,17 +198,6 @@ func (self *ChainManager) State() *state.StateDB {
return state.New(self.CurrentBlock().Root(), self.stateDb)
}
-func (self *ChainManager) TransState() *state.StateDB {
- self.tsmu.RLock()
- defer self.tsmu.RUnlock()
-
- return self.transState
-}
-
-func (self *ChainManager) setTransState(statedb *state.StateDB) {
- self.transState = statedb
-}
-
func (bc *ChainManager) recover() bool {
data, _ := bc.blockDb.Get([]byte("checkpoint"))
if len(data) != 0 {
@@ -226,7 +216,7 @@ func (bc *ChainManager) recover() bool {
return false
}
-func (bc *ChainManager) setLastState() {
+func (bc *ChainManager) setLastState() error {
data, _ := bc.blockDb.Get([]byte("LastBlock"))
if len(data) != 0 {
block := bc.GetBlock(common.BytesToHash(data))
@@ -250,6 +240,8 @@ func (bc *ChainManager) setLastState() {
if glog.V(logger.Info) {
glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td)
}
+
+ return nil
}
func (bc *ChainManager) makeCache() {
@@ -272,7 +264,11 @@ func (bc *ChainManager) Reset() {
bc.cache, _ = lru.New(blockCacheLimit)
// Prepare the genesis block
- bc.write(bc.genesisBlock)
+ err := WriteBlock(bc.blockDb, bc.genesisBlock)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
+
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
bc.makeCache()
@@ -295,7 +291,12 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
// Prepare the genesis block
gb.Td = gb.Difficulty()
bc.genesisBlock = gb
- bc.write(bc.genesisBlock)
+
+ err := WriteBlock(bc.blockDb, bc.genesisBlock)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
+
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
bc.makeCache()
@@ -357,21 +358,6 @@ func (bc *ChainManager) insert(block *types.Block) {
bc.lastBlockHash = block.Hash()
}
-func (bc *ChainManager) write(block *types.Block) {
- tstart := time.Now()
-
- enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
- key := append(blockHashPre, block.Hash().Bytes()...)
- err := bc.blockDb.Put(key, enc)
- if err != nil {
- glog.Fatal("db write fail:", err)
- }
-
- if glog.V(logger.Debug) {
- glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart))
- }
-}
-
// Accessors
func (bc *ChainManager) Genesis() *types.Block {
return bc.genesisBlock
@@ -466,6 +452,9 @@ func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
}
func (bc *ChainManager) Stop() {
+ if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
+ return
+ }
close(bc.quit)
atomic.StoreInt32(&bc.procInterrupt, 1)
@@ -527,15 +516,15 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr
self.insert(block)
self.mu.Unlock()
- self.setTransState(state.New(block.Root(), self.stateDb))
- self.txState.SetState(state.New(block.Root(), self.stateDb))
-
status = CanonStatTy
} else {
status = SideStatTy
}
- self.write(block)
+ err = WriteBlock(self.blockDb, block)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
// Delete from future blocks
self.futureBlocks.Remove(block.Hash())
@@ -662,6 +651,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
queue[i] = ChainSplitEvent{block, logs}
queueEvent.splitCount++
}
+ PutBlockReceipts(self.extraDb, block, receipts)
+
stats.processed++
}
@@ -739,7 +730,12 @@ func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error {
// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
self.mu.Lock()
for _, block := range newChain {
+ // insert the block in the canonical way, re-writing history
self.insert(block)
+ // write canonical receipts and transactions
+ PutTransactions(self.extraDb, block, block.Transactions())
+ PutReceipts(self.extraDb, GetBlockReceipts(self.extraDb, block.Hash()))
+
}
self.mu.Unlock()