X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=protocol%2Fblock.go;h=801811324cfb18581796090b8ec661f1f4e2aed6;hb=0f705655e257982edfc95526f58bf074462fd7ba;hp=ad4647b55f57d54bc55892a24b3ecbee082bfa81;hpb=2cf5801b2e693a45de9b51ec9aa9c1f787d57105;p=bytom%2Fvapor.git diff --git a/protocol/block.go b/protocol/block.go index ad4647b5..80181132 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -4,6 +4,8 @@ import ( log "github.com/sirupsen/logrus" "github.com/vapor/errors" + "github.com/vapor/event" + "github.com/vapor/config" "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 @@ -87,8 +90,17 @@ func (c *Chain) connectBlock(block *types.Block) (err error) { return err } + voteResultMap := make(map[uint64]*state.VoteResult) + if err := c.bbft.ApplyBlock(voteResultMap, block); err != nil { + return err + } + node := c.index.GetNode(&bcBlock.ID) - if err := c.setState(node, utxoView); err != nil { + if c.bbft.isIrreversible(block) && block.Height > irreversibleNode.Height { + irreversibleNode = node + } + + if err := c.setState(node, irreversibleNode, utxoView, voteResultMap); err != nil { return err } @@ -101,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) @@ -108,18 +122,28 @@ 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 } + if err := c.bbft.DetachBlock(voteResultMap, b); err != nil { + return err + } + log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Debug("detach from mainchain") } @@ -133,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 } + if err := c.bbft.ApplyBlock(voteResultMap, b); err != nil { + return err + } + + if c.bbft.isIrreversible(b) && 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) - parent := c.index.GetNode(&block.PreviousBlockHash) + if err := c.bbft.ValidateBlock(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) } + + signature, err := c.bbft.SignBlock(block) + if err != nil { + return errors.Sub(ErrBadBlock, err) + } + if err := c.store.SaveBlock(block, bcBlock.TransactionStatus); err != nil { return err } @@ -166,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.bbft.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: block.Hash(), Signature: signature, XPub: xPub}); err != nil { + return err + } + } return nil } @@ -222,13 +272,18 @@ 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{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("block has been processed") return c.orphanManage.BlockExist(&blockHash), nil } - if parent := c.index.GetNode(&block.PreviousBlockHash); parent == nil { + parent := c.index.GetNode(&block.PreviousBlockHash) + if parent == nil { c.orphanManage.Add(block) return true, nil } @@ -252,3 +307,20 @@ func (c *Chain) processBlock(block *types.Block) (bool, error) { } return false, nil } + +func (c *Chain) ProcessBlockSignature(signature []byte, xPub [64]byte, blockHeight uint64, blockHash *bc.Hash) error { + isIrreversible, err := c.bbft.ProcessBlockSignature(signature, xPub, blockHeight, blockHash) + if err != nil { + return err + } + + if isIrreversible && blockHeight > c.bestIrreversibleNode.Height { + bestIrreversibleNode := c.index.GetNode(blockHash) + if err := c.store.SaveChainNodeStatus(c.bestNode, bestIrreversibleNode); err != nil { + return err + } + + c.bestIrreversibleNode = bestIrreversibleNode + } + return nil +}