OSDN Git Service

mov some logic to tree folder (#2019)
[bytom/bytom.git] / protocol / casper / apply_block.go
1 package casper
2
3 import (
4         "github.com/sirupsen/logrus"
5
6         "github.com/bytom/bytom/config"
7         "github.com/bytom/bytom/consensus"
8         "github.com/bytom/bytom/errors"
9         "github.com/bytom/bytom/protocol/bc"
10         "github.com/bytom/bytom/protocol/bc/types"
11         "github.com/bytom/bytom/protocol/state"
12 )
13
14 type ApplyBlockReply struct {
15         Verification *Verification
16         BestHash     bc.Hash
17 }
18
19 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
20 // and parse the vote and mortgage from the transactions, then save to the checkpoint
21 // the tree of checkpoint will grow with the arrival of new blocks
22 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
23 // the chain module must broadcast the verification
24 func (c *Casper) ApplyBlock(block *types.Block) (*ApplyBlockReply, error) {
25         if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
26                 c.newEpochCh <- block.PreviousBlockHash
27         }
28
29         c.mu.Lock()
30         defer c.mu.Unlock()
31         if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
32                 return &ApplyBlockReply{BestHash: c.bestChain()}, nil
33         }
34
35         target, err := c.applyBlockToCheckpoint(block)
36         if err != nil {
37                 return nil, errors.Wrap(err, "apply block to checkpoint")
38         }
39
40         validators, err := c.Validators(&target.Hash)
41         if err != nil {
42                 return nil, err
43         }
44
45         verification, err := c.applyMyVerification(target, block, validators)
46         if err != nil {
47                 return nil, err
48         }
49
50         affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks, validators)
51         if err != nil {
52                 return nil, err
53         }
54
55         return &ApplyBlockReply{Verification: verification, BestHash: c.bestChain()}, c.saveCheckpoints(affectedCheckpoints)
56 }
57
58 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
59         node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
60         if err != nil {
61                 return nil, err
62         }
63
64         checkpoint := node.Checkpoint
65         if mod := block.Height % consensus.ActiveNetParams.BlocksOfEpoch; mod == 1 {
66                 parent := checkpoint
67                 checkpoint = state.NewCheckpoint(parent)
68                 node.addChild(&treeNode{Checkpoint: checkpoint})
69         }
70
71         return checkpoint, checkpoint.Increase(block)
72 }
73
74 func (c *Casper) checkpointNodeByHash(blockHash bc.Hash) (*treeNode, error) {
75         node, err := c.tree.nodeByHash(blockHash)
76         if err != nil {
77                 logrus.WithFields(logrus.Fields{"err": err, "module": logModule}).Error("fail find checkpoint, start to reorganize checkpoint")
78                 return c.replayCheckpoint(blockHash)
79         }
80
81         return node, nil
82 }
83
84 func (c *Casper) replayCheckpoint(hash bc.Hash) (*treeNode, error) {
85         prevHash := hash
86         var attachBlocks []*types.Block
87         for {
88                 prevBlock, err := c.store.GetBlock(&prevHash)
89                 if err != nil {
90                         return nil, err
91                 }
92
93                 if prevBlock.Height%consensus.ActiveNetParams.BlocksOfEpoch == 0 {
94                         break
95                 }
96
97                 attachBlocks = append([]*types.Block{prevBlock}, attachBlocks...)
98                 prevHash = prevBlock.PreviousBlockHash
99         }
100
101         parent, err := c.tree.nodeByHash(prevHash)
102         if err != nil {
103                 return nil, err
104         }
105
106         node := &treeNode{Checkpoint: state.NewCheckpoint(parent.Checkpoint)}
107         parent.addChild(node)
108         for _, attachBlock := range attachBlocks {
109                 if err := node.Increase(attachBlock); err != nil {
110                         return nil, err
111                 }
112         }
113         return node, nil
114 }
115
116 // applySupLinks copy the block's supLink to the checkpoint
117 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators map[string]*state.Validator) ([]*state.Checkpoint, error) {
118         affectedCheckpoints := []*state.Checkpoint{target}
119         if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
120                 return affectedCheckpoints, nil
121         }
122
123         for _, supLink := range supLinks {
124                 var validVerifications []*Verification
125                 for _, v := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
126                         if validate(v) == nil && c.verifyVerification(v, validators[v.PubKey].Order) == nil {
127                                 validVerifications = append(validVerifications, v)
128                         }
129                 }
130
131                 checkpoints, err := c.addVerificationToCheckpoint(target, validators, validVerifications...)
132                 if err != nil {
133                         return nil, err
134                 }
135
136                 affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
137         }
138         return affectedCheckpoints, nil
139 }
140
141 func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block, validators map[string]*state.Validator) (*Verification, error) {
142         v, err := c.myVerification(target, validators)
143         if err != nil {
144                 return nil, err
145         }
146
147         if v == nil {
148                 return nil, nil
149         }
150
151         block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, v.Signature, validators[v.PubKey].Order)
152         return v, c.store.SaveBlockHeader(&block.BlockHeader)
153 }
154
155 func (c *Casper) myVerification(target *state.Checkpoint, validators map[string]*state.Validator) (*Verification, error) {
156         if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
157                 return nil, nil
158         }
159
160         pubKey := config.CommonConfig.PrivateKey().XPub().String()
161         if _, ok := validators[pubKey]; !ok {
162                 return nil, nil
163         }
164
165         validatorOrder := validators[pubKey].Order
166         if target.ContainsVerification(validatorOrder, nil) {
167                 return nil, nil
168         }
169
170         if source := c.lastJustifiedCheckpoint(target); source != nil {
171                 v := &Verification{
172                         SourceHash:   source.Hash,
173                         TargetHash:   target.Hash,
174                         SourceHeight: source.Height,
175                         TargetHeight: target.Height,
176                         PubKey:       pubKey,
177                 }
178
179                 prvKey := config.CommonConfig.PrivateKey()
180                 if err := v.Sign(*prvKey); err != nil {
181                         return nil, err
182                 }
183
184                 if err := c.verifyVerification(v, validatorOrder); err != nil {
185                         return nil, nil
186                 }
187
188                 return v, nil
189         }
190         return nil, nil
191 }
192
193 func (c *Casper) lastJustifiedCheckpoint(branch *state.Checkpoint) *state.Checkpoint {
194         parent := branch.Parent
195         for parent != nil {
196                 switch parent.Status {
197                 case state.Finalized:
198                         return nil
199                 case state.Justified:
200                         return parent
201                 }
202                 parent = parent.Parent
203         }
204         return nil
205 }
206
207 func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
208         checkpointSet := make(map[bc.Hash]*state.Checkpoint)
209         for _, c := range checkpoints {
210                 checkpointSet[c.Hash] = c
211         }
212
213         var result []*state.Checkpoint
214         for _, c := range checkpointSet {
215                 result = append(result, c)
216         }
217
218         return c.store.SaveCheckpoints(result)
219 }
220
221 func supLinkToVerifications(supLink *types.SupLink, validators map[string]*state.Validator, targetHash bc.Hash, targetHeight uint64) []*Verification {
222         validatorList := make([]*state.Validator, len(validators))
223         for _, validator := range validators {
224                 validatorList[validator.Order] = validator
225         }
226
227         var result []*Verification
228         for i := 0; i < len(validators); i++ {
229                 signature := supLink.Signatures[i]
230                 if len(signature) == 0 {
231                         continue
232                 }
233
234                 result = append(result, &Verification{
235                         SourceHash:   supLink.SourceHash,
236                         TargetHash:   targetHash,
237                         SourceHeight: supLink.SourceHeight,
238                         TargetHeight: targetHeight,
239                         Signature:    signature,
240                         PubKey:       validatorList[i].PubKey,
241                 })
242         }
243         return result
244 }