OSDN Git Service

69abaf013b5e5ebec31bfba5408d5e8238bbbe1a
[bytom/vapor.git] / consensus / consensus / dpos / dpos.go
1 package dpos
2
3 import (
4         "bufio"
5         "encoding/binary"
6         "encoding/json"
7         "errors"
8         "fmt"
9         "io"
10         "math/rand"
11         "os"
12         "path/filepath"
13         "sort"
14         "strings"
15         "sync"
16         "time"
17
18         "github.com/vapor/chain"
19         "github.com/vapor/common"
20         "github.com/vapor/config"
21         "github.com/vapor/consensus"
22         engine "github.com/vapor/consensus/consensus"
23         "github.com/vapor/crypto"
24         "github.com/vapor/protocol/bc"
25         "github.com/vapor/protocol/bc/types"
26         "github.com/vapor/protocol/vm"
27 )
28
29 type Delegate struct {
30         DelegateAddress string `json:"delegate_address"`
31         Votes           uint64 `json:"votes"`
32 }
33
34 type DelegateWrapper struct {
35         delegate []Delegate
36         by       func(p, q *Delegate) bool
37 }
38
39 func (dw DelegateWrapper) Len() int {
40         return len(dw.delegate)
41 }
42 func (dw DelegateWrapper) Swap(i, j int) {
43         dw.delegate[i], dw.delegate[j] = dw.delegate[j], dw.delegate[i]
44 }
45 func (dw DelegateWrapper) Less(i, j int) bool {
46         return dw.by(&dw.delegate[i], &dw.delegate[j])
47 }
48
49 type DelegateInfo struct {
50         Delegates []Delegate `json:"delegates"`
51 }
52
53 func (d *DelegateInfo) ConsensusName() string {
54         return "dpos"
55 }
56
57 const maxConfirmBlockCount = 2
58
59 type IrreversibleBlockInfo struct {
60         heights    []int64
61         hashs      []bc.Hash
62         HeightHash map[int64]bc.Hash
63 }
64
65 func newIrreversibleBlockInfo() *IrreversibleBlockInfo {
66         o := &IrreversibleBlockInfo{}
67         for i := 0; i < maxConfirmBlockCount; i++ {
68                 o.heights = append(o.heights, -1)
69                 o.hashs = append(o.hashs, bc.Hash{})
70         }
71         o.HeightHash = make(map[int64]bc.Hash)
72         return o
73 }
74
75 type DposType struct {
76         c                           chain.Chain
77         vote                        *Vote
78         MaxDelegateNumber           uint64
79         BlockIntervalTime           uint64
80         DposStartHeight             uint64
81         DposStartTime               uint64
82         superForgerAddress          common.Address
83         irreversibleBlockFileName   string
84         irreversibleBlockInfo       IrreversibleBlockInfo
85         lockIrreversibleBlockInfo   sync.Mutex
86         maxIrreversibleCount        int
87         firstIrreversibleThreshold  uint64
88         secondIrreversibleThreshold uint64
89 }
90
91 var GDpos = &DposType{
92         maxIrreversibleCount:        10000,
93         firstIrreversibleThreshold:  90,
94         secondIrreversibleThreshold: 67,
95 }
96
97 func (d *DposType) Init(c chain.Chain, delegateNumber, intervalTime, blockHeight uint64, blockHash bc.Hash) error {
98         d.c = c
99         vote, err := newVote(blockHeight, blockHash)
100         if err != nil {
101                 return err
102         }
103         d.vote = vote
104         d.MaxDelegateNumber = delegateNumber
105         d.BlockIntervalTime = intervalTime
106         d.DposStartHeight = 0
107         address, _ := common.DecodeAddress("vsm1qkm743xmgnvh84pmjchq2s4tnfpgu9ae2f9slep", &consensus.ActiveNetParams)
108         d.superForgerAddress = address
109
110         GDpos.irreversibleBlockFileName = filepath.Join(config.CommonConfig.RootDir, "dpos", "irreversible_block.dat")
111         GDpos.irreversibleBlockInfo = *newIrreversibleBlockInfo()
112         GDpos.ReadIrreversibleBlockInfo(&GDpos.irreversibleBlockInfo)
113         header, _ := c.GetHeaderByHeight(d.DposStartHeight)
114         d.setStartTime(header.Timestamp)
115         return nil
116 }
117
118 func (d *DposType) setStartTime(t uint64) {
119         d.DposStartTime = t
120 }
121
122 func (d *DposType) IsMining(address common.Address, t uint64) (interface{}, error) {
123
124         header := d.c.BestBlockHeader()
125         currentLoopIndex := d.GetLoopIndex(t)
126         currentDelegateIndex := d.GetDelegateIndex(t)
127         prevLoopIndex := d.GetLoopIndex(header.Timestamp)
128         prevDelegateIndex := d.GetDelegateIndex(header.Timestamp)
129         if currentLoopIndex > prevLoopIndex {
130                 delegateInfo := d.GetNextDelegates(t)
131                 cDelegateInfo := delegateInfo.(*DelegateInfo)
132                 if uint64(len(cDelegateInfo.Delegates)) < currentDelegateIndex+1 {
133                         return nil, errors.New("Out of the block node list")
134                 }
135                 if cDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
136                         return delegateInfo, nil
137                 }
138                 return nil, errors.New("Is not the current mining node")
139         } else if currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex {
140                 currentDelegateInfo, err := d.GetBlockDelegates(header)
141                 if err != nil {
142                         return nil, err
143                 }
144                 if currentDelegateIndex+1 > uint64(len(currentDelegateInfo.Delegates)) {
145                         return nil, errors.New("Out of the block node list")
146                 } else if currentDelegateInfo.Delegates[currentDelegateIndex].DelegateAddress == address.EncodeAddress() {
147                         return nil, nil
148                 } else {
149                         return nil, errors.New("Is not the current mining node")
150                 }
151         } else {
152                 return nil, errors.New("Time anomaly")
153         }
154 }
155
156 func (d *DposType) ProcessRegister(delegateAddress string, delegateName string, hash bc.Hash, height uint64) bool {
157         return d.vote.ProcessRegister(delegateAddress, delegateName, hash, height)
158 }
159
160 func (d *DposType) ProcessVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
161         return d.vote.ProcessVote(voterAddress, delegates, hash, height)
162 }
163
164 func (d *DposType) ProcessCancelVote(voterAddress string, delegates []string, hash bc.Hash, height uint64) bool {
165         return d.vote.ProcessCancelVote(voterAddress, delegates, hash, height)
166 }
167
168 func (d *DposType) UpdateAddressBalance(addressBalance []engine.AddressBalance) {
169         d.vote.UpdateAddressBalance(addressBalance)
170 }
171
172 func (d *DposType) GetLoopIndex(time uint64) uint64 {
173         if time < d.DposStartTime {
174                 return 0
175         }
176         return (time - d.DposStartTime) / (d.MaxDelegateNumber * d.BlockIntervalTime)
177 }
178
179 func (d *DposType) GetDelegateIndex(time uint64) uint64 {
180         if time < d.DposStartTime {
181                 return 0
182         }
183         return (time - d.DposStartTime) % (d.MaxDelegateNumber * d.BlockIntervalTime) / d.BlockIntervalTime
184 }
185
186 func (d *DposType) GetNextDelegates(t uint64) interface{} {
187         delegates := d.vote.GetTopDelegateInfo(config.CommonConfig.Consensus.MinVoterBalance, d.MaxDelegateNumber-1)
188         delegate := Delegate{
189                 DelegateAddress: d.superForgerAddress.EncodeAddress(),
190                 Votes:           7,
191         }
192         delegates = append(delegates, delegate)
193         delegateInfo := DelegateInfo{}
194         delegateInfo.Delegates = SortDelegate(delegates, t)
195         return &delegateInfo
196 }
197
198 func (d *DposType) GetBlockDelegates(header *types.BlockHeader) (*DelegateInfo, error) {
199         loopIndex := d.GetLoopIndex(header.Timestamp)
200         for {
201                 preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
202                 if err != nil {
203                         return nil, err
204                 }
205                 if header.Height == d.DposStartHeight || d.GetLoopIndex(preHeader.Timestamp) < loopIndex {
206                         block, err := d.c.GetBlockByHeight(header.Height)
207                         if err != nil {
208                                 return nil, err
209                         }
210                         delegateInfo, err := d.GetBlockDelegate(block)
211                         if err != nil {
212                                 return nil, err
213                         }
214                         return delegateInfo, nil
215                 }
216                 header = preHeader
217         }
218 }
219
220 func (d *DposType) GetBlockDelegate(block *types.Block) (*DelegateInfo, error) {
221         tx := block.Transactions[0]
222         if len(tx.TxData.Inputs) == 1 && tx.TxData.Inputs[0].InputType() == types.CoinbaseInputType {
223                 msg := &DposMsg{}
224                 if err := json.Unmarshal(tx.TxData.ReferenceData, msg); err != nil {
225                         return nil, err
226                 }
227                 if msg.Type == vm.OP_DELEGATE {
228                         delegateInfo := &DelegateInfoList{}
229                         if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
230                                 return nil, err
231                         }
232                         return &delegateInfo.Delegate, nil
233                 }
234
235         }
236         return nil, errors.New("The first transaction is not a coinbase transaction")
237 }
238
239 func (d *DposType) CheckCoinbase(tx types.TxData, t uint64, Height uint64) error {
240         msg := &DposMsg{}
241         if err := json.Unmarshal(tx.ReferenceData, msg); err != nil {
242                 return err
243         }
244         if msg.Type == vm.OP_DELEGATE {
245                 delegateInfo := &DelegateInfoList{}
246                 if err := json.Unmarshal(msg.Data, delegateInfo); err != nil {
247                         return err
248                 }
249                 buf := [8]byte{}
250                 binary.LittleEndian.PutUint64(buf[:], t)
251
252                 if !delegateInfo.Xpub.Verify(buf[:], delegateInfo.SigTime) {
253                         return errors.New("CheckBlock CheckCoinbase: Verification signature error")
254                 }
255                 var (
256                         address common.Address
257                         err     error
258                 )
259                 address, err = common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
260                 if err != nil {
261                         return err
262                 }
263                 derivedPK := delegateInfo.Xpub.PublicKey()
264                 pubHash := crypto.Ripemd160(derivedPK)
265
266                 addressDet, err := common.NewAddressWitnessPubKeyHash(pubHash, &consensus.ActiveNetParams)
267                 if err != nil {
268                         return err
269                 }
270
271                 if addressDet.EncodeAddress() == address.EncodeAddress() {
272                         return nil
273                 }
274         }
275         return errors.New("CheckBlock CheckCoinbase error")
276 }
277
278 func (d *DposType) CheckBlockHeader(header types.BlockHeader) error {
279         blockT := time.Unix(int64(header.Timestamp), 0)
280
281         if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
282                 return errors.New("block time is error")
283         }
284
285         if header.Height > d.DposStartHeight {
286                 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
287                 d.setStartTime(header.Timestamp)
288         }
289
290         preHeader, err := d.c.GetHeaderByHash(&header.PreviousBlockHash)
291         if err != nil {
292                 return err
293         }
294
295         currentLoopIndex := d.GetLoopIndex(header.Timestamp)
296         currentDelegateIndex := d.GetDelegateIndex(header.Timestamp)
297         prevLoopIndex := d.GetLoopIndex(preHeader.Timestamp)
298         prevDelegateIndex := d.GetDelegateIndex(preHeader.Timestamp)
299         if currentLoopIndex > prevLoopIndex ||
300                 (currentLoopIndex == prevLoopIndex && currentDelegateIndex > prevDelegateIndex) {
301                 return nil
302         }
303
304         return errors.New("DPoS CheckBlockHeader error")
305 }
306
307 func (d *DposType) CheckBlock(block types.Block, fIsCheckDelegateInfo bool) error {
308         if block.Height > d.DposStartHeight {
309                 header, _ := d.c.GetHeaderByHeight(d.DposStartHeight)
310                 d.setStartTime(header.Timestamp)
311         }
312
313         blockT := time.Unix(int64(block.Timestamp), 0)
314         if blockT.Sub(time.Now()).Seconds() > float64(d.BlockIntervalTime) {
315                 return errors.New("block time is error")
316         }
317         if err := d.CheckCoinbase(block.Transactions[0].TxData, block.Timestamp, block.Height); err != nil {
318                 return err
319         }
320
321         preBlock, err := d.c.GetBlockByHash(&block.PreviousBlockHash)
322         if err != nil {
323                 return err
324         }
325
326         currentLoopIndex := d.GetLoopIndex(block.Timestamp)
327         currentDelegateIndex := d.GetDelegateIndex(block.Timestamp)
328         prevLoopIndex := d.GetLoopIndex(preBlock.Timestamp)
329         prevDelegateIndex := d.GetDelegateIndex(preBlock.Timestamp)
330
331         delegateInfo := &DelegateInfo{}
332
333         if currentLoopIndex < prevLoopIndex {
334                 return errors.New("Block time exception")
335         } else if currentLoopIndex > prevLoopIndex {
336                 if fIsCheckDelegateInfo {
337                         if err := d.CheckBlockDelegate(block); err != nil {
338                                 return err
339                         }
340                         d.ProcessIrreversibleBlock(block.Height, block.Hash())
341                 }
342                 delegateInfo, err = d.GetBlockDelegate(&block)
343                 if err != nil {
344                         return err
345                 }
346         } else {
347                 if currentDelegateIndex < prevDelegateIndex {
348                         return errors.New("Block time exception")
349                 }
350
351                 delegateInfo, err = d.GetBlockDelegates(&preBlock.BlockHeader)
352                 if err != nil {
353                         return err
354                 }
355         }
356
357         delegateAddress := d.getBlockForgerAddress(block)
358         if currentDelegateIndex < uint64(len(delegateInfo.Delegates)) &&
359                 delegateInfo.Delegates[currentDelegateIndex].DelegateAddress == delegateAddress.EncodeAddress() {
360                 return nil
361         }
362         h := block.Hash()
363         return fmt.Errorf("CheckBlock GetDelegateID blockhash:%s error", h.String())
364 }
365
366 func (d *DposType) CheckBlockDelegate(block types.Block) error {
367         delegateInfo, err := d.GetBlockDelegate(&block)
368         if err != nil {
369                 return err
370         }
371         nextDelegateInfoInterface := d.GetNextDelegates(block.Timestamp)
372         nextDelegateInfo := nextDelegateInfoInterface.(*DelegateInfo)
373         if len(delegateInfo.Delegates) != len(nextDelegateInfo.Delegates) {
374                 return errors.New("The delegates num is not correct in block")
375         }
376         for index, v := range delegateInfo.Delegates {
377                 if v.DelegateAddress != nextDelegateInfo.Delegates[index].DelegateAddress {
378                         return errors.New("The delegates address is not correct in block")
379                 }
380         }
381
382         return nil
383 }
384
385 func (d *DposType) ProcessIrreversibleBlock(height uint64, hash bc.Hash) {
386         d.lockIrreversibleBlockInfo.Lock()
387         defer d.lockIrreversibleBlockInfo.Unlock()
388         i := 0
389         for i = maxConfirmBlockCount - 1; i >= 0; i-- {
390                 if d.irreversibleBlockInfo.heights[i] < 0 || int64(height) < d.irreversibleBlockInfo.heights[i] {
391                         d.irreversibleBlockInfo.heights[i] = -1
392                 } else {
393                         level := (height - uint64(d.irreversibleBlockInfo.heights[i])) * 100
394                         if level >= d.MaxDelegateNumber*d.firstIrreversibleThreshold {
395                                 d.AddIrreversibleBlock(int64(height), hash)
396                         } else if level >= d.MaxDelegateNumber*d.secondIrreversibleThreshold {
397                                 if i == maxConfirmBlockCount-1 {
398                                         d.AddIrreversibleBlock(int64(height), hash)
399                                         for k := 0; k < maxConfirmBlockCount-1; k++ {
400                                                 d.irreversibleBlockInfo.heights[k] = d.irreversibleBlockInfo.heights[k+1]
401                                                 d.irreversibleBlockInfo.hashs[k] = d.irreversibleBlockInfo.hashs[k+1]
402                                         }
403                                         d.irreversibleBlockInfo.heights[i] = int64(height)
404                                         d.irreversibleBlockInfo.hashs[i] = hash
405                                         return
406                                 } else {
407                                         d.irreversibleBlockInfo.heights[i+1] = int64(height)
408                                         d.irreversibleBlockInfo.hashs[i+1] = hash
409                                         return
410                                 }
411
412                         }
413                         for k := 0; k < maxConfirmBlockCount; k++ {
414                                 d.irreversibleBlockInfo.heights[k] = -1
415                         }
416                         d.irreversibleBlockInfo.heights[0] = int64(height)
417                         d.irreversibleBlockInfo.hashs[0] = hash
418                         return
419
420                 }
421         }
422         if i < 0 {
423                 d.irreversibleBlockInfo.heights[0] = int64(height)
424                 d.irreversibleBlockInfo.hashs[0] = hash
425         }
426 }
427
428 func (d *DposType) getBlockForgerAddress(block types.Block) common.Address {
429         tx := block.Transactions[0].TxData
430
431         if len(tx.Inputs) == 1 && tx.Inputs[0].InputType() == types.CoinbaseInputType {
432                 address, err := common.NewAddressWitnessPubKeyHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
433                 if err != nil {
434                         address, err := common.NewAddressWitnessScriptHash(tx.Outputs[0].ControlProgram[2:], &consensus.ActiveNetParams)
435                         if err != nil {
436                                 return nil
437                         }
438                         return address
439                 }
440                 return address
441         }
442
443         return nil
444 }
445
446 func (d *DposType) IsValidBlockCheckIrreversibleBlock(height uint64, hash bc.Hash) error {
447         d.lockIrreversibleBlockInfo.Lock()
448         defer d.lockIrreversibleBlockInfo.Unlock()
449
450         if h, ok := d.irreversibleBlockInfo.HeightHash[int64(height)]; ok {
451                 if h != hash {
452                         return fmt.Errorf("invalid block[%d:%s]", height, hash.String())
453                 }
454         }
455
456         return nil
457 }
458
459 func (d *DposType) ReadIrreversibleBlockInfo(info *IrreversibleBlockInfo) error {
460         f, err := os.Open(d.irreversibleBlockFileName)
461         if err != nil {
462                 return err
463         }
464         defer f.Close()
465         buf := bufio.NewReader(f)
466         for {
467                 line, err := buf.ReadString('\n')
468                 if err != nil {
469                         if err == io.EOF {
470                                 return nil
471                         }
472                         return err
473                 }
474                 line = strings.TrimSpace(line)
475                 var height int64
476                 var hashString string
477                 n, err := fmt.Sscanf(line, "%d;%s\n", &height, &hashString)
478                 if err != nil || n != 2 {
479                         return errors.New("parse error for ReadIrreversibleBlockInfo ")
480                 }
481                 var hash bc.Hash
482                 if err := hash.UnmarshalText([]byte(hashString)); err != nil {
483                         return err
484                 }
485                 d.AddIrreversibleBlock(height, hash)
486         }
487 }
488
489 type Int64Slice []int64
490
491 func (a Int64Slice) Len() int {
492         return len(a)
493 }
494 func (a Int64Slice) Swap(i, j int) {
495         a[i], a[j] = a[j], a[i]
496 }
497 func (a Int64Slice) Less(i, j int) bool {
498         return a[i] < a[j]
499 }
500
501 func (d *DposType) WriteIrreversibleBlockInfo() error {
502         if len(d.irreversibleBlockInfo.HeightHash) == 0 {
503                 return nil
504         }
505
506         f, err := os.Create(d.irreversibleBlockFileName)
507         if err != nil {
508                 return err
509         }
510         defer f.Close()
511         w := bufio.NewWriter(f)
512         var keys []int64
513         for k := range d.irreversibleBlockInfo.HeightHash {
514                 keys = append(keys, k)
515         }
516
517         sort.Sort(Int64Slice(keys))
518
519         for _, k := range keys {
520                 data, _ := d.irreversibleBlockInfo.HeightHash[k].MarshalText()
521                 line := fmt.Sprintf("%d;%s\n", k, string(data))
522                 w.WriteString(line)
523         }
524
525         if err := w.Flush(); err != nil {
526                 return err
527         }
528
529         return nil
530 }
531
532 func (d *DposType) AddIrreversibleBlock(height int64, hash bc.Hash) {
533         for k, _ := range d.irreversibleBlockInfo.HeightHash {
534                 if len(d.irreversibleBlockInfo.HeightHash) > d.maxIrreversibleCount {
535                         delete(d.irreversibleBlockInfo.HeightHash, k)
536                 } else {
537                         break
538                 }
539         }
540         d.irreversibleBlockInfo.HeightHash[height] = hash
541         d.vote.DeleteInvalidVote(uint64(height))
542 }
543
544 func (d *DposType) GetSuperForgerAddress() common.Address {
545         return d.superForgerAddress
546 }
547
548 func (d *DposType) GetIrreversibleBlock() {
549
550 }
551
552 func (d *DposType) GetOldBlockHeight() uint64 {
553         return d.vote.GetOldBlockHeight()
554 }
555
556 func (d *DposType) GetOldBlockHash() bc.Hash {
557         return d.vote.GetOldBlockHash()
558 }
559
560 func (d *DposType) ListDelegates() map[string]string {
561         return d.vote.ListDelegates()
562 }
563
564 func (d *DposType) GetDelegateVotes(delegate string) uint64 {
565         return d.vote.GetDelegateVotes(delegate)
566 }
567
568 func (d *DposType) GetDelegateVoters(delegate string) []string {
569         return d.vote.GetDelegateVoters(delegate)
570 }
571
572 func (d *DposType) GetDelegate(name string) string {
573         return d.vote.GetDelegate(name)
574
575 }
576
577 func (d *DposType) GetDelegateName(address string) string {
578         return d.vote.GetDelegateName(address)
579 }
580
581 func (d *DposType) GetAddressBalance(address string) uint64 {
582         return d.vote.GetAddressBalance(address)
583 }
584
585 func (d *DposType) GetVotedDelegates(voter string) []string {
586         return d.vote.GetVotedDelegates(voter)
587 }
588
589 func (d *DposType) HaveVote(voter, delegate string) bool {
590         return d.vote.HaveVote(voter, delegate)
591 }
592
593 func (d *DposType) HaveDelegate(name, delegate string) bool {
594         return d.vote.HaveDelegate(name, delegate)
595 }
596
597 func (d *DposType) Finish() error {
598         header := d.c.BestBlockHeader()
599         if err := d.vote.Store(header.Height, header.Hash()); err != nil {
600                 return err
601         }
602
603         if err := d.WriteIrreversibleBlockInfo(); err != nil {
604                 return err
605         }
606
607         return nil
608 }
609
610 func SortDelegate(delegates []Delegate, t uint64) []Delegate {
611         var result []Delegate
612         r := getRand(uint64(len(delegates)), int64(t))
613         for _, i := range r {
614                 result = append(result, delegates[i])
615         }
616         return result
617 }
618
619 func getRand(num uint64, seed int64) []uint64 {
620         rand.Seed(seed)
621         var r []uint64
622         s := make(map[uint64]bool)
623         for {
624                 v := rand.Uint64()
625                 v %= num
626                 if _, ok := s[v]; ok {
627                         continue
628                 }
629                 s[v] = true
630                 r = append(r, v)
631                 if uint64(len(r)) >= num {
632                         break
633                 }
634         }
635
636         return r
637 }