@ -85,12 +85,14 @@ type ChainManager struct {
lastBlockHash [ ] byte
lastBlockHash [ ] byte
transState * state . StateDB
transState * state . StateDB
txState * state . StateDB
}
}
func NewChainManager ( db ethutil . Database , mux * event . TypeMux ) * ChainManager {
func NewChainManager ( db ethutil . Database , mux * event . TypeMux ) * ChainManager {
bc := & ChainManager { db : db , genesisBlock : GenesisBlock ( db ) , eventMux : mux }
bc := & ChainManager { db : db , genesisBlock : GenesisBlock ( db ) , eventMux : mux }
bc . setLastBlock ( )
bc . setLastBlock ( )
bc . transState = bc . State ( ) . Copy ( )
bc . transState = bc . State ( ) . Copy ( )
bc . txState = bc . State ( ) . Copy ( )
return bc
return bc
}
}
@ -138,6 +140,19 @@ func (self *ChainManager) TransState() *state.StateDB {
return self . transState
return self . transState
}
}
func ( self * ChainManager ) TxState ( ) * state . StateDB {
self . tsmu . RLock ( )
defer self . tsmu . RUnlock ( )
return self . txState
}
func ( self * ChainManager ) setTxState ( state * state . StateDB ) {
self . tsmu . Lock ( )
defer self . tsmu . Unlock ( )
self . txState = state
}
func ( self * ChainManager ) setTransState ( statedb * state . StateDB ) {
func ( self * ChainManager ) setTransState ( statedb * state . StateDB ) {
self . transState = statedb
self . transState = statedb
}
}
@ -268,7 +283,6 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
break
break
}
}
}
}
fmt . Printf ( "get hash %x (%d)\n" , hash , len ( chain ) )
return
return
}
}
@ -363,6 +377,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
defer self . tsmu . Unlock ( )
defer self . tsmu . Unlock ( )
for _ , block := range chain {
for _ , block := range chain {
// 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).
td , err := self . processor . Process ( block )
td , err := self . processor . Process ( block )
if err != nil {
if err != nil {
if IsKnownBlockErr ( err ) {
if IsKnownBlockErr ( err ) {
@ -377,11 +393,15 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
}
block . Td = td
block . Td = td
var chain , split bool
var canonical , split bool
self . mu . Lock ( )
self . mu . Lock ( )
{
{
// 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 )
self . write ( block )
cblock := self . currentBlock
cblock := self . currentBlock
// 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 td . Cmp ( self . td ) > 0 {
if td . Cmp ( self . td ) > 0 {
if block . Header ( ) . Number . Cmp ( new ( big . Int ) . Add ( cblock . Header ( ) . Number , ethutil . Big1 ) ) < 0 {
if block . Header ( ) . Number . Cmp ( new ( big . Int ) . Add ( cblock . Header ( ) . Number , ethutil . Big1 ) ) < 0 {
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 )
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 )
@ -391,17 +411,18 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self . setTotalDifficulty ( td )
self . setTotalDifficulty ( td )
self . insert ( block )
self . insert ( block )
chain = true
canonical = true
}
}
}
}
self . mu . Unlock ( )
self . mu . Unlock ( )
if chain {
if canonical {
self . setTransState ( state . New ( block . Root ( ) , self . db ) )
self . eventMux . Post ( ChainEvent { block , td } )
self . eventMux . Post ( ChainEvent { block , td } )
}
}
if split {
if split {
self . setTrans State ( state . New ( block . Root ( ) , self . db ) )
self . setTx State ( state . New ( block . Root ( ) , self . db ) )
self . eventMux . Post ( ChainSplitEvent { block } )
self . eventMux . Post ( ChainSplitEvent { block } )
}
}
}
}