type applyBlockReply struct {
verification *Verification
- isRollback bool
- newBestHash bc.Hash
+ bestHash bc.Hash
}
// ApplyBlock used to receive a new block from upper layer, it provides idempotence
defer c.mu.Unlock()
if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
- return nil, errAlreadyProcessedBlock
+ _, bestHash := c.bestChain()
+ return &applyBlockReply{bestHash: bestHash}, nil
}
- _, oldBestHash := c.bestChain()
target, err := c.applyBlockToCheckpoint(block)
if err != nil {
return nil, errors.Wrap(err, "apply block to checkpoint")
return nil, err
}
- reply := &applyBlockReply{verification: verification}
- if c.isRollback(oldBestHash, block) {
- reply.isRollback = true
- reply.newBestHash = block.Hash()
- }
+ _, bestHash := c.bestChain()
+ reply := &applyBlockReply{verification: verification, bestHash: bestHash}
return reply, c.saveCheckpoints(affectedCheckpoints)
}
return node, nil
}
-func (c *Casper) isRollback(oldBestHash bc.Hash, block *types.Block) bool {
- _, newBestHash := c.bestChain()
- return block.Hash() == newBestHash && block.PreviousBlockHash != oldBestHash
-}
-
func (c *Casper) reorganizeCheckpoint(hash bc.Hash) (*treeNode, error) {
prevHash := hash
var attachBlocks []*types.Block
return false, c.connectBlock(bestBlock)
}
- log.WithFields(log.Fields{"module": logModule}).Debug("apply fork chain to casper")
return false, c.applyForkChainToCasper(bestNode)
}
func (c *Chain) applyForkChainToCasper(bestNode *state.BlockNode) error {
attachNodes, _ := c.calcReorganizeNodes(bestNode)
+ var reply *applyBlockReply
for _, node := range attachNodes {
block, err := c.store.GetBlock(&node.Hash)
if err != nil {
return err
}
- reply, err := c.casper.ApplyBlock(block)
+ reply, err = c.casper.ApplyBlock(block)
if err != nil {
return err
}
+ log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Info("apply fork node")
+
if reply.verification != nil {
if err := c.broadcastVerification(reply.verification); err != nil {
return err
}
}
-
- if reply.isRollback {
- if err := c.rollback(reply.newBestHash); err != nil {
- return err
- }
- }
+ }
+ if reply.bestHash != c.bestNode.Hash {
+ return c.rollback(reply.bestHash)
}
return nil
}
}
node := c.index.GetNode(&bestHash)
- log.WithFields(log.Fields{"module": logModule}).Debug("start to reorganize chain")
+ log.WithFields(log.Fields{"module": logModule, "bestHash": bestHash.String()}).Info("start to reorganize chain")
return c.reorganizeChain(node)
}
errVoteToNonValidator = errors.New("pubKey of vote is not validator")
errGuarantyLessThanMinimum = errors.New("guaranty less than minimum")
errOverflow = errors.New("arithmetic overflow/underflow")
- errAlreadyProcessedBlock = errors.New("block already processed in casper")
)
const minGuaranty = 1E14