OSDN Git Service

edit dup sup link struct (#1988)
[bytom/bytom.git] / protocol / apply_block.go
1 package protocol
2
3 import (
4         "encoding/hex"
5
6         "github.com/sirupsen/logrus"
7
8         "github.com/bytom/bytom/config"
9         "github.com/bytom/bytom/consensus"
10         "github.com/bytom/bytom/errors"
11         "github.com/bytom/bytom/math/checked"
12         "github.com/bytom/bytom/protocol/bc"
13         "github.com/bytom/bytom/protocol/bc/types"
14         "github.com/bytom/bytom/protocol/state"
15 )
16
17 type applyBlockReply struct {
18         verification *Verification
19         bestHash     bc.Hash
20 }
21
22 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
23 // and parse the vote and mortgage from the transactions, then save to the checkpoint
24 // the tree of checkpoint will grow with the arrival of new blocks
25 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
26 // the chain module must broadcast the verification
27 func (c *Casper) ApplyBlock(block *types.Block) (*applyBlockReply, error) {
28         if block.Height%consensus.ActiveNetParams.BlocksOfEpoch == 1 {
29                 c.newEpochCh <- block.PreviousBlockHash
30         }
31
32         c.mu.Lock()
33         defer c.mu.Unlock()
34
35         if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
36                 return &applyBlockReply{bestHash: c.bestChain()}, nil
37         }
38
39         target, err := c.applyBlockToCheckpoint(block)
40         if err != nil {
41                 return nil, errors.Wrap(err, "apply block to checkpoint")
42         }
43
44         if err := applyTransactions(target, block.Transactions); err != nil {
45                 return nil, err
46         }
47
48         validators, err := c.Validators(&target.Hash)
49         if err != nil {
50                 return nil, err
51         }
52
53         verification, err := c.applyMyVerification(target, block, validators)
54         if err != nil {
55                 return nil, err
56         }
57
58         affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks, validators)
59         if err != nil {
60                 return nil, err
61         }
62
63         return &applyBlockReply{verification: verification, bestHash: c.bestChain()}, c.saveCheckpoints(affectedCheckpoints)
64 }
65
66 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
67         node, err := c.checkpointNodeByHash(block.PreviousBlockHash)
68         if err != nil {
69                 return nil, err
70         }
71
72         checkpoint := node.checkpoint
73         if mod := block.Height % consensus.ActiveNetParams.BlocksOfEpoch; mod == 1 {
74                 parent := checkpoint
75                 checkpoint = state.NewCheckpoint(parent)
76                 node.addChild(&treeNode{checkpoint: checkpoint})
77         } else if mod == 0 {
78                 checkpoint.Status = state.Unjustified
79                 if err := checkpoint.ApplyFederationReward(); err != nil {
80                         return nil, err
81                 }
82         }
83
84         if err := checkpoint.ApplyValidatorReward(block); err != nil {
85                 return nil, err
86         }
87
88         return checkpoint, checkpoint.Increase(block)
89 }
90
91 func (c *Casper) checkpointNodeByHash(blockHash bc.Hash) (*treeNode, error) {
92         node, err := c.tree.nodeByHash(blockHash)
93         if err != nil {
94                 logrus.WithField("err", err).Error("fail find checkpoint, start to reorganize checkpoint")
95
96                 return c.replayCheckpoint(blockHash)
97         }
98
99         return node, nil
100 }
101
102 func (c *Casper) replayCheckpoint(hash bc.Hash) (*treeNode, error) {
103         prevHash := hash
104         var attachBlocks []*types.Block
105         for {
106                 prevBlock, err := c.store.GetBlock(&prevHash)
107                 if err != nil {
108                         return nil, err
109                 }
110
111                 if prevBlock.Height%consensus.ActiveNetParams.BlocksOfEpoch == 0 {
112                         break
113                 }
114
115                 attachBlocks = append([]*types.Block{prevBlock}, attachBlocks...)
116                 prevHash = prevBlock.PreviousBlockHash
117         }
118
119         parent, err := c.tree.nodeByHash(prevHash)
120         if err != nil {
121                 return nil, err
122         }
123
124         node := &treeNode{checkpoint: state.NewCheckpoint(parent.checkpoint)}
125         parent.addChild(node)
126         for _, attachBlock := range attachBlocks {
127                 if err := applyTransactions(node.checkpoint, attachBlock.Transactions); err != nil {
128                         return nil, err
129                 }
130
131                 if err := node.checkpoint.ApplyValidatorReward(attachBlock); err != nil {
132                         return nil, err
133                 }
134
135                 if err := node.checkpoint.Increase(attachBlock); err != nil {
136                         return nil, err
137                 }
138         }
139         return node, nil
140 }
141
142 func applyTransactions(target *state.Checkpoint, transactions []*types.Tx) error {
143         for _, tx := range transactions {
144                 for _, input := range tx.Inputs {
145                         if vetoInput, ok := input.TypedInput.(*types.VetoInput); ok {
146                                 if err := processVeto(vetoInput, target); err != nil {
147                                         return err
148                                 }
149                         }
150                 }
151
152                 for _, output := range tx.Outputs {
153                         if _, ok := output.TypedOutput.(*types.VoteOutput); ok {
154                                 if err := processVote(output, target); err != nil {
155                                         return err
156                                 }
157                         }
158                 }
159         }
160         return nil
161 }
162
163 // applySupLinks copy the block's supLink to the checkpoint
164 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators map[string]*state.Validator) ([]*state.Checkpoint, error) {
165         affectedCheckpoints := []*state.Checkpoint{target}
166         if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
167                 return nil, nil
168         }
169
170         for _, supLink := range supLinks {
171                 var validVerifications []*Verification
172                 for _, v := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
173                         if validate(v) == nil && c.verifyVerification(v, validators[v.PubKey].Order, true) == nil {
174                                 validVerifications = append(validVerifications, v)
175                         }
176                 }
177
178                 checkpoints, err := c.addVerificationToCheckpoint(target, validators, validVerifications...)
179                 if err != nil {
180                         return nil, err
181                 }
182
183                 affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
184         }
185         return affectedCheckpoints, nil
186 }
187
188 func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block, validators map[string]*state.Validator) (*Verification, error) {
189         v, err := c.myVerification(target, validators)
190         if err != nil {
191                 return nil, err
192         }
193
194         if v == nil {
195                 return nil, nil
196         }
197
198         block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, v.Signature, validators[v.PubKey].Order)
199         return v, c.store.SaveBlockHeader(&block.BlockHeader)
200 }
201
202 func (c *Casper) myVerification(target *state.Checkpoint, validators map[string]*state.Validator) (*Verification, error) {
203         if target.Height%consensus.ActiveNetParams.BlocksOfEpoch != 0 {
204                 return nil, nil
205         }
206
207         pubKey := config.CommonConfig.PrivateKey().XPub().String()
208         if _, ok := validators[pubKey]; !ok {
209                 return nil, nil
210         }
211
212         validatorOrder := validators[pubKey].Order
213         if target.ContainsVerification(validatorOrder, nil) {
214                 return nil, nil
215         }
216
217         if source := c.lastJustifiedCheckpoint(target); source != nil {
218                 v := &Verification{
219                         SourceHash:   source.Hash,
220                         TargetHash:   target.Hash,
221                         SourceHeight: source.Height,
222                         TargetHeight: target.Height,
223                         PubKey:       pubKey,
224                 }
225
226                 prvKey := config.CommonConfig.PrivateKey()
227                 if err := v.Sign(*prvKey); err != nil {
228                         return nil, err
229                 }
230
231                 if err := c.verifyVerification(v, validatorOrder, false); err != nil {
232                         return nil, nil
233                 }
234
235                 return v, nil
236         }
237         return nil, nil
238 }
239
240 func processVeto(input *types.VetoInput, checkpoint *state.Checkpoint) error {
241         pubKey := hex.EncodeToString(input.Vote)
242         voteNum := checkpoint.Votes[pubKey]
243         voteNum, ok := checked.SubUint64(voteNum, input.Amount)
244         if !ok {
245                 return checked.ErrOverflow
246         }
247
248         checkpoint.Votes[pubKey] = voteNum
249         return nil
250 }
251
252 func processVote(output *types.TxOutput, checkpoint *state.Checkpoint) error {
253         voteOutput := output.TypedOutput.(*types.VoteOutput)
254         pubKey := hex.EncodeToString(voteOutput.Vote)
255         voteNum := checkpoint.Votes[pubKey]
256         voteNum, ok := checked.AddUint64(voteNum, output.Amount)
257         if !ok {
258                 return checked.ErrOverflow
259         }
260
261         checkpoint.Votes[pubKey] = voteNum
262         return nil
263 }
264
265 func (c *Casper) lastJustifiedCheckpoint(branch *state.Checkpoint) *state.Checkpoint {
266         parent := branch.Parent
267         for parent != nil {
268                 switch parent.Status {
269                 case state.Finalized:
270                         return nil
271                 case state.Justified:
272                         return parent
273                 }
274                 parent = parent.Parent
275         }
276         return nil
277 }
278
279 func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
280         checkpointSet := make(map[bc.Hash]*state.Checkpoint)
281         for _, c := range checkpoints {
282                 checkpointSet[c.Hash] = c
283         }
284
285         var result []*state.Checkpoint
286         for _, c := range checkpointSet {
287                 result = append(result, c)
288         }
289
290         return c.store.SaveCheckpoints(result)
291 }
292
293 func supLinkToVerifications(supLink *types.SupLink, validators map[string]*state.Validator, targetHash bc.Hash, targetHeight uint64) []*Verification {
294         validatorList := make([]*state.Validator, len(validators))
295         for _, validator := range validators {
296                 validatorList[validator.Order] = validator
297         }
298
299         var result []*Verification
300         for i := 0; i < len(validators); i++ {
301                 signature := supLink.Signatures[i]
302                 if len(signature) == 0 {
303                         continue
304                 }
305
306                 result = append(result, &Verification{
307                         SourceHash:   supLink.SourceHash,
308                         TargetHash:   targetHash,
309                         SourceHeight: supLink.SourceHeight,
310                         TargetHeight: targetHeight,
311                         Signature:    signature,
312                         PubKey:       validatorList[i].PubKey,
313                 })
314         }
315         return result
316 }