@@ -74,9 +74,8 @@ type ChainManager struct {
74
74
eventMux * event.TypeMux
75
75
genesisBlock * types.Block
76
76
// Last known total difficulty
77
- mu sync.RWMutex
78
- tsmu sync.RWMutex
79
- insertMu sync.Mutex
77
+ mu sync.RWMutex
78
+ tsmu sync.RWMutex
80
79
81
80
td * big.Int
82
81
currentBlock * types.Block
@@ -321,6 +320,7 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
321
320
bc .insert (bc .genesisBlock )
322
321
bc .currentBlock = bc .genesisBlock
323
322
bc .makeCache ()
323
+ bc .td = gb .Difficulty ()
324
324
}
325
325
326
326
// Export writes the active chain to the given writer.
@@ -348,8 +348,6 @@ func (self *ChainManager) Export(w io.Writer) error {
348
348
func (bc * ChainManager ) insert (block * types.Block ) {
349
349
key := append (blockNumPre , block .Number ().Bytes ()... )
350
350
bc .blockDb .Put (key , block .Hash ().Bytes ())
351
- // Push block to cache
352
- bc .cache .Push (block )
353
351
354
352
bc .blockDb .Put ([]byte ("LastBlock" ), block .Hash ().Bytes ())
355
353
bc .currentBlock = block
@@ -360,6 +358,8 @@ func (bc *ChainManager) write(block *types.Block) {
360
358
enc , _ := rlp .EncodeToBytes ((* types .StorageBlock )(block ))
361
359
key := append (blockHashPre , block .Hash ().Bytes ()... )
362
360
bc .blockDb .Put (key , enc )
361
+ // Push block to cache
362
+ bc .cache .Push (block )
363
363
}
364
364
365
365
// Accessors
@@ -498,9 +498,6 @@ func (self *ChainManager) procFutureBlocks() {
498
498
}
499
499
500
500
func (self * ChainManager ) InsertChain (chain types.Blocks ) error {
501
- self .insertMu .Lock ()
502
- defer self .insertMu .Unlock ()
503
-
504
501
// A queued approach to delivering events. This is generally faster than direct delivery and requires much less mutex acquiring.
505
502
var (
506
503
queue = make ([]interface {}, len (chain ))
@@ -557,16 +554,17 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
557
554
// Compare the TD of the last known block in the canonical chain to make sure it's greater.
558
555
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
559
556
if block .Td .Cmp (self .td ) > 0 {
560
- //if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, common.Big1)) < 0 {
561
- if block .Number (). Cmp ( cblock . Number ()) <= 0 {
557
+ // Check for chain forks. If H(block.num - 1) != block.parent, we're on a fork and need to do some merging
558
+ if previous := self . getBlockByNumber ( block .NumberU64 () - 1 ); previous . Hash () != block . ParentHash () {
562
559
chash := cblock .Hash ()
563
560
hash := block .Hash ()
564
561
565
562
if glog .V (logger .Info ) {
566
563
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 )
567
564
}
565
+
568
566
// during split we merge two different chains and create the new canonical chain
569
- self .merge (self . getBlockByNumber ( block . NumberU64 ()) , block )
567
+ self .merge (previous , block )
570
568
571
569
queue [i ] = ChainSplitEvent {block , logs }
572
570
queueEvent .splitCount ++
@@ -592,16 +590,19 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
592
590
glog .Infof ("inserted block #%d (%d TXs %d UNCs) (%x...)\n " , block .Number (), len (block .Transactions ()), len (block .Uncles ()), block .Hash ().Bytes ()[0 :4 ])
593
591
}
594
592
} else {
593
+ if glog .V (logger .Detail ) {
594
+ glog .Infof ("inserted forked block #%d (%d TXs %d UNCs) (%x...)\n " , block .Number (), len (block .Transactions ()), len (block .Uncles ()), block .Hash ().Bytes ()[0 :4 ])
595
+ }
596
+
595
597
queue [i ] = ChainSideEvent {block , logs }
596
598
queueEvent .sideCount ++
597
599
}
600
+ self .futureBlocks .Delete (block .Hash ())
598
601
}
599
602
self .mu .Unlock ()
600
603
601
604
stats .processed ++
602
605
603
- self .futureBlocks .Delete (block .Hash ())
604
-
605
606
}
606
607
607
608
if (stats .queued > 0 || stats .processed > 0 ) && bool (glog .V (logger .Info )) {
@@ -615,33 +616,38 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
615
616
return nil
616
617
}
617
618
618
- // merge takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
619
+ // diff takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
619
620
// to be part of the new canonical chain.
620
- func (self * ChainManager ) merge (oldBlock , newBlock * types.Block ) {
621
+ func (self * ChainManager ) diff (oldBlock , newBlock * types.Block ) types. Blocks {
621
622
glog .V (logger .Debug ).Infof ("Applying diff to %x & %x\n " , oldBlock .Hash ().Bytes ()[:4 ], newBlock .Hash ().Bytes ()[:4 ])
622
623
623
- var oldChain , newChain types.Blocks
624
- // First find the split (common ancestor) so we can perform an adequate merge
624
+ var newChain types.Blocks
625
+ // first find common number
626
+ for newBlock = newBlock ; newBlock .NumberU64 () != oldBlock .NumberU64 (); newBlock = self .GetBlock (newBlock .ParentHash ()) {
627
+ newChain = append (newChain , newBlock )
628
+ }
629
+
630
+ glog .V (logger .Debug ).Infoln ("Found common number" , newBlock .Number ())
625
631
for {
626
- oldBlock , newBlock = self .GetBlock (oldBlock .ParentHash ()), self .GetBlock (newBlock .ParentHash ())
627
632
if oldBlock .Hash () == newBlock .Hash () {
628
633
break
629
634
}
630
- oldChain = append (oldChain , oldBlock )
631
635
newChain = append (newChain , newBlock )
636
+
637
+ oldBlock , newBlock = self .GetBlock (oldBlock .ParentHash ()), self .GetBlock (newBlock .ParentHash ())
632
638
}
633
639
640
+ return newChain
641
+ }
642
+
643
+ // merge merges two different chain to the new canonical chain
644
+ func (self * ChainManager ) merge (oldBlock , newBlock * types.Block ) {
645
+ newChain := self .diff (oldBlock , newBlock )
646
+
634
647
// insert blocks
635
648
for _ , block := range newChain {
636
649
self .insert (block )
637
650
}
638
-
639
- if glog .V (logger .Detail ) {
640
- for i , oldBlock := range oldChain {
641
- glog .Infof ("- %.10v = %x\n " , oldBlock .Number (), oldBlock .Hash ())
642
- glog .Infof ("+ %.10v = %x\n " , newChain [i ].Number (), newChain [i ].Hash ())
643
- }
644
- }
645
651
}
646
652
647
653
func (self * ChainManager ) update () {
0 commit comments