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  }