github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/consensus/approvals/aggregated_signatures_test.go (about)

     1  package approvals
     2  
     3  import (
     4  	"testing"
     5  
     6  	"github.com/stretchr/testify/require"
     7  
     8  	"github.com/onflow/flow-go/model/flow"
     9  	"github.com/onflow/flow-go/utils/unittest"
    10  )
    11  
    12  // TestAggregatedSignatures_NoChunks verifies that NewAggregatedSignatures
    13  // errors when initialized with 0 chunks. This is compatible with Flow's
    14  // architecture, because each block contains at least one chunk (the system chunk).
    15  func TestAggregatedSignatures_NoChunks(t *testing.T) {
    16  	_, err := NewAggregatedSignatures(0)
    17  	require.Error(t, err)
    18  }
    19  
    20  // TestAggregatedSignatures_PutSignature tests putting signature with different indexes
    21  func TestAggregatedSignatures_PutSignature(t *testing.T) {
    22  	// create NewAggregatedSignatures for block with chunk indices 0, 1, ... , 9
    23  	sigs, err := NewAggregatedSignatures(10)
    24  	require.NoError(t, err)
    25  	require.Empty(t, sigs.signatures)
    26  
    27  	// add signature for chunk with index 3
    28  	n, err := sigs.PutSignature(3, flow.AggregatedSignature{})
    29  	require.NoError(t, err)
    30  	require.Equal(t, uint64(1), n)
    31  	require.Len(t, sigs.signatures, 1)
    32  
    33  	// attempt to add signature for chunk with index 10 should error
    34  	n, err = sigs.PutSignature(sigs.numberOfChunks, flow.AggregatedSignature{})
    35  	require.Error(t, err)
    36  	require.Equal(t, uint64(1), n)
    37  }
    38  
    39  // TestAggregatedSignatures_Repeated_PutSignature tests that repeated calls to
    40  // PutSignature for the same chunk index are no-ops except for the first one.
    41  func TestAggregatedSignatures_Repeated_PutSignature(t *testing.T) {
    42  	// create NewAggregatedSignatures for block with chunk indices 0, 1, ... , 9
    43  	sigs, err := NewAggregatedSignatures(10)
    44  	require.NoError(t, err)
    45  	require.Empty(t, sigs.signatures)
    46  
    47  	// add signature for chunk with index 3
    48  	as1 := flow.AggregatedSignature{
    49  		VerifierSignatures: unittest.SignaturesFixture(22),
    50  		SignerIDs:          unittest.IdentifierListFixture(22),
    51  	}
    52  	n, err := sigs.PutSignature(3, as1)
    53  	require.NoError(t, err)
    54  	require.Equal(t, uint64(1), n)
    55  
    56  	// add _different_ sig for chunk index 3 (should be no-op)
    57  	as2 := flow.AggregatedSignature{
    58  		VerifierSignatures: unittest.SignaturesFixture(2),
    59  		SignerIDs:          unittest.IdentifierListFixture(2),
    60  	}
    61  	n, err = sigs.PutSignature(3, as2)
    62  	require.NoError(t, err)
    63  	require.Equal(t, uint64(1), n)
    64  
    65  	aggSigs := sigs.Collect()
    66  	for idx, s := range aggSigs {
    67  		if idx == 3 {
    68  			require.Equal(t, 22, s.CardinalitySignerSet())
    69  		} else {
    70  			require.Equal(t, 0, s.CardinalitySignerSet())
    71  		}
    72  	}
    73  }
    74  
    75  // TestAggregatedSignatures_Repeated_Signer tests that repeated calls to
    76  // PutSignature for the same chunk index are no-ops except for the first one.
    77  func TestAggregatedSignatures_Repeated_Signer(t *testing.T) {
    78  	// create NewAggregatedSignatures for block with chunk indices 0, 1, ... , 9
    79  	sigs, err := NewAggregatedSignatures(10)
    80  	require.NoError(t, err)
    81  	require.Empty(t, sigs.signatures)
    82  
    83  	// add signature for chunk with index 3
    84  	as1 := flow.AggregatedSignature{
    85  		VerifierSignatures: unittest.SignaturesFixture(22),
    86  		SignerIDs:          unittest.IdentifierListFixture(22),
    87  	}
    88  	n, err := sigs.PutSignature(3, as1)
    89  	require.NoError(t, err)
    90  	require.Equal(t, uint64(1), n)
    91  
    92  	// add _different_ sig for chunk index 3 (should be no-op)
    93  	as2 := flow.AggregatedSignature{
    94  		VerifierSignatures: unittest.SignaturesFixture(2),
    95  		SignerIDs:          unittest.IdentifierListFixture(2),
    96  	}
    97  	n, err = sigs.PutSignature(3, as2)
    98  	require.NoError(t, err)
    99  	require.Equal(t, uint64(1), n)
   100  
   101  	aggSigs := sigs.Collect()
   102  	for idx, s := range aggSigs {
   103  		if idx == 3 {
   104  			require.Equal(t, 22, s.CardinalitySignerSet())
   105  		} else {
   106  			require.Equal(t, 0, s.CardinalitySignerSet())
   107  		}
   108  	}
   109  }
   110  
   111  // TestAggregatedSignatures_PutSignature_Sequence tests PutSignature for a full sequence
   112  func TestAggregatedSignatures_PutSignature_Sequence(t *testing.T) {
   113  	chunks := uint64(10)
   114  	sigs, err := NewAggregatedSignatures(chunks)
   115  	require.NoError(t, err)
   116  
   117  	for index := uint64(0); index < chunks; index++ {
   118  		n, err := sigs.PutSignature(index, flow.AggregatedSignature{})
   119  		require.NoError(t, err)
   120  		require.Equal(t, n, index+1)
   121  	}
   122  }
   123  
   124  // TestAggregatedSignatures_Collect tests that collecting over full signatures and partial signatures behaves as expected
   125  func TestAggregatedSignatures_Collect(t *testing.T) {
   126  	chunks := uint64(10)
   127  	sigs, err := NewAggregatedSignatures(chunks)
   128  	require.NoError(t, err)
   129  	sig := flow.AggregatedSignature{}
   130  	_, err = sigs.PutSignature(5, sig)
   131  	require.NoError(t, err)
   132  
   133  	// collecting over signatures with missing chunks results in empty array
   134  	require.Len(t, sigs.Collect(), int(chunks))
   135  	for index := uint64(0); index < chunks; index++ {
   136  		_, err := sigs.PutSignature(index, sig)
   137  		require.NoError(t, err)
   138  		require.Len(t, sigs.Collect(), int(chunks))
   139  	}
   140  }
   141  
   142  // TestAggregatedSignatures_HasSignature tests that after putting a signature we can get it
   143  func TestAggregatedSignatures_HasSignature(t *testing.T) {
   144  	sigs, err := NewAggregatedSignatures(10)
   145  	require.NoError(t, err)
   146  	index := uint64(5)
   147  	_, err = sigs.PutSignature(index, flow.AggregatedSignature{})
   148  	require.NoError(t, err)
   149  	require.True(t, sigs.HasSignature(index))
   150  	require.False(t, sigs.HasSignature(0))
   151  }
   152  
   153  // TestAggregatedSignatures_ChunksWithoutAggregatedSignature tests that we can retrieve all chunks with missing signatures
   154  func TestAggregatedSignatures_ChunksWithoutAggregatedSignature(t *testing.T) {
   155  	numberOfChunks := uint64(10)
   156  	sigs, err := NewAggregatedSignatures(numberOfChunks)
   157  	require.NoError(t, err)
   158  	_, err = sigs.PutSignature(0, flow.AggregatedSignature{})
   159  	require.NoError(t, err)
   160  	chunks := sigs.ChunksWithoutAggregatedSignature()
   161  	require.Len(t, chunks, int(numberOfChunks)-1)
   162  
   163  	expectedChunks := make([]uint64, 0, numberOfChunks)
   164  	for i := uint64(1); i < numberOfChunks; i++ {
   165  		expectedChunks = append(expectedChunks, i)
   166  	}
   167  	require.ElementsMatch(t, expectedChunks, chunks)
   168  }