github.com/nnlgsakib/mind-dpos@v0.0.0-20230606105614-f3c8ca06f808/consensus/alien/snapshot_test.go (about)

     1  // Copyright 2018 The gttc Authors
     2  // This file is part of the gttc library.
     3  //
     4  // The gttc 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 gttc 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 gttc library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package alien implements the delegated-proof-of-stake consensus engine.
    18  
    19  package alien
    20  
    21  import (
    22  	"bytes"
    23  	"crypto/ecdsa"
    24  	"math/big"
    25  	"testing"
    26  
    27  	"github.com/TTCECO/gttc/common"
    28  	"github.com/TTCECO/gttc/core"
    29  	"github.com/TTCECO/gttc/core/rawdb"
    30  	"github.com/TTCECO/gttc/core/types"
    31  	"github.com/TTCECO/gttc/crypto"
    32  	"github.com/TTCECO/gttc/ethdb"
    33  	"github.com/TTCECO/gttc/params"
    34  )
    35  
    36  type testerTransaction struct {
    37  	from         string // name of from address
    38  	to           string // name of to address
    39  	balance      int    // balance address in snap.voter
    40  	isVote       bool   // "ufo:1:event:vote"
    41  	isProposal   bool   // "ufo:1:event:proposal:..."
    42  	proposalType uint64 // proposalTypeCandidateAdd or proposalTypeCandidateRemove
    43  	isDeclare    bool   // "ufo:1:event:declare:..."
    44  	candidate    string // name of candidate in proposal
    45  	txHash       string // hash of tx
    46  	decision     bool   // decision of declare
    47  }
    48  
    49  type testerSingleHeader struct {
    50  	txs []testerTransaction
    51  }
    52  
    53  type testerSelfVoter struct {
    54  	voter   string // name of self voter address in genesis block
    55  	balance int    // balance
    56  }
    57  
    58  type testerVote struct {
    59  	voter     string
    60  	candidate string
    61  	stake     int
    62  }
    63  
    64  type testerSnapshot struct {
    65  	Signers []string
    66  	Votes   map[string]*testerVote
    67  	Tally   map[string]int
    68  	Voters  map[string]int
    69  }
    70  
    71  // testerAccountPool is a pool to maintain currently active tester accounts,
    72  // mapped from textual names used in the tests below to actual Ethereum private
    73  // keys capable of signing transactions.
    74  type testerAccountPool struct {
    75  	accounts map[string]*ecdsa.PrivateKey
    76  }
    77  
    78  func newTesterAccountPool() *testerAccountPool {
    79  	return &testerAccountPool{
    80  		accounts: make(map[string]*ecdsa.PrivateKey),
    81  	}
    82  }
    83  
    84  func (ap *testerAccountPool) sign(header *types.Header, signer string) {
    85  	// Ensure we have a persistent key for the signer
    86  	if ap.accounts[signer] == nil {
    87  		ap.accounts[signer], _ = crypto.GenerateKey()
    88  	}
    89  	// Sign the header and embed the signature in extra data
    90  	headerSigHash, _ := sigHash(header)
    91  	sig, _ := crypto.Sign(headerSigHash.Bytes(), ap.accounts[signer])
    92  	copy(header.Extra[len(header.Extra)-65:], sig)
    93  }
    94  
    95  func (ap *testerAccountPool) address(account string) common.Address {
    96  	// Ensure we have a persistent key for the account
    97  	if ap.accounts[account] == nil {
    98  		ap.accounts[account], _ = crypto.GenerateKey()
    99  	}
   100  	// Resolve and return the Ethereum address
   101  	return crypto.PubkeyToAddress(ap.accounts[account].PublicKey)
   102  }
   103  
   104  func (ap *testerAccountPool) name(address common.Address) string {
   105  	for name, v := range ap.accounts {
   106  		if crypto.PubkeyToAddress(v.PublicKey) == address {
   107  			return name
   108  		}
   109  	}
   110  	return ""
   111  }
   112  
   113  // testerChainReader implements consensus.ChainReader to access the genesis
   114  // block. All other methods and requests will panic.
   115  type testerChainReader struct {
   116  	db ethdb.Database
   117  }
   118  
   119  func (r *testerChainReader) Config() *params.ChainConfig                 { return params.AllAlienProtocolChanges }
   120  func (r *testerChainReader) CurrentHeader() *types.Header                { panic("not supported") }
   121  func (r *testerChainReader) GetHeader(common.Hash, uint64) *types.Header { panic("not supported") }
   122  func (r *testerChainReader) GetBlock(common.Hash, uint64) *types.Block   { panic("not supported") }
   123  func (r *testerChainReader) GetHeaderByHash(common.Hash) *types.Header   { panic("not supported") }
   124  func (r *testerChainReader) GetHeaderByNumber(number uint64) *types.Header {
   125  	if number == 0 {
   126  		return rawdb.ReadHeader(r.db, rawdb.ReadCanonicalHash(r.db, 0), 0)
   127  	}
   128  	panic("not supported")
   129  }
   130  
   131  // Tests that voting is evaluated correctly for various simple and complex scenarios.
   132  func TestVoting(t *testing.T) {
   133  	// Define the various voting scenarios to test
   134  	tests := []struct {
   135  		addrNames        []string             // accounts used in this case
   136  		candidateNeedPD  bool                 // candidate from POA
   137  		period           uint64               // default 3
   138  		epoch            uint64               // default 30000
   139  		maxSignerCount   uint64               // default 5 for test
   140  		minVoterBalance  int                  // default 50
   141  		genesisTimestamp uint64               // default time.now() - period + 1
   142  		lcrs             uint64               // loop count to recreate signers from top tally
   143  		selfVoters       []testerSelfVoter    //
   144  		txHeaders        []testerSingleHeader //
   145  		result           testerSnapshot       // the result of current snapshot
   146  		vlCnt            uint64
   147  	}{
   148  		{
   149  			/* 	Case 0:
   150  			*	Just two self vote address A B in genesis
   151  			*  	No votes or transactions through blocks
   152  			 */
   153  			addrNames:        []string{"A", "B"},
   154  			period:           uint64(3),
   155  			epoch:            uint64(31),
   156  			maxSignerCount:   uint64(5),
   157  			minVoterBalance:  50,
   158  			lcrs:             1,
   159  			genesisTimestamp: uint64(0),
   160  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   161  			txHeaders: []testerSingleHeader{
   162  				{[]testerTransaction{}},
   163  				{[]testerTransaction{}},
   164  				{[]testerTransaction{}},
   165  				{[]testerTransaction{}},
   166  				{[]testerTransaction{}},
   167  				{[]testerTransaction{}},
   168  			},
   169  			result: testerSnapshot{
   170  				Signers: []string{"A", "B"},
   171  				Tally:   map[string]int{"A": 100, "B": 200},
   172  				Voters:  map[string]int{"A": 0, "B": 0},
   173  				Votes: map[string]*testerVote{
   174  					"A": {"A", "A", 100},
   175  					"B": {"B", "B", 200},
   176  				},
   177  			},
   178  		},
   179  		{
   180  			/*	Case 1:
   181  			*	Two self vote address A B in  genesis
   182  			* 	C vote D to be signer in block 3
   183  			* 	But current loop do not finish, so D is not signer,
   184  			* 	the vote info already in Tally, Voters and Votes
   185  			 */
   186  			addrNames:        []string{"A", "B", "C", "D"},
   187  			period:           uint64(3),
   188  			epoch:            uint64(31),
   189  			maxSignerCount:   uint64(7),
   190  			minVoterBalance:  50,
   191  			lcrs:             1,
   192  			genesisTimestamp: uint64(0),
   193  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   194  			txHeaders: []testerSingleHeader{
   195  				{[]testerTransaction{}},
   196  				{[]testerTransaction{}},
   197  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   198  				{[]testerTransaction{}},
   199  			},
   200  			result: testerSnapshot{
   201  				Signers: []string{"A", "B"},
   202  				Tally:   map[string]int{"A": 100, "B": 200, "D": 200},
   203  				Voters:  map[string]int{"A": 0, "B": 0, "C": 3},
   204  				Votes: map[string]*testerVote{
   205  					"A": {"A", "A", 100},
   206  					"B": {"B", "B", 200},
   207  					"C": {"C", "D", 200},
   208  				},
   209  			},
   210  		},
   211  		{
   212  			/*	Case 2:
   213  			*	Two self vote address in  genesis
   214  			* 	C vote D to be signer in block 2
   215  			* 	But balance of C is lower than minVoterBalance,
   216  			*   so this vote not processed, D is not signer
   217  			* 	the vote info is dropped .
   218  			 */
   219  			addrNames:        []string{"A", "B", "C", "D"},
   220  			period:           uint64(3),
   221  			epoch:            uint64(31),
   222  			maxSignerCount:   uint64(5),
   223  			minVoterBalance:  50,
   224  			lcrs:             1,
   225  			genesisTimestamp: uint64(0),
   226  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   227  			txHeaders: []testerSingleHeader{
   228  				{[]testerTransaction{}},
   229  				{[]testerTransaction{{from: "C", to: "D", balance: 20, isVote: true}}},
   230  				{[]testerTransaction{}},
   231  				{[]testerTransaction{}},
   232  				{[]testerTransaction{}},
   233  				{[]testerTransaction{}},
   234  			},
   235  			result: testerSnapshot{
   236  				Signers: []string{"A", "B"},
   237  				Tally:   map[string]int{"A": 100, "B": 200},
   238  				Voters:  map[string]int{"A": 0, "B": 0},
   239  				Votes: map[string]*testerVote{
   240  					"A": {"A", "A", 100},
   241  					"B": {"B", "B", 200},
   242  				},
   243  			},
   244  		},
   245  		{
   246  			/*	Case 3:
   247  			*	Two self vote address A B in  genesis
   248  			* 	C vote D to be signer in block 3
   249  			* 	balance of C is higher than minVoterBalance
   250  			* 	D is signer in next loop
   251  			 */
   252  			addrNames:        []string{"A", "B", "C", "D"},
   253  			period:           uint64(3),
   254  			epoch:            uint64(31),
   255  			maxSignerCount:   uint64(5),
   256  			minVoterBalance:  50,
   257  			lcrs:             1,
   258  			genesisTimestamp: uint64(0),
   259  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   260  			txHeaders: []testerSingleHeader{
   261  				{[]testerTransaction{}},
   262  				{[]testerTransaction{}},
   263  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   264  				{[]testerTransaction{}},
   265  				{[]testerTransaction{}},
   266  				{[]testerTransaction{}},
   267  				{[]testerTransaction{}},
   268  			},
   269  			result: testerSnapshot{
   270  				Signers: []string{"A", "B", "D"},
   271  				Tally:   map[string]int{"A": 100, "B": 200, "D": 200},
   272  				Voters:  map[string]int{"A": 0, "B": 0, "C": 3},
   273  				Votes: map[string]*testerVote{
   274  					"A": {"A", "A", 100},
   275  					"B": {"B", "B", 200},
   276  					"C": {"C", "D", 200},
   277  				},
   278  			},
   279  		},
   280  
   281  		{
   282  			/*	Case 4:
   283  			*	Two self vote address A B in  genesis
   284  			* 	C vote D to be signer in block 2
   285  			*  	C vote B to be signer in block 3
   286  			* 	balance of C is higher minVoterBalance
   287  			* 	the first vote from C is dropped
   288  			* 	the signers are still A and B
   289  			 */
   290  			addrNames:        []string{"A", "B", "C", "D"},
   291  			period:           uint64(3),
   292  			epoch:            uint64(31),
   293  			maxSignerCount:   uint64(5),
   294  			minVoterBalance:  50,
   295  			lcrs:             1,
   296  			genesisTimestamp: uint64(0),
   297  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   298  			txHeaders: []testerSingleHeader{
   299  				{[]testerTransaction{}},
   300  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   301  				{[]testerTransaction{{from: "C", to: "B", balance: 180, isVote: true}}},
   302  				{[]testerTransaction{}},
   303  				{[]testerTransaction{}},
   304  				{[]testerTransaction{}},
   305  			},
   306  			result: testerSnapshot{
   307  				Signers: []string{"A", "B"},
   308  				Tally:   map[string]int{"A": 100, "B": 380},
   309  				Voters:  map[string]int{"A": 0, "B": 0, "C": 3},
   310  				Votes: map[string]*testerVote{
   311  					"A": {"A", "A", 100},
   312  					"B": {"B", "B", 200},
   313  					"C": {"C", "B", 180},
   314  				},
   315  			},
   316  		},
   317  		{
   318  			/*	Case 5:
   319  			*	Two self vote address A B in  genesis
   320  			* 	C vote D to be signer in block 2
   321  			*  	C transaction to E 20 in block 3
   322  			*	In Voters, the vote block number of C is still 2, not 4
   323  			 */
   324  			addrNames:        []string{"A", "B", "C", "D", "E"},
   325  			period:           uint64(3),
   326  			epoch:            uint64(31),
   327  			maxSignerCount:   uint64(5),
   328  			minVoterBalance:  50,
   329  			lcrs:             1,
   330  			genesisTimestamp: uint64(0),
   331  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   332  			txHeaders: []testerSingleHeader{
   333  				{[]testerTransaction{}},
   334  				{[]testerTransaction{{from: "C", to: "D", balance: 100, isVote: true}}},
   335  				{[]testerTransaction{}},
   336  				{[]testerTransaction{{from: "C", to: "E", balance: 20, isVote: false}}}, // when C transaction to E, the balance of C is 20
   337  				{[]testerTransaction{}},
   338  				{[]testerTransaction{}},
   339  			},
   340  			result: testerSnapshot{
   341  				Signers: []string{"A", "B", "D"},
   342  				Tally:   map[string]int{"A": 100, "B": 200, "D": 20},
   343  				Voters:  map[string]int{"A": 0, "B": 0, "C": 2},
   344  				Votes: map[string]*testerVote{
   345  					"A": {"A", "A", 100},
   346  					"B": {"B", "B", 200},
   347  					"C": {"C", "D", 20},
   348  				},
   349  			},
   350  		},
   351  		{
   352  			/*	Case 6:
   353  			*	Two self vote address A B in  genesis
   354  			* 	C vote D , J vote K, H vote I  to be signer in block 2
   355  			*   E vote F in block 3
   356  			* 	The signers in the next loop is A,B,D,F,I but not K
   357  			*	K is not top 5(maxsigercount) in Tally
   358  			 */
   359  			addrNames:        []string{"A", "B", "C", "D", "E", "F", "H", "I", "J", "K"},
   360  			period:           uint64(3),
   361  			epoch:            uint64(31),
   362  			maxSignerCount:   uint64(5),
   363  			minVoterBalance:  50,
   364  			lcrs:             1,
   365  			genesisTimestamp: uint64(0),
   366  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   367  			txHeaders: []testerSingleHeader{
   368  				{[]testerTransaction{}},
   369  				{[]testerTransaction{{from: "C", to: "D", balance: 110, isVote: true}, {from: "J", to: "K", balance: 80, isVote: true}, {from: "H", to: "I", balance: 160, isVote: true}}},
   370  				{[]testerTransaction{{from: "E", to: "F", balance: 130, isVote: true}}},
   371  				{[]testerTransaction{}},
   372  				{[]testerTransaction{}},
   373  				{[]testerTransaction{}},
   374  				{[]testerTransaction{}},
   375  			},
   376  			result: testerSnapshot{
   377  				Signers: []string{"A", "B", "D", "F", "I"},
   378  				Tally:   map[string]int{"A": 100, "B": 200, "D": 110, "I": 160, "F": 130, "K": 80},
   379  				Voters:  map[string]int{"A": 0, "B": 0, "C": 2, "H": 2, "J": 2, "E": 3},
   380  				Votes: map[string]*testerVote{
   381  					"A": {"A", "A", 100},
   382  					"B": {"B", "B", 200},
   383  					"C": {"C", "D", 110},
   384  					"J": {"J", "K", 80},
   385  					"H": {"H", "I", 160},
   386  					"E": {"E", "F", 130},
   387  				},
   388  			},
   389  		},
   390  		{
   391  			/*	Case 7:
   392  			*	one self vote address A in  genesis
   393  			* 	C vote D , J vote K, H vote I  to be signer in block 3
   394  			*   E vote F in block 4
   395  			* 	B vote B in block 5
   396  			* 	The signers in the next loop is A, B, D,F,I,K
   397  			*	current number - The block number of vote for A > epoch expired
   398  			*
   399  			 */
   400  			addrNames:        []string{"A", "B", "C", "D", "E", "F", "H", "I", "J", "K"},
   401  			period:           uint64(3),
   402  			epoch:            uint64(8),
   403  			maxSignerCount:   uint64(5),
   404  			minVoterBalance:  50,
   405  			lcrs:             1,
   406  			genesisTimestamp: uint64(0),
   407  			selfVoters:       []testerSelfVoter{{"A", 100}},
   408  			txHeaders: []testerSingleHeader{
   409  				{[]testerTransaction{}},
   410  				{[]testerTransaction{}},
   411  				{[]testerTransaction{}},
   412  				{[]testerTransaction{}},
   413  				{[]testerTransaction{}},
   414  				{[]testerTransaction{}},
   415  				{[]testerTransaction{}},
   416  				{[]testerTransaction{}},
   417  				{[]testerTransaction{}},
   418  				{[]testerTransaction{}},
   419  				{[]testerTransaction{}},
   420  				{[]testerTransaction{{from: "C", to: "D", balance: 110, isVote: true}, {from: "J", to: "K", balance: 80, isVote: true}, {from: "H", to: "I", balance: 160, isVote: true}}},
   421  				{[]testerTransaction{{from: "E", to: "F", balance: 130, isVote: true}}},
   422  				{[]testerTransaction{{from: "B", to: "B", balance: 200, isVote: true}}},
   423  				{[]testerTransaction{}},
   424  				{[]testerTransaction{}},
   425  			},
   426  			result: testerSnapshot{
   427  				Signers: []string{"B", "D", "F", "I", "K"},
   428  				Tally:   map[string]int{"B": 200, "D": 110, "I": 160, "F": 130, "K": 80},
   429  				Voters:  map[string]int{"B": 14, "C": 12, "H": 12, "J": 12, "E": 13},
   430  				Votes: map[string]*testerVote{
   431  					"B": {"B", "B", 200},
   432  					"C": {"C", "D", 110},
   433  					"J": {"J", "K", 80},
   434  					"H": {"H", "I", 160},
   435  					"E": {"E", "F", 130},
   436  				},
   437  			},
   438  		},
   439  		{
   440  			/*	Case 8:
   441  			*	Two self vote address A,B in  genesis
   442  			* 	C vote D , D vote C to be signer in block 3
   443  			 */
   444  			addrNames:        []string{"A", "B", "C", "D", "E"},
   445  			period:           uint64(3),
   446  			epoch:            uint64(31),
   447  			maxSignerCount:   uint64(5),
   448  			minVoterBalance:  50,
   449  			lcrs:             1,
   450  			genesisTimestamp: uint64(0),
   451  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   452  			txHeaders: []testerSingleHeader{
   453  				{[]testerTransaction{}},
   454  				{[]testerTransaction{}},
   455  				{[]testerTransaction{{from: "C", to: "D", balance: 110, isVote: true}, {from: "D", to: "C", balance: 80, isVote: true}, {from: "C", to: "E", balance: 110, isVote: false}}},
   456  				{[]testerTransaction{}},
   457  				{[]testerTransaction{}},
   458  				{[]testerTransaction{}},
   459  			},
   460  			result: testerSnapshot{
   461  				Signers: []string{"B", "A", "C", "D"},
   462  				Tally:   map[string]int{"B": 200, "D": 110, "A": 100, "C": 80},
   463  				Voters:  map[string]int{"B": 0, "C": 3, "D": 3, "A": 0},
   464  				Votes: map[string]*testerVote{
   465  					"B": {"B", "B", 200},
   466  					"A": {"A", "A", 100},
   467  					"C": {"C", "D", 110},
   468  					"D": {"D", "C", 80},
   469  				},
   470  			},
   471  		},
   472  		{
   473  			/*	Case 9:
   474  			*	Two self vote address A B in  genesis
   475  			* 	C vote D to be signer in block 3
   476  			* 	lcrs  is 2, so the signers will recalculate after 5 *2 block
   477  			* 	D is still not signer
   478  			 */
   479  			addrNames:        []string{"A", "B", "C", "D"},
   480  			period:           uint64(3),
   481  			epoch:            uint64(31),
   482  			maxSignerCount:   uint64(5),
   483  			minVoterBalance:  50,
   484  			lcrs:             2,
   485  			genesisTimestamp: uint64(0),
   486  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   487  			txHeaders: []testerSingleHeader{
   488  				{[]testerTransaction{}},
   489  				{[]testerTransaction{}},
   490  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   491  				{[]testerTransaction{}},
   492  				{[]testerTransaction{}},
   493  				{[]testerTransaction{}},
   494  				{[]testerTransaction{}},
   495  			},
   496  			result: testerSnapshot{
   497  				Signers: []string{"A", "B"},
   498  				Tally:   map[string]int{"A": 100, "B": 200, "D": 200},
   499  				Voters:  map[string]int{"A": 0, "B": 0, "C": 3},
   500  				Votes: map[string]*testerVote{
   501  					"A": {"A", "A", 100},
   502  					"B": {"B", "B", 200},
   503  					"C": {"C", "D", 200},
   504  				},
   505  			},
   506  		},
   507  		{
   508  			/*	Case 10:
   509  			*	Two self vote address A B in  genesis
   510  			* 	C vote D to be signer in block 3
   511  			* 	lcrs  is 2, so the signers will recalculate after 5 *2 block
   512  			* 	D is signer
   513  			 */
   514  			addrNames:        []string{"A", "B", "C", "D"},
   515  			period:           uint64(3),
   516  			epoch:            uint64(31),
   517  			maxSignerCount:   uint64(5),
   518  			minVoterBalance:  50,
   519  			lcrs:             2,
   520  			genesisTimestamp: uint64(0),
   521  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   522  			txHeaders: []testerSingleHeader{
   523  				{[]testerTransaction{}},
   524  				{[]testerTransaction{}},
   525  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   526  				{[]testerTransaction{}},
   527  				{[]testerTransaction{}},
   528  				{[]testerTransaction{}},
   529  				{[]testerTransaction{}},
   530  				{[]testerTransaction{}},
   531  				{[]testerTransaction{}},
   532  				{[]testerTransaction{}},
   533  				{[]testerTransaction{}},
   534  				{[]testerTransaction{}},
   535  			},
   536  			result: testerSnapshot{
   537  				Signers: []string{"A", "B", "D"},
   538  				Tally:   map[string]int{"A": 100, "B": 200, "D": 200},
   539  				Voters:  map[string]int{"A": 0, "B": 0, "C": 3},
   540  				Votes: map[string]*testerVote{
   541  					"A": {"A", "A", 100},
   542  					"B": {"B", "B", 200},
   543  					"C": {"C", "D", 200},
   544  				},
   545  			},
   546  		},
   547  		{
   548  			/*	Case 11:
   549  			*	All self vote in  genesis
   550  			* 	lcrs  is 1, so the signers will recalculate after 5 block
   551  			*   official 21 node test case
   552  			 */
   553  			addrNames: []string{"A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "A10",
   554  				"A11", "A12", "A13", "A14", "A15", "A16", "A17", "A18", "A19", "A20",
   555  				"A21", "A22", "A23", "A24", "A25", "A26", "A27", "A28", "A29", "A30",
   556  				"A31", "A32", "A33", "A34", "A35", "A36", "A37", "A38", "A39", "A40"},
   557  			period:           uint64(3),
   558  			epoch:            uint64(300),
   559  			maxSignerCount:   uint64(21),
   560  			minVoterBalance:  50,
   561  			lcrs:             1,
   562  			genesisTimestamp: uint64(0),
   563  			selfVoters: []testerSelfVoter{{"A1", 5000}, {"A2", 5000}, {"A3", 5000}, {"A4", 5000}, {"A5", 5000},
   564  				{"A6", 5000}, {"A7", 5000}, {"A8", 5000}, {"A9", 5000}, {"A10", 5000},
   565  				{"A11", 4000}, {"A12", 4000}, {"A13", 4000}, {"A14", 4000}, {"A15", 4000},
   566  				{"A16", 4000}, {"A17", 4000}, {"A18", 4000}, {"A19", 4000}, {"A20", 4000},
   567  				{"A21", 3000}, {"A22", 3000}, {"A23", 3000}, {"A24", 3000}, {"A25", 3000},
   568  				{"A26", 3000}, {"A27", 3000}, {"A28", 3000}, {"A29", 3000}, {"A30", 3000},
   569  				{"A31", 2000}, {"A32", 2000}, {"A33", 2000}, {"A34", 2000}, {"A35", 2000},
   570  				{"A36", 2000}, {"A37", 2000}, {"A38", 2000}, {"A39", 2000}, {"A40", 2000}},
   571  			txHeaders: []testerSingleHeader{
   572  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   573  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   574  				{[]testerTransaction{}}, {[]testerTransaction{}},
   575  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   576  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   577  				{[]testerTransaction{}}, {[]testerTransaction{}},
   578  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   579  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   580  				{[]testerTransaction{}}, {[]testerTransaction{}},
   581  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   582  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   583  				{[]testerTransaction{}}, {[]testerTransaction{}},
   584  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   585  				{[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}}, {[]testerTransaction{}},
   586  				{[]testerTransaction{}}, {[]testerTransaction{}},
   587  			},
   588  			result: testerSnapshot{
   589  				Signers: []string{},
   590  				Tally: map[string]int{"A1": 5000, "A2": 5000, "A3": 5000, "A4": 5000, "A5": 5000, "A6": 5000, "A7": 5000, "A8": 5000, "A9": 5000, "A10": 5000,
   591  					"A11": 4000, "A12": 4000, "A13": 4000, "A14": 4000, "A15": 4000, "A16": 4000, "A17": 4000, "A18": 4000, "A19": 4000, "A20": 4000,
   592  					"A21": 3000, "A22": 3000, "A23": 3000, "A24": 3000, "A25": 3000, "A26": 3000, "A27": 3000, "A28": 3000, "A29": 3000, "A30": 3000,
   593  					"A31": 2000, "A32": 2000, "A33": 2000, "A34": 2000, "A35": 2000, "A36": 2000, "A37": 2000, "A38": 2000, "A39": 2000, "A40": 2000},
   594  				Voters: map[string]int{"A1": 0, "A2": 0, "A3": 0, "A4": 0, "A5": 0, "A6": 0, "A7": 0, "A8": 0, "A9": 0, "A10": 0,
   595  					"A11": 0, "A12": 0, "A13": 0, "A14": 0, "A15": 0, "A16": 0, "A17": 0, "A18": 0, "A19": 0, "A20": 0,
   596  					"A21": 0, "A22": 0, "A23": 0, "A24": 0, "A25": 0, "A26": 0, "A27": 0, "A28": 0, "A29": 0, "A30": 0,
   597  					"A31": 0, "A32": 0, "A33": 0, "A34": 0, "A35": 0, "A36": 0, "A37": 0, "A38": 0, "A39": 0, "A40": 0},
   598  				Votes: map[string]*testerVote{
   599  					"A1":  {"A1", "A1", 5000},
   600  					"A2":  {"A2", "A2", 5000},
   601  					"A3":  {"A3", "A3", 5000},
   602  					"A4":  {"A4", "A4", 5000},
   603  					"A5":  {"A5", "A5", 5000},
   604  					"A6":  {"A6", "A6", 5000},
   605  					"A7":  {"A7", "A7", 5000},
   606  					"A8":  {"A8", "A8", 5000},
   607  					"A9":  {"A9", "A9", 5000},
   608  					"A10": {"A10", "A10", 5000},
   609  					"A11": {"A11", "A11", 4000},
   610  					"A12": {"A12", "A12", 4000},
   611  					"A13": {"A13", "A13", 4000},
   612  					"A14": {"A14", "A14", 4000},
   613  					"A15": {"A15", "A15", 4000},
   614  					"A16": {"A16", "A16", 4000},
   615  					"A17": {"A17", "A17", 4000},
   616  					"A18": {"A18", "A18", 4000},
   617  					"A19": {"A19", "A19", 4000},
   618  					"A20": {"A20", "A20", 4000},
   619  					"A21": {"A21", "A21", 3000},
   620  					"A22": {"A22", "A22", 3000},
   621  					"A23": {"A23", "A23", 3000},
   622  					"A24": {"A24", "A24", 3000},
   623  					"A25": {"A25", "A25", 3000},
   624  					"A26": {"A26", "A26", 3000},
   625  					"A27": {"A27", "A27", 3000},
   626  					"A28": {"A28", "A28", 3000},
   627  					"A29": {"A29", "A29", 3000},
   628  					"A30": {"A30", "A30", 3000},
   629  					"A31": {"A31", "A31", 2000},
   630  					"A32": {"A32", "A32", 2000},
   631  					"A33": {"A33", "A33", 2000},
   632  					"A34": {"A34", "A34", 2000},
   633  					"A35": {"A35", "A35", 2000},
   634  					"A36": {"A36", "A36", 2000},
   635  					"A37": {"A37", "A37", 2000},
   636  					"A38": {"A38", "A38", 2000},
   637  					"A39": {"A39", "A39", 2000},
   638  					"A40": {"A40", "A40", 2000},
   639  				},
   640  			},
   641  		},
   642  		{
   643  			/*	Case 12:
   644  			*   Candidate from Poa is enable
   645  			*	Two self vote address A B in  genesis
   646  			* 	C vote D to be signer in block 3, but D is not in candidates ,so this vote not valid
   647  			 */
   648  			addrNames:        []string{"A", "B", "C", "D"},
   649  			candidateNeedPD:  true,
   650  			period:           uint64(3),
   651  			epoch:            uint64(31),
   652  			maxSignerCount:   uint64(5),
   653  			minVoterBalance:  50,
   654  			lcrs:             1,
   655  			genesisTimestamp: uint64(0),
   656  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   657  			txHeaders: []testerSingleHeader{
   658  				{[]testerTransaction{}},
   659  				{[]testerTransaction{}},
   660  				{[]testerTransaction{{from: "C", to: "D", balance: 200, isVote: true}}},
   661  				{[]testerTransaction{}},
   662  				{[]testerTransaction{}},
   663  				{[]testerTransaction{}},
   664  				{[]testerTransaction{}},
   665  			},
   666  			result: testerSnapshot{
   667  				Signers: []string{"A", "B"},
   668  				Tally:   map[string]int{"A": 100, "B": 200},
   669  				Voters:  map[string]int{"A": 0, "B": 0},
   670  				Votes: map[string]*testerVote{
   671  					"A": {"A", "A", 100},
   672  					"B": {"B", "B", 200},
   673  				},
   674  			},
   675  		},
   676  		{
   677  			/*	Case 13:
   678  			*   Candidate from Poa is enable
   679  			*	Two self vote address A B in  genesis
   680  			*   A proposal D to candidates, B declare agree to this proposal ,but not pass 2/3 * all stake, so fail
   681  			* 	C vote D to be signer in block 3, but D is not in candidates ,so this vote not valid
   682  			 */
   683  			addrNames:        []string{"A", "B", "C", "D"},
   684  			candidateNeedPD:  true,
   685  			period:           uint64(3),
   686  			epoch:            uint64(31),
   687  			maxSignerCount:   uint64(5),
   688  			minVoterBalance:  50,
   689  			lcrs:             1,
   690  			genesisTimestamp: uint64(0),
   691  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   692  			txHeaders: []testerSingleHeader{
   693  				{[]testerTransaction{}},
   694  				{[]testerTransaction{{from: "A", to: "A", isProposal: true, candidate: "D", txHash: "a", proposalType: proposalTypeCandidateAdd}}},
   695  				{[]testerTransaction{{from: "B", to: "B", isDeclare: true, txHash: "a", decision: true}}},
   696  				{[]testerTransaction{}},
   697  				{[]testerTransaction{{from: "C", to: "D", balance: 250, isVote: true}}},
   698  				{[]testerTransaction{}},
   699  				{[]testerTransaction{}},
   700  				{[]testerTransaction{}},
   701  				{[]testerTransaction{}},
   702  				{[]testerTransaction{}},
   703  				{[]testerTransaction{}},
   704  			},
   705  			result: testerSnapshot{
   706  				Signers: []string{"A", "B"},
   707  				Tally:   map[string]int{"A": 100, "B": 200},
   708  				Voters:  map[string]int{"A": 0, "B": 0},
   709  				Votes: map[string]*testerVote{
   710  					"A": {"A", "A", 100},
   711  					"B": {"B", "B", 200},
   712  				},
   713  			},
   714  		},
   715  		{
   716  			/*	Case 14:
   717  			*   Candidate from Poa is enable
   718  			*	Two self vote address A B in  genesis
   719  			*   A proposal D to candidates, and A,B declare agree to this proposal, so D is in candidates
   720  			* 	C vote D to be signer in block 5
   721  			 */
   722  			addrNames:        []string{"A", "B", "C", "D"},
   723  			candidateNeedPD:  true,
   724  			period:           uint64(3),
   725  			epoch:            uint64(31),
   726  			maxSignerCount:   uint64(5),
   727  			minVoterBalance:  50,
   728  			lcrs:             1,
   729  			genesisTimestamp: uint64(0),
   730  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}},
   731  			txHeaders: []testerSingleHeader{
   732  				{[]testerTransaction{}},
   733  				{[]testerTransaction{{from: "A", to: "A", isProposal: true, candidate: "D", txHash: "a", proposalType: proposalTypeCandidateAdd}}},
   734  				{[]testerTransaction{{from: "A", to: "A", isDeclare: true, txHash: "a", decision: true}, {from: "B", to: "B", isDeclare: true, txHash: "a", decision: true}}},
   735  				{[]testerTransaction{}},
   736  				{[]testerTransaction{}},
   737  				{[]testerTransaction{}},
   738  				{[]testerTransaction{}},
   739  				{[]testerTransaction{}},
   740  				{[]testerTransaction{}},
   741  				{[]testerTransaction{}},
   742  				{[]testerTransaction{{from: "C", to: "D", balance: 250, isVote: true}}},
   743  				{[]testerTransaction{}},
   744  				{[]testerTransaction{}},
   745  				{[]testerTransaction{}},
   746  				{[]testerTransaction{}},
   747  				{[]testerTransaction{}},
   748  				{[]testerTransaction{}},
   749  			},
   750  			result: testerSnapshot{
   751  				Signers: []string{"A", "B", "D"},
   752  				Tally:   map[string]int{"A": 100, "B": 200, "D": 250},
   753  				Voters:  map[string]int{"A": 0, "B": 0, "C": 11},
   754  				Votes: map[string]*testerVote{
   755  					"A": {"A", "A", 100},
   756  					"B": {"B", "B", 200},
   757  					"C": {"C", "D", 250},
   758  				},
   759  			},
   760  		},
   761  		{
   762  			/*	Case 15:
   763  			*   Candidate from Poa is enable
   764  			*	Two self vote address A B E F in  genesis
   765  			*   A proposal D to candidates, and A,B,F declare agree to this proposal,
   766  			*   but the sum stake of A B F is less than 2/3 of all stake, so D is not in candidates
   767  			* 	C vote D to be signer in block 5
   768  			 */
   769  			addrNames:        []string{"A", "B", "C", "D", "E", "F"},
   770  			candidateNeedPD:  true,
   771  			period:           uint64(3),
   772  			epoch:            uint64(31),
   773  			maxSignerCount:   uint64(5),
   774  			minVoterBalance:  50,
   775  			lcrs:             1,
   776  			genesisTimestamp: uint64(0),
   777  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}, {"E", 2000}, {"F", 200}},
   778  			txHeaders: []testerSingleHeader{
   779  				{[]testerTransaction{}},
   780  				{[]testerTransaction{{from: "A", to: "A", isProposal: true, candidate: "D", txHash: "a", proposalType: proposalTypeCandidateAdd}}},
   781  				{[]testerTransaction{{from: "A", to: "A", isDeclare: true, txHash: "a", decision: true}, {from: "B", to: "B", isDeclare: true, txHash: "a", decision: true}, {from: "F", to: "F", isDeclare: true, txHash: "a", decision: true}}},
   782  				{[]testerTransaction{}},
   783  				{[]testerTransaction{{from: "C", to: "D", balance: 250, isVote: true}}},
   784  				{[]testerTransaction{}},
   785  				{[]testerTransaction{}},
   786  				{[]testerTransaction{}},
   787  				{[]testerTransaction{}},
   788  				{[]testerTransaction{}},
   789  				{[]testerTransaction{}},
   790  			},
   791  			result: testerSnapshot{
   792  				Signers: []string{"A", "B", "E", "F"},
   793  				Tally:   map[string]int{"A": 100, "B": 200, "E": 2000, "F": 200},
   794  				Voters:  map[string]int{"A": 0, "B": 0, "E": 0, "F": 0},
   795  				Votes: map[string]*testerVote{
   796  					"A": {"A", "A", 100},
   797  					"B": {"B", "B", 200},
   798  					"E": {"E", "E", 2000},
   799  					"F": {"F", "F", 200},
   800  				},
   801  			},
   802  		},
   803  		{
   804  			/*	Case 16:
   805  			*   Candidate from Poa is enable
   806  			*	Two self vote address A B E F in  genesis
   807  			*   A proposal B remove from candidates, and A, E ,F declare agree to this proposal,
   808  			*   the sum stake of A E F is more than 2/3 of all stake, so B is not in candidates
   809  			*   Now do not change the vote automatically,
   810  			 */
   811  			addrNames:        []string{"A", "B", "C", "D", "E", "F"},
   812  			candidateNeedPD:  true,
   813  			period:           uint64(3),
   814  			epoch:            uint64(31),
   815  			maxSignerCount:   uint64(5),
   816  			minVoterBalance:  50,
   817  			lcrs:             1,
   818  			genesisTimestamp: uint64(0),
   819  			selfVoters:       []testerSelfVoter{{"A", 100}, {"B", 200}, {"E", 2000}, {"F", 200}},
   820  			txHeaders: []testerSingleHeader{
   821  				{[]testerTransaction{}},
   822  				{[]testerTransaction{{from: "A", to: "A", isProposal: true, candidate: "B", txHash: "a", proposalType: proposalTypeCandidateRemove}}},
   823  				{[]testerTransaction{{from: "A", to: "A", isDeclare: true, txHash: "a", decision: true}, {from: "E", to: "E", isDeclare: true, txHash: "a", decision: true}, {from: "F", to: "F", isDeclare: true, txHash: "a", decision: true}}},
   824  				{[]testerTransaction{}},
   825  				{[]testerTransaction{}},
   826  				{[]testerTransaction{}},
   827  				{[]testerTransaction{}},
   828  				{[]testerTransaction{}},
   829  				{[]testerTransaction{}},
   830  				{[]testerTransaction{}},
   831  			},
   832  			result: testerSnapshot{
   833  				Signers: []string{"A", "E", "F"},
   834  				Tally:   map[string]int{"A": 100, "B": 200, "E": 2000, "F": 200},
   835  				Voters:  map[string]int{"A": 0, "B": 0, "E": 0, "F": 0},
   836  				Votes: map[string]*testerVote{
   837  					"A": {"A", "A", 100},
   838  					"B": {"B", "B", 200},
   839  					"E": {"E", "E", 2000},
   840  					"F": {"F", "F", 200},
   841  				},
   842  			},
   843  		},
   844  	}
   845  
   846  	// Run through the scenarios and test them
   847  	for i, tt := range tests {
   848  		candidateNeedPD = tt.candidateNeedPD
   849  		if tt.vlCnt == 0 {
   850  			tt.vlCnt = 1
   851  		}
   852  		// Create the account pool and generate the initial set of all address in addrNames
   853  		accounts := newTesterAccountPool()
   854  		addrNames := make([]common.Address, len(tt.addrNames))
   855  		for j, signer := range tt.addrNames {
   856  			addrNames[j] = accounts.address(signer)
   857  		}
   858  		for j := 0; j < len(addrNames); j++ {
   859  			for k := j + 1; k < len(addrNames); k++ {
   860  				if bytes.Compare(addrNames[j][:], addrNames[k][:]) > 0 {
   861  					addrNames[j], addrNames[k] = addrNames[k], addrNames[j]
   862  				}
   863  			}
   864  		}
   865  
   866  		var snap *Snapshot
   867  		// Prepare data for the genesis block
   868  		var genesisVotes []*Vote                       // for create the new snapshot of genesis block
   869  		var selfVoteSigners []common.UnprefixedAddress // for header extra
   870  		alreadyVote := make(map[common.Address]struct{})
   871  		for _, voter := range tt.selfVoters {
   872  			if _, ok := alreadyVote[accounts.address(voter.voter)]; !ok {
   873  				genesisVotes = append(genesisVotes, &Vote{
   874  					Voter:     accounts.address(voter.voter),
   875  					Candidate: accounts.address(voter.voter),
   876  					Stake:     big.NewInt(int64(voter.balance)),
   877  				})
   878  				selfVoteSigners = append(selfVoteSigners, common.UnprefixedAddress(accounts.address(voter.voter)))
   879  				alreadyVote[accounts.address(voter.voter)] = struct{}{}
   880  			}
   881  		}
   882  
   883  		// extend length of extra, so address of CoinBase can keep signature .
   884  		genesis := &core.Genesis{
   885  			ExtraData: make([]byte, extraVanity+extraSeal),
   886  		}
   887  
   888  		// Create a pristine blockchain with the genesis injected
   889  		db := ethdb.NewMemDatabase()
   890  		genesis.Commit(db)
   891  
   892  		// Create new alien
   893  		alien := New(&params.AlienConfig{
   894  			Period:          tt.period,
   895  			Epoch:           tt.epoch,
   896  			MinVoterBalance: big.NewInt(int64(tt.minVoterBalance)),
   897  			MaxSignerCount:  tt.maxSignerCount,
   898  			SelfVoteSigners: selfVoteSigners,
   899  		}, db)
   900  
   901  		// Assemble a chain of headers from the cast votes
   902  		headers := make([]*types.Header, len(tt.txHeaders))
   903  		for j, header := range tt.txHeaders {
   904  
   905  			var currentBlockVotes []Vote
   906  			var currentBlockProposals []Proposal
   907  			var currentBlockDeclares []Declare
   908  			var modifyPredecessorVotes []Vote
   909  			for _, trans := range header.txs {
   910  				if trans.isVote {
   911  					if trans.balance >= tt.minVoterBalance && (!candidateNeedPD || snap.isCandidate(accounts.address(trans.to))) {
   912  						// vote event
   913  						currentBlockVotes = append(currentBlockVotes, Vote{
   914  							Voter:     accounts.address(trans.from),
   915  							Candidate: accounts.address(trans.to),
   916  							Stake:     big.NewInt(int64(trans.balance)),
   917  						})
   918  					}
   919  				} else if trans.isProposal {
   920  					if snap.isCandidate(accounts.address(trans.from)) {
   921  						currentBlockProposals = append(currentBlockProposals, Proposal{
   922  							Hash:                   common.HexToHash(trans.txHash),
   923  							ReceivedNumber:         big.NewInt(int64(j)),
   924  							CurrentDeposit:         proposalDeposit,
   925  							ValidationLoopCnt:      tt.vlCnt,
   926  							ProposalType:           trans.proposalType,
   927  							Proposer:               accounts.address(trans.from),
   928  							TargetAddress:          accounts.address(trans.candidate),
   929  							MinerRewardPerThousand: minerRewardPerThousand,
   930  							SCHash:                 common.Hash{},
   931  							SCBlockCountPerPeriod:  1,
   932  							SCBlockRewardPerPeriod: 0,
   933  							Declares:               []*Declare{},
   934  							MinVoterBalance:        new(big.Int).Div(minVoterBalance, big.NewInt(1e+18)).Uint64(),
   935  							ProposalDeposit:        new(big.Int).Div(proposalDeposit, big.NewInt(1e+18)).Uint64(),
   936  							SCRentFee:              0,
   937  							SCRentRate:             1,
   938  							SCRentLength:           defaultSCRentLength,
   939  						})
   940  					}
   941  				} else if trans.isDeclare {
   942  					if snap.isCandidate(accounts.address(trans.from)) {
   943  
   944  						currentBlockDeclares = append(currentBlockDeclares, Declare{
   945  							ProposalHash: common.HexToHash(trans.txHash),
   946  							Declarer:     accounts.address(trans.from),
   947  							Decision:     trans.decision,
   948  						})
   949  
   950  					}
   951  				} else {
   952  					// modify balance
   953  					// modifyPredecessorVotes
   954  					// only consider the voter
   955  					modifyPredecessorVotes = append(modifyPredecessorVotes, Vote{
   956  						Voter: accounts.address(trans.from),
   957  						Stake: big.NewInt(int64(trans.balance)),
   958  					})
   959  				}
   960  			}
   961  			currentHeaderExtra := HeaderExtra{}
   962  			signer := common.Address{}
   963  
   964  			// (j==0) means (header.Number==1)
   965  			if j == 0 {
   966  				for k := 0; k < int(tt.maxSignerCount); k++ {
   967  					currentHeaderExtra.SignerQueue = append(currentHeaderExtra.SignerQueue, common.Address(selfVoteSigners[k%len(selfVoteSigners)]))
   968  				}
   969  				currentHeaderExtra.LoopStartTime = tt.genesisTimestamp // here should be parent genesisTimestamp
   970  				signer = common.Address(selfVoteSigners[0])
   971  
   972  			} else {
   973  				// decode parent header.extra
   974  				//rlp.DecodeBytes(headers[j-1].Extra[extraVanity:len(headers[j-1].Extra)-extraSeal], &currentHeaderExtra)
   975  
   976  				decodeHeaderExtra(alien.config, headers[j-1].Number, headers[j-1].Extra[extraVanity:len(headers[j-1].Extra)-extraSeal], &currentHeaderExtra)
   977  				signer = currentHeaderExtra.SignerQueue[uint64(j)%tt.maxSignerCount]
   978  				// means header.Number % tt.maxSignerCount == 0
   979  				if (j+1)%int(tt.maxSignerCount) == 0 {
   980  					snap, err := alien.snapshot(&testerChainReader{db: db}, headers[j-1].Number.Uint64(), headers[j-1].Hash(), headers, nil, uint64(tt.lcrs))
   981  					if err != nil {
   982  						t.Errorf("test %d: failed to create voting snapshot: %v", i, err)
   983  						continue
   984  					}
   985  					currentHeaderExtra.SignerQueue = []common.Address{}
   986  					newSignerQueue, err := snap.createSignerQueue()
   987  					if err != nil {
   988  						t.Errorf("test %d: failed to create signer queue: %v", i, err)
   989  					}
   990  
   991  					currentHeaderExtra.SignerQueue = newSignerQueue
   992  
   993  					currentHeaderExtra.LoopStartTime = currentHeaderExtra.LoopStartTime + tt.period*tt.maxSignerCount
   994  				} else {
   995  				}
   996  			}
   997  
   998  			currentHeaderExtra.CurrentBlockVotes = currentBlockVotes
   999  			currentHeaderExtra.ModifyPredecessorVotes = modifyPredecessorVotes
  1000  			currentHeaderExtra.CurrentBlockProposals = currentBlockProposals
  1001  			currentHeaderExtra.CurrentBlockDeclares = currentBlockDeclares
  1002  			//currentHeaderExtraEnc, err := rlp.EncodeToBytes(currentHeaderExtra)
  1003  			currentHeaderExtraEnc, err := encodeHeaderExtra(alien.config, big.NewInt(int64(j)+1), currentHeaderExtra)
  1004  
  1005  			if err != nil {
  1006  				t.Errorf("test %d: failed to rlp encode to bytes: %v", i, err)
  1007  				continue
  1008  			}
  1009  			// Create the genesis block with the initial set of signers
  1010  			ExtraData := make([]byte, extraVanity+len(currentHeaderExtraEnc)+extraSeal)
  1011  			copy(ExtraData[extraVanity:], currentHeaderExtraEnc)
  1012  
  1013  			headers[j] = &types.Header{
  1014  				Number:   big.NewInt(int64(j) + 1),
  1015  				Time:     big.NewInt((int64(j)+1)*int64(defaultBlockPeriod) - 1),
  1016  				Coinbase: signer,
  1017  				Extra:    ExtraData,
  1018  			}
  1019  			if j > 0 {
  1020  				headers[j].ParentHash = headers[j-1].Hash()
  1021  			}
  1022  			accounts.sign(headers[j], accounts.name(signer))
  1023  
  1024  			// Pass all the headers through alien and ensure tallying succeeds
  1025  			snap, err = alien.snapshot(&testerChainReader{db: db}, headers[j].Number.Uint64(), headers[j].Hash(), headers[:j+1], genesisVotes, uint64(tt.lcrs))
  1026  			genesisVotes = []*Vote{}
  1027  			if err != nil {
  1028  				t.Errorf("test %d: failed to create voting snapshot: %v", i, err)
  1029  				continue
  1030  			}
  1031  		}
  1032  
  1033  		// verify the result in test case
  1034  		head := headers[len(headers)-1]
  1035  		snap, err := alien.snapshot(&testerChainReader{db: db}, head.Number.Uint64(), head.Hash(), headers, nil, uint64(tt.lcrs))
  1036  		//
  1037  		if err != nil {
  1038  			t.Errorf("test %d: failed to create voting snapshot: %v", i, err)
  1039  			continue
  1040  		}
  1041  		// check signers
  1042  		if len(tt.result.Signers) > 0 {
  1043  
  1044  			signers := map[common.Address]int{}
  1045  			for _, signer := range snap.Signers {
  1046  				signers[*signer] = 1
  1047  
  1048  			}
  1049  			for _, signer := range tt.result.Signers {
  1050  				signers[accounts.address(signer)] += 2
  1051  			}
  1052  
  1053  			for address, cnt := range signers {
  1054  				if cnt != 3 {
  1055  					t.Errorf("test %d: signer %v address: %v not in result signers %d", i, accounts.name(address), address, cnt)
  1056  					continue
  1057  				}
  1058  			}
  1059  		} else {
  1060  			// check signers official 21 node
  1061  			firstLevel := map[common.Address]int{}
  1062  			secondLevel := map[common.Address]int{}
  1063  			thirdLevel := map[common.Address]int{}
  1064  			otherLevel := map[common.Address]int{}
  1065  
  1066  			for signer, tally := range tt.result.Tally {
  1067  				switch tally {
  1068  				case 5000:
  1069  					firstLevel[accounts.address(signer)] = 0
  1070  				case 4000:
  1071  					secondLevel[accounts.address(signer)] = 0
  1072  				case 3000:
  1073  					thirdLevel[accounts.address(signer)] = 0
  1074  				case 2000:
  1075  					otherLevel[accounts.address(signer)] = 0
  1076  
  1077  				}
  1078  
  1079  			}
  1080  			var l1, l2, l3, l4 int
  1081  			for _, signer := range snap.Signers {
  1082  				if _, ok := firstLevel[*signer]; ok {
  1083  					l1 += 1
  1084  					continue
  1085  				}
  1086  				if _, ok := secondLevel[*signer]; ok {
  1087  					l2 += 1
  1088  					continue
  1089  				}
  1090  				if _, ok := thirdLevel[*signer]; ok {
  1091  					l3 += 1
  1092  					continue
  1093  				}
  1094  				if _, ok := otherLevel[*signer]; ok {
  1095  					l4 += 1
  1096  				}
  1097  			}
  1098  			if l1 != 10 || l2 != 6 || l3 != 4 || l4 != 1 {
  1099  				t.Errorf("test %d: signer not select right count from different level l1 = %d, l2 = %d, l3 = %d, l4 = %d", i, l1, l2, l3, l4)
  1100  			}
  1101  
  1102  		}
  1103  
  1104  		// check tally
  1105  		if len(tt.result.Tally) != len(snap.Tally) {
  1106  			t.Errorf("test %d: tally length result %d, snap %d dismatch", i, len(tt.result.Tally), len(snap.Tally))
  1107  		}
  1108  		for name, tally := range tt.result.Tally {
  1109  			if big.NewInt(int64(tally)).Cmp(snap.Tally[accounts.address(name)]) != 0 {
  1110  				t.Errorf("test %d: tally %v address: %v, tally:%v ,result: %v", i, name, accounts.address(name), snap.Tally[accounts.address(name)], big.NewInt(int64(tally)))
  1111  				continue
  1112  			}
  1113  		}
  1114  		// check voters
  1115  		if len(tt.result.Voters) != len(snap.Voters) {
  1116  			t.Errorf("test %d: voter length result %d, snap %d dismatch", i, len(tt.result.Voters), len(snap.Voters))
  1117  		}
  1118  		for name, number := range tt.result.Voters {
  1119  			if snap.Voters[accounts.address(name)].Cmp(big.NewInt(int64(number))) != 0 {
  1120  				t.Errorf("test %d: voter %v address: %v, number:%v ,result: %v", i, name, accounts.address(name), snap.Voters[accounts.address(name)], big.NewInt(int64(number)))
  1121  				continue
  1122  			}
  1123  		}
  1124  		// check votes
  1125  
  1126  		if len(tt.result.Votes) != len(snap.Votes) {
  1127  			t.Errorf("test %d: votes length result %d, snap %d dismatch", i, len(tt.result.Votes), len(snap.Votes))
  1128  		}
  1129  		for name, vote := range tt.result.Votes {
  1130  			snapVote, ok := snap.Votes[accounts.address(name)]
  1131  			if !ok {
  1132  				t.Errorf("test %d: votes %v address: %v can not found", i, name, accounts.address(name))
  1133  
  1134  			}
  1135  			if snapVote.Voter != accounts.address(vote.voter) {
  1136  				t.Errorf("test %d: votes voter dismatch %v address: %v  , show in snap is %v address: %v", i, vote.voter, accounts.address(vote.voter), accounts.name(snapVote.Voter), snapVote.Voter)
  1137  			}
  1138  			if snapVote.Candidate != accounts.address(vote.candidate) {
  1139  				t.Errorf("test %d: votes candidate dismatch %v address: %v , show in snap is %v address: %v ", i, vote.candidate, accounts.address(vote.candidate), accounts.name(snapVote.Candidate), snapVote.Candidate)
  1140  			}
  1141  			if snapVote.Stake.Cmp(big.NewInt(int64(vote.stake))) != 0 {
  1142  				t.Errorf("test %d: votes stake dismatch %v ,show in snap is %v ", i, vote.stake, snapVote.Stake)
  1143  			}
  1144  		}
  1145  
  1146  	}
  1147  }