github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/state/protocol/badger/validity_test.go (about)

     1  package badger
     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/state/protocol"
    10  	"github.com/onflow/flow-go/state/protocol/mock"
    11  	"github.com/onflow/flow-go/utils/unittest"
    12  )
    13  
    14  var participants = unittest.IdentityListFixture(20, unittest.WithAllRoles())
    15  
    16  // TestEntityExpirySnapshotValidation tests that we perform correct sanity checks when
    17  // bootstrapping consensus nodes and access nodes we expect that we only bootstrap snapshots
    18  // with sufficient history.
    19  func TestEntityExpirySnapshotValidation(t *testing.T) {
    20  	t.Run("spork-root-snapshot", func(t *testing.T) {
    21  		rootSnapshot := unittest.RootSnapshotFixture(participants)
    22  		err := ValidRootSnapshotContainsEntityExpiryRange(rootSnapshot)
    23  		require.NoError(t, err)
    24  	})
    25  	t.Run("not-enough-history", func(t *testing.T) {
    26  		rootSnapshot := unittest.RootSnapshotFixture(participants)
    27  		rootSnapshot.Encodable().Head.Height += 10 // advance height to be not spork root snapshot
    28  		err := ValidRootSnapshotContainsEntityExpiryRange(rootSnapshot)
    29  		require.Error(t, err)
    30  	})
    31  	t.Run("enough-history-spork-just-started", func(t *testing.T) {
    32  		rootSnapshot := unittest.RootSnapshotFixture(participants)
    33  		// advance height to be not spork root snapshot, but still lower than transaction expiry
    34  		rootSnapshot.Encodable().Head.Height += flow.DefaultTransactionExpiry / 2
    35  		// add blocks to sealing segment
    36  		rootSnapshot.Encodable().SealingSegment.ExtraBlocks = unittest.BlockFixtures(int(flow.DefaultTransactionExpiry / 2))
    37  		err := ValidRootSnapshotContainsEntityExpiryRange(rootSnapshot)
    38  		require.NoError(t, err)
    39  	})
    40  	t.Run("enough-history-long-spork", func(t *testing.T) {
    41  		rootSnapshot := unittest.RootSnapshotFixture(participants)
    42  		// advance height to be not spork root snapshot
    43  		rootSnapshot.Encodable().Head.Height += flow.DefaultTransactionExpiry * 2
    44  		// add blocks to sealing segment
    45  		rootSnapshot.Encodable().SealingSegment.ExtraBlocks = unittest.BlockFixtures(int(flow.DefaultTransactionExpiry) - 1)
    46  		err := ValidRootSnapshotContainsEntityExpiryRange(rootSnapshot)
    47  		require.NoError(t, err)
    48  	})
    49  	t.Run("more-history-than-needed", func(t *testing.T) {
    50  		rootSnapshot := unittest.RootSnapshotFixture(participants)
    51  		// advance height to be not spork root snapshot
    52  		rootSnapshot.Encodable().Head.Height += flow.DefaultTransactionExpiry * 2
    53  		// add blocks to sealing segment
    54  		rootSnapshot.Encodable().SealingSegment.ExtraBlocks = unittest.BlockFixtures(flow.DefaultTransactionExpiry * 2)
    55  		err := ValidRootSnapshotContainsEntityExpiryRange(rootSnapshot)
    56  		require.NoError(t, err)
    57  	})
    58  }
    59  
    60  func TestValidateVersionBeacon(t *testing.T) {
    61  	t.Run("no version beacon is ok", func(t *testing.T) {
    62  		snap := new(mock.Snapshot)
    63  
    64  		snap.On("VersionBeacon").Return(nil, nil)
    65  
    66  		err := validateVersionBeacon(snap)
    67  		require.NoError(t, err)
    68  	})
    69  	t.Run("valid version beacon is ok", func(t *testing.T) {
    70  		snap := new(mock.Snapshot)
    71  		block := unittest.BlockFixture()
    72  		block.Header.Height = 100
    73  
    74  		vb := &flow.SealedVersionBeacon{
    75  			VersionBeacon: &flow.VersionBeacon{
    76  				VersionBoundaries: []flow.VersionBoundary{
    77  					{
    78  						BlockHeight: 1000,
    79  						Version:     "1.0.0",
    80  					},
    81  				},
    82  				Sequence: 50,
    83  			},
    84  			SealHeight: uint64(37),
    85  		}
    86  
    87  		snap.On("Head").Return(block.Header, nil)
    88  		snap.On("VersionBeacon").Return(vb, nil)
    89  
    90  		err := validateVersionBeacon(snap)
    91  		require.NoError(t, err)
    92  	})
    93  	t.Run("height must be below highest block", func(t *testing.T) {
    94  		snap := new(mock.Snapshot)
    95  		block := unittest.BlockFixture()
    96  		block.Header.Height = 12
    97  
    98  		vb := &flow.SealedVersionBeacon{
    99  			VersionBeacon: &flow.VersionBeacon{
   100  				VersionBoundaries: []flow.VersionBoundary{
   101  					{
   102  						BlockHeight: 1000,
   103  						Version:     "1.0.0",
   104  					},
   105  				},
   106  				Sequence: 50,
   107  			},
   108  			SealHeight: uint64(37),
   109  		}
   110  
   111  		snap.On("Head").Return(block.Header, nil)
   112  		snap.On("VersionBeacon").Return(vb, nil)
   113  
   114  		err := validateVersionBeacon(snap)
   115  		require.Error(t, err)
   116  		require.True(t, protocol.IsInvalidServiceEventError(err))
   117  	})
   118  	t.Run("version beacon must be valid", func(t *testing.T) {
   119  		snap := new(mock.Snapshot)
   120  		block := unittest.BlockFixture()
   121  		block.Header.Height = 12
   122  
   123  		vb := &flow.SealedVersionBeacon{
   124  			VersionBeacon: &flow.VersionBeacon{
   125  				VersionBoundaries: []flow.VersionBoundary{
   126  					{
   127  						BlockHeight: 0,
   128  						Version:     "asdf", // invalid semver - hence will be considered invalid
   129  					},
   130  				},
   131  				Sequence: 50,
   132  			},
   133  			SealHeight: uint64(1),
   134  		}
   135  
   136  		snap.On("Head").Return(block.Header, nil)
   137  		snap.On("VersionBeacon").Return(vb, nil)
   138  
   139  		err := validateVersionBeacon(snap)
   140  		require.Error(t, err)
   141  		require.True(t, protocol.IsInvalidServiceEventError(err))
   142  	})
   143  }