OSDN Git Service

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