2014-12-04 03:28:02 -06:00
package core
2014-02-14 16:56:09 -06:00
import (
2014-12-23 06:48:44 -06:00
"bytes"
2014-09-24 04:39:17 -05:00
"fmt"
2015-03-18 07:36:48 -05:00
"io"
2014-07-29 17:31:15 -05:00
"math/big"
2014-12-18 06:12:54 -06:00
"sync"
2015-04-04 09:35:23 -05:00
"time"
2014-07-29 17:31:15 -05:00
2015-03-16 05:27:38 -05:00
"github.com/ethereum/go-ethereum/common"
2015-03-23 16:59:19 -05:00
"github.com/ethereum/go-ethereum/core/state"
2015-03-16 17:48:18 -05:00
"github.com/ethereum/go-ethereum/core/types"
2014-12-03 07:05:19 -06:00
"github.com/ethereum/go-ethereum/event"
2014-10-31 06:56:05 -05:00
"github.com/ethereum/go-ethereum/logger"
2015-04-04 05:40:11 -05:00
"github.com/ethereum/go-ethereum/logger/glog"
2015-04-01 22:17:15 -05:00
"github.com/ethereum/go-ethereum/params"
2014-12-23 06:48:44 -06:00
"github.com/ethereum/go-ethereum/rlp"
2014-02-14 16:56:09 -06:00
)
2015-03-03 02:44:41 -06:00
var (
chainlogger = logger . NewLogger ( "CHAIN" )
jsonlogger = logger . NewJsonLogger ( )
2015-03-13 12:29:42 -05:00
blockHashPre = [ ] byte ( "block-hash-" )
blockNumPre = [ ] byte ( "block-num-" )
2015-03-03 02:44:41 -06:00
)
2014-06-23 06:54:10 -05:00
2015-04-20 13:37:40 -05:00
const (
blockCacheLimit = 10000
maxFutureBlocks = 256
)
2015-01-02 05:07:54 -06:00
2015-03-04 03:49:56 -06:00
func CalcDifficulty ( block , parent * types . Header ) * big . Int {
2014-11-17 05:12:55 -06:00
diff := new ( big . Int )
2015-04-01 22:17:15 -05:00
adjust := new ( big . Int ) . Div ( parent . Difficulty , params . DifficultyBoundDivisor )
if big . NewInt ( int64 ( block . Time ) - int64 ( parent . Time ) ) . Cmp ( params . DurationLimit ) < 0 {
2015-03-04 03:49:56 -06:00
diff . Add ( parent . Difficulty , adjust )
2015-03-02 09:32:02 -06:00
} else {
2015-03-04 03:49:56 -06:00
diff . Sub ( parent . Difficulty , adjust )
2014-11-17 05:12:55 -06:00
}
2015-04-01 22:17:15 -05:00
if diff . Cmp ( params . MinimumDifficulty ) < 0 {
return params . MinimumDifficulty
2015-03-05 02:14:58 -06:00
}
2014-11-17 05:12:55 -06:00
return diff
}
2015-01-09 15:42:36 -06:00
func CalculateTD ( block , parent * types . Block ) * big . Int {
2015-04-30 07:55:21 -05:00
if parent == nil {
return block . Difficulty ( )
}
2015-04-09 09:37:04 -05:00
td := new ( big . Int ) . Add ( parent . Td , block . Header ( ) . Difficulty )
2015-01-09 15:42:36 -06:00
return td
}
2015-04-26 04:19:40 -05:00
func CalcGasLimit ( parent * types . Block ) * big . Int {
2014-12-23 06:48:44 -06:00
// ((1024-1) * parent.gasLimit + (gasUsed * 6 / 5)) / 1024
previous := new ( big . Int ) . Mul ( big . NewInt ( 1024 - 1 ) , parent . GasLimit ( ) )
current := new ( big . Rat ) . Mul ( new ( big . Rat ) . SetInt ( parent . GasUsed ( ) ) , big . NewRat ( 6 , 5 ) )
curInt := new ( big . Int ) . Div ( current . Num ( ) , current . Denom ( ) )
result := new ( big . Int ) . Add ( previous , curInt )
result . Div ( result , big . NewInt ( 1024 ) )
2015-04-01 22:17:15 -05:00
return common . BigMax ( params . GenesisGasLimit , result )
2014-12-23 06:48:44 -06:00
}
2014-10-20 04:53:11 -05:00
type ChainManager struct {
2014-11-18 09:58:22 -06:00
//eth EthManager
2015-03-16 05:27:38 -05:00
blockDb common . Database
stateDb common . Database
2014-11-18 09:58:22 -06:00
processor types . BlockProcessor
2014-12-03 07:05:19 -06:00
eventMux * event . TypeMux
2014-11-18 09:58:22 -06:00
genesisBlock * types . Block
2014-02-14 16:56:09 -06:00
// Last known total difficulty
2015-04-29 05:43:24 -05:00
mu sync . RWMutex
tsmu sync . RWMutex
2015-04-28 10:48:46 -05:00
2015-04-24 10:45:51 -05:00
td * big . Int
currentBlock * types . Block
lastBlockHash common . Hash
currentGasLimit * big . Int
2014-02-14 16:56:09 -06:00
2014-12-18 06:12:54 -06:00
transState * state . StateDB
2015-03-13 08:37:54 -05:00
txState * state . ManagedState
2015-03-06 08:50:44 -06:00
2015-04-04 09:35:23 -05:00
cache * BlockCache
futureBlocks * BlockCache
2015-03-20 09:54:42 -05:00
2015-03-06 08:50:44 -06:00
quit chan struct { }
2015-04-30 10:50:23 -05:00
wg sync . WaitGroup
2014-12-18 06:12:54 -06:00
}
2014-02-14 16:56:09 -06:00
2015-03-16 05:27:38 -05:00
func NewChainManager ( blockDb , stateDb common . Database , mux * event . TypeMux ) * ChainManager {
2015-04-20 13:37:40 -05:00
bc := & ChainManager {
2015-04-28 10:13:51 -05:00
blockDb : blockDb ,
stateDb : stateDb ,
genesisBlock : GenesisBlock ( stateDb ) ,
eventMux : mux ,
quit : make ( chan struct { } ) ,
cache : NewBlockCache ( blockCacheLimit ) ,
2015-04-20 13:37:40 -05:00
}
2015-04-28 10:13:51 -05:00
bc . setLastState ( )
2015-04-20 05:58:17 -05:00
// 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 {
if block := bc . GetBlock ( hash ) ; block != nil {
glog . V ( logger . Error ) . Infof ( "Found bad hash. Reorganising chain to state %x\n" , block . ParentHash ( ) . Bytes ( ) [ : 4 ] )
block = bc . GetBlock ( block . ParentHash ( ) )
if block == nil {
glog . Fatal ( "Unable to complete. Parent block not found. Corrupted DB?" )
}
bc . SetHead ( block )
glog . V ( logger . Error ) . Infoln ( "Chain reorg was successfull. Resuming normal operation" )
}
}
2015-02-18 06:14:21 -06:00
bc . transState = bc . State ( ) . Copy ( )
2015-03-13 08:37:54 -05:00
// Take ownership of this particular state
bc . txState = state . ManageState ( bc . State ( ) . Copy ( ) )
2015-03-20 09:54:42 -05:00
2015-04-20 13:37:40 -05:00
bc . futureBlocks = NewBlockCache ( maxFutureBlocks )
2015-03-23 06:22:58 -05:00
bc . makeCache ( )
2015-03-20 09:54:42 -05:00
2015-03-06 08:50:44 -06:00
go bc . update ( )
2015-02-18 06:14:21 -06:00
return bc
}
2015-04-20 05:58:17 -05:00
func ( bc * ChainManager ) SetHead ( head * types . Block ) {
2015-04-20 05:29:02 -05:00
bc . mu . Lock ( )
defer bc . mu . Unlock ( )
2015-04-20 05:58:17 -05:00
for block := bc . currentBlock ; block != nil && block . Hash ( ) != head . Hash ( ) ; block = bc . GetBlock ( block . Header ( ) . ParentHash ) {
2015-04-20 05:29:02 -05:00
bc . removeBlock ( block )
}
2015-04-20 05:58:17 -05:00
bc . cache = NewBlockCache ( blockCacheLimit )
bc . currentBlock = head
2015-04-20 05:29:02 -05:00
bc . makeCache ( )
2015-04-20 05:58:17 -05:00
statedb := state . New ( head . Root ( ) , bc . stateDb )
2015-04-20 05:29:02 -05:00
bc . txState = state . ManageState ( statedb )
bc . transState = statedb . Copy ( )
2015-04-20 05:58:17 -05:00
bc . setTotalDifficulty ( head . Td )
bc . insert ( head )
2015-04-28 10:13:51 -05:00
bc . setLastState ( )
2015-04-20 05:29:02 -05:00
}
2014-12-18 06:12:54 -06:00
func ( self * ChainManager ) Td ( ) * big . Int {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2014-12-10 12:59:12 -06:00
2014-12-18 06:12:54 -06:00
return self . td
}
2015-04-24 10:45:51 -05:00
func ( self * ChainManager ) GasLimit ( ) * big . Int {
2015-04-22 17:11:11 -05:00
// return self.currentGasLimit
return self . currentBlock . GasLimit ( )
2015-04-24 10:45:51 -05:00
}
2015-03-16 17:48:18 -05:00
func ( self * ChainManager ) LastBlockHash ( ) common . Hash {
2014-12-18 06:17:24 -06:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
return self . lastBlockHash
}
2014-12-18 06:12:54 -06:00
func ( self * ChainManager ) CurrentBlock ( ) * types . Block {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
return self . currentBlock
2014-02-14 16:56:09 -06:00
}
2015-03-16 17:48:18 -05:00
func ( self * ChainManager ) Status ( ) ( td * big . Int , currentBlock common . Hash , genesisBlock common . Hash ) {
2014-12-18 06:22:59 -06:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2015-03-03 02:44:41 -06:00
return self . td , self . currentBlock . Hash ( ) , self . genesisBlock . Hash ( )
2014-12-14 12:20:37 -06:00
}
2014-11-18 09:58:22 -06:00
func ( self * ChainManager ) SetProcessor ( proc types . BlockProcessor ) {
self . processor = proc
}
2014-12-10 12:59:12 -06:00
func ( self * ChainManager ) State ( ) * state . StateDB {
2015-03-06 11:26:16 -06:00
return state . New ( self . CurrentBlock ( ) . Root ( ) , self . stateDb )
2014-12-10 12:59:12 -06:00
}
func ( self * ChainManager ) TransState ( ) * state . StateDB {
2015-02-17 09:12:55 -06:00
self . tsmu . RLock ( )
defer self . tsmu . RUnlock ( )
2014-12-10 12:59:12 -06:00
return self . transState
}
2015-03-13 08:37:54 -05:00
func ( self * ChainManager ) TxState ( ) * state . ManagedState {
2015-02-23 08:43:41 -06:00
self . tsmu . RLock ( )
defer self . tsmu . RUnlock ( )
return self . txState
}
2015-03-13 08:37:54 -05:00
func ( self * ChainManager ) setTxState ( statedb * state . StateDB ) {
2015-02-23 08:43:41 -06:00
self . tsmu . Lock ( )
defer self . tsmu . Unlock ( )
2015-03-13 08:37:54 -05:00
self . txState = state . ManageState ( statedb )
2015-02-23 08:43:41 -06:00
}
2015-02-17 09:12:55 -06:00
func ( self * ChainManager ) setTransState ( statedb * state . StateDB ) {
self . transState = statedb
}
2015-04-28 10:13:51 -05:00
func ( bc * ChainManager ) setLastState ( ) {
2015-03-06 11:26:16 -06:00
data , _ := bc . blockDb . Get ( [ ] byte ( "LastBlock" ) )
2014-11-17 05:12:55 -06:00
if len ( data ) != 0 {
2015-03-16 17:48:18 -05:00
block := bc . GetBlock ( common . BytesToHash ( data ) )
2015-03-13 12:29:42 -05:00
bc . currentBlock = block
2014-12-18 06:12:54 -06:00
bc . lastBlockHash = block . Hash ( )
2014-11-17 05:12:55 -06:00
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
2015-03-16 05:27:38 -05:00
bc . td = common . BigD ( bc . blockDb . LastKnownTD ( ) )
2014-11-17 05:12:55 -06:00
} else {
bc . Reset ( )
}
2015-04-28 10:13:51 -05:00
bc . currentGasLimit = CalcGasLimit ( bc . currentBlock )
2014-11-17 05:12:55 -06:00
2015-04-04 06:41:58 -05:00
if glog . V ( logger . Info ) {
glog . Infof ( "Last block (#%v) %x TD=%v\n" , bc . currentBlock . Number ( ) , bc . currentBlock . Hash ( ) , bc . td )
}
2014-02-14 16:56:09 -06:00
}
2015-03-23 06:22:58 -05:00
func ( bc * ChainManager ) makeCache ( ) {
if bc . cache == nil {
bc . cache = NewBlockCache ( blockCacheLimit )
}
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
ancestors := bc . GetAncestors ( bc . currentBlock , blockCacheLimit - 1 )
ancestors = append ( ancestors , bc . currentBlock )
for _ , block := range ancestors {
bc . cache . Push ( block )
}
}
2014-11-17 05:12:55 -06:00
// Block creation & chain handling
2015-03-16 17:48:18 -05:00
func ( bc * ChainManager ) NewBlock ( coinbase common . Address ) * types . Block {
2014-12-18 06:12:54 -06:00
bc . mu . RLock ( )
defer bc . mu . RUnlock ( )
2015-03-16 17:48:18 -05:00
var (
root common . Hash
parentHash common . Hash
)
2014-02-14 16:56:09 -06:00
2015-02-14 19:09:57 -06:00
if bc . currentBlock != nil {
2014-12-23 06:48:44 -06:00
root = bc . currentBlock . Header ( ) . Root
parentHash = bc . lastBlockHash
2014-02-14 16:56:09 -06:00
}
2014-04-23 08:53:53 -05:00
2014-12-23 06:48:44 -06:00
block := types . NewBlock (
parentHash ,
2014-02-14 16:56:09 -06:00
coinbase ,
2014-12-23 06:48:44 -06:00
root ,
2015-03-16 05:27:38 -05:00
common . BigPow ( 2 , 32 ) ,
2015-03-03 14:04:31 -06:00
0 ,
2015-04-05 11:57:03 -05:00
nil )
2015-02-09 09:20:34 -06:00
block . SetUncles ( nil )
block . SetTransactions ( nil )
block . SetReceipts ( nil )
2014-02-14 16:56:09 -06:00
2014-12-18 06:12:54 -06:00
parent := bc . currentBlock
2014-09-15 08:42:12 -05:00
if parent != nil {
2014-12-23 06:48:44 -06:00
header := block . Header ( )
2015-03-04 03:49:56 -06:00
header . Difficulty = CalcDifficulty ( block . Header ( ) , parent . Header ( ) )
2015-03-16 05:27:38 -05:00
header . Number = new ( big . Int ) . Add ( parent . Header ( ) . Number , common . Big1 )
2015-04-26 04:19:40 -05:00
header . GasLimit = CalcGasLimit ( parent )
2014-02-14 16:56:09 -06:00
}
return block
}
2014-10-20 04:53:11 -05:00
func ( bc * ChainManager ) Reset ( ) {
2014-12-18 06:12:54 -06:00
bc . mu . Lock ( )
defer bc . mu . Unlock ( )
2014-12-23 07:50:04 -06:00
for block := bc . currentBlock ; block != nil ; block = bc . GetBlock ( block . Header ( ) . ParentHash ) {
2015-03-13 12:29:42 -05:00
bc . removeBlock ( block )
2014-12-23 07:50:04 -06:00
}
2015-03-23 06:22:58 -05:00
if bc . cache == nil {
bc . cache = NewBlockCache ( blockCacheLimit )
}
2014-10-08 04:59:44 -05:00
// Prepare the genesis block
2014-12-05 09:26:39 -06:00
bc . write ( bc . genesisBlock )
bc . insert ( bc . genesisBlock )
2014-12-18 06:12:54 -06:00
bc . currentBlock = bc . genesisBlock
2015-03-23 06:22:58 -05:00
bc . makeCache ( )
2014-10-08 04:59:44 -05:00
2015-03-16 05:27:38 -05:00
bc . setTotalDifficulty ( common . Big ( "0" ) )
2014-10-08 04:59:44 -05:00
}
2015-03-13 12:29:42 -05:00
func ( bc * ChainManager ) removeBlock ( block * types . Block ) {
2015-03-16 17:48:18 -05:00
bc . blockDb . Delete ( append ( blockHashPre , block . Hash ( ) . Bytes ( ) ... ) )
2015-03-13 12:29:42 -05:00
}
2015-03-03 11:41:51 -06:00
func ( bc * ChainManager ) ResetWithGenesisBlock ( gb * types . Block ) {
bc . mu . Lock ( )
defer bc . mu . Unlock ( )
for block := bc . currentBlock ; block != nil ; block = bc . GetBlock ( block . Header ( ) . ParentHash ) {
2015-03-13 12:29:42 -05:00
bc . removeBlock ( block )
2015-03-03 11:41:51 -06:00
}
// Prepare the genesis block
2015-05-06 16:22:49 -05:00
gb . Td = gb . Difficulty ( )
2015-03-03 11:41:51 -06:00
bc . genesisBlock = gb
bc . write ( bc . genesisBlock )
bc . insert ( bc . genesisBlock )
bc . currentBlock = bc . genesisBlock
2015-03-23 06:22:58 -05:00
bc . makeCache ( )
2015-04-29 05:43:24 -05:00
bc . td = gb . Difficulty ( )
2015-03-03 11:41:51 -06:00
}
2015-03-18 07:36:48 -05:00
// Export writes the active chain to the given writer.
func ( self * ChainManager ) Export ( w io . Writer ) error {
2014-12-18 06:12:54 -06:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2015-04-04 06:41:58 -05:00
glog . V ( logger . Info ) . Infof ( "exporting %v blocks...\n" , self . currentBlock . Header ( ) . Number )
2015-04-04 16:04:19 -05:00
2015-04-13 03:13:52 -05:00
last := self . currentBlock . NumberU64 ( )
for nr := uint64 ( 0 ) ; nr <= last ; nr ++ {
2015-04-20 09:02:50 -05:00
block := self . GetBlockByNumber ( nr )
if block == nil {
return fmt . Errorf ( "export failed on #%d: not found" , nr )
}
if err := block . EncodeRLP ( w ) ; err != nil {
2015-03-18 07:36:48 -05:00
return err
}
2014-12-17 05:57:35 -06:00
}
2015-04-13 03:13:52 -05:00
2015-03-18 07:36:48 -05:00
return nil
2014-12-17 05:57:35 -06:00
}
2014-12-05 09:26:39 -06:00
func ( bc * ChainManager ) insert ( block * types . Block ) {
2015-03-13 12:29:42 -05:00
key := append ( blockNumPre , block . Number ( ) . Bytes ( ) ... )
2015-04-22 05:46:41 -05:00
bc . blockDb . Put ( key , block . Hash ( ) . Bytes ( ) )
bc . blockDb . Put ( [ ] byte ( "LastBlock" ) , block . Hash ( ) . Bytes ( ) )
bc . currentBlock = block
bc . lastBlockHash = block . Hash ( )
2014-12-05 09:26:39 -06:00
}
func ( bc * ChainManager ) write ( block * types . Block ) {
2015-03-18 07:36:48 -05:00
enc , _ := rlp . EncodeToBytes ( ( * types . StorageBlock ) ( block ) )
2015-03-16 17:48:18 -05:00
key := append ( blockHashPre , block . Hash ( ) . Bytes ( ) ... )
2015-03-18 07:36:48 -05:00
bc . blockDb . Put ( key , enc )
2015-04-29 05:43:24 -05:00
// Push block to cache
bc . cache . Push ( block )
2014-03-21 09:06:23 -05:00
}
2014-11-17 05:12:55 -06:00
// Accessors
2014-11-18 09:58:22 -06:00
func ( bc * ChainManager ) Genesis ( ) * types . Block {
2014-02-14 16:56:09 -06:00
return bc . genesisBlock
}
2014-11-17 05:12:55 -06:00
// Block fetching methods
2015-03-16 17:48:18 -05:00
func ( bc * ChainManager ) HasBlock ( hash common . Hash ) bool {
data , _ := bc . blockDb . Get ( append ( blockHashPre , hash [ : ] ... ) )
2014-11-17 05:12:55 -06:00
return len ( data ) != 0
}
2015-03-16 17:48:18 -05:00
func ( self * ChainManager ) GetBlockHashesFromHash ( hash common . Hash , max uint64 ) ( chain [ ] common . Hash ) {
2014-08-21 07:47:58 -05:00
block := self . GetBlock ( hash )
if block == nil {
return
}
// XXX Could be optimised by using a different database which only holds hashes (i.e., linked list)
for i := uint64 ( 0 ) ; i < max ; i ++ {
2015-04-18 17:08:57 -05:00
block = self . GetBlock ( block . ParentHash ( ) )
2015-01-28 14:12:26 -06:00
if block == nil {
break
}
2014-08-21 07:47:58 -05:00
chain = append ( chain , block . Hash ( ) )
2015-04-18 17:08:57 -05:00
if block . Number ( ) . Cmp ( common . Big0 ) <= 0 {
2014-08-21 07:47:58 -05:00
break
}
}
return
}
2015-03-16 17:48:18 -05:00
func ( self * ChainManager ) GetBlock ( hash common . Hash ) * types . Block {
2015-03-20 09:54:42 -05:00
if block := self . cache . Get ( hash ) ; block != nil {
return block
}
2015-03-16 17:48:18 -05:00
data , _ := self . blockDb . Get ( append ( blockHashPre , hash [ : ] ... ) )
2014-02-21 06:05:59 -06:00
if len ( data ) == 0 {
return nil
}
2015-03-18 07:36:48 -05:00
var block types . StorageBlock
2014-12-23 06:48:44 -06:00
if err := rlp . Decode ( bytes . NewReader ( data ) , & block ) ; err != nil {
2015-04-04 16:04:19 -05:00
glog . V ( logger . Error ) . Infof ( "invalid block RLP for hash %x: %v" , hash , err )
2014-12-23 06:48:44 -06:00
return nil
}
2015-03-18 07:36:48 -05:00
return ( * types . Block ) ( & block )
2014-02-14 16:56:09 -06:00
}
2015-03-13 12:29:42 -05:00
func ( self * ChainManager ) GetBlockByNumber ( num uint64 ) * types . Block {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2015-04-18 14:23:42 -05:00
return self . getBlockByNumber ( num )
}
// non blocking version
func ( self * ChainManager ) getBlockByNumber ( num uint64 ) * types . Block {
2015-03-13 12:29:42 -05:00
key , _ := self . blockDb . Get ( append ( blockNumPre , big . NewInt ( int64 ( num ) ) . Bytes ( ) ... ) )
if len ( key ) == 0 {
return nil
}
2015-03-16 17:48:18 -05:00
return self . GetBlock ( common . BytesToHash ( key ) )
2015-03-13 12:29:42 -05:00
}
2015-01-09 10:38:35 -06:00
func ( self * ChainManager ) GetUnclesInChain ( block * types . Block , length int ) ( uncles [ ] * types . Header ) {
for i := 0 ; block != nil && i < length ; i ++ {
uncles = append ( uncles , block . Uncles ( ) ... )
block = self . GetBlock ( block . ParentHash ( ) )
}
return
}
func ( self * ChainManager ) GetAncestors ( block * types . Block , length int ) ( blocks [ ] * types . Block ) {
for i := 0 ; i < length ; i ++ {
block = self . GetBlock ( block . ParentHash ( ) )
if block == nil {
break
}
blocks = append ( blocks , block )
}
return
}
2014-12-18 06:12:54 -06:00
func ( bc * ChainManager ) setTotalDifficulty ( td * big . Int ) {
2015-03-06 11:26:16 -06:00
bc . blockDb . Put ( [ ] byte ( "LTD" ) , td . Bytes ( ) )
2015-03-24 09:27:05 -05:00
bc . td = td
2014-11-17 05:12:55 -06:00
}
2014-09-26 06:32:54 -05:00
2014-11-18 09:58:22 -06:00
func ( self * ChainManager ) CalcTotalDiff ( block * types . Block ) ( * big . Int , error ) {
2014-12-23 06:48:44 -06:00
parent := self . GetBlock ( block . Header ( ) . ParentHash )
2014-11-17 05:12:55 -06:00
if parent == nil {
2014-12-23 06:48:44 -06:00
return nil , fmt . Errorf ( "Unable to calculate total diff without known parent %x" , block . Header ( ) . ParentHash )
2014-09-26 06:32:54 -05:00
}
2014-12-23 06:48:44 -06:00
parentTd := parent . Td
2014-09-26 06:32:54 -05:00
2014-11-17 05:12:55 -06:00
uncleDiff := new ( big . Int )
2014-12-23 06:48:44 -06:00
for _ , uncle := range block . Uncles ( ) {
2014-11-17 05:12:55 -06:00
uncleDiff = uncleDiff . Add ( uncleDiff , uncle . Difficulty )
}
2014-02-14 16:56:09 -06:00
2014-11-17 05:12:55 -06:00
td := new ( big . Int )
td = td . Add ( parentTd , uncleDiff )
2014-12-23 06:48:44 -06:00
td = td . Add ( td , block . Header ( ) . Difficulty )
2014-11-17 05:12:55 -06:00
return td , nil
2014-02-14 16:56:09 -06:00
}
2014-10-20 04:53:11 -05:00
func ( bc * ChainManager ) Stop ( ) {
2015-03-06 08:50:44 -06:00
close ( bc . quit )
2015-04-30 10:50:23 -05:00
bc . wg . Wait ( )
glog . V ( logger . Info ) . Infoln ( "Chain manager stopped" )
2015-03-06 08:50:44 -06:00
}
type queueEvent struct {
queue [ ] interface { }
canonicalCount int
sideCount int
splitCount int
2014-02-14 16:56:09 -06:00
}
2014-11-04 05:46:33 -06:00
2015-04-04 09:35:23 -05:00
func ( self * ChainManager ) procFutureBlocks ( ) {
blocks := make ( [ ] * types . Block , len ( self . futureBlocks . blocks ) )
2015-04-04 13:34:10 -05:00
self . futureBlocks . Each ( func ( i int , block * types . Block ) {
blocks [ i ] = block
} )
2015-04-04 09:35:23 -05:00
types . BlockBy ( types . Number ) . Sort ( blocks )
self . InsertChain ( blocks )
}
2015-04-29 07:00:24 -05:00
// InsertChain will attempt to insert the given chain in to the canonical chain or, otherwise, create a fork. It an error is returned
// it will return the index number of the failing block as well an error describing what went wrong (for possible errors see core/errors.go).
func ( self * ChainManager ) InsertChain ( chain types . Blocks ) ( int , error ) {
2015-04-30 10:50:23 -05:00
self . wg . Add ( 1 )
defer self . wg . Done ( )
2015-03-06 08:50:44 -06:00
// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
2015-04-04 16:04:19 -05:00
var (
queue = make ( [ ] interface { } , len ( chain ) )
queueEvent = queueEvent { queue : queue }
2015-05-01 09:00:30 -05:00
stats struct { queued , processed , ignored int }
2015-04-05 10:59:38 -05:00
tstart = time . Now ( )
2015-04-04 16:04:19 -05:00
)
2015-03-06 08:50:44 -06:00
for i , block := range chain {
2015-04-04 05:40:48 -05:00
if block == nil {
continue
}
2015-04-30 06:41:47 -05:00
// Setting block.Td regardless of error (known for example) prevents errors down the line
// in the protocol handler
block . Td = new ( big . Int ) . Set ( CalculateTD ( block , self . GetBlock ( block . ParentHash ( ) ) ) )
2015-02-23 08:43:41 -06:00
// Call in to the block processor and check for errors. It's likely that if one block fails
// all others will fail too (unless a known block is returned).
2015-04-20 05:01:20 -05:00
logs , err := self . processor . Process ( block )
2014-11-04 05:46:33 -06:00
if err != nil {
2014-12-02 04:37:33 -06:00
if IsKnownBlockErr ( err ) {
2015-05-01 09:00:30 -05:00
stats . ignored ++
2014-12-02 04:37:33 -06:00
continue
}
2014-11-04 05:46:33 -06:00
2015-04-04 09:35:23 -05:00
block . Td = new ( big . Int )
// Do not penelise on future block. We'll need a block queue eventually that will queue
// future block for future use
if err == BlockFutureErr {
2015-04-08 06:43:55 -05:00
block . SetQueued ( true )
2015-04-04 09:35:23 -05:00
self . futureBlocks . Push ( block )
2015-04-07 07:57:04 -05:00
stats . queued ++
2015-04-04 09:35:23 -05:00
continue
}
if IsParentErr ( err ) && self . futureBlocks . Has ( block . ParentHash ( ) ) {
2015-04-12 14:25:09 -05:00
block . SetQueued ( true )
2015-04-04 09:35:23 -05:00
self . futureBlocks . Push ( block )
2015-04-07 07:57:04 -05:00
stats . queued ++
2015-03-23 10:14:33 -05:00
continue
}
2014-12-23 06:48:44 -06:00
h := block . Header ( )
2015-04-04 16:04:19 -05:00
2015-04-20 05:58:17 -05:00
glog . V ( logger . Error ) . Infof ( "INVALID block #%v (%x)\n" , h . Number , h . Hash ( ) . Bytes ( ) )
2015-04-04 16:04:19 -05:00
glog . V ( logger . Error ) . Infoln ( err )
glog . V ( logger . Debug ) . Infoln ( block )
2015-04-29 07:00:24 -05:00
return i , err
2014-11-04 05:46:33 -06:00
}
2015-04-20 05:01:20 -05:00
2015-04-28 10:48:46 -05:00
self . mu . Lock ( )
{
cblock := self . currentBlock
// Write block to database. Eventually we'll have to improve on this and throw away blocks that are
// not in the canonical chain.
self . write ( block )
// Compare the TD of the last known block in the canonical chain to make sure it's greater.
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
if block . Td . Cmp ( self . td ) > 0 {
2015-04-29 05:43:24 -05:00
// Check for chain forks. If H(block.num - 1) != block.parent, we're on a fork and need to do some merging
if previous := self . getBlockByNumber ( block . NumberU64 ( ) - 1 ) ; previous . Hash ( ) != block . ParentHash ( ) {
2015-04-28 10:48:46 -05:00
chash := cblock . Hash ( )
hash := block . Hash ( )
if glog . V ( logger . Info ) {
glog . Infof ( "Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n" , block . Header ( ) . Number , hash [ : 4 ] , block . Td , cblock . Header ( ) . Number , chash [ : 4 ] , self . td )
}
2015-04-29 05:43:24 -05:00
2015-04-28 10:48:46 -05:00
// during split we merge two different chains and create the new canonical chain
2015-04-29 05:43:24 -05:00
self . merge ( previous , block )
2015-04-28 10:48:46 -05:00
queue [ i ] = ChainSplitEvent { block , logs }
queueEvent . splitCount ++
2014-12-18 06:12:54 -06:00
}
2015-04-28 10:48:46 -05:00
self . setTotalDifficulty ( block . Td )
self . insert ( block )
2014-12-05 09:26:39 -06:00
2015-04-28 10:48:46 -05:00
jsonlogger . LogJson ( & logger . EthChainNewHead {
BlockHash : block . Hash ( ) . Hex ( ) ,
BlockNumber : block . Number ( ) ,
ChainHeadHash : cblock . Hash ( ) . Hex ( ) ,
BlockPrevHash : block . ParentHash ( ) . Hex ( ) ,
} )
2015-03-06 08:50:44 -06:00
2015-04-28 10:48:46 -05:00
self . setTransState ( state . New ( block . Root ( ) , self . stateDb ) )
self . txState . SetState ( state . New ( block . Root ( ) , self . stateDb ) )
2015-03-13 11:47:11 -05:00
2015-04-28 10:48:46 -05:00
queue [ i ] = ChainEvent { block , logs }
queueEvent . canonicalCount ++
2015-04-04 05:40:11 -05:00
2015-04-28 10:48:46 -05:00
if glog . V ( logger . Debug ) {
2015-05-03 14:44:44 -05:00
glog . Infof ( "[%v] inserted block #%d (%d TXs %d UNCs) (%x...)\n" , time . Now ( ) . UnixNano ( ) , block . Number ( ) , len ( block . Transactions ( ) ) , len ( block . Uncles ( ) ) , block . Hash ( ) . Bytes ( ) [ 0 : 4 ] )
2015-04-28 10:48:46 -05:00
}
} else {
2015-04-29 05:43:24 -05:00
if glog . V ( logger . Detail ) {
2015-04-29 17:08:43 -05:00
glog . Infof ( "inserted forked block #%d (TD=%v) (%d TXs %d UNCs) (%x...)\n" , block . Number ( ) , block . Difficulty ( ) , len ( block . Transactions ( ) ) , len ( block . Uncles ( ) ) , block . Hash ( ) . Bytes ( ) [ 0 : 4 ] )
2015-04-29 05:43:24 -05:00
}
2015-04-28 10:48:46 -05:00
queue [ i ] = ChainSideEvent { block , logs }
queueEvent . sideCount ++
2015-02-09 09:20:34 -06:00
}
2015-04-29 05:43:24 -05:00
self . futureBlocks . Delete ( block . Hash ( ) )
2014-12-04 08:35:21 -06:00
}
2015-04-28 10:48:46 -05:00
self . mu . Unlock ( )
2015-02-19 15:33:22 -06:00
2015-04-04 16:04:19 -05:00
stats . processed ++
2014-11-04 05:46:33 -06:00
}
2015-05-03 07:09:50 -05:00
if ( stats . queued > 0 || stats . processed > 0 || stats . ignored > 0 ) && bool ( glog . V ( logger . Info ) ) {
2015-04-05 10:59:38 -05:00
tend := time . Since ( tstart )
2015-04-04 05:40:11 -05:00
start , end := chain [ 0 ] , chain [ len ( chain ) - 1 ]
2015-05-01 09:00:30 -05:00
glog . Infof ( "imported %d block(s) (%d queued %d ignored) in %v. #%v [%x / %x]\n" , stats . processed , stats . queued , stats . ignored , tend , end . Number ( ) , start . Hash ( ) . Bytes ( ) [ : 4 ] , end . Hash ( ) . Bytes ( ) [ : 4 ] )
2015-04-04 05:40:11 -05:00
}
2015-03-06 08:50:44 -06:00
go self . eventMux . Post ( queueEvent )
2015-04-29 07:00:24 -05:00
return 0 , nil
2014-11-17 05:12:55 -06:00
}
2015-01-02 05:07:54 -06:00
2015-04-29 05:43:24 -05:00
// diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
2015-04-13 17:18:38 -05:00
// to be part of the new canonical chain.
2015-04-29 05:43:24 -05:00
func ( self * ChainManager ) diff ( oldBlock , newBlock * types . Block ) types . Blocks {
2015-04-13 17:18:38 -05:00
glog . V ( logger . Debug ) . Infof ( "Applying diff to %x & %x\n" , oldBlock . Hash ( ) . Bytes ( ) [ : 4 ] , newBlock . Hash ( ) . Bytes ( ) [ : 4 ] )
2015-04-29 05:43:24 -05:00
var newChain types . Blocks
// first find common number
for newBlock = newBlock ; newBlock . NumberU64 ( ) != oldBlock . NumberU64 ( ) ; newBlock = self . GetBlock ( newBlock . ParentHash ( ) ) {
newChain = append ( newChain , newBlock )
}
glog . V ( logger . Debug ) . Infoln ( "Found common number" , newBlock . Number ( ) )
2015-04-13 17:18:38 -05:00
for {
if oldBlock . Hash ( ) == newBlock . Hash ( ) {
break
}
newChain = append ( newChain , newBlock )
2015-04-29 05:43:24 -05:00
oldBlock , newBlock = self . GetBlock ( oldBlock . ParentHash ( ) ) , self . GetBlock ( newBlock . ParentHash ( ) )
2015-04-13 17:18:38 -05:00
}
2015-04-29 05:43:24 -05:00
return newChain
}
// merge merges two different chain to the new canonical chain
func ( self * ChainManager ) merge ( oldBlock , newBlock * types . Block ) {
newChain := self . diff ( oldBlock , newBlock )
2015-04-13 17:18:38 -05:00
// insert blocks
for _ , block := range newChain {
self . insert ( block )
}
}
2015-03-06 08:50:44 -06:00
func ( self * ChainManager ) update ( ) {
events := self . eventMux . Subscribe ( queueEvent { } )
2015-05-01 09:30:02 -05:00
futureTimer := time . Tick ( 5 * time . Second )
2015-03-06 08:50:44 -06:00
out :
for {
select {
case ev := <- events . Chan ( ) :
switch ev := ev . ( type ) {
case queueEvent :
for i , event := range ev . queue {
switch event := event . ( type ) {
case ChainEvent :
// We need some control over the mining operation. Acquiring locks and waiting for the miner to create new block takes too long
// and in most cases isn't even necessary.
2015-03-23 16:59:19 -05:00
if i + 1 == ev . canonicalCount {
2015-04-26 04:19:40 -05:00
self . currentGasLimit = CalcGasLimit ( event . Block )
2015-03-06 08:50:44 -06:00
self . eventMux . Post ( ChainHeadEvent { event . Block } )
}
case ChainSplitEvent :
// On chain splits we need to reset the transaction state. We can't be sure whether the actual
// state of the accounts are still valid.
if i == ev . splitCount {
2015-03-06 11:26:16 -06:00
self . setTxState ( state . New ( event . Block . Root ( ) , self . stateDb ) )
2015-03-06 08:50:44 -06:00
}
}
self . eventMux . Post ( event )
}
}
2015-05-01 09:30:02 -05:00
case <- futureTimer :
2015-04-04 09:35:23 -05:00
self . procFutureBlocks ( )
2015-03-06 08:50:44 -06:00
case <- self . quit :
break out
}
}
}