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  }