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

     1  // Copyright 2019 The Celo Authors
     2  // This file is part of the celo library.
     3  //
     4  // The celo 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 celo 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 celo library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package validator
    18  
    19  import (
    20  	"fmt"
    21  	"reflect"
    22  	"testing"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/consensus/istanbul"
    26  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
    27  )
    28  
    29  var testAddresses = []string{
    30  	"0000000000000000000000000000000000000001",
    31  	"0000000000000000000000000000000000000002",
    32  	"0000000000000000000000000000000000000003",
    33  	"0000000000000000000000000000000000000004",
    34  	"0000000000000000000000000000000000000005",
    35  }
    36  
    37  func TestStickyProposer(t *testing.T) {
    38  	var addrs []common.Address
    39  	var validators []istanbul.Validator
    40  	for _, strAddr := range testAddresses {
    41  		addr := common.HexToAddress(strAddr)
    42  		addrs = append(addrs, addr)
    43  		validators = append(validators, New(addr, blscrypto.SerializedPublicKey{}))
    44  	}
    45  
    46  	v, err := istanbul.CombineIstanbulExtraToValidatorData(addrs, make([]blscrypto.SerializedPublicKey, len(addrs)))
    47  	if err != nil {
    48  		t.Fatalf("CombineIstanbulExtraToValidatorData(...): %v", err)
    49  	}
    50  	valSet := newDefaultSet(v)
    51  	selector := GetProposerSelector(istanbul.Sticky)
    52  
    53  	cases := []struct {
    54  		lastProposer common.Address
    55  		round        uint64
    56  		want         istanbul.Validator
    57  	}{{
    58  		lastProposer: addrs[0],
    59  		round:        0,
    60  		want:         validators[0],
    61  	}, {
    62  		lastProposer: addrs[0],
    63  		round:        1,
    64  		want:         validators[1],
    65  	}, {
    66  		lastProposer: addrs[0],
    67  		round:        2,
    68  		want:         validators[2],
    69  	}, {
    70  		lastProposer: addrs[2],
    71  		round:        2,
    72  		want:         validators[4],
    73  	}, {
    74  		lastProposer: addrs[2],
    75  		round:        3,
    76  		want:         validators[0],
    77  	}, {
    78  		lastProposer: common.Address{},
    79  		round:        3,
    80  		want:         validators[3],
    81  	}}
    82  
    83  	for i, c := range cases {
    84  		t.Run(fmt.Sprintf("case:%d", i), func(t *testing.T) {
    85  			t.Logf("selectProposer(%s, %d)", c.lastProposer.String(), c.round)
    86  			proposer := selector(valSet, c.lastProposer, c.round)
    87  			if val := proposer; !reflect.DeepEqual(val, c.want) {
    88  				t.Errorf("proposer mismatch: have %v, want %v", val, c.want)
    89  			}
    90  		})
    91  	}
    92  }
    93  
    94  func TestRoundRobinProposer(t *testing.T) {
    95  	var addrs []common.Address
    96  	var validators []istanbul.Validator
    97  	for _, strAddr := range testAddresses {
    98  		addr := common.HexToAddress(strAddr)
    99  		addrs = append(addrs, addr)
   100  		validators = append(validators, New(addr, blscrypto.SerializedPublicKey{}))
   101  	}
   102  
   103  	v, err := istanbul.CombineIstanbulExtraToValidatorData(addrs, make([]blscrypto.SerializedPublicKey, len(addrs)))
   104  	if err != nil {
   105  		t.Fatalf("CombineIstanbulExtraToValidatorData(...): %v", err)
   106  	}
   107  	valSet := newDefaultSet(v)
   108  	selector := GetProposerSelector(istanbul.RoundRobin)
   109  
   110  	cases := []struct {
   111  		lastProposer common.Address
   112  		round        uint64
   113  		want         istanbul.Validator
   114  	}{{
   115  		lastProposer: addrs[0],
   116  		round:        0,
   117  		want:         validators[1],
   118  	}, {
   119  		lastProposer: addrs[0],
   120  		round:        1,
   121  		want:         validators[2],
   122  	}, {
   123  		lastProposer: addrs[0],
   124  		round:        2,
   125  		want:         validators[3],
   126  	}, {
   127  		lastProposer: addrs[2],
   128  		round:        2,
   129  		want:         validators[0],
   130  	}, {
   131  		lastProposer: addrs[2],
   132  		round:        3,
   133  		want:         validators[1],
   134  	}, {
   135  		lastProposer: common.Address{},
   136  		round:        3,
   137  		want:         validators[3],
   138  	}}
   139  
   140  	for i, c := range cases {
   141  		t.Run(fmt.Sprintf("case:%d", i), func(t *testing.T) {
   142  			t.Logf("selectProposer(%s, %d)", c.lastProposer.String(), c.round)
   143  			proposer := selector(valSet, c.lastProposer, c.round)
   144  			if val := proposer; !reflect.DeepEqual(val, c.want) {
   145  				t.Errorf("proposer mismatch: have %v, want %v", val, c.want)
   146  			}
   147  		})
   148  	}
   149  }
   150  
   151  func TestShuffledRoundRobinProposer(t *testing.T) {
   152  	var addrs []common.Address
   153  	var validators []istanbul.Validator
   154  	for _, strAddr := range testAddresses {
   155  		addr := common.HexToAddress(strAddr)
   156  		addrs = append(addrs, addr)
   157  		validators = append(validators, New(addr, blscrypto.SerializedPublicKey{}))
   158  	}
   159  
   160  	v, err := istanbul.CombineIstanbulExtraToValidatorData(addrs, make([]blscrypto.SerializedPublicKey, len(addrs)))
   161  	if err != nil {
   162  		t.Fatalf("CombineIstanbulExtraToValidatorData(...): %v", err)
   163  	}
   164  	valSet := newDefaultSet(v)
   165  	selector := GetProposerSelector(istanbul.ShuffledRoundRobin)
   166  
   167  	testSeed := common.HexToHash("f36aa9716b892ec8")
   168  	cases := []struct {
   169  		lastProposer common.Address
   170  		round        uint64
   171  		seed         common.Hash
   172  		want         istanbul.Validator
   173  	}{{
   174  		lastProposer: addrs[0],
   175  		round:        0,
   176  		want:         validators[1],
   177  	}, {
   178  		lastProposer: addrs[0],
   179  		round:        1,
   180  		want:         validators[4],
   181  	}, {
   182  		lastProposer: addrs[0],
   183  		round:        2,
   184  		want:         validators[2],
   185  	}, {
   186  		lastProposer: addrs[2],
   187  		round:        2,
   188  		want:         validators[1],
   189  	}, {
   190  		lastProposer: addrs[2],
   191  		round:        3,
   192  		want:         validators[4],
   193  	}, {
   194  		lastProposer: addrs[0],
   195  		round:        0,
   196  		seed:         testSeed,
   197  		want:         validators[4],
   198  	}, {
   199  		lastProposer: addrs[0],
   200  		round:        1,
   201  		seed:         testSeed,
   202  		want:         validators[2],
   203  	}, {
   204  		lastProposer: addrs[0],
   205  		round:        2,
   206  		seed:         testSeed,
   207  		want:         validators[1],
   208  	}, {
   209  		lastProposer: common.Address{},
   210  		round:        3,
   211  		want:         validators[0],
   212  	}}
   213  
   214  	for i, c := range cases {
   215  		t.Run(fmt.Sprintf("case:%d", i), func(t *testing.T) {
   216  			t.Logf("SetRandomness(%s)", c.seed.String())
   217  			valSet.SetRandomness(c.seed)
   218  			t.Logf("selectProposer(%s, %d)", c.lastProposer.String(), c.round)
   219  			proposer := selector(valSet, c.lastProposer, c.round)
   220  			if val := proposer; !reflect.DeepEqual(val, c.want) {
   221  				t.Errorf("proposer mismatch: have %v, want %v", val, c.want)
   222  			}
   223  		})
   224  	}
   225  }