aboutsummaryrefslogtreecommitdiffstats
path: root/core/chain_manager.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-04-14 06:18:38 +0800
committerobscuren <geffobscura@gmail.com>2015-04-14 06:20:29 +0800
commit333d4e0f278166455f9261f795aa0a8c5ce5d534 (patch)
tree5a2bee1fbc1fa19f31714e8dc0fcc0eea7cd54cd /core/chain_manager.go
parent4f3c169b4ece4935209ffd060ceaebe1702bc2f0 (diff)
downloaddexon-333d4e0f278166455f9261f795aa0a8c5ce5d534.tar.gz
dexon-333d4e0f278166455f9261f795aa0a8c5ce5d534.tar.zst
dexon-333d4e0f278166455f9261f795aa0a8c5ce5d534.zip
core: during split properly insert parent blocks
During a split parent and grand parent were included in the database but not in the canonical chain (numbered chain). Added a `merge` function which finds the common ancestor of the chains and reinserts the missing blocks.
Diffstat (limited to 'core/chain_manager.go')
-rw-r--r--core/chain_manager.go33
1 files changed, 32 insertions, 1 deletions
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 721c008bc..ade922217 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -490,8 +490,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
block.Td = td
self.mu.Lock()
- cblock := self.currentBlock
{
+ 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)
@@ -505,6 +505,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
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], td, cblock.Header().Number, chash[:4], self.td)
}
+ // during split we merge two different chains and create the new canonical chain
+ self.merge(cblock, block)
queue[i] = ChainSplitEvent{block, logs}
queueEvent.splitCount++
@@ -553,6 +555,35 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
return nil
}
+// merge takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them
+// to be part of the new canonical chain.
+func (self *ChainManager) merge(oldBlock, newBlock *types.Block) {
+ glog.V(logger.Debug).Infof("Applying diff to %x & %x\n", oldBlock.Hash().Bytes()[:4], newBlock.Hash().Bytes()[:4])
+
+ var oldChain, newChain types.Blocks
+ // First find the split (common ancestor) so we can perform an adequate merge
+ for {
+ oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash())
+ if oldBlock.Hash() == newBlock.Hash() {
+ break
+ }
+ oldChain = append(oldChain, oldBlock)
+ newChain = append(newChain, newBlock)
+ }
+
+ // insert blocks
+ for _, block := range newChain {
+ self.insert(block)
+ }
+
+ if glog.V(logger.Detail) {
+ for i, oldBlock := range oldChain {
+ glog.Infof("- %.10v = %x\n", oldBlock.Number(), oldBlock.Hash())
+ glog.Infof("+ %.10v = %x\n", newChain[i].Number(), newChain[i].Hash())
+ }
+ }
+}
+
func (self *ChainManager) update() {
events := self.eventMux.Subscribe(queueEvent{})
futureTimer := time.NewTicker(5 * time.Second)