github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/synchronizer/datacommittee_test.go (about)

     1  package synchronizer
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"math/big"
     8  	"strconv"
     9  	"testing"
    10  
    11  	"github.com/0xPolygon/supernets2-node/etherman"
    12  	"github.com/0xPolygon/supernets2-node/jsonrpc/types"
    13  	"github.com/0xPolygon/supernets2-node/state"
    14  	"github.com/ethereum/go-ethereum/common"
    15  	ethTypes "github.com/ethereum/go-ethereum/core/types"
    16  	"github.com/ethereum/go-ethereum/crypto"
    17  	"github.com/stretchr/testify/assert"
    18  	"github.com/stretchr/testify/require"
    19  )
    20  
    21  func TestGetBatchL2DataWithoutCommittee(t *testing.T) {
    22  	m := mocks{
    23  		State:       newStateMock(t),
    24  		ZKEVMClient: newZkEVMClientMock(t),
    25  		Etherman:    newEthermanMock(t),
    26  	}
    27  
    28  	ctx := context.Background()
    29  
    30  	trustedSync := ClientSynchronizer{
    31  		isTrustedSequencer:      true,
    32  		state:                   m.State,
    33  		zkEVMClient:             m.ZKEVMClient,
    34  		etherMan:                m.Etherman,
    35  		ctx:                     ctx,
    36  		selectedCommitteeMember: -1,
    37  	}
    38  
    39  	permissionlessSync := ClientSynchronizer{
    40  		isTrustedSequencer:      false,
    41  		state:                   m.State,
    42  		zkEVMClient:             m.ZKEVMClient,
    43  		etherMan:                m.Etherman,
    44  		ctx:                     ctx,
    45  		selectedCommitteeMember: -1,
    46  	}
    47  
    48  	const batchNum uint64 = 5
    49  	batchNumBig := big.NewInt(int64(batchNum))
    50  	dataFromDB := []byte("i poli tis Kerkyras einai omorfi")
    51  	errorHash := state.ZeroHash
    52  	unexpectedErrFromDB := errors.New("unexpected db")
    53  	errFromDBTemplate := "failed to get batch data from state for batch num " + strconv.Itoa(int(batchNum)) + ": %s"
    54  
    55  	trustedResponse := &types.Batch{Transactions: []types.TransactionOrHash{
    56  		{Tx: &types.Transaction{Nonce: 4}},
    57  		{Tx: &types.Transaction{Nonce: 284}},
    58  	}}
    59  	txs := []ethTypes.Transaction{}
    60  	for _, transaction := range trustedResponse.Transactions {
    61  		tx := transaction.Tx.CoreTx()
    62  		txs = append(txs, *tx)
    63  	}
    64  	dataFromTrusted, err := state.EncodeTransactions(txs)
    65  	require.NoError(t, err)
    66  	trustedResponse.BatchL2Data = dataFromTrusted
    67  	trustedResponseEmpty := &types.Batch{Transactions: []types.TransactionOrHash{}}
    68  	txs = []ethTypes.Transaction{}
    69  	dataFromTrustedEmpty, err := state.EncodeTransactions(txs)
    70  	require.NoError(t, err)
    71  
    72  	unexpectedErrFromTrusted := errors.New("unexpected trusted")
    73  
    74  	type testCase struct {
    75  		Name           string
    76  		ExpectedResult []byte
    77  		ExpectedError  error
    78  		Sync           *ClientSynchronizer
    79  		SetupMocks     func(m *mocks)
    80  	}
    81  
    82  	testCases := []testCase{
    83  		// Trusted sync cases
    84  		{
    85  			Name:           "Trusted sync fail if unexpected error from DB",
    86  			ExpectedResult: nil,
    87  			ExpectedError:  fmt.Errorf(errFromDBTemplate, unexpectedErrFromDB),
    88  			Sync:           &trustedSync,
    89  			SetupMocks: func(m *mocks) {
    90  				m.State.
    91  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
    92  					Return(nil, unexpectedErrFromDB).
    93  					Once()
    94  			},
    95  		},
    96  		{
    97  			Name:           "Trusted sync fail if data not found on DB",
    98  			ExpectedResult: nil,
    99  			ExpectedError:  fmt.Errorf("data not found on the local DB nor on any data committee member"),
   100  			Sync:           &trustedSync,
   101  			SetupMocks: func(m *mocks) {
   102  				m.State.
   103  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   104  					Return(nil, state.ErrNotFound).
   105  					Once()
   106  				m.Etherman.
   107  					On("GetCurrentDataCommittee").
   108  					Return(nil, nil).
   109  					Once()
   110  			},
   111  		},
   112  		{
   113  			Name:           "Trusted sync fail if hash missmatch on DB",
   114  			ExpectedResult: nil,
   115  			ExpectedError:  fmt.Errorf("data not found on the local DB nor on any data committee member"),
   116  			Sync:           &trustedSync,
   117  			SetupMocks: func(m *mocks) {
   118  				m.State.
   119  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   120  					Return(dataFromDB, nil).
   121  					Once()
   122  				m.Etherman.
   123  					On("GetCurrentDataCommittee").
   124  					Return(nil, nil).
   125  					Once()
   126  			},
   127  		},
   128  		{
   129  			Name:           "Trusted sync succeeds if hash match on DB",
   130  			ExpectedResult: dataFromDB,
   131  			ExpectedError:  nil,
   132  			Sync:           &trustedSync,
   133  			SetupMocks: func(m *mocks) {
   134  				m.State.
   135  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   136  					Return(dataFromDB, nil).
   137  					Once()
   138  			},
   139  		},
   140  		// Permissionless sync  cases
   141  		{
   142  			Name:           "Permissionless sync succeeds if hash match on DB",
   143  			ExpectedResult: dataFromDB,
   144  			ExpectedError:  nil,
   145  			Sync:           &permissionlessSync,
   146  			SetupMocks: func(m *mocks) {
   147  				m.State.
   148  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   149  					Return(dataFromDB, nil).
   150  					Once()
   151  			},
   152  		},
   153  		{
   154  			Name:           "Permissionless sync fail if unexpected error from DB",
   155  			ExpectedResult: nil,
   156  			ExpectedError:  fmt.Errorf(errFromDBTemplate, unexpectedErrFromDB),
   157  			Sync:           &permissionlessSync,
   158  			SetupMocks: func(m *mocks) {
   159  				m.State.
   160  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   161  					Return(nil, unexpectedErrFromDB).
   162  					Once()
   163  			},
   164  		},
   165  		{
   166  			Name:           "Permissionless sync fail if hash missmatch on the DB and error from trusted",
   167  			ExpectedResult: nil,
   168  			ExpectedError:  fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"),
   169  			Sync:           &permissionlessSync,
   170  			SetupMocks: func(m *mocks) {
   171  				m.State.
   172  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   173  					Return(dataFromDB, nil).
   174  					Once()
   175  				m.Etherman.
   176  					On("GetCurrentDataCommittee").
   177  					Return(nil, nil).
   178  					Once()
   179  				m.ZKEVMClient.
   180  					On("BatchByNumber", ctx, batchNumBig).
   181  					Return(nil, unexpectedErrFromTrusted).
   182  					Once()
   183  			},
   184  		},
   185  		{
   186  			Name:           "Permissionless sync fail if hash missmatch on the DB and from trusted sequencer",
   187  			ExpectedResult: nil,
   188  			ExpectedError:  fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"),
   189  			Sync:           &permissionlessSync,
   190  			SetupMocks: func(m *mocks) {
   191  				m.State.
   192  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   193  					Return(dataFromDB, nil).
   194  					Once()
   195  				m.Etherman.
   196  					On("GetCurrentDataCommittee").
   197  					Return(nil, nil).
   198  					Once()
   199  				m.ZKEVMClient.
   200  					On("BatchByNumber", ctx, batchNumBig).
   201  					Return(trustedResponse, nil).
   202  					Once()
   203  			},
   204  		},
   205  		{
   206  			Name:           "Permissionless sync succeeds if hash missmatch on the DB and match from trusted",
   207  			ExpectedResult: dataFromTrusted,
   208  			ExpectedError:  nil,
   209  			Sync:           &permissionlessSync,
   210  			SetupMocks: func(m *mocks) {
   211  				m.State.
   212  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   213  					Return(dataFromDB, nil).
   214  					Once()
   215  				m.ZKEVMClient.
   216  					On("BatchByNumber", ctx, batchNumBig).
   217  					Return(trustedResponse, nil).
   218  					Once()
   219  			},
   220  		},
   221  		{
   222  			Name:           "Permissionless sync fail if not found on the DB and error from trusted",
   223  			ExpectedResult: nil,
   224  			ExpectedError:  fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"),
   225  			Sync:           &permissionlessSync,
   226  			SetupMocks: func(m *mocks) {
   227  				m.State.
   228  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   229  					Return(nil, state.ErrNotFound).
   230  					Once()
   231  				m.Etherman.
   232  					On("GetCurrentDataCommittee").
   233  					Return(nil, nil).
   234  					Once()
   235  				m.ZKEVMClient.
   236  					On("BatchByNumber", ctx, batchNumBig).
   237  					Return(nil, unexpectedErrFromTrusted).
   238  					Once()
   239  			},
   240  		},
   241  		{
   242  			Name:           "Permissionless sync fail fail if not found on the DB and hash missmatch trusted",
   243  			ExpectedResult: nil,
   244  			ExpectedError:  fmt.Errorf("data not found on the local DB, nor from the trusted sequencer nor on any data committee member"),
   245  			Sync:           &permissionlessSync,
   246  			SetupMocks: func(m *mocks) {
   247  				m.State.
   248  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   249  					Return(nil, state.ErrNotFound).
   250  					Once()
   251  				m.Etherman.
   252  					On("GetCurrentDataCommittee").
   253  					Return(nil, nil).
   254  					Once()
   255  				m.ZKEVMClient.
   256  					On("BatchByNumber", ctx, batchNumBig).
   257  					Return(trustedResponse, nil).
   258  					Once()
   259  			},
   260  		},
   261  		{
   262  			Name:           "Permissionless sync succeeds if not found on the DB and match from trusted",
   263  			ExpectedResult: dataFromTrusted,
   264  			ExpectedError:  nil,
   265  			Sync:           &permissionlessSync,
   266  			SetupMocks: func(m *mocks) {
   267  				m.State.
   268  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   269  					Return(nil, state.ErrNotFound).
   270  					Once()
   271  				m.ZKEVMClient.
   272  					On("BatchByNumber", ctx, batchNumBig).
   273  					Return(trustedResponse, nil).
   274  					Once()
   275  			},
   276  		},
   277  		{
   278  			Name:           "Permissionless sync succeeds if not found on the DB and match from trusted empty response",
   279  			ExpectedResult: dataFromTrustedEmpty,
   280  			ExpectedError:  nil,
   281  			Sync:           &permissionlessSync,
   282  			SetupMocks: func(m *mocks) {
   283  				m.State.
   284  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   285  					Return(nil, state.ErrNotFound).
   286  					Once()
   287  				m.ZKEVMClient.
   288  					On("BatchByNumber", ctx, batchNumBig).
   289  					Return(trustedResponseEmpty, nil).
   290  					Once()
   291  			},
   292  		},
   293  	}
   294  
   295  	for _, testCase := range testCases {
   296  		t.Run(testCase.Name, func(t *testing.T) {
   297  			tc := testCase
   298  			tc.SetupMocks(&m)
   299  
   300  			var expectedHash common.Hash
   301  			if tc.ExpectedError == nil {
   302  				expectedHash = crypto.Keccak256Hash(tc.ExpectedResult)
   303  			} else {
   304  				expectedHash = errorHash
   305  			}
   306  
   307  			res, err := tc.Sync.getBatchL2Data(batchNum, expectedHash)
   308  			assert.Equal(t, tc.ExpectedResult, res)
   309  			if tc.ExpectedError != nil {
   310  				require.NotNil(t, err)
   311  				assert.Equal(t, tc.ExpectedError.Error(), err.Error())
   312  			}
   313  		})
   314  	}
   315  }
   316  
   317  func TestGetBatchL2DataWithCommittee(t *testing.T) {
   318  	m := mocks{
   319  		State:                      newStateMock(t),
   320  		ZKEVMClient:                newZkEVMClientMock(t),
   321  		Etherman:                   newEthermanMock(t),
   322  		DataCommitteeClientFactory: newDataCommitteeClientFactoryMock(t),
   323  	}
   324  
   325  	ctx := context.Background()
   326  
   327  	committeeMembers := []etherman.DataCommitteeMember{
   328  		{
   329  			URL:  "0",
   330  			Addr: common.HexToAddress("0x0"),
   331  		},
   332  		{
   333  			URL:  "1",
   334  			Addr: common.HexToAddress("0x1"),
   335  		},
   336  		{
   337  			URL:  "2",
   338  			Addr: common.HexToAddress("0x2"),
   339  		},
   340  	}
   341  	trustedSync := ClientSynchronizer{
   342  		isTrustedSequencer:         true,
   343  		state:                      m.State,
   344  		zkEVMClient:                m.ZKEVMClient,
   345  		etherMan:                   m.Etherman,
   346  		ctx:                        ctx,
   347  		selectedCommitteeMember:    0,
   348  		committeeMembers:           committeeMembers,
   349  		dataCommitteeClientFactory: m.DataCommitteeClientFactory,
   350  	}
   351  
   352  	permissionlessSync := ClientSynchronizer{
   353  		isTrustedSequencer:         false,
   354  		state:                      m.State,
   355  		zkEVMClient:                m.ZKEVMClient,
   356  		etherMan:                   m.Etherman,
   357  		ctx:                        ctx,
   358  		selectedCommitteeMember:    1,
   359  		committeeMembers:           committeeMembers,
   360  		dataCommitteeClientFactory: m.DataCommitteeClientFactory,
   361  	}
   362  
   363  	const batchNum uint64 = 5
   364  	batchNumBig := big.NewInt(int64(batchNum))
   365  	dataFromDB := []byte("i poli tis Kerkyras einai omorfi")
   366  	errorHash := state.ZeroHash
   367  
   368  	trustedResponse := &types.Batch{Transactions: []types.TransactionOrHash{
   369  		{Tx: &types.Transaction{Nonce: 4}},
   370  		{Tx: &types.Transaction{Nonce: 284}},
   371  	}}
   372  	txs := []ethTypes.Transaction{}
   373  	for _, transaction := range trustedResponse.Transactions {
   374  		tx := transaction.Tx.CoreTx()
   375  		txs = append(txs, *tx)
   376  	}
   377  	dataFromTrusted, err := state.EncodeTransactions(txs)
   378  	require.NoError(t, err)
   379  	trustedResponse.BatchL2Data = dataFromTrusted
   380  
   381  	type testCase struct {
   382  		Name           string
   383  		ExpectedResult []byte
   384  		ExpectedError  error
   385  		Sync           *ClientSynchronizer
   386  		SetupMocks     func(m *mocks)
   387  		Retry          bool
   388  	}
   389  
   390  	testCases := []testCase{
   391  		// Trusted sync cases
   392  		{
   393  			Name:           "Trusted sync fail if all the members don't answer",
   394  			ExpectedResult: nil,
   395  			ExpectedError:  fmt.Errorf("data not found on the local DB nor on any data committee member"),
   396  			Sync:           &trustedSync,
   397  			SetupMocks: func(m *mocks) {
   398  				m.State.
   399  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   400  					Return(nil, state.ErrNotFound).
   401  					Once()
   402  				DAClientMock := newDataCommitteeClientMock(t)
   403  				m.DataCommitteeClientFactory.
   404  					On("New", "0").
   405  					Return(DAClientMock).
   406  					Once()
   407  				DAClientMock.
   408  					On("GetOffChainData", trustedSync.ctx, state.ZeroHash).
   409  					Return([]byte("not the correct data"), nil).
   410  					Once()
   411  				m.DataCommitteeClientFactory.
   412  					On("New", "1").
   413  					Return(DAClientMock).
   414  					Once()
   415  				DAClientMock.
   416  					On("GetOffChainData", trustedSync.ctx, state.ZeroHash).
   417  					Return(nil, errors.New("not today")).
   418  					Once()
   419  				m.DataCommitteeClientFactory.
   420  					On("New", "2").
   421  					Return(DAClientMock).
   422  					Once()
   423  				DAClientMock.
   424  					On("GetOffChainData", trustedSync.ctx, state.ZeroHash).
   425  					Return([]byte("not the correct data"), nil).
   426  					Once()
   427  				m.Etherman.
   428  					On("GetCurrentDataCommittee").
   429  					Return(nil, nil).
   430  					Once()
   431  			},
   432  		},
   433  		{
   434  			Name:           "Trusted sync succeeds after 2nd committee member answers correctly",
   435  			ExpectedResult: dataFromDB,
   436  			ExpectedError:  nil,
   437  			Sync:           &trustedSync,
   438  			SetupMocks: func(m *mocks) {
   439  				// Reset DAC
   440  				trustedSync.committeeMembers = committeeMembers
   441  				trustedSync.selectedCommitteeMember = 0
   442  				m.State.
   443  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   444  					Return(nil, state.ErrNotFound).
   445  					Once()
   446  				DAClientMock := newDataCommitteeClientMock(t)
   447  				m.DataCommitteeClientFactory.
   448  					On("New", "0").
   449  					Return(DAClientMock).
   450  					Once()
   451  				DAClientMock.
   452  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   453  					Return([]byte("not the correct data"), nil).
   454  					Once()
   455  				m.DataCommitteeClientFactory.
   456  					On("New", "1").
   457  					Return(DAClientMock).
   458  					Once()
   459  				DAClientMock.
   460  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   461  					Return(nil, errors.New("not today")).
   462  					Once()
   463  				m.DataCommitteeClientFactory.
   464  					On("New", "2").
   465  					Return(DAClientMock).
   466  					Once()
   467  				DAClientMock.
   468  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   469  					Return(dataFromDB, nil).
   470  					Once()
   471  			},
   472  		},
   473  		// Permissionless sync  cases
   474  		{
   475  			Name:           "Permissionless sync succeeds after 2nd committee member answers correctly",
   476  			ExpectedResult: dataFromDB,
   477  			ExpectedError:  nil,
   478  			Sync:           &permissionlessSync,
   479  			SetupMocks: func(m *mocks) {
   480  				m.State.
   481  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   482  					Return(nil, state.ErrNotFound).
   483  					Once()
   484  				m.ZKEVMClient.
   485  					On("BatchByNumber", ctx, batchNumBig).
   486  					Return(nil, errors.New("not today")).
   487  					Once()
   488  				DAClientMock := newDataCommitteeClientMock(t)
   489  				m.DataCommitteeClientFactory.
   490  					On("New", "1").
   491  					Return(DAClientMock).
   492  					Once()
   493  				DAClientMock.
   494  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   495  					Return([]byte("not the correct data"), nil).
   496  					Once()
   497  				m.DataCommitteeClientFactory.
   498  					On("New", "2").
   499  					Return(DAClientMock).
   500  					Once()
   501  				DAClientMock.
   502  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   503  					Return(nil, errors.New("not today")).
   504  					Once()
   505  				m.DataCommitteeClientFactory.
   506  					On("New", "0").
   507  					Return(DAClientMock).
   508  					Once()
   509  				DAClientMock.
   510  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   511  					Return(dataFromDB, nil).
   512  					Once()
   513  			},
   514  		},
   515  		{
   516  			Name:           "Permissionless sync succeeds after updating DAC",
   517  			ExpectedResult: dataFromDB,
   518  			ExpectedError:  nil,
   519  			Sync:           &permissionlessSync,
   520  			Retry:          true,
   521  			SetupMocks: func(m *mocks) {
   522  				m.State.
   523  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   524  					Return(nil, state.ErrNotFound).
   525  					Once()
   526  				m.ZKEVMClient.
   527  					On("BatchByNumber", ctx, batchNumBig).
   528  					Return(nil, errors.New("not today")).
   529  					Once()
   530  				DAClientMock := newDataCommitteeClientMock(t)
   531  				m.DataCommitteeClientFactory.
   532  					On("New", "1").
   533  					Return(DAClientMock).
   534  					Once()
   535  				DAClientMock.
   536  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   537  					Return([]byte("not the correct data"), nil).
   538  					Once()
   539  				m.DataCommitteeClientFactory.
   540  					On("New", "2").
   541  					Return(DAClientMock).
   542  					Once()
   543  				DAClientMock.
   544  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   545  					Return(nil, errors.New("not today")).
   546  					Once()
   547  				m.DataCommitteeClientFactory.
   548  					On("New", "0").
   549  					Return(DAClientMock).
   550  					Once()
   551  				DAClientMock.
   552  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   553  					Return(nil, errors.New("not today")).
   554  					Once()
   555  				const succesfullURL = "the time is now"
   556  				m.Etherman.
   557  					On("GetCurrentDataCommittee").
   558  					Return(&etherman.DataCommittee{
   559  						Members: []etherman.DataCommitteeMember{{
   560  							URL:  succesfullURL,
   561  							Addr: common.HexToAddress("0xff"),
   562  						}},
   563  					}, nil).
   564  					Once()
   565  				m.State.
   566  					On("GetBatchL2DataByNumber", ctx, batchNum, nil).
   567  					Return(nil, state.ErrNotFound).
   568  					Once()
   569  				m.ZKEVMClient.
   570  					On("BatchByNumber", ctx, batchNumBig).
   571  					Return(nil, errors.New("not today")).
   572  					Once()
   573  				m.DataCommitteeClientFactory.
   574  					On("New", succesfullURL).
   575  					Return(DAClientMock).
   576  					Once()
   577  				DAClientMock.
   578  					On("GetOffChainData", trustedSync.ctx, crypto.Keccak256Hash(dataFromDB)).
   579  					Return(dataFromDB, nil).
   580  					Once()
   581  			},
   582  		},
   583  	}
   584  
   585  	for _, testCase := range testCases {
   586  		t.Run(testCase.Name, func(t *testing.T) {
   587  			tc := testCase
   588  			tc.SetupMocks(&m)
   589  
   590  			var expectedHash common.Hash
   591  			if tc.ExpectedError == nil {
   592  				expectedHash = crypto.Keccak256Hash(tc.ExpectedResult)
   593  			} else {
   594  				expectedHash = errorHash
   595  			}
   596  
   597  			res, err := tc.Sync.getBatchL2Data(batchNum, expectedHash)
   598  			if tc.Retry {
   599  				require.Error(t, err)
   600  				res, err = tc.Sync.getBatchL2Data(batchNum, expectedHash)
   601  			}
   602  			assert.Equal(t, tc.ExpectedResult, res)
   603  			if tc.ExpectedError != nil {
   604  				require.NotNil(t, err)
   605  				assert.Equal(t, tc.ExpectedError.Error(), err.Error())
   606  			}
   607  		})
   608  	}
   609  }