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