OSDN Git Service

Merge branch 'dev' into bvm
[bytom/bytom.git] / protocol / block.go
1 package protocol
2
3 import (
4         "github.com/bytom/errors"
5         "github.com/bytom/protocol/bc"
6         "github.com/bytom/protocol/bc/legacy"
7         "github.com/bytom/protocol/state"
8         "github.com/bytom/protocol/validation"
9 )
10
11 var (
12         // ErrBadBlock is returned when a block is invalid.
13         ErrBadBlock = errors.New("invalid block")
14
15         // ErrStaleState is returned when the Chain does not have a current
16         // blockchain state.
17         ErrStaleState = errors.New("stale blockchain state")
18
19         // ErrBadStateRoot is returned when the computed assets merkle root
20         // disagrees with the one declared in a block header.
21         ErrBadStateRoot = errors.New("invalid state merkle root")
22 )
23
24 func (c *Chain) BlockExist(hash *bc.Hash) bool {
25         return c.orphanManage.BlockExist(hash) || c.store.BlockExist(hash)
26 }
27
28 func (c *Chain) GetBlockByHash(hash *bc.Hash) (*legacy.Block, error) {
29         return c.store.GetBlock(hash)
30 }
31
32 func (c *Chain) GetBlockByHeight(height uint64) (*legacy.Block, error) {
33         c.state.cond.L.Lock()
34         hash, ok := c.state.mainChain[height]
35         c.state.cond.L.Unlock()
36         if !ok {
37                 return nil, errors.New("can't find block in given hight")
38         }
39         return c.GetBlockByHash(hash)
40 }
41
42 // ValidateBlock validates an incoming block in advance of applying it
43 // to a snapshot (with ApplyValidBlock) and committing it to the
44 // blockchain (with CommitAppliedBlock).
45 func (c *Chain) ValidateBlock(block, prev *legacy.Block) error {
46         blockEnts := legacy.MapBlock(block)
47         prevEnts := legacy.MapBlock(prev)
48         if err := validation.ValidateBlock(blockEnts, prevEnts); err != nil {
49                 return errors.Sub(ErrBadBlock, err)
50         }
51         return nil
52 }
53
54 // ApplyValidBlock creates an updated snapshot without validating the
55 // block.
56 func (c *Chain) ConnectBlock(block *legacy.Block) error {
57         newSnapshot := state.Copy(c.state.snapshot)
58         if err := newSnapshot.ApplyBlock(legacy.MapBlock(block)); err != nil {
59                 return err
60         }
61
62         blockHash := block.Hash()
63         if err := c.setState(block, newSnapshot, map[uint64]*bc.Hash{block.Height: &blockHash}); err != nil {
64                 return err
65         }
66
67         for _, tx := range block.Transactions {
68                 c.txPool.RemoveTransaction(&tx.Tx.ID)
69         }
70         return nil
71 }
72
73 func (c *Chain) getReorganizeBlocks(block *legacy.Block) ([]*legacy.Block, []*legacy.Block) {
74         attachBlocks := []*legacy.Block{}
75         detachBlocks := []*legacy.Block{}
76         ancestor := block
77
78         for !c.InMainchain(ancestor) {
79                 attachBlocks = append([]*legacy.Block{ancestor}, attachBlocks...)
80                 ancestor, _ = c.GetBlockByHash(&ancestor.PreviousBlockHash)
81         }
82
83         for d := c.state.block; d.Hash() != ancestor.Hash(); d, _ = c.GetBlockByHash(&d.PreviousBlockHash) {
84                 detachBlocks = append(detachBlocks, d)
85         }
86
87         return attachBlocks, detachBlocks
88 }
89
90 func (c *Chain) reorganizeChain(block *legacy.Block) error {
91         attachBlocks, detachBlocks := c.getReorganizeBlocks(block)
92         newSnapshot := state.Copy(c.state.snapshot)
93         chainChanges := map[uint64]*bc.Hash{}
94
95         for _, d := range detachBlocks {
96                 if err := newSnapshot.DetachBlock(legacy.MapBlock(d)); err != nil {
97                         return err
98                 }
99         }
100
101         for _, a := range attachBlocks {
102                 if err := newSnapshot.ApplyBlock(legacy.MapBlock(a)); err != nil {
103                         return err
104                 }
105                 aHash := a.Hash()
106                 chainChanges[a.Height] = &aHash
107         }
108
109         return c.setState(block, newSnapshot, chainChanges)
110 }
111
112 func (c *Chain) SaveBlock(block *legacy.Block) error {
113         preBlock, _ := c.GetBlockByHash(&block.PreviousBlockHash)
114         if err := c.ValidateBlock(block, preBlock); err != nil {
115                 return err
116         }
117         if err := c.store.SaveBlock(block); err != nil {
118                 return err
119         }
120
121         preorphans, ok := c.orphanManage.preOrphans[block.Hash()]
122         if !ok {
123                 return nil
124         }
125         for _, preorphan := range preorphans {
126                 orphanBlock, ok := c.orphanManage.Get(preorphan)
127                 if !ok {
128                         continue
129                 }
130                 c.SaveBlock(orphanBlock)
131                 c.orphanManage.Delete(preorphan)
132         }
133         return nil
134 }
135
136 func (c *Chain) ProcessBlock(block *legacy.Block) (bool, error) {
137         if blockHash := block.Hash(); c.BlockExist(&blockHash) {
138                 return false, nil
139         }
140         if !c.BlockExist(&block.PreviousBlockHash) {
141                 c.orphanManage.Add(block)
142                 return true, nil
143         }
144         if err := c.SaveBlock(block); err != nil {
145                 return false, err
146         }
147
148         c.state.cond.L.Lock()
149         if c.state.block.Hash() == block.PreviousBlockHash {
150                 defer c.state.cond.L.Unlock()
151                 return false, c.ConnectBlock(block)
152         }
153
154         if block.Height > c.state.height && block.Bits >= c.state.block.Bits {
155                 defer c.state.cond.L.Unlock()
156                 return false, c.reorganizeChain(block)
157         }
158         c.state.cond.L.Unlock()
159         return false, nil
160 }