A very experimental PLC implementation which uses BFT consensus for decentralization
at main 140 lines 4.2 kB view raw
1package store_test 2 3import ( 4 "crypto/rand" 5 "testing" 6 "time" 7 8 "github.com/gbl08ma/stacktrace" 9 "github.com/stretchr/testify/require" 10 "tangled.org/gbl08ma.com/didplcbft/store" 11 "tangled.org/gbl08ma.com/didplcbft/testutil" 12) 13 14func TestValidatorReputation(t *testing.T) { 15 txFactory, _, _ := testutil.NewTestTxFactory(t) 16 17 tx, err := txFactory.ReadWorking(time.Now()).Upgrade() 18 require.NoError(t, err) 19 20 err = store.Consensus.ChangeAllNonZeroValidatorReputations(tx, func(validatorAddress []byte, reputation uint64) (uint64, error) { 21 return 0, stacktrace.NewError("should not be called once") 22 }) 23 require.NoError(t, err) 24 25 validators := make([][]byte, 10) 26 for i := range validators { 27 validators[i] = make([]byte, store.PublicKeyLength) 28 rand.Read(validators[i]) 29 } 30 31 for range 3 { 32 for i := range validators { 33 err = store.Consensus.ChangeValidatorReputation(tx, validators[i], func(reputation uint64) (uint64, error) { 34 return reputation + uint64(i)*10, nil 35 }) 36 require.NoError(t, err) 37 } 38 } 39 40 for i := range validators { 41 rep, err := store.Consensus.ValidatorReputation(tx.Downgrade(), validators[i]) 42 require.NoError(t, err) 43 require.Equal(t, uint64(3*10*i), rep) 44 } 45 46 err = store.Consensus.ChangeAllNonZeroValidatorReputations(tx, func(validatorAddress []byte, reputation uint64) (uint64, error) { 47 require.Contains(t, validators, validatorAddress) 48 return reputation + 100, nil 49 }) 50 require.NoError(t, err) 51 52 err = store.Consensus.ChangeAllNonZeroValidatorReputations(tx, func(validatorAddress []byte, reputation uint64) (uint64, error) { 53 return 0, stacktrace.NewError("should propagate error") 54 }) 55 require.Error(t, err) 56 57 for i := range validators { 58 rep, err := store.Consensus.ValidatorReputation(tx.Downgrade(), validators[i]) 59 require.NoError(t, err) 60 if i == 0 { 61 // validators[0] did not have a NonZero reputation, so we don't expect it to change 62 require.Zero(t, rep) 63 } else { 64 require.Equal(t, uint64(100+3*10*i), rep) 65 } 66 } 67 68 err = store.Consensus.ChangeAllNonZeroValidatorReputations(tx, func(validatorAddress []byte, reputation uint64) (uint64, error) { 69 require.Contains(t, validators, validatorAddress) 70 if reputation < 1000 { 71 return 0, nil 72 } 73 return reputation - 1000, nil 74 }) 75 require.NoError(t, err) 76 77 for i := range validators { 78 rep, err := store.Consensus.ValidatorReputation(tx.Downgrade(), validators[i]) 79 require.NoError(t, err) 80 require.Zero(t, rep) 81 } 82} 83 84func TestValidatorVotingActivity(t *testing.T) { 85 txFactory, _, _ := testutil.NewTestTxFactory(t) 86 87 tx, err := txFactory.ReadWorking(time.Now()).Upgrade() 88 require.NoError(t, err) 89 90 store.Consensus.ConfigureEpochSize(100) 91 92 validatorPubKey := make([]byte, store.PublicKeyLength) 93 rand.Read(validatorPubKey) 94 95 validatorAddress := make([]byte, store.AddressLength) 96 rand.Read(validatorAddress) 97 98 err = store.Consensus.InitializeValidatorVotingActivity(tx, validatorAddress, validatorPubKey, 100) 99 require.NoError(t, err) 100 101 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 100) 102 require.NoError(t, err) 103 104 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 101) 105 require.NoError(t, err) 106 107 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 123) 108 require.NoError(t, err) 109 110 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 199) 111 require.NoError(t, err) 112 113 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 321) 114 require.Error(t, err) 115 116 err = store.Consensus.InitializeValidatorVotingActivity(tx, validatorAddress, validatorPubKey, 300) 117 require.NoError(t, err) 118 119 err = store.Consensus.MarkValidatorVote(tx, validatorAddress, 321) 120 require.NoError(t, err) 121 122 for epoch := range []uint64{100, 200, 300} { 123 iterated := false 124 for v := range store.Consensus.ActiveValidatorsIterator(tx.Downgrade(), 100, &err) { 125 iterated = true 126 require.Equal(t, validatorAddress, v.Address) 127 require.Equal(t, validatorPubKey, v.PublicKey) 128 switch epoch { 129 case 100: 130 require.Equal(t, uint64(4), v.VoteCount) 131 case 200: 132 require.Zero(t, v.VoteCount) 133 case 300: 134 require.Equal(t, uint64(1), v.VoteCount) 135 } 136 } 137 require.True(t, iterated) 138 require.NoError(t, err) 139 } 140}