OSDN Git Service

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