github.com/klaytn/klaytn@v1.10.2/consensus/istanbul/validator/weighted_test.go (about)

     1  // Copyright 2019 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package validator
    18  
    19  import (
    20  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/klaytn/klaytn/blockchain"
    25  	"github.com/klaytn/klaytn/common"
    26  	"github.com/klaytn/klaytn/consensus/istanbul"
    27  	"github.com/klaytn/klaytn/crypto"
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  func TestNewWeightedCouncil(t *testing.T) {
    32  	const ValCnt = 100
    33  	var validators []istanbul.Validator
    34  	var rewardAddrs []common.Address
    35  	var votingPowers []uint64
    36  
    37  	// Create 100 validators with random addresses
    38  	b := []byte{}
    39  	for i := 0; i < ValCnt; i++ {
    40  		key, _ := crypto.GenerateKey()
    41  		addr := crypto.PubkeyToAddress(key.PublicKey)
    42  		val := New(addr)
    43  		validators = append(validators, val)
    44  		b = append(b, val.Address().Bytes()...)
    45  
    46  		rewardKey, _ := crypto.GenerateKey()
    47  		rewardAddr := crypto.PubkeyToAddress(rewardKey.PublicKey)
    48  		rewardAddrs = append(rewardAddrs, rewardAddr)
    49  
    50  		votingPowers = append(votingPowers, uint64(1))
    51  	}
    52  
    53  	// Create ValidatorSet
    54  	valSet := NewWeightedCouncil(ExtractValidators(b), nil, rewardAddrs, votingPowers, nil, istanbul.WeightedRandom, 21, 0, 0, nil)
    55  	if valSet == nil {
    56  		t.Errorf("the validator byte array cannot be parsed")
    57  		t.FailNow()
    58  	}
    59  
    60  	// Check validators sorting: should be in ascending order
    61  	for i := 0; i < ValCnt-1; i++ {
    62  		val := valSet.GetByIndex(uint64(i))
    63  		nextVal := valSet.GetByIndex(uint64(i + 1))
    64  		if strings.Compare(val.String(), nextVal.String()) >= 0 {
    65  			t.Errorf("validator set is not sorted in descending order")
    66  		}
    67  	}
    68  }
    69  
    70  func TestNormalWeightedCouncil(t *testing.T) {
    71  	b1 := common.Hex2Bytes(testAddress)
    72  	b2 := common.Hex2Bytes(testAddress2)
    73  	addr1 := common.BytesToAddress(b1)
    74  	addr2 := common.BytesToAddress(b2)
    75  
    76  	rewardKey1, _ := crypto.GenerateKey()
    77  	rewardAddr1 := crypto.PubkeyToAddress(rewardKey1.PublicKey)
    78  
    79  	rewardKey2, _ := crypto.GenerateKey()
    80  	rewardAddr2 := crypto.PubkeyToAddress(rewardKey2.PublicKey)
    81  
    82  	votingPower1 := uint64(1)
    83  	votingPower2 := uint64(2)
    84  
    85  	weight1 := uint64(1)
    86  	weight2 := uint64(2)
    87  
    88  	val1 := newWeightedValidator(addr1, rewardAddr1, votingPower1, weight1)
    89  	val2 := newWeightedValidator(addr2, rewardAddr2, votingPower2, weight2)
    90  
    91  	valSet := NewWeightedCouncil([]common.Address{addr1, addr2}, nil, []common.Address{rewardAddr1, rewardAddr2}, []uint64{votingPower1, votingPower2}, []uint64{weight1, weight2}, istanbul.WeightedRandom, 21, 0, 0, nil)
    92  	if valSet == nil {
    93  		t.Errorf("the format of validator set is invalid")
    94  		t.FailNow()
    95  	}
    96  
    97  	// check size
    98  	if size := valSet.Size(); size != 2 {
    99  		t.Errorf("the size of validator set is wrong: have %v, want 2", size)
   100  	}
   101  
   102  	// test get by index
   103  	if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) {
   104  		t.Errorf("validator mismatch:")
   105  		t.Errorf("  Address(): %v, %v", val.Address(), val1.Address())
   106  		t.Errorf("  String(): %v, %v", val.String(), val1.String())
   107  		t.Errorf("  RewardAddresS(): %v, %v", val.RewardAddress(), val1.RewardAddress())
   108  		t.Errorf("  VotingPower(): %v, %v", val.VotingPower(), val1.VotingPower())
   109  		t.Errorf("  Weight(): %v, %v", val.Weight(), val1.Weight())
   110  	}
   111  
   112  	// test get by invalid index
   113  	if val := valSet.GetByIndex(uint64(2)); val != nil {
   114  		t.Errorf("validator mismatch: have %v, want nil", val)
   115  	}
   116  
   117  	// test get by address
   118  	if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) {
   119  		t.Errorf("validator mismatch: have %v, want %v", val, val2)
   120  	}
   121  
   122  	// test get by invalid address
   123  	invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b")
   124  	if _, val := valSet.GetByAddress(invalidAddr); val != nil {
   125  		t.Errorf("validator mismatch: have %v, want nil", val)
   126  	}
   127  
   128  	// test get proposer
   129  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   130  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   131  	}
   132  
   133  	// test calculate proposer
   134  	lastProposer := addr1
   135  	valSet.CalcProposer(lastProposer, uint64(0))
   136  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   137  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   138  	}
   139  
   140  	valSet.CalcProposer(lastProposer, uint64(1))
   141  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   142  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   143  	}
   144  
   145  	valSet.CalcProposer(lastProposer, uint64(2))
   146  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   147  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   148  	}
   149  
   150  	valSet.CalcProposer(lastProposer, uint64(5))
   151  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   152  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   153  	}
   154  
   155  	// test empty last proposer
   156  	lastProposer = common.Address{}
   157  	valSet.CalcProposer(lastProposer, uint64(3))
   158  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   159  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   160  	}
   161  }
   162  
   163  func TestEmptyWeightedCouncil(t *testing.T) {
   164  	valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{})
   165  	if valSet == nil {
   166  		t.Errorf("validator set should not be nil")
   167  	}
   168  }
   169  
   170  func TestNewWeightedCouncil_InvalidPolicy(t *testing.T) {
   171  	// Invalid proposer policy
   172  	valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.Sticky, 0, 0, 0, &blockchain.BlockChain{})
   173  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   174  
   175  	valSet = NewWeightedCouncil(ExtractValidators([]byte{}), nil, nil, nil, nil, istanbul.RoundRobin, 0, 0, 0, &blockchain.BlockChain{})
   176  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   177  }
   178  
   179  func TestNewWeightedCouncil_IncompleteParams(t *testing.T) {
   180  	const ValCnt = 3
   181  	var validators []istanbul.Validator
   182  	var rewardAddrs []common.Address
   183  	var votingPowers []uint64
   184  	var weights []uint64
   185  
   186  	// Create 3 validators with random addresses
   187  	b := []byte{}
   188  	for i := 0; i < ValCnt; i++ {
   189  		key, _ := crypto.GenerateKey()
   190  		addr := crypto.PubkeyToAddress(key.PublicKey)
   191  		val := New(addr)
   192  		validators = append(validators, val)
   193  		b = append(b, val.Address().Bytes()...)
   194  
   195  		rewardKey, _ := crypto.GenerateKey()
   196  		rewardAddr := crypto.PubkeyToAddress(rewardKey.PublicKey)
   197  		rewardAddrs = append(rewardAddrs, rewardAddr)
   198  
   199  		votingPowers = append(votingPowers, uint64(1))
   200  		weights = append(weights, uint64(1))
   201  	}
   202  
   203  	// No validator address
   204  	valSet := NewWeightedCouncil(ExtractValidators([]byte{}), nil, rewardAddrs, votingPowers, weights, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{})
   205  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   206  
   207  	// Incomplete rewardAddrs
   208  	incompleteRewardAddrs := make([]common.Address, 1)
   209  	valSet = NewWeightedCouncil(ExtractValidators(b), nil, incompleteRewardAddrs, nil, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{})
   210  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   211  
   212  	// Incomplete rewardAddrs
   213  	incompleteVotingPowers := make([]uint64, 1)
   214  	valSet = NewWeightedCouncil(ExtractValidators(b), nil, nil, incompleteVotingPowers, nil, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{})
   215  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   216  
   217  	// Incomplete rewardAddrs
   218  	incompleteWeights := make([]uint64, 1)
   219  	valSet = NewWeightedCouncil(ExtractValidators(b), nil, nil, nil, incompleteWeights, istanbul.WeightedRandom, 0, 0, 0, &blockchain.BlockChain{})
   220  	assert.Equal(t, (*weightedCouncil)(nil), valSet)
   221  }