X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;ds=sidebyside;f=protocol%2Fblock.go;h=86c96504c994fc3083049cd75f27e5ff57088766;hb=8f3497631ce7cf7ae1e03200a9be9adecf4a9e57;hp=a1d5830d8df769e5d0b7f5dec8d142fdd6074831;hpb=42c5ab23c13e7f43d0055221ec38752555bd987e;p=bytom%2Fvapor.git diff --git a/protocol/block.go b/protocol/block.go index a1d5830d..86c96504 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -102,20 +102,20 @@ func (c *Chain) connectBlock(block *types.Block) (err error) { return err } - voteResult, err := c.getBestVoteResult() + consensusResult, err := c.getBestConsensusResult() if err != nil { return err } - if err := voteResult.ApplyBlock(block); err != nil { + if err := consensusResult.ApplyBlock(block); err != nil { return err } - irrBlockHeader := c.bestIrrBlockHeader + irrBlockHeader := c.lastIrrBlockHeader if c.isIrreversible(&block.BlockHeader) && block.Height > irrBlockHeader.Height { irrBlockHeader = &block.BlockHeader } - if err := c.setState(&block.BlockHeader, irrBlockHeader, []*types.BlockHeader{&block.BlockHeader}, utxoView, []*state.VoteResult{voteResult}); err != nil { + if err := c.setState(&block.BlockHeader, irrBlockHeader, []*types.BlockHeader{&block.BlockHeader}, utxoView, []*state.ConsensusResult{consensusResult}); err != nil { return err } @@ -132,12 +132,13 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { } utxoView := state.NewUtxoViewpoint() - voteResults := []*state.VoteResult{} - voteResult, err := c.getBestVoteResult() + consensusResults := []*state.ConsensusResult{} + consensusResult, err := c.getBestConsensusResult() if err != nil { return err } + txsToRestore := map[bc.Hash]*types.Tx{} for _, detachBlockHeader := range detachBlockHeaders { detachHash := detachBlockHeader.Hash() b, err := c.store.GetBlock(&detachHash) @@ -159,15 +160,20 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { return err } - if err := voteResult.DetachBlock(b); err != nil { + if err := consensusResult.DetachBlock(b); err != nil { return err } + for _, tx := range b.Transactions { + txsToRestore[tx.ID] = tx + } + blockHash := blockHeader.Hash() log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("detach from mainchain") } - irrBlockHeader := c.bestIrrBlockHeader + txsToRemove := map[bc.Hash]*types.Tx{} + irrBlockHeader := c.lastIrrBlockHeader for _, attachBlockHeader := range attachBlockHeaders { attachHash := attachBlockHeader.Hash() b, err := c.store.GetBlock(&attachHash) @@ -189,27 +195,58 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { return err } - if err := voteResult.ApplyBlock(b); err != nil { + if err := consensusResult.ApplyBlock(b); err != nil { return err } - if voteResult.IsFinalize() { - voteResults = append(voteResults, voteResult.Fork()) + if consensusResult.IsFinalize() { + consensusResults = append(consensusResults, consensusResult.Fork()) } if c.isIrreversible(attachBlockHeader) && attachBlockHeader.Height > irrBlockHeader.Height { irrBlockHeader = attachBlockHeader } + for _, tx := range b.Transactions { + if _, ok := txsToRestore[tx.ID]; !ok { + txsToRemove[tx.ID] = tx + } else { + delete(txsToRestore, tx.ID) + } + } + blockHash := blockHeader.Hash() log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("attach from mainchain") } - if detachBlockHeaders[len(detachBlockHeaders)-1].Height <= c.bestIrrBlockHeader.Height && irrBlockHeader.Height <= c.bestIrrBlockHeader.Height { + if len(detachBlockHeaders) > 0 && + detachBlockHeaders[len(detachBlockHeaders)-1].Height <= c.lastIrrBlockHeader.Height && + irrBlockHeader.Height <= c.lastIrrBlockHeader.Height { return errors.New("rollback block below the height of irreversible block") } - voteResults = append(voteResults, voteResult.Fork()) - return c.setState(blockHeader, irrBlockHeader, attachBlockHeaders, utxoView, voteResults) + + consensusResults = append(consensusResults, consensusResult.Fork()) + if err := c.setState(blockHeader, irrBlockHeader, attachBlockHeaders, utxoView, consensusResults); err != nil { + return err + } + + for txHash := range txsToRemove { + c.txPool.RemoveTransaction(&txHash) + } + + for _, tx := range txsToRestore { + // the number of restored Tx should be very small or most of time ZERO + // Error returned from validation is ignored, tx could still be lost if validation fails. + // TODO: adjust tx timestamp so that it won't starve in pool. + if _, err := c.validateTx(tx, blockHeader); err != nil { + log.WithFields(log.Fields{"module": logModule, "tx_id": tx.Tx.ID.String(), "error": err}).Info("restore tx fail") + } + } + + if len(txsToRestore) > 0 { + log.WithFields(log.Fields{"module": logModule, "num": len(txsToRestore)}).Debug("restore txs back to pool") + } + return nil } // SaveBlock will validate and save block into storage @@ -223,8 +260,18 @@ func (c *Chain) saveBlock(block *types.Block) error { return err } + consensusResult, err := c.GetConsensusResultByHash(&block.PreviousBlockHash) + if err != nil { + return err + } + + rewards, err := consensusResult.GetCoinbaseRewards(parent.Height) + if err != nil { + return err + } + bcBlock := types.MapBlock(block) - if err := validation.ValidateBlock(bcBlock, parent); err != nil { + if err := validation.ValidateBlock(bcBlock, parent, rewards); err != nil { return errors.Sub(ErrBadBlock, err) } @@ -302,10 +349,12 @@ func (c *Chain) blockProcesser() { func (c *Chain) processBlock(block *types.Block) (bool, error) { blockHash := block.Hash() if c.BlockExist(&blockHash) { - log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("block has been processed") + log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Debug("block has been processed") return c.orphanManage.BlockExist(&blockHash), nil } + c.markTransactions(block.Transactions...) + if _, err := c.store.GetBlockHeader(&block.PreviousBlockHash); err != nil { c.orphanManage.Add(block) return true, nil