github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/consense/poa/snapshot.go (about) 1 package poa 2 3 import ( 4 "bytes" 5 //"encoding/json" 6 7 "github.com/sixexorg/magnetic-ring/common" 8 "github.com/sixexorg/magnetic-ring/core/orgchain/types" 9 //"github.com/ethereum/go-ethereum/ethdb" 10 //"github.com/ethereum/go-ethereum/params" 11 lru "github.com/hashicorp/golang-lru" 12 "github.com/sixexorg/magnetic-ring/config" 13 "fmt" 14 ) 15 16 type Snapshot struct { 17 config *config.CliqueConfig // 18 sigcache *lru.ARCCache // 19 20 Number uint64 `json:"number"` 21 Hash common.Hash `json:"hash"` 22 Signers map[common.Address]struct{} `json:"signers"` 23 Recents map[uint64]common.Address `json:"recents"` 24 } 25 26 func newSnapshot(config *config.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot { 27 snap := &Snapshot{ 28 config: config, 29 sigcache: sigcache, 30 Number: number, 31 Hash: hash, 32 Signers: make(map[common.Address]struct{}), 33 Recents: make(map[uint64]common.Address), 34 } 35 for _, signer := range signers { 36 snap.Signers[signer] = struct{}{} 37 } 38 return snap 39 } 40 41 func (s *Snapshot) copy() *Snapshot { 42 cpy := &Snapshot{ 43 config: s.config, 44 sigcache: s.sigcache, 45 Number: s.Number, 46 Hash: s.Hash, 47 Signers: make(map[common.Address]struct{}), 48 Recents: make(map[uint64]common.Address), 49 } 50 51 for signer := range s.Signers { 52 cpy.Signers[signer] = struct{}{} 53 } 54 55 for block, signer := range s.Recents { 56 cpy.Recents[block] = signer 57 } 58 59 return cpy 60 } 61 62 func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) { 63 if len(headers) == 0 { 64 return s, nil 65 } 66 67 for i := 0; i < len(headers)-1; i++ { 68 if headers[i+1].Height != headers[i].Height+1 { 69 return nil, errInvalidVotingChain 70 } 71 } 72 73 if headers[0].Height != s.Number+1 { 74 return nil, errInvalidVotingChain 75 } 76 77 snap := s.copy() 78 79 for _, header := range headers { 80 number := header.Height 81 if limit := uint64(len(snap.Signers)/2 + 1); number >= limit { 82 delete(snap.Recents, number-limit) 83 } 84 85 //signer, err := ecrecover(header, s.sigcache) 86 signer := header.Coinbase 87 //if err != nil { 88 // return nil, err 89 //} 90 91 if _, ok := snap.Signers[signer]; !ok { 92 for a, _ := range snap.Signers{ 93 fmt.Println("-------------!!!!!!!!!!!!!!!!!!!!!!!!!", a.ToString()) 94 } 95 fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!", header.Height, signer.ToString()) 96 return nil, errUnauthorized 97 } 98 99 for _, recent := range snap.Recents { 100 if recent == signer { 101 return nil, errUnauthorized 102 } 103 } 104 105 snap.Recents[number] = signer 106 } 107 snap.Number += uint64(len(headers)) 108 snap.Hash = headers[len(headers)-1].Hash() 109 110 return snap, nil 111 } 112 113 // signers retrieves the list of authorized signers in ascending order. 114 func (s *Snapshot) signers() []common.Address { 115 signers := make([]common.Address, 0, len(s.Signers)) 116 for signer := range s.Signers { 117 signers = append(signers, signer) 118 } 119 for i := 0; i < len(signers); i++ { 120 for j := i + 1; j < len(signers); j++ { 121 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 122 signers[i], signers[j] = signers[j], signers[i] 123 } 124 } 125 } 126 return signers 127 } 128 129 // inturn returns if a signer at a given block height is in-turn or not. 130 func (s *Snapshot) inturn(number uint64, signer common.Address) bool { 131 signers, offset := s.signers(), 0 132 for offset < len(signers) && signers[offset] != signer { 133 offset++ 134 } 135 return (number % uint64(len(signers))) == uint64(offset) 136 }