github.com/koko1123/flow-go-1@v0.29.6/state/protocol/badger/mutator_test.go (about)

     1  // (c) 2019 Dapper Labs - ALL RIGHTS RESERVED
     2  
     3  package badger_test
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"math/rand"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/dgraph-io/badger/v3"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/mock"
    16  	"github.com/stretchr/testify/require"
    17  
    18  	"github.com/koko1123/flow-go-1/engine"
    19  	"github.com/koko1123/flow-go-1/model/flow"
    20  	"github.com/koko1123/flow-go-1/model/flow/filter"
    21  	"github.com/koko1123/flow-go-1/model/flow/order"
    22  	"github.com/koko1123/flow-go-1/module/metrics"
    23  	mockmodule "github.com/koko1123/flow-go-1/module/mock"
    24  	"github.com/koko1123/flow-go-1/module/signature"
    25  	"github.com/koko1123/flow-go-1/module/trace"
    26  	st "github.com/koko1123/flow-go-1/state"
    27  	realprotocol "github.com/koko1123/flow-go-1/state/protocol"
    28  	protocol "github.com/koko1123/flow-go-1/state/protocol/badger"
    29  	"github.com/koko1123/flow-go-1/state/protocol/events"
    30  	"github.com/koko1123/flow-go-1/state/protocol/inmem"
    31  	mockprotocol "github.com/koko1123/flow-go-1/state/protocol/mock"
    32  	"github.com/koko1123/flow-go-1/state/protocol/util"
    33  	"github.com/koko1123/flow-go-1/storage"
    34  	stoerr "github.com/koko1123/flow-go-1/storage"
    35  	bstorage "github.com/koko1123/flow-go-1/storage/badger"
    36  	"github.com/koko1123/flow-go-1/storage/badger/operation"
    37  	storeutil "github.com/koko1123/flow-go-1/storage/util"
    38  	"github.com/koko1123/flow-go-1/utils/unittest"
    39  	"github.com/onflow/flow-go/crypto"
    40  )
    41  
    42  func init() {
    43  	rand.Seed(time.Now().UnixNano())
    44  }
    45  
    46  var participants = unittest.IdentityListFixture(5, unittest.WithAllRoles())
    47  
    48  func TestBootstrapValid(t *testing.T) {
    49  	rootSnapshot := unittest.RootSnapshotFixture(participants)
    50  	util.RunWithBootstrapState(t, rootSnapshot, func(db *badger.DB, state *protocol.State) {
    51  		var finalized uint64
    52  		err := db.View(operation.RetrieveFinalizedHeight(&finalized))
    53  		require.NoError(t, err)
    54  
    55  		var sealed uint64
    56  		err = db.View(operation.RetrieveSealedHeight(&sealed))
    57  		require.NoError(t, err)
    58  
    59  		var genesisID flow.Identifier
    60  		err = db.View(operation.LookupBlockHeight(0, &genesisID))
    61  		require.NoError(t, err)
    62  
    63  		var header flow.Header
    64  		err = db.View(operation.RetrieveHeader(genesisID, &header))
    65  		require.NoError(t, err)
    66  
    67  		var sealID flow.Identifier
    68  		err = db.View(operation.LookupLatestSealAtBlock(genesisID, &sealID))
    69  		require.NoError(t, err)
    70  
    71  		_, seal, err := rootSnapshot.SealedResult()
    72  		require.NoError(t, err)
    73  		err = db.View(operation.RetrieveSeal(sealID, seal))
    74  		require.NoError(t, err)
    75  
    76  		block, err := rootSnapshot.Head()
    77  		require.NoError(t, err)
    78  		require.Equal(t, block.Height, finalized)
    79  		require.Equal(t, block.Height, sealed)
    80  		require.Equal(t, block.ID(), genesisID)
    81  		require.Equal(t, block.ID(), seal.BlockID)
    82  		require.Equal(t, block, &header)
    83  	})
    84  }
    85  
    86  func TestExtendValid(t *testing.T) {
    87  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
    88  		metrics := metrics.NewNoopCollector()
    89  		tracer := trace.NewNoopTracer()
    90  		headers, _, seals, index, payloads, blocks, setups, commits, statuses, results := storeutil.StorageLayer(t, db)
    91  
    92  		// create a event consumer to test epoch transition events
    93  		distributor := events.NewDistributor()
    94  		consumer := new(mockprotocol.Consumer)
    95  		distributor.AddConsumer(consumer)
    96  
    97  		block, result, seal := unittest.BootstrapFixture(participants)
    98  		qc := unittest.QuorumCertificateFixture(unittest.QCWithBlockID(block.ID()))
    99  		rootSnapshot, err := inmem.SnapshotFromBootstrapState(block, result, seal, qc)
   100  		require.NoError(t, err)
   101  
   102  		state, err := protocol.Bootstrap(metrics, db, headers, seals, results, blocks, setups, commits, statuses, rootSnapshot)
   103  		require.NoError(t, err)
   104  
   105  		fullState, err := protocol.NewFullConsensusState(state, index, payloads, tracer, consumer, util.MockBlockTimer(),
   106  			util.MockReceiptValidator(), util.MockSealValidator(seals))
   107  		require.NoError(t, err)
   108  
   109  		extend := unittest.BlockWithParentFixture(block.Header)
   110  		extend.Payload.Guarantees = nil
   111  		extend.Header.PayloadHash = extend.Payload.Hash()
   112  
   113  		err = fullState.Extend(context.Background(), extend)
   114  		require.NoError(t, err)
   115  
   116  		finalCommit, err := state.Final().Commit()
   117  		require.NoError(t, err)
   118  		require.Equal(t, seal.FinalState, finalCommit)
   119  
   120  		consumer.On("BlockFinalized", extend.Header).Once()
   121  		err = fullState.Finalize(context.Background(), extend.ID())
   122  		require.NoError(t, err)
   123  		consumer.AssertExpectations(t)
   124  	})
   125  }
   126  
   127  func TestSealedIndex(t *testing.T) {
   128  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   129  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   130  		rootHeader, err := rootSnapshot.Head()
   131  		require.NoError(t, err)
   132  
   133  		// build a chain:
   134  		// G <- B1 <- B2 (resultB1) <- B3 <- B4 (resultB2, resultB3) <- B5 (sealB1) <- B6 (sealB2, sealB3) <- B7
   135  		// test that when B4 is finalized, can only find seal for G
   136  		// 					 when B5 is finalized, can find seal for B1
   137  		//					 when B7 is finalized, can find seals for B2, B3
   138  
   139  		// block 1
   140  		b1 := unittest.BlockWithParentFixture(rootHeader)
   141  		b1.SetPayload(flow.EmptyPayload())
   142  		err = state.Extend(context.Background(), b1)
   143  		require.NoError(t, err)
   144  
   145  		// block 2(result B1)
   146  		b1Receipt := unittest.ReceiptForBlockFixture(b1)
   147  		b2 := unittest.BlockWithParentFixture(b1.Header)
   148  		b2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(b1Receipt)))
   149  		err = state.Extend(context.Background(), b2)
   150  		require.NoError(t, err)
   151  
   152  		// block 3
   153  		b3 := unittest.BlockWithParentFixture(b2.Header)
   154  		b3.SetPayload(flow.EmptyPayload())
   155  		err = state.Extend(context.Background(), b3)
   156  		require.NoError(t, err)
   157  
   158  		// block 4 (resultB2, resultB3)
   159  		b2Receipt := unittest.ReceiptForBlockFixture(b2)
   160  		b3Receipt := unittest.ReceiptForBlockFixture(b3)
   161  		b4 := unittest.BlockWithParentFixture(b3.Header)
   162  		b4.SetPayload(flow.Payload{
   163  			Receipts: []*flow.ExecutionReceiptMeta{b2Receipt.Meta(), b3Receipt.Meta()},
   164  			Results:  []*flow.ExecutionResult{&b2Receipt.ExecutionResult, &b3Receipt.ExecutionResult},
   165  		})
   166  		err = state.Extend(context.Background(), b4)
   167  		require.NoError(t, err)
   168  
   169  		// block 5 (sealB1)
   170  		b1Seal := unittest.Seal.Fixture(unittest.Seal.WithResult(&b1Receipt.ExecutionResult))
   171  		b5 := unittest.BlockWithParentFixture(b4.Header)
   172  		b5.SetPayload(flow.Payload{
   173  			Seals: []*flow.Seal{b1Seal},
   174  		})
   175  		err = state.Extend(context.Background(), b5)
   176  		require.NoError(t, err)
   177  
   178  		// block 6 (sealB2, sealB3)
   179  		b2Seal := unittest.Seal.Fixture(unittest.Seal.WithResult(&b2Receipt.ExecutionResult))
   180  		b3Seal := unittest.Seal.Fixture(unittest.Seal.WithResult(&b3Receipt.ExecutionResult))
   181  		b6 := unittest.BlockWithParentFixture(b5.Header)
   182  		b6.SetPayload(flow.Payload{
   183  			Seals: []*flow.Seal{b2Seal, b3Seal},
   184  		})
   185  		err = state.Extend(context.Background(), b6)
   186  		require.NoError(t, err)
   187  
   188  		// block 7
   189  		b7 := unittest.BlockWithParentFixture(b6.Header)
   190  		b7.SetPayload(flow.EmptyPayload())
   191  		err = state.Extend(context.Background(), b7)
   192  		require.NoError(t, err)
   193  
   194  		// finalizing b1 - b4
   195  		// when B4 is finalized, can only find seal for G
   196  		err = state.Finalize(context.Background(), b1.ID())
   197  		require.NoError(t, err)
   198  		err = state.Finalize(context.Background(), b2.ID())
   199  		require.NoError(t, err)
   200  		err = state.Finalize(context.Background(), b3.ID())
   201  		require.NoError(t, err)
   202  		err = state.Finalize(context.Background(), b4.ID())
   203  		require.NoError(t, err)
   204  
   205  		metrics := metrics.NewNoopCollector()
   206  		seals := bstorage.NewSeals(metrics, db)
   207  
   208  		// can only find seal for G
   209  		_, err = seals.FinalizedSealForBlock(rootHeader.ID())
   210  		require.NoError(t, err)
   211  
   212  		_, err = seals.FinalizedSealForBlock(b1.ID())
   213  		require.Error(t, err)
   214  		require.ErrorIs(t, err, storage.ErrNotFound)
   215  
   216  		// when B5 is finalized, can find seal for B1
   217  		err = state.Finalize(context.Background(), b5.ID())
   218  		require.NoError(t, err)
   219  
   220  		s1, err := seals.FinalizedSealForBlock(b1.ID())
   221  		require.NoError(t, err)
   222  		require.Equal(t, b1Seal, s1)
   223  
   224  		_, err = seals.FinalizedSealForBlock(b2.ID())
   225  		require.Error(t, err)
   226  		require.ErrorIs(t, err, storage.ErrNotFound)
   227  
   228  		// when B7 is finalized, can find seals for B2, B3
   229  		err = state.Finalize(context.Background(), b6.ID())
   230  		require.NoError(t, err)
   231  
   232  		err = state.Finalize(context.Background(), b7.ID())
   233  		require.NoError(t, err)
   234  
   235  		s2, err := seals.FinalizedSealForBlock(b2.ID())
   236  		require.NoError(t, err)
   237  		require.Equal(t, b2Seal, s2)
   238  
   239  		s3, err := seals.FinalizedSealForBlock(b3.ID())
   240  		require.NoError(t, err)
   241  		require.Equal(t, b3Seal, s3)
   242  	})
   243  
   244  }
   245  
   246  func TestExtendSealedBoundary(t *testing.T) {
   247  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   248  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   249  		head, err := rootSnapshot.Head()
   250  		require.NoError(t, err)
   251  		_, seal, err := rootSnapshot.SealedResult()
   252  		require.NoError(t, err)
   253  		finalCommit, err := state.Final().Commit()
   254  		require.NoError(t, err)
   255  		require.Equal(t, seal.FinalState, finalCommit, "original commit should be root commit")
   256  
   257  		// Create a first block on top of the snapshot
   258  		block1 := unittest.BlockWithParentFixture(head)
   259  		block1.SetPayload(flow.EmptyPayload())
   260  		err = state.Extend(context.Background(), block1)
   261  		require.NoError(t, err)
   262  
   263  		// Add a second block containing a receipt committing to the first block
   264  		block1Receipt := unittest.ReceiptForBlockFixture(block1)
   265  		block2 := unittest.BlockWithParentFixture(block1.Header)
   266  		block2.SetPayload(flow.Payload{
   267  			Receipts: []*flow.ExecutionReceiptMeta{block1Receipt.Meta()},
   268  			Results:  []*flow.ExecutionResult{&block1Receipt.ExecutionResult},
   269  		})
   270  		err = state.Extend(context.Background(), block2)
   271  		require.NoError(t, err)
   272  
   273  		// Add a third block containing a seal for the first block
   274  		block1Seal := unittest.Seal.Fixture(unittest.Seal.WithResult(&block1Receipt.ExecutionResult))
   275  		block3 := unittest.BlockWithParentFixture(block2.Header)
   276  		block3.SetPayload(flow.Payload{
   277  			Seals: []*flow.Seal{block1Seal},
   278  		})
   279  		err = state.Extend(context.Background(), block3)
   280  		require.NoError(t, err)
   281  
   282  		finalCommit, err = state.Final().Commit()
   283  		require.NoError(t, err)
   284  		require.Equal(t, seal.FinalState, finalCommit, "commit should not change before finalizing")
   285  
   286  		err = state.Finalize(context.Background(), block1.ID())
   287  		require.NoError(t, err)
   288  
   289  		finalCommit, err = state.Final().Commit()
   290  		require.NoError(t, err)
   291  		require.Equal(t, seal.FinalState, finalCommit, "commit should not change after finalizing non-sealing block")
   292  
   293  		err = state.Finalize(context.Background(), block2.ID())
   294  		require.NoError(t, err)
   295  
   296  		finalCommit, err = state.Final().Commit()
   297  		require.NoError(t, err)
   298  		require.Equal(t, seal.FinalState, finalCommit, "commit should not change after finalizing non-sealing block")
   299  
   300  		err = state.Finalize(context.Background(), block3.ID())
   301  		require.NoError(t, err)
   302  
   303  		finalCommit, err = state.Final().Commit()
   304  		require.NoError(t, err)
   305  		require.Equal(t, block1Seal.FinalState, finalCommit, "commit should change after finalizing sealing block")
   306  	})
   307  }
   308  
   309  func TestExtendMissingParent(t *testing.T) {
   310  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   311  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   312  		extend := unittest.BlockFixture()
   313  		extend.Payload.Guarantees = nil
   314  		extend.Payload.Seals = nil
   315  		extend.Header.Height = 2
   316  		extend.Header.View = 2
   317  		extend.Header.ParentID = unittest.BlockFixture().ID()
   318  		extend.Header.PayloadHash = extend.Payload.Hash()
   319  
   320  		err := state.Extend(context.Background(), &extend)
   321  		require.Error(t, err)
   322  		require.True(t, st.IsInvalidExtensionError(err), err)
   323  
   324  		// verify seal not indexed
   325  		var sealID flow.Identifier
   326  		err = db.View(operation.LookupLatestSealAtBlock(extend.ID(), &sealID))
   327  		require.Error(t, err)
   328  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
   329  	})
   330  }
   331  
   332  func TestExtendHeightTooSmall(t *testing.T) {
   333  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   334  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   335  		head, err := rootSnapshot.Head()
   336  		require.NoError(t, err)
   337  
   338  		extend := unittest.BlockFixture()
   339  		extend.SetPayload(flow.EmptyPayload())
   340  		extend.Header.Height = 1
   341  		extend.Header.View = 1
   342  		extend.Header.ParentID = head.ID()
   343  
   344  		err = state.Extend(context.Background(), &extend)
   345  		require.NoError(t, err)
   346  
   347  		// create another block with the same height and view, that is coming after
   348  		extend.Header.ParentID = extend.Header.ID()
   349  		extend.Header.Height = 1
   350  		extend.Header.View = 2
   351  
   352  		err = state.Extend(context.Background(), &extend)
   353  		require.Error(t, err)
   354  
   355  		// verify seal not indexed
   356  		var sealID flow.Identifier
   357  		err = db.View(operation.LookupLatestSealAtBlock(extend.ID(), &sealID))
   358  		require.Error(t, err)
   359  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
   360  	})
   361  }
   362  
   363  func TestExtendHeightTooLarge(t *testing.T) {
   364  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   365  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   366  
   367  		head, err := rootSnapshot.Head()
   368  		require.NoError(t, err)
   369  
   370  		block := unittest.BlockWithParentFixture(head)
   371  		block.SetPayload(flow.EmptyPayload())
   372  		// set an invalid height
   373  		block.Header.Height = head.Height + 2
   374  
   375  		err = state.Extend(context.Background(), block)
   376  		require.Error(t, err)
   377  	})
   378  }
   379  
   380  func TestExtendBlockNotConnected(t *testing.T) {
   381  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   382  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   383  
   384  		head, err := rootSnapshot.Head()
   385  		require.NoError(t, err)
   386  
   387  		// add 2 blocks, the second finalizing/sealing the state of the first
   388  		extend := unittest.BlockWithParentFixture(head)
   389  		extend.SetPayload(flow.EmptyPayload())
   390  
   391  		err = state.Extend(context.Background(), extend)
   392  		require.NoError(t, err)
   393  
   394  		err = state.Finalize(context.Background(), extend.ID())
   395  		require.NoError(t, err)
   396  
   397  		// create a fork at view/height 1 and try to connect it to root
   398  		extend.Header.Timestamp = extend.Header.Timestamp.Add(time.Second)
   399  		extend.Header.ParentID = head.ID()
   400  
   401  		err = state.Extend(context.Background(), extend)
   402  		require.Error(t, err)
   403  
   404  		// verify seal not indexed
   405  		var sealID flow.Identifier
   406  		err = db.View(operation.LookupLatestSealAtBlock(extend.ID(), &sealID))
   407  		require.Error(t, err)
   408  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
   409  	})
   410  }
   411  
   412  func TestExtendInvalidChainID(t *testing.T) {
   413  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   414  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   415  		head, err := rootSnapshot.Head()
   416  		require.NoError(t, err)
   417  
   418  		block := unittest.BlockWithParentFixture(head)
   419  		block.SetPayload(flow.EmptyPayload())
   420  		// use an invalid chain ID
   421  		block.Header.ChainID = head.ChainID + "-invalid"
   422  
   423  		err = state.Extend(context.Background(), block)
   424  		require.Error(t, err)
   425  		require.True(t, st.IsInvalidExtensionError(err), err)
   426  	})
   427  }
   428  
   429  func TestExtendReceiptsNotSorted(t *testing.T) {
   430  	// TODO: this test needs to be updated:
   431  	// We don't require the receipts to be sorted by height anymore
   432  	// We could require an "parent first" ordering, which is less strict than
   433  	// a full ordering by height
   434  	unittest.SkipUnless(t, unittest.TEST_TODO, "needs update")
   435  
   436  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   437  	head, err := rootSnapshot.Head()
   438  	require.NoError(t, err)
   439  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   440  		// create block2 and block3
   441  		block2 := unittest.BlockWithParentFixture(head)
   442  		block2.Payload.Guarantees = nil
   443  		block2.Header.PayloadHash = block2.Payload.Hash()
   444  		err := state.Extend(context.Background(), block2)
   445  		require.NoError(t, err)
   446  
   447  		block3 := unittest.BlockWithParentFixture(block2.Header)
   448  		block3.Payload.Guarantees = nil
   449  		block3.Header.PayloadHash = block3.Payload.Hash()
   450  		err = state.Extend(context.Background(), block3)
   451  		require.NoError(t, err)
   452  
   453  		receiptA := unittest.ReceiptForBlockFixture(block3)
   454  		receiptB := unittest.ReceiptForBlockFixture(block2)
   455  
   456  		// insert a block with payload receipts not sorted by block height.
   457  		block4 := unittest.BlockWithParentFixture(block3.Header)
   458  		block4.Payload = &flow.Payload{
   459  			Receipts: []*flow.ExecutionReceiptMeta{receiptA.Meta(), receiptB.Meta()},
   460  			Results:  []*flow.ExecutionResult{&receiptA.ExecutionResult, &receiptB.ExecutionResult},
   461  		}
   462  		block4.Header.PayloadHash = block4.Payload.Hash()
   463  		err = state.Extend(context.Background(), block4)
   464  		require.Error(t, err)
   465  		require.True(t, st.IsInvalidExtensionError(err), err)
   466  	})
   467  }
   468  
   469  func TestExtendReceiptsInvalid(t *testing.T) {
   470  	validator := &mockmodule.ReceiptValidator{}
   471  
   472  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   473  	util.RunWithFullProtocolStateAndValidator(t, rootSnapshot, validator, func(db *badger.DB, state *protocol.MutableState) {
   474  		head, err := rootSnapshot.Head()
   475  		require.NoError(t, err)
   476  
   477  		validator.On("ValidatePayload", mock.Anything).Return(nil).Once()
   478  
   479  		// create block2 and block3
   480  		block2 := unittest.BlockWithParentFixture(head)
   481  		block2.SetPayload(flow.EmptyPayload())
   482  		err = state.Extend(context.Background(), block2)
   483  		require.NoError(t, err)
   484  
   485  		// Add a receipt for block 2
   486  		receipt := unittest.ExecutionReceiptFixture()
   487  
   488  		block3 := unittest.BlockWithParentFixture(block2.Header)
   489  		block3.SetPayload(flow.Payload{
   490  			Receipts: []*flow.ExecutionReceiptMeta{receipt.Meta()},
   491  			Results:  []*flow.ExecutionResult{&receipt.ExecutionResult},
   492  		})
   493  
   494  		// force the receipt validator to refuse this payload
   495  		validator.On("ValidatePayload", block3).Return(engine.NewInvalidInputError("")).Once()
   496  
   497  		err = state.Extend(context.Background(), block3)
   498  		require.Error(t, err)
   499  		require.True(t, st.IsInvalidExtensionError(err), err)
   500  		validator.AssertExpectations(t)
   501  	})
   502  }
   503  
   504  func TestExtendReceiptsValid(t *testing.T) {
   505  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   506  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   507  		head, err := rootSnapshot.Head()
   508  		require.NoError(t, err)
   509  		block2 := unittest.BlockWithParentFixture(head)
   510  		block2.SetPayload(flow.EmptyPayload())
   511  		err = state.Extend(context.Background(), block2)
   512  		require.NoError(t, err)
   513  
   514  		block3 := unittest.BlockWithParentFixture(block2.Header)
   515  		block3.SetPayload(flow.EmptyPayload())
   516  		err = state.Extend(context.Background(), block3)
   517  		require.NoError(t, err)
   518  
   519  		block4 := unittest.BlockWithParentFixture(block3.Header)
   520  		block4.SetPayload(flow.EmptyPayload())
   521  		err = state.Extend(context.Background(), block4)
   522  		require.NoError(t, err)
   523  
   524  		receipt3a := unittest.ReceiptForBlockFixture(block3)
   525  		receipt3b := unittest.ReceiptForBlockFixture(block3)
   526  		receipt3c := unittest.ReceiptForBlockFixture(block4)
   527  
   528  		block5 := unittest.BlockWithParentFixture(block4.Header)
   529  		block5.SetPayload(flow.Payload{
   530  			Receipts: []*flow.ExecutionReceiptMeta{
   531  				receipt3a.Meta(),
   532  				receipt3b.Meta(),
   533  				receipt3c.Meta(),
   534  			},
   535  			Results: []*flow.ExecutionResult{
   536  				&receipt3a.ExecutionResult,
   537  				&receipt3b.ExecutionResult,
   538  				&receipt3c.ExecutionResult,
   539  			},
   540  		})
   541  		err = state.Extend(context.Background(), block5)
   542  		require.NoError(t, err)
   543  	})
   544  }
   545  
   546  // Tests the full flow of transitioning between epochs by finalizing a setup
   547  // event, then a commit event, then finalizing the first block of the next epoch.
   548  // Also tests that appropriate epoch transition events are fired.
   549  //
   550  // Epoch information becomes available in the protocol state in the block AFTER
   551  // the block sealing the relevant service event. This is because the block after
   552  // the sealing block contains a QC certifying validity of the payload of the
   553  // sealing block.
   554  //
   555  // ROOT <- B1 <- B2(R1) <- B3(S1) <- B4 <- B5(R2) <- B6(S2) <- B7 <- B8 <-|- B9
   556  //
   557  // B4 contains a QC for B3, which seals B1, in which EpochSetup is emitted.
   558  // * we can query the EpochSetup beginning with B4
   559  // * EpochSetupPhaseStarted triggered when B4 is finalized
   560  //
   561  // B7 contains a QC for B6, which seals B2, in which EpochCommitted is emitted.
   562  // * we can query the EpochCommit beginning with B7
   563  // * EpochSetupPhaseStarted triggered when B7 is finalized
   564  //
   565  // B8 is the final block of the epoch.
   566  // B9 is the first block of the NEXT epoch.
   567  func TestExtendEpochTransitionValid(t *testing.T) {
   568  	// create a event consumer to test epoch transition events
   569  	consumer := new(mockprotocol.Consumer)
   570  	consumer.On("BlockFinalized", mock.Anything)
   571  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   572  
   573  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
   574  
   575  		// set up state and mock ComplianceMetrics object
   576  		metrics := new(mockmodule.ComplianceMetrics)
   577  		metrics.On("BlockSealed", mock.Anything)
   578  		metrics.On("SealedHeight", mock.Anything)
   579  		metrics.On("FinalizedHeight", mock.Anything)
   580  		metrics.On("BlockFinalized", mock.Anything)
   581  
   582  		// expect epoch metric calls on bootstrap
   583  		initialCurrentEpoch := rootSnapshot.Epochs().Current()
   584  		counter, err := initialCurrentEpoch.Counter()
   585  		require.NoError(t, err)
   586  		finalView, err := initialCurrentEpoch.FinalView()
   587  		require.NoError(t, err)
   588  		initialPhase, err := rootSnapshot.Phase()
   589  		require.NoError(t, err)
   590  		metrics.On("CurrentEpochCounter", counter).Once()
   591  		metrics.On("CurrentEpochPhase", initialPhase).Once()
   592  		metrics.On("CommittedEpochFinalView", finalView).Once()
   593  
   594  		metrics.On("CurrentEpochFinalView", finalView).Once()
   595  
   596  		dkgPhase1FinalView, dkgPhase2FinalView, dkgPhase3FinalView, err := realprotocol.DKGPhaseViews(initialCurrentEpoch)
   597  		require.NoError(t, err)
   598  		metrics.On("CurrentDKGPhase1FinalView", dkgPhase1FinalView).Once()
   599  		metrics.On("CurrentDKGPhase2FinalView", dkgPhase2FinalView).Once()
   600  		metrics.On("CurrentDKGPhase3FinalView", dkgPhase3FinalView).Once()
   601  
   602  		tracer := trace.NewNoopTracer()
   603  		headers, _, seals, index, payloads, blocks, setups, commits, statuses, results := storeutil.StorageLayer(t, db)
   604  		protoState, err := protocol.Bootstrap(metrics, db, headers, seals, results, blocks, setups, commits, statuses, rootSnapshot)
   605  		require.NoError(t, err)
   606  		receiptValidator := util.MockReceiptValidator()
   607  		sealValidator := util.MockSealValidator(seals)
   608  		state, err := protocol.NewFullConsensusState(protoState, index, payloads, tracer, consumer,
   609  			util.MockBlockTimer(), receiptValidator, sealValidator)
   610  		require.NoError(t, err)
   611  
   612  		head, err := rootSnapshot.Head()
   613  		require.NoError(t, err)
   614  		result, _, err := rootSnapshot.SealedResult()
   615  		require.NoError(t, err)
   616  
   617  		// we should begin the epoch in the staking phase
   618  		phase, err := state.AtBlockID(head.ID()).Phase()
   619  		assert.NoError(t, err)
   620  		require.Equal(t, flow.EpochPhaseStaking, phase)
   621  
   622  		// add a block for the first seal to reference
   623  		block1 := unittest.BlockWithParentFixture(head)
   624  		block1.SetPayload(flow.EmptyPayload())
   625  		err = state.Extend(context.Background(), block1)
   626  		require.NoError(t, err)
   627  		err = state.Finalize(context.Background(), block1.ID())
   628  		require.NoError(t, err)
   629  
   630  		epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
   631  		epoch1FinalView := epoch1Setup.FinalView
   632  
   633  		// add a participant for the next epoch
   634  		epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleVerification))
   635  		epoch2Participants := append(participants, epoch2NewParticipant).Sort(order.Canonical)
   636  
   637  		// create the epoch setup event for the second epoch
   638  		epoch2Setup := unittest.EpochSetupFixture(
   639  			unittest.WithParticipants(epoch2Participants),
   640  			unittest.SetupWithCounter(epoch1Setup.Counter+1),
   641  			unittest.WithFinalView(epoch1FinalView+1000),
   642  			unittest.WithFirstView(epoch1FinalView+1),
   643  		)
   644  
   645  		// create a receipt for block 1 containing the EpochSetup event
   646  		receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
   647  		receipt1.ExecutionResult.ServiceEvents = []flow.ServiceEvent{epoch2Setup.ServiceEvent()}
   648  		seal1.ResultID = receipt1.ExecutionResult.ID()
   649  
   650  		// add a second block with the receipt for block 1
   651  		block2 := unittest.BlockWithParentFixture(block1.Header)
   652  		block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
   653  
   654  		err = state.Extend(context.Background(), block2)
   655  		require.NoError(t, err)
   656  		err = state.Finalize(context.Background(), block2.ID())
   657  		require.NoError(t, err)
   658  
   659  		// block 3 contains the seal for block 1
   660  		block3 := unittest.BlockWithParentFixture(block2.Header)
   661  		block3.SetPayload(flow.Payload{
   662  			Seals: []*flow.Seal{seal1},
   663  		})
   664  
   665  		// insert the block sealing the EpochSetup event
   666  		err = state.Extend(context.Background(), block3)
   667  		require.NoError(t, err)
   668  
   669  		// insert a block with a QC pointing to block 3
   670  		block4 := unittest.BlockWithParentFixture(block3.Header)
   671  		err = state.Extend(context.Background(), block4)
   672  		require.NoError(t, err)
   673  
   674  		// now that the setup event has been emitted, we should be in the setup phase
   675  		phase, err = state.AtBlockID(block4.ID()).Phase()
   676  		assert.NoError(t, err)
   677  		require.Equal(t, flow.EpochPhaseSetup, phase)
   678  
   679  		// we should NOT be able to query epoch 2 wrt blocks before 4
   680  		for _, blockID := range []flow.Identifier{block1.ID(), block2.ID(), block3.ID()} {
   681  			_, err = state.AtBlockID(blockID).Epochs().Next().InitialIdentities()
   682  			require.Error(t, err)
   683  			_, err = state.AtBlockID(blockID).Epochs().Next().Clustering()
   684  			require.Error(t, err)
   685  		}
   686  
   687  		// we should be able to query epoch 2 wrt block 4
   688  		_, err = state.AtBlockID(block4.ID()).Epochs().Next().InitialIdentities()
   689  		assert.NoError(t, err)
   690  		_, err = state.AtBlockID(block4.ID()).Epochs().Next().Clustering()
   691  		assert.NoError(t, err)
   692  
   693  		// only setup event is finalized, not commit, so shouldn't be able to get certain info
   694  		_, err = state.AtBlockID(block4.ID()).Epochs().Next().DKG()
   695  		require.Error(t, err)
   696  
   697  		// finalize block 3 so we can finalize subsequent blocks
   698  		err = state.Finalize(context.Background(), block3.ID())
   699  		require.NoError(t, err)
   700  
   701  		// finalize block 4 so we can finalize subsequent blocks
   702  		// ensure an epoch phase transition when we finalize block 4
   703  		consumer.On("EpochSetupPhaseStarted", epoch2Setup.Counter-1, block4.Header).Once()
   704  		metrics.On("CurrentEpochPhase", flow.EpochPhaseSetup).Once()
   705  		err = state.Finalize(context.Background(), block4.ID())
   706  		require.NoError(t, err)
   707  		consumer.AssertCalled(t, "EpochSetupPhaseStarted", epoch2Setup.Counter-1, block4.Header)
   708  		metrics.AssertCalled(t, "CurrentEpochPhase", flow.EpochPhaseSetup)
   709  
   710  		// now that the setup event has been emitted, we should be in the setup phase
   711  		phase, err = state.AtBlockID(block4.ID()).Phase()
   712  		assert.NoError(t, err)
   713  		require.Equal(t, flow.EpochPhaseSetup, phase)
   714  
   715  		epoch2Commit := unittest.EpochCommitFixture(
   716  			unittest.CommitWithCounter(epoch2Setup.Counter),
   717  			unittest.WithClusterQCsFromAssignments(epoch2Setup.Assignments),
   718  			unittest.WithDKGFromParticipants(epoch2Participants),
   719  		)
   720  
   721  		// create receipt and seal for block 2
   722  		// the receipt for block 2 contains the EpochCommit event
   723  		receipt2, seal2 := unittest.ReceiptAndSealForBlock(block2)
   724  		receipt2.ExecutionResult.ServiceEvents = []flow.ServiceEvent{epoch2Commit.ServiceEvent()}
   725  		seal2.ResultID = receipt2.ExecutionResult.ID()
   726  
   727  		// block 5 contains the receipt for block 2
   728  		block5 := unittest.BlockWithParentFixture(block4.Header)
   729  		block5.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt2)))
   730  
   731  		err = state.Extend(context.Background(), block5)
   732  		require.NoError(t, err)
   733  		err = state.Finalize(context.Background(), block5.ID())
   734  		require.NoError(t, err)
   735  
   736  		// block 6 contains the seal for block 2
   737  		block6 := unittest.BlockWithParentFixture(block5.Header)
   738  		block6.SetPayload(flow.Payload{
   739  			Seals: []*flow.Seal{seal2},
   740  		})
   741  
   742  		err = state.Extend(context.Background(), block6)
   743  		require.NoError(t, err)
   744  
   745  		// insert a block with a QC pointing to block 6
   746  		block7 := unittest.BlockWithParentFixture(block6.Header)
   747  		err = state.Extend(context.Background(), block7)
   748  		require.NoError(t, err)
   749  
   750  		// we should NOT be able to query epoch 2 commit info wrt blocks before 7
   751  		for _, blockID := range []flow.Identifier{block4.ID(), block5.ID(), block6.ID()} {
   752  			_, err = state.AtBlockID(blockID).Epochs().Next().DKG()
   753  			require.Error(t, err)
   754  		}
   755  
   756  		// now epoch 2 is fully ready, we can query anything we want about it wrt block 7 (or later)
   757  		_, err = state.AtBlockID(block7.ID()).Epochs().Next().InitialIdentities()
   758  		require.NoError(t, err)
   759  		_, err = state.AtBlockID(block7.ID()).Epochs().Next().Clustering()
   760  		require.NoError(t, err)
   761  		_, err = state.AtBlockID(block7.ID()).Epochs().Next().DKG()
   762  		assert.NoError(t, err)
   763  
   764  		// now that the commit event has been emitted, we should be in the committed phase
   765  		phase, err = state.AtBlockID(block7.ID()).Phase()
   766  		assert.NoError(t, err)
   767  		require.Equal(t, flow.EpochPhaseCommitted, phase)
   768  
   769  		err = state.Finalize(context.Background(), block6.ID())
   770  		require.NoError(t, err)
   771  
   772  		// expect epoch phase transition once we finalize block 7
   773  		consumer.On("EpochCommittedPhaseStarted", epoch2Setup.Counter-1, block7.Header).Once()
   774  		// expect committed final view to be updated, since we are committing epoch 2
   775  		metrics.On("CommittedEpochFinalView", epoch2Setup.FinalView).Once()
   776  		metrics.On("CurrentEpochPhase", flow.EpochPhaseCommitted).Once()
   777  		err = state.Finalize(context.Background(), block7.ID())
   778  
   779  		require.NoError(t, err)
   780  		consumer.AssertCalled(t, "EpochCommittedPhaseStarted", epoch2Setup.Counter-1, block7.Header)
   781  		metrics.AssertCalled(t, "CommittedEpochFinalView", epoch2Setup.FinalView)
   782  		metrics.AssertCalled(t, "CurrentEpochPhase", flow.EpochPhaseCommitted)
   783  
   784  		// we should still be in epoch 1
   785  		epochCounter, err := state.AtBlockID(block4.ID()).Epochs().Current().Counter()
   786  		require.NoError(t, err)
   787  		require.Equal(t, epoch1Setup.Counter, epochCounter)
   788  
   789  		// block 8 has the final view of the epoch
   790  		block8 := unittest.BlockWithParentFixture(block7.Header)
   791  		block8.SetPayload(flow.EmptyPayload())
   792  		block8.Header.View = epoch1FinalView
   793  
   794  		err = state.Extend(context.Background(), block8)
   795  		require.NoError(t, err)
   796  
   797  		// we should still be in epoch 1, since epochs are inclusive of final view
   798  		epochCounter, err = state.AtBlockID(block8.ID()).Epochs().Current().Counter()
   799  		require.NoError(t, err)
   800  		require.Equal(t, epoch1Setup.Counter, epochCounter)
   801  
   802  		// block 9 has a view > final view of epoch 1, it will be considered the first block of epoch 2
   803  		block9 := unittest.BlockWithParentFixture(block8.Header)
   804  		block9.SetPayload(flow.EmptyPayload())
   805  		// we should handle views that aren't exactly the first valid view of the epoch
   806  		block9.Header.View = epoch1FinalView + uint64(1+rand.Intn(10))
   807  
   808  		err = state.Extend(context.Background(), block9)
   809  		require.NoError(t, err)
   810  
   811  		// now, at long last, we are in epoch 2
   812  		epochCounter, err = state.AtBlockID(block9.ID()).Epochs().Current().Counter()
   813  		require.NoError(t, err)
   814  		require.Equal(t, epoch2Setup.Counter, epochCounter)
   815  
   816  		// we should begin epoch 2 in staking phase
   817  		// how that the commit event has been emitted, we should be in the committed phase
   818  		phase, err = state.AtBlockID(block9.ID()).Phase()
   819  		assert.NoError(t, err)
   820  		require.Equal(t, flow.EpochPhaseStaking, phase)
   821  
   822  		// expect epoch transition once we finalize block 9
   823  		consumer.On("EpochTransition", epoch2Setup.Counter, block9.Header).Once()
   824  		metrics.On("CurrentEpochCounter", epoch2Setup.Counter).Once()
   825  		metrics.On("CurrentEpochPhase", flow.EpochPhaseStaking).Once()
   826  		metrics.On("CurrentEpochFinalView", epoch2Setup.FinalView).Once()
   827  		metrics.On("CurrentDKGPhase1FinalView", epoch2Setup.DKGPhase1FinalView).Once()
   828  		metrics.On("CurrentDKGPhase2FinalView", epoch2Setup.DKGPhase2FinalView).Once()
   829  		metrics.On("CurrentDKGPhase3FinalView", epoch2Setup.DKGPhase3FinalView).Once()
   830  
   831  		err = state.Finalize(context.Background(), block8.ID())
   832  		require.NoError(t, err)
   833  		err = state.Finalize(context.Background(), block9.ID())
   834  		require.NoError(t, err)
   835  		consumer.AssertCalled(t, "EpochTransition", epoch2Setup.Counter, block9.Header)
   836  		metrics.AssertCalled(t, "CurrentEpochCounter", epoch2Setup.Counter)
   837  		metrics.AssertCalled(t, "CurrentEpochPhase", flow.EpochPhaseStaking)
   838  		metrics.AssertCalled(t, "CurrentEpochFinalView", epoch2Setup.FinalView)
   839  		metrics.AssertCalled(t, "CurrentDKGPhase1FinalView", epoch2Setup.DKGPhase1FinalView)
   840  		metrics.AssertCalled(t, "CurrentDKGPhase2FinalView", epoch2Setup.DKGPhase2FinalView)
   841  		metrics.AssertCalled(t, "CurrentDKGPhase3FinalView", epoch2Setup.DKGPhase3FinalView)
   842  
   843  		metrics.AssertExpectations(t)
   844  	})
   845  }
   846  
   847  // we should be able to have conflicting forks with two different instances of
   848  // the same service event for the same epoch
   849  //
   850  //	         /--B1<--B3(R1)<--B5(S1)<--B7
   851  //	ROOT <--+
   852  //	         \--B2<--B4(R2)<--B6(S2)<--B8
   853  func TestExtendConflictingEpochEvents(t *testing.T) {
   854  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   855  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   856  
   857  		head, err := rootSnapshot.Head()
   858  		require.NoError(t, err)
   859  		result, _, err := rootSnapshot.SealedResult()
   860  		require.NoError(t, err)
   861  
   862  		// add two conflicting blocks for each service event to reference
   863  		block1 := unittest.BlockWithParentFixture(head)
   864  		block1.SetPayload(flow.EmptyPayload())
   865  		err = state.Extend(context.Background(), block1)
   866  		require.NoError(t, err)
   867  
   868  		block2 := unittest.BlockWithParentFixture(head)
   869  		block2.SetPayload(flow.EmptyPayload())
   870  		err = state.Extend(context.Background(), block2)
   871  		require.NoError(t, err)
   872  
   873  		rootSetup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
   874  
   875  		// create two conflicting epoch setup events for the next epoch (final view differs)
   876  		nextEpochSetup1 := unittest.EpochSetupFixture(
   877  			unittest.WithParticipants(rootSetup.Participants),
   878  			unittest.SetupWithCounter(rootSetup.Counter+1),
   879  			unittest.WithFinalView(rootSetup.FinalView+1000),
   880  			unittest.WithFirstView(rootSetup.FinalView+1),
   881  		)
   882  		nextEpochSetup2 := unittest.EpochSetupFixture(
   883  			unittest.WithParticipants(rootSetup.Participants),
   884  			unittest.SetupWithCounter(rootSetup.Counter+1),
   885  			unittest.WithFinalView(rootSetup.FinalView+2000), // final view differs
   886  			unittest.WithFirstView(rootSetup.FinalView+1),
   887  		)
   888  
   889  		// add blocks containing receipts for block1 and block2 (necessary for sealing)
   890  		// block 1 receipt contains nextEpochSetup1
   891  		block1Receipt := unittest.ReceiptForBlockFixture(block1)
   892  		block1Receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{nextEpochSetup1.ServiceEvent()}
   893  
   894  		// add block 1 receipt to block 3 payload
   895  		block3 := unittest.BlockWithParentFixture(block1.Header)
   896  		block3.SetPayload(flow.Payload{
   897  			Receipts: []*flow.ExecutionReceiptMeta{block1Receipt.Meta()},
   898  			Results:  []*flow.ExecutionResult{&block1Receipt.ExecutionResult},
   899  		})
   900  		err = state.Extend(context.Background(), block3)
   901  		require.NoError(t, err)
   902  
   903  		// block 2 receipt contains nextEpochSetup2
   904  		block2Receipt := unittest.ReceiptForBlockFixture(block2)
   905  		block2Receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{nextEpochSetup2.ServiceEvent()}
   906  
   907  		// add block 2 receipt to block 4 payload
   908  		block4 := unittest.BlockWithParentFixture(block2.Header)
   909  		block4.SetPayload(flow.Payload{
   910  			Receipts: []*flow.ExecutionReceiptMeta{block2Receipt.Meta()},
   911  			Results:  []*flow.ExecutionResult{&block2Receipt.ExecutionResult},
   912  		})
   913  		err = state.Extend(context.Background(), block4)
   914  		require.NoError(t, err)
   915  
   916  		// seal for block 1
   917  		seal1 := unittest.Seal.Fixture(unittest.Seal.WithResult(&block1Receipt.ExecutionResult))
   918  
   919  		// seal for block 2
   920  		seal2 := unittest.Seal.Fixture(unittest.Seal.WithResult(&block2Receipt.ExecutionResult))
   921  
   922  		// block 5 builds on block 3, contains seal for block 1
   923  		block5 := unittest.BlockWithParentFixture(block3.Header)
   924  		block5.SetPayload(flow.Payload{
   925  			Seals: []*flow.Seal{seal1},
   926  		})
   927  		err = state.Extend(context.Background(), block5)
   928  		require.NoError(t, err)
   929  
   930  		// block 6 builds on block 4, contains seal for block 2
   931  		block6 := unittest.BlockWithParentFixture(block4.Header)
   932  		block6.SetPayload(flow.Payload{
   933  			Seals: []*flow.Seal{seal2},
   934  		})
   935  		err = state.Extend(context.Background(), block6)
   936  		require.NoError(t, err)
   937  
   938  		// block 7 builds on block 5, contains QC for block 7
   939  		block7 := unittest.BlockWithParentFixture(block5.Header)
   940  		err = state.Extend(context.Background(), block7)
   941  		require.NoError(t, err)
   942  
   943  		// block 8 builds on block 6, contains QC for block 6
   944  		block8 := unittest.BlockWithParentFixture(block6.Header)
   945  		err = state.Extend(context.Background(), block8)
   946  		require.NoError(t, err)
   947  
   948  		// should be able query each epoch from the appropriate reference block
   949  		setup1FinalView, err := state.AtBlockID(block7.ID()).Epochs().Next().FinalView()
   950  		assert.NoError(t, err)
   951  		require.Equal(t, nextEpochSetup1.FinalView, setup1FinalView)
   952  
   953  		setup2FinalView, err := state.AtBlockID(block8.ID()).Epochs().Next().FinalView()
   954  		assert.NoError(t, err)
   955  		require.Equal(t, nextEpochSetup2.FinalView, setup2FinalView)
   956  	})
   957  }
   958  
   959  // we should be able to have conflicting forks with two DUPLICATE instances of
   960  // the same service event for the same epoch
   961  //
   962  //	        /--B1<--B3(R1)<--B5(S1)<--B7
   963  //	ROOT <--+
   964  //	        \--B2<--B4(R2)<--B6(S2)<--B8
   965  func TestExtendDuplicateEpochEvents(t *testing.T) {
   966  	rootSnapshot := unittest.RootSnapshotFixture(participants)
   967  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
   968  
   969  		head, err := rootSnapshot.Head()
   970  		require.NoError(t, err)
   971  		result, _, err := rootSnapshot.SealedResult()
   972  		require.NoError(t, err)
   973  
   974  		// add two conflicting blocks for each service event to reference
   975  		block1 := unittest.BlockWithParentFixture(head)
   976  		block1.SetPayload(flow.EmptyPayload())
   977  		err = state.Extend(context.Background(), block1)
   978  		require.NoError(t, err)
   979  
   980  		block2 := unittest.BlockWithParentFixture(head)
   981  		block2.SetPayload(flow.EmptyPayload())
   982  		err = state.Extend(context.Background(), block2)
   983  		require.NoError(t, err)
   984  
   985  		rootSetup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
   986  
   987  		// create an epoch setup event to insert to BOTH forks
   988  		nextEpochSetup := unittest.EpochSetupFixture(
   989  			unittest.WithParticipants(rootSetup.Participants),
   990  			unittest.SetupWithCounter(rootSetup.Counter+1),
   991  			unittest.WithFinalView(rootSetup.FinalView+1000),
   992  			unittest.WithFirstView(rootSetup.FinalView+1),
   993  		)
   994  
   995  		// add blocks containing receipts for block1 and block2 (necessary for sealing)
   996  		// block 1 receipt contains nextEpochSetup1
   997  		block1Receipt := unittest.ReceiptForBlockFixture(block1)
   998  		block1Receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{nextEpochSetup.ServiceEvent()}
   999  
  1000  		// add block 1 receipt to block 3 payload
  1001  		block3 := unittest.BlockWithParentFixture(block1.Header)
  1002  		block3.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(block1Receipt)))
  1003  		err = state.Extend(context.Background(), block3)
  1004  		require.NoError(t, err)
  1005  
  1006  		// block 2 receipt contains nextEpochSetup2
  1007  		block2Receipt := unittest.ReceiptForBlockFixture(block2)
  1008  		block2Receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{nextEpochSetup.ServiceEvent()}
  1009  
  1010  		// add block 2 receipt to block 4 payload
  1011  		block4 := unittest.BlockWithParentFixture(block2.Header)
  1012  		block4.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(block2Receipt)))
  1013  		err = state.Extend(context.Background(), block4)
  1014  		require.NoError(t, err)
  1015  
  1016  		// seal for block 1
  1017  		seal1 := unittest.Seal.Fixture(unittest.Seal.WithResult(&block1Receipt.ExecutionResult))
  1018  
  1019  		// seal for block 2
  1020  		seal2 := unittest.Seal.Fixture(unittest.Seal.WithResult(&block2Receipt.ExecutionResult))
  1021  
  1022  		// block 5 builds on block 3, contains seal for block 1
  1023  		block5 := unittest.BlockWithParentFixture(block3.Header)
  1024  		block5.SetPayload(flow.Payload{
  1025  			Seals: []*flow.Seal{seal1},
  1026  		})
  1027  		err = state.Extend(context.Background(), block5)
  1028  		require.NoError(t, err)
  1029  
  1030  		// block 6 builds on block 4, contains seal for block 2
  1031  		block6 := unittest.BlockWithParentFixture(block4.Header)
  1032  		block6.SetPayload(flow.Payload{
  1033  			Seals: []*flow.Seal{seal2},
  1034  		})
  1035  		err = state.Extend(context.Background(), block6)
  1036  		require.NoError(t, err)
  1037  
  1038  		// block 7 builds on block 5, contains QC for block 7
  1039  		block7 := unittest.BlockWithParentFixture(block5.Header)
  1040  		err = state.Extend(context.Background(), block7)
  1041  		require.NoError(t, err)
  1042  
  1043  		// block 8 builds on block 6, contains QC for block 6
  1044  		// at this point we are inserting the duplicate EpochSetup, should not error
  1045  		block8 := unittest.BlockWithParentFixture(block6.Header)
  1046  		err = state.Extend(context.Background(), block8)
  1047  		require.NoError(t, err)
  1048  
  1049  		// should be able query each epoch from the appropriate reference block
  1050  		finalView, err := state.AtBlockID(block7.ID()).Epochs().Next().FinalView()
  1051  		assert.NoError(t, err)
  1052  		require.Equal(t, nextEpochSetup.FinalView, finalView)
  1053  
  1054  		finalView, err = state.AtBlockID(block8.ID()).Epochs().Next().FinalView()
  1055  		assert.NoError(t, err)
  1056  		require.Equal(t, nextEpochSetup.FinalView, finalView)
  1057  	})
  1058  }
  1059  
  1060  // extending protocol state with an invalid epoch setup service event should cause an error
  1061  func TestExtendEpochSetupInvalid(t *testing.T) {
  1062  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1063  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
  1064  		head, err := rootSnapshot.Head()
  1065  		require.NoError(t, err)
  1066  		result, _, err := rootSnapshot.SealedResult()
  1067  		require.NoError(t, err)
  1068  
  1069  		// add a block for the first seal to reference
  1070  		block1 := unittest.BlockWithParentFixture(head)
  1071  		block1.SetPayload(flow.EmptyPayload())
  1072  		err = state.Extend(context.Background(), block1)
  1073  		require.NoError(t, err)
  1074  
  1075  		epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1076  
  1077  		// add a participant for the next epoch
  1078  		epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleVerification))
  1079  		epoch2Participants := append(participants, epoch2NewParticipant).Sort(order.Canonical)
  1080  
  1081  		// this function will return a VALID setup event and seal, we will modify
  1082  		// in different ways in each test case
  1083  		createSetup := func(opts ...func(*flow.EpochSetup)) (*flow.EpochSetup, *flow.ExecutionReceipt, *flow.Seal) {
  1084  			setup := unittest.EpochSetupFixture(
  1085  				unittest.WithParticipants(epoch2Participants),
  1086  				unittest.SetupWithCounter(epoch1Setup.Counter+1),
  1087  				unittest.WithFinalView(epoch1Setup.FinalView+1000),
  1088  				unittest.WithFirstView(epoch1Setup.FinalView+1),
  1089  			)
  1090  			for _, apply := range opts {
  1091  				apply(setup)
  1092  			}
  1093  			receipt, seal := unittest.ReceiptAndSealForBlock(block1)
  1094  			receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{setup.ServiceEvent()}
  1095  			seal.ResultID = receipt.ExecutionResult.ID()
  1096  			return setup, receipt, seal
  1097  		}
  1098  
  1099  		// expect a setup event with wrong counter to trigger EECC without error
  1100  		t.Run("wrong counter (EECC)", func(t *testing.T) {
  1101  			_, receipt, seal := createSetup(func(setup *flow.EpochSetup) {
  1102  				setup.Counter = epoch1Setup.Counter
  1103  			})
  1104  
  1105  			sealingBlock := unittest.SealBlock(t, state, block1, receipt, seal)
  1106  
  1107  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1108  			err = state.Extend(context.Background(), qcBlock)
  1109  			require.NoError(t, err)
  1110  			assertEpochEmergencyFallbackTriggered(t, db)
  1111  		})
  1112  
  1113  		// expect a setup event with wrong final view to trigger EECC without error
  1114  		t.Run("invalid final view (EECC)", func(t *testing.T) {
  1115  			_, receipt, seal := createSetup(func(setup *flow.EpochSetup) {
  1116  				setup.FinalView = block1.Header.View
  1117  			})
  1118  
  1119  			sealingBlock := unittest.SealBlock(t, state, block1, receipt, seal)
  1120  
  1121  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1122  			err = state.Extend(context.Background(), qcBlock)
  1123  			require.NoError(t, err)
  1124  			assertEpochEmergencyFallbackTriggered(t, db)
  1125  		})
  1126  
  1127  		// expect a setup event with empty seed to trigger EECC without error
  1128  		t.Run("empty seed (EECC)", func(t *testing.T) {
  1129  			_, receipt, seal := createSetup(func(setup *flow.EpochSetup) {
  1130  				setup.RandomSource = nil
  1131  			})
  1132  
  1133  			sealingBlock := unittest.SealBlock(t, state, block1, receipt, seal)
  1134  
  1135  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1136  			err = state.Extend(context.Background(), qcBlock)
  1137  			require.NoError(t, err)
  1138  			assertEpochEmergencyFallbackTriggered(t, db)
  1139  		})
  1140  	})
  1141  }
  1142  
  1143  // extending protocol state with an invalid epoch commit service event should cause an error
  1144  func TestExtendEpochCommitInvalid(t *testing.T) {
  1145  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1146  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
  1147  
  1148  		head, err := rootSnapshot.Head()
  1149  		require.NoError(t, err)
  1150  		result, _, err := rootSnapshot.SealedResult()
  1151  		require.NoError(t, err)
  1152  
  1153  		// add a block for the first seal to reference
  1154  		block1 := unittest.BlockWithParentFixture(head)
  1155  		block1.SetPayload(flow.EmptyPayload())
  1156  		err = state.Extend(context.Background(), block1)
  1157  		require.NoError(t, err)
  1158  
  1159  		epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1160  
  1161  		// swap consensus node for a new one for epoch 2
  1162  		epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleConsensus))
  1163  		epoch2Participants := append(
  1164  			participants.Filter(filter.Not(filter.HasRole(flow.RoleConsensus))),
  1165  			epoch2NewParticipant,
  1166  		).Sort(order.Canonical)
  1167  
  1168  		createSetup := func(block *flow.Block) (*flow.EpochSetup, *flow.ExecutionReceipt, *flow.Seal) {
  1169  			setup := unittest.EpochSetupFixture(
  1170  				unittest.WithParticipants(epoch2Participants),
  1171  				unittest.SetupWithCounter(epoch1Setup.Counter+1),
  1172  				unittest.WithFinalView(epoch1Setup.FinalView+1000),
  1173  				unittest.WithFirstView(epoch1Setup.FinalView+1),
  1174  			)
  1175  
  1176  			receipt, seal := unittest.ReceiptAndSealForBlock(block)
  1177  			receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{setup.ServiceEvent()}
  1178  			seal.ResultID = receipt.ExecutionResult.ID()
  1179  			return setup, receipt, seal
  1180  		}
  1181  
  1182  		createCommit := func(block *flow.Block, opts ...func(*flow.EpochCommit)) (*flow.EpochCommit, *flow.ExecutionReceipt, *flow.Seal) {
  1183  			commit := unittest.EpochCommitFixture(
  1184  				unittest.CommitWithCounter(epoch1Setup.Counter+1),
  1185  				unittest.WithDKGFromParticipants(epoch2Participants),
  1186  			)
  1187  			for _, apply := range opts {
  1188  				apply(commit)
  1189  			}
  1190  			receipt, seal := unittest.ReceiptAndSealForBlock(block)
  1191  			receipt.ExecutionResult.ServiceEvents = []flow.ServiceEvent{commit.ServiceEvent()}
  1192  			seal.ResultID = receipt.ExecutionResult.ID()
  1193  			return commit, receipt, seal
  1194  		}
  1195  
  1196  		t.Run("without setup", func(t *testing.T) {
  1197  			_, receipt, seal := createCommit(block1)
  1198  
  1199  			sealingBlock := unittest.SealBlock(t, state, block1, receipt, seal)
  1200  
  1201  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1202  			err = state.Extend(context.Background(), qcBlock)
  1203  			require.Error(t, err)
  1204  			require.True(t, st.IsInvalidExtensionError(err), err)
  1205  		})
  1206  
  1207  		// seal block 1, in which EpochSetup was emitted
  1208  		epoch2Setup, setupReceipt, setupSeal := createSetup(block1)
  1209  		block2 := unittest.SealBlock(t, state, block1, setupReceipt, setupSeal)
  1210  
  1211  		// insert a block with a QC for block 2
  1212  		block3 := unittest.BlockWithParentFixture(block2)
  1213  		err = state.Extend(context.Background(), block3)
  1214  		require.NoError(t, err)
  1215  
  1216  		// expect a commit event with wrong counter to trigger EECC without error
  1217  		t.Run("inconsistent counter (EECC)", func(t *testing.T) {
  1218  			_, receipt, seal := createCommit(block3, func(commit *flow.EpochCommit) {
  1219  				commit.Counter = epoch2Setup.Counter + 1
  1220  			})
  1221  
  1222  			sealingBlock := unittest.SealBlock(t, state, block3, receipt, seal)
  1223  
  1224  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1225  			err = state.Extend(context.Background(), qcBlock)
  1226  			require.NoError(t, err)
  1227  			assertEpochEmergencyFallbackTriggered(t, db)
  1228  		})
  1229  
  1230  		// expect a commit event with wrong cluster QCs to trigger EECC without error
  1231  		t.Run("inconsistent cluster QCs (EECC)", func(t *testing.T) {
  1232  			_, receipt, seal := createCommit(block3, func(commit *flow.EpochCommit) {
  1233  				commit.ClusterQCs = append(commit.ClusterQCs, flow.ClusterQCVoteDataFromQC(unittest.QuorumCertificateWithSignerIDsFixture()))
  1234  			})
  1235  
  1236  			sealingBlock := unittest.SealBlock(t, state, block3, receipt, seal)
  1237  
  1238  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1239  			err = state.Extend(context.Background(), qcBlock)
  1240  			require.NoError(t, err)
  1241  			assertEpochEmergencyFallbackTriggered(t, db)
  1242  		})
  1243  
  1244  		// expect a commit event with wrong dkg participants to trigger EECC without error
  1245  		t.Run("inconsistent DKG participants (EECC)", func(t *testing.T) {
  1246  			_, receipt, seal := createCommit(block3, func(commit *flow.EpochCommit) {
  1247  				// add an extra dkg key
  1248  				commit.DKGParticipantKeys = append(commit.DKGParticipantKeys, unittest.KeyFixture(crypto.BLSBLS12381).PublicKey())
  1249  			})
  1250  
  1251  			sealingBlock := unittest.SealBlock(t, state, block3, receipt, seal)
  1252  
  1253  			qcBlock := unittest.BlockWithParentFixture(sealingBlock)
  1254  			err = state.Extend(context.Background(), qcBlock)
  1255  			require.NoError(t, err)
  1256  			assertEpochEmergencyFallbackTriggered(t, db)
  1257  		})
  1258  	})
  1259  }
  1260  
  1261  // if we reach the first block of the next epoch before both setup and commit
  1262  // service events are finalized, the chain should halt
  1263  //
  1264  // ROOT <- B1 <- B2(R1) <- B3(S1) <- B4
  1265  func TestExtendEpochTransitionWithoutCommit(t *testing.T) {
  1266  
  1267  	// skipping because this case will now result in emergency epoch continuation kicking in
  1268  	unittest.SkipUnless(t, unittest.TEST_TODO, "disabled as the current implementation uses a temporary fallback measure in this case (triggers EECC), rather than returning an error")
  1269  
  1270  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1271  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
  1272  		head, err := rootSnapshot.Head()
  1273  		require.NoError(t, err)
  1274  		result, _, err := rootSnapshot.SealedResult()
  1275  		require.NoError(t, err)
  1276  
  1277  		// add a block for the first seal to reference
  1278  		block1 := unittest.BlockWithParentFixture(head)
  1279  		block1.SetPayload(flow.EmptyPayload())
  1280  		err = state.Extend(context.Background(), block1)
  1281  		require.NoError(t, err)
  1282  		err = state.Finalize(context.Background(), block1.ID())
  1283  		require.NoError(t, err)
  1284  
  1285  		epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1286  		epoch1FinalView := epoch1Setup.FinalView
  1287  
  1288  		// add a participant for the next epoch
  1289  		epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleVerification))
  1290  		epoch2Participants := append(participants, epoch2NewParticipant).Sort(order.Canonical)
  1291  
  1292  		// create the epoch setup event for the second epoch
  1293  		epoch2Setup := unittest.EpochSetupFixture(
  1294  			unittest.WithParticipants(epoch2Participants),
  1295  			unittest.SetupWithCounter(epoch1Setup.Counter+1),
  1296  			unittest.WithFinalView(epoch1FinalView+1000),
  1297  			unittest.WithFirstView(epoch1FinalView+1),
  1298  		)
  1299  
  1300  		receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
  1301  		receipt1.ExecutionResult.ServiceEvents = []flow.ServiceEvent{epoch2Setup.ServiceEvent()}
  1302  
  1303  		// add a block containing a receipt for block 1
  1304  		block2 := unittest.BlockWithParentFixture(block1.Header)
  1305  		block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
  1306  		err = state.Extend(context.Background(), block2)
  1307  		require.NoError(t, err)
  1308  		err = state.Finalize(context.Background(), block2.ID())
  1309  		require.NoError(t, err)
  1310  
  1311  		// block 3 seals block 1
  1312  		block3 := unittest.BlockWithParentFixture(block2.Header)
  1313  		block3.SetPayload(flow.Payload{
  1314  			Seals: []*flow.Seal{seal1},
  1315  		})
  1316  		err = state.Extend(context.Background(), block3)
  1317  		require.NoError(t, err)
  1318  
  1319  		// block 4 will be the first block for epoch 2
  1320  		block4 := unittest.BlockWithParentFixture(block3.Header)
  1321  		block4.Header.View = epoch1Setup.FinalView + 1
  1322  
  1323  		err = state.Extend(context.Background(), block4)
  1324  		require.Error(t, err)
  1325  	})
  1326  }
  1327  
  1328  func TestEmergencyEpochChainContinuation(t *testing.T) {
  1329  
  1330  	// if we reach the first block of the next epoch before both setup and commit
  1331  	// service events are finalized, the chain should continue with the previous epoch.
  1332  	//
  1333  	// ROOT <- B1 <- B2(R1) <- B3(S1) <- B4
  1334  	t.Run("epoch transition without commit event - should continue with fallback epoch", func(t *testing.T) {
  1335  
  1336  		rootSnapshot := unittest.RootSnapshotFixture(participants)
  1337  		metricsMock := new(mockmodule.ComplianceMetrics)
  1338  		mockMetricsForRootSnapshot(metricsMock, rootSnapshot)
  1339  
  1340  		util.RunWithFullProtocolStateAndMetrics(t, rootSnapshot, metricsMock, func(db *badger.DB, state *protocol.MutableState) {
  1341  			head, err := rootSnapshot.Head()
  1342  			require.NoError(t, err)
  1343  			result, _, err := rootSnapshot.SealedResult()
  1344  			require.NoError(t, err)
  1345  
  1346  			// add a block for the first seal to reference
  1347  			block1 := unittest.BlockWithParentFixture(head)
  1348  			block1.SetPayload(flow.EmptyPayload())
  1349  			err = state.Extend(context.Background(), block1)
  1350  			require.NoError(t, err)
  1351  			err = state.Finalize(context.Background(), block1.ID())
  1352  			require.NoError(t, err)
  1353  
  1354  			epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1355  			epoch1FinalView := epoch1Setup.FinalView
  1356  
  1357  			// add a participant for the next epoch
  1358  			epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleVerification))
  1359  			epoch2Participants := append(participants, epoch2NewParticipant).Sort(order.Canonical)
  1360  
  1361  			// create the epoch setup event for the second epoch
  1362  			epoch2Setup := unittest.EpochSetupFixture(
  1363  				unittest.WithParticipants(epoch2Participants),
  1364  				unittest.SetupWithCounter(epoch1Setup.Counter+1),
  1365  				unittest.WithFinalView(epoch1FinalView+1000),
  1366  				unittest.WithFirstView(epoch1FinalView+1),
  1367  			)
  1368  
  1369  			receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
  1370  			receipt1.ExecutionResult.ServiceEvents = []flow.ServiceEvent{epoch2Setup.ServiceEvent()}
  1371  
  1372  			// add a block containing a receipt for block 1
  1373  			block2 := unittest.BlockWithParentFixture(block1.Header)
  1374  			block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
  1375  			err = state.Extend(context.Background(), block2)
  1376  			require.NoError(t, err)
  1377  			err = state.Finalize(context.Background(), block2.ID())
  1378  			require.NoError(t, err)
  1379  
  1380  			// block 3 seals block 1
  1381  			block3 := unittest.BlockWithParentFixture(block2.Header)
  1382  			block3.SetPayload(flow.Payload{
  1383  				Seals: []*flow.Seal{seal1},
  1384  			})
  1385  			err = state.Extend(context.Background(), block3)
  1386  			require.NoError(t, err)
  1387  
  1388  			// block 4 will be the first block for epoch 2
  1389  			block4 := unittest.BlockWithParentFixture(block3.Header)
  1390  			block4.Header.View = epoch1Setup.FinalView + 1
  1391  
  1392  			// inserting block 4 should trigger EECC
  1393  			metricsMock.On("EpochEmergencyFallbackTriggered").Once()
  1394  
  1395  			err = state.Extend(context.Background(), block4)
  1396  			require.NoError(t, err)
  1397  
  1398  			assertEpochEmergencyFallbackTriggered(t, db)
  1399  
  1400  			// epoch metrics should not be emitted
  1401  			metricsMock.AssertNotCalled(t, "EpochTransition", epoch2Setup.Counter, mock.Anything)
  1402  			metricsMock.AssertNotCalled(t, "CurrentEpochCounter", epoch2Setup.Counter)
  1403  			metricsMock.AssertExpectations(t)
  1404  		})
  1405  	})
  1406  
  1407  	// if we reach the first block of the next epoch before either setup and commit
  1408  	// service events are finalized, the chain should continue with the previous epoch.
  1409  	//
  1410  	// ROOT <- B1 <- B2(R1) <- B3(S1) <- B4
  1411  	t.Run("epoch transition without setup event - should continue with fallback epoch", func(t *testing.T) {
  1412  
  1413  		rootSnapshot := unittest.RootSnapshotFixture(participants)
  1414  		metricsMock := new(mockmodule.ComplianceMetrics)
  1415  		mockMetricsForRootSnapshot(metricsMock, rootSnapshot)
  1416  
  1417  		util.RunWithFullProtocolStateAndMetrics(t, rootSnapshot, metricsMock, func(db *badger.DB, state *protocol.MutableState) {
  1418  			head, err := rootSnapshot.Head()
  1419  			require.NoError(t, err)
  1420  			result, _, err := rootSnapshot.SealedResult()
  1421  			require.NoError(t, err)
  1422  
  1423  			// add a block for the first seal to reference
  1424  			block1 := unittest.BlockWithParentFixture(head)
  1425  			block1.SetPayload(flow.EmptyPayload())
  1426  			err = state.Extend(context.Background(), block1)
  1427  			require.NoError(t, err)
  1428  			err = state.Finalize(context.Background(), block1.ID())
  1429  			require.NoError(t, err)
  1430  
  1431  			epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1432  			receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
  1433  
  1434  			// add a block containing a receipt for block 1
  1435  			block2 := unittest.BlockWithParentFixture(block1.Header)
  1436  			block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
  1437  			err = state.Extend(context.Background(), block2)
  1438  			require.NoError(t, err)
  1439  			err = state.Finalize(context.Background(), block2.ID())
  1440  			require.NoError(t, err)
  1441  
  1442  			// block 3 seals block 1
  1443  			block3 := unittest.BlockWithParentFixture(block2.Header)
  1444  			block3.SetPayload(flow.Payload{
  1445  				Seals: []*flow.Seal{seal1},
  1446  			})
  1447  			err = state.Extend(context.Background(), block3)
  1448  			require.NoError(t, err)
  1449  
  1450  			// block 4 will be the first block for epoch 2
  1451  			block4 := unittest.BlockWithParentFixture(block3.Header)
  1452  			block4.Header.View = epoch1Setup.FinalView + 1
  1453  
  1454  			// inserting block 4 should trigger EECC
  1455  			metricsMock.On("EpochEmergencyFallbackTriggered").Once()
  1456  
  1457  			err = state.Extend(context.Background(), block4)
  1458  			require.NoError(t, err)
  1459  
  1460  			assertEpochEmergencyFallbackTriggered(t, db)
  1461  
  1462  			// epoch metrics should not be emitted
  1463  			metricsMock.AssertNotCalled(t, "EpochTransition", epoch1Setup.Counter+1, mock.Anything)
  1464  			metricsMock.AssertNotCalled(t, "CurrentEpochCounter", epoch1Setup.Counter+1)
  1465  			metricsMock.AssertExpectations(t)
  1466  		})
  1467  	})
  1468  
  1469  	// if an invalid epoch service event is incorporated, we should:
  1470  	//  * not apply the phase transition corresponding to the invalid service event
  1471  	//  * trigger EECC
  1472  	//
  1473  	// ROOT <- B1 <- B2(R1) <- B3(S1) <- B4
  1474  	t.Run("epoch transition with invalid service event - should continue with fallback epoch", func(t *testing.T) {
  1475  
  1476  		rootSnapshot := unittest.RootSnapshotFixture(participants)
  1477  		metricsMock := new(mockmodule.ComplianceMetrics)
  1478  		mockMetricsForRootSnapshot(metricsMock, rootSnapshot)
  1479  
  1480  		util.RunWithFullProtocolStateAndMetrics(t, rootSnapshot, metricsMock, func(db *badger.DB, state *protocol.MutableState) {
  1481  			head, err := rootSnapshot.Head()
  1482  			require.NoError(t, err)
  1483  			result, _, err := rootSnapshot.SealedResult()
  1484  			require.NoError(t, err)
  1485  
  1486  			// add a block for the first seal to reference
  1487  			block1 := unittest.BlockWithParentFixture(head)
  1488  			block1.SetPayload(flow.EmptyPayload())
  1489  			err = state.Extend(context.Background(), block1)
  1490  			require.NoError(t, err)
  1491  			err = state.Finalize(context.Background(), block1.ID())
  1492  			require.NoError(t, err)
  1493  
  1494  			epoch1Setup := result.ServiceEvents[0].Event.(*flow.EpochSetup)
  1495  			epoch1FinalView := epoch1Setup.FinalView
  1496  
  1497  			// add a participant for the next epoch
  1498  			epoch2NewParticipant := unittest.IdentityFixture(unittest.WithRole(flow.RoleVerification))
  1499  			epoch2Participants := append(participants, epoch2NewParticipant).Sort(order.Canonical)
  1500  
  1501  			// create the epoch setup event for the second epoch
  1502  			// this event is invalid because it used a non-contiguous first view
  1503  			epoch2Setup := unittest.EpochSetupFixture(
  1504  				unittest.WithParticipants(epoch2Participants),
  1505  				unittest.SetupWithCounter(epoch1Setup.Counter+1),
  1506  				unittest.WithFinalView(epoch1FinalView+1000),
  1507  				unittest.WithFirstView(epoch1FinalView+10), // invalid first view
  1508  			)
  1509  
  1510  			receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
  1511  			receipt1.ExecutionResult.ServiceEvents = []flow.ServiceEvent{epoch2Setup.ServiceEvent()}
  1512  
  1513  			// incorporating the service event should trigger EECC
  1514  			metricsMock.On("EpochEmergencyFallbackTriggered").Once()
  1515  
  1516  			// add a block containing a receipt for block 1
  1517  			block2 := unittest.BlockWithParentFixture(block1.Header)
  1518  			block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
  1519  			err = state.Extend(context.Background(), block2)
  1520  			require.NoError(t, err)
  1521  			err = state.Finalize(context.Background(), block2.ID())
  1522  			require.NoError(t, err)
  1523  
  1524  			// block 3 seals block 1
  1525  			block3 := unittest.BlockWithParentFixture(block2.Header)
  1526  			block3.SetPayload(flow.Payload{
  1527  				Seals: []*flow.Seal{seal1},
  1528  			})
  1529  			err = state.Extend(context.Background(), block3)
  1530  			require.NoError(t, err)
  1531  
  1532  			// block 4 will be the first block for epoch 2
  1533  			block4 := unittest.BlockWithParentFixture(block3.Header)
  1534  			block4.Header.View = epoch1Setup.FinalView + 1
  1535  
  1536  			err = state.Extend(context.Background(), block4)
  1537  			require.NoError(t, err)
  1538  
  1539  			assertEpochEmergencyFallbackTriggered(t, db)
  1540  
  1541  			// epoch metrics should not be emitted
  1542  			metricsMock.AssertNotCalled(t, "EpochTransition", epoch2Setup.Counter, mock.Anything)
  1543  			metricsMock.AssertNotCalled(t, "CurrentEpochCounter", epoch2Setup.Counter)
  1544  			metricsMock.AssertExpectations(t)
  1545  		})
  1546  	})
  1547  }
  1548  
  1549  func TestExtendInvalidSealsInBlock(t *testing.T) {
  1550  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
  1551  		metrics := metrics.NewNoopCollector()
  1552  		tracer := trace.NewNoopTracer()
  1553  		headers, _, seals, index, payloads, blocks, setups, commits, statuses, results := storeutil.StorageLayer(t, db)
  1554  
  1555  		// create a event consumer to test epoch transition events
  1556  		distributor := events.NewDistributor()
  1557  		consumer := new(mockprotocol.Consumer)
  1558  		distributor.AddConsumer(consumer)
  1559  
  1560  		rootSnapshot := unittest.RootSnapshotFixture(participants)
  1561  
  1562  		state, err := protocol.Bootstrap(metrics, db, headers, seals, results, blocks, setups, commits, statuses, rootSnapshot)
  1563  		require.NoError(t, err)
  1564  
  1565  		head, err := rootSnapshot.Head()
  1566  		require.NoError(t, err)
  1567  
  1568  		block1 := unittest.BlockWithParentFixture(head)
  1569  		block1.Payload.Guarantees = nil
  1570  		block1.Header.PayloadHash = block1.Payload.Hash()
  1571  
  1572  		block1Receipt := unittest.ReceiptForBlockFixture(block1)
  1573  		block2 := unittest.BlockWithParentFixture(block1.Header)
  1574  		block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(block1Receipt)))
  1575  
  1576  		block1Seal := unittest.Seal.Fixture(unittest.Seal.WithResult(&block1Receipt.ExecutionResult))
  1577  		block3 := unittest.BlockWithParentFixture(block2.Header)
  1578  		block3.SetPayload(flow.Payload{
  1579  			Seals: []*flow.Seal{block1Seal},
  1580  		})
  1581  
  1582  		sealValidator := &mockmodule.SealValidator{}
  1583  		sealValidator.On("Validate", mock.Anything).
  1584  			Return(func(candidate *flow.Block) *flow.Seal {
  1585  				if candidate.ID() == block3.ID() {
  1586  					return nil
  1587  				}
  1588  				seal, _ := seals.HighestInFork(candidate.Header.ParentID)
  1589  				return seal
  1590  			}, func(candidate *flow.Block) error {
  1591  				if candidate.ID() == block3.ID() {
  1592  					return engine.NewInvalidInputError("")
  1593  				}
  1594  				_, err := seals.HighestInFork(candidate.Header.ParentID)
  1595  				return err
  1596  			}).
  1597  			Times(3)
  1598  
  1599  		fullState, err := protocol.NewFullConsensusState(state, index, payloads, tracer, consumer,
  1600  			util.MockBlockTimer(), util.MockReceiptValidator(), sealValidator)
  1601  		require.NoError(t, err)
  1602  
  1603  		err = fullState.Extend(context.Background(), block1)
  1604  		require.NoError(t, err)
  1605  		err = fullState.Extend(context.Background(), block2)
  1606  		require.NoError(t, err)
  1607  		err = fullState.Extend(context.Background(), block3)
  1608  
  1609  		sealValidator.AssertExpectations(t)
  1610  		require.Error(t, err)
  1611  		require.True(t, st.IsInvalidExtensionError(err))
  1612  	})
  1613  }
  1614  
  1615  func TestHeaderExtendValid(t *testing.T) {
  1616  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1617  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1618  		head, err := rootSnapshot.Head()
  1619  		require.NoError(t, err)
  1620  		_, seal, err := rootSnapshot.SealedResult()
  1621  		require.NoError(t, err)
  1622  
  1623  		extend := unittest.BlockWithParentFixture(head)
  1624  		extend.SetPayload(flow.EmptyPayload())
  1625  
  1626  		err = state.Extend(context.Background(), extend)
  1627  		require.NoError(t, err)
  1628  
  1629  		finalCommit, err := state.Final().Commit()
  1630  		require.NoError(t, err)
  1631  		require.Equal(t, seal.FinalState, finalCommit)
  1632  	})
  1633  }
  1634  
  1635  func TestHeaderExtendMissingParent(t *testing.T) {
  1636  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1637  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1638  		extend := unittest.BlockFixture()
  1639  		extend.Payload.Guarantees = nil
  1640  		extend.Payload.Seals = nil
  1641  		extend.Header.Height = 2
  1642  		extend.Header.View = 2
  1643  		extend.Header.ParentID = unittest.BlockFixture().ID()
  1644  		extend.Header.PayloadHash = extend.Payload.Hash()
  1645  
  1646  		err := state.Extend(context.Background(), &extend)
  1647  		require.Error(t, err)
  1648  		require.True(t, st.IsInvalidExtensionError(err), err)
  1649  
  1650  		// verify seal not indexed
  1651  		var sealID flow.Identifier
  1652  		err = db.View(operation.LookupLatestSealAtBlock(extend.ID(), &sealID))
  1653  		require.Error(t, err)
  1654  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
  1655  	})
  1656  }
  1657  
  1658  func TestHeaderExtendHeightTooSmall(t *testing.T) {
  1659  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1660  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1661  		head, err := rootSnapshot.Head()
  1662  		require.NoError(t, err)
  1663  
  1664  		block1 := unittest.BlockWithParentFixture(head)
  1665  		err = state.Extend(context.Background(), block1)
  1666  		require.NoError(t, err)
  1667  
  1668  		// create another block that points to the previous block `extend` as parent
  1669  		// but has _same_ height as parent. This violates the condition that a child's
  1670  		// height must increment the parent's height by one, i.e. it should be rejected
  1671  		// by the follower right away
  1672  		block2 := unittest.BlockWithParentFixture(block1.Header)
  1673  		block2.Header.Height = block1.Header.Height
  1674  
  1675  		err = state.Extend(context.Background(), block2)
  1676  		require.Error(t, err)
  1677  
  1678  		// verify seal not indexed
  1679  		var sealID flow.Identifier
  1680  		err = db.View(operation.LookupLatestSealAtBlock(block2.ID(), &sealID))
  1681  		require.Error(t, err)
  1682  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
  1683  	})
  1684  }
  1685  
  1686  func TestHeaderExtendHeightTooLarge(t *testing.T) {
  1687  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1688  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1689  		head, err := rootSnapshot.Head()
  1690  		require.NoError(t, err)
  1691  
  1692  		block := unittest.BlockWithParentFixture(head)
  1693  		block.SetPayload(flow.EmptyPayload())
  1694  		// set an invalid height
  1695  		block.Header.Height = head.Height + 2
  1696  
  1697  		err = state.Extend(context.Background(), block)
  1698  		require.Error(t, err)
  1699  	})
  1700  }
  1701  
  1702  func TestHeaderExtendBlockNotConnected(t *testing.T) {
  1703  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1704  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1705  		head, err := rootSnapshot.Head()
  1706  		require.NoError(t, err)
  1707  
  1708  		// add 2 blocks, where:
  1709  		// first block is added and then finalized;
  1710  		// second block is a sibling to the finalized block
  1711  		// The Follower should reject this block as an outdated chain extension
  1712  		block1 := unittest.BlockWithParentFixture(head)
  1713  		err = state.Extend(context.Background(), block1)
  1714  		require.NoError(t, err)
  1715  
  1716  		err = state.Finalize(context.Background(), block1.ID())
  1717  		require.NoError(t, err)
  1718  
  1719  		// create a fork at view/height 1 and try to connect it to root
  1720  		block2 := unittest.BlockWithParentFixture(head)
  1721  		err = state.Extend(context.Background(), block2)
  1722  		require.Error(t, err)
  1723  		require.True(t, st.IsOutdatedExtensionError(err), err)
  1724  
  1725  		// verify seal not indexed
  1726  		var sealID flow.Identifier
  1727  		err = db.View(operation.LookupLatestSealAtBlock(block2.ID(), &sealID))
  1728  		require.Error(t, err)
  1729  		require.True(t, errors.Is(err, stoerr.ErrNotFound), err)
  1730  	})
  1731  }
  1732  
  1733  func TestHeaderExtendHighestSeal(t *testing.T) {
  1734  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1735  	head, err := rootSnapshot.Head()
  1736  	require.NoError(t, err)
  1737  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1738  		// create block2 and block3
  1739  		block2 := unittest.BlockWithParentFixture(head)
  1740  		block2.SetPayload(flow.EmptyPayload())
  1741  		err := state.Extend(context.Background(), block2)
  1742  		require.NoError(t, err)
  1743  
  1744  		block3 := unittest.BlockWithParentFixture(block2.Header)
  1745  		block3.SetPayload(flow.EmptyPayload())
  1746  		err = state.Extend(context.Background(), block3)
  1747  		require.NoError(t, err)
  1748  
  1749  		// create seals for block2 and block3
  1750  		seal2 := unittest.Seal.Fixture(
  1751  			unittest.Seal.WithBlockID(block2.ID()),
  1752  		)
  1753  		seal3 := unittest.Seal.Fixture(
  1754  			unittest.Seal.WithBlockID(block3.ID()),
  1755  		)
  1756  
  1757  		// include the seals in block4
  1758  		block4 := unittest.BlockWithParentFixture(block3.Header)
  1759  		block4.SetPayload(flow.Payload{
  1760  			// placing seals in the reversed order to test
  1761  			// Extend will pick the highest sealed block
  1762  			Seals:      []*flow.Seal{seal3, seal2},
  1763  			Guarantees: nil,
  1764  		})
  1765  		err = state.Extend(context.Background(), block4)
  1766  		require.NoError(t, err)
  1767  
  1768  		finalCommit, err := state.AtBlockID(block4.ID()).Commit()
  1769  		require.NoError(t, err)
  1770  		require.Equal(t, seal3.FinalState, finalCommit)
  1771  	})
  1772  }
  1773  
  1774  // TestExtendInvalidGuarantee checks if Extend method will reject invalid blocks that contain
  1775  // guarantees with invalid guarantors
  1776  func TestExtendInvalidGuarantee(t *testing.T) {
  1777  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1778  	util.RunWithFullProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.MutableState) {
  1779  		// create a valid block
  1780  		head, err := rootSnapshot.Head()
  1781  		require.NoError(t, err)
  1782  
  1783  		cluster, err := unittest.SnapshotClusterByIndex(rootSnapshot, 0)
  1784  		require.NoError(t, err)
  1785  
  1786  		// prepare for a valid guarantor signer indices to be used in the valid block
  1787  		all := cluster.Members().NodeIDs()
  1788  		validSignerIndices, err := signature.EncodeSignersToIndices(all, all)
  1789  		require.NoError(t, err)
  1790  
  1791  		block := unittest.BlockWithParentFixture(head)
  1792  		payload := flow.EmptyPayload()
  1793  		payload.Guarantees = []*flow.CollectionGuarantee{
  1794  			{
  1795  				ChainID:          cluster.ChainID(),
  1796  				ReferenceBlockID: head.ID(),
  1797  				SignerIndices:    validSignerIndices,
  1798  			},
  1799  		}
  1800  
  1801  		// now the valid block has a guarantee in the payload with valid signer indices.
  1802  		block.SetPayload(payload)
  1803  
  1804  		// check Extend should accept this valid block
  1805  		err = state.Extend(context.Background(), block)
  1806  		require.NoError(t, err)
  1807  
  1808  		// now the guarantee has invalid signer indices: the checksum should have 4 bytes, but it only has 1
  1809  		payload.Guarantees[0].SignerIndices = []byte{byte(1)}
  1810  		err = state.Extend(context.Background(), block)
  1811  		require.Error(t, err)
  1812  		require.True(t, signature.IsInvalidSignerIndicesError(err), err)
  1813  		require.True(t, errors.Is(err, signature.ErrInvalidChecksum), err)
  1814  		require.True(t, st.IsInvalidExtensionError(err), err)
  1815  
  1816  		// now the guarantee has invalid signer indices: the checksum should have 4 bytes, but it only has 1
  1817  		checksumMismatch := make([]byte, len(validSignerIndices))
  1818  		copy(checksumMismatch, validSignerIndices)
  1819  		checksumMismatch[0] = byte(1)
  1820  		if checksumMismatch[0] == validSignerIndices[0] {
  1821  			checksumMismatch[0] = byte(2)
  1822  		}
  1823  		payload.Guarantees[0].SignerIndices = checksumMismatch
  1824  		err = state.Extend(context.Background(), block)
  1825  		require.Error(t, err)
  1826  		require.True(t, signature.IsInvalidSignerIndicesError(err), err)
  1827  		require.True(t, errors.Is(err, signature.ErrInvalidChecksum), err)
  1828  		require.True(t, st.IsInvalidExtensionError(err), err)
  1829  
  1830  		// let's test even if the checksum is correct, but signer indices is still wrong because the tailing are not 0,
  1831  		// then the block should still be rejected.
  1832  		wrongTailing := make([]byte, len(validSignerIndices))
  1833  		copy(wrongTailing, validSignerIndices)
  1834  		wrongTailing[len(wrongTailing)-1] = byte(255)
  1835  
  1836  		payload.Guarantees[0].SignerIndices = wrongTailing
  1837  		err = state.Extend(context.Background(), block)
  1838  		require.Error(t, err)
  1839  		require.True(t, signature.IsInvalidSignerIndicesError(err), err)
  1840  		require.True(t, errors.Is(err, signature.ErrIllegallyPaddedBitVector), err)
  1841  		require.True(t, st.IsInvalidExtensionError(err), err)
  1842  
  1843  		// test imcompatible bit vector length
  1844  		wrongbitVectorLength := validSignerIndices[0 : len(validSignerIndices)-1]
  1845  		payload.Guarantees[0].SignerIndices = wrongbitVectorLength
  1846  		err = state.Extend(context.Background(), block)
  1847  		require.Error(t, err)
  1848  		require.True(t, signature.IsInvalidSignerIndicesError(err), err)
  1849  		require.True(t, errors.Is(err, signature.ErrIncompatibleBitVectorLength), err)
  1850  		require.True(t, st.IsInvalidExtensionError(err), err)
  1851  
  1852  		// revert back to good value
  1853  		payload.Guarantees[0].SignerIndices = validSignerIndices
  1854  
  1855  		// test the ReferenceBlockID is not found
  1856  		payload.Guarantees[0].ReferenceBlockID = flow.ZeroID
  1857  		err = state.Extend(context.Background(), block)
  1858  		require.Error(t, err)
  1859  		require.True(t, errors.Is(err, storage.ErrNotFound), err)
  1860  		require.True(t, st.IsInvalidExtensionError(err), err)
  1861  
  1862  		// revert back to good value
  1863  		payload.Guarantees[0].ReferenceBlockID = head.ID()
  1864  
  1865  		// TODO: test the guarantee has bad reference block ID that would return ErrEpochNotCommitted
  1866  		// this case is not easy to create, since the test case has no such block yet.
  1867  		// we need to refactor the MutableState to add a guaranteeValidator, so that we can mock it and
  1868  		// return the ErrEpochNotCommitted for testing
  1869  
  1870  		// test the guarantee has wrong chain ID, and should return ErrClusterNotFound
  1871  		payload.Guarantees[0].ChainID = flow.ChainID("some_bad_chain_ID")
  1872  		err = state.Extend(context.Background(), block)
  1873  		require.Error(t, err)
  1874  		require.True(t, errors.Is(err, realprotocol.ErrClusterNotFound), err)
  1875  		require.True(t, st.IsInvalidExtensionError(err), err)
  1876  	})
  1877  }
  1878  
  1879  func TestMakeValid(t *testing.T) {
  1880  	t.Run("should trigger BlockProcessable with parent block", func(t *testing.T) {
  1881  		consumer := &mockprotocol.Consumer{}
  1882  		rootSnapshot := unittest.RootSnapshotFixture(participants)
  1883  		head, err := rootSnapshot.Head()
  1884  		require.NoError(t, err)
  1885  		util.RunWithFullProtocolStateAndConsumer(t, rootSnapshot, consumer, func(db *badger.DB, state *protocol.MutableState) {
  1886  			// create block2 and block3
  1887  			block2 := unittest.BlockWithParentFixture(head)
  1888  			block2.SetPayload(flow.EmptyPayload())
  1889  			err := state.Extend(context.Background(), block2)
  1890  			require.NoError(t, err)
  1891  
  1892  			block3 := unittest.BlockWithParentFixture(block2.Header)
  1893  			block3.SetPayload(flow.EmptyPayload())
  1894  			err = state.Extend(context.Background(), block3)
  1895  			require.NoError(t, err)
  1896  
  1897  			consumer.On("BlockProcessable", mock.Anything).Return()
  1898  
  1899  			// make valid on block2
  1900  			err = state.MarkValid(block2.ID())
  1901  			require.NoError(t, err)
  1902  
  1903  			// because the parent block is the root block,
  1904  			// BlockProcessable is not triggered on root block.
  1905  			consumer.AssertNotCalled(t, "BlockProcessable")
  1906  
  1907  			err = state.MarkValid(block3.ID())
  1908  			require.NoError(t, err)
  1909  
  1910  			// because the parent is not a root block, BlockProcessable event should be emitted
  1911  			// block3's parent is block2
  1912  			consumer.AssertCalled(t, "BlockProcessable", block2.Header)
  1913  		})
  1914  	})
  1915  }
  1916  
  1917  // If block B is finalized and contains a seal for block A, then A is the last sealed block
  1918  func TestSealed(t *testing.T) {
  1919  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1920  	util.RunWithFollowerProtocolState(t, rootSnapshot, func(db *badger.DB, state *protocol.FollowerState) {
  1921  		head, err := rootSnapshot.Head()
  1922  		require.NoError(t, err)
  1923  
  1924  		// block 1 will be sealed
  1925  		block1 := unittest.BlockWithParentFixture(head)
  1926  		err = state.Extend(context.Background(), block1)
  1927  		require.NoError(t, err)
  1928  		err = state.Finalize(context.Background(), block1.ID())
  1929  		require.NoError(t, err)
  1930  
  1931  		receipt1, seal1 := unittest.ReceiptAndSealForBlock(block1)
  1932  
  1933  		// block 2 contains receipt for block 1
  1934  		block2 := unittest.BlockWithParentFixture(block1.Header)
  1935  		block2.SetPayload(unittest.PayloadFixture(unittest.WithReceipts(receipt1)))
  1936  		err = state.Extend(context.Background(), block2)
  1937  		require.NoError(t, err)
  1938  		err = state.Finalize(context.Background(), block2.ID())
  1939  		require.NoError(t, err)
  1940  
  1941  		// block 3 contains seal for block 1
  1942  		block3 := unittest.BlockWithParentFixture(block2.Header)
  1943  		block3.SetPayload(flow.Payload{
  1944  			Seals: []*flow.Seal{seal1},
  1945  		})
  1946  		err = state.Extend(context.Background(), block3)
  1947  		require.NoError(t, err)
  1948  		err = state.Finalize(context.Background(), block3.ID())
  1949  		require.NoError(t, err)
  1950  
  1951  		sealed, err := state.Sealed().Head()
  1952  		require.NoError(t, err)
  1953  		require.Equal(t, block1.ID(), sealed.ID())
  1954  	})
  1955  }
  1956  
  1957  // Test that when adding a block to database, there are only two cases at any point of time:
  1958  // 1) neither the block header, nor the payload index exist in database
  1959  // 2) both the block header and the payload index can be found in database
  1960  // A non atomic bug would be: header is found in DB, but payload index is not found
  1961  func TestCacheAtomicity(t *testing.T) {
  1962  	rootSnapshot := unittest.RootSnapshotFixture(participants)
  1963  	util.RunWithFollowerProtocolStateAndHeaders(t, rootSnapshot,
  1964  		func(db *badger.DB, state *protocol.FollowerState, headers storage.Headers, index storage.Index) {
  1965  			head, err := rootSnapshot.Head()
  1966  			require.NoError(t, err)
  1967  
  1968  			block := unittest.BlockWithParentFixture(head)
  1969  			blockID := block.ID()
  1970  
  1971  			// check 100 times to see if either 1) or 2) satisfies
  1972  			var wg sync.WaitGroup
  1973  			wg.Add(1)
  1974  			go func(blockID flow.Identifier) {
  1975  				for i := 0; i < 100; i++ {
  1976  					_, err := headers.ByBlockID(blockID)
  1977  					if errors.Is(err, stoerr.ErrNotFound) {
  1978  						continue
  1979  					}
  1980  					require.NoError(t, err)
  1981  
  1982  					_, err = index.ByBlockID(blockID)
  1983  					require.NoError(t, err, "found block ID, but index is missing, DB updates is non-atomic")
  1984  				}
  1985  				wg.Done()
  1986  			}(blockID)
  1987  
  1988  			// storing the block to database, which supposed to be atomic updates to headers and index,
  1989  			// both to badger database and the cache.
  1990  			err = state.Extend(context.Background(), block)
  1991  			require.NoError(t, err)
  1992  			wg.Wait()
  1993  		})
  1994  }
  1995  
  1996  // TestHeaderInvalidTimestamp tests that extending header with invalid timestamp results in sentinel error
  1997  func TestHeaderInvalidTimestamp(t *testing.T) {
  1998  	unittest.RunWithBadgerDB(t, func(db *badger.DB) {
  1999  		metrics := metrics.NewNoopCollector()
  2000  		tracer := trace.NewNoopTracer()
  2001  		headers, _, seals, index, payloads, blocks, setups, commits, statuses, results := storeutil.StorageLayer(t, db)
  2002  
  2003  		// create a event consumer to test epoch transition events
  2004  		distributor := events.NewDistributor()
  2005  		consumer := new(mockprotocol.Consumer)
  2006  		distributor.AddConsumer(consumer)
  2007  
  2008  		block, result, seal := unittest.BootstrapFixture(participants)
  2009  		qc := unittest.QuorumCertificateFixture(unittest.QCWithBlockID(block.ID()))
  2010  		rootSnapshot, err := inmem.SnapshotFromBootstrapState(block, result, seal, qc)
  2011  		require.NoError(t, err)
  2012  
  2013  		state, err := protocol.Bootstrap(metrics, db, headers, seals, results, blocks, setups, commits, statuses, rootSnapshot)
  2014  		require.NoError(t, err)
  2015  
  2016  		blockTimer := &mockprotocol.BlockTimer{}
  2017  		blockTimer.On("Validate", mock.Anything, mock.Anything).Return(realprotocol.NewInvalidBlockTimestamp(""))
  2018  
  2019  		fullState, err := protocol.NewFullConsensusState(state, index, payloads, tracer, consumer, blockTimer,
  2020  			util.MockReceiptValidator(), util.MockSealValidator(seals))
  2021  		require.NoError(t, err)
  2022  
  2023  		extend := unittest.BlockWithParentFixture(block.Header)
  2024  		extend.Payload.Guarantees = nil
  2025  		extend.Header.PayloadHash = extend.Payload.Hash()
  2026  
  2027  		err = fullState.Extend(context.Background(), extend)
  2028  		assert.Error(t, err, "a proposal with invalid timestamp has to be rejected")
  2029  		assert.True(t, st.IsInvalidExtensionError(err), "if timestamp is invalid it should return invalid block error")
  2030  	})
  2031  }
  2032  
  2033  func assertEpochEmergencyFallbackTriggered(t *testing.T, db *badger.DB) {
  2034  	var triggered bool
  2035  	err := db.View(operation.CheckEpochEmergencyFallbackTriggered(&triggered))
  2036  	require.NoError(t, err)
  2037  	assert.True(t, triggered)
  2038  }
  2039  
  2040  // mockMetricsForRootSnapshot mocks the given metrics mock object to expect all
  2041  // metrics which are set during bootstrapping and building blocks.
  2042  func mockMetricsForRootSnapshot(metricsMock *mockmodule.ComplianceMetrics, rootSnapshot *inmem.Snapshot) {
  2043  	metricsMock.On("CurrentEpochCounter", rootSnapshot.Encodable().Epochs.Current.Counter)
  2044  	metricsMock.On("CurrentEpochPhase", rootSnapshot.Encodable().Phase)
  2045  	metricsMock.On("CurrentEpochFinalView", rootSnapshot.Encodable().Epochs.Current.FinalView)
  2046  	metricsMock.On("CommittedEpochFinalView", rootSnapshot.Encodable().Epochs.Current.FinalView)
  2047  	metricsMock.On("CurrentDKGPhase1FinalView", rootSnapshot.Encodable().Epochs.Current.DKGPhase1FinalView)
  2048  	metricsMock.On("CurrentDKGPhase2FinalView", rootSnapshot.Encodable().Epochs.Current.DKGPhase2FinalView)
  2049  	metricsMock.On("CurrentDKGPhase3FinalView", rootSnapshot.Encodable().Epochs.Current.DKGPhase3FinalView)
  2050  	metricsMock.On("BlockSealed", mock.Anything)
  2051  	metricsMock.On("BlockFinalized", mock.Anything)
  2052  	metricsMock.On("FinalizedHeight", mock.Anything)
  2053  	metricsMock.On("SealedHeight", mock.Anything)
  2054  
  2055  }