github.com/MetalBlockchain/metalgo@v1.11.9/snow/consensus/snowman/poll/early_term_no_traversal_test.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package poll 5 6 import ( 7 "testing" 8 9 "github.com/prometheus/client_golang/prometheus" 10 "github.com/stretchr/testify/require" 11 12 "github.com/MetalBlockchain/metalgo/utils/bag" 13 ) 14 15 func newEarlyTermNoTraversalTestFactory(require *require.Assertions, alpha int) Factory { 16 factory, err := NewEarlyTermNoTraversalFactory(alpha, alpha, prometheus.NewRegistry()) 17 require.NoError(err) 18 return factory 19 } 20 21 func TestEarlyTermNoTraversalResults(t *testing.T) { 22 require := require.New(t) 23 24 vdrs := bag.Of(vdr1) // k = 1 25 alpha := 1 26 27 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 28 poll := factory.New(vdrs) 29 30 poll.Vote(vdr1, blkID1) 31 require.True(poll.Finished()) 32 33 result := poll.Result() 34 list := result.List() 35 require.Len(list, 1) 36 require.Equal(blkID1, list[0]) 37 require.Equal(1, result.Count(blkID1)) 38 } 39 40 func TestEarlyTermNoTraversalString(t *testing.T) { 41 require := require.New(t) 42 43 vdrs := bag.Of(vdr1, vdr2) // k = 2 44 alpha := 2 45 46 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 47 poll := factory.New(vdrs) 48 49 poll.Vote(vdr1, blkID1) 50 51 expected := `waiting on Bag[ids.NodeID]: (Size = 1) 52 NodeID-BaMPFdqMUQ46BV8iRcwbVfsam55kMqcp: 1 53 received Bag[ids.ID]: (Size = 1) 54 SYXsAycDPUu4z2ZksJD5fh5nTDcH3vCFHnpcVye5XuJ2jArg: 1` 55 require.Equal(expected, poll.String()) 56 } 57 58 func TestEarlyTermNoTraversalDropsDuplicatedVotes(t *testing.T) { 59 require := require.New(t) 60 61 vdrs := bag.Of(vdr1, vdr2) // k = 2 62 alpha := 2 63 64 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 65 poll := factory.New(vdrs) 66 67 poll.Vote(vdr1, blkID1) 68 require.False(poll.Finished()) 69 70 poll.Vote(vdr1, blkID1) 71 require.False(poll.Finished()) 72 73 poll.Vote(vdr2, blkID1) 74 require.True(poll.Finished()) 75 } 76 77 // Tests case 2 78 func TestEarlyTermNoTraversalTerminatesEarlyWithoutAlphaPreference(t *testing.T) { 79 require := require.New(t) 80 81 vdrs := bag.Of(vdr1, vdr2, vdr3) // k = 3 82 alpha := 2 83 84 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 85 poll := factory.New(vdrs) 86 87 poll.Drop(vdr1) 88 require.False(poll.Finished()) 89 90 poll.Drop(vdr2) 91 require.True(poll.Finished()) 92 } 93 94 // Tests case 3 95 func TestEarlyTermNoTraversalTerminatesEarlyWithAlphaPreference(t *testing.T) { 96 require := require.New(t) 97 98 vdrs := bag.Of(vdr1, vdr2, vdr3, vdr4, vdr5) // k = 5 99 alphaPreference := 3 100 alphaConfidence := 5 101 102 factory, err := NewEarlyTermNoTraversalFactory(alphaPreference, alphaConfidence, prometheus.NewRegistry()) 103 require.NoError(err) 104 poll := factory.New(vdrs) 105 106 poll.Vote(vdr1, blkID1) 107 require.False(poll.Finished()) 108 109 poll.Vote(vdr2, blkID1) 110 require.False(poll.Finished()) 111 112 poll.Vote(vdr3, blkID1) 113 require.False(poll.Finished()) 114 115 poll.Drop(vdr4) 116 require.True(poll.Finished()) 117 } 118 119 // Tests case 4 120 func TestEarlyTermNoTraversalTerminatesEarlyWithAlphaConfidence(t *testing.T) { 121 require := require.New(t) 122 123 vdrs := bag.Of(vdr1, vdr2, vdr3, vdr4, vdr5) // k = 5 124 alphaPreference := 3 125 alphaConfidence := 3 126 127 factory, err := NewEarlyTermNoTraversalFactory(alphaPreference, alphaConfidence, prometheus.NewRegistry()) 128 require.NoError(err) 129 poll := factory.New(vdrs) 130 131 poll.Vote(vdr1, blkID1) 132 require.False(poll.Finished()) 133 134 poll.Vote(vdr2, blkID1) 135 require.False(poll.Finished()) 136 137 poll.Vote(vdr3, blkID1) 138 require.True(poll.Finished()) 139 } 140 141 // If validators 1-3 vote for blocks B, C, and D respectively, which all share 142 // the common ancestor A, then we cannot terminate early with alpha = k = 4. 143 // 144 // If the final vote is cast for any of A, B, C, or D, then A will have 145 // transitively received alpha = 4 votes 146 func TestEarlyTermNoTraversalForSharedAncestor(t *testing.T) { 147 require := require.New(t) 148 149 vdrs := bag.Of(vdr1, vdr2, vdr3, vdr4) // k = 4 150 alpha := 4 151 152 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 153 poll := factory.New(vdrs) 154 155 poll.Vote(vdr1, blkID2) 156 require.False(poll.Finished()) 157 158 poll.Vote(vdr2, blkID3) 159 require.False(poll.Finished()) 160 161 poll.Vote(vdr3, blkID4) 162 require.False(poll.Finished()) 163 164 poll.Vote(vdr4, blkID1) 165 require.True(poll.Finished()) 166 } 167 168 func TestEarlyTermNoTraversalWithWeightedResponses(t *testing.T) { 169 require := require.New(t) 170 171 vdrs := bag.Of(vdr1, vdr2, vdr2) // k = 3 172 alpha := 2 173 174 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 175 poll := factory.New(vdrs) 176 177 poll.Vote(vdr2, blkID1) 178 require.True(poll.Finished()) 179 180 result := poll.Result() 181 list := result.List() 182 require.Len(list, 1) 183 require.Equal(blkID1, list[0]) 184 require.Equal(2, result.Count(blkID1)) 185 } 186 187 func TestEarlyTermNoTraversalDropWithWeightedResponses(t *testing.T) { 188 require := require.New(t) 189 190 vdrs := bag.Of(vdr1, vdr2, vdr2) // k = 3 191 alpha := 2 192 193 factory := newEarlyTermNoTraversalTestFactory(require, alpha) 194 poll := factory.New(vdrs) 195 196 poll.Drop(vdr2) 197 require.True(poll.Finished()) 198 }