diff --git a/reorgdetector/migrations/migrations.go b/reorgdetector/migrations/migrations.go index 49d85972..d3d7484b 100644 --- a/reorgdetector/migrations/migrations.go +++ b/reorgdetector/migrations/migrations.go @@ -10,12 +10,19 @@ import ( //go:embed reorgdetector0001.sql var mig001 string +//go:embed reorgdetector0002.sql +var mig002 string + func RunMigrations(dbPath string) error { migrations := []types.Migration{ { ID: "reorgdetector0001", SQL: mig001, }, + { + ID: "reorgdetector0002", + SQL: mig002, + }, } return db.RunMigrations(dbPath, migrations) } diff --git a/reorgdetector/migrations/reorgdetector0002.sql b/reorgdetector/migrations/reorgdetector0002.sql new file mode 100644 index 00000000..345d40b1 --- /dev/null +++ b/reorgdetector/migrations/reorgdetector0002.sql @@ -0,0 +1,15 @@ +-- +migrate Down +DROP TABLE IF EXISTS reorg_event; + +-- +migrate Up +CREATE TABLE reorg_event ( + detected_at INTEGER NOT NULL, + from_block BIGINT NOT NULL, + to_block BIGINT NOT NULL, + subscriber_id VARCHAR NOT NULL, + current_hash VARCHAR, + tracked_hash VARCHAR, + version VARCHAR, + extra_data VARCHAR, + PRIMARY KEY (detected_at, subscriber_id, from_block, to_block) +) \ No newline at end of file diff --git a/reorgdetector/reorgdetector.go b/reorgdetector/reorgdetector.go index 57c50eec..45d0cae1 100644 --- a/reorgdetector/reorgdetector.go +++ b/reorgdetector/reorgdetector.go @@ -176,7 +176,7 @@ func (rd *ReorgDetector) detectReorgInTrackedList(ctx context.Context) error { ) subscriberIDs := rd.getSubscriberIDs() - + startTime := time.Now() for _, id := range subscriberIDs { id := id @@ -223,17 +223,31 @@ func (rd *ReorgDetector) detectReorgInTrackedList(ctx context.Context) error { continue } - + event := ReorgEvent{ + DetectedAt: startTime.Unix(), + FromBlock: hdr.Num, + ToBlock: headers[len(headers)-1].Num, + SubscriberID: id, + CurrentHash: currentHeader.Hash(), + TrackedHash: hdr.Hash, + ExtraData: fmt.Sprintf("network:%s, blockTstamp:%d", + rd.network.String(), + currentHeader.Time), + } + if err := rd.insertReorgEvent(event); err != nil { + return fmt.Errorf("failed to insert reorg event: %w", err) + } + rd.log.Warnf("Reorg detected %s for subscriber %s between blocks %d and %d. currentHash: %s trackHash: %s", + rd.network, event.SubscriberID, event.FromBlock, event.ToBlock, event.CurrentHash, event.TrackedHash) // Notify the subscriber about the reorg rd.notifySubscriber(id, hdr) - // Remove the reorged block and all the following blocks from DB - if err := rd.removeTrackedBlockRange(id, hdr.Num, headers[len(headers)-1].Num); err != nil { + if err := rd.removeTrackedBlockRange(event.SubscriberID, event.FromBlock, event.ToBlock); err != nil { return fmt.Errorf("error removing blocks from DB for subscriber %s between blocks %d and %d: %w", - id, hdr.Num, headers[len(headers)-1].Num, err) + event.SubscriberID, event.FromBlock, event.ToBlock, err) } // Remove the reorged block and all the following blocks from memory - hdrs.removeRange(hdr.Num, headers[len(headers)-1].Num) + hdrs.removeRange(event.FromBlock, event.ToBlock) break } diff --git a/reorgdetector/reorgdetector_db.go b/reorgdetector/reorgdetector_db.go index dcb9a0f6..21723f97 100644 --- a/reorgdetector/reorgdetector_db.go +++ b/reorgdetector/reorgdetector_db.go @@ -4,7 +4,9 @@ import ( "errors" "fmt" + "github.com/agglayer/aggkit" "github.com/agglayer/aggkit/db" + common "github.com/ethereum/go-ethereum/common" "github.com/russross/meddler" ) @@ -78,3 +80,21 @@ func (rd *ReorgDetector) removeTrackedBlockRange(id string, fromBlock, toBlock u ) return err } + +type ReorgEvent struct { + DetectedAt int64 `meddler:"detected_at"` + FromBlock uint64 `meddler:"from_block"` + ToBlock uint64 `meddler:"to_block"` + SubscriberID string `meddler:"subscriber_id"` + TrackedHash common.Hash `meddler:"tracked_hash,hash"` + CurrentHash common.Hash `meddler:"current_hash,hash"` + Version string `meddler:"version"` + ExtraData string `meddler:"extra_data"` +} + +func (rd *ReorgDetector) insertReorgEvent(event ReorgEvent) error { + if event.Version == "" { + event.Version = aggkit.GetVersion().Brief() + } + return meddler.Insert(rd.db, "reorg_event", &event) +} diff --git a/reorgdetector/reorgdetector_db_test.go b/reorgdetector/reorgdetector_db_test.go new file mode 100644 index 00000000..2c9ee4ea --- /dev/null +++ b/reorgdetector/reorgdetector_db_test.go @@ -0,0 +1,56 @@ +package reorgdetector + +import ( + "testing" + "time" + + aggkittypes "github.com/agglayer/aggkit/config/types" + "github.com/agglayer/aggkit/etherman" + common "github.com/ethereum/go-ethereum/common" + "github.com/stretchr/testify/require" +) + +func TestInsertReorgEvent(t *testing.T) { + // Create test DB dir + //testDir := path.Join(t.TempDir(), "reorgdetectorTest_ReorgDetector.sqlite") + testDir := "/tmp/kk.sqlite" + reorgDetector, err := New(nil, + Config{ + DBPath: testDir, + CheckReorgsInterval: aggkittypes.NewDuration(time.Millisecond * 100), + FinalizedBlock: etherman.FinalizedBlock, + }, L1) + require.NoError(t, err) + event := ReorgEvent{ + DetectedAt: time.Now().Unix(), + FromBlock: 1, + ToBlock: 2, + SubscriberID: "test", + TrackedHash: common.Hash{}, + CurrentHash: common.Hash{}, + Version: "1.0", + ExtraData: "extra", + } + + err = reorgDetector.insertReorgEvent(event) + require.NoError(t, err) + row := reorgDetector.db.QueryRow("SELECT * FROM reorg_event WHERE subscriber_id = $1", "test") + var detectedAt int64 + var fromBlock uint64 + var toBlock uint64 + var subscriberID string + var trackedHash string + var currentHash string + var version string + var extraData string + err = row.Scan(&detectedAt, &fromBlock, &toBlock, &subscriberID, &trackedHash, ¤tHash, &version, &extraData) + require.NoError(t, err) + require.Equal(t, event.DetectedAt, detectedAt) + require.Equal(t, event.FromBlock, fromBlock) + require.Equal(t, event.ToBlock, toBlock) + require.Equal(t, event.SubscriberID, subscriberID) + require.Equal(t, event.TrackedHash.String(), trackedHash) + require.Equal(t, event.CurrentHash.String(), currentHash) + require.Equal(t, event.Version, version) + require.Equal(t, event.ExtraData, extraData) +} diff --git a/version.go b/version.go index e52f56eb..a3bf4120 100644 --- a/version.go +++ b/version.go @@ -52,3 +52,9 @@ func (f FullVersion) String() string { f.Version, f.GitRev, f.GitBranch, f.GoVersion, f.BuildDate, f.OS, f.Arch) } + +func (f FullVersion) Brief() string { + return fmt.Sprintf("%s - %s / %s - build:%s os:%s/%s", + f.Version, f.GitRev, f.GitBranch, + f.BuildDate, f.OS, f.Arch) +}