github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/consensus/bor/snapshot_test.go (about) 1 package bor 2 3 import ( 4 "math/big" 5 "sort" 6 "testing" 7 8 "github.com/maticnetwork/crand" 9 "github.com/stretchr/testify/require" 10 "pgregory.net/rapid" 11 12 "github.com/ethereum/go-ethereum/common" 13 unique "github.com/ethereum/go-ethereum/common/set" 14 "github.com/ethereum/go-ethereum/consensus/bor/valset" 15 ) 16 17 const ( 18 numVals = 100 19 ) 20 21 func TestGetSignerSuccessionNumber_ProposerIsSigner(t *testing.T) { 22 t.Parallel() 23 24 validators := buildRandomValidatorSet(numVals) 25 validatorSet := valset.NewValidatorSet(validators) 26 snap := Snapshot{ 27 ValidatorSet: validatorSet, 28 } 29 30 // proposer is signer 31 signerTest := validatorSet.Proposer.Address 32 successionNumber, err := snap.GetSignerSuccessionNumber(signerTest) 33 if err != nil { 34 t.Fatalf("%s", err) 35 } 36 37 require.Equal(t, 0, successionNumber) 38 } 39 40 func TestGetSignerSuccessionNumber_SignerIndexIsLarger(t *testing.T) { 41 t.Parallel() 42 43 validators := buildRandomValidatorSet(numVals) 44 45 // sort validators by address, which is what NewValidatorSet also does 46 sort.Sort(valset.ValidatorsByAddress(validators)) 47 48 proposerIndex := 32 49 signerIndex := 56 50 // give highest ProposerPriority to a particular val, so that they become the proposer 51 validators[proposerIndex].VotingPower = 200 52 snap := Snapshot{ 53 ValidatorSet: valset.NewValidatorSet(validators), 54 } 55 56 // choose a signer at an index greater than proposer index 57 signerTest := snap.ValidatorSet.Validators[signerIndex].Address 58 successionNumber, err := snap.GetSignerSuccessionNumber(signerTest) 59 if err != nil { 60 t.Fatalf("%s", err) 61 } 62 63 require.Equal(t, signerIndex-proposerIndex, successionNumber) 64 } 65 66 func TestGetSignerSuccessionNumber_SignerIndexIsSmaller(t *testing.T) { 67 t.Parallel() 68 69 validators := buildRandomValidatorSet(numVals) 70 proposerIndex := 98 71 signerIndex := 11 72 // give highest ProposerPriority to a particular val, so that they become the proposer 73 validators[proposerIndex].VotingPower = 200 74 snap := Snapshot{ 75 ValidatorSet: valset.NewValidatorSet(validators), 76 } 77 78 // choose a signer at an index greater than proposer index 79 signerTest := snap.ValidatorSet.Validators[signerIndex].Address 80 successionNumber, err := snap.GetSignerSuccessionNumber(signerTest) 81 if err != nil { 82 t.Fatalf("%s", err) 83 } 84 85 require.Equal(t, signerIndex+numVals-proposerIndex, successionNumber) 86 } 87 88 func TestGetSignerSuccessionNumber_ProposerNotFound(t *testing.T) { 89 t.Parallel() 90 91 validators := buildRandomValidatorSet(numVals) 92 snap := Snapshot{ 93 ValidatorSet: valset.NewValidatorSet(validators), 94 } 95 96 require.Len(t, snap.ValidatorSet.Validators, numVals) 97 98 dummyProposerAddress := randomAddress(toAddresses(validators)...) 99 snap.ValidatorSet.Proposer = &valset.Validator{Address: dummyProposerAddress} 100 101 // choose any signer 102 signerTest := snap.ValidatorSet.Validators[3].Address 103 104 _, err := snap.GetSignerSuccessionNumber(signerTest) 105 require.NotNil(t, err) 106 107 e, ok := err.(*UnauthorizedProposerError) 108 require.True(t, ok) 109 require.Equal(t, dummyProposerAddress.Bytes(), e.Proposer) 110 } 111 112 func TestGetSignerSuccessionNumber_SignerNotFound(t *testing.T) { 113 t.Parallel() 114 115 validators := buildRandomValidatorSet(numVals) 116 snap := Snapshot{ 117 ValidatorSet: valset.NewValidatorSet(validators), 118 } 119 120 dummySignerAddress := randomAddress(toAddresses(validators)...) 121 _, err := snap.GetSignerSuccessionNumber(dummySignerAddress) 122 require.NotNil(t, err) 123 124 e, ok := err.(*UnauthorizedSignerError) 125 require.True(t, ok) 126 127 require.Equal(t, dummySignerAddress.Bytes(), e.Signer) 128 } 129 130 // nolint: unparam 131 func buildRandomValidatorSet(numVals int) []*valset.Validator { 132 validators := make([]*valset.Validator, numVals) 133 valAddrs := randomAddresses(numVals) 134 135 for i := 0; i < numVals; i++ { 136 power := crand.BigInt(big.NewInt(99)) 137 powerN := power.Int64() + 1 138 139 validators[i] = &valset.Validator{ 140 Address: valAddrs[i], 141 // cannot process validators with voting power 0, hence +1 142 VotingPower: powerN, 143 } 144 } 145 146 // sort validators by address, which is what NewValidatorSet also does 147 sort.Sort(valset.ValidatorsByAddress(validators)) 148 149 return validators 150 } 151 152 func randomAddress(exclude ...common.Address) common.Address { 153 excl := make(map[common.Address]struct{}, len(exclude)) 154 155 for _, addr := range exclude { 156 excl[addr] = struct{}{} 157 } 158 159 r := crand.NewRand() 160 161 for { 162 addr := r.Address() 163 if _, ok := excl[addr]; ok { 164 continue 165 } 166 167 return addr 168 } 169 } 170 171 func randomAddresses(n int) []common.Address { 172 if n <= 0 { 173 return []common.Address{} 174 } 175 176 addrs := make([]common.Address, 0, n) 177 addrsSet := make(map[common.Address]struct{}, n) 178 179 var exist bool 180 181 r := crand.NewRand() 182 183 for { 184 addr := r.Address() 185 186 _, exist = addrsSet[addr] 187 if !exist { 188 addrs = append(addrs, addr) 189 190 addrsSet[addr] = struct{}{} 191 } 192 193 if len(addrs) == n { 194 return addrs 195 } 196 } 197 } 198 199 func TestRandomAddresses(t *testing.T) { 200 t.Parallel() 201 202 rapid.Check(t, func(t *rapid.T) { 203 length := rapid.IntMax(300).Draw(t, "length").(int) 204 205 addrs := randomAddresses(length) 206 addressSet := unique.New(addrs) 207 208 if len(addrs) != len(addressSet) { 209 t.Fatalf("length of unique addresses %d, expected %d", len(addressSet), len(addrs)) 210 } 211 }) 212 } 213 214 func toAddresses(vals []*valset.Validator) []common.Address { 215 addrs := make([]common.Address, len(vals)) 216 217 for i, val := range vals { 218 addrs[i] = val.Address 219 } 220 221 return addrs 222 }