github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/module/signature/checksum_test.go (about)

     1  package signature_test
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  	"pgregory.net/rapid"
     9  
    10  	"github.com/onflow/flow-go/model/flow"
    11  	msig "github.com/onflow/flow-go/module/signature"
    12  	"github.com/onflow/flow-go/utils/unittest"
    13  )
    14  
    15  // Test that the CheckSumFromIdentities method is able to produce checksum for empty identity list,
    16  // and produce the correct checksum
    17  func TestCheckSum(t *testing.T) {
    18  	t.Run("no identity", func(t *testing.T) {
    19  		require.Equal(t, msig.CheckSumFromIdentities(nil), msig.CheckSumFromIdentities(nil))
    20  		require.Equal(t, msig.CheckSumFromIdentities([]flow.Identifier{}), msig.CheckSumFromIdentities([]flow.Identifier{}))
    21  		require.Equal(t, msig.CheckSumFromIdentities(nil), msig.CheckSumFromIdentities([]flow.Identifier{}))
    22  	})
    23  
    24  	t.Run("same identities, same checksum", func(t *testing.T) {
    25  		ids := unittest.IdentifierListFixture(3)
    26  		require.Equal(t, msig.CheckSumFromIdentities(ids), msig.CheckSumFromIdentities(ids))
    27  		require.Equal(t, msig.CheckSumFromIdentities(ids[1:]), msig.CheckSumFromIdentities(ids[1:]))
    28  		require.Equal(t, msig.CheckSumFromIdentities(ids[2:]), msig.CheckSumFromIdentities(ids[2:]))
    29  	})
    30  
    31  	t.Run("different identities, different checksum", func(t *testing.T) {
    32  		ids := unittest.IdentifierListFixture(4)
    33  		require.NotEqual(t, msig.CheckSumFromIdentities(ids), msig.CheckSumFromIdentities(ids[1:]))     // subset
    34  		require.NotEqual(t, msig.CheckSumFromIdentities(ids[1:]), msig.CheckSumFromIdentities(ids[:2])) // overlap
    35  		require.NotEqual(t, msig.CheckSumFromIdentities(ids[:2]), msig.CheckSumFromIdentities(ids[2:])) // no overlap
    36  	})
    37  
    38  	t.Run("checksum length always constant", func(t *testing.T) {
    39  		ids := unittest.IdentifierListFixture(4)
    40  		require.Len(t, msig.CheckSumFromIdentities(nil), msig.CheckSumLen)
    41  		require.Len(t, msig.CheckSumFromIdentities(ids), msig.CheckSumLen)
    42  		require.Len(t, msig.CheckSumFromIdentities(ids[1:]), msig.CheckSumLen)
    43  		require.Len(t, msig.CheckSumFromIdentities(ids[2:]), msig.CheckSumLen)
    44  		require.Len(t, msig.CheckSumFromIdentities(ids[3:]), msig.CheckSumLen)
    45  	})
    46  }
    47  
    48  // Test that if an encoder generates a checksum with a committee and added to some random data
    49  // using PrefixCheckSum method, then an decoder using the same committee to call CompareAndExtract
    50  // is able to extract the same data as the encoder.
    51  func TestPrefixCheckSum(t *testing.T) {
    52  	rapid.Check(t, func(t *rapid.T) {
    53  		committeeSize := rapid.IntRange(0, 300).Draw(t, "committeeSize")
    54  		committee := unittest.IdentifierListFixture(committeeSize)
    55  		data := rapid.Map(rapid.IntRange(0, 200), func(count int) []byte {
    56  			return unittest.RandomBytes(count)
    57  		}).Draw(t, "data")
    58  		extracted, err := msig.CompareAndExtract(committee, msig.PrefixCheckSum(committee, data))
    59  		require.NoError(t, err)
    60  		require.Equal(t, data, extracted)
    61  	})
    62  }
    63  
    64  // Test_InvalidCheckSum verifies correct handling of invalid checksums. We expect:
    65  //  1. `SplitCheckSum` returns the expected sentinel error `ErrInvalidChecksum` is the input is shorter than 4 bytes
    66  //  2. `CompareAndExtract` returns `ErrInvalidChecksum` is the checksum does not match
    67  func Test_InvalidCheckSum(t *testing.T) {
    68  	t.Run("checksum too short", func(t *testing.T) {
    69  		for i := 0; i < 4; i++ {
    70  			_, _, err := msig.SplitCheckSum(unittest.RandomBytes(i))
    71  			require.True(t, errors.Is(err, msig.ErrInvalidChecksum))
    72  		}
    73  	})
    74  
    75  	t.Run("mismatching checksum", func(t *testing.T) {
    76  		committee := unittest.IdentifierListFixture(20)
    77  		_, err := msig.CompareAndExtract(committee, unittest.RandomBytes(112))
    78  		require.True(t, errors.Is(err, msig.ErrInvalidChecksum))
    79  	})
    80  }