github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/validator/default_test.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package validator
    18  
    19  import (
    20  	"math/big"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/rlp"
    25  
    26  	"github.com/ethereum/go-ethereum/common"
    27  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    28  	"github.com/ethereum/go-ethereum/crypto"
    29  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
    30  )
    31  
    32  var (
    33  	testAddress  = "70524d664ffe731100208a0154e556f9bb679ae6"
    34  	testAddress2 = "b37866a925bccd69cfa98d43b510f1d23d78a851"
    35  )
    36  
    37  func TestValidatorSet(t *testing.T) {
    38  	t.Run("NewValidatorSet", testNewValidatorSet)
    39  	t.Run("NormalValSet", testNormalValSet)
    40  	t.Run("EmptyValSet", testEmptyValSet)
    41  	t.Run("AddAndRemoveValidator", testAddAndRemoveValidator)
    42  	t.Run("QuorumSizes", testQuorumSizes)
    43  }
    44  
    45  func testNewValidatorSet(t *testing.T) {
    46  	var validators []istanbul.Validator
    47  	const ValCnt = 100
    48  
    49  	// Create 100 validators with random addresses
    50  	b := []byte{}
    51  	for i := 0; i < ValCnt; i++ {
    52  		key, _ := crypto.GenerateKey()
    53  		blsPrivateKey, _ := blscrypto.ECDSAToBLS(key)
    54  		blsPublicKey, _ := blscrypto.PrivateToPublic(blsPrivateKey)
    55  		addr := crypto.PubkeyToAddress(key.PublicKey)
    56  		val := New(addr, blsPublicKey)
    57  		validators = append(validators, val)
    58  		b = append(b, val.Address().Bytes()...)
    59  		b = append(b, blsPublicKey[:]...)
    60  	}
    61  
    62  	// Create ValidatorSet
    63  	valSet := NewSet(ExtractValidators(b))
    64  	if valSet == nil {
    65  		t.Errorf("the validator byte array cannot be parsed")
    66  		t.FailNow()
    67  	}
    68  }
    69  
    70  func testNormalValSet(t *testing.T) {
    71  	b1 := common.Hex2Bytes(testAddress)
    72  	b2 := common.Hex2Bytes(testAddress2)
    73  	addr1 := common.BytesToAddress(b1)
    74  	addr2 := common.BytesToAddress(b2)
    75  	val1 := New(addr1, blscrypto.SerializedPublicKey{})
    76  	val2 := New(addr2, blscrypto.SerializedPublicKey{})
    77  
    78  	validators, _ := istanbul.CombineIstanbulExtraToValidatorData([]common.Address{addr1, addr2}, []blscrypto.SerializedPublicKey{{}, {}})
    79  	valSet := newDefaultSet(validators)
    80  	if valSet == nil {
    81  		t.Errorf("the format of validator set is invalid")
    82  		t.FailNow()
    83  	}
    84  
    85  	// check size
    86  	if size := valSet.Size(); size != 2 {
    87  		t.Errorf("the size of validator set is wrong: have %v, want 2", size)
    88  	}
    89  	// test get by index
    90  	if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) {
    91  		t.Errorf("validator mismatch: have %v, want %v", val, val1)
    92  	}
    93  	// test get by invalid index
    94  	if val := valSet.GetByIndex(uint64(2)); val != nil {
    95  		t.Errorf("validator mismatch: have %v, want nil", val)
    96  	}
    97  	// test get by address
    98  	if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) {
    99  		t.Errorf("validator mismatch: have %v, want %v", val, val2)
   100  	}
   101  	// test get by invalid address
   102  	invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b")
   103  	if _, val := valSet.GetByAddress(invalidAddr); val != nil {
   104  		t.Errorf("validator mismatch: have %v, want nil", val)
   105  	}
   106  }
   107  
   108  func testEmptyValSet(t *testing.T) {
   109  	valSet := NewSet(ExtractValidators([]byte{}))
   110  	if valSet == nil {
   111  		t.Errorf("validator set should not be nil")
   112  	}
   113  }
   114  
   115  func testAddAndRemoveValidator(t *testing.T) {
   116  	valSet := NewSet(ExtractValidators([]byte{}))
   117  	if !valSet.AddValidators(
   118  		[]istanbul.ValidatorData{
   119  			{
   120  				common.BytesToAddress([]byte(string(3))),
   121  				blscrypto.SerializedPublicKey{},
   122  			},
   123  		},
   124  	) {
   125  		t.Error("the validator should be added")
   126  	}
   127  	if valSet.AddValidators(
   128  		[]istanbul.ValidatorData{
   129  			{
   130  				common.BytesToAddress([]byte(string(3))),
   131  				blscrypto.SerializedPublicKey{},
   132  			},
   133  		},
   134  	) {
   135  		t.Error("the existing validator should not be added")
   136  	}
   137  	valSet.AddValidators(
   138  		[]istanbul.ValidatorData{
   139  			{
   140  				common.BytesToAddress([]byte(string(2))),
   141  				blscrypto.SerializedPublicKey{},
   142  			},
   143  			{
   144  				common.BytesToAddress([]byte(string(1))),
   145  				blscrypto.SerializedPublicKey{},
   146  			},
   147  		},
   148  	)
   149  	if valSet.Size() != 3 {
   150  		t.Error("the size of validator set should be 3")
   151  	}
   152  
   153  	expectedOrder := []int{3, 2, 1}
   154  	for i, v := range valSet.List() {
   155  		expected := common.BytesToAddress([]byte(string(expectedOrder[i])))
   156  		if v.Address() != expected {
   157  			t.Errorf("the order of validators is wrong: have %v, want %v", v.Address().Hex(), expected.Hex())
   158  		}
   159  	}
   160  
   161  	if !valSet.RemoveValidators(big.NewInt(1)) { // remove first falidator
   162  		t.Error("the validator should be removed")
   163  	}
   164  
   165  	if len(valSet.List()) != 2 || len(valSet.List()) != valSet.Size() { // validators set should have the same size
   166  		t.Error("the size of validator set should be 2")
   167  	}
   168  	valSet.RemoveValidators(big.NewInt(2))                              // remove second validator
   169  	if len(valSet.List()) != 1 || len(valSet.List()) != valSet.Size() { // validators set should have the same size
   170  		t.Error("the size of validator set should be 1")
   171  	}
   172  	valSet.RemoveValidators(big.NewInt(1))                              // remove third validator
   173  	if len(valSet.List()) != 0 || len(valSet.List()) != valSet.Size() { // validators set should have the same size
   174  		t.Error("the size of validator set should be 0")
   175  	}
   176  }
   177  
   178  func generateValidators(n int) ([]istanbul.ValidatorData, [][]byte) {
   179  	vals := make([]istanbul.ValidatorData, 0)
   180  	keys := make([][]byte, 0)
   181  	for i := 0; i < n; i++ {
   182  		privateKey, _ := crypto.GenerateKey()
   183  		blsPrivateKey, _ := blscrypto.ECDSAToBLS(privateKey)
   184  		blsPublicKey, _ := blscrypto.PrivateToPublic(blsPrivateKey)
   185  		vals = append(vals, istanbul.ValidatorData{
   186  			Address:      crypto.PubkeyToAddress(privateKey.PublicKey),
   187  			BLSPublicKey: blsPublicKey,
   188  		})
   189  		keys = append(keys, blsPrivateKey)
   190  	}
   191  	return vals, keys
   192  }
   193  
   194  func testQuorumSizes(t *testing.T) {
   195  	testCases := []struct {
   196  		validatorSetSize      int
   197  		expectedMinQuorumSize int
   198  	}{
   199  		{validatorSetSize: 1, expectedMinQuorumSize: 1},
   200  		{validatorSetSize: 2, expectedMinQuorumSize: 2},
   201  		{validatorSetSize: 3, expectedMinQuorumSize: 2},
   202  		{validatorSetSize: 4, expectedMinQuorumSize: 3},
   203  		{validatorSetSize: 5, expectedMinQuorumSize: 4},
   204  		{validatorSetSize: 6, expectedMinQuorumSize: 4},
   205  		{validatorSetSize: 7, expectedMinQuorumSize: 5},
   206  	}
   207  
   208  	for _, testCase := range testCases {
   209  		vals, _ := generateValidators(testCase.validatorSetSize)
   210  		valSet := newDefaultSet(vals)
   211  
   212  		if valSet.MinQuorumSize() != testCase.expectedMinQuorumSize {
   213  			t.Errorf("error mismatch quorum size for valset of size %d: have %d, want %d", valSet.Size(), valSet.MinQuorumSize(), testCase.expectedMinQuorumSize)
   214  		}
   215  	}
   216  }
   217  
   218  func TestValidatorRLPEncoding(t *testing.T) {
   219  
   220  	val := New(common.BytesToAddress([]byte(string(2))), blscrypto.SerializedPublicKey{1, 2, 3})
   221  
   222  	rawVal, err := rlp.EncodeToBytes(val)
   223  	if err != nil {
   224  		t.Errorf("Error %v", err)
   225  	}
   226  
   227  	var result *defaultValidator
   228  	if err = rlp.DecodeBytes(rawVal, &result); err != nil {
   229  		t.Errorf("Error %v", err)
   230  	}
   231  
   232  	if !reflect.DeepEqual(val, result) {
   233  		t.Errorf("validator mismatch: have %v, want %v", val, result)
   234  	}
   235  }
   236  
   237  func TestValidatorSetRLPEncoding(t *testing.T) {
   238  
   239  	valSet := NewSet([]istanbul.ValidatorData{
   240  		{Address: common.BytesToAddress([]byte(string(2))), BLSPublicKey: blscrypto.SerializedPublicKey{1, 2, 3}},
   241  		{Address: common.BytesToAddress([]byte(string(4))), BLSPublicKey: blscrypto.SerializedPublicKey{3, 1, 4}},
   242  	})
   243  
   244  	rawVal, err := rlp.EncodeToBytes(valSet)
   245  	if err != nil {
   246  		t.Errorf("Error %v", err)
   247  	}
   248  
   249  	var result *defaultSet
   250  	if err = rlp.DecodeBytes(rawVal, &result); err != nil {
   251  		t.Errorf("Error %v", err)
   252  	}
   253  
   254  	if !reflect.DeepEqual(valSet, result) {
   255  		t.Errorf("validatorSet mismatch: have %v, want %v", valSet, result)
   256  	}
   257  }