github.com/klaytn/klaytn@v1.12.1/consensus/istanbul/backend/engine_test.go (about)

     1  // Modifications Copyright 2020 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from quorum/consensus/istanbul/backend/engine_test.go (2020/04/16).
    19  // Modified and improved for the klaytn development.
    20  
    21  package backend
    22  
    23  import (
    24  	"bytes"
    25  	"crypto/ecdsa"
    26  	"math/big"
    27  	"reflect"
    28  	"sort"
    29  	"strings"
    30  	"testing"
    31  	"time"
    32  
    33  	"github.com/klaytn/klaytn/blockchain"
    34  	"github.com/klaytn/klaytn/blockchain/types"
    35  	"github.com/klaytn/klaytn/blockchain/vm"
    36  	"github.com/klaytn/klaytn/common"
    37  	"github.com/klaytn/klaytn/common/hexutil"
    38  	"github.com/klaytn/klaytn/consensus"
    39  	"github.com/klaytn/klaytn/consensus/istanbul"
    40  	"github.com/klaytn/klaytn/consensus/istanbul/core"
    41  	"github.com/klaytn/klaytn/crypto"
    42  	"github.com/klaytn/klaytn/params"
    43  	"github.com/klaytn/klaytn/reward"
    44  	"github.com/klaytn/klaytn/rlp"
    45  	"github.com/stretchr/testify/assert"
    46  )
    47  
    48  // These variables are the global variables of the test blockchain.
    49  var (
    50  	nodeKeys []*ecdsa.PrivateKey
    51  	addrs    []common.Address
    52  )
    53  
    54  // These are the types in order to add a custom configuration of the test chain.
    55  // You may need to create a configuration type if necessary.
    56  type (
    57  	istanbulCompatibleBlock  *big.Int
    58  	LondonCompatibleBlock    *big.Int
    59  	EthTxTypeCompatibleBlock *big.Int
    60  	magmaCompatibleBlock     *big.Int
    61  	koreCompatibleBlock      *big.Int
    62  )
    63  
    64  type (
    65  	minimumStake           *big.Int
    66  	mintingAmount          *big.Int
    67  	stakingUpdateInterval  uint64
    68  	proposerUpdateInterval uint64
    69  	proposerPolicy         uint64
    70  	governanceMode         string
    71  	epoch                  uint64
    72  	subGroupSize           uint64
    73  	blockPeriod            uint64
    74  )
    75  
    76  // makeCommittedSeals returns a list of committed seals for the global variable nodeKeys.
    77  func makeCommittedSeals(hash common.Hash) [][]byte {
    78  	committedSeals := make([][]byte, len(nodeKeys))
    79  	hashData := crypto.Keccak256(core.PrepareCommittedSeal(hash))
    80  	for i, key := range nodeKeys {
    81  		sig, _ := crypto.Sign(hashData, key)
    82  		committedSeals[i] = make([]byte, types.IstanbulExtraSeal)
    83  		copy(committedSeals[i][:], sig)
    84  	}
    85  	return committedSeals
    86  }
    87  
    88  // Include a node from the global nodeKeys and addrs
    89  func includeNode(addr common.Address, key *ecdsa.PrivateKey) {
    90  	for _, a := range addrs {
    91  		if a.String() == addr.String() {
    92  			// already exists
    93  			return
    94  		}
    95  	}
    96  	nodeKeys = append(nodeKeys, key)
    97  	addrs = append(addrs, addr)
    98  }
    99  
   100  // Exclude a node from the global nodeKeys and addrs
   101  func excludeNodeByAddr(target common.Address) {
   102  	for i, a := range addrs {
   103  		if a.String() == target.String() {
   104  			nodeKeys = append(nodeKeys[:i], nodeKeys[i+1:]...)
   105  			addrs = append(addrs[:i], addrs[i+1:]...)
   106  			break
   107  		}
   108  	}
   109  }
   110  
   111  // in this test, we can set n to 1, and it means we can process Istanbul and commit a
   112  // block by one node. Otherwise, if n is larger than 1, we have to generate
   113  // other fake events to process Istanbul.
   114  func newBlockChain(n int, items ...interface{}) (*blockchain.BlockChain, *backend) {
   115  	// generate a genesis block
   116  	genesis := blockchain.DefaultGenesisBlock()
   117  	genesis.Config = params.TestChainConfig.Copy()
   118  	genesis.Timestamp = uint64(time.Now().Unix())
   119  
   120  	var (
   121  		key    *ecdsa.PrivateKey
   122  		period = istanbul.DefaultConfig.BlockPeriod
   123  	)
   124  	// force enable Istanbul engine and governance
   125  	genesis.Config.Istanbul = params.GetDefaultIstanbulConfig()
   126  	genesis.Config.Governance = params.GetDefaultGovernanceConfig()
   127  	for _, item := range items {
   128  		switch v := item.(type) {
   129  		case istanbulCompatibleBlock:
   130  			genesis.Config.IstanbulCompatibleBlock = v
   131  		case LondonCompatibleBlock:
   132  			genesis.Config.LondonCompatibleBlock = v
   133  		case EthTxTypeCompatibleBlock:
   134  			genesis.Config.EthTxTypeCompatibleBlock = v
   135  		case magmaCompatibleBlock:
   136  			genesis.Config.MagmaCompatibleBlock = v
   137  		case koreCompatibleBlock:
   138  			genesis.Config.KoreCompatibleBlock = v
   139  		case proposerPolicy:
   140  			genesis.Config.Istanbul.ProposerPolicy = uint64(v)
   141  		case epoch:
   142  			genesis.Config.Istanbul.Epoch = uint64(v)
   143  		case subGroupSize:
   144  			genesis.Config.Istanbul.SubGroupSize = uint64(v)
   145  		case minimumStake:
   146  			genesis.Config.Governance.Reward.MinimumStake = v
   147  		case stakingUpdateInterval:
   148  			genesis.Config.Governance.Reward.StakingUpdateInterval = uint64(v)
   149  		case proposerUpdateInterval:
   150  			genesis.Config.Governance.Reward.ProposerUpdateInterval = uint64(v)
   151  		case mintingAmount:
   152  			genesis.Config.Governance.Reward.MintingAmount = v
   153  		case governanceMode:
   154  			genesis.Config.Governance.GovernanceMode = string(v)
   155  		case *ecdsa.PrivateKey:
   156  			key = v
   157  		case blockPeriod:
   158  			period = uint64(v)
   159  		}
   160  	}
   161  	nodeKeys = make([]*ecdsa.PrivateKey, n)
   162  	addrs = make([]common.Address, n)
   163  
   164  	var b *backend
   165  	if len(items) != 0 {
   166  		b = newTestBackendWithConfig(genesis.Config, period, key)
   167  	} else {
   168  		b = newTestBackend()
   169  	}
   170  
   171  	nodeKeys[0] = b.privateKey
   172  	addrs[0] = b.address // if governance mode is single, this address is the governing node address
   173  	for i := 1; i < n; i++ {
   174  		nodeKeys[i], _ = crypto.GenerateKey()
   175  		addrs[i] = crypto.PubkeyToAddress(nodeKeys[i].PublicKey)
   176  	}
   177  
   178  	appendValidators(genesis, addrs)
   179  
   180  	genesis.MustCommit(b.db)
   181  
   182  	bc, err := blockchain.NewBlockChain(b.db, nil, genesis.Config, b, vm.Config{})
   183  	if err != nil {
   184  		panic(err)
   185  	}
   186  	b.governance.SetBlockchain(bc)
   187  
   188  	if b.Start(bc, bc.CurrentBlock, bc.HasBadBlock) != nil {
   189  		panic(err)
   190  	}
   191  
   192  	return bc, b
   193  }
   194  
   195  func appendValidators(genesis *blockchain.Genesis, addrs []common.Address) {
   196  	if len(genesis.ExtraData) < types.IstanbulExtraVanity {
   197  		genesis.ExtraData = append(genesis.ExtraData, bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity)...)
   198  	}
   199  	genesis.ExtraData = genesis.ExtraData[:types.IstanbulExtraVanity]
   200  
   201  	ist := &types.IstanbulExtra{
   202  		Validators:    addrs,
   203  		Seal:          []byte{},
   204  		CommittedSeal: [][]byte{},
   205  	}
   206  
   207  	istPayload, err := rlp.EncodeToBytes(&ist)
   208  	if err != nil {
   209  		panic("failed to encode istanbul extra")
   210  	}
   211  	genesis.ExtraData = append(genesis.ExtraData, istPayload...)
   212  }
   213  
   214  func makeHeader(parent *types.Block, config *istanbul.Config) *types.Header {
   215  	header := &types.Header{
   216  		ParentHash: parent.Hash(),
   217  		Number:     parent.Number().Add(parent.Number(), common.Big1),
   218  		GasUsed:    0,
   219  		Extra:      parent.Extra(),
   220  		Time:       new(big.Int).Add(parent.Time(), new(big.Int).SetUint64(config.BlockPeriod)),
   221  		BlockScore: defaultBlockScore,
   222  	}
   223  	if parent.Header().BaseFee != nil {
   224  		// We don't have chainConfig so the BaseFee of the current block is set by parent's for test
   225  		header.BaseFee = parent.Header().BaseFee
   226  	}
   227  	return header
   228  }
   229  
   230  func makeBlock(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block {
   231  	block := makeBlockWithoutSeal(chain, engine, parent)
   232  	stopCh := make(chan struct{})
   233  	result, err := engine.Seal(chain, block, stopCh)
   234  	if err != nil {
   235  		panic(err)
   236  	}
   237  	return result
   238  }
   239  
   240  // makeBlockWithSeal creates a block with the proposer seal as well as all committed seals of validators.
   241  func makeBlockWithSeal(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block {
   242  	blockWithoutSeal := makeBlockWithoutSeal(chain, engine, parent)
   243  
   244  	// add proposer seal for the block
   245  	block, err := engine.updateBlock(blockWithoutSeal)
   246  	if err != nil {
   247  		panic(err)
   248  	}
   249  
   250  	// write validators committed seals to the block
   251  	header := block.Header()
   252  	committedSeals := makeCommittedSeals(block.Hash())
   253  	err = writeCommittedSeals(header, committedSeals)
   254  	if err != nil {
   255  		panic(err)
   256  	}
   257  	block = block.WithSeal(header)
   258  
   259  	return block
   260  }
   261  
   262  func makeBlockWithoutSeal(chain *blockchain.BlockChain, engine *backend, parent *types.Block) *types.Block {
   263  	header := makeHeader(parent, engine.config)
   264  	if err := engine.Prepare(chain, header); err != nil {
   265  		panic(err)
   266  	}
   267  	state, _ := chain.StateAt(parent.Root())
   268  	block, _ := engine.Finalize(chain, header, state, nil, nil)
   269  	return block
   270  }
   271  
   272  func TestPrepare(t *testing.T) {
   273  	chain, engine := newBlockChain(1)
   274  	defer engine.Stop()
   275  
   276  	header := makeHeader(chain.Genesis(), engine.config)
   277  	err := engine.Prepare(chain, header)
   278  	if err != nil {
   279  		t.Errorf("error mismatch: have %v, want nil", err)
   280  	}
   281  
   282  	header.ParentHash = common.HexToHash("0x1234567890")
   283  	err = engine.Prepare(chain, header)
   284  	if err != consensus.ErrUnknownAncestor {
   285  		t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrUnknownAncestor)
   286  	}
   287  }
   288  
   289  func TestSealStopChannel(t *testing.T) {
   290  	chain, engine := newBlockChain(4)
   291  	defer engine.Stop()
   292  	oldStakingManager := setTestStakingInfo(nil)
   293  	defer reward.SetTestStakingManager(oldStakingManager)
   294  
   295  	block := makeBlockWithoutSeal(chain, engine, chain.Genesis())
   296  	stop := make(chan struct{}, 1)
   297  	eventSub := engine.EventMux().Subscribe(istanbul.RequestEvent{})
   298  	eventLoop := func() {
   299  		select {
   300  		case ev := <-eventSub.Chan():
   301  			_, ok := ev.Data.(istanbul.RequestEvent)
   302  			if !ok {
   303  				t.Errorf("unexpected event comes: %v", reflect.TypeOf(ev.Data))
   304  			}
   305  			stop <- struct{}{}
   306  		}
   307  		eventSub.Unsubscribe()
   308  	}
   309  	go eventLoop()
   310  
   311  	finalBlock, err := engine.Seal(chain, block, stop)
   312  	if err != nil {
   313  		t.Errorf("error mismatch: have %v, want nil", err)
   314  	}
   315  
   316  	if finalBlock != nil {
   317  		t.Errorf("block mismatch: have %v, want nil", finalBlock)
   318  	}
   319  }
   320  
   321  func TestSealCommitted(t *testing.T) {
   322  	chain, engine := newBlockChain(1)
   323  	defer engine.Stop()
   324  	oldStakingManager := setTestStakingInfo(nil)
   325  	defer reward.SetTestStakingManager(oldStakingManager)
   326  
   327  	block := makeBlockWithoutSeal(chain, engine, chain.Genesis())
   328  	expectedBlock, _ := engine.updateBlock(block)
   329  
   330  	actualBlock, err := engine.Seal(chain, block, make(chan struct{}))
   331  	if err != nil {
   332  		t.Errorf("error mismatch: have %v, want %v", err, expectedBlock)
   333  	}
   334  
   335  	if actualBlock.Hash() != expectedBlock.Hash() {
   336  		t.Errorf("hash mismatch: have %v, want %v", actualBlock.Hash(), expectedBlock.Hash())
   337  	}
   338  }
   339  
   340  func TestVerifyHeader(t *testing.T) {
   341  	var configItems []interface{}
   342  	configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
   343  	configItems = append(configItems, LondonCompatibleBlock(new(big.Int).SetUint64(0)))
   344  	configItems = append(configItems, EthTxTypeCompatibleBlock(new(big.Int).SetUint64(0)))
   345  	configItems = append(configItems, magmaCompatibleBlock(new(big.Int).SetUint64(0)))
   346  	configItems = append(configItems, koreCompatibleBlock(new(big.Int).SetUint64(0)))
   347  	chain, engine := newBlockChain(1, configItems...)
   348  	defer engine.Stop()
   349  
   350  	// errEmptyCommittedSeals case
   351  	block := makeBlockWithoutSeal(chain, engine, chain.Genesis())
   352  	block, _ = engine.updateBlock(block)
   353  	err := engine.VerifyHeader(chain, block.Header(), false)
   354  	if err != errEmptyCommittedSeals {
   355  		t.Errorf("error mismatch: have %v, want %v", err, errEmptyCommittedSeals)
   356  	}
   357  
   358  	// short extra data
   359  	header := block.Header()
   360  	header.Extra = []byte{}
   361  	err = engine.VerifyHeader(chain, header, false)
   362  	if err != errInvalidExtraDataFormat {
   363  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat)
   364  	}
   365  	// incorrect extra format
   366  	header.Extra = []byte("0000000000000000000000000000000012300000000000000000000000000000000000000000000000000000000000000000")
   367  	err = engine.VerifyHeader(chain, header, false)
   368  	if err != errInvalidExtraDataFormat {
   369  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidExtraDataFormat)
   370  	}
   371  
   372  	// invalid difficulty
   373  	block = makeBlockWithoutSeal(chain, engine, chain.Genesis())
   374  	header = block.Header()
   375  	header.BlockScore = big.NewInt(2)
   376  	err = engine.VerifyHeader(chain, header, false)
   377  	if err != errInvalidBlockScore {
   378  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidBlockScore)
   379  	}
   380  
   381  	// invalid timestamp
   382  	block = makeBlockWithoutSeal(chain, engine, chain.Genesis())
   383  	header = block.Header()
   384  	header.Time = new(big.Int).Add(chain.Genesis().Time(), new(big.Int).SetUint64(engine.config.BlockPeriod-1))
   385  	err = engine.VerifyHeader(chain, header, false)
   386  	if err != errInvalidTimestamp {
   387  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidTimestamp)
   388  	}
   389  
   390  	// future block
   391  	block = makeBlockWithoutSeal(chain, engine, chain.Genesis())
   392  	header = block.Header()
   393  	header.Time = new(big.Int).Add(big.NewInt(now().Unix()), new(big.Int).SetUint64(10))
   394  	err = engine.VerifyHeader(chain, header, false)
   395  	if err != consensus.ErrFutureBlock {
   396  		t.Errorf("error mismatch: have %v, want %v", err, consensus.ErrFutureBlock)
   397  	}
   398  
   399  	// TODO-Klaytn: add more tests for header.Governance, header.Rewardbase, header.Vote
   400  }
   401  
   402  func TestVerifySeal(t *testing.T) {
   403  	chain, engine := newBlockChain(1)
   404  	defer engine.Stop()
   405  	oldStakingManager := setTestStakingInfo(nil)
   406  	defer reward.SetTestStakingManager(oldStakingManager)
   407  
   408  	genesis := chain.Genesis()
   409  
   410  	// cannot verify genesis
   411  	err := engine.VerifySeal(chain, genesis.Header())
   412  	if err != errUnknownBlock {
   413  		t.Errorf("error mismatch: have %v, want %v", err, errUnknownBlock)
   414  	}
   415  	block := makeBlock(chain, engine, genesis)
   416  
   417  	// clean cache before testing
   418  	signatureAddresses.Purge()
   419  
   420  	// change block content
   421  	header := block.Header()
   422  	header.Number = big.NewInt(4)
   423  	block1 := block.WithSeal(header)
   424  	err = engine.VerifySeal(chain, block1.Header())
   425  	if err != errUnauthorized {
   426  		t.Errorf("error mismatch: have %v, want %v", err, errUnauthorized)
   427  	}
   428  
   429  	// clean cache before testing
   430  	signatureAddresses.Purge()
   431  
   432  	// unauthorized users but still can get correct signer address
   433  	engine.privateKey, _ = crypto.GenerateKey()
   434  	err = engine.VerifySeal(chain, block.Header())
   435  	if err != nil {
   436  		t.Errorf("error mismatch: have %v, want nil", err)
   437  	}
   438  }
   439  
   440  func TestVerifyHeaders(t *testing.T) {
   441  	chain, engine := newBlockChain(1)
   442  	defer engine.Stop()
   443  
   444  	oldStakingManager := setTestStakingInfo(nil)
   445  	defer reward.SetTestStakingManager(oldStakingManager)
   446  
   447  	genesis := chain.Genesis()
   448  
   449  	// success case
   450  	headers := []*types.Header{}
   451  	blocks := []*types.Block{}
   452  	size := 100
   453  
   454  	for i := 0; i < size; i++ {
   455  		var b *types.Block
   456  		if i == 0 {
   457  			b = makeBlockWithoutSeal(chain, engine, genesis)
   458  			b, _ = engine.updateBlock(b)
   459  			engine.db.WriteHeader(b.Header())
   460  		} else {
   461  			b = makeBlockWithoutSeal(chain, engine, blocks[i-1])
   462  			b, _ = engine.updateBlock(b)
   463  			engine.db.WriteHeader(b.Header())
   464  		}
   465  		blocks = append(blocks, b)
   466  		headers = append(headers, blocks[i].Header())
   467  	}
   468  
   469  	// proceed time to avoid future block errors
   470  	now = func() time.Time {
   471  		return time.Unix(headers[size-1].Time.Int64(), 0)
   472  	}
   473  	defer func() {
   474  		now = time.Now
   475  	}()
   476  
   477  	_, results := engine.VerifyHeaders(chain, headers, nil)
   478  	const timeoutDura = 2 * time.Second
   479  	timeout := time.NewTimer(timeoutDura)
   480  	index := 0
   481  OUT1:
   482  	for {
   483  		select {
   484  		case err := <-results:
   485  			if err != nil {
   486  				if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals {
   487  					t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals", err)
   488  					break OUT1
   489  				}
   490  			}
   491  			index++
   492  			if index == size {
   493  				break OUT1
   494  			}
   495  		case <-timeout.C:
   496  			break OUT1
   497  		}
   498  	}
   499  	// abort cases
   500  	abort, results := engine.VerifyHeaders(chain, headers, nil)
   501  	timeout = time.NewTimer(timeoutDura)
   502  	index = 0
   503  OUT2:
   504  	for {
   505  		select {
   506  		case err := <-results:
   507  			if err != nil {
   508  				if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals {
   509  					t.Errorf("error mismatch: have %v, want errEmptyCommittedSeals|errInvalidCommittedSeals", err)
   510  					break OUT2
   511  				}
   512  			}
   513  			index++
   514  			if index == 5 {
   515  				abort <- struct{}{}
   516  			}
   517  			if index >= size {
   518  				t.Errorf("verifyheaders should be aborted")
   519  				break OUT2
   520  			}
   521  		case <-timeout.C:
   522  			break OUT2
   523  		}
   524  	}
   525  	// error header cases
   526  	headers[2].Number = big.NewInt(100)
   527  	abort, results = engine.VerifyHeaders(chain, headers, nil)
   528  	timeout = time.NewTimer(timeoutDura)
   529  	index = 0
   530  	errors := 0
   531  	expectedErrors := 2
   532  OUT3:
   533  	for {
   534  		select {
   535  		case err := <-results:
   536  			if err != nil {
   537  				if err != errEmptyCommittedSeals && err != errInvalidCommittedSeals {
   538  					errors++
   539  				}
   540  			}
   541  			index++
   542  			if index == size {
   543  				if errors != expectedErrors {
   544  					t.Errorf("error mismatch: have %v, want %v", err, expectedErrors)
   545  				}
   546  				break OUT3
   547  			}
   548  		case <-timeout.C:
   549  			break OUT3
   550  		}
   551  	}
   552  }
   553  
   554  func TestPrepareExtra(t *testing.T) {
   555  	validators := make([]common.Address, 4)
   556  	validators[0] = common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a"))
   557  	validators[1] = common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212"))
   558  	validators[2] = common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6"))
   559  	validators[3] = common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440"))
   560  
   561  	vanity := make([]byte, types.IstanbulExtraVanity)
   562  	expectedResult := append(vanity, hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0")...)
   563  
   564  	h := &types.Header{
   565  		Extra: vanity,
   566  	}
   567  
   568  	payload, err := prepareExtra(h, validators)
   569  	if err != nil {
   570  		t.Errorf("error mismatch: have %v, want: nil", err)
   571  	}
   572  	if !reflect.DeepEqual(payload, expectedResult) {
   573  		t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult)
   574  	}
   575  
   576  	// append useless information to extra-data
   577  	h.Extra = append(vanity, make([]byte, 15)...)
   578  
   579  	payload, err = prepareExtra(h, validators)
   580  	if !reflect.DeepEqual(payload, expectedResult) {
   581  		t.Errorf("payload mismatch: have %v, want %v", payload, expectedResult)
   582  	}
   583  }
   584  
   585  func TestWriteSeal(t *testing.T) {
   586  	vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity)
   587  	istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0")
   588  	expectedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.IstanbulExtraSeal-3)...)
   589  	expectedIstExtra := &types.IstanbulExtra{
   590  		Validators: []common.Address{
   591  			common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")),
   592  			common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")),
   593  			common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")),
   594  			common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")),
   595  		},
   596  		Seal:          expectedSeal,
   597  		CommittedSeal: [][]byte{},
   598  	}
   599  	var expectedErr error
   600  
   601  	h := &types.Header{
   602  		Extra: append(vanity, istRawData...),
   603  	}
   604  
   605  	// normal case
   606  	err := writeSeal(h, expectedSeal)
   607  	if err != expectedErr {
   608  		t.Errorf("error mismatch: have %v, want %v", err, expectedErr)
   609  	}
   610  
   611  	// verify istanbul extra-data
   612  	istExtra, err := types.ExtractIstanbulExtra(h)
   613  	if err != nil {
   614  		t.Errorf("error mismatch: have %v, want nil", err)
   615  	}
   616  	if !reflect.DeepEqual(istExtra, expectedIstExtra) {
   617  		t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra)
   618  	}
   619  
   620  	// invalid seal
   621  	unexpectedSeal := append(expectedSeal, make([]byte, 1)...)
   622  	err = writeSeal(h, unexpectedSeal)
   623  	if err != errInvalidSignature {
   624  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidSignature)
   625  	}
   626  }
   627  
   628  func TestWriteCommittedSeals(t *testing.T) {
   629  	vanity := bytes.Repeat([]byte{0x00}, types.IstanbulExtraVanity)
   630  	istRawData := hexutil.MustDecode("0xf858f8549444add0ec310f115a0e603b2d7db9f067778eaf8a94294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212946beaaed781d2d2ab6350f5c4566a2c6eaac407a6948be76812f765c24641ec63dc2852b378aba2b44080c0")
   631  	expectedCommittedSeal := append([]byte{1, 2, 3}, bytes.Repeat([]byte{0x00}, types.IstanbulExtraSeal-3)...)
   632  	expectedIstExtra := &types.IstanbulExtra{
   633  		Validators: []common.Address{
   634  			common.BytesToAddress(hexutil.MustDecode("0x44add0ec310f115a0e603b2d7db9f067778eaf8a")),
   635  			common.BytesToAddress(hexutil.MustDecode("0x294fc7e8f22b3bcdcf955dd7ff3ba2ed833f8212")),
   636  			common.BytesToAddress(hexutil.MustDecode("0x6beaaed781d2d2ab6350f5c4566a2c6eaac407a6")),
   637  			common.BytesToAddress(hexutil.MustDecode("0x8be76812f765c24641ec63dc2852b378aba2b440")),
   638  		},
   639  		Seal:          []byte{},
   640  		CommittedSeal: [][]byte{expectedCommittedSeal},
   641  	}
   642  	var expectedErr error
   643  
   644  	h := &types.Header{
   645  		Extra: append(vanity, istRawData...),
   646  	}
   647  
   648  	// normal case
   649  	err := writeCommittedSeals(h, [][]byte{expectedCommittedSeal})
   650  	if err != expectedErr {
   651  		t.Errorf("error mismatch: have %v, want %v", err, expectedErr)
   652  	}
   653  
   654  	// verify istanbul extra-data
   655  	istExtra, err := types.ExtractIstanbulExtra(h)
   656  	if err != nil {
   657  		t.Errorf("error mismatch: have %v, want nil", err)
   658  	}
   659  	if !reflect.DeepEqual(istExtra, expectedIstExtra) {
   660  		t.Errorf("extra data mismatch: have %v, want %v", istExtra, expectedIstExtra)
   661  	}
   662  
   663  	// invalid seal
   664  	unexpectedCommittedSeal := append(expectedCommittedSeal, make([]byte, 1)...)
   665  	err = writeCommittedSeals(h, [][]byte{unexpectedCommittedSeal})
   666  	if err != errInvalidCommittedSeals {
   667  		t.Errorf("error mismatch: have %v, want %v", err, errInvalidCommittedSeals)
   668  	}
   669  }
   670  
   671  func TestRewardDistribution(t *testing.T) {
   672  	type vote = map[string]interface{}
   673  	type expected = map[int]uint64
   674  	type testcase struct {
   675  		length   int // total number of blocks to simulate
   676  		votes    map[int]vote
   677  		expected expected
   678  	}
   679  
   680  	mintAmount := uint64(1)
   681  	koreBlock := uint64(9)
   682  	testEpoch := 3
   683  
   684  	testcases := []testcase{
   685  		{
   686  			12,
   687  			map[int]vote{
   688  				1: {"reward.mintingamount": "2"}, // activated at block 7 (activation is before-Kore)
   689  				4: {"reward.mintingamount": "3"}, // activated at block 9 (activation is after-Kore)
   690  			},
   691  			map[int]uint64{
   692  				1:  1,
   693  				2:  2,
   694  				3:  3,
   695  				4:  4,
   696  				5:  5,
   697  				6:  6,
   698  				7:  8, // 2 is minted from now
   699  				8:  10,
   700  				9:  13, // 3 is minted from now
   701  				10: 16,
   702  				11: 19,
   703  				12: 22,
   704  				13: 25,
   705  			},
   706  		},
   707  	}
   708  
   709  	var configItems []interface{}
   710  	configItems = append(configItems, epoch(testEpoch))
   711  	configItems = append(configItems, mintingAmount(new(big.Int).SetUint64(mintAmount)))
   712  	configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
   713  	configItems = append(configItems, LondonCompatibleBlock(new(big.Int).SetUint64(0)))
   714  	configItems = append(configItems, EthTxTypeCompatibleBlock(new(big.Int).SetUint64(0)))
   715  	configItems = append(configItems, magmaCompatibleBlock(new(big.Int).SetUint64(0)))
   716  	configItems = append(configItems, koreCompatibleBlock(new(big.Int).SetUint64(koreBlock)))
   717  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
   718  
   719  	chain, engine := newBlockChain(1, configItems...)
   720  	assert.Equal(t, uint64(testEpoch), engine.governance.CurrentParams().Epoch())
   721  	assert.Equal(t, mintAmount, engine.governance.CurrentParams().MintingAmountBig().Uint64())
   722  
   723  	var previousBlock, currentBlock *types.Block = nil, chain.Genesis()
   724  
   725  	for _, tc := range testcases {
   726  		// Place a vote if a vote is scheduled in upcoming block
   727  		// Note that we're building (head+1)'th block here.
   728  		for num := 0; num <= tc.length; num++ {
   729  			for k, v := range tc.votes[num+1] {
   730  				ok := engine.governance.AddVote(k, v)
   731  				assert.True(t, ok)
   732  			}
   733  
   734  			// Create a block
   735  			previousBlock = currentBlock
   736  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
   737  			_, err := chain.InsertChain(types.Blocks{currentBlock})
   738  			assert.NoError(t, err)
   739  
   740  			// check balance
   741  			addr := currentBlock.Rewardbase()
   742  			state, err := chain.State()
   743  			assert.NoError(t, err)
   744  			bal := state.GetBalance(addr)
   745  
   746  			assert.Equal(t, tc.expected[num+1], bal.Uint64(), "wrong at block %d", num+1)
   747  		}
   748  	}
   749  }
   750  
   751  func makeSnapshotTestConfigItems() []interface{} {
   752  	return []interface{}{
   753  		stakingUpdateInterval(1),
   754  		proposerUpdateInterval(1),
   755  		proposerPolicy(params.WeightedRandom),
   756  	}
   757  }
   758  
   759  // Set StakingInfo with given amount for nodeKeys. If amounts == nil, set to 0 amounts.
   760  // Returns the original (old) StakingManager. Call `reward.SetTestStakingManager(oldStakingManager)`
   761  func setTestStakingInfo(amounts []uint64) *reward.StakingManager {
   762  	if amounts == nil {
   763  		amounts = make([]uint64, len(nodeKeys))
   764  	}
   765  
   766  	stakingInfo := &reward.StakingInfo{
   767  		BlockNum: 0,
   768  	}
   769  	for idx, key := range nodeKeys {
   770  		addr := crypto.PubkeyToAddress(key.PublicKey)
   771  
   772  		pk, _ := crypto.GenerateKey()
   773  		rewardAddr := crypto.PubkeyToAddress(pk.PublicKey)
   774  
   775  		stakingInfo.CouncilNodeAddrs = append(stakingInfo.CouncilNodeAddrs, addr)
   776  		stakingInfo.CouncilStakingAddrs = append(stakingInfo.CouncilStakingAddrs, addr)
   777  		stakingInfo.CouncilStakingAmounts = append(stakingInfo.CouncilStakingAmounts, amounts[idx])
   778  		stakingInfo.CouncilRewardAddrs = append(stakingInfo.CouncilRewardAddrs, rewardAddr)
   779  	}
   780  
   781  	// Save old StakingManager, overwrite to the fake one.
   782  	oldStakingManager := reward.GetStakingManager()
   783  	reward.SetTestStakingManagerWithStakingInfoCache(stakingInfo)
   784  	return oldStakingManager
   785  }
   786  
   787  func toAddressList(validators []istanbul.Validator) []common.Address {
   788  	addresses := make([]common.Address, len(validators))
   789  	for idx, val := range validators {
   790  		addresses[idx] = val.Address()
   791  	}
   792  	return addresses
   793  }
   794  
   795  func copyAndSortAddrs(addrs []common.Address) []common.Address {
   796  	copied := make([]common.Address, len(addrs))
   797  	copy(copied, addrs)
   798  
   799  	sort.Slice(copied, func(i, j int) bool {
   800  		return strings.Compare(copied[i].String(), copied[j].String()) < 0
   801  	})
   802  
   803  	return copied
   804  }
   805  
   806  func makeExpectedResult(indices []int, candidate []common.Address) []common.Address {
   807  	expected := make([]common.Address, len(indices))
   808  	for eIdx, cIdx := range indices {
   809  		expected[eIdx] = candidate[cIdx]
   810  	}
   811  	return copyAndSortAddrs(expected)
   812  }
   813  
   814  // Asserts taht if all (key,value) pairs of `subset` exists in `set`
   815  func assertMapSubset(t *testing.T, subset, set map[string]interface{}) {
   816  	for k, v := range subset {
   817  		assert.Equal(t, set[k], v)
   818  	}
   819  }
   820  
   821  func TestSnapshot_Validators_AfterMinimumStakingVotes(t *testing.T) {
   822  	type vote struct {
   823  		key   string
   824  		value interface{}
   825  	}
   826  	type expected struct {
   827  		blocks     []uint64
   828  		validators []int
   829  		demoted    []int
   830  	}
   831  	type testcase struct {
   832  		stakingAmounts []uint64
   833  		votes          []vote
   834  		expected       []expected
   835  	}
   836  
   837  	testcases := []testcase{
   838  		{
   839  			// test the validators are updated properly when minimum staking is changed in none mode
   840  			[]uint64{8000000, 7000000, 6000000, 5000000},
   841  			[]vote{
   842  				{"governance.governancemode", "none"}, // voted on epoch 1, applied from 6-8
   843  				{"reward.minimumstake", "5500000"},    // voted on epoch 2, applied from 9-11
   844  				{"reward.minimumstake", "6500000"},    // voted on epoch 3, applied from 12-14
   845  				{"reward.minimumstake", "7500000"},    // voted on epoch 4, applied from 15-17
   846  				{"reward.minimumstake", "8500000"},    // voted on epoch 5, applied from 18-20
   847  				{"reward.minimumstake", "7500000"},    // voted on epoch 6, applied from 21-23
   848  				{"reward.minimumstake", "6500000"},    // voted on epoch 7, applied from 24-26
   849  				{"reward.minimumstake", "5500000"},    // voted on epoch 8, applied from 27-29
   850  				{"reward.minimumstake", "4500000"},    // voted on epoch 9, applied from 30-32
   851  			},
   852  			[]expected{
   853  				{[]uint64{0, 1, 2, 3, 4, 5, 6, 7, 8}, []int{0, 1, 2, 3}, []int{}},
   854  				{[]uint64{9, 10, 11}, []int{0, 1, 2}, []int{3}},
   855  				{[]uint64{12, 13, 14}, []int{0, 1}, []int{2, 3}},
   856  				{[]uint64{15, 16, 17}, []int{0}, []int{1, 2, 3}},
   857  				{[]uint64{18, 19, 20}, []int{0, 1, 2, 3}, []int{}},
   858  				{[]uint64{21, 22, 23}, []int{0}, []int{1, 2, 3}},
   859  				{[]uint64{24, 25, 26}, []int{0, 1}, []int{2, 3}},
   860  				{[]uint64{27, 28, 29}, []int{0, 1, 2}, []int{3}},
   861  				{[]uint64{30, 31, 32}, []int{0, 1, 2, 3}, []int{}},
   862  			},
   863  		},
   864  		{
   865  			// test the validators (including governing node) are updated properly when minimum staking is changed in single mode
   866  			[]uint64{5000000, 6000000, 7000000, 8000000},
   867  			[]vote{
   868  				{"reward.minimumstake", "8500000"}, // voted on epoch 1, applied from 6-8
   869  				{"reward.minimumstake", "7500000"}, // voted on epoch 2, applied from 9-11
   870  				{"reward.minimumstake", "6500000"}, // voted on epoch 3, applied from 12-14
   871  				{"reward.minimumstake", "5500000"}, // voted on epoch 4, applied from 15-17
   872  				{"reward.minimumstake", "4500000"}, // voted on epoch 5, applied from 18-20
   873  				{"reward.minimumstake", "5500000"}, // voted on epoch 6, applied from 21-23
   874  				{"reward.minimumstake", "6500000"}, // voted on epoch 7, applied from 24-26
   875  				{"reward.minimumstake", "7500000"}, // voted on epoch 8, applied from 27-29
   876  				{"reward.minimumstake", "8500000"}, // voted on epoch 9, applied from 30-32
   877  			},
   878  			[]expected{
   879  				// 0 is governing node, so it is included in the validators all the time
   880  				{[]uint64{0, 1, 2, 3, 4, 5, 6, 7, 8}, []int{0, 1, 2, 3}, []int{}},
   881  				{[]uint64{9, 10, 11}, []int{0, 3}, []int{1, 2}},
   882  				{[]uint64{12, 13, 14}, []int{0, 2, 3}, []int{1}},
   883  				{[]uint64{15, 16, 17, 18, 19, 20, 21, 22, 23}, []int{0, 1, 2, 3}, []int{}},
   884  				{[]uint64{24, 25, 26}, []int{0, 2, 3}, []int{1}},
   885  				{[]uint64{27, 28, 29}, []int{0, 3}, []int{1, 2}},
   886  				{[]uint64{30, 31, 32}, []int{0, 1, 2, 3}, []int{}},
   887  			},
   888  		},
   889  		{
   890  			// test the validators are updated properly if governing node is changed
   891  			[]uint64{6000000, 6000000, 5000000, 5000000},
   892  			[]vote{
   893  				{"reward.minimumstake", "5500000"}, // voted on epoch 1, applied from 6-8
   894  				{"governance.governingnode", 2},    // voted on epoch 2, applied from 9-11
   895  			},
   896  			[]expected{
   897  				// 0 is governing node, so it is included in the validators all the time
   898  				{[]uint64{0, 1, 2, 3, 4, 5}, []int{0, 1, 2, 3}, []int{}},
   899  				{[]uint64{6, 7, 8}, []int{0, 1}, []int{2, 3}},
   900  				{[]uint64{9, 10, 11}, []int{0, 1, 2}, []int{3}},
   901  			},
   902  		},
   903  	}
   904  
   905  	testEpoch := 3
   906  
   907  	var configItems []interface{}
   908  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
   909  	configItems = append(configItems, proposerUpdateInterval(1))
   910  	configItems = append(configItems, epoch(testEpoch))
   911  	configItems = append(configItems, governanceMode("single"))
   912  	configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000)))
   913  	configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
   914  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
   915  
   916  	for _, tc := range testcases {
   917  		chain, engine := newBlockChain(4, configItems...)
   918  		oldStakingManager := setTestStakingInfo(tc.stakingAmounts)
   919  
   920  		var previousBlock, currentBlock *types.Block = nil, chain.Genesis()
   921  
   922  		for _, v := range tc.votes {
   923  			// vote a vote in each epoch
   924  			if v.key == "governance.governingnode" {
   925  				idx := v.value.(int)
   926  				v.value = addrs[idx].String()
   927  			}
   928  			engine.governance.AddVote(v.key, v.value)
   929  
   930  			for i := 0; i < testEpoch; i++ {
   931  				previousBlock = currentBlock
   932  				currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
   933  				_, err := chain.InsertChain(types.Blocks{currentBlock})
   934  				assert.NoError(t, err)
   935  			}
   936  		}
   937  
   938  		// insert blocks on extra epoch
   939  		for i := 0; i < 2*testEpoch; i++ {
   940  			previousBlock = currentBlock
   941  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
   942  			_, err := chain.InsertChain(types.Blocks{currentBlock})
   943  			assert.NoError(t, err)
   944  		}
   945  
   946  		for _, e := range tc.expected {
   947  			for _, num := range e.blocks {
   948  				block := chain.GetBlockByNumber(num)
   949  				snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true)
   950  				assert.NoError(t, err)
   951  
   952  				validators := toAddressList(snap.ValSet.List())
   953  				demoted := toAddressList(snap.ValSet.DemotedList())
   954  
   955  				expectedValidators := makeExpectedResult(e.validators, addrs)
   956  				expectedDemoted := makeExpectedResult(e.demoted, addrs)
   957  
   958  				assert.Equal(t, expectedValidators, validators)
   959  				assert.Equal(t, expectedDemoted, demoted)
   960  			}
   961  		}
   962  
   963  		reward.SetTestStakingManager(oldStakingManager)
   964  		engine.Stop()
   965  	}
   966  }
   967  
   968  func TestSnapshot_Validators_BasedOnStaking(t *testing.T) {
   969  	type testcase struct {
   970  		stakingAmounts       []uint64 // test staking amounts of each validator
   971  		isIstanbulCompatible bool     // whether or not if the inserted block is istanbul compatible
   972  		isSingleMode         bool     // whether or not if the governance mode is single
   973  		expectedValidators   []int    // the indices of expected validators
   974  		expectedDemoted      []int    // the indices of expected demoted validators
   975  	}
   976  
   977  	testcases := []testcase{
   978  		// The following testcases are the ones before istanbul incompatible change
   979  		{
   980  			[]uint64{5000000, 5000000, 5000000, 5000000},
   981  			false,
   982  			false,
   983  			[]int{0, 1, 2, 3},
   984  			[]int{},
   985  		},
   986  		{
   987  			[]uint64{5000000, 5000000, 5000000, 6000000},
   988  			false,
   989  			false,
   990  			[]int{0, 1, 2, 3},
   991  			[]int{},
   992  		},
   993  		{
   994  			[]uint64{5000000, 5000000, 6000000, 6000000},
   995  			false,
   996  			false,
   997  			[]int{0, 1, 2, 3},
   998  			[]int{},
   999  		},
  1000  		{
  1001  			[]uint64{5000000, 6000000, 6000000, 6000000},
  1002  			false,
  1003  			false,
  1004  			[]int{0, 1, 2, 3},
  1005  			[]int{},
  1006  		},
  1007  		{
  1008  			[]uint64{6000000, 6000000, 6000000, 6000000},
  1009  			false,
  1010  			false,
  1011  			[]int{0, 1, 2, 3},
  1012  			[]int{},
  1013  		},
  1014  		// The following testcases are the ones after istanbul incompatible change
  1015  		{
  1016  			[]uint64{5000000, 5000000, 5000000, 5000000},
  1017  			true,
  1018  			false,
  1019  			[]int{0, 1, 2, 3},
  1020  			[]int{},
  1021  		},
  1022  		{
  1023  			[]uint64{5000000, 5000000, 5000000, 6000000},
  1024  			true,
  1025  			false,
  1026  			[]int{3},
  1027  			[]int{0, 1, 2},
  1028  		},
  1029  		{
  1030  			[]uint64{5000000, 5000000, 6000000, 6000000},
  1031  			true,
  1032  			false,
  1033  			[]int{2, 3},
  1034  			[]int{0, 1},
  1035  		},
  1036  		{
  1037  			[]uint64{5000000, 6000000, 6000000, 6000000},
  1038  			true,
  1039  			false,
  1040  			[]int{1, 2, 3},
  1041  			[]int{0},
  1042  		},
  1043  		{
  1044  			[]uint64{6000000, 6000000, 6000000, 6000000},
  1045  			true,
  1046  			false,
  1047  			[]int{0, 1, 2, 3},
  1048  			[]int{},
  1049  		},
  1050  		{
  1051  			[]uint64{5500001, 5500000, 5499999, 0},
  1052  			true,
  1053  			false,
  1054  			[]int{0, 1},
  1055  			[]int{2, 3},
  1056  		},
  1057  		// The following testcases are the ones for testing governing node in single mode
  1058  		// The first staking amount is of the governing node
  1059  		{
  1060  			[]uint64{6000000, 6000000, 6000000, 6000000},
  1061  			true,
  1062  			true,
  1063  			[]int{0, 1, 2, 3},
  1064  			[]int{},
  1065  		},
  1066  		{
  1067  			[]uint64{5000000, 6000000, 6000000, 6000000},
  1068  			true,
  1069  			true,
  1070  			[]int{0, 1, 2, 3},
  1071  			[]int{},
  1072  		},
  1073  		{
  1074  			[]uint64{5000000, 5000000, 6000000, 6000000},
  1075  			true,
  1076  			true,
  1077  			[]int{0, 2, 3},
  1078  			[]int{1},
  1079  		},
  1080  		{
  1081  			[]uint64{5000000, 5000000, 5000000, 6000000},
  1082  			true,
  1083  			true,
  1084  			[]int{0, 3},
  1085  			[]int{1, 2},
  1086  		},
  1087  		{
  1088  			[]uint64{5000000, 5000000, 5000000, 5000000},
  1089  			true,
  1090  			true,
  1091  			[]int{0, 1, 2, 3},
  1092  			[]int{},
  1093  		},
  1094  	}
  1095  
  1096  	testNum := 4
  1097  	ms := uint64(5500000)
  1098  	configItems := makeSnapshotTestConfigItems()
  1099  	configItems = append(configItems, minimumStake(new(big.Int).SetUint64(ms)))
  1100  	for _, tc := range testcases {
  1101  		if tc.isIstanbulCompatible {
  1102  			configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
  1103  		}
  1104  		if tc.isSingleMode {
  1105  			configItems = append(configItems, governanceMode("single"))
  1106  		}
  1107  		chain, engine := newBlockChain(testNum, configItems...)
  1108  		oldStakingManager := setTestStakingInfo(tc.stakingAmounts)
  1109  
  1110  		block := makeBlockWithSeal(chain, engine, chain.Genesis())
  1111  		_, err := chain.InsertChain(types.Blocks{block})
  1112  		assert.NoError(t, err)
  1113  
  1114  		snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true)
  1115  		assert.NoError(t, err)
  1116  
  1117  		validators := toAddressList(snap.ValSet.List())
  1118  		demoted := toAddressList(snap.ValSet.DemotedList())
  1119  
  1120  		expectedValidators := makeExpectedResult(tc.expectedValidators, addrs)
  1121  		expectedDemoted := makeExpectedResult(tc.expectedDemoted, addrs)
  1122  
  1123  		assert.Equal(t, expectedValidators, validators)
  1124  		assert.Equal(t, expectedDemoted, demoted)
  1125  
  1126  		reward.SetTestStakingManager(oldStakingManager)
  1127  		engine.Stop()
  1128  	}
  1129  }
  1130  
  1131  func TestSnapshot_Validators_AddRemove(t *testing.T) {
  1132  	type vote struct {
  1133  		key   string
  1134  		value interface{}
  1135  	}
  1136  	type expected struct {
  1137  		validators []int // expected validator indexes at given block
  1138  	}
  1139  	type testcase struct {
  1140  		length   int // total number of blocks to simulate
  1141  		votes    map[int]vote
  1142  		expected map[int]expected
  1143  	}
  1144  
  1145  	testcases := []testcase{
  1146  		{ // Singular change
  1147  			5,
  1148  			map[int]vote{
  1149  				1: {"governance.removevalidator", 3},
  1150  				3: {"governance.addvalidator", 3},
  1151  			},
  1152  			map[int]expected{
  1153  				0: {[]int{0, 1, 2, 3}},
  1154  				1: {[]int{0, 1, 2, 3}},
  1155  				2: {[]int{0, 1, 2}},
  1156  				3: {[]int{0, 1, 2}},
  1157  				4: {[]int{0, 1, 2, 3}},
  1158  			},
  1159  		},
  1160  		{ // Plural change
  1161  			5,
  1162  			map[int]vote{
  1163  				1: {"governance.removevalidator", []int{1, 2, 3}},
  1164  				3: {"governance.addvalidator", []int{1, 2}},
  1165  			},
  1166  			map[int]expected{
  1167  				0: {[]int{0, 1, 2, 3}},
  1168  				1: {[]int{0, 1, 2, 3}},
  1169  				2: {[]int{0}},
  1170  				3: {[]int{0}},
  1171  				4: {[]int{0, 1, 2}},
  1172  			},
  1173  		},
  1174  		{ // Around checkpoint interval (i.e. every 1024 block)
  1175  			params.CheckpointInterval + 10,
  1176  			map[int]vote{
  1177  				params.CheckpointInterval - 5: {"governance.removevalidator", 3},
  1178  				params.CheckpointInterval - 1: {"governance.removevalidator", 2},
  1179  				params.CheckpointInterval + 0: {"governance.removevalidator", 1},
  1180  				params.CheckpointInterval + 1: {"governance.addvalidator", 1},
  1181  				params.CheckpointInterval + 2: {"governance.addvalidator", 2},
  1182  				params.CheckpointInterval + 3: {"governance.addvalidator", 3},
  1183  			},
  1184  			map[int]expected{
  1185  				0:                             {[]int{0, 1, 2, 3}},
  1186  				1:                             {[]int{0, 1, 2, 3}},
  1187  				params.CheckpointInterval - 4: {[]int{0, 1, 2}},
  1188  				params.CheckpointInterval + 0: {[]int{0, 1}},
  1189  				params.CheckpointInterval + 1: {[]int{0}},
  1190  				params.CheckpointInterval + 2: {[]int{0, 1}},
  1191  				params.CheckpointInterval + 3: {[]int{0, 1, 2}},
  1192  				params.CheckpointInterval + 4: {[]int{0, 1, 2, 3}},
  1193  				params.CheckpointInterval + 9: {[]int{0, 1, 2, 3}},
  1194  			},
  1195  		},
  1196  		{ // multiple addvalidator & removevalidator
  1197  			10,
  1198  			map[int]vote{
  1199  				0: {"governance.removevalidator", 3},
  1200  				2: {"governance.addvalidator", 3},
  1201  				4: {"governance.addvalidator", 3},
  1202  				6: {"governance.removevalidator", 3},
  1203  				8: {"governance.removevalidator", 3},
  1204  			},
  1205  			map[int]expected{
  1206  				1: {[]int{0, 1, 2}},
  1207  				3: {[]int{0, 1, 2, 3}},
  1208  				5: {[]int{0, 1, 2, 3}},
  1209  				7: {[]int{0, 1, 2}},
  1210  				9: {[]int{0, 1, 2}},
  1211  			},
  1212  		},
  1213  		{ // multiple removevalidator & addvalidator
  1214  			10,
  1215  			map[int]vote{
  1216  				0: {"governance.removevalidator", 3},
  1217  				2: {"governance.removevalidator", 3},
  1218  				4: {"governance.addvalidator", 3},
  1219  				6: {"governance.addvalidator", 3},
  1220  			},
  1221  			map[int]expected{
  1222  				1: {[]int{0, 1, 2}},
  1223  				3: {[]int{0, 1, 2}},
  1224  				5: {[]int{0, 1, 2, 3}},
  1225  				7: {[]int{0, 1, 2, 3}},
  1226  			},
  1227  		},
  1228  		{ // multiple addvalidators & removevalidators
  1229  			10,
  1230  			map[int]vote{
  1231  				0: {"governance.removevalidator", []int{2, 3}},
  1232  				2: {"governance.addvalidator", []int{2, 3}},
  1233  				4: {"governance.addvalidator", []int{2, 3}},
  1234  				6: {"governance.removevalidator", []int{2, 3}},
  1235  				8: {"governance.removevalidator", []int{2, 3}},
  1236  			},
  1237  			map[int]expected{
  1238  				1: {[]int{0, 1}},
  1239  				3: {[]int{0, 1, 2, 3}},
  1240  				5: {[]int{0, 1, 2, 3}},
  1241  				7: {[]int{0, 1}},
  1242  				9: {[]int{0, 1}},
  1243  			},
  1244  		},
  1245  		{ // multiple removevalidators & addvalidators
  1246  			10,
  1247  			map[int]vote{
  1248  				0: {"governance.removevalidator", []int{2, 3}},
  1249  				2: {"governance.removevalidator", []int{2, 3}},
  1250  				4: {"governance.addvalidator", []int{2, 3}},
  1251  				6: {"governance.addvalidator", []int{2, 3}},
  1252  			},
  1253  			map[int]expected{
  1254  				1: {[]int{0, 1}},
  1255  				3: {[]int{0, 1}},
  1256  				5: {[]int{0, 1, 2, 3}},
  1257  				7: {[]int{0, 1, 2, 3}},
  1258  			},
  1259  		},
  1260  	}
  1261  
  1262  	var configItems []interface{}
  1263  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
  1264  	configItems = append(configItems, proposerUpdateInterval(1))
  1265  	configItems = append(configItems, epoch(3))
  1266  	configItems = append(configItems, subGroupSize(4))
  1267  	configItems = append(configItems, governanceMode("single"))
  1268  	configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000)))
  1269  	configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
  1270  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1271  	stakes := []uint64{4000000, 4000000, 4000000, 4000000}
  1272  
  1273  	for _, tc := range testcases {
  1274  		// Create test blockchain
  1275  		chain, engine := newBlockChain(4, configItems...)
  1276  		oldStakingManager := setTestStakingInfo(stakes)
  1277  
  1278  		// Backup the globals. The globals `nodeKeys` and `addrs` will be
  1279  		// modified according to validator change votes.
  1280  		allNodeKeys := make([]*ecdsa.PrivateKey, len(nodeKeys))
  1281  		allAddrs := make([]common.Address, len(addrs))
  1282  		copy(allNodeKeys, nodeKeys)
  1283  		copy(allAddrs, addrs)
  1284  
  1285  		var previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1286  
  1287  		// Create blocks with votes
  1288  		for i := 0; i < tc.length; i++ {
  1289  			if v, ok := tc.votes[i]; ok { // If a vote is scheduled in this block,
  1290  				if idx, ok := v.value.(int); ok {
  1291  					addr := allAddrs[idx]
  1292  					engine.governance.AddVote(v.key, addr)
  1293  				} else {
  1294  					addrList := makeExpectedResult(v.value.([]int), allAddrs)
  1295  					engine.governance.AddVote(v.key, addrList)
  1296  				}
  1297  				// t.Logf("Voting at block #%d for %s, %v", i, v.key, v.value)
  1298  			}
  1299  
  1300  			previousBlock = currentBlock
  1301  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1302  			_, err := chain.InsertChain(types.Blocks{currentBlock})
  1303  			assert.NoError(t, err)
  1304  
  1305  			// After a voting, reflect the validator change to the globals
  1306  			if v, ok := tc.votes[i]; ok {
  1307  				var indices []int
  1308  				if idx, ok := v.value.(int); ok {
  1309  					indices = []int{idx}
  1310  				} else {
  1311  					indices = v.value.([]int)
  1312  				}
  1313  				if v.key == "governance.addvalidator" {
  1314  					for _, i := range indices {
  1315  						includeNode(allAddrs[i], allNodeKeys[i])
  1316  					}
  1317  				}
  1318  				if v.key == "governance.removevalidator" {
  1319  					for _, i := range indices {
  1320  						excludeNodeByAddr(allAddrs[i])
  1321  					}
  1322  				}
  1323  			}
  1324  		}
  1325  
  1326  		// Calculate historical validators using the snapshot.
  1327  		for i := 0; i < tc.length; i++ {
  1328  			if _, ok := tc.expected[i]; !ok {
  1329  				continue
  1330  			}
  1331  			block := chain.GetBlockByNumber(uint64(i))
  1332  			snap, err := engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true)
  1333  			assert.NoError(t, err)
  1334  			validators := copyAndSortAddrs(toAddressList(snap.ValSet.List()))
  1335  
  1336  			expectedValidators := makeExpectedResult(tc.expected[i].validators, allAddrs)
  1337  			assert.Equal(t, expectedValidators, validators)
  1338  			// t.Logf("snap at block #%d: size %d", i, snap.ValSet.Size())
  1339  		}
  1340  
  1341  		reward.SetTestStakingManager(oldStakingManager)
  1342  		engine.Stop()
  1343  	}
  1344  }
  1345  
  1346  func TestSnapshot_Writable(t *testing.T) {
  1347  	var configItems []interface{}
  1348  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
  1349  	configItems = append(configItems, epoch(3))
  1350  	configItems = append(configItems, governanceMode("single"))
  1351  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1352  	chain, engine := newBlockChain(1, configItems...)
  1353  	defer engine.Stop()
  1354  	oldStakingManager := setTestStakingInfo(nil)
  1355  	defer reward.SetTestStakingManager(oldStakingManager)
  1356  
  1357  	// add votes and insert voted blocks
  1358  	var (
  1359  		previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1360  		err                         error
  1361  	)
  1362  
  1363  	// voteData is inserted at block 4, and current block is block 5.
  1364  	for i := 0; i < 5; i++ {
  1365  		if i == 4 {
  1366  			engine.governance.AddVote("governance.unitprice", uint64(2000000))
  1367  		}
  1368  		previousBlock = currentBlock
  1369  		currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1370  		_, err = chain.InsertChain(types.Blocks{currentBlock})
  1371  		assert.NoError(t, err)
  1372  	}
  1373  
  1374  	// save current gov.changeSet's length for the expected value.
  1375  	currentChangeSetLength := len(engine.governance.GetGovernanceChange())
  1376  	assert.Equal(t, 1, currentChangeSetLength)
  1377  
  1378  	// block 3 is the start block of an epoch. In this test, the cache of this block's snapshot is cleared.
  1379  	// If cache is not removed, it will just read the cache rather than making the snapshot itself.
  1380  	block := chain.GetBlockByNumber(uint64(3))
  1381  
  1382  	// case [writable == false]
  1383  	// expected result: gov.changeSet should not be modified.
  1384  	engine.recents.Remove(block.Hash()) // assume node is restarted
  1385  	_, err = engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, false)
  1386  	assert.Equal(t, currentChangeSetLength, len(engine.governance.GetGovernanceChange()))
  1387  
  1388  	// case [writable == true]
  1389  	// expected result: gov.changeSet is modified.
  1390  	engine.recents.Remove(block.Hash()) // assume node is restarted
  1391  	_, err = engine.snapshot(chain, block.NumberU64(), block.Hash(), nil, true)
  1392  	assert.Equal(t, 0, len(engine.governance.GetGovernanceChange()))
  1393  }
  1394  
  1395  func TestGovernance_Votes(t *testing.T) {
  1396  	type vote struct {
  1397  		key   string
  1398  		value interface{}
  1399  	}
  1400  	type governanceItem struct {
  1401  		vote
  1402  		appliedBlockNumber uint64 // if applied block number is 0, then it checks the item on current block
  1403  	}
  1404  	type testcase struct {
  1405  		votes    []vote
  1406  		expected []governanceItem
  1407  	}
  1408  
  1409  	testcases := []testcase{
  1410  		{
  1411  			votes: []vote{
  1412  				{"governance.governancemode", "none"},     // voted on block 1
  1413  				{"istanbul.committeesize", uint64(4)},     // voted on block 2
  1414  				{"governance.unitprice", uint64(2000000)}, // voted on block 3
  1415  				{"reward.mintingamount", "96000000000"},   // voted on block 4
  1416  				{"reward.ratio", "34/33/33"},              // voted on block 5
  1417  				{"reward.useginicoeff", true},             // voted on block 6
  1418  				{"reward.minimumstake", "5000000"},        // voted on block 7
  1419  				{"reward.kip82ratio", "50/50"},            // voted on block 8
  1420  				{"governance.deriveshaimpl", uint64(2)},   // voted on block 9
  1421  			},
  1422  			expected: []governanceItem{
  1423  				{vote{"governance.governancemode", "none"}, 6},
  1424  				{vote{"istanbul.committeesize", uint64(4)}, 6},
  1425  				{vote{"governance.unitprice", uint64(2000000)}, 9},
  1426  				{vote{"reward.mintingamount", "96000000000"}, 9},
  1427  				{vote{"reward.ratio", "34/33/33"}, 9},
  1428  				{vote{"reward.useginicoeff", true}, 12},
  1429  				{vote{"reward.minimumstake", "5000000"}, 12},
  1430  				{vote{"reward.kip82ratio", "50/50"}, 12},
  1431  				{vote{"governance.deriveshaimpl", uint64(2)}, 15},
  1432  				// check governance items on current block
  1433  				{vote{"governance.governancemode", "none"}, 0},
  1434  				{vote{"istanbul.committeesize", uint64(4)}, 0},
  1435  				{vote{"governance.unitprice", uint64(2000000)}, 0},
  1436  				{vote{"reward.mintingamount", "96000000000"}, 0},
  1437  				{vote{"reward.ratio", "34/33/33"}, 0},
  1438  				{vote{"reward.useginicoeff", true}, 0},
  1439  				{vote{"reward.minimumstake", "5000000"}, 0},
  1440  				{vote{"reward.kip82ratio", "50/50"}, 0},
  1441  				{vote{"governance.deriveshaimpl", uint64(2)}, 0},
  1442  			},
  1443  		},
  1444  		{
  1445  			votes: []vote{
  1446  				{"governance.governancemode", "none"},   // voted on block 1
  1447  				{"governance.governancemode", "single"}, // voted on block 2
  1448  				{"governance.governancemode", "none"},   // voted on block 3
  1449  				{"governance.governancemode", "single"}, // voted on block 4
  1450  				{"governance.governancemode", "none"},   // voted on block 5
  1451  				{"governance.governancemode", "single"}, // voted on block 6
  1452  				{"governance.governancemode", "none"},   // voted on block 7
  1453  				{"governance.governancemode", "single"}, // voted on block 8
  1454  				{"governance.governancemode", "none"},   // voted on block 9
  1455  			},
  1456  			expected: []governanceItem{
  1457  				{vote{"governance.governancemode", "single"}, 6},
  1458  				{vote{"governance.governancemode", "none"}, 9},
  1459  				{vote{"governance.governancemode", "single"}, 12},
  1460  				{vote{"governance.governancemode", "none"}, 15},
  1461  			},
  1462  		},
  1463  		{
  1464  			votes: []vote{
  1465  				{"governance.governancemode", "none"},     // voted on block 1
  1466  				{"istanbul.committeesize", uint64(4)},     // voted on block 2
  1467  				{"governance.unitprice", uint64(2000000)}, // voted on block 3
  1468  				{"governance.governancemode", "single"},   // voted on block 4
  1469  				{"istanbul.committeesize", uint64(22)},    // voted on block 5
  1470  				{"governance.unitprice", uint64(2)},       // voted on block 6
  1471  				{"governance.governancemode", "none"},     // voted on block 7
  1472  			},
  1473  			expected: []governanceItem{
  1474  				// governance mode for all blocks
  1475  				{vote{"governance.governancemode", "single"}, 1},
  1476  				{vote{"governance.governancemode", "single"}, 2},
  1477  				{vote{"governance.governancemode", "single"}, 3},
  1478  				{vote{"governance.governancemode", "single"}, 4},
  1479  				{vote{"governance.governancemode", "single"}, 5},
  1480  				{vote{"governance.governancemode", "none"}, 6},
  1481  				{vote{"governance.governancemode", "none"}, 7},
  1482  				{vote{"governance.governancemode", "none"}, 8},
  1483  				{vote{"governance.governancemode", "single"}, 9},
  1484  				{vote{"governance.governancemode", "single"}, 10},
  1485  				{vote{"governance.governancemode", "single"}, 11},
  1486  				{vote{"governance.governancemode", "none"}, 12},
  1487  				{vote{"governance.governancemode", "none"}, 13},
  1488  				{vote{"governance.governancemode", "none"}, 14},
  1489  				{vote{"governance.governancemode", "none"}, 0}, // check on current
  1490  
  1491  				// committee size for all blocks
  1492  				{vote{"istanbul.committeesize", uint64(21)}, 1},
  1493  				{vote{"istanbul.committeesize", uint64(21)}, 2},
  1494  				{vote{"istanbul.committeesize", uint64(21)}, 3},
  1495  				{vote{"istanbul.committeesize", uint64(21)}, 4},
  1496  				{vote{"istanbul.committeesize", uint64(21)}, 5},
  1497  				{vote{"istanbul.committeesize", uint64(4)}, 6},
  1498  				{vote{"istanbul.committeesize", uint64(4)}, 7},
  1499  				{vote{"istanbul.committeesize", uint64(4)}, 8},
  1500  				{vote{"istanbul.committeesize", uint64(22)}, 9},
  1501  				{vote{"istanbul.committeesize", uint64(22)}, 10},
  1502  				{vote{"istanbul.committeesize", uint64(22)}, 11},
  1503  				{vote{"istanbul.committeesize", uint64(22)}, 12},
  1504  				{vote{"istanbul.committeesize", uint64(22)}, 13},
  1505  				{vote{"istanbul.committeesize", uint64(22)}, 14},
  1506  				{vote{"istanbul.committeesize", uint64(22)}, 0}, // check on current
  1507  
  1508  				// unitprice for all blocks
  1509  				{vote{"governance.unitprice", uint64(1)}, 1},
  1510  				{vote{"governance.unitprice", uint64(1)}, 2},
  1511  				{vote{"governance.unitprice", uint64(1)}, 3},
  1512  				{vote{"governance.unitprice", uint64(1)}, 4},
  1513  				{vote{"governance.unitprice", uint64(1)}, 5},
  1514  				{vote{"governance.unitprice", uint64(1)}, 6},
  1515  				{vote{"governance.unitprice", uint64(1)}, 7},
  1516  				{vote{"governance.unitprice", uint64(1)}, 8},
  1517  				{vote{"governance.unitprice", uint64(2000000)}, 9},
  1518  				{vote{"governance.unitprice", uint64(2000000)}, 10},
  1519  				{vote{"governance.unitprice", uint64(2000000)}, 11},
  1520  				{vote{"governance.unitprice", uint64(2)}, 12},
  1521  				{vote{"governance.unitprice", uint64(2)}, 13},
  1522  				{vote{"governance.unitprice", uint64(2)}, 14},
  1523  				{vote{"governance.unitprice", uint64(2)}, 0}, // check on current
  1524  			},
  1525  		},
  1526  		{
  1527  			votes: []vote{
  1528  				{}, // voted on block 1
  1529  				{"kip71.lowerboundbasefee", uint64(750000000000)}, // voted on block 2
  1530  				{}, // voted on block 3
  1531  				{}, // voted on block 4
  1532  				{"kip71.lowerboundbasefee", uint64(25000000000)}, // voted on block 5
  1533  			},
  1534  			expected: []governanceItem{
  1535  				{vote{"kip71.lowerboundbasefee", uint64(750000000000)}, 6},
  1536  				{vote{"kip71.lowerboundbasefee", uint64(25000000000)}, 9},
  1537  			},
  1538  		},
  1539  		{
  1540  			votes: []vote{
  1541  				{}, // voted on block 1
  1542  				{"kip71.upperboundbasefee", uint64(750000000000)}, // voted on block 2
  1543  				{}, // voted on block 3
  1544  				{}, // voted on block 4
  1545  				{"kip71.upperboundbasefee", uint64(25000000000)}, // voted on block 5
  1546  			},
  1547  			expected: []governanceItem{
  1548  				{vote{"kip71.upperboundbasefee", uint64(750000000000)}, 6},
  1549  				{vote{"kip71.upperboundbasefee", uint64(25000000000)}, 9},
  1550  			},
  1551  		},
  1552  		{
  1553  			votes: []vote{
  1554  				{}, // voted on block 1
  1555  				{"kip71.maxblockgasusedforbasefee", uint64(840000000)}, // voted on block 2
  1556  				{}, // voted on block 3
  1557  				{}, // voted on block 4
  1558  				{"kip71.maxblockgasusedforbasefee", uint64(84000000)}, // voted on block 5
  1559  			},
  1560  			expected: []governanceItem{
  1561  				{vote{"kip71.maxblockgasusedforbasefee", uint64(840000000)}, 6},
  1562  				{vote{"kip71.maxblockgasusedforbasefee", uint64(84000000)}, 9},
  1563  			},
  1564  		},
  1565  		{
  1566  			votes: []vote{
  1567  				{},                                    // voted on block 1
  1568  				{"kip71.gastarget", uint64(50000000)}, // voted on block 2
  1569  				{},                                    // voted on block 3
  1570  				{},                                    // voted on block 4
  1571  				{"kip71.gastarget", uint64(30000000)}, // voted on block 5
  1572  			},
  1573  			expected: []governanceItem{
  1574  				{vote{"kip71.gastarget", uint64(50000000)}, 6},
  1575  				{vote{"kip71.gastarget", uint64(30000000)}, 9},
  1576  			},
  1577  		},
  1578  		{
  1579  			votes: []vote{
  1580  				{},                                       // voted on block 1
  1581  				{"kip71.basefeedenominator", uint64(32)}, // voted on block 2
  1582  				{},                                       // voted on block 3
  1583  				{},                                       // voted on block 4
  1584  				{"kip71.basefeedenominator", uint64(64)}, // voted on block 5
  1585  			},
  1586  			expected: []governanceItem{
  1587  				{vote{"kip71.basefeedenominator", uint64(32)}, 6},
  1588  				{vote{"kip71.basefeedenominator", uint64(64)}, 9},
  1589  			},
  1590  		},
  1591  		{
  1592  			votes: []vote{
  1593  				{}, // voted on block 1
  1594  				{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000000")}, // voted on block 2
  1595  				{}, // voted on block 3
  1596  				{}, // voted on block 4
  1597  				{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000400")}, // voted on block 5
  1598  			},
  1599  			expected: []governanceItem{
  1600  				{vote{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000000")}, 6},
  1601  				{vote{"governance.govparamcontract", common.HexToAddress("0x0000000000000000000000000000000000000400")}, 9},
  1602  			},
  1603  		},
  1604  	}
  1605  
  1606  	var configItems []interface{}
  1607  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
  1608  	configItems = append(configItems, epoch(3))
  1609  	configItems = append(configItems, governanceMode("single"))
  1610  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1611  	for _, tc := range testcases {
  1612  		chain, engine := newBlockChain(1, configItems...)
  1613  		oldStakingManager := setTestStakingInfo(nil)
  1614  
  1615  		// test initial governance items
  1616  		assert.Equal(t, uint64(3), engine.governance.CurrentParams().Epoch())
  1617  		assert.Equal(t, "single", engine.governance.CurrentParams().GovernanceModeStr())
  1618  		assert.Equal(t, uint64(21), engine.governance.CurrentParams().CommitteeSize())
  1619  		assert.Equal(t, uint64(1), engine.governance.CurrentParams().UnitPrice())
  1620  		assert.Equal(t, "0", engine.governance.CurrentParams().MintingAmountStr())
  1621  		assert.Equal(t, "100/0/0", engine.governance.CurrentParams().Ratio())
  1622  		assert.Equal(t, false, engine.governance.CurrentParams().UseGiniCoeff())
  1623  		assert.Equal(t, "2000000", engine.governance.CurrentParams().MinimumStakeStr())
  1624  
  1625  		// add votes and insert voted blocks
  1626  		var (
  1627  			previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1628  			err                         error
  1629  		)
  1630  
  1631  		for _, v := range tc.votes {
  1632  			engine.governance.AddVote(v.key, v.value)
  1633  			previousBlock = currentBlock
  1634  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1635  			_, err = chain.InsertChain(types.Blocks{currentBlock})
  1636  			assert.NoError(t, err)
  1637  		}
  1638  
  1639  		// insert blocks until the vote is applied
  1640  		for i := 0; i < 6; i++ {
  1641  			previousBlock = currentBlock
  1642  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1643  			_, err = chain.InsertChain(types.Blocks{currentBlock})
  1644  			assert.NoError(t, err)
  1645  		}
  1646  
  1647  		for _, item := range tc.expected {
  1648  			blockNumber := item.appliedBlockNumber
  1649  			if blockNumber == 0 {
  1650  				blockNumber = chain.CurrentBlock().NumberU64()
  1651  			}
  1652  			_, items, err := engine.governance.ReadGovernance(blockNumber)
  1653  			assert.NoError(t, err)
  1654  			assert.Equal(t, item.value, items[item.key])
  1655  		}
  1656  
  1657  		reward.SetTestStakingManager(oldStakingManager)
  1658  		engine.Stop()
  1659  	}
  1660  }
  1661  
  1662  func TestGovernance_ReaderEngine(t *testing.T) {
  1663  	// Test that ReaderEngine (CurrentParams(), EffectiveParams(), UpdateParams()) works.
  1664  	type vote = map[string]interface{}
  1665  	type expected = map[string]interface{} // expected (subset of) governance items
  1666  	type testcase struct {
  1667  		length   int // total number of blocks to simulate
  1668  		votes    map[int]vote
  1669  		expected map[int]expected
  1670  	}
  1671  
  1672  	testcases := []testcase{
  1673  		{
  1674  			8,
  1675  			map[int]vote{
  1676  				1: {"governance.unitprice": uint64(17)},
  1677  			},
  1678  			map[int]expected{
  1679  				0: {"governance.unitprice": uint64(1)},
  1680  				1: {"governance.unitprice": uint64(1)},
  1681  				2: {"governance.unitprice": uint64(1)},
  1682  				3: {"governance.unitprice": uint64(1)},
  1683  				4: {"governance.unitprice": uint64(1)},
  1684  				5: {"governance.unitprice": uint64(1)},
  1685  				6: {"governance.unitprice": uint64(1)},
  1686  				7: {"governance.unitprice": uint64(17)},
  1687  				8: {"governance.unitprice": uint64(17)},
  1688  			},
  1689  		},
  1690  	}
  1691  
  1692  	var configItems []interface{}
  1693  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
  1694  	configItems = append(configItems, proposerUpdateInterval(1))
  1695  	configItems = append(configItems, epoch(3))
  1696  	configItems = append(configItems, governanceMode("single"))
  1697  	configItems = append(configItems, minimumStake(new(big.Int).SetUint64(4000000)))
  1698  	configItems = append(configItems, istanbulCompatibleBlock(new(big.Int).SetUint64(0)))
  1699  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1700  	stakes := []uint64{4000000, 4000000, 4000000, 4000000}
  1701  
  1702  	for _, tc := range testcases {
  1703  		// Create test blockchain
  1704  		chain, engine := newBlockChain(4, configItems...)
  1705  		oldStakingManager := setTestStakingInfo(stakes)
  1706  
  1707  		var previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1708  
  1709  		// Create blocks with votes
  1710  		for num := 0; num <= tc.length; num++ {
  1711  			// Validate current params with CurrentParams() and CurrentSetCopy().
  1712  			// Check that both returns the expected result.
  1713  			assertMapSubset(t, tc.expected[num+1], engine.governance.CurrentParams().StrMap())
  1714  			assertMapSubset(t, tc.expected[num+1], engine.governance.CurrentSetCopy())
  1715  
  1716  			// Place a vote if a vote is scheduled in upcoming block
  1717  			// Note that we're building (head+1)'th block here.
  1718  			for k, v := range tc.votes[num+1] {
  1719  				ok := engine.governance.AddVote(k, v)
  1720  				assert.True(t, ok)
  1721  			}
  1722  
  1723  			// Create a block
  1724  			previousBlock = currentBlock
  1725  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1726  			_, err := chain.InsertChain(types.Blocks{currentBlock})
  1727  			assert.NoError(t, err)
  1728  
  1729  			// Load parameters for the next block
  1730  			err = engine.governance.UpdateParams(currentBlock.NumberU64())
  1731  			assert.NoError(t, err)
  1732  		}
  1733  
  1734  		// Validate historic parameters with EffectiveParams() and ReadGovernance().
  1735  		// Check that both returns the expected result.
  1736  		for num := 0; num <= tc.length; num++ {
  1737  			pset, err := engine.governance.EffectiveParams(uint64(num))
  1738  			assert.NoError(t, err)
  1739  			assertMapSubset(t, tc.expected[num], pset.StrMap())
  1740  
  1741  			_, items, err := engine.governance.ReadGovernance(uint64(num))
  1742  			assert.NoError(t, err)
  1743  			assertMapSubset(t, tc.expected[num+1], items)
  1744  		}
  1745  
  1746  		reward.SetTestStakingManager(oldStakingManager)
  1747  		engine.Stop()
  1748  	}
  1749  }
  1750  
  1751  func TestChainConfig_UpdateAfterVotes(t *testing.T) {
  1752  	type vote struct {
  1753  		key   string
  1754  		value interface{}
  1755  	}
  1756  	type testcase struct {
  1757  		voting   vote
  1758  		expected vote
  1759  	}
  1760  
  1761  	testcases := []testcase{
  1762  		{
  1763  			voting:   vote{"kip71.lowerboundbasefee", uint64(20000000000)}, // voted on block 1
  1764  			expected: vote{"kip71.lowerboundbasefee", uint64(20000000000)},
  1765  		},
  1766  		{
  1767  			voting:   vote{"kip71.upperboundbasefee", uint64(500000000000)}, // voted on block 1
  1768  			expected: vote{"kip71.upperboundbasefee", uint64(500000000000)},
  1769  		},
  1770  		{
  1771  			voting:   vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, // voted on block 1
  1772  			expected: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)},
  1773  		},
  1774  		{
  1775  			voting:   vote{"kip71.gastarget", uint64(50000000)}, // voted on block 1
  1776  			expected: vote{"kip71.gastarget", uint64(50000000)},
  1777  		},
  1778  		{
  1779  			voting:   vote{"kip71.basefeedenominator", uint64(32)}, // voted on block 1
  1780  			expected: vote{"kip71.basefeedenominator", uint64(32)},
  1781  		},
  1782  	}
  1783  
  1784  	var configItems []interface{}
  1785  	configItems = append(configItems, epoch(3))
  1786  	configItems = append(configItems, governanceMode("single"))
  1787  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1788  	for _, tc := range testcases {
  1789  		chain, engine := newBlockChain(1, configItems...)
  1790  
  1791  		// test initial governance items
  1792  		assert.Equal(t, uint64(25000000000), chain.Config().Governance.KIP71.LowerBoundBaseFee)
  1793  		assert.Equal(t, uint64(750000000000), chain.Config().Governance.KIP71.UpperBoundBaseFee)
  1794  		assert.Equal(t, uint64(20), chain.Config().Governance.KIP71.BaseFeeDenominator)
  1795  		assert.Equal(t, uint64(60000000), chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee)
  1796  		assert.Equal(t, uint64(30000000), chain.Config().Governance.KIP71.GasTarget)
  1797  
  1798  		// add votes and insert voted blocks
  1799  		var (
  1800  			previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1801  			err                         error
  1802  		)
  1803  
  1804  		engine.governance.SetBlockchain(chain)
  1805  		engine.governance.AddVote(tc.voting.key, tc.voting.value)
  1806  		previousBlock = currentBlock
  1807  		currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1808  		_, err = chain.InsertChain(types.Blocks{currentBlock})
  1809  		assert.NoError(t, err)
  1810  
  1811  		// insert blocks until the vote is applied
  1812  		for i := 0; i < 6; i++ {
  1813  			previousBlock = currentBlock
  1814  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1815  			_, err = chain.InsertChain(types.Blocks{currentBlock})
  1816  			assert.NoError(t, err)
  1817  		}
  1818  
  1819  		govConfig := chain.Config().Governance
  1820  		switch tc.expected.key {
  1821  		case "kip71.lowerboundbasefee":
  1822  			assert.Equal(t, tc.expected.value, govConfig.KIP71.LowerBoundBaseFee)
  1823  		case "kip71.upperboundbasefee":
  1824  			assert.Equal(t, tc.expected.value, govConfig.KIP71.UpperBoundBaseFee)
  1825  		case "kip71.gastarget":
  1826  			assert.Equal(t, tc.expected.value, govConfig.KIP71.GasTarget)
  1827  		case "kip71.maxblockgasusedforbasefee":
  1828  			assert.Equal(t, tc.expected.value, govConfig.KIP71.MaxBlockGasUsedForBaseFee)
  1829  		case "kip71.basefeedenominator":
  1830  			assert.Equal(t, tc.expected.value, govConfig.KIP71.BaseFeeDenominator)
  1831  		default:
  1832  			assert.Error(t, nil)
  1833  		}
  1834  	}
  1835  }
  1836  
  1837  func TestChainConfig_ReadFromDBAfterVotes(t *testing.T) {
  1838  	type vote struct {
  1839  		key   string
  1840  		value interface{}
  1841  	}
  1842  	type testcase struct {
  1843  		voting   vote
  1844  		expected vote
  1845  	}
  1846  
  1847  	testcases := []testcase{
  1848  		{
  1849  			voting:   vote{"kip71.lowerboundbasefee", uint64(20000000000)}, // voted on block 1
  1850  			expected: vote{"kip71.lowerboundbasefee", uint64(20000000000)},
  1851  		},
  1852  		{
  1853  			voting:   vote{"kip71.upperboundbasefee", uint64(500000000000)}, // voted on block 1
  1854  			expected: vote{"kip71.upperboundbasefee", uint64(500000000000)},
  1855  		},
  1856  		{
  1857  			voting:   vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)}, // voted on block 1
  1858  			expected: vote{"kip71.maxblockgasusedforbasefee", uint64(100000000)},
  1859  		},
  1860  		{
  1861  			voting:   vote{"kip71.gastarget", uint64(50000000)}, // voted on block 1
  1862  			expected: vote{"kip71.gastarget", uint64(50000000)},
  1863  		},
  1864  		{
  1865  			voting:   vote{"kip71.basefeedenominator", uint64(32)}, // voted on block 1
  1866  			expected: vote{"kip71.basefeedenominator", uint64(32)},
  1867  		},
  1868  	}
  1869  
  1870  	var configItems []interface{}
  1871  	configItems = append(configItems, proposerPolicy(params.WeightedRandom))
  1872  	configItems = append(configItems, epoch(3))
  1873  	configItems = append(configItems, governanceMode("single"))
  1874  	configItems = append(configItems, blockPeriod(0)) // set block period to 0 to prevent creating future block
  1875  	for _, tc := range testcases {
  1876  		chain, engine := newBlockChain(1, configItems...)
  1877  		oldStakingManager := setTestStakingInfo(nil)
  1878  
  1879  		// test initial governance items
  1880  		assert.Equal(t, uint64(25000000000), chain.Config().Governance.KIP71.LowerBoundBaseFee)
  1881  		assert.Equal(t, uint64(750000000000), chain.Config().Governance.KIP71.UpperBoundBaseFee)
  1882  		assert.Equal(t, uint64(20), chain.Config().Governance.KIP71.BaseFeeDenominator)
  1883  		assert.Equal(t, uint64(60000000), chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee)
  1884  		assert.Equal(t, uint64(30000000), chain.Config().Governance.KIP71.GasTarget)
  1885  
  1886  		// add votes and insert voted blocks
  1887  		var (
  1888  			previousBlock, currentBlock *types.Block = nil, chain.Genesis()
  1889  			err                         error
  1890  		)
  1891  
  1892  		engine.governance.SetBlockchain(chain)
  1893  		engine.governance.AddVote(tc.voting.key, tc.voting.value)
  1894  		previousBlock = currentBlock
  1895  		currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1896  		_, err = chain.InsertChain(types.Blocks{currentBlock})
  1897  		assert.NoError(t, err)
  1898  
  1899  		// insert blocks until the vote is applied
  1900  		for i := 0; i < params.CheckpointInterval; i++ {
  1901  			previousBlock = currentBlock
  1902  			currentBlock = makeBlockWithSeal(chain, engine, previousBlock)
  1903  			_, err = chain.InsertChain(types.Blocks{currentBlock})
  1904  			assert.NoError(t, err)
  1905  		}
  1906  
  1907  		switch tc.expected.key {
  1908  		case "kip71.lowerboundbasefee":
  1909  			assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.LowerBoundBaseFee)
  1910  		case "kip71.upperboundbasefee":
  1911  			assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.UpperBoundBaseFee)
  1912  		case "kip71.gastarget":
  1913  			assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.GasTarget)
  1914  		case "kip71.maxblockgasusedforbasefee":
  1915  			assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.MaxBlockGasUsedForBaseFee)
  1916  		case "kip71.basefeedenominator":
  1917  			assert.Equal(t, tc.expected.value, chain.Config().Governance.KIP71.BaseFeeDenominator)
  1918  		default:
  1919  			assert.Error(t, nil)
  1920  		}
  1921  
  1922  		reward.SetTestStakingManager(oldStakingManager)
  1923  		engine.Stop()
  1924  	}
  1925  }