diff --git a/aggsender/aggsender.go b/aggsender/aggsender.go index 56bc0da28..dcac24171 100644 --- a/aggsender/aggsender.go +++ b/aggsender/aggsender.go @@ -665,19 +665,24 @@ func (a *AggSender) checkLastCertificateFromAgglayer(ctx context.Context) error return nil } // CASE 2.1: certificate in storage but not in agglayer - // this is a non-sense, so thrown an error + // this is a non-sense, so throw an error if localLastCert != nil && aggLayerLastCert == nil { - return fmt.Errorf("recovery: certificate in storage but not in agglayer. Inconsistency") + return fmt.Errorf("recovery: certificate exists in storage but not in agglayer. Inconsistency") } - // CASE 3: aggsender stopped between sending to agglayer and storing on DB + // CASE 3.1: the certificate on the agglayer has less height than the one stored in the local storage + if aggLayerLastCert.Height < localLastCert.Height { + return fmt.Errorf("recovery: the last certificate in the agglayer has less height (%d) "+ + "than the one in the local storage (%d)", aggLayerLastCert.Height, localLastCert.Height) + } + // CASE 3.2: aggsender stopped between sending to agglayer and storing to the local storage if aggLayerLastCert.Height == localLastCert.Height+1 { - a.log.Infof("recovery: AggLayer have next cert (height:%d), so is a recovery case: storing cert: %s", - aggLayerLastCert.Height, localLastCert.String()) + a.log.Infof("recovery: AggLayer has the next cert (height: %d), so is a recovery case: storing cert: %s", + aggLayerLastCert.Height, aggLayerLastCert.String()) // we need to store the certificate in the local storage. localLastCert, err = a.updateLocalStorageWithAggLayerCert(ctx, aggLayerLastCert) if err != nil { - log.Errorf("recovery: error updating status certificate: %s status: %w", aggLayerLastCert.String(), err) - return fmt.Errorf("recovery: error updating certificate status: %w", err) + log.Errorf("recovery: error updating certificate: %s, reason: %w", aggLayerLastCert.String(), err) + return fmt.Errorf("recovery: error updating certificate: %w", err) } } // CASE 4: AggSender and AggLayer are not on the same page diff --git a/aggsender/aggsender_test.go b/aggsender/aggsender_test.go index 79504f6a0..cfdaa9a88 100644 --- a/aggsender/aggsender_test.go +++ b/aggsender/aggsender_test.go @@ -1832,8 +1832,21 @@ func TestCheckLastCertificateFromAgglayer_Case2_1NoCertRemoteButCertLocal(t *tes require.Error(t, err) } -// CASE 3: AggSender and AggLayer not same certificateID. AggLayer has a new certificate -func TestCheckLastCertificateFromAgglayer_Case3Mismatch(t *testing.T) { +// CASE 3.1: the certificate on the agglayer has less height than the one stored in the local storage +func TestCheckLastCertificateFromAgglayer_Case3_1LessHeight(t *testing.T) { + testData := newAggsenderTestData(t, testDataFlagMockStorage) + testData.l2syncerMock.EXPECT().OriginNetwork().Return(networkIDTest).Once() + testData.agglayerClientMock.EXPECT().GetLatestKnownCertificateHeader(networkIDTest). + Return(certInfoToCertHeader(&testData.testCerts[0], networkIDTest), nil).Once() + testData.storageMock.EXPECT().GetLastSentCertificate().Return(&testData.testCerts[1], nil) + + err := testData.sut.checkLastCertificateFromAgglayer(testData.ctx) + + require.ErrorContains(t, err, "recovery: the last certificate in the agglayer has less height (1) than the one in the local storage (2)") +} + +// CASE 3.2: AggSender and AggLayer not same height. AggLayer has a new certificate +func TestCheckLastCertificateFromAgglayer_Case3_2Mismatch(t *testing.T) { testData := newAggsenderTestData(t, testDataFlagMockStorage) testData.l2syncerMock.EXPECT().OriginNetwork().Return(networkIDTest).Once() testData.agglayerClientMock.EXPECT().GetLatestKnownCertificateHeader(networkIDTest).