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 }