OSDN Git Service

cfb94174ae5db666bf1333203af6e9fd2d3dd7b2
[bytom/vapor.git] / protocol / block.go
1 package protocol
2
3 import (
4         log "github.com/sirupsen/logrus"
5
6         "github.com/vapor/errors"
7         "github.com/vapor/event"
8         "github.com/vapor/protocol/bc"
9         "github.com/vapor/protocol/bc/types"
10         "github.com/vapor/protocol/state"
11         "github.com/vapor/protocol/validation"
12 )
13
14 var (
15         // ErrBadBlock is returned when a block is invalid.
16         ErrBadBlock = errors.New("invalid block")
17         // ErrBadStateRoot is returned when the computed assets merkle root
18         // disagrees with the one declared in a block header.
19         ErrBadStateRoot = errors.New("invalid state merkle root")
20 )
21
22 // BlockExist check is a block in chain or orphan
23 func (c *Chain) BlockExist(hash *bc.Hash) bool {
24         return c.index.BlockExist(hash) || c.orphanManage.BlockExist(hash)
25 }
26
27 // GetBlockByHash return a block by given hash
28 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*types.Block, error) {
29         return c.store.GetBlock(hash)
30 }
31
32 // GetBlockByHeight return a block header by given height
33 func (c *Chain) GetBlockByHeight(height uint64) (*types.Block, error) {
34         node := c.index.NodeByHeight(height)
35         if node == nil {
36                 return nil, errors.New("can't find block in given height")
37         }
38         return c.store.GetBlock(&node.Hash)
39 }
40
41 // GetHeaderByHash return a block header by given hash
42 func (c *Chain) GetHeaderByHash(hash *bc.Hash) (*types.BlockHeader, error) {
43         node := c.index.GetNode(hash)
44         if node == nil {
45                 return nil, errors.New("can't find block header in given hash")
46         }
47         return node.BlockHeader(), nil
48 }
49
50 // GetHeaderByHeight return a block header by given height
51 func (c *Chain) GetHeaderByHeight(height uint64) (*types.BlockHeader, error) {
52         node := c.index.NodeByHeight(height)
53         if node == nil {
54                 return nil, errors.New("can't find block header in given height")
55         }
56         return node.BlockHeader(), nil
57 }
58
59 func (c *Chain) calcReorganizeNodes(node *state.BlockNode) ([]*state.BlockNode, []*state.BlockNode) {
60         var attachNodes []*state.BlockNode
61         var detachNodes []*state.BlockNode
62
63         attachNode := node
64         for c.index.NodeByHeight(attachNode.Height) != attachNode {
65                 attachNodes = append([]*state.BlockNode{attachNode}, attachNodes...)
66                 attachNode = attachNode.Parent
67         }
68
69         detachNode := c.bestNode
70         for detachNode != attachNode {
71                 detachNodes = append(detachNodes, detachNode)
72                 detachNode = detachNode.Parent
73         }
74         return attachNodes, detachNodes
75 }
76
77 func (c *Chain) connectBlock(block *types.Block) (err error) {
78         irreversibleNode := c.bestIrreversibleNode
79         bcBlock := types.MapBlock(block)
80         if bcBlock.TransactionStatus, err = c.store.GetTransactionStatus(&bcBlock.ID); err != nil {
81                 return err
82         }
83
84         utxoView := state.NewUtxoViewpoint()
85         if err := c.store.GetTransactionsUtxo(utxoView, bcBlock.Transactions); err != nil {
86                 return err
87         }
88         if err := utxoView.ApplyBlock(bcBlock, bcBlock.TransactionStatus); err != nil {
89                 return err
90         }
91
92         voteResultMap := make(map[uint64]*state.VoteResult)
93         if err := c.bbft.ApplyBlock(voteResultMap, block); err != nil {
94                 return err
95         }
96
97         node := c.index.GetNode(&bcBlock.ID)
98         if c.bbft.isIrreversible(block) && block.Height > irreversibleNode.Height {
99                 irreversibleNode = node
100         }
101
102         if err := c.setState(node, irreversibleNode, utxoView, voteResultMap); err != nil {
103                 return err
104         }
105
106         for _, tx := range block.Transactions {
107                 c.txPool.RemoveTransaction(&tx.Tx.ID)
108         }
109         return nil
110 }
111
112 func (c *Chain) reorganizeChain(node *state.BlockNode) error {
113         attachNodes, detachNodes := c.calcReorganizeNodes(node)
114         utxoView := state.NewUtxoViewpoint()
115         voteResultMap := make(map[uint64]*state.VoteResult)
116         irreversibleNode := c.bestIrreversibleNode
117
118         for _, detachNode := range detachNodes {
119                 b, err := c.store.GetBlock(&detachNode.Hash)
120                 if err != nil {
121                         return err
122                 }
123
124                 if b.Height <= irreversibleNode.Height {
125                         return errors.New("the height of rollback block below the height of irreversible block")
126                 }
127
128                 detachBlock := types.MapBlock(b)
129                 if err := c.store.GetTransactionsUtxo(utxoView, detachBlock.Transactions); err != nil {
130                         return err
131                 }
132
133                 txStatus, err := c.GetTransactionStatus(&detachBlock.ID)
134                 if err != nil {
135                         return err
136                 }
137
138                 if err := utxoView.DetachBlock(detachBlock, txStatus); err != nil {
139                         return err
140                 }
141
142                 if err := c.bbft.DetachBlock(voteResultMap, b); err != nil {
143                         return err
144                 }
145
146                 log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Debug("detach from mainchain")
147         }
148
149         for _, attachNode := range attachNodes {
150                 b, err := c.store.GetBlock(&attachNode.Hash)
151                 if err != nil {
152                         return err
153                 }
154
155                 attachBlock := types.MapBlock(b)
156                 if err := c.store.GetTransactionsUtxo(utxoView, attachBlock.Transactions); err != nil {
157                         return err
158                 }
159
160                 txStatus, err := c.GetTransactionStatus(&attachBlock.ID)
161                 if err != nil {
162                         return err
163                 }
164
165                 if err := utxoView.ApplyBlock(attachBlock, txStatus); err != nil {
166                         return err
167                 }
168
169                 if err := c.bbft.ApplyBlock(voteResultMap, b); err != nil {
170                         return err
171                 }
172
173                 if c.bbft.isIrreversible(b) && b.Height > irreversibleNode.Height {
174                         irreversibleNode = attachNode
175                 }
176
177                 log.WithFields(log.Fields{"module": logModule, "height": node.Height, "hash": node.Hash.String()}).Debug("attach from mainchain")
178         }
179
180         return c.setState(node, irreversibleNode, utxoView, voteResultMap)
181 }
182
183 // SaveBlock will validate and save block into storage
184 func (c *Chain) saveBlock(block *types.Block) error {
185         if err := c.bbft.ValidateBlock(block); err != nil {
186                 return errors.Sub(ErrBadBlock, err)
187         }
188
189         parent := c.index.GetNode(&block.PreviousBlockHash)
190         if err := validation.ValidateBlock(types.MapBlock(block), parent); err != nil {
191                 return errors.Sub(ErrBadBlock, err)
192         }
193
194         signature, err := c.bbft.SignBlock(block)
195         if err != nil {
196                 return errors.Sub(ErrBadBlock, err)
197         }
198
199         if len(signature) != 0 {
200                 if err := c.bbft.eventDispatcher.Post(event.BlockSignatureEvent{BlockHash: block.Hash(), Signature: signature}); err != nil {
201                         return err
202                 }
203         }
204
205         bcBlock := types.MapBlock(block)
206         if err := c.store.SaveBlock(block, bcBlock.TransactionStatus); err != nil {
207                 return err
208         }
209
210         c.orphanManage.Delete(&bcBlock.ID)
211         node, err := state.NewBlockNode(&block.BlockHeader, parent)
212         if err != nil {
213                 return err
214         }
215
216         c.index.AddNode(node)
217         return nil
218 }
219
220 func (c *Chain) saveSubBlock(block *types.Block) *types.Block {
221         blockHash := block.Hash()
222         prevOrphans, ok := c.orphanManage.GetPrevOrphans(&blockHash)
223         if !ok {
224                 return block
225         }
226
227         bestBlock := block
228         for _, prevOrphan := range prevOrphans {
229                 orphanBlock, ok := c.orphanManage.Get(prevOrphan)
230                 if !ok {
231                         log.WithFields(log.Fields{"module": logModule, "hash": prevOrphan.String()}).Warning("saveSubBlock fail to get block from orphanManage")
232                         continue
233                 }
234                 if err := c.saveBlock(orphanBlock); err != nil {
235                         log.WithFields(log.Fields{"module": logModule, "hash": prevOrphan.String(), "height": orphanBlock.Height}).Warning("saveSubBlock fail to save block")
236                         continue
237                 }
238
239                 if subBestBlock := c.saveSubBlock(orphanBlock); subBestBlock.Height > bestBlock.Height {
240                         bestBlock = subBestBlock
241                 }
242         }
243         return bestBlock
244 }
245
246 type processBlockResponse struct {
247         isOrphan bool
248         err      error
249 }
250
251 type processBlockMsg struct {
252         block *types.Block
253         reply chan processBlockResponse
254 }
255
256 // ProcessBlock is the entry for chain update
257 func (c *Chain) ProcessBlock(block *types.Block) (bool, error) {
258         reply := make(chan processBlockResponse, 1)
259         c.processBlockCh <- &processBlockMsg{block: block, reply: reply}
260         response := <-reply
261         return response.isOrphan, response.err
262 }
263
264 func (c *Chain) blockProcesser() {
265         for msg := range c.processBlockCh {
266                 isOrphan, err := c.processBlock(msg.block)
267                 msg.reply <- processBlockResponse{isOrphan: isOrphan, err: err}
268         }
269 }
270
271 // ProcessBlock is the entry for handle block insert
272 func (c *Chain) processBlock(block *types.Block) (bool, error) {
273         if block.Height <= c.bestIrreversibleNode.Height {
274                 return false, errors.New("the height of block below the height of irreversible block")
275         }
276
277         blockHash := block.Hash()
278         if c.BlockExist(&blockHash) {
279                 log.WithFields(log.Fields{"module": logModule, "hash": blockHash.String(), "height": block.Height}).Info("block has been processed")
280                 return c.orphanManage.BlockExist(&blockHash), nil
281         }
282
283         parent := c.index.GetNode(&block.PreviousBlockHash)
284         if parent == nil {
285                 c.orphanManage.Add(block)
286                 return true, nil
287         }
288
289         if err := c.saveBlock(block); err != nil {
290                 return false, err
291         }
292
293         bestBlock := c.saveSubBlock(block)
294         bestBlockHash := bestBlock.Hash()
295         bestNode := c.index.GetNode(&bestBlockHash)
296
297         if bestNode.Parent == c.bestNode {
298                 log.WithFields(log.Fields{"module": logModule}).Debug("append block to the end of mainchain")
299                 return false, c.connectBlock(bestBlock)
300         }
301
302         if bestNode.Height > c.bestNode.Height {
303                 log.WithFields(log.Fields{"module": logModule}).Debug("start to reorganize chain")
304                 return false, c.reorganizeChain(bestNode)
305         }
306         return false, nil
307 }
308
309 func (c *Chain) ProcessBlockSignature(signature, pubkey []byte, blockHeight uint64, blockHash *bc.Hash) error {
310         isBestIrreversible, err := c.bbft.ProcessBlockSignature(signature, pubkey, blockHeight, blockHash)
311         if err != nil {
312                 return err
313         }
314
315         if isBestIrreversible {
316                 bestIrreversibleNode := c.index.GetNode(blockHash)
317                 if err := c.store.SaveChainNodeStatus(c.bestNode, bestIrreversibleNode); err != nil {
318                         return err
319                 }
320
321                 c.bestIrreversibleNode = bestIrreversibleNode
322         }
323         return nil
324 }