X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=protocol%2Fblock.go;h=e3f0f8390e86b92af21fe67fc7517009a3189789;hb=644c2afa58cfef47dbb1df817399b1da4d353aa0;hp=1894f68b6f7af25c7c2da7840fb6e11674071471;hpb=ddc7106558f020bde24cc337d51649611dddaba8;p=bytom%2Fvapor.git diff --git a/protocol/block.go b/protocol/block.go index 1894f68b..e3f0f839 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -3,7 +3,9 @@ package protocol import ( log "github.com/sirupsen/logrus" + "github.com/vapor/config" "github.com/vapor/errors" + "github.com/vapor/event" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" "github.com/vapor/protocol/state" @@ -74,6 +76,7 @@ func (c *Chain) calcReorganizeNodes(node *state.BlockNode) ([]*state.BlockNode, } func (c *Chain) connectBlock(block *types.Block) (err error) { + irreversibleNode := c.bestIrreversibleNode bcBlock := types.MapBlock(block) if bcBlock.TransactionStatus, err = c.store.GetTransactionStatus(&bcBlock.ID); err != nil { return err @@ -86,19 +89,22 @@ func (c *Chain) connectBlock(block *types.Block) (err error) { if err := utxoView.ApplyBlock(bcBlock, bcBlock.TransactionStatus); err != nil { return err } + + voteResultMap := make(map[uint64]*state.VoteResult) + if err := c.consensusNodeManager.applyBlock(voteResultMap, block); err != nil { + return err + } + node := c.index.GetNode(&bcBlock.ID) - if err := c.setState(node, utxoView); err != nil { + if c.isIrreversible(node) && block.Height > irreversibleNode.Height { + irreversibleNode = node + } + + if err := c.setState(node, irreversibleNode, utxoView, voteResultMap); err != nil { return err } + for _, tx := range block.Transactions { - for key, value := range tx.Entries { - switch value.(type) { - case *bc.Claim: - c.store.SetWithdrawSpent(&key) - default: - continue - } - } c.txPool.RemoveTransaction(&tx.Tx.ID) } return nil @@ -107,6 +113,8 @@ func (c *Chain) connectBlock(block *types.Block) (err error) { func (c *Chain) reorganizeChain(node *state.BlockNode) error { attachNodes, detachNodes := c.calcReorganizeNodes(node) utxoView := state.NewUtxoViewpoint() + voteResultMap := make(map[uint64]*state.VoteResult) + irreversibleNode := c.bestIrreversibleNode for _, detachNode := range detachNodes { b, err := c.store.GetBlock(&detachNode.Hash) @@ -114,19 +122,29 @@ func (c *Chain) reorganizeChain(node *state.BlockNode) error { return err } + if b.Height <= irreversibleNode.Height { + return errors.New("the height of rollback block below the height of irreversible block") + } + detachBlock := types.MapBlock(b) if err := c.store.GetTransactionsUtxo(utxoView, detachBlock.Transactions); err != nil { return err } + txStatus, err := c.GetTransactionStatus(&detachBlock.ID) if err != nil { return err } + if err := utxoView.DetachBlock(detachBlock, txStatus); err != nil { return err } - log.WithFields(log.Fields{"height": node.Height, "hash": node.Hash.String()}).Debug("detach from mainchain") + if err := c.consensusNodeManager.detachBlock(voteResultMap, b); err != nil { + return err + } + + log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Debug("detach from mainchain") } for _, attachNode := range attachNodes { @@ -139,28 +157,47 @@ func (c *Chain) reorganizeChain(node *state.BlockNode) error { if err := c.store.GetTransactionsUtxo(utxoView, attachBlock.Transactions); err != nil { return err } + txStatus, err := c.GetTransactionStatus(&attachBlock.ID) if err != nil { return err } + if err := utxoView.ApplyBlock(attachBlock, txStatus); err != nil { return err } - log.WithFields(log.Fields{"height": node.Height, "hash": node.Hash.String()}).Debug("attach from mainchain") + if err := c.consensusNodeManager.applyBlock(voteResultMap, b); err != nil { + return err + } + + if c.isIrreversible(attachNode) && b.Height > irreversibleNode.Height { + irreversibleNode = attachNode + } + + log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Debug("attach from mainchain") } - return c.setState(node, utxoView) + return c.setState(node, irreversibleNode, utxoView, voteResultMap) } // SaveBlock will validate and save block into storage func (c *Chain) saveBlock(block *types.Block) error { - bcBlock := types.MapBlock(block) + if _, err := c.validateSign(block); err != nil { + return errors.Sub(ErrBadBlock, err) + } + parent := c.index.GetNode(&block.PreviousBlockHash) + bcBlock := types.MapBlock(block) + if err := validation.ValidateBlock(bcBlock, parent); err != nil { + return errors.Sub(ErrBadBlock, err) + } - if err := validation.ValidateBlock(bcBlock, parent, block, c, c.engine, c.Authoritys, c.position); err != nil { + signature, err := c.SignBlock(block) + if err != nil { return errors.Sub(ErrBadBlock, err) } + if err := c.store.SaveBlock(block, bcBlock.TransactionStatus); err != nil { return err } @@ -172,6 +209,13 @@ func (c *Chain) saveBlock(block *types.Block) error { } c.index.AddNode(node) + + if len(signature) != 0 { + xPub := config.CommonConfig.PrivateKey().XPub() + if err := c.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: block.Hash(), Signature: signature, XPub: xPub}); err != nil { + return err + } + } return nil } @@ -186,11 +230,11 @@ func (c *Chain) saveSubBlock(block *types.Block) *types.Block { for _, prevOrphan := range prevOrphans { orphanBlock, ok := c.orphanManage.Get(prevOrphan) if !ok { - log.WithFields(log.Fields{"hash": prevOrphan.String()}).Warning("saveSubBlock fail to get block from orphanManage") + log.WithFields(log.Fields{"module": logModule, "hash": prevOrphan.String()}).Warning("saveSubBlock fail to get block from orphanManage") continue } if err := c.saveBlock(orphanBlock); err != nil { - log.WithFields(log.Fields{"hash": prevOrphan.String(), "height": orphanBlock.Height}).Warning("saveSubBlock fail to save block") + log.WithFields(log.Fields{"module": logModule, "hash": prevOrphan.String(), "height": orphanBlock.Height}).Warning("saveSubBlock fail to save block") continue } @@ -228,9 +272,13 @@ func (c *Chain) blockProcesser() { // ProcessBlock is the entry for handle block insert func (c *Chain) processBlock(block *types.Block) (bool, error) { + if block.Height <= c.bestIrreversibleNode.Height { + return false, errors.New("the height of block below the height of irreversible block") + } + blockHash := block.Hash() if c.BlockExist(&blockHash) { - log.WithFields(log.Fields{"hash": blockHash.String(), "height": block.Height}).Info("block has been processed") + log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("block has been processed") return c.orphanManage.BlockExist(&blockHash), nil } @@ -248,12 +296,12 @@ func (c *Chain) processBlock(block *types.Block) (bool, error) { bestNode := c.index.GetNode(&bestBlockHash) if bestNode.Parent == c.bestNode { - log.Debug("append block to the end of mainchain") + log.WithFields(log.Fields{"module": logModule}).Debug("append block to the end of mainchain") return false, c.connectBlock(bestBlock) } - if bestNode.Height > c.bestNode.Height && bestNode.WorkSum.Cmp(c.bestNode.WorkSum) >= 0 { - log.Debug("start to reorganize chain") + if bestNode.Height > c.bestNode.Height { + log.WithFields(log.Fields{"module": logModule}).Debug("start to reorganize chain") return false, c.reorganizeChain(bestNode) } return false, nil