github.com/ConsenSys/Quorum@v20.10.0+incompatible/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  	"reflect"
    21  	"strings"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  )
    28  
    29  var (
    30  	testAddress  = "70524d664ffe731100208a0154e556f9bb679ae6"
    31  	testAddress2 = "b37866a925bccd69cfa98d43b510f1d23d78a851"
    32  )
    33  
    34  func TestValidatorSet(t *testing.T) {
    35  	testNewValidatorSet(t)
    36  	testNormalValSet(t)
    37  	testEmptyValSet(t)
    38  	testStickyProposer(t)
    39  	testAddAndRemoveValidator(t)
    40  }
    41  
    42  func testNewValidatorSet(t *testing.T) {
    43  	var validators []istanbul.Validator
    44  	const ValCnt = 100
    45  
    46  	// Create 100 validators with random addresses
    47  	b := []byte{}
    48  	for i := 0; i < ValCnt; i++ {
    49  		key, _ := crypto.GenerateKey()
    50  		addr := crypto.PubkeyToAddress(key.PublicKey)
    51  		val := New(addr)
    52  		validators = append(validators, val)
    53  		b = append(b, val.Address().Bytes()...)
    54  	}
    55  
    56  	// Create ValidatorSet
    57  	valSet := NewSet(ExtractValidators(b), istanbul.RoundRobin)
    58  	if valSet == nil {
    59  		t.Errorf("the validator byte array cannot be parsed")
    60  		t.FailNow()
    61  	}
    62  
    63  	// Check validators sorting: should be in ascending order
    64  	for i := 0; i < ValCnt-1; i++ {
    65  		val := valSet.GetByIndex(uint64(i))
    66  		nextVal := valSet.GetByIndex(uint64(i + 1))
    67  		if strings.Compare(val.String(), nextVal.String()) >= 0 {
    68  			t.Errorf("validator set is not sorted in ascending order")
    69  		}
    70  	}
    71  }
    72  
    73  func testNormalValSet(t *testing.T) {
    74  	b1 := common.Hex2Bytes(testAddress)
    75  	b2 := common.Hex2Bytes(testAddress2)
    76  	addr1 := common.BytesToAddress(b1)
    77  	addr2 := common.BytesToAddress(b2)
    78  	val1 := New(addr1)
    79  	val2 := New(addr2)
    80  
    81  	valSet := newDefaultSet([]common.Address{addr1, addr2}, istanbul.RoundRobin)
    82  	if valSet == nil {
    83  		t.Errorf("the format of validator set is invalid")
    84  		t.FailNow()
    85  	}
    86  
    87  	// check size
    88  	if size := valSet.Size(); size != 2 {
    89  		t.Errorf("the size of validator set is wrong: have %v, want 2", size)
    90  	}
    91  	// test get by index
    92  	if val := valSet.GetByIndex(uint64(0)); !reflect.DeepEqual(val, val1) {
    93  		t.Errorf("validator mismatch: have %v, want %v", val, val1)
    94  	}
    95  	// test get by invalid index
    96  	if val := valSet.GetByIndex(uint64(2)); val != nil {
    97  		t.Errorf("validator mismatch: have %v, want nil", val)
    98  	}
    99  	// test get by address
   100  	if _, val := valSet.GetByAddress(addr2); !reflect.DeepEqual(val, val2) {
   101  		t.Errorf("validator mismatch: have %v, want %v", val, val2)
   102  	}
   103  	// test get by invalid address
   104  	invalidAddr := common.HexToAddress("0x9535b2e7faaba5288511d89341d94a38063a349b")
   105  	if _, val := valSet.GetByAddress(invalidAddr); val != nil {
   106  		t.Errorf("validator mismatch: have %v, want nil", val)
   107  	}
   108  	// test get proposer
   109  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   110  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   111  	}
   112  	// test calculate proposer
   113  	lastProposer := addr1
   114  	valSet.CalcProposer(lastProposer, uint64(0))
   115  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   116  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   117  	}
   118  	valSet.CalcProposer(lastProposer, uint64(3))
   119  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   120  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   121  	}
   122  	// test empty last proposer
   123  	lastProposer = common.Address{}
   124  	valSet.CalcProposer(lastProposer, uint64(3))
   125  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   126  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   127  	}
   128  }
   129  
   130  func testEmptyValSet(t *testing.T) {
   131  	valSet := NewSet(ExtractValidators([]byte{}), istanbul.RoundRobin)
   132  	if valSet == nil {
   133  		t.Errorf("validator set should not be nil")
   134  	}
   135  }
   136  
   137  func testAddAndRemoveValidator(t *testing.T) {
   138  	valSet := NewSet(ExtractValidators([]byte{}), istanbul.RoundRobin)
   139  	if !valSet.AddValidator(common.StringToAddress(string(2))) {
   140  		t.Error("the validator should be added")
   141  	}
   142  	if valSet.AddValidator(common.StringToAddress(string(2))) {
   143  		t.Error("the existing validator should not be added")
   144  	}
   145  	valSet.AddValidator(common.StringToAddress(string(1)))
   146  	valSet.AddValidator(common.StringToAddress(string(0)))
   147  	if len(valSet.List()) != 3 {
   148  		t.Error("the size of validator set should be 3")
   149  	}
   150  
   151  	for i, v := range valSet.List() {
   152  		expected := common.StringToAddress(string(i))
   153  		if v.Address() != expected {
   154  			t.Errorf("the order of validators is wrong: have %v, want %v", v.Address().Hex(), expected.Hex())
   155  		}
   156  	}
   157  
   158  	if !valSet.RemoveValidator(common.StringToAddress(string(2))) {
   159  		t.Error("the validator should be removed")
   160  	}
   161  	if valSet.RemoveValidator(common.StringToAddress(string(2))) {
   162  		t.Error("the non-existing validator should not be removed")
   163  	}
   164  	if len(valSet.List()) != 2 {
   165  		t.Error("the size of validator set should be 2")
   166  	}
   167  	valSet.RemoveValidator(common.StringToAddress(string(1)))
   168  	if len(valSet.List()) != 1 {
   169  		t.Error("the size of validator set should be 1")
   170  	}
   171  	valSet.RemoveValidator(common.StringToAddress(string(0)))
   172  	if len(valSet.List()) != 0 {
   173  		t.Error("the size of validator set should be 0")
   174  	}
   175  }
   176  
   177  func testStickyProposer(t *testing.T) {
   178  	b1 := common.Hex2Bytes(testAddress)
   179  	b2 := common.Hex2Bytes(testAddress2)
   180  	addr1 := common.BytesToAddress(b1)
   181  	addr2 := common.BytesToAddress(b2)
   182  	val1 := New(addr1)
   183  	val2 := New(addr2)
   184  
   185  	valSet := newDefaultSet([]common.Address{addr1, addr2}, istanbul.Sticky)
   186  
   187  	// test get proposer
   188  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   189  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   190  	}
   191  	// test calculate proposer
   192  	lastProposer := addr1
   193  	valSet.CalcProposer(lastProposer, uint64(0))
   194  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val1) {
   195  		t.Errorf("proposer mismatch: have %v, want %v", val, val1)
   196  	}
   197  
   198  	valSet.CalcProposer(lastProposer, uint64(1))
   199  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   200  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   201  	}
   202  	// test empty last proposer
   203  	lastProposer = common.Address{}
   204  	valSet.CalcProposer(lastProposer, uint64(3))
   205  	if val := valSet.GetProposer(); !reflect.DeepEqual(val, val2) {
   206  		t.Errorf("proposer mismatch: have %v, want %v", val, val2)
   207  	}
   208  }