github.com/gochain-io/gochain@v2.2.26+incompatible/consensus/clique/snapshot.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package clique 18 19 import ( 20 "bytes" 21 "context" 22 "encoding/json" 23 "fmt" 24 25 "github.com/gochain-io/gochain/common" 26 "github.com/gochain-io/gochain/core/types" 27 "github.com/gochain-io/gochain/params" 28 "github.com/hashicorp/golang-lru" 29 ) 30 31 // Vote represents a single vote that an authorized signer made to modify the 32 // list of authorizations. 33 type Vote struct { 34 Signer common.Address `json:"signer"` // Authorized signer that cast this vote 35 Block uint64 `json:"block"` // Block number the vote was cast in (expire old votes) 36 Address common.Address `json:"address"` // Account being voted on to change its authorization 37 Authorize bool `json:"authorize"` // Whether to authorize or deauthorize the voted account 38 } 39 40 // Tally is a simple vote tally to keep the current score of votes. Votes that 41 // go against the proposal aren't counted since it's equivalent to not voting. 42 type Tally struct { 43 Authorize bool `json:"authorize"` // Whether the vote is about authorizing or kicking someone 44 Votes int `json:"votes"` // Number of votes until now wanting to pass the proposal 45 } 46 47 // Snapshot is the state of the authorization voting at a given point in time. 48 type Snapshot struct { 49 config *params.CliqueConfig // Consensus engine parameters to fine tune behavior 50 sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover 51 52 Number uint64 `json:"number"` // Block number where the snapshot was created 53 Hash common.Hash `json:"hash"` // Block hash where the snapshot was created 54 Signers map[common.Address]uint64 `json:"signers"` // Each authorized signer at this moment and their most recently signed block 55 Voters map[common.Address]struct{} `json:"voters"` // Set of authorized voters at this moment 56 Votes []*Vote `json:"votes"` // List of votes cast in chronological order 57 Tally map[common.Address]Tally `json:"tally"` // Current vote tally to avoid recalculating 58 } 59 60 // newGenesisSnapshot creates a new snapshot with the specified startup parameters. This 61 // method does not initialize the signers most recently signed blocks, so only ever use if for 62 // the genesis block. 63 func newGenesisSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers, voters []common.Address) *Snapshot { 64 snap := &Snapshot{ 65 config: config, 66 sigcache: sigcache, 67 Number: number, 68 Hash: hash, 69 Signers: make(map[common.Address]uint64), 70 Voters: make(map[common.Address]struct{}), 71 Tally: make(map[common.Address]Tally), 72 } 73 for _, signer := range signers { 74 snap.Signers[signer] = 0 75 } 76 for _, voter := range voters { 77 snap.Voters[voter] = struct{}{} 78 } 79 return snap 80 } 81 82 // loadSnapshot loads an existing snapshot from the database. 83 func loadSnapshot(config *params.CliqueConfig, sigcache *lru.ARCCache, db common.Database, hash common.Hash) (*Snapshot, error) { 84 blob, err := db.GlobalTable().Get(append([]byte("clique-"), hash[:]...)) 85 if err != nil { 86 return nil, err 87 } 88 snap := new(Snapshot) 89 if err := json.Unmarshal(blob, snap); err != nil { 90 return nil, err 91 } 92 snap.config = config 93 snap.sigcache = sigcache 94 95 return snap, nil 96 } 97 98 // store inserts the snapshot into the database. 99 func (s *Snapshot) store(db common.Database) error { 100 blob, err := json.Marshal(s) 101 if err != nil { 102 return err 103 } 104 return db.GlobalTable().Put(append([]byte("clique-"), s.Hash[:]...), blob) 105 } 106 107 // copy creates a deep copy of the snapshot, though not the individual votes. 108 func (s *Snapshot) copy() *Snapshot { 109 cpy := &Snapshot{ 110 config: s.config, 111 sigcache: s.sigcache, 112 Number: s.Number, 113 Hash: s.Hash, 114 Signers: make(map[common.Address]uint64), 115 Voters: make(map[common.Address]struct{}), 116 Votes: make([]*Vote, len(s.Votes)), 117 Tally: make(map[common.Address]Tally), 118 } 119 for signer, signed := range s.Signers { 120 cpy.Signers[signer] = signed 121 } 122 for voter := range s.Voters { 123 cpy.Voters[voter] = struct{}{} 124 } 125 for address, tally := range s.Tally { 126 cpy.Tally[address] = tally 127 } 128 copy(cpy.Votes, s.Votes) 129 130 return cpy 131 } 132 133 // validVote returns whether it makes sense to cast the specified vote in the 134 // given snapshot context (e.g. don't try to add an already authorized voter or 135 // remove an not authorized signer). 136 func (s *Snapshot) validVote(address common.Address, authorize bool, voterElection bool) bool { 137 if voterElection { 138 _, voter := s.Voters[address] 139 return (voter && !authorize) || (!voter && authorize) 140 } 141 _, signer := s.Signers[address] 142 return (signer && !authorize) || (!signer && authorize) 143 } 144 145 // cast adds a new vote into the tally. 146 func (s *Snapshot) cast(address common.Address, authorize bool, voterElection bool) bool { 147 // Ensure the vote is meaningful 148 if !s.validVote(address, authorize, voterElection) { 149 return false 150 } 151 // Cast the vote into an existing or new tally 152 if old, ok := s.Tally[address]; ok { 153 old.Votes++ 154 s.Tally[address] = old 155 } else { 156 s.Tally[address] = Tally{Authorize: authorize, Votes: 1} 157 } 158 return true 159 } 160 161 // uncast removes a previously cast vote from the tally. 162 func (s *Snapshot) uncast(address common.Address, authorize bool) bool { 163 // If there's no tally, it's a dangling vote, just drop 164 tally, ok := s.Tally[address] 165 if !ok { 166 return false 167 } 168 // Ensure we only revert counted votes 169 if tally.Authorize != authorize { 170 return false 171 } 172 // Otherwise revert the vote 173 if tally.Votes > 1 { 174 tally.Votes-- 175 s.Tally[address] = tally 176 } else { 177 delete(s.Tally, address) 178 } 179 return true 180 } 181 182 // apply creates a new authorization snapshot by applying the given headers to 183 // the original one. 184 func (s *Snapshot) apply(ctx context.Context, headers []*types.Header) (*Snapshot, error) { 185 // Allow passing in no headers for cleaner code 186 if len(headers) == 0 { 187 return s, nil 188 } 189 // Sanity check that the headers can be applied 190 for i := 0; i < len(headers)-1; i++ { 191 if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 { 192 return nil, errInvalidVotingChain 193 } 194 } 195 if headers[0].Number.Uint64() != s.Number+1 { 196 return nil, errInvalidVotingChain 197 } 198 // Iterate through the headers and create a new snapshot 199 snap := s.copy() 200 201 for _, header := range headers { 202 // Remove any votes on checkpoint blocks 203 number := header.Number.Uint64() 204 if number%s.config.Epoch == 0 { 205 snap.Votes = nil 206 snap.Tally = make(map[common.Address]Tally) 207 } 208 // Resolve the authorization key and check against signers 209 signer, err := ecrecover(header, s.sigcache) 210 if err != nil { 211 return nil, err 212 } 213 lastBlockSigned, authorized := snap.Signers[signer] 214 if !authorized { 215 return nil, fmt.Errorf("%s not authorized to sign", signer.Hex()) 216 } 217 if lastBlockSigned > 0 { 218 if next := snap.nextSignableBlockNumber(lastBlockSigned); number < next { 219 return nil, fmt.Errorf("%s not authorized to sign %d: signed recently %d, next eligible signature %d", signer.Hex(), number, lastBlockSigned, next) 220 } 221 } 222 snap.Signers[signer] = number 223 224 // Verify if signer can vote 225 if _, ok := snap.Voters[signer]; ok { 226 227 var voterElection bool 228 var candidate common.Address 229 230 if ExtraHasVote(header.Extra) { 231 candidate = ExtraCandidate(header.Extra) 232 voterElection = ExtraIsVoterElection(header.Extra) 233 } 234 // Header authorized, discard any previous votes from the voter 235 for i, vote := range snap.Votes { 236 if vote.Signer == signer && vote.Address == candidate { 237 // Uncast the vote from the cached tally 238 snap.uncast(vote.Address, vote.Authorize) 239 240 // Uncast the vote from the chronological list 241 snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) 242 break // only one vote allowed 243 } 244 } 245 // Tally up the new vote from the signer 246 var authorize bool 247 switch { 248 case bytes.Equal(header.Nonce[:], nonceAuthVote): 249 authorize = true 250 case bytes.Equal(header.Nonce[:], nonceDropVote): 251 authorize = false 252 default: 253 return nil, errInvalidVote 254 } 255 256 if snap.cast(candidate, authorize, voterElection) { 257 snap.Votes = append(snap.Votes, &Vote{ 258 Signer: signer, 259 Block: number, 260 Address: candidate, 261 Authorize: authorize, 262 }) 263 } 264 // If the vote passed, update the list of signers or voters 265 if tally := snap.Tally[candidate]; tally.Votes > len(snap.Voters)/2 { 266 if tally.Authorize { 267 _, signer := snap.Signers[candidate] 268 if !signer { 269 snap.Signers[candidate] = 0 270 } else { 271 snap.Voters[candidate] = struct{}{} 272 } 273 } else { 274 _, voter := snap.Voters[candidate] 275 if !voter { 276 delete(snap.Signers, candidate) 277 } else { 278 delete(snap.Voters, candidate) 279 // Discard any previous votes the deauthorized voter cast 280 for i := 0; i < len(snap.Votes); i++ { 281 if snap.Votes[i].Signer == candidate { 282 // Uncast the vote from the cached tally 283 snap.uncast(snap.Votes[i].Address, snap.Votes[i].Authorize) 284 285 // Uncast the vote from the chronological list 286 snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) 287 288 i-- 289 } 290 } 291 } 292 } 293 // Discard any previous votes around the just changed account 294 for i := 0; i < len(snap.Votes); i++ { 295 if snap.Votes[i].Address == candidate { 296 snap.Votes = append(snap.Votes[:i], snap.Votes[i+1:]...) 297 i-- 298 } 299 } 300 delete(snap.Tally, candidate) 301 } 302 } 303 } 304 305 snap.Number += uint64(len(headers)) 306 snap.Hash = headers[len(headers)-1].Hash() 307 308 return snap, nil 309 } 310 311 // signers retrieves the list of authorized signers in ascending order. 312 func (s *Snapshot) signers() []common.Address { 313 signers := make([]common.Address, 0, len(s.Signers)) 314 for signer := range s.Signers { 315 signers = append(signers, signer) 316 } 317 for i := 0; i < len(signers); i++ { 318 for j := i + 1; j < len(signers); j++ { 319 if bytes.Compare(signers[i][:], signers[j][:]) > 0 { 320 signers[i], signers[j] = signers[j], signers[i] 321 } 322 } 323 } 324 return signers 325 } 326 327 // voters retrieves the list of authorized voters in ascending order. 328 func (s *Snapshot) voters() []common.Address { 329 voters := make([]common.Address, 0, len(s.Voters)) 330 for voter := range s.Voters { 331 voters = append(voters, voter) 332 } 333 for i := 0; i < len(voters); i++ { 334 for j := i + 1; j < len(voters); j++ { 335 if bytes.Compare(voters[i][:], voters[j][:]) > 0 { 336 voters[i], voters[j] = voters[j], voters[i] 337 } 338 } 339 } 340 return voters 341 } 342 343 // nextSignableBlockNumber returns the number of the next block legal for signature by the signer of 344 // lastSignedBlockNumber, based on the current number of signers. 345 func (s *Snapshot) nextSignableBlockNumber(lastSignedBlockNumber uint64) uint64 { 346 n := uint64(len(s.Signers)) 347 return lastSignedBlockNumber + n/2 + 1 348 }