2014-12-04 11:28:02 +02:00
package core
2014-02-15 00:56:09 +02:00
import (
2014-12-23 14:48:44 +02:00
"bytes"
2014-09-24 12:39:17 +03:00
"fmt"
2014-07-30 01:31:15 +03:00
"math/big"
2014-12-18 14:12:54 +02:00
"sync"
2014-07-30 01:31:15 +03:00
2014-12-04 11:28:02 +02:00
"github.com/ethereum/go-ethereum/core/types"
2014-10-23 16:01:27 +03:00
"github.com/ethereum/go-ethereum/ethutil"
2014-12-03 15:05:19 +02:00
"github.com/ethereum/go-ethereum/event"
2014-10-31 13:56:05 +02:00
"github.com/ethereum/go-ethereum/logger"
2014-12-23 14:48:44 +02:00
"github.com/ethereum/go-ethereum/rlp"
2014-12-10 20:59:12 +02:00
"github.com/ethereum/go-ethereum/state"
2014-02-15 00:56:09 +02:00
)
2014-10-31 13:56:05 +02:00
var chainlogger = logger . NewLogger ( "CHAIN" )
2014-06-23 14:54:10 +03:00
2015-02-09 17:20:34 +02:00
type ChainEvent struct {
Block * types . Block
Td * big . Int
}
2015-01-02 13:07:54 +02:00
type StateQuery interface {
GetAccount ( addr [ ] byte ) * state . StateObject
}
2014-11-18 17:58:22 +02:00
func CalcDifficulty ( block , parent * types . Block ) * big . Int {
2014-11-17 13:12:55 +02:00
diff := new ( big . Int )
2015-01-18 16:45:54 +02:00
adjust := new ( big . Int ) . Rsh ( parent . Difficulty ( ) , 10 )
if block . Time ( ) >= parent . Time ( ) + 8 {
diff . Sub ( parent . Difficulty ( ) , adjust )
2014-11-17 13:12:55 +02:00
} else {
2015-01-18 16:45:54 +02:00
diff . Add ( parent . Difficulty ( ) , adjust )
2014-11-17 13:12:55 +02:00
}
return diff
}
2015-01-09 23:42:36 +02:00
func CalculateTD ( block , parent * types . Block ) * big . Int {
uncleDiff := new ( big . Int )
for _ , uncle := range block . Uncles ( ) {
uncleDiff = uncleDiff . Add ( uncleDiff , uncle . Difficulty )
}
// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
td := new ( big . Int )
td = td . Add ( parent . Td , uncleDiff )
td = td . Add ( td , block . Header ( ) . Difficulty )
return td
}
2014-12-23 14:48:44 +02:00
func CalcGasLimit ( parent , block * types . Block ) * big . Int {
if block . Number ( ) . Cmp ( big . NewInt ( 0 ) ) == 0 {
return ethutil . BigPow ( 10 , 6 )
}
// ((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 ) )
min := big . NewInt ( 125000 )
return ethutil . BigMax ( min , result )
}
2014-10-20 12:53:11 +03:00
type ChainManager struct {
2014-11-18 17:58:22 +02:00
//eth EthManager
2015-01-07 14:17:48 +02:00
db ethutil . Database
2014-11-18 17:58:22 +02:00
processor types . BlockProcessor
2014-12-03 15:05:19 +02:00
eventMux * event . TypeMux
2014-11-18 17:58:22 +02:00
genesisBlock * types . Block
2014-02-15 00:56:09 +02:00
// Last known total difficulty
2015-02-16 13:03:27 +02:00
mu sync . RWMutex
2015-02-17 17:12:55 +02:00
tsmu sync . RWMutex
2015-02-16 13:03:27 +02:00
td * big . Int
currentBlock * types . Block
lastBlockHash [ ] byte
2014-02-15 00:56:09 +02:00
2014-12-18 14:12:54 +02:00
transState * state . StateDB
}
2014-02-15 00:56:09 +02:00
2015-02-18 14:14:21 +02:00
func NewChainManager ( db ethutil . Database , mux * event . TypeMux ) * ChainManager {
bc := & ChainManager { db : db , genesisBlock : GenesisBlock ( db ) , eventMux : mux }
bc . setLastBlock ( )
bc . transState = bc . State ( ) . Copy ( )
return bc
}
2014-12-18 14:12:54 +02:00
func ( self * ChainManager ) Td ( ) * big . Int {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2014-12-10 20:59:12 +02:00
2014-12-18 14:12:54 +02:00
return self . td
}
2014-12-18 14:17:24 +02:00
func ( self * ChainManager ) LastBlockHash ( ) [ ] byte {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
return self . lastBlockHash
}
2014-12-18 14:12:54 +02:00
func ( self * ChainManager ) CurrentBlock ( ) * types . Block {
self . mu . RLock ( )
defer self . mu . RUnlock ( )
return self . currentBlock
2014-02-15 00:56:09 +02:00
}
2014-12-14 20:20:37 +02:00
func ( self * ChainManager ) Status ( ) ( td * big . Int , currentBlock [ ] byte , genesisBlock [ ] byte ) {
2014-12-18 14:22:59 +02:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
return self . td , self . currentBlock . Hash ( ) , self . Genesis ( ) . Hash ( )
2014-12-14 20:20:37 +02:00
}
2014-11-18 17:58:22 +02:00
func ( self * ChainManager ) SetProcessor ( proc types . BlockProcessor ) {
self . processor = proc
}
2014-12-10 20:59:12 +02:00
func ( self * ChainManager ) State ( ) * state . StateDB {
2015-01-07 14:17:48 +02:00
return state . New ( self . CurrentBlock ( ) . Root ( ) , self . db )
2014-12-10 20:59:12 +02:00
}
func ( self * ChainManager ) TransState ( ) * state . StateDB {
2015-02-17 17:12:55 +02:00
self . tsmu . RLock ( )
defer self . tsmu . RUnlock ( )
2014-12-10 20:59:12 +02:00
return self . transState
}
2015-02-17 17:12:55 +02:00
func ( self * ChainManager ) setTransState ( statedb * state . StateDB ) {
self . transState = statedb
}
2014-11-17 13:12:55 +02:00
func ( bc * ChainManager ) setLastBlock ( ) {
2015-01-07 14:17:48 +02:00
data , _ := bc . db . Get ( [ ] byte ( "LastBlock" ) )
2014-11-17 13:12:55 +02:00
if len ( data ) != 0 {
2014-12-23 14:48:44 +02:00
var block types . Block
rlp . Decode ( bytes . NewReader ( data ) , & block )
bc . currentBlock = & block
2014-12-18 14:12:54 +02:00
bc . lastBlockHash = block . Hash ( )
2014-11-17 13:12:55 +02:00
// Set the last know difficulty (might be 0x0 as initial value, Genesis)
2015-01-07 14:17:48 +02:00
bc . td = ethutil . BigD ( bc . db . LastKnownTD ( ) )
2014-11-17 13:12:55 +02:00
} else {
bc . Reset ( )
}
2015-02-16 13:03:27 +02:00
chainlogger . Infof ( "Last block (#%v) %x TD=%v\n" , bc . currentBlock . Number ( ) , bc . currentBlock . Hash ( ) , bc . td )
2014-02-15 00:56:09 +02:00
}
2014-11-17 13:12:55 +02:00
// Block creation & chain handling
2014-11-18 17:58:22 +02:00
func ( bc * ChainManager ) NewBlock ( coinbase [ ] byte ) * types . Block {
2014-12-18 14:12:54 +02:00
bc . mu . RLock ( )
defer bc . mu . RUnlock ( )
2014-12-23 14:48:44 +02:00
var root [ ] byte
parentHash := ZeroHash256
2014-02-15 00:56:09 +02:00
2015-02-15 03:09:57 +02:00
if bc . currentBlock != nil {
2014-12-23 14:48:44 +02:00
root = bc . currentBlock . Header ( ) . Root
parentHash = bc . lastBlockHash
2014-02-15 00:56:09 +02:00
}
2014-04-23 16:53:53 +03:00
2014-12-23 14:48:44 +02:00
block := types . NewBlock (
parentHash ,
2014-02-15 00:56:09 +02:00
coinbase ,
2014-12-23 14:48:44 +02:00
root ,
2014-02-15 00:56:09 +02:00
ethutil . BigPow ( 2 , 32 ) ,
nil ,
2014-05-22 18:35:26 +03:00
"" )
2015-02-09 17:20:34 +02:00
block . SetUncles ( nil )
block . SetTransactions ( nil )
block . SetReceipts ( nil )
2014-02-15 00:56:09 +02:00
2014-12-18 14:12:54 +02:00
parent := bc . currentBlock
2014-09-15 16:42:12 +03:00
if parent != nil {
2014-12-23 14:48:44 +02:00
header := block . Header ( )
header . Difficulty = CalcDifficulty ( block , parent )
header . Number = new ( big . Int ) . Add ( parent . Header ( ) . Number , ethutil . Big1 )
header . GasLimit = CalcGasLimit ( parent , block )
2014-09-15 16:42:12 +03:00
2014-02-15 00:56:09 +02:00
}
return block
}
2014-10-20 12:53:11 +03:00
func ( bc * ChainManager ) Reset ( ) {
2014-12-18 14:12:54 +02:00
bc . mu . Lock ( )
defer bc . mu . Unlock ( )
2014-12-23 15:50:04 +02:00
for block := bc . currentBlock ; block != nil ; block = bc . GetBlock ( block . Header ( ) . ParentHash ) {
2015-01-07 14:17:48 +02:00
bc . db . Delete ( block . Hash ( ) )
2014-12-23 15:50:04 +02:00
}
2014-10-08 12:59:44 +03:00
// Prepare the genesis block
2014-12-05 17:26:39 +02:00
bc . write ( bc . genesisBlock )
bc . insert ( bc . genesisBlock )
2014-12-18 14:12:54 +02:00
bc . currentBlock = bc . genesisBlock
2014-10-08 12:59:44 +03:00
2014-12-18 14:12:54 +02:00
bc . setTotalDifficulty ( ethutil . Big ( "0" ) )
2014-10-08 12:59:44 +03:00
}
2014-12-17 13:57:35 +02:00
func ( self * ChainManager ) Export ( ) [ ] byte {
2014-12-18 14:12:54 +02:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2014-12-23 14:48:44 +02:00
chainlogger . Infof ( "exporting %v blocks...\n" , self . currentBlock . Header ( ) . Number )
2014-12-17 13:57:35 +02:00
2014-12-23 14:48:44 +02:00
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
2014-12-17 13:57:35 +02:00
}
2014-12-18 14:12:54 +02:00
2014-12-17 13:57:35 +02:00
return ethutil . Encode ( blocks )
}
2014-12-05 17:26:39 +02:00
func ( bc * ChainManager ) insert ( block * types . Block ) {
2014-12-23 14:48:44 +02:00
encodedBlock := ethutil . Encode ( block )
2015-01-07 14:17:48 +02:00
bc . db . Put ( [ ] byte ( "LastBlock" ) , encodedBlock )
2014-12-18 14:12:54 +02:00
bc . currentBlock = block
bc . lastBlockHash = block . Hash ( )
2014-12-05 17:26:39 +02:00
}
func ( bc * ChainManager ) write ( block * types . Block ) {
2015-01-08 17:37:06 +02:00
encodedBlock := ethutil . Encode ( block . RlpDataForStorage ( ) )
2015-01-07 14:17:48 +02:00
bc . db . Put ( block . Hash ( ) , encodedBlock )
2014-03-21 16:06:23 +02:00
}
2014-11-17 13:12:55 +02:00
// Accessors
2014-11-18 17:58:22 +02:00
func ( bc * ChainManager ) Genesis ( ) * types . Block {
2014-02-15 00:56:09 +02:00
return bc . genesisBlock
}
2014-11-17 13:12:55 +02:00
// Block fetching methods
func ( bc * ChainManager ) HasBlock ( hash [ ] byte ) bool {
2015-01-07 14:17:48 +02:00
data , _ := bc . db . Get ( hash )
2014-11-17 13:12:55 +02:00
return len ( data ) != 0
}
2014-12-14 20:20:37 +02:00
func ( self * ChainManager ) GetBlockHashesFromHash ( hash [ ] byte , max uint64 ) ( chain [ ] [ ] byte ) {
2014-08-21 15:47:58 +03: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-01-28 22:12:26 +02:00
parentHash := block . Header ( ) . ParentHash
block = self . GetBlock ( parentHash )
if block == nil {
chainlogger . Infof ( "GetBlockHashesFromHash Parent UNKNOWN %x\n" , parentHash )
break
}
2014-08-21 15:47:58 +03:00
chain = append ( chain , block . Hash ( ) )
2014-12-23 14:48:44 +02:00
if block . Header ( ) . Number . Cmp ( ethutil . Big0 ) <= 0 {
2014-08-21 15:47:58 +03:00
break
}
}
return
}
2014-11-18 17:58:22 +02:00
func ( self * ChainManager ) GetBlock ( hash [ ] byte ) * types . Block {
2015-01-07 14:17:48 +02:00
data , _ := self . db . Get ( hash )
2014-02-21 14:05:59 +02:00
if len ( data ) == 0 {
return nil
}
2014-12-23 14:48:44 +02:00
var block types . Block
if err := rlp . Decode ( bytes . NewReader ( data ) , & block ) ; err != nil {
fmt . Println ( err )
return nil
}
2014-02-15 00:56:09 +02:00
2014-12-23 14:48:44 +02:00
return & block
2014-02-15 00:56:09 +02:00
}
2015-01-09 18:38:35 +02: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-11-18 17:58:22 +02:00
func ( self * ChainManager ) GetBlockByNumber ( num uint64 ) * types . Block {
2014-12-18 14:12:54 +02:00
self . mu . RLock ( )
defer self . mu . RUnlock ( )
2015-01-03 18:18:43 +02:00
var block * types . Block
if num <= self . currentBlock . Number ( ) . Uint64 ( ) {
block = self . currentBlock
for ; block != nil ; block = self . GetBlock ( block . Header ( ) . ParentHash ) {
if block . Header ( ) . Number . Uint64 ( ) == num {
break
}
2014-09-19 14:19:19 +03:00
}
2014-08-06 10:53:00 +03:00
}
return block
}
2014-12-18 14:12:54 +02:00
func ( bc * ChainManager ) setTotalDifficulty ( td * big . Int ) {
2015-01-07 14:17:48 +02:00
bc . db . Put ( [ ] byte ( "LTD" ) , td . Bytes ( ) )
2014-12-18 14:12:54 +02:00
bc . td = td
2014-11-17 13:12:55 +02:00
}
2014-09-26 14:32:54 +03:00
2014-11-18 17:58:22 +02:00
func ( self * ChainManager ) CalcTotalDiff ( block * types . Block ) ( * big . Int , error ) {
2014-12-23 14:48:44 +02:00
parent := self . GetBlock ( block . Header ( ) . ParentHash )
2014-11-17 13:12:55 +02:00
if parent == nil {
2014-12-23 14:48:44 +02:00
return nil , fmt . Errorf ( "Unable to calculate total diff without known parent %x" , block . Header ( ) . ParentHash )
2014-09-26 14:32:54 +03:00
}
2014-12-23 14:48:44 +02:00
parentTd := parent . Td
2014-09-26 14:32:54 +03:00
2014-11-17 13:12:55 +02:00
uncleDiff := new ( big . Int )
2014-12-23 14:48:44 +02:00
for _ , uncle := range block . Uncles ( ) {
2014-11-17 13:12:55 +02:00
uncleDiff = uncleDiff . Add ( uncleDiff , uncle . Difficulty )
}
2014-02-15 00:56:09 +02:00
2014-11-17 13:12:55 +02:00
td := new ( big . Int )
td = td . Add ( parentTd , uncleDiff )
2014-12-23 14:48:44 +02:00
td = td . Add ( td , block . Header ( ) . Difficulty )
2014-11-17 13:12:55 +02:00
return td , nil
2014-02-15 00:56:09 +02:00
}
2014-10-20 12:53:11 +03:00
func ( bc * ChainManager ) Stop ( ) {
2014-02-15 00:56:09 +02:00
if bc . CurrentBlock != nil {
2014-06-23 14:54:10 +03:00
chainlogger . Infoln ( "Stopped" )
2014-02-15 00:56:09 +02:00
}
}
2014-11-04 13:46:33 +02:00
2014-12-03 15:05:19 +02:00
func ( self * ChainManager ) InsertChain ( chain types . Blocks ) error {
2015-02-19 23:33:22 +02:00
self . tsmu . Lock ( )
defer self . tsmu . Unlock ( )
2014-12-01 21:18:09 +02:00
for _ , block := range chain {
2015-02-05 01:05:47 +02:00
td , err := self . processor . Process ( block )
2014-11-04 13:46:33 +02:00
if err != nil {
2014-12-02 12:37:33 +02:00
if IsKnownBlockErr ( err ) {
continue
}
2014-11-04 13:46:33 +02:00
2014-12-23 14:48:44 +02:00
h := block . Header ( )
chainlogger . Infof ( "block #%v process failed (%x)\n" , h . Number , h . Hash ( ) [ : 4 ] )
2014-12-02 18:22:33 +02:00
chainlogger . Infoln ( block )
chainlogger . Infoln ( err )
2014-12-01 21:18:09 +02:00
return err
2014-11-04 13:46:33 +02:00
}
2015-01-02 12:16:42 +02:00
block . Td = td
2014-11-04 13:46:33 +02:00
2015-02-19 23:33:22 +02:00
var chain , split bool
2014-12-18 14:12:54 +02:00
self . mu . Lock ( )
{
self . write ( block )
2014-12-23 14:48:44 +02:00
cblock := self . currentBlock
2014-12-18 14:12:54 +02:00
if td . Cmp ( self . td ) > 0 {
2014-12-23 14:48:44 +02:00
if block . Header ( ) . Number . Cmp ( new ( big . Int ) . Add ( cblock . Header ( ) . Number , ethutil . Big1 ) ) < 0 {
2015-01-09 23:42:36 +02:00
chainlogger . Infof ( "Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n" , block . Header ( ) . Number , block . Hash ( ) [ : 4 ] , td , cblock . Header ( ) . Number , cblock . Hash ( ) [ : 4 ] , self . td )
2015-02-19 23:33:22 +02:00
split = true
2014-12-18 14:12:54 +02:00
}
self . setTotalDifficulty ( td )
self . insert ( block )
2014-12-05 17:26:39 +02:00
2015-02-19 23:33:22 +02:00
chain = true
2015-02-09 17:20:34 +02:00
}
2014-12-04 16:35:21 +02:00
}
2014-12-18 14:12:54 +02:00
self . mu . Unlock ( )
2015-02-19 23:33:22 +02:00
if chain {
//self.setTransState(state.New(block.Root(), self.db))
self . eventMux . Post ( ChainEvent { block , td } )
}
if split {
self . setTransState ( state . New ( block . Root ( ) , self . db ) )
self . eventMux . Post ( ChainSplitEvent { block } )
}
2014-11-04 13:46:33 +02:00
}
2014-12-01 21:18:09 +02:00
return nil
2014-11-17 13:12:55 +02:00
}
2015-01-02 13:07:54 +02:00
// Satisfy state query interface
func ( self * ChainManager ) GetAccount ( addr [ ] byte ) * state . StateObject {
return self . State ( ) . GetAccount ( addr )
}
2015-02-19 23:33:22 +02:00
func ( self * ChainManager ) TransMut ( ) * sync . RWMutex {
return & self . tsmu
}