aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-05-28 21:35:50 +0800
committerobscuren <geffobscura@gmail.com>2015-05-28 21:35:50 +0800
commit75f5ae80fd8a63d3e21462bcb7c338f44cd2b6e8 (patch)
tree6a9c6ccbf06f1bcdf1e3e8baa137ed6f71d8cea9
parent4baa5ca963552df6ed11112094f08111c8cf14bd (diff)
downloaddexon-75f5ae80fd8a63d3e21462bcb7c338f44cd2b6e8.tar.gz
dexon-75f5ae80fd8a63d3e21462bcb7c338f44cd2b6e8.tar.zst
dexon-75f5ae80fd8a63d3e21462bcb7c338f44cd2b6e8.zip
core: partially removed nonce parallelisation and added merge error chk
Invalid forks are now detected Current setup of parellelisation actually inserts bad blocks. This fix is tmp until a better one is found
-rw-r--r--core/chain_manager.go80
1 files changed, 56 insertions, 24 deletions
diff --git a/core/chain_manager.go b/core/chain_manager.go
index edf8825f3..24ef2c0ab 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -548,18 +548,21 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
tstart = time.Now()
)
- // check the nonce in parallel to the block processing
- // this speeds catching up significantly
- nonceErrCh := make(chan error)
- go func() {
- nonceErrCh <- verifyNonces(self.pow, chain)
- }()
-
for i, block := range chain {
if block == nil {
continue
}
+ if BadHashes[block.Hash()] {
+ err := fmt.Errorf("Found known bad hash in chain %x", block.Hash())
+ blockErr(block, err)
+ return i, err
+ }
+
+ // create a nonce channel for parallisation of the nonce check
+ nonceErrCh := make(chan error)
+ go verifyBlockNonce(self.pow, block, nonceErrCh)
+
// Setting block.Td regardless of error (known for example) prevents errors down the line
// in the protocol handler
block.Td = new(big.Int).Set(CalcTD(block, self.GetBlock(block.ParentHash())))
@@ -568,13 +571,14 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// all others will fail too (unless a known block is returned).
logs, err := self.processor.Process(block)
if err != nil {
+ // empty the nonce channel
+ <-nonceErrCh
+
if IsKnownBlockErr(err) {
stats.ignored++
continue
}
- // Do not penelise on future block. We'll need a block queue eventually that will queue
- // future block for future use
if err == BlockFutureErr {
block.SetQueued(true)
self.futureBlocks.Push(block)
@@ -593,18 +597,23 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
return i, err
}
+ // Wait and check nonce channel and make sure it checks out fine
+ // otherwise return the error
+ if err := <-nonceErrCh; err != nil {
+ return i, err
+ }
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 {
// chain fork
if block.ParentHash() != cblock.Hash() {
// during split we merge two different chains and create the new canonical chain
- self.merge(cblock, block)
+ err := self.merge(cblock, block)
+ if err != nil {
+ return i, err
+ }
queue[i] = ChainSplitEvent{block, logs}
queueEvent.splitCount++
@@ -637,19 +646,16 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
queue[i] = ChainSideEvent{block, logs}
queueEvent.sideCount++
}
+ // 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)
+ // Delete from future blocks
self.futureBlocks.Delete(block.Hash())
stats.processed++
}
- // check and wait for the nonce error channel and
- // make sure no nonce error was thrown in the process
- err := <-nonceErrCh
- if err != nil {
- return 0, err
- }
-
if (stats.queued > 0 || stats.processed > 0 || stats.ignored > 0) && bool(glog.V(logger.Info)) {
tend := time.Since(tstart)
start, end := chain[0], chain[len(chain)-1]
@@ -663,7 +669,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
// diff 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) diff(oldBlock, newBlock *types.Block) types.Blocks {
+func (self *ChainManager) diff(oldBlock, newBlock *types.Block) (types.Blocks, error) {
var (
newChain types.Blocks
commonBlock *types.Block
@@ -675,10 +681,17 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
if oldBlock.NumberU64() > newBlock.NumberU64() {
// reduce old chain
for oldBlock = oldBlock; oldBlock.NumberU64() != newBlock.NumberU64(); oldBlock = self.GetBlock(oldBlock.ParentHash()) {
+ if oldBlock == nil {
+ return nil, fmt.Errorf("Invalid old chain")
+ }
}
} else {
// reduce new chain and append new chain blocks for inserting later on
for newBlock = newBlock; newBlock.NumberU64() != oldBlock.NumberU64(); newBlock = self.GetBlock(newBlock.ParentHash()) {
+ if newBlock == nil {
+ return nil, fmt.Errorf("Invalid new chain")
+ }
+
newChain = append(newChain, newBlock)
}
}
@@ -692,6 +705,12 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
newChain = append(newChain, newBlock)
oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash())
+ if oldBlock == nil {
+ return nil, fmt.Errorf("Invalid old chain")
+ }
+ if newBlock == nil {
+ return nil, fmt.Errorf("Invalid new chain")
+ }
}
if glog.V(logger.Info) {
@@ -699,17 +718,22 @@ func (self *ChainManager) diff(oldBlock, newBlock *types.Block) types.Blocks {
glog.Infof("Fork detected @ %x. Reorganising chain from #%v %x to %x", commonHash[:4], numSplit, oldStart.Hash().Bytes()[:4], newStart.Hash().Bytes()[:4])
}
- return newChain
+ return newChain, nil
}
// merge merges two different chain to the new canonical chain
-func (self *ChainManager) merge(oldBlock, newBlock *types.Block) {
- newChain := self.diff(oldBlock, newBlock)
+func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error {
+ newChain, err := self.diff(oldBlock, newBlock)
+ if err != nil {
+ return fmt.Errorf("chain reorg failed: %v", err)
+ }
// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
for _, block := range newChain {
self.insert(block)
}
+
+ return nil
}
func (self *ChainManager) update() {
@@ -808,3 +832,11 @@ func verifyNonce(pow pow.PoW, in <-chan *types.Block, done chan<- error) {
}
}
}
+
+func verifyBlockNonce(pow pow.PoW, block *types.Block, done chan<- error) {
+ if !pow.Verify(block) {
+ done <- ValidationError("Block(#%v) nonce is invalid (= %x)", block.Number(), block.Nonce)
+ } else {
+ done <- nil
+ }
+}