github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/validator_set_test.go (about)

     1  package types
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"math"
     7  	"sort"
     8  	"strings"
     9  	"testing"
    10  	"testing/quick"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  
    14  	"github.com/evdatsion/aphelion-dpos-bft/crypto"
    15  	"github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519"
    16  	cmn "github.com/evdatsion/aphelion-dpos-bft/libs/common"
    17  	tmtime "github.com/evdatsion/aphelion-dpos-bft/types/time"
    18  )
    19  
    20  func TestValidatorSetBasic(t *testing.T) {
    21  	// empty or nil validator lists are allowed,
    22  	// but attempting to IncrementProposerPriority on them will panic.
    23  	vset := NewValidatorSet([]*Validator{})
    24  	assert.Panics(t, func() { vset.IncrementProposerPriority(1) })
    25  
    26  	vset = NewValidatorSet(nil)
    27  	assert.Panics(t, func() { vset.IncrementProposerPriority(1) })
    28  
    29  	assert.EqualValues(t, vset, vset.Copy())
    30  	assert.False(t, vset.HasAddress([]byte("some val")))
    31  	idx, val := vset.GetByAddress([]byte("some val"))
    32  	assert.Equal(t, -1, idx)
    33  	assert.Nil(t, val)
    34  	addr, val := vset.GetByIndex(-100)
    35  	assert.Nil(t, addr)
    36  	assert.Nil(t, val)
    37  	addr, val = vset.GetByIndex(0)
    38  	assert.Nil(t, addr)
    39  	assert.Nil(t, val)
    40  	addr, val = vset.GetByIndex(100)
    41  	assert.Nil(t, addr)
    42  	assert.Nil(t, val)
    43  	assert.Zero(t, vset.Size())
    44  	assert.Equal(t, int64(0), vset.TotalVotingPower())
    45  	assert.Nil(t, vset.GetProposer())
    46  	assert.Nil(t, vset.Hash())
    47  
    48  	// add
    49  	val = randValidator_(vset.TotalVotingPower())
    50  	assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val}))
    51  
    52  	assert.True(t, vset.HasAddress(val.Address))
    53  	idx, _ = vset.GetByAddress(val.Address)
    54  	assert.Equal(t, 0, idx)
    55  	addr, _ = vset.GetByIndex(0)
    56  	assert.Equal(t, []byte(val.Address), addr)
    57  	assert.Equal(t, 1, vset.Size())
    58  	assert.Equal(t, val.VotingPower, vset.TotalVotingPower())
    59  	assert.NotNil(t, vset.Hash())
    60  	assert.NotPanics(t, func() { vset.IncrementProposerPriority(1) })
    61  	assert.Equal(t, val.Address, vset.GetProposer().Address)
    62  
    63  	// update
    64  	val = randValidator_(vset.TotalVotingPower())
    65  	assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val}))
    66  	_, val = vset.GetByAddress(val.Address)
    67  	val.VotingPower += 100
    68  	proposerPriority := val.ProposerPriority
    69  
    70  	val.ProposerPriority = 0
    71  	assert.NoError(t, vset.UpdateWithChangeSet([]*Validator{val}))
    72  	_, val = vset.GetByAddress(val.Address)
    73  	assert.Equal(t, proposerPriority, val.ProposerPriority)
    74  
    75  }
    76  
    77  func TestCopy(t *testing.T) {
    78  	vset := randValidatorSet(10)
    79  	vsetHash := vset.Hash()
    80  	if len(vsetHash) == 0 {
    81  		t.Fatalf("ValidatorSet had unexpected zero hash")
    82  	}
    83  
    84  	vsetCopy := vset.Copy()
    85  	vsetCopyHash := vsetCopy.Hash()
    86  
    87  	if !bytes.Equal(vsetHash, vsetCopyHash) {
    88  		t.Fatalf("ValidatorSet copy had wrong hash. Orig: %X, Copy: %X", vsetHash, vsetCopyHash)
    89  	}
    90  }
    91  
    92  // Test that IncrementProposerPriority requires positive times.
    93  func TestIncrementProposerPriorityPositiveTimes(t *testing.T) {
    94  	vset := NewValidatorSet([]*Validator{
    95  		newValidator([]byte("foo"), 1000),
    96  		newValidator([]byte("bar"), 300),
    97  		newValidator([]byte("baz"), 330),
    98  	})
    99  
   100  	assert.Panics(t, func() { vset.IncrementProposerPriority(-1) })
   101  	assert.Panics(t, func() { vset.IncrementProposerPriority(0) })
   102  	vset.IncrementProposerPriority(1)
   103  }
   104  
   105  func BenchmarkValidatorSetCopy(b *testing.B) {
   106  	b.StopTimer()
   107  	vset := NewValidatorSet([]*Validator{})
   108  	for i := 0; i < 1000; i++ {
   109  		privKey := ed25519.GenPrivKey()
   110  		pubKey := privKey.PubKey()
   111  		val := NewValidator(pubKey, 10)
   112  		err := vset.UpdateWithChangeSet([]*Validator{val})
   113  		if err != nil {
   114  			panic("Failed to add validator")
   115  		}
   116  	}
   117  	b.StartTimer()
   118  
   119  	for i := 0; i < b.N; i++ {
   120  		vset.Copy()
   121  	}
   122  }
   123  
   124  //-------------------------------------------------------------------
   125  
   126  func TestProposerSelection1(t *testing.T) {
   127  	vset := NewValidatorSet([]*Validator{
   128  		newValidator([]byte("foo"), 1000),
   129  		newValidator([]byte("bar"), 300),
   130  		newValidator([]byte("baz"), 330),
   131  	})
   132  	var proposers []string
   133  	for i := 0; i < 99; i++ {
   134  		val := vset.GetProposer()
   135  		proposers = append(proposers, string(val.Address))
   136  		vset.IncrementProposerPriority(1)
   137  	}
   138  	expected := `foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo foo baz bar foo foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo bar foo foo baz foo foo bar foo baz foo foo bar foo baz foo foo bar foo baz foo foo`
   139  	if expected != strings.Join(proposers, " ") {
   140  		t.Errorf("Expected sequence of proposers was\n%v\nbut got \n%v", expected, strings.Join(proposers, " "))
   141  	}
   142  }
   143  
   144  func TestProposerSelection2(t *testing.T) {
   145  	addr0 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   146  	addr1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
   147  	addr2 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}
   148  
   149  	// when all voting power is same, we go in order of addresses
   150  	val0, val1, val2 := newValidator(addr0, 100), newValidator(addr1, 100), newValidator(addr2, 100)
   151  	valList := []*Validator{val0, val1, val2}
   152  	vals := NewValidatorSet(valList)
   153  	for i := 0; i < len(valList)*5; i++ {
   154  		ii := (i) % len(valList)
   155  		prop := vals.GetProposer()
   156  		if !bytes.Equal(prop.Address, valList[ii].Address) {
   157  			t.Fatalf("(%d): Expected %X. Got %X", i, valList[ii].Address, prop.Address)
   158  		}
   159  		vals.IncrementProposerPriority(1)
   160  	}
   161  
   162  	// One validator has more than the others, but not enough to propose twice in a row
   163  	*val2 = *newValidator(addr2, 400)
   164  	vals = NewValidatorSet(valList)
   165  	// vals.IncrementProposerPriority(1)
   166  	prop := vals.GetProposer()
   167  	if !bytes.Equal(prop.Address, addr2) {
   168  		t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
   169  	}
   170  	vals.IncrementProposerPriority(1)
   171  	prop = vals.GetProposer()
   172  	if !bytes.Equal(prop.Address, addr0) {
   173  		t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
   174  	}
   175  
   176  	// One validator has more than the others, and enough to be proposer twice in a row
   177  	*val2 = *newValidator(addr2, 401)
   178  	vals = NewValidatorSet(valList)
   179  	prop = vals.GetProposer()
   180  	if !bytes.Equal(prop.Address, addr2) {
   181  		t.Fatalf("Expected address with highest voting power to be first proposer. Got %X", prop.Address)
   182  	}
   183  	vals.IncrementProposerPriority(1)
   184  	prop = vals.GetProposer()
   185  	if !bytes.Equal(prop.Address, addr2) {
   186  		t.Fatalf("Expected address with highest voting power to be second proposer. Got %X", prop.Address)
   187  	}
   188  	vals.IncrementProposerPriority(1)
   189  	prop = vals.GetProposer()
   190  	if !bytes.Equal(prop.Address, addr0) {
   191  		t.Fatalf("Expected smallest address to be validator. Got %X", prop.Address)
   192  	}
   193  
   194  	// each validator should be the proposer a proportional number of times
   195  	val0, val1, val2 = newValidator(addr0, 4), newValidator(addr1, 5), newValidator(addr2, 3)
   196  	valList = []*Validator{val0, val1, val2}
   197  	propCount := make([]int, 3)
   198  	vals = NewValidatorSet(valList)
   199  	N := 1
   200  	for i := 0; i < 120*N; i++ {
   201  		prop := vals.GetProposer()
   202  		ii := prop.Address[19]
   203  		propCount[ii]++
   204  		vals.IncrementProposerPriority(1)
   205  	}
   206  
   207  	if propCount[0] != 40*N {
   208  		t.Fatalf("Expected prop count for validator with 4/12 of voting power to be %d/%d. Got %d/%d", 40*N, 120*N, propCount[0], 120*N)
   209  	}
   210  	if propCount[1] != 50*N {
   211  		t.Fatalf("Expected prop count for validator with 5/12 of voting power to be %d/%d. Got %d/%d", 50*N, 120*N, propCount[1], 120*N)
   212  	}
   213  	if propCount[2] != 30*N {
   214  		t.Fatalf("Expected prop count for validator with 3/12 of voting power to be %d/%d. Got %d/%d", 30*N, 120*N, propCount[2], 120*N)
   215  	}
   216  }
   217  
   218  func TestProposerSelection3(t *testing.T) {
   219  	vset := NewValidatorSet([]*Validator{
   220  		newValidator([]byte("a"), 1),
   221  		newValidator([]byte("b"), 1),
   222  		newValidator([]byte("c"), 1),
   223  		newValidator([]byte("d"), 1),
   224  	})
   225  
   226  	proposerOrder := make([]*Validator, 4)
   227  	for i := 0; i < 4; i++ {
   228  		proposerOrder[i] = vset.GetProposer()
   229  		vset.IncrementProposerPriority(1)
   230  	}
   231  
   232  	// i for the loop
   233  	// j for the times
   234  	// we should go in order for ever, despite some IncrementProposerPriority with times > 1
   235  	var i, j int
   236  	for ; i < 10000; i++ {
   237  		got := vset.GetProposer().Address
   238  		expected := proposerOrder[j%4].Address
   239  		if !bytes.Equal(got, expected) {
   240  			t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match expected proposer (%X) for (%d, %d)", got, expected, i, j))
   241  		}
   242  
   243  		// serialize, deserialize, check proposer
   244  		b := vset.toBytes()
   245  		vset.fromBytes(b)
   246  
   247  		computed := vset.GetProposer() // findGetProposer()
   248  		if i != 0 {
   249  			if !bytes.Equal(got, computed.Address) {
   250  				t.Fatalf(fmt.Sprintf("vset.Proposer (%X) does not match computed proposer (%X) for (%d, %d)", got, computed.Address, i, j))
   251  			}
   252  		}
   253  
   254  		// times is usually 1
   255  		times := 1
   256  		mod := (cmn.RandInt() % 5) + 1
   257  		if cmn.RandInt()%mod > 0 {
   258  			// sometimes its up to 5
   259  			times = (cmn.RandInt() % 4) + 1
   260  		}
   261  		vset.IncrementProposerPriority(times)
   262  
   263  		j += times
   264  	}
   265  }
   266  
   267  func newValidator(address []byte, power int64) *Validator {
   268  	return &Validator{Address: address, VotingPower: power}
   269  }
   270  
   271  func randPubKey() crypto.PubKey {
   272  	var pubKey [32]byte
   273  	copy(pubKey[:], cmn.RandBytes(32))
   274  	return ed25519.PubKeyEd25519(pubKey)
   275  }
   276  
   277  func randValidator_(totalVotingPower int64) *Validator {
   278  	// this modulo limits the ProposerPriority/VotingPower to stay in the
   279  	// bounds of MaxTotalVotingPower minus the already existing voting power:
   280  	val := NewValidator(randPubKey(), int64(cmn.RandUint64()%uint64((MaxTotalVotingPower-totalVotingPower))))
   281  	val.ProposerPriority = cmn.RandInt64() % (MaxTotalVotingPower - totalVotingPower)
   282  	return val
   283  }
   284  
   285  func randValidatorSet(numValidators int) *ValidatorSet {
   286  	validators := make([]*Validator, numValidators)
   287  	totalVotingPower := int64(0)
   288  	for i := 0; i < numValidators; i++ {
   289  		validators[i] = randValidator_(totalVotingPower)
   290  		totalVotingPower += validators[i].VotingPower
   291  	}
   292  	return NewValidatorSet(validators)
   293  }
   294  
   295  func (valSet *ValidatorSet) toBytes() []byte {
   296  	bz, err := cdc.MarshalBinaryLengthPrefixed(valSet)
   297  	if err != nil {
   298  		panic(err)
   299  	}
   300  	return bz
   301  }
   302  
   303  func (valSet *ValidatorSet) fromBytes(b []byte) {
   304  	err := cdc.UnmarshalBinaryLengthPrefixed(b, &valSet)
   305  	if err != nil {
   306  		// DATA HAS BEEN CORRUPTED OR THE SPEC HAS CHANGED
   307  		panic(err)
   308  	}
   309  }
   310  
   311  //-------------------------------------------------------------------
   312  
   313  func TestValidatorSetTotalVotingPowerPanicsOnOverflow(t *testing.T) {
   314  	// NewValidatorSet calls IncrementProposerPriority which calls TotalVotingPower()
   315  	// which should panic on overflows:
   316  	shouldPanic := func() {
   317  		NewValidatorSet([]*Validator{
   318  			{Address: []byte("a"), VotingPower: math.MaxInt64, ProposerPriority: 0},
   319  			{Address: []byte("b"), VotingPower: math.MaxInt64, ProposerPriority: 0},
   320  			{Address: []byte("c"), VotingPower: math.MaxInt64, ProposerPriority: 0},
   321  		})
   322  	}
   323  
   324  	assert.Panics(t, shouldPanic)
   325  }
   326  
   327  func TestAvgProposerPriority(t *testing.T) {
   328  	// Create Validator set without calling IncrementProposerPriority:
   329  	tcs := []struct {
   330  		vs   ValidatorSet
   331  		want int64
   332  	}{
   333  		0: {ValidatorSet{Validators: []*Validator{{ProposerPriority: 0}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, 0},
   334  		1: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}, {ProposerPriority: 0}}}, math.MaxInt64 / 3},
   335  		2: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: 0}}}, math.MaxInt64 / 2},
   336  		3: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MaxInt64}, {ProposerPriority: math.MaxInt64}}}, math.MaxInt64},
   337  		4: {ValidatorSet{Validators: []*Validator{{ProposerPriority: math.MinInt64}, {ProposerPriority: math.MinInt64}}}, math.MinInt64},
   338  	}
   339  	for i, tc := range tcs {
   340  		got := tc.vs.computeAvgProposerPriority()
   341  		assert.Equal(t, tc.want, got, "test case: %v", i)
   342  	}
   343  }
   344  
   345  func TestAveragingInIncrementProposerPriority(t *testing.T) {
   346  	// Test that the averaging works as expected inside of IncrementProposerPriority.
   347  	// Each validator comes with zero voting power which simplifies reasoning about
   348  	// the expected ProposerPriority.
   349  	tcs := []struct {
   350  		vs    ValidatorSet
   351  		times int
   352  		avg   int64
   353  	}{
   354  		0: {ValidatorSet{
   355  			Validators: []*Validator{
   356  				{Address: []byte("a"), ProposerPriority: 1},
   357  				{Address: []byte("b"), ProposerPriority: 2},
   358  				{Address: []byte("c"), ProposerPriority: 3}}},
   359  			1, 2},
   360  		1: {ValidatorSet{
   361  			Validators: []*Validator{
   362  				{Address: []byte("a"), ProposerPriority: 10},
   363  				{Address: []byte("b"), ProposerPriority: -10},
   364  				{Address: []byte("c"), ProposerPriority: 1}}},
   365  			// this should average twice but the average should be 0 after the first iteration
   366  			// (voting power is 0 -> no changes)
   367  			11, 1 / 3},
   368  		2: {ValidatorSet{
   369  			Validators: []*Validator{
   370  				{Address: []byte("a"), ProposerPriority: 100},
   371  				{Address: []byte("b"), ProposerPriority: -10},
   372  				{Address: []byte("c"), ProposerPriority: 1}}},
   373  			1, 91 / 3},
   374  	}
   375  	for i, tc := range tcs {
   376  		// work on copy to have the old ProposerPriorities:
   377  		newVset := tc.vs.CopyIncrementProposerPriority(tc.times)
   378  		for _, val := range tc.vs.Validators {
   379  			_, updatedVal := newVset.GetByAddress(val.Address)
   380  			assert.Equal(t, updatedVal.ProposerPriority, val.ProposerPriority-tc.avg, "test case: %v", i)
   381  		}
   382  	}
   383  }
   384  
   385  func TestAveragingInIncrementProposerPriorityWithVotingPower(t *testing.T) {
   386  	// Other than TestAveragingInIncrementProposerPriority this is a more complete test showing
   387  	// how each ProposerPriority changes in relation to the validator's voting power respectively.
   388  	// average is zero in each round:
   389  	vp0 := int64(10)
   390  	vp1 := int64(1)
   391  	vp2 := int64(1)
   392  	total := vp0 + vp1 + vp2
   393  	avg := (vp0 + vp1 + vp2 - total) / 3
   394  	vals := ValidatorSet{Validators: []*Validator{
   395  		{Address: []byte{0}, ProposerPriority: 0, VotingPower: vp0},
   396  		{Address: []byte{1}, ProposerPriority: 0, VotingPower: vp1},
   397  		{Address: []byte{2}, ProposerPriority: 0, VotingPower: vp2}}}
   398  	tcs := []struct {
   399  		vals                  *ValidatorSet
   400  		wantProposerPrioritys []int64
   401  		times                 int
   402  		wantProposer          *Validator
   403  	}{
   404  
   405  		0: {
   406  			vals.Copy(),
   407  			[]int64{
   408  				// Acumm+VotingPower-Avg:
   409  				0 + vp0 - total - avg, // mostest will be subtracted by total voting power (12)
   410  				0 + vp1,
   411  				0 + vp2},
   412  			1,
   413  			vals.Validators[0]},
   414  		1: {
   415  			vals.Copy(),
   416  			[]int64{
   417  				(0 + vp0 - total) + vp0 - total - avg, // this will be mostest on 2nd iter, too
   418  				(0 + vp1) + vp1,
   419  				(0 + vp2) + vp2},
   420  			2,
   421  			vals.Validators[0]}, // increment twice -> expect average to be subtracted twice
   422  		2: {
   423  			vals.Copy(),
   424  			[]int64{
   425  				0 + 3*(vp0-total) - avg, // still mostest
   426  				0 + 3*vp1,
   427  				0 + 3*vp2},
   428  			3,
   429  			vals.Validators[0]},
   430  		3: {
   431  			vals.Copy(),
   432  			[]int64{
   433  				0 + 4*(vp0-total), // still mostest
   434  				0 + 4*vp1,
   435  				0 + 4*vp2},
   436  			4,
   437  			vals.Validators[0]},
   438  		4: {
   439  			vals.Copy(),
   440  			[]int64{
   441  				0 + 4*(vp0-total) + vp0, // 4 iters was mostest
   442  				0 + 5*vp1 - total,       // now this val is mostest for the 1st time (hence -12==totalVotingPower)
   443  				0 + 5*vp2},
   444  			5,
   445  			vals.Validators[1]},
   446  		5: {
   447  			vals.Copy(),
   448  			[]int64{
   449  				0 + 6*vp0 - 5*total, // mostest again
   450  				0 + 6*vp1 - total,   // mostest once up to here
   451  				0 + 6*vp2},
   452  			6,
   453  			vals.Validators[0]},
   454  		6: {
   455  			vals.Copy(),
   456  			[]int64{
   457  				0 + 7*vp0 - 6*total, // in 7 iters this val is mostest 6 times
   458  				0 + 7*vp1 - total,   // in 7 iters this val is mostest 1 time
   459  				0 + 7*vp2},
   460  			7,
   461  			vals.Validators[0]},
   462  		7: {
   463  			vals.Copy(),
   464  			[]int64{
   465  				0 + 8*vp0 - 7*total, // mostest again
   466  				0 + 8*vp1 - total,
   467  				0 + 8*vp2},
   468  			8,
   469  			vals.Validators[0]},
   470  		8: {
   471  			vals.Copy(),
   472  			[]int64{
   473  				0 + 9*vp0 - 7*total,
   474  				0 + 9*vp1 - total,
   475  				0 + 9*vp2 - total}, // mostest
   476  			9,
   477  			vals.Validators[2]},
   478  		9: {
   479  			vals.Copy(),
   480  			[]int64{
   481  				0 + 10*vp0 - 8*total, // after 10 iters this is mostest again
   482  				0 + 10*vp1 - total,   // after 6 iters this val is "mostest" once and not in between
   483  				0 + 10*vp2 - total},  // in between 10 iters this val is "mostest" once
   484  			10,
   485  			vals.Validators[0]},
   486  		10: {
   487  			vals.Copy(),
   488  			[]int64{
   489  				0 + 11*vp0 - 9*total,
   490  				0 + 11*vp1 - total,  // after 6 iters this val is "mostest" once and not in between
   491  				0 + 11*vp2 - total}, // after 10 iters this val is "mostest" once
   492  			11,
   493  			vals.Validators[0]},
   494  	}
   495  	for i, tc := range tcs {
   496  		tc.vals.IncrementProposerPriority(tc.times)
   497  
   498  		assert.Equal(t, tc.wantProposer.Address, tc.vals.GetProposer().Address,
   499  			"test case: %v",
   500  			i)
   501  
   502  		for valIdx, val := range tc.vals.Validators {
   503  			assert.Equal(t,
   504  				tc.wantProposerPrioritys[valIdx],
   505  				val.ProposerPriority,
   506  				"test case: %v, validator: %v",
   507  				i,
   508  				valIdx)
   509  		}
   510  	}
   511  }
   512  
   513  func TestSafeAdd(t *testing.T) {
   514  	f := func(a, b int64) bool {
   515  		c, overflow := safeAdd(a, b)
   516  		return overflow || (!overflow && c == a+b)
   517  	}
   518  	if err := quick.Check(f, nil); err != nil {
   519  		t.Error(err)
   520  	}
   521  }
   522  
   523  func TestSafeAddClip(t *testing.T) {
   524  	assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, 10))
   525  	assert.EqualValues(t, math.MaxInt64, safeAddClip(math.MaxInt64, math.MaxInt64))
   526  	assert.EqualValues(t, math.MinInt64, safeAddClip(math.MinInt64, -10))
   527  }
   528  
   529  func TestSafeSubClip(t *testing.T) {
   530  	assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, 10))
   531  	assert.EqualValues(t, 0, safeSubClip(math.MinInt64, math.MinInt64))
   532  	assert.EqualValues(t, math.MinInt64, safeSubClip(math.MinInt64, math.MaxInt64))
   533  	assert.EqualValues(t, math.MaxInt64, safeSubClip(math.MaxInt64, -10))
   534  }
   535  
   536  //-------------------------------------------------------------------
   537  
   538  func TestValidatorSetVerifyCommit(t *testing.T) {
   539  	privKey := ed25519.GenPrivKey()
   540  	pubKey := privKey.PubKey()
   541  	v1 := NewValidator(pubKey, 1000)
   542  	vset := NewValidatorSet([]*Validator{v1})
   543  
   544  	chainID := "mychainID"
   545  	blockID := BlockID{Hash: []byte("hello")}
   546  	height := int64(5)
   547  	vote := &Vote{
   548  		ValidatorAddress: v1.Address,
   549  		ValidatorIndex:   0,
   550  		Height:           height,
   551  		Round:            0,
   552  		Timestamp:        tmtime.Now(),
   553  		Type:             PrecommitType,
   554  		BlockID:          blockID,
   555  	}
   556  	sig, err := privKey.Sign(vote.SignBytes(chainID))
   557  	assert.NoError(t, err)
   558  	vote.Signature = sig
   559  	commit := NewCommit(blockID, []*CommitSig{vote.CommitSig()})
   560  
   561  	badChainID := "notmychainID"
   562  	badBlockID := BlockID{Hash: []byte("goodbye")}
   563  	badHeight := height + 1
   564  	badCommit := NewCommit(blockID, []*CommitSig{nil})
   565  
   566  	// test some error cases
   567  	// TODO: test more cases!
   568  	cases := []struct {
   569  		chainID string
   570  		blockID BlockID
   571  		height  int64
   572  		commit  *Commit
   573  	}{
   574  		{badChainID, blockID, height, commit},
   575  		{chainID, badBlockID, height, commit},
   576  		{chainID, blockID, badHeight, commit},
   577  		{chainID, blockID, height, badCommit},
   578  	}
   579  
   580  	for i, c := range cases {
   581  		err := vset.VerifyCommit(c.chainID, c.blockID, c.height, c.commit)
   582  		assert.NotNil(t, err, i)
   583  	}
   584  
   585  	// test a good one
   586  	err = vset.VerifyCommit(chainID, blockID, height, commit)
   587  	assert.Nil(t, err)
   588  }
   589  
   590  func TestEmptySet(t *testing.T) {
   591  
   592  	var valList []*Validator
   593  	valSet := NewValidatorSet(valList)
   594  	assert.Panics(t, func() { valSet.IncrementProposerPriority(1) })
   595  	assert.Panics(t, func() { valSet.RescalePriorities(100) })
   596  	assert.Panics(t, func() { valSet.shiftByAvgProposerPriority() })
   597  	assert.Panics(t, func() { assert.Zero(t, computeMaxMinPriorityDiff(valSet)) })
   598  	valSet.GetProposer()
   599  
   600  	// Add to empty set
   601  	v1 := newValidator([]byte("v1"), 100)
   602  	v2 := newValidator([]byte("v2"), 100)
   603  	valList = []*Validator{v1, v2}
   604  	assert.NoError(t, valSet.UpdateWithChangeSet(valList))
   605  	verifyValidatorSet(t, valSet)
   606  
   607  	// Delete all validators from set
   608  	v1 = newValidator([]byte("v1"), 0)
   609  	v2 = newValidator([]byte("v2"), 0)
   610  	delList := []*Validator{v1, v2}
   611  	assert.Error(t, valSet.UpdateWithChangeSet(delList))
   612  
   613  	// Attempt delete from empty set
   614  	assert.Error(t, valSet.UpdateWithChangeSet(delList))
   615  
   616  }
   617  
   618  func TestUpdatesForNewValidatorSet(t *testing.T) {
   619  
   620  	v1 := newValidator([]byte("v1"), 100)
   621  	v2 := newValidator([]byte("v2"), 100)
   622  	valList := []*Validator{v1, v2}
   623  	valSet := NewValidatorSet(valList)
   624  	verifyValidatorSet(t, valSet)
   625  
   626  	// Verify duplicates are caught in NewValidatorSet() and it panics
   627  	v111 := newValidator([]byte("v1"), 100)
   628  	v112 := newValidator([]byte("v1"), 123)
   629  	v113 := newValidator([]byte("v1"), 234)
   630  	valList = []*Validator{v111, v112, v113}
   631  	assert.Panics(t, func() { NewValidatorSet(valList) })
   632  
   633  	// Verify set including validator with voting power 0 cannot be created
   634  	v1 = newValidator([]byte("v1"), 0)
   635  	v2 = newValidator([]byte("v2"), 22)
   636  	v3 := newValidator([]byte("v3"), 33)
   637  	valList = []*Validator{v1, v2, v3}
   638  	assert.Panics(t, func() { NewValidatorSet(valList) })
   639  
   640  	// Verify set including validator with negative voting power cannot be created
   641  	v1 = newValidator([]byte("v1"), 10)
   642  	v2 = newValidator([]byte("v2"), -20)
   643  	v3 = newValidator([]byte("v3"), 30)
   644  	valList = []*Validator{v1, v2, v3}
   645  	assert.Panics(t, func() { NewValidatorSet(valList) })
   646  
   647  }
   648  
   649  type testVal struct {
   650  	name  string
   651  	power int64
   652  }
   653  
   654  func permutation(valList []testVal) []testVal {
   655  	if len(valList) == 0 {
   656  		return nil
   657  	}
   658  	permList := make([]testVal, len(valList))
   659  	perm := cmn.RandPerm(len(valList))
   660  	for i, v := range perm {
   661  		permList[v] = valList[i]
   662  	}
   663  	return permList
   664  }
   665  
   666  func createNewValidatorList(testValList []testVal) []*Validator {
   667  	valList := make([]*Validator, 0, len(testValList))
   668  	for _, val := range testValList {
   669  		valList = append(valList, newValidator([]byte(val.name), val.power))
   670  	}
   671  	return valList
   672  }
   673  
   674  func createNewValidatorSet(testValList []testVal) *ValidatorSet {
   675  	return NewValidatorSet(createNewValidatorList(testValList))
   676  }
   677  
   678  func valSetTotalProposerPriority(valSet *ValidatorSet) int64 {
   679  	sum := int64(0)
   680  	for _, val := range valSet.Validators {
   681  		// mind overflow
   682  		sum = safeAddClip(sum, val.ProposerPriority)
   683  	}
   684  	return sum
   685  }
   686  
   687  func verifyValidatorSet(t *testing.T, valSet *ValidatorSet) {
   688  	// verify that the capacity and length of validators is the same
   689  	assert.Equal(t, len(valSet.Validators), cap(valSet.Validators))
   690  
   691  	// verify that the set's total voting power has been updated
   692  	tvp := valSet.totalVotingPower
   693  	valSet.updateTotalVotingPower()
   694  	expectedTvp := valSet.TotalVotingPower()
   695  	assert.Equal(t, expectedTvp, tvp,
   696  		"expected TVP %d. Got %d, valSet=%s", expectedTvp, tvp, valSet)
   697  
   698  	// verify that validator priorities are centered
   699  	valsCount := int64(len(valSet.Validators))
   700  	tpp := valSetTotalProposerPriority(valSet)
   701  	assert.True(t, tpp < valsCount && tpp > -valsCount,
   702  		"expected total priority in (-%d, %d). Got %d", valsCount, valsCount, tpp)
   703  
   704  	// verify that priorities are scaled
   705  	dist := computeMaxMinPriorityDiff(valSet)
   706  	assert.True(t, dist <= PriorityWindowSizeFactor*tvp,
   707  		"expected priority distance < %d. Got %d", PriorityWindowSizeFactor*tvp, dist)
   708  }
   709  
   710  func toTestValList(valList []*Validator) []testVal {
   711  	testList := make([]testVal, len(valList))
   712  	for i, val := range valList {
   713  		testList[i].name = string(val.Address)
   714  		testList[i].power = val.VotingPower
   715  	}
   716  	return testList
   717  }
   718  
   719  func testValSet(nVals int, power int64) []testVal {
   720  	vals := make([]testVal, nVals)
   721  	for i := 0; i < nVals; i++ {
   722  		vals[i] = testVal{fmt.Sprintf("v%d", i+1), power}
   723  	}
   724  	return vals
   725  }
   726  
   727  type valSetErrTestCase struct {
   728  	startVals  []testVal
   729  	updateVals []testVal
   730  }
   731  
   732  func executeValSetErrTestCase(t *testing.T, idx int, tt valSetErrTestCase) {
   733  	// create a new set and apply updates, keeping copies for the checks
   734  	valSet := createNewValidatorSet(tt.startVals)
   735  	valSetCopy := valSet.Copy()
   736  	valList := createNewValidatorList(tt.updateVals)
   737  	valListCopy := validatorListCopy(valList)
   738  	err := valSet.UpdateWithChangeSet(valList)
   739  
   740  	// for errors check the validator set has not been changed
   741  	assert.Error(t, err, "test %d", idx)
   742  	assert.Equal(t, valSet, valSetCopy, "test %v", idx)
   743  
   744  	// check the parameter list has not changed
   745  	assert.Equal(t, valList, valListCopy, "test %v", idx)
   746  }
   747  
   748  func TestValSetUpdatesDuplicateEntries(t *testing.T) {
   749  	testCases := []valSetErrTestCase{
   750  		// Duplicate entries in changes
   751  		{ // first entry is duplicated change
   752  			testValSet(2, 10),
   753  			[]testVal{{"v1", 11}, {"v1", 22}},
   754  		},
   755  		{ // second entry is duplicated change
   756  			testValSet(2, 10),
   757  			[]testVal{{"v2", 11}, {"v2", 22}},
   758  		},
   759  		{ // change duplicates are separated by a valid change
   760  			testValSet(2, 10),
   761  			[]testVal{{"v1", 11}, {"v2", 22}, {"v1", 12}},
   762  		},
   763  		{ // change duplicates are separated by a valid change
   764  			testValSet(3, 10),
   765  			[]testVal{{"v1", 11}, {"v3", 22}, {"v1", 12}},
   766  		},
   767  
   768  		// Duplicate entries in remove
   769  		{ // first entry is duplicated remove
   770  			testValSet(2, 10),
   771  			[]testVal{{"v1", 0}, {"v1", 0}},
   772  		},
   773  		{ // second entry is duplicated remove
   774  			testValSet(2, 10),
   775  			[]testVal{{"v2", 0}, {"v2", 0}},
   776  		},
   777  		{ // remove duplicates are separated by a valid remove
   778  			testValSet(2, 10),
   779  			[]testVal{{"v1", 0}, {"v2", 0}, {"v1", 0}},
   780  		},
   781  		{ // remove duplicates are separated by a valid remove
   782  			testValSet(3, 10),
   783  			[]testVal{{"v1", 0}, {"v3", 0}, {"v1", 0}},
   784  		},
   785  
   786  		{ // remove and update same val
   787  			testValSet(2, 10),
   788  			[]testVal{{"v1", 0}, {"v2", 20}, {"v1", 30}},
   789  		},
   790  		{ // duplicate entries in removes + changes
   791  			testValSet(2, 10),
   792  			[]testVal{{"v1", 0}, {"v2", 20}, {"v2", 30}, {"v1", 0}},
   793  		},
   794  		{ // duplicate entries in removes + changes
   795  			testValSet(3, 10),
   796  			[]testVal{{"v1", 0}, {"v3", 5}, {"v2", 20}, {"v2", 30}, {"v1", 0}},
   797  		},
   798  	}
   799  
   800  	for i, tt := range testCases {
   801  		executeValSetErrTestCase(t, i, tt)
   802  	}
   803  }
   804  
   805  func TestValSetUpdatesOverflows(t *testing.T) {
   806  	maxVP := MaxTotalVotingPower
   807  	testCases := []valSetErrTestCase{
   808  		{ // single update leading to overflow
   809  			testValSet(2, 10),
   810  			[]testVal{{"v1", math.MaxInt64}},
   811  		},
   812  		{ // single update leading to overflow
   813  			testValSet(2, 10),
   814  			[]testVal{{"v2", math.MaxInt64}},
   815  		},
   816  		{ // add validator leading to overflow
   817  			testValSet(1, maxVP),
   818  			[]testVal{{"v2", math.MaxInt64}},
   819  		},
   820  		{ // add validator leading to exceed Max
   821  			testValSet(1, maxVP-1),
   822  			[]testVal{{"v2", 5}},
   823  		},
   824  		{ // add validator leading to exceed Max
   825  			testValSet(2, maxVP/3),
   826  			[]testVal{{"v3", maxVP / 2}},
   827  		},
   828  		{ // add validator leading to exceed Max
   829  			testValSet(1, maxVP),
   830  			[]testVal{{"v2", maxVP}},
   831  		},
   832  	}
   833  
   834  	for i, tt := range testCases {
   835  		executeValSetErrTestCase(t, i, tt)
   836  	}
   837  }
   838  
   839  func TestValSetUpdatesOtherErrors(t *testing.T) {
   840  	testCases := []valSetErrTestCase{
   841  		{ // update with negative voting power
   842  			testValSet(2, 10),
   843  			[]testVal{{"v1", -123}},
   844  		},
   845  		{ // update with negative voting power
   846  			testValSet(2, 10),
   847  			[]testVal{{"v2", -123}},
   848  		},
   849  		{ // remove non-existing validator
   850  			testValSet(2, 10),
   851  			[]testVal{{"v3", 0}},
   852  		},
   853  		{ // delete all validators
   854  			[]testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}},
   855  			[]testVal{{"v1", 0}, {"v2", 0}, {"v3", 0}},
   856  		},
   857  	}
   858  
   859  	for i, tt := range testCases {
   860  		executeValSetErrTestCase(t, i, tt)
   861  	}
   862  }
   863  
   864  func TestValSetUpdatesBasicTestsExecute(t *testing.T) {
   865  	valSetUpdatesBasicTests := []struct {
   866  		startVals    []testVal
   867  		updateVals   []testVal
   868  		expectedVals []testVal
   869  	}{
   870  		{ // no changes
   871  			testValSet(2, 10),
   872  			[]testVal{},
   873  			testValSet(2, 10),
   874  		},
   875  		{ // voting power changes
   876  			testValSet(2, 10),
   877  			[]testVal{{"v1", 11}, {"v2", 22}},
   878  			[]testVal{{"v1", 11}, {"v2", 22}},
   879  		},
   880  		{ // add new validators
   881  			[]testVal{{"v1", 10}, {"v2", 20}},
   882  			[]testVal{{"v3", 30}, {"v4", 40}},
   883  			[]testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}},
   884  		},
   885  		{ // add new validator to middle
   886  			[]testVal{{"v1", 10}, {"v3", 20}},
   887  			[]testVal{{"v2", 30}},
   888  			[]testVal{{"v1", 10}, {"v2", 30}, {"v3", 20}},
   889  		},
   890  		{ // add new validator to beginning
   891  			[]testVal{{"v2", 10}, {"v3", 20}},
   892  			[]testVal{{"v1", 30}},
   893  			[]testVal{{"v1", 30}, {"v2", 10}, {"v3", 20}},
   894  		},
   895  		{ // delete validators
   896  			[]testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}},
   897  			[]testVal{{"v2", 0}},
   898  			[]testVal{{"v1", 10}, {"v3", 30}},
   899  		},
   900  	}
   901  
   902  	for i, tt := range valSetUpdatesBasicTests {
   903  		// create a new set and apply updates, keeping copies for the checks
   904  		valSet := createNewValidatorSet(tt.startVals)
   905  		valList := createNewValidatorList(tt.updateVals)
   906  		err := valSet.UpdateWithChangeSet(valList)
   907  		assert.NoError(t, err, "test %d", i)
   908  
   909  		valListCopy := validatorListCopy(valSet.Validators)
   910  		// check that the voting power in the set's validators is not changing if the voting power
   911  		// is changed in the list of validators previously passed as parameter to UpdateWithChangeSet.
   912  		// this is to make sure copies of the validators are made by UpdateWithChangeSet.
   913  		if len(valList) > 0 {
   914  			valList[0].VotingPower++
   915  			assert.Equal(t, toTestValList(valListCopy), toTestValList(valSet.Validators), "test %v", i)
   916  
   917  		}
   918  
   919  		// check the final validator list is as expected and the set is properly scaled and centered.
   920  		assert.Equal(t, tt.expectedVals, toTestValList(valSet.Validators), "test %v", i)
   921  		verifyValidatorSet(t, valSet)
   922  	}
   923  }
   924  
   925  // Test that different permutations of an update give the same result.
   926  func TestValSetUpdatesOrderIndependenceTestsExecute(t *testing.T) {
   927  	// startVals - initial validators to create the set with
   928  	// updateVals - a sequence of updates to be applied to the set.
   929  	// updateVals is shuffled a number of times during testing to check for same resulting validator set.
   930  	valSetUpdatesOrderTests := []struct {
   931  		startVals  []testVal
   932  		updateVals []testVal
   933  	}{
   934  		0: { // order of changes should not matter, the final validator sets should be the same
   935  			[]testVal{{"v1", 10}, {"v2", 10}, {"v3", 30}, {"v4", 40}},
   936  			[]testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}},
   937  
   938  		1: { // order of additions should not matter
   939  			[]testVal{{"v1", 10}, {"v2", 20}},
   940  			[]testVal{{"v3", 30}, {"v4", 40}, {"v5", 50}, {"v6", 60}}},
   941  
   942  		2: { // order of removals should not matter
   943  			[]testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}},
   944  			[]testVal{{"v1", 0}, {"v3", 0}, {"v4", 0}}},
   945  
   946  		3: { // order of mixed operations should not matter
   947  			[]testVal{{"v1", 10}, {"v2", 20}, {"v3", 30}, {"v4", 40}},
   948  			[]testVal{{"v1", 0}, {"v3", 0}, {"v2", 22}, {"v5", 50}, {"v4", 44}}},
   949  	}
   950  
   951  	for i, tt := range valSetUpdatesOrderTests {
   952  		// create a new set and apply updates
   953  		valSet := createNewValidatorSet(tt.startVals)
   954  		valSetCopy := valSet.Copy()
   955  		valList := createNewValidatorList(tt.updateVals)
   956  		assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList))
   957  
   958  		// save the result as expected for next updates
   959  		valSetExp := valSetCopy.Copy()
   960  
   961  		// perform at most 20 permutations on the updates and call UpdateWithChangeSet()
   962  		n := len(tt.updateVals)
   963  		maxNumPerms := cmn.MinInt(20, n*n)
   964  		for j := 0; j < maxNumPerms; j++ {
   965  			// create a copy of original set and apply a random permutation of updates
   966  			valSetCopy := valSet.Copy()
   967  			valList := createNewValidatorList(permutation(tt.updateVals))
   968  
   969  			// check there was no error and the set is properly scaled and centered.
   970  			assert.NoError(t, valSetCopy.UpdateWithChangeSet(valList),
   971  				"test %v failed for permutation %v", i, valList)
   972  			verifyValidatorSet(t, valSetCopy)
   973  
   974  			// verify the resulting test is same as the expected
   975  			assert.Equal(t, valSetCopy, valSetExp,
   976  				"test %v failed for permutation %v", i, valList)
   977  		}
   978  	}
   979  }
   980  
   981  // This tests the private function validator_set.go:applyUpdates() function, used only for additions and changes.
   982  // Should perform a proper merge of updatedVals and startVals
   983  func TestValSetApplyUpdatesTestsExecute(t *testing.T) {
   984  	valSetUpdatesBasicTests := []struct {
   985  		startVals    []testVal
   986  		updateVals   []testVal
   987  		expectedVals []testVal
   988  	}{
   989  		// additions
   990  		0: { // prepend
   991  			[]testVal{{"v4", 44}, {"v5", 55}},
   992  			[]testVal{{"v1", 11}},
   993  			[]testVal{{"v1", 11}, {"v4", 44}, {"v5", 55}}},
   994  		1: { // append
   995  			[]testVal{{"v4", 44}, {"v5", 55}},
   996  			[]testVal{{"v6", 66}},
   997  			[]testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}},
   998  		2: { // insert
   999  			[]testVal{{"v4", 44}, {"v6", 66}},
  1000  			[]testVal{{"v5", 55}},
  1001  			[]testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}}},
  1002  		3: { // insert multi
  1003  			[]testVal{{"v4", 44}, {"v6", 66}, {"v9", 99}},
  1004  			[]testVal{{"v5", 55}, {"v7", 77}, {"v8", 88}},
  1005  			[]testVal{{"v4", 44}, {"v5", 55}, {"v6", 66}, {"v7", 77}, {"v8", 88}, {"v9", 99}}},
  1006  		// changes
  1007  		4: { // head
  1008  			[]testVal{{"v1", 111}, {"v2", 22}},
  1009  			[]testVal{{"v1", 11}},
  1010  			[]testVal{{"v1", 11}, {"v2", 22}}},
  1011  		5: { // tail
  1012  			[]testVal{{"v1", 11}, {"v2", 222}},
  1013  			[]testVal{{"v2", 22}},
  1014  			[]testVal{{"v1", 11}, {"v2", 22}}},
  1015  		6: { // middle
  1016  			[]testVal{{"v1", 11}, {"v2", 222}, {"v3", 33}},
  1017  			[]testVal{{"v2", 22}},
  1018  			[]testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}},
  1019  		7: { // multi
  1020  			[]testVal{{"v1", 111}, {"v2", 222}, {"v3", 333}},
  1021  			[]testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}},
  1022  			[]testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}}},
  1023  		// additions and changes
  1024  		8: {
  1025  			[]testVal{{"v1", 111}, {"v2", 22}},
  1026  			[]testVal{{"v1", 11}, {"v3", 33}, {"v4", 44}},
  1027  			[]testVal{{"v1", 11}, {"v2", 22}, {"v3", 33}, {"v4", 44}}},
  1028  	}
  1029  
  1030  	for i, tt := range valSetUpdatesBasicTests {
  1031  		// create a new validator set with the start values
  1032  		valSet := createNewValidatorSet(tt.startVals)
  1033  
  1034  		// applyUpdates() with the update values
  1035  		valList := createNewValidatorList(tt.updateVals)
  1036  		valSet.applyUpdates(valList)
  1037  
  1038  		// check the new list of validators for proper merge
  1039  		assert.Equal(t, toTestValList(valSet.Validators), tt.expectedVals, "test %v", i)
  1040  	}
  1041  }
  1042  
  1043  type testVSetCfg struct {
  1044  	startVals    []testVal
  1045  	deletedVals  []testVal
  1046  	updatedVals  []testVal
  1047  	addedVals    []testVal
  1048  	expectedVals []testVal
  1049  }
  1050  
  1051  func randTestVSetCfg(t *testing.T, nBase, nAddMax int) testVSetCfg {
  1052  	if nBase <= 0 || nAddMax < 0 {
  1053  		panic(fmt.Sprintf("bad parameters %v %v", nBase, nAddMax))
  1054  	}
  1055  
  1056  	const maxPower = 1000
  1057  	var nOld, nDel, nChanged, nAdd int
  1058  
  1059  	nOld = int(cmn.RandUint()%uint(nBase)) + 1
  1060  	if nBase-nOld > 0 {
  1061  		nDel = int(cmn.RandUint() % uint(nBase-nOld))
  1062  	}
  1063  	nChanged = nBase - nOld - nDel
  1064  
  1065  	if nAddMax > 0 {
  1066  		nAdd = cmn.RandInt()%nAddMax + 1
  1067  	}
  1068  
  1069  	cfg := testVSetCfg{}
  1070  
  1071  	cfg.startVals = make([]testVal, nBase)
  1072  	cfg.deletedVals = make([]testVal, nDel)
  1073  	cfg.addedVals = make([]testVal, nAdd)
  1074  	cfg.updatedVals = make([]testVal, nChanged)
  1075  	cfg.expectedVals = make([]testVal, nBase-nDel+nAdd)
  1076  
  1077  	for i := 0; i < nBase; i++ {
  1078  		cfg.startVals[i] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)}
  1079  		if i < nOld {
  1080  			cfg.expectedVals[i] = cfg.startVals[i]
  1081  		}
  1082  		if i >= nOld && i < nOld+nChanged {
  1083  			cfg.updatedVals[i-nOld] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)}
  1084  			cfg.expectedVals[i] = cfg.updatedVals[i-nOld]
  1085  		}
  1086  		if i >= nOld+nChanged {
  1087  			cfg.deletedVals[i-nOld-nChanged] = testVal{fmt.Sprintf("v%d", i), 0}
  1088  		}
  1089  	}
  1090  
  1091  	for i := nBase; i < nBase+nAdd; i++ {
  1092  		cfg.addedVals[i-nBase] = testVal{fmt.Sprintf("v%d", i), int64(cmn.RandUint()%maxPower + 1)}
  1093  		cfg.expectedVals[i-nDel] = cfg.addedVals[i-nBase]
  1094  	}
  1095  
  1096  	sort.Sort(testValsByAddress(cfg.startVals))
  1097  	sort.Sort(testValsByAddress(cfg.deletedVals))
  1098  	sort.Sort(testValsByAddress(cfg.updatedVals))
  1099  	sort.Sort(testValsByAddress(cfg.addedVals))
  1100  	sort.Sort(testValsByAddress(cfg.expectedVals))
  1101  
  1102  	return cfg
  1103  
  1104  }
  1105  
  1106  func applyChangesToValSet(t *testing.T, valSet *ValidatorSet, valsLists ...[]testVal) {
  1107  	changes := make([]testVal, 0)
  1108  	for _, valsList := range valsLists {
  1109  		changes = append(changes, valsList...)
  1110  	}
  1111  	valList := createNewValidatorList(changes)
  1112  	err := valSet.UpdateWithChangeSet(valList)
  1113  	assert.NoError(t, err)
  1114  }
  1115  
  1116  func TestValSetUpdatePriorityOrderTests(t *testing.T) {
  1117  	const nMaxElections = 5000
  1118  
  1119  	testCases := []testVSetCfg{
  1120  		0: { // remove high power validator, keep old equal lower power validators
  1121  			startVals:    []testVal{{"v1", 1}, {"v2", 1}, {"v3", 1000}},
  1122  			deletedVals:  []testVal{{"v3", 0}},
  1123  			updatedVals:  []testVal{},
  1124  			addedVals:    []testVal{},
  1125  			expectedVals: []testVal{{"v1", 1}, {"v2", 1}},
  1126  		},
  1127  		1: { // remove high power validator, keep old different power validators
  1128  			startVals:    []testVal{{"v1", 1}, {"v2", 10}, {"v3", 1000}},
  1129  			deletedVals:  []testVal{{"v3", 0}},
  1130  			updatedVals:  []testVal{},
  1131  			addedVals:    []testVal{},
  1132  			expectedVals: []testVal{{"v1", 1}, {"v2", 10}},
  1133  		},
  1134  		2: { // remove high power validator, add new low power validators, keep old lower power
  1135  			startVals:    []testVal{{"v1", 1}, {"v2", 2}, {"v3", 1000}},
  1136  			deletedVals:  []testVal{{"v3", 0}},
  1137  			updatedVals:  []testVal{{"v2", 1}},
  1138  			addedVals:    []testVal{{"v4", 40}, {"v5", 50}},
  1139  			expectedVals: []testVal{{"v1", 1}, {"v2", 1}, {"v4", 40}, {"v5", 50}},
  1140  		},
  1141  
  1142  		// generate a configuration with 100 validators,
  1143  		// randomly select validators for updates and deletes, and
  1144  		// generate 10 new validators to be added
  1145  		3: randTestVSetCfg(t, 100, 10),
  1146  
  1147  		4: randTestVSetCfg(t, 1000, 100),
  1148  
  1149  		5: randTestVSetCfg(t, 10, 100),
  1150  
  1151  		6: randTestVSetCfg(t, 100, 1000),
  1152  
  1153  		7: randTestVSetCfg(t, 1000, 1000),
  1154  
  1155  		8: randTestVSetCfg(t, 10000, 1000),
  1156  
  1157  		9: randTestVSetCfg(t, 1000, 10000),
  1158  	}
  1159  
  1160  	for _, cfg := range testCases {
  1161  
  1162  		// create a new validator set
  1163  		valSet := createNewValidatorSet(cfg.startVals)
  1164  		verifyValidatorSet(t, valSet)
  1165  
  1166  		// run election up to nMaxElections times, apply changes and verify that the priority order is correct
  1167  		verifyValSetUpdatePriorityOrder(t, valSet, cfg, nMaxElections)
  1168  	}
  1169  }
  1170  
  1171  func verifyValSetUpdatePriorityOrder(t *testing.T, valSet *ValidatorSet, cfg testVSetCfg, nMaxElections int) {
  1172  
  1173  	// Run election up to nMaxElections times, sort validators by priorities
  1174  	valSet.IncrementProposerPriority(cmn.RandInt()%nMaxElections + 1)
  1175  	origValsPriSorted := validatorListCopy(valSet.Validators)
  1176  	sort.Sort(validatorsByPriority(origValsPriSorted))
  1177  
  1178  	// apply the changes, get the updated validators, sort by priorities
  1179  	applyChangesToValSet(t, valSet, cfg.addedVals, cfg.updatedVals, cfg.deletedVals)
  1180  	updatedValsPriSorted := validatorListCopy(valSet.Validators)
  1181  	sort.Sort(validatorsByPriority(updatedValsPriSorted))
  1182  
  1183  	// basic checks
  1184  	assert.Equal(t, toTestValList(valSet.Validators), cfg.expectedVals)
  1185  	verifyValidatorSet(t, valSet)
  1186  
  1187  	// verify that the added validators have the smallest priority:
  1188  	//  - they should be at the beginning of valListNewPriority since it is sorted by priority
  1189  	if len(cfg.addedVals) > 0 {
  1190  		addedValsPriSlice := updatedValsPriSorted[:len(cfg.addedVals)]
  1191  		sort.Sort(ValidatorsByAddress(addedValsPriSlice))
  1192  		assert.Equal(t, cfg.addedVals, toTestValList(addedValsPriSlice))
  1193  
  1194  		//  - and should all have the same priority
  1195  		expectedPri := addedValsPriSlice[0].ProposerPriority
  1196  		for _, val := range addedValsPriSlice[1:] {
  1197  			assert.Equal(t, expectedPri, val.ProposerPriority)
  1198  		}
  1199  	}
  1200  }
  1201  
  1202  //---------------------
  1203  // Sort validators by priority and address
  1204  type validatorsByPriority []*Validator
  1205  
  1206  func (valz validatorsByPriority) Len() int {
  1207  	return len(valz)
  1208  }
  1209  
  1210  func (valz validatorsByPriority) Less(i, j int) bool {
  1211  	if valz[i].ProposerPriority < valz[j].ProposerPriority {
  1212  		return true
  1213  	}
  1214  	if valz[i].ProposerPriority > valz[j].ProposerPriority {
  1215  		return false
  1216  	}
  1217  	return bytes.Compare(valz[i].Address, valz[j].Address) < 0
  1218  }
  1219  
  1220  func (valz validatorsByPriority) Swap(i, j int) {
  1221  	it := valz[i]
  1222  	valz[i] = valz[j]
  1223  	valz[j] = it
  1224  }
  1225  
  1226  //-------------------------------------
  1227  // Sort testVal-s by address.
  1228  type testValsByAddress []testVal
  1229  
  1230  func (tvals testValsByAddress) Len() int {
  1231  	return len(tvals)
  1232  }
  1233  
  1234  func (tvals testValsByAddress) Less(i, j int) bool {
  1235  	return bytes.Compare([]byte(tvals[i].name), []byte(tvals[j].name)) == -1
  1236  }
  1237  
  1238  func (tvals testValsByAddress) Swap(i, j int) {
  1239  	it := tvals[i]
  1240  	tvals[i] = tvals[j]
  1241  	tvals[j] = it
  1242  }
  1243  
  1244  //-------------------------------------
  1245  // Benchmark tests
  1246  //
  1247  func BenchmarkUpdates(b *testing.B) {
  1248  	const (
  1249  		n = 100
  1250  		m = 2000
  1251  	)
  1252  	// Init with n validators
  1253  	vs := make([]*Validator, n)
  1254  	for j := 0; j < n; j++ {
  1255  		vs[j] = newValidator([]byte(fmt.Sprintf("v%d", j)), 100)
  1256  	}
  1257  	valSet := NewValidatorSet(vs)
  1258  	l := len(valSet.Validators)
  1259  
  1260  	// Make m new validators
  1261  	newValList := make([]*Validator, m)
  1262  	for j := 0; j < m; j++ {
  1263  		newValList[j] = newValidator([]byte(fmt.Sprintf("v%d", j+l)), 1000)
  1264  	}
  1265  	b.ResetTimer()
  1266  
  1267  	for i := 0; i < b.N; i++ {
  1268  		// Add m validators to valSetCopy
  1269  		valSetCopy := valSet.Copy()
  1270  		assert.NoError(b, valSetCopy.UpdateWithChangeSet(newValList))
  1271  	}
  1272  }