|
|
@ -18,6 +18,7 @@ |
|
|
|
package core |
|
|
|
package core |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
|
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"fmt" |
|
|
|
"io" |
|
|
|
"io" |
|
|
|
"math/big" |
|
|
|
"math/big" |
|
|
@ -34,7 +35,6 @@ import ( |
|
|
|
"github.com/ethereum/go-ethereum/logger/glog" |
|
|
|
"github.com/ethereum/go-ethereum/logger/glog" |
|
|
|
"github.com/ethereum/go-ethereum/metrics" |
|
|
|
"github.com/ethereum/go-ethereum/metrics" |
|
|
|
"github.com/ethereum/go-ethereum/pow" |
|
|
|
"github.com/ethereum/go-ethereum/pow" |
|
|
|
"github.com/ethereum/go-ethereum/rlp" |
|
|
|
|
|
|
|
"github.com/hashicorp/golang-lru" |
|
|
|
"github.com/hashicorp/golang-lru" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -42,10 +42,9 @@ var ( |
|
|
|
chainlogger = logger.NewLogger("CHAIN") |
|
|
|
chainlogger = logger.NewLogger("CHAIN") |
|
|
|
jsonlogger = logger.NewJsonLogger() |
|
|
|
jsonlogger = logger.NewJsonLogger() |
|
|
|
|
|
|
|
|
|
|
|
blockHashPre = []byte("block-hash-") |
|
|
|
|
|
|
|
blockNumPre = []byte("block-num-") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
blockInsertTimer = metrics.NewTimer("chain/inserts") |
|
|
|
blockInsertTimer = metrics.NewTimer("chain/inserts") |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ErrNoGenesis = errors.New("Genesis not found in chain") |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const ( |
|
|
|
const ( |
|
|
@ -88,25 +87,32 @@ type ChainManager struct { |
|
|
|
pow pow.PoW |
|
|
|
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) |
|
|
|
cache, _ := lru.New(blockCacheLimit) |
|
|
|
bc := &ChainManager{ |
|
|
|
bc := &ChainManager{ |
|
|
|
blockDb: blockDb, |
|
|
|
blockDb: blockDb, |
|
|
|
stateDb: stateDb, |
|
|
|
stateDb: stateDb, |
|
|
|
extraDb: extraDb, |
|
|
|
extraDb: extraDb, |
|
|
|
genesisBlock: GenesisBlock(42, stateDb), |
|
|
|
|
|
|
|
eventMux: mux, |
|
|
|
eventMux: mux, |
|
|
|
quit: make(chan struct{}), |
|
|
|
quit: make(chan struct{}), |
|
|
|
cache: cache, |
|
|
|
cache: cache, |
|
|
|
pow: pow, |
|
|
|
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.
|
|
|
|
bc.genesisBlock = bc.GetBlockByNumber(0) |
|
|
|
if g := bc.GetBlockByNumber(0); g != nil && g.Hash() != genesis.Hash() { |
|
|
|
if bc.genesisBlock == nil { |
|
|
|
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]) |
|
|
|
// XXX Uncomment me before Frontier
|
|
|
|
|
|
|
|
//return nil, ErrNoGenesis
|
|
|
|
|
|
|
|
genesis, err := WriteTestNetGenesisBlock(bc.stateDb, bc.blockDb, 42) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
glog.Fatalln("genisis err", err) |
|
|
|
} |
|
|
|
} |
|
|
|
bc.genesisBlock = genesis |
|
|
|
bc.genesisBlock = genesis |
|
|
|
bc.setLastState() |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
// 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 { |
|
|
|
for hash, _ := range BadHashes { |
|
|
@ -226,7 +232,7 @@ func (bc *ChainManager) recover() bool { |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (bc *ChainManager) setLastState() { |
|
|
|
func (bc *ChainManager) setLastState() error { |
|
|
|
data, _ := bc.blockDb.Get([]byte("LastBlock")) |
|
|
|
data, _ := bc.blockDb.Get([]byte("LastBlock")) |
|
|
|
if len(data) != 0 { |
|
|
|
if len(data) != 0 { |
|
|
|
block := bc.GetBlock(common.BytesToHash(data)) |
|
|
|
block := bc.GetBlock(common.BytesToHash(data)) |
|
|
@ -250,6 +256,8 @@ func (bc *ChainManager) setLastState() { |
|
|
|
if glog.V(logger.Info) { |
|
|
|
if glog.V(logger.Info) { |
|
|
|
glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td) |
|
|
|
glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (bc *ChainManager) makeCache() { |
|
|
|
func (bc *ChainManager) makeCache() { |
|
|
@ -272,7 +280,11 @@ func (bc *ChainManager) Reset() { |
|
|
|
bc.cache, _ = lru.New(blockCacheLimit) |
|
|
|
bc.cache, _ = lru.New(blockCacheLimit) |
|
|
|
|
|
|
|
|
|
|
|
// Prepare the genesis block
|
|
|
|
// 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.insert(bc.genesisBlock) |
|
|
|
bc.currentBlock = bc.genesisBlock |
|
|
|
bc.currentBlock = bc.genesisBlock |
|
|
|
bc.makeCache() |
|
|
|
bc.makeCache() |
|
|
@ -295,7 +307,12 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) { |
|
|
|
// Prepare the genesis block
|
|
|
|
// Prepare the genesis block
|
|
|
|
gb.Td = gb.Difficulty() |
|
|
|
gb.Td = gb.Difficulty() |
|
|
|
bc.genesisBlock = gb |
|
|
|
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.insert(bc.genesisBlock) |
|
|
|
bc.currentBlock = bc.genesisBlock |
|
|
|
bc.currentBlock = bc.genesisBlock |
|
|
|
bc.makeCache() |
|
|
|
bc.makeCache() |
|
|
@ -357,21 +374,6 @@ func (bc *ChainManager) insert(block *types.Block) { |
|
|
|
bc.lastBlockHash = block.Hash() |
|
|
|
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
|
|
|
|
// Accessors
|
|
|
|
func (bc *ChainManager) Genesis() *types.Block { |
|
|
|
func (bc *ChainManager) Genesis() *types.Block { |
|
|
|
return bc.genesisBlock |
|
|
|
return bc.genesisBlock |
|
|
@ -535,7 +537,10 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr |
|
|
|
status = SideStatTy |
|
|
|
status = SideStatTy |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
self.write(block) |
|
|
|
err = WriteBlock(self.blockDb, block) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
glog.Fatalln("db err:", err) |
|
|
|
|
|
|
|
} |
|
|
|
// Delete from future blocks
|
|
|
|
// Delete from future blocks
|
|
|
|
self.futureBlocks.Remove(block.Hash()) |
|
|
|
self.futureBlocks.Remove(block.Hash()) |
|
|
|
|
|
|
|
|
|
|
|