From 8843442679cb0fb007c54108f97f348867ee6ad2 Mon Sep 17 00:00:00 2001 From: Goran Rojovic Date: Mon, 18 Nov 2024 16:22:07 +0100 Subject: [PATCH] feat: utilize the endpoint and new UTs --- aggsender/aggsender.go | 171 ++++++++----- aggsender/aggsender_test.go | 278 ++++++++++++++++++++++ aggsender/block_notifier_polling_test.go | 7 +- aggsender/db/aggsender_db_storage.go | 16 +- aggsender/db/aggsender_db_storage_test.go | 2 +- aggsender/mocks/agg_sender_storage.go | 38 ++- aggsender/types/epoch_notifier.go | 3 - aggsender/types/types.go | 6 + 8 files changed, 421 insertions(+), 100 deletions(-) diff --git a/aggsender/aggsender.go b/aggsender/aggsender.go index 7a629c91..8a44f4b6 100644 --- a/aggsender/aggsender.go +++ b/aggsender/aggsender.go @@ -85,64 +85,26 @@ func New( // Start starts the AggSender func (a *AggSender) Start(ctx context.Context) { - var err error + a.checkInitialStatus(ctx) + a.sendCertificates(ctx) +} + +// checkInitialStatus check local status vs agglayer status +func (a *AggSender) checkInitialStatus(ctx context.Context) { + ticker := time.NewTicker(retryInitialStatus) + defer ticker.Stop() + for { select { case <-ctx.Done(): - a.log.Info("AggSender stopped") return - default: - err = a.checkInitialStatus(ctx) - if err != nil { + case <-ticker.C: + if err := a.checkLastCertificateFromAgglayer(ctx); err != nil { log.Errorf("error checking initial status: %w, retrying in %s", err, retryInitialStatus) - time.Sleep(retryInitialStatus) + continue } } } - a.sendCertificates(ctx) -} - -// checkInitialStatus check local status vs agglayer status -func (a *AggSender) checkInitialStatus(ctx context.Context) error { - aggLayerLastCert, err := a.aggLayerClient.GetLatestKnownCertificateHeader(a.l2Syncer.OriginNetwork()) - // TODO: Case no certificate in agglayer - if err != nil { - return fmt.Errorf("error getting latest known certificate header from agglayer: %w", err) - } - localLastCert, err := a.storage.GetLastSentCertificate() - if err != nil { - return fmt.Errorf("error getting last sent certificate from local storage: %w", err) - } - if localLastCert == nil && aggLayerLastCert == nil { - log.Info("No certificates in local storage and agglayer: initial state") - return nil - } - if localLastCert == nil && aggLayerLastCert != nil { - log.Info("No certificates in local storage but agglayer have one: recovery") - return a.updateLocalStorageWithAggLayerCert(ctx, aggLayerLastCert) - } - if localLastCert.CertificateID != aggLayerLastCert.CertificateID { - a.log.Errorf("local certificate %s is different from agglayer certificate %s", - localLastCert.String(), aggLayerLastCert.String()) - localLastCert.Status = agglayer.InError - return fmt.Errorf("mismatch between local and agglayer certificates") - } - return nil -} - -func (a *AggSender) updateLocalStorageWithAggLayerCert(ctx context.Context, aggLayerCert *agglayer.CertificateHeader) error { - certInfo := types.CertificateInfo{ - Height: aggLayerCert.Height, - CertificateID: aggLayerCert.CertificateID, - NewLocalExitRoot: aggLayerCert.NewLocalExitRoot, - FromBlock: 0, - ToBlock: extractFromCertificateMetadataToBlock(aggLayerCert.Metadata), - CreatedAt: time.Now().UTC().UnixMilli(), - UpdatedAt: time.Now().UTC().UnixMilli(), - SignedCertificate: "", - } - log.Infof("setting initial certificate from AggLayer: %s", certInfo.String()) - return a.storage.SaveLastSentCertificate(ctx, certInfo) } // sendCertificates sends certificates to the aggLayer @@ -191,10 +153,6 @@ func (a *AggSender) sendCertificate(ctx context.Context) (*agglayer.SignedCertif if err != nil { return nil, err } - if lastSentCertificateInfo == nil { - // There are no certificates, so we set that to a empty one - lastSentCertificateInfo = &types.CertificateInfo{} - } previousToBlock := lastSentCertificateInfo.ToBlock if lastSentCertificateInfo.Status == agglayer.InError { @@ -229,7 +187,7 @@ func (a *AggSender) sendCertificate(ctx context.Context) (*agglayer.SignedCertif a.log.Infof("building certificate for block: %d to block: %d", fromBlock, toBlock) - certificate, err := a.buildCertificate(ctx, bridges, claims, *lastSentCertificateInfo, toBlock) + certificate, err := a.buildCertificate(ctx, bridges, claims, lastSentCertificateInfo, toBlock) if err != nil { return nil, fmt.Errorf("error building certificate: %w", err) } @@ -554,20 +512,21 @@ func (a *AggSender) signCertificate(certificate *agglayer.Certificate) (*agglaye func (a *AggSender) checkPendingCertificatesStatus(ctx context.Context) bool { pendingCertificates, err := a.storage.GetCertificatesByStatus(nonSettledStatuses) if err != nil { - err = fmt.Errorf("error getting pending certificates: %w", err) - a.log.Error(err) + a.log.Errorf("error getting pending certificates: %w", err) return true } - thereArePendingCerts := false + a.log.Debugf("checkPendingCertificatesStatus num of pendingCertificates: %d", len(pendingCertificates)) + thereArePendingCerts := false + for _, certificate := range pendingCertificates { certificateHeader, err := a.aggLayerClient.GetCertificateHeader(certificate.CertificateID) if err != nil { - err = fmt.Errorf("error getting certificate header of %d/%s from agglayer: %w", + a.log.Errorf("error getting certificate header of %d/%s from agglayer: %w", certificate.Height, certificate.String(), err) - a.log.Error(err) return true } + elapsedTime := time.Now().UTC().Sub(time.UnixMilli(certificate.CreatedAt)) a.log.Debugf("aggLayerClient.GetCertificateHeader status [%s] of certificate %s elapsed time:%s", certificateHeader.Status, @@ -581,12 +540,12 @@ func (a *AggSender) checkPendingCertificatesStatus(ctx context.Context) bool { certificate.Status = certificateHeader.Status certificate.UpdatedAt = time.Now().UTC().UnixMilli() - if err := a.storage.UpdateCertificateStatus(ctx, *certificate); err != nil { - err = fmt.Errorf("error updating certificate %s status in storage: %w", certificateHeader.String(), err) - a.log.Error(err) + if err := a.storage.UpdateCertificate(ctx, *certificate); err != nil { + a.log.Errorf("error updating certificate %s status in storage: %w", certificateHeader.String(), err) return true } } + if slices.Contains(nonSettledStatuses, certificateHeader.Status) { a.log.Infof("certificate %s is still pending, elapsed time:%s ", certificateHeader.String(), elapsedTime) @@ -607,6 +566,92 @@ func (a *AggSender) shouldSendCertificate() (bool, error) { return len(pendingCertificates) == 0, nil } +// checkLastCertificateFromAgglayer checks the last certificate from agglayer +func (a *AggSender) checkLastCertificateFromAgglayer(ctx context.Context) error { + aggLayerLastCert, err := a.aggLayerClient.GetLatestKnownCertificateHeader(a.l2Syncer.OriginNetwork()) + if err != nil { + return fmt.Errorf("recovery: error getting latest known certificate header from agglayer: %w", err) + } + + localLastCert, err := a.storage.GetLastSentCertificate() + if err != nil { + return fmt.Errorf("recovery: error getting last sent certificate from local storage: %w", err) + } + + // first case, we have nothing in db + if localLastCert.IsNil() { + if aggLayerLastCert == nil { + log.Info("recovery: No certificates in local storage and agglayer: initial state") + return nil + } else { + log.Infof("recovery: No certificates in local storage but agglayer have one %s", aggLayerLastCert.String()) + if err := a.updateLocalStorageWithAggLayerCert(ctx, aggLayerLastCert); err != nil { + return fmt.Errorf("recovery: error updating local storage with agglayer certificate: %w", err) + } + + return nil + } + } + + // second case, we have a certificate in db, but agglayer has a heigher height + if localLastCert.Height < aggLayerLastCert.Height { + log.Infof("recovery: Local certificate %s is older than agglayer certificate %s.", + localLastCert.String(), aggLayerLastCert.String()) + if err := a.updateLocalStorageWithAggLayerCert(ctx, aggLayerLastCert); err != nil { + return fmt.Errorf("recovery: error updating local storage with agglayer certificate: %w", err) + } + + return nil + } + + // third case, we have a certificate in db, but agglayer has a lower height + if localLastCert.Height > aggLayerLastCert.Height { + log.Info("recovery: Local certificate is newer than agglayer certificate. We will mark it as in error to resend it.") + + localLastCert.Status = agglayer.InError + localLastCert.UpdatedAt = time.Now().UTC().UnixMilli() + if err := a.storage.UpdateCertificate(ctx, localLastCert); err != nil { + return fmt.Errorf("recovery: error updating certificate status: %w", err) + } + + return nil + } + + // fourth case, we have a certificate in db, and agglayer has the same height + if localLastCert.CertificateID != aggLayerLastCert.CertificateID { + log.Infof("recovery: Local certificate %s is different from agglayer certificate %s.", + localLastCert.String(), aggLayerLastCert.String()) + + if err := a.storage.DeleteCertificate(ctx, localLastCert.CertificateID); err != nil { + return fmt.Errorf("recovery: error deleting certificate: %w", err) + } + + if err := a.updateLocalStorageWithAggLayerCert(ctx, aggLayerLastCert); err != nil { + return fmt.Errorf("recovery: error updating local storage with agglayer certificate: %w", err) + } + } + + return nil +} + +// updateLocalStorageWithAggLayerCert updates the local storage with the certificate from the AggLayer +func (a *AggSender) updateLocalStorageWithAggLayerCert(ctx context.Context, aggLayerCert *agglayer.CertificateHeader) error { + certInfo := types.CertificateInfo{ + Height: aggLayerCert.Height, + CertificateID: aggLayerCert.CertificateID, + NewLocalExitRoot: aggLayerCert.NewLocalExitRoot, + FromBlock: 0, + ToBlock: extractFromCertificateMetadataToBlock(aggLayerCert.Metadata), + CreatedAt: time.Now().UTC().UnixMilli(), + UpdatedAt: time.Now().UTC().UnixMilli(), + SignedCertificate: "", + Status: aggLayerCert.Status, + } + + log.Infof("setting initial certificate from AggLayer: %s", certInfo.String()) + return a.storage.SaveLastSentCertificate(ctx, certInfo) +} + // extractSignatureData extracts the R, S, and V from a 65-byte signature func extractSignatureData(signature []byte) (r, s common.Hash, isOddParity bool, err error) { if len(signature) != signatureSize { diff --git a/aggsender/aggsender_test.go b/aggsender/aggsender_test.go index e9a1c8f5..d5e5ae3a 100644 --- a/aggsender/aggsender_test.go +++ b/aggsender/aggsender_test.go @@ -12,6 +12,7 @@ import ( "time" "github.com/0xPolygon/cdk/agglayer" + "github.com/0xPolygon/cdk/aggsender/db" "github.com/0xPolygon/cdk/aggsender/mocks" aggsendertypes "github.com/0xPolygon/cdk/aggsender/types" "github.com/0xPolygon/cdk/bridgesync" @@ -1618,3 +1619,280 @@ func TestMetadataConversions(t *testing.T) { extractBlock := extractFromCertificateMetadataToBlock(c) require.Equal(t, toBlock, extractBlock) } + +func TestExtractFromCertificateMetadataToBlock(t *testing.T) { + tests := []struct { + name string + metadata common.Hash + expected uint64 + }{ + { + name: "Valid metadata", + metadata: common.BigToHash(big.NewInt(123567890)), + expected: 123567890, + }, + { + name: "Zero metadata", + metadata: common.BigToHash(big.NewInt(0)), + expected: 0, + }, + { + name: "Max uint64 metadata", + metadata: common.BigToHash(new(big.Int).SetUint64(^uint64(0))), + expected: ^uint64(0), + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + result := extractFromCertificateMetadataToBlock(tt.metadata) + require.Equal(t, tt.expected, result) + }) + } +} + +//nolint:dupl +func TestCheckLastCertificateFromAgglayer(t *testing.T) { + tests := []struct { + name string + agglayerMock func(*agglayer.AgglayerClientMock) + storageMock func(*AggSender, *log.Logger) + storageCheck func(*AggSender) + expectedError string + }{ + { + name: "Get last certificate from agglayer error", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(nil, errors.New("error")).Once() + }, + expectedError: "error getting latest known certificate header from agglayer", + }, + { + name: "Get last sent certificate from storage error", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(&agglayer.CertificateHeader{ + Height: 1, + NetworkID: 1, + CertificateID: common.HexToHash("0x1"), + NewLocalExitRoot: common.HexToHash("0x2"), + Status: agglayer.Pending, + Metadata: createCertificateMetadata(10), + }, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storageMock := mocks.NewAggSenderStorage(t) + storageMock.On("GetLastSentCertificate").Return(aggsendertypes.CertificateInfo{}, errors.New("error")).Once() + aggsender.storage = storageMock + }, + storageCheck: func(aggsender *AggSender) { + storageMock, ok := aggsender.storage.(*mocks.AggSenderStorage) + require.True(t, ok) + storageMock.AssertExpectations(t) + }, + expectedError: "error getting last sent certificate from local storage", + }, + { + name: "No last sent certificate in local storage and in agglayer", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(nil, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storageMock := mocks.NewAggSenderStorage(t) + storageMock.On("GetLastSentCertificate").Return(aggsendertypes.CertificateInfo{}, nil).Once() + aggsender.storage = storageMock + }, + storageCheck: func(aggsender *AggSender) { + storageMock, ok := aggsender.storage.(*mocks.AggSenderStorage) + require.True(t, ok) + storageMock.AssertExpectations(t) + }, + }, + { + name: "No last sent certificate in local storage, but exists one in agglayer", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(&agglayer.CertificateHeader{ + Height: 1, + NetworkID: 1, + CertificateID: common.HexToHash("0x1"), + NewLocalExitRoot: common.HexToHash("0x2"), + Status: agglayer.Pending, + Metadata: createCertificateMetadata(10), + }, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storage, err := db.NewAggSenderSQLStorage(logger, "file::memory:?cache=shared") + require.NoError(t, err) + + aggsender.storage = storage + }, + storageCheck: func(aggsender *AggSender) { + cert, err := aggsender.storage.GetLastSentCertificate() + require.NoError(t, err) + + require.Equal(t, cert.Height, uint64(1)) + require.Equal(t, cert.CertificateID, common.HexToHash("0x1")) + require.Equal(t, cert.NewLocalExitRoot, common.HexToHash("0x2")) + require.Equal(t, cert.Status, agglayer.Pending) + require.Equal(t, cert.ToBlock, uint64(10)) + }, + }, + { + name: "Last sent certificate in local storage and in agglayer, but older than agglayer's", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(&agglayer.CertificateHeader{ + Height: 11, + NetworkID: 1, + CertificateID: common.HexToHash("0x111"), + NewLocalExitRoot: common.HexToHash("0x222"), + Status: agglayer.Settled, + Metadata: createCertificateMetadata(100), + }, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storage, err := db.NewAggSenderSQLStorage(logger, "file::memory:?cache=shared") + require.NoError(t, err) + + aggsender.storage = storage + + err = storage.SaveLastSentCertificate(context.TODO(), aggsendertypes.CertificateInfo{ + Height: 10, + CertificateID: common.HexToHash("0x11"), + NewLocalExitRoot: common.HexToHash("0x22"), + Status: agglayer.Settled, + FromBlock: 0, + ToBlock: 90, + }) + require.NoError(t, err) + }, + storageCheck: func(aggsender *AggSender) { + cert, err := aggsender.storage.GetLastSentCertificate() + require.NoError(t, err) + + require.Equal(t, cert.Height, uint64(11)) + require.Equal(t, cert.CertificateID, common.HexToHash("0x111")) + require.Equal(t, cert.NewLocalExitRoot, common.HexToHash("0x222")) + require.Equal(t, cert.Status, agglayer.Settled) + require.Equal(t, cert.ToBlock, uint64(100)) + }, + }, + { + name: "Last sent certificate in local storage and in agglayer, but newer than agglayer's", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(&agglayer.CertificateHeader{ + Height: 19, + NetworkID: 1, + CertificateID: common.HexToHash("0x1111"), + NewLocalExitRoot: common.HexToHash("0x2222"), + Status: agglayer.Settled, + Metadata: createCertificateMetadata(90), + }, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storage, err := db.NewAggSenderSQLStorage(logger, "file::memory:?cache=shared") + require.NoError(t, err) + + aggsender.storage = storage + + err = storage.SaveLastSentCertificate(context.TODO(), aggsendertypes.CertificateInfo{ + Height: 20, + CertificateID: common.HexToHash("0x11111"), + NewLocalExitRoot: common.HexToHash("0x22222"), + Status: agglayer.Pending, + FromBlock: 0, + ToBlock: 100, + }) + require.NoError(t, err) + }, + storageCheck: func(aggsender *AggSender) { + cert, err := aggsender.storage.GetLastSentCertificate() + require.NoError(t, err) + + require.Equal(t, cert.Height, uint64(20)) + require.Equal(t, cert.CertificateID, common.HexToHash("0x11111")) + require.Equal(t, cert.NewLocalExitRoot, common.HexToHash("0x22222")) + require.Equal(t, cert.Status, agglayer.InError) // we mark it as InError to resend it again + require.Equal(t, cert.ToBlock, uint64(100)) + }, + }, + { + name: "Last sent certificate in local storage and in agglayer, but not the same hash", + agglayerMock: func(agglayerClientMock *agglayer.AgglayerClientMock) { + agglayerClientMock.On("GetLatestKnownCertificateHeader", mock.Anything).Return(&agglayer.CertificateHeader{ + Height: 30, + NetworkID: 1, + CertificateID: common.HexToHash("0x111111"), + NewLocalExitRoot: common.HexToHash("0x222222"), + Status: agglayer.Settled, + Metadata: createCertificateMetadata(90), + }, nil).Once() + }, + storageMock: func(aggsender *AggSender, logger *log.Logger) { + storage, err := db.NewAggSenderSQLStorage(logger, "file::memory:?cache=shared") + require.NoError(t, err) + + aggsender.storage = storage + + err = storage.SaveLastSentCertificate(context.TODO(), aggsendertypes.CertificateInfo{ + Height: 30, + CertificateID: common.HexToHash("0x111111a"), // not the same hash + NewLocalExitRoot: common.HexToHash("0x222222"), + Status: agglayer.Pending, + FromBlock: 91, + ToBlock: 100, + }) + require.NoError(t, err) + }, + storageCheck: func(aggsender *AggSender) { + cert, err := aggsender.storage.GetLastSentCertificate() + require.NoError(t, err) + + require.Equal(t, cert.Height, uint64(30)) + require.Equal(t, cert.CertificateID, common.HexToHash("0x111111")) // updated hash + require.Equal(t, cert.NewLocalExitRoot, common.HexToHash("0x222222")) + require.Equal(t, cert.Status, agglayer.Settled) + require.Equal(t, cert.ToBlock, uint64(90)) + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + l2syncerMock := mocks.NewL2BridgeSyncer(t) + l2syncerMock.On("OriginNetwork").Return(uint32(1), nil).Once() + + agglayerClientMock := agglayer.NewAgglayerClientMock(t) + logger := log.WithFields("aggsender-test", "checkLastCertificateFromAgglayer") + aggsender := &AggSender{ + log: logger, + l2Syncer: l2syncerMock, + aggLayerClient: agglayerClientMock, + } + + if test.agglayerMock != nil { + test.agglayerMock(agglayerClientMock) + } + + if test.storageMock != nil { + test.storageMock(aggsender, logger) + } + + err := aggsender.checkLastCertificateFromAgglayer(context.Background()) + if test.expectedError != "" { + require.ErrorContains(t, err, test.expectedError) + } else { + require.NoError(t, err) + } + + if test.storageCheck != nil { + test.storageCheck(aggsender) + } + + l2syncerMock.AssertExpectations(t) + agglayerClientMock.AssertExpectations(t) + }) + } +} diff --git a/aggsender/block_notifier_polling_test.go b/aggsender/block_notifier_polling_test.go index 83b3b643..e4f15ad7 100644 --- a/aggsender/block_notifier_polling_test.go +++ b/aggsender/block_notifier_polling_test.go @@ -32,11 +32,8 @@ func TestExploratoryBlockNotifierPolling(t *testing.T) { require.NoError(t, errSut) go sut.Start(context.Background()) ch := sut.Subscribe("test") - for { - select { - case block := <-ch: - fmt.Println(block) - } + for block := range ch { + fmt.Println(block) } } diff --git a/aggsender/db/aggsender_db_storage.go b/aggsender/db/aggsender_db_storage.go index 87d65e35..41f65e3e 100644 --- a/aggsender/db/aggsender_db_storage.go +++ b/aggsender/db/aggsender_db_storage.go @@ -23,15 +23,15 @@ type AggSenderStorage interface { // GetCertificateByHeight returns a certificate by its height GetCertificateByHeight(height uint64) (types.CertificateInfo, error) // GetLastSentCertificate returns the last certificate sent to the aggLayer - GetLastSentCertificate() (*types.CertificateInfo, error) + GetLastSentCertificate() (types.CertificateInfo, error) // SaveLastSentCertificate saves the last certificate sent to the aggLayer SaveLastSentCertificate(ctx context.Context, certificate types.CertificateInfo) error // DeleteCertificate deletes a certificate from the storage DeleteCertificate(ctx context.Context, certificateID common.Hash) error // GetCertificatesByStatus returns a list of certificates by their status GetCertificatesByStatus(status []agglayer.CertificateStatus) ([]*types.CertificateInfo, error) - // UpdateCertificateStatus updates the status of a certificate - UpdateCertificateStatus(ctx context.Context, certificate types.CertificateInfo) error + // UpdateCertificate updates certificate in db + UpdateCertificate(ctx context.Context, certificate types.CertificateInfo) error } var _ AggSenderStorage = (*AggSenderSQLStorage)(nil) @@ -105,14 +105,14 @@ func getCertificateByHeight(db meddler.DB, } // GetLastSentCertificate returns the last certificate sent to the aggLayer -func (a *AggSenderSQLStorage) GetLastSentCertificate() (*types.CertificateInfo, error) { +func (a *AggSenderSQLStorage) GetLastSentCertificate() (types.CertificateInfo, error) { var certificateInfo types.CertificateInfo if err := meddler.QueryRow(a.db, &certificateInfo, "SELECT * FROM certificate_info ORDER BY height DESC LIMIT 1;"); err != nil { - return nil, getSelectQueryError(0, err) + return types.CertificateInfo{}, getSelectQueryError(0, err) } - return &certificateInfo, nil + return certificateInfo, nil } // SaveLastSentCertificate saves the last certificate sent to the aggLayer @@ -191,8 +191,8 @@ func deleteCertificate(db meddler.DB, certificateID common.Hash) error { return nil } -// UpdateCertificateStatus updates the status of a certificate -func (a *AggSenderSQLStorage) UpdateCertificateStatus(ctx context.Context, certificate types.CertificateInfo) error { +// UpdateCertificate updates a certificate +func (a *AggSenderSQLStorage) UpdateCertificate(ctx context.Context, certificate types.CertificateInfo) error { tx, err := db.NewTx(ctx, a.db) if err != nil { return err diff --git a/aggsender/db/aggsender_db_storage_test.go b/aggsender/db/aggsender_db_storage_test.go index a0a20894..810e079a 100644 --- a/aggsender/db/aggsender_db_storage_test.go +++ b/aggsender/db/aggsender_db_storage_test.go @@ -213,7 +213,7 @@ func Test_Storage(t *testing.T) { // Update the status of the certificate certificate.Status = agglayer.Settled - require.NoError(t, storage.UpdateCertificateStatus(ctx, certificate)) + require.NoError(t, storage.UpdateCertificate(ctx, certificate)) // Fetch the certificate and verify the status has been updated certificateFromDB, err := storage.GetCertificateByHeight(certificate.Height) diff --git a/aggsender/mocks/agg_sender_storage.go b/aggsender/mocks/agg_sender_storage.go index 5ba08be0..9ae03379 100644 --- a/aggsender/mocks/agg_sender_storage.go +++ b/aggsender/mocks/agg_sender_storage.go @@ -188,24 +188,22 @@ func (_c *AggSenderStorage_GetCertificatesByStatus_Call) RunAndReturn(run func([ } // GetLastSentCertificate provides a mock function with given fields: -func (_m *AggSenderStorage) GetLastSentCertificate() (*types.CertificateInfo, error) { +func (_m *AggSenderStorage) GetLastSentCertificate() (types.CertificateInfo, error) { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for GetLastSentCertificate") } - var r0 *types.CertificateInfo + var r0 types.CertificateInfo var r1 error - if rf, ok := ret.Get(0).(func() (*types.CertificateInfo, error)); ok { + if rf, ok := ret.Get(0).(func() (types.CertificateInfo, error)); ok { return rf() } - if rf, ok := ret.Get(0).(func() *types.CertificateInfo); ok { + if rf, ok := ret.Get(0).(func() types.CertificateInfo); ok { r0 = rf() } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*types.CertificateInfo) - } + r0 = ret.Get(0).(types.CertificateInfo) } if rf, ok := ret.Get(1).(func() error); ok { @@ -234,12 +232,12 @@ func (_c *AggSenderStorage_GetLastSentCertificate_Call) Run(run func()) *AggSend return _c } -func (_c *AggSenderStorage_GetLastSentCertificate_Call) Return(_a0 *types.CertificateInfo, _a1 error) *AggSenderStorage_GetLastSentCertificate_Call { +func (_c *AggSenderStorage_GetLastSentCertificate_Call) Return(_a0 types.CertificateInfo, _a1 error) *AggSenderStorage_GetLastSentCertificate_Call { _c.Call.Return(_a0, _a1) return _c } -func (_c *AggSenderStorage_GetLastSentCertificate_Call) RunAndReturn(run func() (*types.CertificateInfo, error)) *AggSenderStorage_GetLastSentCertificate_Call { +func (_c *AggSenderStorage_GetLastSentCertificate_Call) RunAndReturn(run func() (types.CertificateInfo, error)) *AggSenderStorage_GetLastSentCertificate_Call { _c.Call.Return(run) return _c } @@ -291,12 +289,12 @@ func (_c *AggSenderStorage_SaveLastSentCertificate_Call) RunAndReturn(run func(c return _c } -// UpdateCertificateStatus provides a mock function with given fields: ctx, certificate -func (_m *AggSenderStorage) UpdateCertificateStatus(ctx context.Context, certificate types.CertificateInfo) error { +// UpdateCertificate provides a mock function with given fields: ctx, certificate +func (_m *AggSenderStorage) UpdateCertificate(ctx context.Context, certificate types.CertificateInfo) error { ret := _m.Called(ctx, certificate) if len(ret) == 0 { - panic("no return value specified for UpdateCertificateStatus") + panic("no return value specified for UpdateCertificate") } var r0 error @@ -309,31 +307,31 @@ func (_m *AggSenderStorage) UpdateCertificateStatus(ctx context.Context, certifi return r0 } -// AggSenderStorage_UpdateCertificateStatus_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateCertificateStatus' -type AggSenderStorage_UpdateCertificateStatus_Call struct { +// AggSenderStorage_UpdateCertificate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateCertificate' +type AggSenderStorage_UpdateCertificate_Call struct { *mock.Call } -// UpdateCertificateStatus is a helper method to define mock.On call +// UpdateCertificate is a helper method to define mock.On call // - ctx context.Context // - certificate types.CertificateInfo -func (_e *AggSenderStorage_Expecter) UpdateCertificateStatus(ctx interface{}, certificate interface{}) *AggSenderStorage_UpdateCertificateStatus_Call { - return &AggSenderStorage_UpdateCertificateStatus_Call{Call: _e.mock.On("UpdateCertificateStatus", ctx, certificate)} +func (_e *AggSenderStorage_Expecter) UpdateCertificate(ctx interface{}, certificate interface{}) *AggSenderStorage_UpdateCertificate_Call { + return &AggSenderStorage_UpdateCertificate_Call{Call: _e.mock.On("UpdateCertificate", ctx, certificate)} } -func (_c *AggSenderStorage_UpdateCertificateStatus_Call) Run(run func(ctx context.Context, certificate types.CertificateInfo)) *AggSenderStorage_UpdateCertificateStatus_Call { +func (_c *AggSenderStorage_UpdateCertificate_Call) Run(run func(ctx context.Context, certificate types.CertificateInfo)) *AggSenderStorage_UpdateCertificate_Call { _c.Call.Run(func(args mock.Arguments) { run(args[0].(context.Context), args[1].(types.CertificateInfo)) }) return _c } -func (_c *AggSenderStorage_UpdateCertificateStatus_Call) Return(_a0 error) *AggSenderStorage_UpdateCertificateStatus_Call { +func (_c *AggSenderStorage_UpdateCertificate_Call) Return(_a0 error) *AggSenderStorage_UpdateCertificate_Call { _c.Call.Return(_a0) return _c } -func (_c *AggSenderStorage_UpdateCertificateStatus_Call) RunAndReturn(run func(context.Context, types.CertificateInfo) error) *AggSenderStorage_UpdateCertificateStatus_Call { +func (_c *AggSenderStorage_UpdateCertificate_Call) RunAndReturn(run func(context.Context, types.CertificateInfo) error) *AggSenderStorage_UpdateCertificate_Call { _c.Call.Return(run) return _c } diff --git a/aggsender/types/epoch_notifier.go b/aggsender/types/epoch_notifier.go index 045ba7ff..426ad362 100644 --- a/aggsender/types/epoch_notifier.go +++ b/aggsender/types/epoch_notifier.go @@ -23,6 +23,3 @@ type EpochNotifier interface { Start(ctx context.Context) String() string } - -type BridgeL2Syncer interface { -} diff --git a/aggsender/types/types.go b/aggsender/types/types.go index d9e0b2e7..bce5fc8a 100644 --- a/aggsender/types/types.go +++ b/aggsender/types/types.go @@ -15,6 +15,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" ) +var ZeroHash = common.Hash{} + // L1InfoTreeSyncer is an interface defining functions that an L1InfoTreeSyncer should implement type L1InfoTreeSyncer interface { GetInfoByGlobalExitRoot(globalExitRoot common.Hash) (*l1infotreesync.L1InfoTreeLeaf, error) @@ -65,6 +67,10 @@ type CertificateInfo struct { SignedCertificate string `meddler:"signed_certificate"` } +func (c CertificateInfo) IsNil() bool { + return c.CertificateID == ZeroHash +} + func (c CertificateInfo) String() string { return fmt.Sprintf( "Height: %d\n"+