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