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 }