github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/forks/test/finalizer_test.go (about)

     1  package test
     2  
     3  import (
     4  	"fmt"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/assert"
     8  	"github.com/stretchr/testify/mock"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/koko1123/flow-go-1/consensus/hotstuff/forks"
    12  	"github.com/koko1123/flow-go-1/consensus/hotstuff/forks/finalizer"
    13  	"github.com/koko1123/flow-go-1/consensus/hotstuff/mocks"
    14  	"github.com/koko1123/flow-go-1/consensus/hotstuff/model"
    15  	mockm "github.com/koko1123/flow-go-1/module/mock"
    16  )
    17  
    18  // denotion:
    19  // A block is denoted as [<qc_number>, <block_view_number>].
    20  // For example, [1,2] means: a block of view 2 has a QC for view 1.
    21  
    22  // receives [1,2], [2,3], [3,4], [4,5],
    23  // it should finalize [1,2], it should lock [2,3].
    24  func TestLocked(t *testing.T) {
    25  	builder := NewBlockBuilder()
    26  	builder.Add(1, 2) // creates a block of view 2, with a QC of view 1
    27  	builder.Add(2, 3)
    28  	builder.Add(3, 4)
    29  	builder.Add(4, 5)
    30  
    31  	blocks, err := builder.Blocks()
    32  	require.Nil(t, err)
    33  
    34  	fin, _, _ := newFinalizer(t)
    35  
    36  	err = addBlocksToFinalizer(fin, blocks)
    37  	require.Nil(t, err)
    38  
    39  	assertFinalizedBlock(t, fin, 1, 2) // check if the finalized block has view 1, and its QC is 2
    40  	assertTheLockedBlock(t, fin, 2, 3)
    41  	// ^^^ the reason it's not called "assertLockedBlock" is to match
    42  	// its length with assertFinalizedBlock in order to align their arguments
    43  }
    44  
    45  // receives [1,2], [2,3], [3,4], [4,5], [4,6], [6,8]
    46  // it should finalize [1,2], it should lock [3,4].
    47  func TestLocked2(t *testing.T) {
    48  	builder := NewBlockBuilder()
    49  	builder.Add(1, 2)
    50  	builder.Add(2, 3)
    51  	builder.Add(3, 4)
    52  	builder.Add(4, 5)
    53  	builder.Add(4, 6)
    54  	builder.Add(6, 8)
    55  
    56  	blocks, err := builder.Blocks()
    57  	require.Nil(t, err)
    58  
    59  	fin, _, _ := newFinalizer(t)
    60  
    61  	err = addBlocksToFinalizer(fin, blocks)
    62  	require.Nil(t, err)
    63  
    64  	assertFinalizedBlock(t, fin, 1, 2)
    65  	assertTheLockedBlock(t, fin, 3, 4)
    66  }
    67  
    68  // receives [1,2], [2,3], [3,4], [4,5], [4,6], [6,8], [8,10]
    69  // it should finalize [1,2], it should lock [4,6].
    70  func TestLocked3(t *testing.T) {
    71  	builder := NewBlockBuilder()
    72  	builder.Add(1, 2)
    73  	builder.Add(2, 3)
    74  	builder.Add(3, 4)
    75  	builder.Add(4, 5)
    76  	builder.Add(4, 6)
    77  	builder.Add(6, 8)
    78  	builder.Add(8, 10)
    79  
    80  	blocks, err := builder.Blocks()
    81  	require.Nil(t, err)
    82  
    83  	fin, _, _ := newFinalizer(t)
    84  
    85  	err = addBlocksToFinalizer(fin, blocks)
    86  	require.Nil(t, err)
    87  
    88  	assertFinalizedBlock(t, fin, 1, 2)
    89  	assertTheLockedBlock(t, fin, 4, 6)
    90  }
    91  
    92  // receives [1,2], [2,3], [3,4], [4,5], [5,6]
    93  // it should finalize [2,3], it should lock [3,4]
    94  func TestFinalizedDirect3builder(t *testing.T) {
    95  	builder := NewBlockBuilder()
    96  	builder.Add(1, 2)
    97  	builder.Add(2, 3)
    98  	builder.Add(3, 4)
    99  	builder.Add(4, 5)
   100  	builder.Add(5, 6)
   101  
   102  	blocks, err := builder.Blocks()
   103  	require.Nil(t, err)
   104  
   105  	fin, _, _ := newFinalizer(t)
   106  
   107  	err = addBlocksToFinalizer(fin, blocks)
   108  	require.Nil(t, err)
   109  
   110  	assertFinalizedBlock(t, fin, 2, 3)
   111  	assertTheLockedBlock(t, fin, 3, 4)
   112  }
   113  
   114  // receives [1,2], [2,3], [3,4], [4,5], [5,6], [6,7], [7,8], [8, 9]
   115  // it should finalize [5,6], it should lock [6,7]
   116  func TestFinalizedDirect3builder2(t *testing.T) {
   117  	builder := NewBlockBuilder()
   118  	builder.Add(1, 2)
   119  	builder.Add(2, 3)
   120  	builder.Add(3, 4)
   121  	builder.Add(4, 5)
   122  	builder.Add(5, 6)
   123  	builder.Add(6, 7)
   124  	builder.Add(7, 8)
   125  	builder.Add(8, 9)
   126  
   127  	blocks, err := builder.Blocks()
   128  	require.Nil(t, err)
   129  
   130  	fin, _, _ := newFinalizer(t)
   131  
   132  	err = addBlocksToFinalizer(fin, blocks)
   133  	require.Nil(t, err)
   134  
   135  	assertFinalizedBlock(t, fin, 5, 6)
   136  	assertTheLockedBlock(t, fin, 6, 7)
   137  }
   138  
   139  // receives [1,2], [2,3], [3,4], [4,5], [5,7],
   140  // it should finalize [2,3], it should lock [3,4]
   141  func TestFinalizedDirect2builderPlus1builder(t *testing.T) {
   142  	builder := NewBlockBuilder()
   143  	builder.Add(1, 2)
   144  	builder.Add(2, 3)
   145  	builder.Add(3, 4)
   146  	builder.Add(4, 5)
   147  	builder.Add(5, 7)
   148  
   149  	blocks, err := builder.Blocks()
   150  	require.Nil(t, err)
   151  
   152  	fin, _, _ := newFinalizer(t)
   153  
   154  	err = addBlocksToFinalizer(fin, blocks)
   155  	require.Nil(t, err)
   156  
   157  	assertFinalizedBlock(t, fin, 2, 3)
   158  	assertTheLockedBlock(t, fin, 3, 4)
   159  }
   160  
   161  // receives [1,2], [2,3], [3,4], [4,5], [4,6],
   162  // it should finalize [1,2], it should lock [2,3]
   163  func TestUnfinalized(t *testing.T) {
   164  	builder := NewBlockBuilder()
   165  	builder.Add(1, 2)
   166  	builder.Add(2, 3)
   167  	builder.Add(3, 4)
   168  	builder.Add(4, 5)
   169  	builder.Add(4, 6)
   170  
   171  	blocks, err := builder.Blocks()
   172  	require.Nil(t, err)
   173  
   174  	fin, _, _ := newFinalizer(t)
   175  
   176  	err = addBlocksToFinalizer(fin, blocks)
   177  	require.Nil(t, err)
   178  
   179  	assertFinalizedBlock(t, fin, 1, 2)
   180  	assertTheLockedBlock(t, fin, 2, 3)
   181  }
   182  
   183  // receives [1,2], [2,3], [3,4], [4,5], [4,7],
   184  // it should finalize [1,2], it should lock [2,3]
   185  func TestUnfinalized2(t *testing.T) {
   186  	builder := NewBlockBuilder()
   187  	builder.Add(1, 2)
   188  	builder.Add(2, 3)
   189  	builder.Add(3, 4)
   190  	builder.Add(4, 5)
   191  	builder.Add(4, 7)
   192  
   193  	blocks, err := builder.Blocks()
   194  	require.Nil(t, err)
   195  
   196  	fin, _, _ := newFinalizer(t)
   197  
   198  	err = addBlocksToFinalizer(fin, blocks)
   199  	require.Nil(t, err)
   200  
   201  	assertFinalizedBlock(t, fin, 1, 2)
   202  	assertTheLockedBlock(t, fin, 2, 3)
   203  }
   204  
   205  // Tolerable Forks that extend from locked block (1: might change locked block, 2: not change locked block)
   206  // receives [1,2], [2,3], [3,4], [4,5], [3,6], [6,7], [7,8]
   207  // it should finalize [1,2], it should lock [3,6]
   208  func TestTolerableForksExtendsFromLockedBlock(t *testing.T) {
   209  	builder := NewBlockBuilder()
   210  	builder.Add(1, 2)
   211  	builder.Add(2, 3)
   212  	builder.Add(3, 4)
   213  	builder.Add(4, 5)
   214  	builder.Add(3, 6)
   215  	builder.Add(6, 7)
   216  	builder.Add(7, 8)
   217  
   218  	blocks, err := builder.Blocks()
   219  	require.Nil(t, err)
   220  
   221  	fin, _, _ := newFinalizer(t)
   222  
   223  	err = addBlocksToFinalizer(fin, blocks)
   224  	require.Nil(t, err)
   225  
   226  	assertFinalizedBlock(t, fin, 1, 2)
   227  	assertTheLockedBlock(t, fin, 3, 6)
   228  }
   229  
   230  // receives [1,2], [2,3], [3,4], [4,5], [4,6], [6,7], [7,8]
   231  // it should finalize [1,2], it should lock [4,6]
   232  func TestTolerableForksExtendsFromLockedBlock2(t *testing.T) {
   233  	builder := NewBlockBuilder()
   234  	builder.Add(1, 2)
   235  	builder.Add(2, 3)
   236  	builder.Add(3, 4)
   237  	builder.Add(4, 5)
   238  	builder.Add(4, 6)
   239  	builder.Add(6, 7)
   240  	builder.Add(7, 8)
   241  
   242  	blocks, err := builder.Blocks()
   243  	require.Nil(t, err)
   244  
   245  	fin, _, _ := newFinalizer(t)
   246  
   247  	err = addBlocksToFinalizer(fin, blocks)
   248  	require.Nil(t, err)
   249  
   250  	assertFinalizedBlock(t, fin, 1, 2)
   251  	assertTheLockedBlock(t, fin, 4, 6)
   252  }
   253  
   254  // receives [1,2], [2,3], [3,4], [4,5], [3,6], [6,7], [7,8], [8,9]
   255  // it should finalize [3,6], it should lock [6,7]
   256  func TestTolerableForksExtendsFromLockedBlock3(t *testing.T) {
   257  	builder := NewBlockBuilder()
   258  	builder.Add(1, 2)
   259  	builder.Add(2, 3)
   260  	builder.Add(3, 4)
   261  	builder.Add(4, 5)
   262  	builder.Add(3, 6)
   263  	builder.Add(6, 7)
   264  	builder.Add(7, 8)
   265  	builder.Add(8, 9)
   266  
   267  	blocks, err := builder.Blocks()
   268  	require.Nil(t, err)
   269  
   270  	fin, _, _ := newFinalizer(t)
   271  
   272  	err = addBlocksToFinalizer(fin, blocks)
   273  	require.Nil(t, err)
   274  
   275  	assertFinalizedBlock(t, fin, 3, 6)
   276  	assertTheLockedBlock(t, fin, 6, 7)
   277  }
   278  
   279  // receives [1,2], [2,3], [3,4], [4,5], [4,6], [6,7], [7,8], [8,9]
   280  // it should finalize [4,6], it should lock [6,7]
   281  func TestTolerableForksExtendsFromLockedBlock4(t *testing.T) {
   282  	builder := NewBlockBuilder()
   283  	builder.Add(1, 2)
   284  	builder.Add(2, 3)
   285  	builder.Add(3, 4)
   286  	builder.Add(4, 5)
   287  	builder.Add(4, 6)
   288  	builder.Add(6, 7)
   289  	builder.Add(7, 8)
   290  	builder.Add(8, 9)
   291  
   292  	blocks, err := builder.Blocks()
   293  	require.Nil(t, err)
   294  
   295  	fin, _, _ := newFinalizer(t)
   296  
   297  	err = addBlocksToFinalizer(fin, blocks)
   298  	require.Nil(t, err)
   299  
   300  	assertFinalizedBlock(t, fin, 4, 6)
   301  	assertTheLockedBlock(t, fin, 6, 7)
   302  }
   303  
   304  // receives [1,2], [2,3], [3,4], [4,5], [4,6], [6,7], [7,8], [8,10]
   305  // it should finalize [3,6], it should lock [6,7]
   306  func TestTolerableForksExtendsFromLockedBlock5(t *testing.T) {
   307  	builder := NewBlockBuilder()
   308  	builder.Add(1, 2)
   309  	builder.Add(2, 3)
   310  	builder.Add(3, 4)
   311  	builder.Add(4, 5)
   312  	builder.Add(3, 6)
   313  	builder.Add(6, 7)
   314  	builder.Add(7, 8)
   315  	builder.Add(8, 10)
   316  
   317  	blocks, err := builder.Blocks()
   318  	require.Nil(t, err)
   319  
   320  	fin, _, _ := newFinalizer(t)
   321  
   322  	err = addBlocksToFinalizer(fin, blocks)
   323  	require.Nil(t, err)
   324  
   325  	assertFinalizedBlock(t, fin, 3, 6)
   326  	assertTheLockedBlock(t, fin, 6, 7)
   327  }
   328  
   329  // receives [1,2], [2,3], [3,4], [4,5], [2,6]
   330  // it should finalize [1,2], it should lock [2,3]
   331  func TestTolerableForksNotExtendsFromLockedBlock(t *testing.T) {
   332  	builder := NewBlockBuilder()
   333  	builder.Add(1, 2)
   334  	builder.Add(2, 3)
   335  	builder.Add(3, 4)
   336  	builder.Add(4, 5)
   337  	builder.Add(2, 6)
   338  
   339  	blocks, err := builder.Blocks()
   340  	require.Nil(t, err)
   341  
   342  	fin, _, _ := newFinalizer(t)
   343  
   344  	err = addBlocksToFinalizer(fin, blocks)
   345  	require.Nil(t, err)
   346  
   347  	assertFinalizedBlock(t, fin, 1, 2)
   348  	assertTheLockedBlock(t, fin, 2, 3)
   349  }
   350  
   351  // receives [1,2], [2,3], [3,4], [4,5], [2,6], [5,6]
   352  // it should finalize [2,3], it should lock [3,4], because [2,6] is replaced by [5,6]
   353  func TestTolerableForksNotExtendsFromLockedBlock2(t *testing.T) {
   354  	builder := NewBlockBuilder()
   355  	builder.Add(1, 2)
   356  	builder.Add(2, 3)
   357  	builder.Add(3, 4)
   358  	builder.Add(4, 5)
   359  	builder.Add(2, 6)
   360  	builder.Add(5, 6)
   361  
   362  	blocks, err := builder.Blocks()
   363  	require.Nil(t, err)
   364  
   365  	fin, notifier, _ := newFinalizer(t)
   366  	notifier.On("OnDoubleProposeDetected", blocks[5], blocks[4]).Return(nil)
   367  
   368  	err = addBlocksToFinalizer(fin, blocks)
   369  	require.Nil(t, err)
   370  
   371  	assertFinalizedBlock(t, fin, 2, 3)
   372  	assertTheLockedBlock(t, fin, 3, 4)
   373  	notifier.AssertExpectations(t)
   374  }
   375  
   376  // receives [1,2], [2,3], [3,4], [4,5], [2,6], [6,7]
   377  // it should finalize [1,2], it should lock [2,3]
   378  func TestTolerableForksNotExtendsFromLockedBlock3(t *testing.T) {
   379  	builder := NewBlockBuilder()
   380  	builder.Add(1, 2)
   381  	builder.Add(2, 3)
   382  	builder.Add(3, 4)
   383  	builder.Add(4, 5)
   384  	builder.Add(2, 6)
   385  	builder.Add(6, 7)
   386  
   387  	blocks, err := builder.Blocks()
   388  	require.Nil(t, err)
   389  
   390  	fin, _, _ := newFinalizer(t)
   391  
   392  	err = addBlocksToFinalizer(fin, blocks)
   393  	require.Nil(t, err)
   394  
   395  	assertFinalizedBlock(t, fin, 1, 2)
   396  	assertTheLockedBlock(t, fin, 2, 3)
   397  }
   398  
   399  // receives [1,2], [2,3], [3,4], [4,5], [2,6], [6,7],[7,8]
   400  // it should finalize [1,2], it should lock [2,6]
   401  func TestTolerableForksNotExtendsFromLockedBlock4(t *testing.T) {
   402  	builder := NewBlockBuilder()
   403  	builder.Add(1, 2)
   404  	builder.Add(2, 3)
   405  	builder.Add(3, 4)
   406  	builder.Add(4, 5)
   407  	builder.Add(2, 6)
   408  	builder.Add(6, 7)
   409  	builder.Add(7, 8)
   410  
   411  	blocks, err := builder.Blocks()
   412  	require.Nil(t, err)
   413  
   414  	fin, _, _ := newFinalizer(t)
   415  
   416  	err = addBlocksToFinalizer(fin, blocks)
   417  	require.Nil(t, err)
   418  
   419  	assertFinalizedBlock(t, fin, 1, 2)
   420  	assertTheLockedBlock(t, fin, 2, 6)
   421  }
   422  
   423  // receives [1,2], [2,3], [2,3], [3,4], [3,4], [4,5], [4,5], [5,6], [5,6]
   424  // it should finalize [2,3], it should lock [3,4]
   425  func TestDuplication(t *testing.T) {
   426  	builder := NewBlockBuilder()
   427  	builder.Add(1, 2)
   428  	builder.Add(2, 3)
   429  	builder.Add(3, 4)
   430  	builder.Add(2, 3)
   431  	builder.Add(3, 4)
   432  	builder.Add(4, 5)
   433  	builder.Add(5, 6)
   434  	builder.Add(4, 5)
   435  	builder.Add(5, 6)
   436  
   437  	blocks, err := builder.Blocks()
   438  	require.Nil(t, err)
   439  
   440  	fin, _, _ := newFinalizer(t)
   441  
   442  	err = addBlocksToFinalizer(fin, blocks)
   443  	require.Nil(t, err)
   444  
   445  	assertFinalizedBlock(t, fin, 2, 3)
   446  	assertTheLockedBlock(t, fin, 3, 4)
   447  }
   448  
   449  // receives [1,2], [2,3], [3,4], [4,5], [1,6]
   450  // it should finalize [1,2], it should lock [2,3]
   451  func TestIgnoreBlocksBelowFinalizedView(t *testing.T) {
   452  	builder := NewBlockBuilder()
   453  	builder.Add(1, 2)
   454  	builder.Add(2, 3)
   455  	builder.Add(3, 4)
   456  	builder.Add(4, 5)
   457  	builder.Add(1, 6)
   458  
   459  	blocks, err := builder.Blocks()
   460  	require.Nil(t, err)
   461  
   462  	fin, _, _ := newFinalizer(t)
   463  
   464  	err = addBlocksToFinalizer(fin, blocks)
   465  	require.Nil(t, err)
   466  
   467  	assertFinalizedBlock(t, fin, 1, 2)
   468  	assertTheLockedBlock(t, fin, 2, 3)
   469  }
   470  
   471  // receives [1,2], [2,3], [3,4], [4,5], [3,6], [5,6'].
   472  // it should finalize block [2,3], and emits an DoubleProposal event with ([3,6], [5,6'])
   473  func TestDoubleProposal(t *testing.T) {
   474  	builder := NewBlockBuilder()
   475  	builder.Add(1, 2)
   476  	builder.Add(2, 3)
   477  	builder.Add(3, 4)
   478  	builder.Add(4, 5)
   479  	builder.Add(3, 6)
   480  	builder.AddVersioned(5, 6, 0, 1)
   481  
   482  	blocks, err := builder.Blocks()
   483  	require.Nil(t, err)
   484  
   485  	fin, notifier, _ := newFinalizer(t)
   486  	notifier.On("OnDoubleProposeDetected", blocks[5], blocks[4]).Return(nil)
   487  
   488  	err = addBlocksToFinalizer(fin, blocks)
   489  	require.Nil(t, err)
   490  
   491  	assertFinalizedBlock(t, fin, 2, 3)
   492  	notifier.AssertExpectations(t)
   493  }
   494  
   495  // receives [1,2], [2,3], [3,4], [3,4'], [4,5], [4',6].
   496  // it should return fatal error, because conflicting blocks 4 and 4'
   497  // both received enough votes for QC
   498  func TestUntolerableForks(t *testing.T) {
   499  	builder := NewBlockBuilder()
   500  
   501  	builder.Add(1, 2)
   502  	builder.Add(2, 3)
   503  	builder.Add(3, 4)
   504  	builder.AddVersioned(3, 4, 0, 1) // make a special view 4
   505  	builder.Add(4, 5)
   506  	builder.AddVersioned(4, 6, 1, 0) // make a special view 6 extends from special view 4
   507  
   508  	blocks, err := builder.Blocks()
   509  	require.Nil(t, err)
   510  
   511  	fin, notifier, _ := newFinalizer(t)
   512  	notifier.On("OnDoubleProposeDetected", blocks[3], blocks[2]).Return(nil)
   513  
   514  	err = addBlocksToFinalizer(fin, blocks)
   515  	require.NotNil(t, err)
   516  	notifier.AssertExpectations(t)
   517  }
   518  
   519  // receives [1,2], [2,3], [2,7], [3,4], [4,5], [5,6], [7,8], [8,9], [9,10]
   520  // It should return fatal error, because a fork below locked block got finalized
   521  func TestUntolerableForks2(t *testing.T) {
   522  	builder := NewBlockBuilder()
   523  	builder.Add(1, 2)
   524  	builder.Add(2, 3)
   525  	builder.Add(3, 4)
   526  	builder.Add(4, 5)
   527  	builder.Add(5, 6) // this finalizes (2,3)
   528  	builder.Add(2, 7)
   529  	builder.Add(7, 8)
   530  	builder.Add(8, 9)
   531  	builder.Add(9, 10) // this finalizes (2,7), which is a conflicting fork with (2,3)
   532  
   533  	blocks, err := builder.Blocks()
   534  	require.Nil(t, err)
   535  
   536  	fin, _, _ := newFinalizer(t)
   537  
   538  	err = addBlocksToFinalizer(fin, blocks)
   539  	assert.Error(t, err)
   540  }
   541  
   542  func TestNotification(t *testing.T) {
   543  	builder := NewBlockBuilder()
   544  	builder.Add(1, 2)
   545  	builder.Add(2, 3)
   546  	builder.Add(3, 4)
   547  	builder.Add(4, 5)
   548  
   549  	blocks, err := builder.Blocks()
   550  	require.Nil(t, err)
   551  
   552  	notifier := &mocks.Consumer{}
   553  	// 5 blocks including the genesis are incorporated
   554  	notifier.On("OnBlockIncorporated", mock.Anything).Return(nil).Times(5)
   555  	notifier.On("OnFinalizedBlock", blocks[0]).Return(nil).Once()
   556  	finalizationCallback := &mockm.Finalizer{}
   557  	finalizationCallback.On("MakeFinal", blocks[0].BlockID).Return(nil).Once()
   558  	finalizationCallback.On("MakeValid", mock.Anything).Return(nil)
   559  
   560  	genesisBQ := makeGenesis()
   561  
   562  	fin, err := finalizer.New(genesisBQ, finalizationCallback, notifier)
   563  	require.NoError(t, err)
   564  
   565  	err = addBlocksToFinalizer(fin, blocks)
   566  	require.NoError(t, err)
   567  	notifier.AssertExpectations(t)
   568  	finalizationCallback.AssertExpectations(t)
   569  }
   570  
   571  // ========== internal functions ===============
   572  
   573  func newFinalizer(t *testing.T) (forks.Finalizer, *mocks.Consumer, *mockm.Finalizer) {
   574  	notifier := &mocks.Consumer{}
   575  	notifier.On("OnBlockIncorporated", mock.Anything).Return(nil)
   576  	notifier.On("OnFinalizedBlock", mock.Anything).Return(nil)
   577  	finalizationCallback := &mockm.Finalizer{}
   578  	finalizationCallback.On("MakeFinal", mock.Anything).Return(nil)
   579  	finalizationCallback.On("MakeValid", mock.Anything).Return(nil)
   580  
   581  	genesisBQ := makeGenesis()
   582  
   583  	fin, err := finalizer.New(genesisBQ, finalizationCallback, notifier)
   584  
   585  	require.Nil(t, err)
   586  	return fin, notifier, finalizationCallback
   587  }
   588  
   589  func addBlocksToFinalizer(fin forks.Finalizer, blocks []*model.Block) error {
   590  	for _, block := range blocks {
   591  		err := fin.AddBlock(block)
   592  		if err != nil {
   593  			return fmt.Errorf("test case failed at adding block: %v: %w", block.View, err)
   594  		}
   595  	}
   596  
   597  	return nil
   598  }
   599  
   600  // check the view and QC's view of the locked block for the finalizer
   601  func assertTheLockedBlock(t *testing.T, fin forks.Finalizer, qc int, view int) {
   602  	assert.Equal(t, fin.LockedBlock().View, uint64(view), "locked block has wrong view")
   603  	assert.Equal(t, fin.LockedBlock().QC.View, uint64(qc), "locked block has wrong qc")
   604  }
   605  
   606  // check the view and QC's view of the finalized block for the finalizer
   607  func assertFinalizedBlock(t *testing.T, fin forks.Finalizer, qc int, view int) {
   608  	assert.Equal(t, fin.FinalizedBlock().View, uint64(view), "finalized block has wrong view")
   609  	assert.Equal(t, fin.FinalizedBlock().QC.View, uint64(qc), "fianlized block has wrong qc")
   610  }