From 99cd99d8b88f44bc0dce178bb844dd66ebdca37e Mon Sep 17 00:00:00 2001 From: georgehao Date: Thu, 14 Dec 2023 18:33:02 +0800 Subject: [PATCH] feat: update the director --- Makefile | 25 +- bridge-history-api/Makefile | 2 +- bridge-history-api/cmd/api/app/app.go | 8 +- bridge-history-api/cmd/db_cli/app/app.go | 9 +- bridge-history-api/cmd/fetcher/app/app.go | 7 +- bridge-history-api/conf/config.json | 2 +- .../internal/controller/fetcher/l1_fetcher.go | 240 +++--------------- .../internal/controller/fetcher/l2_fetcher.go | 202 +++------------ .../internal/logic/event_update.go | 153 +++++++++++ .../internal/logic/history_logic.go | 1 - ...her_event_parser.go => l1_event_parser.go} | 198 ++------------- .../internal/logic/l1_fetcher.go | 210 +++++++++++++++ .../internal/logic/l2_event_parser.go | 169 ++++++++++++ .../internal/logic/l2_fetcher.go | 202 +++++++++++++++ bridge-history-api/internal/utils/utils.go | 24 ++ go.work.sum | 48 ++-- tests/integration-test/go.sum | 3 + 17 files changed, 892 insertions(+), 611 deletions(-) create mode 100644 bridge-history-api/internal/logic/event_update.go rename bridge-history-api/internal/logic/{watcher_event_parser.go => l1_event_parser.go} (56%) create mode 100644 bridge-history-api/internal/logic/l1_fetcher.go create mode 100644 bridge-history-api/internal/logic/l2_event_parser.go create mode 100644 bridge-history-api/internal/logic/l2_fetcher.go diff --git a/Makefile b/Makefile index 7fa10c8be4..97c846a601 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: fmt dev_docker build_test_docker run_test_docker clean +.PHONY: fmt dev_docker build_test_docker run_test_docker clean update L2GETH_TAG=scroll-v5.1.6 @@ -6,6 +6,15 @@ help: ## Display this help message @grep -h \ -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | \ awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' +update: + go work sync + cd $(PWD)/bridge-history-api/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy + cd $(PWD)/common/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG}&& go mod tidy + cd $(PWD)/coordinator/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy + cd $(PWD)/database/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy + cd $(PWD)/prover/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG}&& go mod tidy + cd $(PWD)/rollup/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy + cd $(PWD)/tests/integration-test/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy lint: ## The code's format and security checks. make -C rollup lint @@ -17,13 +26,13 @@ lint: ## The code's format and security checks. fmt: ## format the code go work sync - cd $(PWD)/bridge-history-api/ && go get -u github.com/ethereum/go-ethereum@latest && go mod tidy - cd $(PWD)/common/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy - cd $(PWD)/coordinator/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy - cd $(PWD)/database/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy - cd $(PWD)/prover/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy - cd $(PWD)/rollup/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy - cd $(PWD)/tests/integration-test/ && go get -u github.com/scroll-tech/go-ethereum@${L2GETH_TAG} && go mod tidy + cd $(PWD)/bridge-history-api/ && go mod tidy + cd $(PWD)/common/ && go mod tidy + cd $(PWD)/coordinator/ && go mod tidy + cd $(PWD)/database/ && go mod tidy + cd $(PWD)/prover/ && go mod tidy + cd $(PWD)/rollup/ && go mod tidy + cd $(PWD)/tests/integration-test/ && go mod tidy goimports -local $(PWD)/bridge-history-api/ -w . goimports -local $(PWD)/common/ -w . diff --git a/bridge-history-api/Makefile b/bridge-history-api/Makefile index 0a7be1de2b..8ffb4c3783 100644 --- a/bridge-history-api/Makefile +++ b/bridge-history-api/Makefile @@ -38,4 +38,4 @@ reset-env: bridgehistoryapi-docker: DOCKER_BUILDKIT=1 docker build -t scrolltech/bridgehistoryapi-fetcher:${IMAGE_VERSION} ${REPO_ROOT_DIR}/ -f ${REPO_ROOT_DIR}/build/dockerfiles/bridgehistoryapi-fetcher.Dockerfile DOCKER_BUILDKIT=1 docker build -t scrolltech/bridgehistoryapi-api:${IMAGE_VERSION} ${REPO_ROOT_DIR}/ -f ${REPO_ROOT_DIR}/build/dockerfiles/bridgehistoryapi-api.Dockerfile - DOCKER_BUILDKIT=1 docker build -t scrolltech/bridgehistoryapi-db-cli:${IMAGE_VERSION} ${REPO_ROOT_DIR}/ -f ${REPO_ROOT_DIR}/build/dockerfiles/bridgehistoryapi-db-cli.Dockerfile \ No newline at end of file + DOCKER_BUILDKIT=1 docker build -t scrolltech/bridgehistoryapi-db-cli:${IMAGE_VERSION} ${REPO_ROOT_DIR}/ -f ${REPO_ROOT_DIR}/build/dockerfiles/bridgehistoryapi-db-cli.Dockerfile diff --git a/bridge-history-api/cmd/api/app/app.go b/bridge-history-api/cmd/api/app/app.go index 7c5e7e8aa3..16a406c709 100644 --- a/bridge-history-api/cmd/api/app/app.go +++ b/bridge-history-api/cmd/api/app/app.go @@ -20,9 +20,7 @@ import ( "scroll-tech/bridge-history-api/internal/route" ) -var ( - app *cli.App -) +var app *cli.App func init() { app = cli.NewApp() @@ -54,12 +52,12 @@ func action(ctx *cli.Context) error { log.Error("failed to close db", "err", err) } }() - redis := redis.NewClient(&redis.Options{ + redisClient := redis.NewClient(&redis.Options{ Addr: cfg.Redis.Address, Password: cfg.Redis.Password, DB: cfg.Redis.DB, }) - api.InitController(db, redis) + api.InitController(db, redisClient) router := gin.Default() registry := prometheus.DefaultRegisterer diff --git a/bridge-history-api/cmd/db_cli/app/app.go b/bridge-history-api/cmd/db_cli/app/app.go index e452f90ce0..e66eb8f886 100644 --- a/bridge-history-api/cmd/db_cli/app/app.go +++ b/bridge-history-api/cmd/db_cli/app/app.go @@ -9,10 +9,8 @@ import ( "scroll-tech/common/utils" ) -var ( - // Set up database app info. - app *cli.App -) +// Set up database app info. +var app *cli.App func init() { app = cli.NewApp() @@ -60,7 +58,8 @@ func init() { Name: "version", Usage: "Rollback to the specified version.", Value: 0, - }}, + }, + }, }, } } diff --git a/bridge-history-api/cmd/fetcher/app/app.go b/bridge-history-api/cmd/fetcher/app/app.go index 26af0bb3ae..feca265676 100644 --- a/bridge-history-api/cmd/fetcher/app/app.go +++ b/bridge-history-api/cmd/fetcher/app/app.go @@ -11,15 +11,14 @@ import ( "github.com/urfave/cli/v2" "scroll-tech/common/database" + "scroll-tech/common/observability" "scroll-tech/common/utils" "scroll-tech/bridge-history-api/internal/config" "scroll-tech/bridge-history-api/internal/controller/fetcher" ) -var ( - app *cli.App -) +var app *cli.App func init() { app = cli.NewApp() @@ -67,6 +66,8 @@ func action(ctx *cli.Context) error { log.Crit("failed to connect to db", "config file", cfgFile, "error", err) } + observability.Server(ctx, db) + // syncInfo is used to store the shared info between L1 fetcher and L2 fetcher, e.g., the sync height. syncInfo := &fetcher.SyncInfo{} diff --git a/bridge-history-api/conf/config.json b/bridge-history-api/conf/config.json index 69c8c49651..df53df2083 100644 --- a/bridge-history-api/conf/config.json +++ b/bridge-history-api/conf/config.json @@ -44,4 +44,4 @@ "password": "", "db": 0 } -} \ No newline at end of file +} diff --git a/bridge-history-api/internal/controller/fetcher/l1_fetcher.go b/bridge-history-api/internal/controller/fetcher/l1_fetcher.go index f6e524e698..33f5a330e1 100644 --- a/bridge-history-api/internal/controller/fetcher/l1_fetcher.go +++ b/bridge-history-api/internal/controller/fetcher/l1_fetcher.go @@ -2,89 +2,49 @@ package fetcher import ( "context" - "math/big" "time" - "github.com/scroll-tech/go-ethereum" - "github.com/scroll-tech/go-ethereum/common" - "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" "gorm.io/gorm" - backendabi "scroll-tech/bridge-history-api/abi" "scroll-tech/bridge-history-api/internal/config" "scroll-tech/bridge-history-api/internal/logic" - "scroll-tech/bridge-history-api/internal/orm" "scroll-tech/bridge-history-api/internal/utils" ) // L1MessageFetcher fetches cross message events from L1 and saves them to database. type L1MessageFetcher struct { - ctx context.Context - cfg *config.LayerConfig - db *gorm.DB - crossMessageOrm *orm.CrossMessage - batchEventOrm *orm.BatchEvent - client *ethclient.Client - addressList []common.Address - syncInfo *SyncInfo - l1ScanHeight uint64 + ctx context.Context + cfg *config.LayerConfig + client *ethclient.Client + + syncInfo *SyncInfo + l1ScanHeight uint64 + + eventUpdateLogic *logic.EventUpdateLogic + l1FetcherLogic *logic.L1FetcherLogic } // NewL1MessageFetcher creates a new L1MessageFetcher instance. func NewL1MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client, syncInfo *SyncInfo) (*L1MessageFetcher, error) { - addressList := []common.Address{ - common.HexToAddress(cfg.ETHGatewayAddr), - - common.HexToAddress(cfg.StandardERC20GatewayAddr), - common.HexToAddress(cfg.CustomERC20GatewayAddr), - common.HexToAddress(cfg.WETHGatewayAddr), - common.HexToAddress(cfg.DAIGatewayAddr), - - common.HexToAddress(cfg.ERC721GatewayAddr), - common.HexToAddress(cfg.ERC1155GatewayAddr), - - common.HexToAddress(cfg.MessengerAddr), - - common.HexToAddress(cfg.ScrollChainAddr), - - common.HexToAddress(cfg.MessageQueueAddr), - } - - // Optional erc20 gateways. - if cfg.USDCGatewayAddr != "" { - addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr)) - } - - if cfg.LIDOGatewayAddr != "" { - addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr)) - } - return &L1MessageFetcher{ - ctx: ctx, - cfg: cfg, - db: db, - crossMessageOrm: orm.NewCrossMessage(db), - batchEventOrm: orm.NewBatchEvent(db), - client: client, - addressList: addressList, - syncInfo: syncInfo, + ctx: ctx, + cfg: cfg, + client: client, + syncInfo: syncInfo, + eventUpdateLogic: logic.NewEventUpdateLogic(db), + l1FetcherLogic: logic.NewL1FetcherLogic(cfg, db, client), }, nil } // Start starts the L1 message fetching process. func (c *L1MessageFetcher) Start() { - messageSyncedHeight, err := c.crossMessageOrm.GetMessageSyncedHeightInDB(c.ctx, orm.MessageTypeL1SentMessage) - if err != nil { - log.Error("failed to get L1 cross message synced height", "error", err) - return - } - batchSyncedHeight, err := c.batchEventOrm.GetBatchEventSyncedHeightInDB(c.ctx) + messageSyncedHeight, batchSyncedHeight, err := c.eventUpdateLogic.GetL1SyncHeight(c.ctx) if err != nil { - log.Error("failed to get L1 batch event synced height", "error", err) - return + log.Crit("L1MessageFetcher start failed", "error", err) } + c.l1ScanHeight = messageSyncedHeight if batchSyncedHeight > c.l1ScanHeight { c.l1ScanHeight = batchSyncedHeight @@ -92,6 +52,7 @@ func (c *L1MessageFetcher) Start() { if c.cfg.StartHeight > c.l1ScanHeight { c.l1ScanHeight = c.cfg.StartHeight - 1 } + log.Info("Start L1 message fetcher", "message synced height", messageSyncedHeight, "batch synced height", batchSyncedHeight, "config start height", c.cfg.StartHeight) tick := time.NewTicker(time.Duration(c.cfg.BlockTime) * time.Second) @@ -122,161 +83,28 @@ func (c *L1MessageFetcher) fetchAndSaveEvents(confirmation uint64) { if to > endHeight { to = endHeight } - err = c.doFetchAndSaveEvents(c.ctx, from, to, c.addressList) - if err != nil { - log.Error("failed to fetch and save L1 events", "from", from, "to", to, "err", err) + + fetcherResult, fetcherErr := c.l1FetcherLogic.L1Fetcher(c.ctx, from, to) + if fetcherErr != nil { + log.Error("failed to fetch L1 events", "from", from, "to", to, "err", err) return } - c.l1ScanHeight = to - } -} - -func (c *L1MessageFetcher) doFetchAndSaveEvents(ctx context.Context, from uint64, to uint64, addrList []common.Address) error { - log.Info("fetch and save L1 events", "from", from, "to", to) - var l1FailedGatewayRouterTxs []*orm.CrossMessage - blockTimestampsMap := make(map[uint64]uint64) - blocks, err := utils.GetL1BlocksInRange(c.ctx, c.client, from, to) - if err != nil { - log.Error("failed to get L1 blocks in range", "from", from, "to", to, "err", err) - return err - } - for i := from; i <= to; i++ { - block := blocks[i-from] - blockTimestampsMap[block.NumberU64()] = block.Time() - - for _, tx := range block.Transactions() { - to := tx.To() - if to == nil { - continue - } - toAddress := to.String() - if toAddress == c.cfg.GatewayRouterAddr { - var receipt *types.Receipt - receipt, err = c.client.TransactionReceipt(ctx, tx.Hash()) - if err != nil { - log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", err) - return err - } - // Check if the transaction failed - if receipt.Status == types.ReceiptStatusFailed { - signer := types.NewLondonSigner(new(big.Int).SetUint64(tx.ChainId().Uint64())) - var sender common.Address - sender, err = signer.Sender(tx) - if err != nil { - log.Error("get sender failed", "chain id", tx.ChainId().Uint64(), "tx hash", tx.Hash().String(), "err", err) - return err - } - l1FailedGatewayRouterTxs = append(l1FailedGatewayRouterTxs, &orm.CrossMessage{ - L1TxHash: tx.Hash().String(), - MessageType: int(orm.MessageTypeL1SentMessage), - Sender: sender.String(), - Receiver: (*tx.To()).String(), - L1BlockNumber: receipt.BlockNumber.Uint64(), - BlockTimestamp: block.Time(), - TxStatus: int(orm.TxStatusTypeSentFailed), - }) - } - } + if insertUpdateErr := c.eventUpdateLogic.L1InsertOrUpdate(c.ctx, fetcherResult); insertUpdateErr != nil { + log.Error("failed to save L1 events", "from", from, "to", to, "err", err) + return } - } - query := ethereum.FilterQuery{ - FromBlock: new(big.Int).SetUint64(from), // inclusive - ToBlock: new(big.Int).SetUint64(to), // inclusive - Addresses: addrList, - Topics: make([][]common.Hash, 1), - } - query.Topics[0] = make([]common.Hash, 13) - query.Topics[0][0] = backendabi.L1DepositETHSig - query.Topics[0][1] = backendabi.L1DepositERC20Sig - query.Topics[0][2] = backendabi.L1DepositERC721Sig - query.Topics[0][3] = backendabi.L1DepositERC1155Sig - query.Topics[0][4] = backendabi.L1SentMessageEventSig - query.Topics[0][5] = backendabi.L1RelayedMessageEventSig - query.Topics[0][6] = backendabi.L1FailedRelayedMessageEventSig - query.Topics[0][7] = backendabi.L1CommitBatchEventSig - query.Topics[0][8] = backendabi.L1RevertBatchEventSig - query.Topics[0][9] = backendabi.L1FinalizeBatchEventSig - query.Topics[0][10] = backendabi.L1QueueTransactionEventSig - query.Topics[0][11] = backendabi.L1DequeueTransactionEventSig - query.Topics[0][12] = backendabi.L1DropTransactionEventSig - - logs, err := c.client.FilterLogs(ctx, query) - if err != nil { - log.Error("failed to filter L1 event logs", "from", from, "to", to, "err", err) - return err - } - l1DepositMessages, l1RelayedMessages, err := logic.ParseL1CrossChainEventLogs(ctx, logs, blockTimestampsMap, c.client) - if err != nil { - log.Error("failed to parse L1 cross chain event logs", "from", from, "to", to, "err", err) - return err - } - l1BatchEvents, err := logic.ParseL1BatchEventLogs(ctx, logs, blockTimestampsMap, c.client) - if err != nil { - log.Error("failed to parse L1 batch event logs", "from", from, "to", to, "err", err) - return err - } - l1MessageQueueEvents, err := logic.ParseL1MessageQueueEventLogs(ctx, logs, blockTimestampsMap, c.client) - if err != nil { - log.Error("failed to parse L1 message queue event logs", "from", from, "to", to, "err", err) - return err - } - err = c.db.Transaction(func(tx *gorm.DB) error { - if txErr := c.crossMessageOrm.InsertOrUpdateL1Messages(ctx, l1DepositMessages, tx); txErr != nil { - log.Error("failed to insert L1 deposit messages", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.InsertOrUpdateL1RelayedMessagesOfL2Withdrawals(ctx, l1RelayedMessages, tx); txErr != nil { - log.Error("failed to update L1 relayed messages of L2 withdrawals", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.batchEventOrm.InsertOrUpdateBatchEvents(ctx, l1BatchEvents, tx); txErr != nil { - log.Error("failed to insert or update batch events", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.UpdateL1MessageQueueEventsInfo(ctx, l1MessageQueueEvents, tx); txErr != nil { - log.Error("failed to insert L1 message queue events", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l1FailedGatewayRouterTxs, tx); txErr != nil { - log.Error("failed to insert L1 failed gateway router transactions", "from", from, "to", to, "err", txErr) - return txErr + l2ScannedHeight := c.syncInfo.GetL2ScanHeight() + if l2ScannedHeight == 0 { + log.Error("L2 fetcher has not successfully synced at least one round yet") + return } - return nil - }) - if err != nil { - log.Error("failed to update db of L1 events", "from", from, "to", to, "err", err) - return err - } - if err = c.updateBatchIndexAndStatus(ctx); err != nil { - log.Error("failed to update batch index and status", "err", err) - return err - } - return nil -} -func (c *L1MessageFetcher) updateBatchIndexAndStatus(ctx context.Context) error { - l2ScannedHeight := c.syncInfo.GetL2ScanHeight() - if l2ScannedHeight == 0 { - log.Info("L2 fetcher has not successfully synced at least one round yet") - return nil - } - batches, err := c.batchEventOrm.GetBatchesLEBlockHeight(ctx, l2ScannedHeight) - if err != nil { - log.Error("failed to get batches >= block height", "error", err) - return err - } - for _, batch := range batches { - log.Info("update batch info of L2 withdrawals", "index", batch.BatchIndex, "start", batch.StartBlockNumber, "end", batch.EndBlockNumber) - if err := c.crossMessageOrm.UpdateBatchStatusOfL2Withdrawals(ctx, batch.StartBlockNumber, batch.EndBlockNumber, batch.BatchIndex); err != nil { - log.Error("failed to update batch status of L2 sent messages", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", err) - return err - } - if err := c.batchEventOrm.UpdateBatchEventStatus(ctx, batch.BatchIndex); err != nil { - log.Error("failed to update batch event status as updated", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", err) - return err + if updateErr := c.eventUpdateLogic.UpdateL1BatchIndexAndStatus(c.ctx, l2ScannedHeight); updateErr != nil { + log.Error("failed to update L1 batch index and status", "from", from, "to", to, "err", err) + return } + c.l1ScanHeight = to } - return nil } diff --git a/bridge-history-api/internal/controller/fetcher/l2_fetcher.go b/bridge-history-api/internal/controller/fetcher/l2_fetcher.go index 86309524ba..27bccaad76 100644 --- a/bridge-history-api/internal/controller/fetcher/l2_fetcher.go +++ b/bridge-history-api/internal/controller/fetcher/l2_fetcher.go @@ -6,15 +6,11 @@ import ( "math/big" "time" - "github.com/scroll-tech/go-ethereum" "github.com/scroll-tech/go-ethereum/common" - "github.com/scroll-tech/go-ethereum/core/types" - "github.com/scroll-tech/go-ethereum/crypto" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" "gorm.io/gorm" - backendabi "scroll-tech/bridge-history-api/abi" "scroll-tech/bridge-history-api/internal/config" "scroll-tech/bridge-history-api/internal/logic" "scroll-tech/bridge-history-api/internal/orm" @@ -23,58 +19,37 @@ import ( // L2MessageFetcher fetches cross message events from L2 and saves them to database. type L2MessageFetcher struct { - ctx context.Context - cfg *config.LayerConfig - db *gorm.DB - crossMessageOrm *orm.CrossMessage - client *ethclient.Client - addressList []common.Address - syncInfo *SyncInfo + ctx context.Context + cfg *config.LayerConfig + db *gorm.DB + client *ethclient.Client + syncInfo *SyncInfo + + eventUpdateLogic *logic.EventUpdateLogic + l2FetcherLogic *logic.L2FetcherLogic } // NewL2MessageFetcher creates a new L2MessageFetcher instance. func NewL2MessageFetcher(ctx context.Context, cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client, syncInfo *SyncInfo) (*L2MessageFetcher, error) { - addressList := []common.Address{ - common.HexToAddress(cfg.ETHGatewayAddr), - - common.HexToAddress(cfg.StandardERC20GatewayAddr), - common.HexToAddress(cfg.CustomERC20GatewayAddr), - common.HexToAddress(cfg.WETHGatewayAddr), - common.HexToAddress(cfg.DAIGatewayAddr), - - common.HexToAddress(cfg.ERC721GatewayAddr), - common.HexToAddress(cfg.ERC1155GatewayAddr), - - common.HexToAddress(cfg.MessengerAddr), - } - - // Optional erc20 gateways. - if cfg.USDCGatewayAddr != "" { - addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr)) - } - - if cfg.LIDOGatewayAddr != "" { - addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr)) - } - return &L2MessageFetcher{ - ctx: ctx, - cfg: cfg, - db: db, - crossMessageOrm: orm.NewCrossMessage(db), - client: client, - addressList: addressList, - syncInfo: syncInfo, + ctx: ctx, + cfg: cfg, + db: db, + syncInfo: syncInfo, + client: client, + eventUpdateLogic: logic.NewEventUpdateLogic(db), + l2FetcherLogic: logic.NewL2FetcherLogic(cfg, db, client), }, nil } // Start starts the L2 message fetching process. func (c *L2MessageFetcher) Start() { - l2SentMessageSyncedHeight, err := c.crossMessageOrm.GetMessageSyncedHeightInDB(c.ctx, orm.MessageTypeL2SentMessage) + l2SentMessageSyncedHeight, err := c.eventUpdateLogic.GetL2MessageSyncedHeightInDB(c.ctx) if err != nil { log.Error("failed to get L2 cross message processed height", "err", err) return } + c.syncInfo.SetL2ScanHeight(l2SentMessageSyncedHeight) log.Info("Start L2 message fetcher", "message synced height", l2SentMessageSyncedHeight) @@ -106,168 +81,61 @@ func (c *L2MessageFetcher) fetchAndSaveEvents(confirmation uint64) { if to > endHeight { to = endHeight } - err = c.doFetchAndSaveEvents(c.ctx, from, to, c.addressList) + + l2FilterResult, err := c.l2FetcherLogic.L2Fetcher(c.ctx, from, to) if err != nil { - log.Error("failed to fetch and save L2 events", "from", from, "to", to, "err", err) + log.Error("failed to fetch events", "from", from, "to", to, "err", err) return } - c.syncInfo.SetL2ScanHeight(to) - } -} - -func (c *L2MessageFetcher) doFetchAndSaveEvents(ctx context.Context, from uint64, to uint64, addrList []common.Address) error { - log.Info("fetch and save L2 events", "from", from, "to", to) - var l2FailedGatewayRouterTxs []*orm.CrossMessage - var l2RevertedRelayedMessages []*orm.CrossMessage - blockTimestampsMap := make(map[uint64]uint64) - blocks, err := utils.GetL2BlocksInRange(c.ctx, c.client, from, to) - if err != nil { - log.Error("failed to get L2 blocks in range", "from", from, "to", to, "err", err) - return err - } - for i := from; i <= to; i++ { - block := blocks[i-from] - blockTimestampsMap[block.NumberU64()] = block.Time() - - for _, tx := range block.Transactions() { - to := tx.To() - if to == nil { - continue - } - toAddress := to.String() - if toAddress == c.cfg.GatewayRouterAddr { - var receipt *types.Receipt - receipt, err = c.client.TransactionReceipt(ctx, tx.Hash()) - if err != nil { - log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", err) - return err - } - // Check if the transaction failed - if receipt.Status == types.ReceiptStatusFailed { - signer := types.NewLondonSigner(new(big.Int).SetUint64(tx.ChainId().Uint64())) - var sender common.Address - sender, err = signer.Sender(tx) - if err != nil { - log.Error("get sender failed", "chain id", tx.ChainId().Uint64(), "tx hash", tx.Hash().String(), "err", err) - return err - } - l2FailedGatewayRouterTxs = append(l2FailedGatewayRouterTxs, &orm.CrossMessage{ - L2TxHash: tx.Hash().String(), - MessageType: int(orm.MessageTypeL2SentMessage), - Sender: sender.String(), - Receiver: (*tx.To()).String(), - L2BlockNumber: receipt.BlockNumber.Uint64(), - BlockTimestamp: block.Time(), - TxStatus: int(orm.TxStatusTypeSentFailed), - }) - } - } - if tx.Type() == types.L1MessageTxType { - var receipt *types.Receipt - receipt, err = c.client.TransactionReceipt(ctx, tx.Hash()) - if err != nil { - log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", err) - return err - } - // Check if the transaction failed - if receipt.Status == types.ReceiptStatusFailed { - l2RevertedRelayedMessages = append(l2RevertedRelayedMessages, &orm.CrossMessage{ - MessageHash: "0x" + common.Bytes2Hex(crypto.Keccak256(tx.AsL1MessageTx().Data)), - L2TxHash: tx.Hash().String(), - TxStatus: int(orm.TxStatusTypeRelayedTxReverted), - L2BlockNumber: receipt.BlockNumber.Uint64(), - MessageType: int(orm.MessageTypeL1SentMessage), - }) - } - } + if updateWithdrawErr := c.updateL2WithdrawMessageProofs(c.ctx, l2FilterResult.WithdrawMessages, to); updateWithdrawErr != nil { + log.Error("failed to update l2 withdraw message failed", "from", from, "to", to, "err", err) + return } - } - - query := ethereum.FilterQuery{ - FromBlock: new(big.Int).SetUint64(from), // inclusive - ToBlock: new(big.Int).SetUint64(to), // inclusive - Addresses: addrList, - Topics: make([][]common.Hash, 1), - } - query.Topics[0] = make([]common.Hash, 7) - query.Topics[0][0] = backendabi.L2WithdrawETHSig - query.Topics[0][1] = backendabi.L2WithdrawERC20Sig - query.Topics[0][2] = backendabi.L2WithdrawERC721Sig - query.Topics[0][3] = backendabi.L2WithdrawERC1155Sig - query.Topics[0][4] = backendabi.L2SentMessageEventSig - query.Topics[0][5] = backendabi.L2RelayedMessageEventSig - query.Topics[0][6] = backendabi.L2FailedRelayedMessageEventSig - logs, err := c.client.FilterLogs(ctx, query) - if err != nil { - log.Error("Failed to filter L2 event logs", "from", from, "to", to, "err", err) - return err - } - l2WithdrawMessages, l2RelayedMessages, err := logic.ParseL2EventLogs(logs, blockTimestampsMap) - if err != nil { - log.Error("failed to parse L2 event logs", "from", from, "to", to, "err", err) - return err - } - - if err = c.updateL2WithdrawMessageProofs(ctx, l2WithdrawMessages, to); err != nil { - log.Error("failed to update withdraw message proofs", "err", err) - } - - err = c.db.Transaction(func(tx *gorm.DB) error { - if txErr := c.crossMessageOrm.InsertOrUpdateL2Messages(ctx, l2WithdrawMessages, tx); txErr != nil { - log.Error("failed to insert L2 withdrawal messages", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.InsertOrUpdateL2RelayedMessagesOfL1Deposits(ctx, l2RelayedMessages, tx); txErr != nil { - log.Error("failed to update L2 relayed messages of L1 deposits", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.InsertOrUpdateL2RevertedRelayedMessagesOfL1Deposits(ctx, l2RevertedRelayedMessages, tx); txErr != nil { - log.Error("failed to update L2 relayed messages of L1 deposits", "from", from, "to", to, "err", txErr) - return txErr - } - if txErr := c.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l2FailedGatewayRouterTxs, tx); txErr != nil { - log.Error("failed to insert L2 failed gateway router transactions", "from", from, "to", to, "err", txErr) - return txErr + if insertUpdateErr := c.eventUpdateLogic.L2InsertOrUpdate(c.ctx, l2FilterResult); insertUpdateErr != nil { + log.Error("failed to save L2 events", "from", from, "to", to, "err", err) + return } - return nil - }) - if err != nil { - log.Error("failed to update db of L2 events", "from", from, "to", to, "err", err) - return err + + c.syncInfo.SetL2ScanHeight(to) } - return nil } func (c *L2MessageFetcher) updateL2WithdrawMessageProofs(ctx context.Context, l2WithdrawMessages []*orm.CrossMessage, endBlock uint64) error { withdrawTrie := utils.NewWithdrawTrie() - message, err := c.crossMessageOrm.GetLatestL2Withdrawal(ctx) + message, err := c.eventUpdateLogic.GetL2LatestWithdrawal(ctx) if err != nil { log.Error("failed to get latest L2 sent message event", "err", err) return err } + if message != nil { withdrawTrie.Initialize(message.MessageNonce, common.HexToHash(message.MessageHash), message.MerkleProof) } + messageHashes := make([]common.Hash, len(l2WithdrawMessages)) for i, message := range l2WithdrawMessages { messageHashes[i] = common.HexToHash(message.MessageHash) } + proofs := withdrawTrie.AppendMessages(messageHashes) if len(l2WithdrawMessages) != len(proofs) { log.Error("invalid proof array length", "L2 withdrawal messages length", len(l2WithdrawMessages), "proofs length", len(proofs)) return fmt.Errorf("invalid proof array length: got %d proofs for %d l2WithdrawMessages", len(proofs), len(l2WithdrawMessages)) } + for i, proof := range proofs { l2WithdrawMessages[i].MerkleProof = proof } + // Verify if local info is correct. withdrawRoot, err := c.client.StorageAt(ctx, common.HexToAddress(c.cfg.MessageQueueAddr), common.Hash{}, new(big.Int).SetUint64(endBlock)) if err != nil { log.Error("failed to get withdraw root", "number", endBlock, "error", err) return fmt.Errorf("failed to get withdraw root: %v, number: %v", err, endBlock) } + if common.BytesToHash(withdrawRoot) != withdrawTrie.MessageRoot() { log.Error("withdraw root mismatch", "expected", common.BytesToHash(withdrawRoot).String(), "got", withdrawTrie.MessageRoot().String()) return fmt.Errorf("withdraw root mismatch. expected: %v, got: %v", common.BytesToHash(withdrawRoot), withdrawTrie.MessageRoot()) diff --git a/bridge-history-api/internal/logic/event_update.go b/bridge-history-api/internal/logic/event_update.go new file mode 100644 index 0000000000..856d05e420 --- /dev/null +++ b/bridge-history-api/internal/logic/event_update.go @@ -0,0 +1,153 @@ +package logic + +import ( + "context" + + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + "scroll-tech/bridge-history-api/internal/orm" +) + +// EventUpdateLogic the logic of insert/update the database +type EventUpdateLogic struct { + db *gorm.DB + crossMessageOrm *orm.CrossMessage + batchEventOrm *orm.BatchEvent +} + +// NewEventUpdateLogic create a EventUpdateLogic instance +func NewEventUpdateLogic(db *gorm.DB) *EventUpdateLogic { + return &EventUpdateLogic{ + db: db, + crossMessageOrm: orm.NewCrossMessage(db), + batchEventOrm: orm.NewBatchEvent(db), + } +} + +// GetL1SyncHeight get the l1 sync height from db +func (b *EventUpdateLogic) GetL1SyncHeight(ctx context.Context) (uint64, uint64, error) { + messageSyncedHeight, err := b.crossMessageOrm.GetMessageSyncedHeightInDB(ctx, orm.MessageTypeL1SentMessage) + if err != nil { + log.Error("failed to get L1 cross message synced height", "error", err) + return 0, 0, err + } + + batchSyncedHeight, err := b.batchEventOrm.GetBatchEventSyncedHeightInDB(ctx) + if err != nil { + log.Error("failed to get L1 batch event synced height", "error", err) + return 0, 0, err + } + + return messageSyncedHeight, batchSyncedHeight, nil +} + +// GetL2MessageSyncedHeightInDB get l2 messages synced height +func (b *EventUpdateLogic) GetL2MessageSyncedHeightInDB(ctx context.Context) (uint64, error) { + l2SentMessageSyncedHeight, err := b.crossMessageOrm.GetMessageSyncedHeightInDB(ctx, orm.MessageTypeL2SentMessage) + if err != nil { + log.Error("failed to get L2 cross message processed height", "err", err) + return 0, err + } + return l2SentMessageSyncedHeight, nil +} + +// GetL2LatestWithdrawal get l2 latest withdrawal message +func (b *EventUpdateLogic) GetL2LatestWithdrawal(ctx context.Context) (*orm.CrossMessage, error) { + message, err := b.crossMessageOrm.GetLatestL2Withdrawal(ctx) + if err != nil { + log.Error("failed to get latest L2 sent message event", "err", err) + return nil, err + } + return message, nil +} + +// L1InsertOrUpdate insert or update l1 messages +func (b *EventUpdateLogic) L1InsertOrUpdate(ctx context.Context, l1FetcherResult *L1FilterResult) error { + err := b.db.Transaction(func(tx *gorm.DB) error { + if txErr := b.crossMessageOrm.InsertOrUpdateL1Messages(ctx, l1FetcherResult.DepositMessages, tx); txErr != nil { + log.Error("failed to insert L1 deposit messages", "err", txErr) + return txErr + } + + if txErr := b.crossMessageOrm.InsertOrUpdateL1RelayedMessagesOfL2Withdrawals(ctx, l1FetcherResult.RelayedMessages, tx); txErr != nil { + log.Error("failed to update L1 relayed messages of L2 withdrawals", "err", txErr) + return txErr + } + + if txErr := b.batchEventOrm.InsertOrUpdateBatchEvents(ctx, l1FetcherResult.BatchEvents, tx); txErr != nil { + log.Error("failed to insert or update batch events", "err", txErr) + return txErr + } + + if txErr := b.crossMessageOrm.UpdateL1MessageQueueEventsInfo(ctx, l1FetcherResult.MessageQueueEvents, tx); txErr != nil { + log.Error("failed to insert L1 message queue events", "err", txErr) + return txErr + } + + if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l1FetcherResult.FailedGatewayRouterTxs, tx); txErr != nil { + log.Error("failed to insert L1 failed gateway router transactions", "err", txErr) + return txErr + } + return nil + }) + + if err != nil { + log.Error("failed to update db of L1 events", "err", err) + return err + } + + return nil +} + +// UpdateL1BatchIndexAndStatus update l1 batch index and status +func (b *EventUpdateLogic) UpdateL1BatchIndexAndStatus(ctx context.Context, height uint64) error { + batches, err := b.batchEventOrm.GetBatchesLEBlockHeight(ctx, height) + if err != nil { + log.Error("failed to get batches >= block height", "error", err) + return err + } + + for _, batch := range batches { + log.Info("update batch info of L2 withdrawals", "index", batch.BatchIndex, "start", batch.StartBlockNumber, "end", batch.EndBlockNumber) + if err = b.crossMessageOrm.UpdateBatchStatusOfL2Withdrawals(ctx, batch.StartBlockNumber, batch.EndBlockNumber, batch.BatchIndex); err != nil { + log.Error("failed to update batch status of L2 sent messages", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", err) + return err + } + if err = b.batchEventOrm.UpdateBatchEventStatus(ctx, batch.BatchIndex); err != nil { + log.Error("failed to update batch event status as updated", "start", batch.StartBlockNumber, "end", batch.EndBlockNumber, "index", batch.BatchIndex, "error", err) + return err + } + } + + return nil +} + +// L2InsertOrUpdate insert or update l2 messages +func (b *EventUpdateLogic) L2InsertOrUpdate(ctx context.Context, l2FetcherResult *L2FilterResult) error { + err := b.db.Transaction(func(tx *gorm.DB) error { + if txErr := b.crossMessageOrm.InsertOrUpdateL2Messages(ctx, l2FetcherResult.WithdrawMessages, tx); txErr != nil { + log.Error("failed to insert L2 withdrawal messages", "err", txErr) + return txErr + } + if txErr := b.crossMessageOrm.InsertOrUpdateL2RelayedMessagesOfL1Deposits(ctx, l2FetcherResult.RelayedMessages, tx); txErr != nil { + log.Error("failed to update L2 relayed messages of L1 deposits", "err", txErr) + return txErr + } + if txErr := b.crossMessageOrm.InsertOrUpdateL2RevertedRelayedMessagesOfL1Deposits(ctx, l2FetcherResult.RevertedRelayedMessages, tx); txErr != nil { + log.Error("failed to update L2 relayed messages of L1 deposits", "err", txErr) + return txErr + } + if txErr := b.crossMessageOrm.InsertFailedGatewayRouterTxs(ctx, l2FetcherResult.FailedGatewayRouterTxs, tx); txErr != nil { + log.Error("failed to insert L2 failed gateway router transactions", "err", txErr) + return txErr + } + return nil + }) + + if err != nil { + log.Error("failed to update db of L2 events", "err", err) + return err + } + return nil +} diff --git a/bridge-history-api/internal/logic/history_logic.go b/bridge-history-api/internal/logic/history_logic.go index 48c6135ca8..ee3de52ba1 100644 --- a/bridge-history-api/internal/logic/history_logic.go +++ b/bridge-history-api/internal/logic/history_logic.go @@ -354,7 +354,6 @@ func (h *HistoryLogic) cacheTxsInfo(ctx context.Context, cacheKey string, txs [] } return nil }) - if err != nil { log.Error("failed to execute transaction", "error", err) return err diff --git a/bridge-history-api/internal/logic/watcher_event_parser.go b/bridge-history-api/internal/logic/l1_event_parser.go similarity index 56% rename from bridge-history-api/internal/logic/watcher_event_parser.go rename to bridge-history-api/internal/logic/l1_event_parser.go index 9fdd461b54..28ec90f214 100644 --- a/bridge-history-api/internal/logic/watcher_event_parser.go +++ b/bridge-history-api/internal/logic/l1_event_parser.go @@ -2,10 +2,7 @@ package logic import ( "context" - "math/big" - "strings" - "github.com/scroll-tech/go-ethereum/common/hexutil" "github.com/scroll-tech/go-ethereum/core/types" "github.com/scroll-tech/go-ethereum/ethclient" "github.com/scroll-tech/go-ethereum/log" @@ -15,8 +12,17 @@ import ( "scroll-tech/bridge-history-api/internal/utils" ) +// L1EventParser the l1 event parser +type L1EventParser struct { +} + +// NewL1EventParser create l1 event parser +func NewL1EventParser() *L1EventParser { + return &L1EventParser{} +} + // ParseL1CrossChainEventLogs parses L1 watched cross chain events. -func ParseL1CrossChainEventLogs(ctx context.Context, logs []types.Log, blockTimestampsMap map[uint64]uint64, client *ethclient.Client) ([]*orm.CrossMessage, []*orm.CrossMessage, error) { +func (e *L1EventParser) ParseL1CrossChainEventLogs(logs []types.Log, blockTimestampsMap map[uint64]uint64) ([]*orm.CrossMessage, []*orm.CrossMessage, error) { var l1DepositMessages []*orm.CrossMessage var l1RelayedMessages []*orm.CrossMessage for _, vlog := range logs { @@ -71,7 +77,7 @@ func ParseL1CrossChainEventLogs(ctx context.Context, logs []types.Log, blockTime lastMessage.TokenType = int(orm.TokenTypeERC721) lastMessage.L1TokenAddress = event.L1Token.String() lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = convertBigIntArrayToString(event.TokenIDs) + lastMessage.TokenIDs = utils.ConvertBigIntArrayToString(event.TokenIDs) case backendabi.L1DepositERC1155Sig: event := backendabi.ERC1155MessageEvent{} if err := utils.UnpackLog(backendabi.IL1ERC1155GatewayABI, &event, "DepositERC1155", vlog); err != nil { @@ -98,8 +104,8 @@ func ParseL1CrossChainEventLogs(ctx context.Context, logs []types.Log, blockTime lastMessage.TokenType = int(orm.TokenTypeERC1155) lastMessage.L1TokenAddress = event.L1Token.String() lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = convertBigIntArrayToString(event.TokenIDs) - lastMessage.TokenAmounts = convertBigIntArrayToString(event.TokenAmounts) + lastMessage.TokenIDs = utils.ConvertBigIntArrayToString(event.TokenIDs) + lastMessage.TokenAmounts = utils.ConvertBigIntArrayToString(event.TokenAmounts) case backendabi.L1SentMessageEventSig: event := backendabi.L1SentMessageEvent{} if err := utils.UnpackLog(backendabi.IL1ScrollMessengerABI, &event, "SentMessage", vlog); err != nil { @@ -153,7 +159,7 @@ func ParseL1CrossChainEventLogs(ctx context.Context, logs []types.Log, blockTime } // ParseL1BatchEventLogs parses L1 watched batch events. -func ParseL1BatchEventLogs(ctx context.Context, logs []types.Log, blockTimestampsMap map[uint64]uint64, client *ethclient.Client) ([]*orm.BatchEvent, error) { +func (e *L1EventParser) ParseL1BatchEventLogs(ctx context.Context, logs []types.Log, client *ethclient.Client) ([]*orm.BatchEvent, error) { var l1BatchEvents []*orm.BatchEvent for _, vlog := range logs { switch vlog.Topics[0] { @@ -211,7 +217,7 @@ func ParseL1BatchEventLogs(ctx context.Context, logs []types.Log, blockTimestamp } // ParseL1MessageQueueEventLogs parses L1 watched message queue events. -func ParseL1MessageQueueEventLogs(ctx context.Context, logs []types.Log, blockTimestampsMap map[uint64]uint64, client *ethclient.Client) ([]*orm.MessageQueueEvent, error) { +func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log) ([]*orm.MessageQueueEvent, error) { var l1MessageQueueEvents []*orm.MessageQueueEvent for _, vlog := range logs { switch vlog.Topics[0] { @@ -234,7 +240,7 @@ func ParseL1MessageQueueEventLogs(ctx context.Context, logs []types.Log, blockTi log.Warn("Failed to unpack DequeueTransaction event", "err", err) return nil, err } - skippedIndices := getSkippedQueueIndices(event.StartIndex.Uint64(), event.SkippedBitmap) + skippedIndices := utils.GetSkippedQueueIndices(event.StartIndex.Uint64(), event.SkippedBitmap) for _, index := range skippedIndices { l1MessageQueueEvents = append(l1MessageQueueEvents, &orm.MessageQueueEvent{ EventType: orm.MessageQueueEventTypeDequeueTransaction, @@ -255,175 +261,3 @@ func ParseL1MessageQueueEventLogs(ctx context.Context, logs []types.Log, blockTi } return l1MessageQueueEvents, nil } - -// ParseL2EventLogs parses L2 watched events -func ParseL2EventLogs(logs []types.Log, blockTimestampsMap map[uint64]uint64) ([]*orm.CrossMessage, []*orm.CrossMessage, error) { - var l2WithdrawMessages []*orm.CrossMessage - var l2RelayedMessages []*orm.CrossMessage - for _, vlog := range logs { - switch vlog.Topics[0] { - case backendabi.L2WithdrawETHSig: - event := backendabi.ETHMessageEvent{} - err := utils.UnpackLog(backendabi.IL2ETHGatewayABI, &event, "WithdrawETH", vlog) - if err != nil { - log.Warn("Failed to unpack WithdrawETH event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeETH) - lastMessage.TokenAmounts = event.Amount.String() - case backendabi.L2WithdrawERC20Sig: - event := backendabi.ERC20MessageEvent{} - err := utils.UnpackLog(backendabi.IL2ERC20GatewayABI, &event, "WithdrawERC20", vlog) - if err != nil { - log.Warn("Failed to unpack WithdrawERC20 event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeERC20) - lastMessage.L1TokenAddress = event.L1Token.String() - lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenAmounts = event.Amount.String() - case backendabi.L2WithdrawERC721Sig: - event := backendabi.ERC721MessageEvent{} - err := utils.UnpackLog(backendabi.IL2ERC721GatewayABI, &event, "WithdrawERC721", vlog) - if err != nil { - log.Warn("Failed to unpack WithdrawERC721 event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeERC721) - lastMessage.L1TokenAddress = event.L1Token.String() - lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = event.TokenID.String() - case backendabi.L2BatchWithdrawERC721Sig: - event := backendabi.BatchERC721MessageEvent{} - err := utils.UnpackLog(backendabi.IL2ERC721GatewayABI, &event, "BatchWithdrawERC721", vlog) - if err != nil { - log.Warn("Failed to unpack BatchWithdrawERC721 event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeERC721) - lastMessage.L1TokenAddress = event.L1Token.String() - lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = convertBigIntArrayToString(event.TokenIDs) - case backendabi.L2WithdrawERC1155Sig: - event := backendabi.ERC1155MessageEvent{} - err := utils.UnpackLog(backendabi.IL2ERC1155GatewayABI, &event, "WithdrawERC1155", vlog) - if err != nil { - log.Warn("Failed to unpack WithdrawERC1155 event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeERC1155) - lastMessage.L1TokenAddress = event.L1Token.String() - lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = event.TokenID.String() - lastMessage.TokenAmounts = event.Amount.String() - case backendabi.L2BatchWithdrawERC1155Sig: - event := backendabi.BatchERC1155MessageEvent{} - err := utils.UnpackLog(backendabi.IL2ERC1155GatewayABI, &event, "BatchWithdrawERC1155", vlog) - if err != nil { - log.Warn("Failed to unpack BatchWithdrawERC1155 event", "err", err) - return nil, nil, err - } - lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] - lastMessage.Sender = event.From.String() - lastMessage.Receiver = event.To.String() - lastMessage.TokenType = int(orm.TokenTypeERC1155) - lastMessage.L1TokenAddress = event.L1Token.String() - lastMessage.L2TokenAddress = event.L2Token.String() - lastMessage.TokenIDs = convertBigIntArrayToString(event.TokenIDs) - lastMessage.TokenAmounts = convertBigIntArrayToString(event.TokenAmounts) - case backendabi.L2SentMessageEventSig: - event := backendabi.L2SentMessageEvent{} - err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "SentMessage", vlog) - if err != nil { - log.Warn("Failed to unpack SentMessage event", "err", err) - return nil, nil, err - } - // Use this messageHash as next deposit event's messageHash - messageHash := utils.ComputeMessageHash(event.Sender, event.Target, event.Value, event.MessageNonce, event.Message) - l2WithdrawMessages = append(l2WithdrawMessages, &orm.CrossMessage{ - MessageHash: messageHash.String(), - Sender: event.Sender.String(), - Receiver: event.Target.String(), - TokenType: int(orm.TokenTypeETH), - L2TxHash: vlog.TxHash.String(), - TokenAmounts: event.Value.String(), - MessageFrom: event.Sender.String(), - MessageTo: event.Target.String(), - MessageValue: event.Value.String(), - MessageNonce: event.MessageNonce.Uint64(), - MessageData: hexutil.Encode(event.Message), - MessageType: int(orm.MessageTypeL2SentMessage), - TxStatus: int(orm.TxStatusTypeSent), - BlockTimestamp: blockTimestampsMap[vlog.BlockNumber], - L2BlockNumber: vlog.BlockNumber, - }) - case backendabi.L2RelayedMessageEventSig: - event := backendabi.L2RelayedMessageEvent{} - err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "RelayedMessage", vlog) - if err != nil { - log.Warn("Failed to unpack RelayedMessage event", "err", err) - return nil, nil, err - } - l2RelayedMessages = append(l2RelayedMessages, &orm.CrossMessage{ - MessageHash: event.MessageHash.String(), - L2BlockNumber: vlog.BlockNumber, - L2TxHash: vlog.TxHash.String(), - TxStatus: int(orm.TxStatusTypeRelayed), - MessageType: int(orm.MessageTypeL1SentMessage), - }) - case backendabi.L2FailedRelayedMessageEventSig: - event := backendabi.L2RelayedMessageEvent{} - err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "FailedRelayedMessage", vlog) - if err != nil { - log.Warn("Failed to unpack FailedRelayedMessage event", "err", err) - return nil, nil, err - } - l2RelayedMessages = append(l2RelayedMessages, &orm.CrossMessage{ - MessageHash: event.MessageHash.String(), - L2BlockNumber: vlog.BlockNumber, - L2TxHash: vlog.TxHash.String(), - TxStatus: int(orm.TxStatusTypeFailedRelayed), - MessageType: int(orm.MessageTypeL1SentMessage), - }) - } - } - return l2WithdrawMessages, l2RelayedMessages, nil -} - -func convertBigIntArrayToString(array []*big.Int) string { - stringArray := make([]string, len(array)) - for i, num := range array { - stringArray[i] = num.String() - } - - result := strings.Join(stringArray, ", ") - return result -} - -func getSkippedQueueIndices(startIndex uint64, skippedBitmap *big.Int) []uint64 { - var indices []uint64 - for i := 0; i < 256; i++ { - index := startIndex + uint64(i) - bit := new(big.Int).Rsh(skippedBitmap, uint(i)) - if bit.Bit(0) == 0 { - continue - } - indices = append(indices, index) - } - return indices -} diff --git a/bridge-history-api/internal/logic/l1_fetcher.go b/bridge-history-api/internal/logic/l1_fetcher.go new file mode 100644 index 0000000000..57b7badcd9 --- /dev/null +++ b/bridge-history-api/internal/logic/l1_fetcher.go @@ -0,0 +1,210 @@ +package logic + +import ( + "context" + "math/big" + + "github.com/scroll-tech/go-ethereum" + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/ethclient" + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + backendabi "scroll-tech/bridge-history-api/abi" + "scroll-tech/bridge-history-api/internal/config" + "scroll-tech/bridge-history-api/internal/orm" + "scroll-tech/bridge-history-api/internal/utils" +) + +// L1FilterResult l1 fetcher result +type L1FilterResult struct { + FailedGatewayRouterTxs []*orm.CrossMessage + DepositMessages []*orm.CrossMessage + RelayedMessages []*orm.CrossMessage + BatchEvents []*orm.BatchEvent + MessageQueueEvents []*orm.MessageQueueEvent +} + +// L1FetcherLogic the l1 fetcher's logic +type L1FetcherLogic struct { + cfg *config.LayerConfig + client *ethclient.Client + addressList []common.Address + parser *L1EventParser + db *gorm.DB + crossMessageOrm *orm.CrossMessage + batchEventOrm *orm.BatchEvent +} + +// NewL1FetcherLogic create l1 fetcher logic +func NewL1FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client) *L1FetcherLogic { + addressList := []common.Address{ + common.HexToAddress(cfg.ETHGatewayAddr), + + common.HexToAddress(cfg.StandardERC20GatewayAddr), + common.HexToAddress(cfg.CustomERC20GatewayAddr), + common.HexToAddress(cfg.WETHGatewayAddr), + common.HexToAddress(cfg.DAIGatewayAddr), + + common.HexToAddress(cfg.ERC721GatewayAddr), + common.HexToAddress(cfg.ERC1155GatewayAddr), + + common.HexToAddress(cfg.MessengerAddr), + + common.HexToAddress(cfg.ScrollChainAddr), + + common.HexToAddress(cfg.MessageQueueAddr), + } + + // Optional erc20 gateways. + if cfg.USDCGatewayAddr != "" { + addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr)) + } + + if cfg.LIDOGatewayAddr != "" { + addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr)) + } + + return &L1FetcherLogic{ + db: db, + crossMessageOrm: orm.NewCrossMessage(db), + batchEventOrm: orm.NewBatchEvent(db), + cfg: cfg, + client: client, + addressList: addressList, + parser: NewL1EventParser(), + } +} + +func (f *L1FetcherLogic) gatewayRouterFailedTxs(ctx context.Context, from, to uint64) (map[uint64]uint64, []*orm.CrossMessage, error) { + blocks, err := utils.GetL1BlocksInRange(ctx, f.client, from, to) + if err != nil { + log.Error("failed to get L1 blocks in range", "from", from, "to", to, "err", err) + return nil, nil, err + } + + blockTimestampsMap := make(map[uint64]uint64) + var l1FailedGatewayRouterTxs []*orm.CrossMessage + for i := from; i <= to; i++ { + block := blocks[i-from] + blockTimestampsMap[block.NumberU64()] = block.Time() + + for _, tx := range block.Transactions() { + txTo := tx.To() + if txTo == nil { + continue + } + toAddress := txTo.String() + + if toAddress != f.cfg.GatewayRouterAddr { + continue + } + + var receipt *types.Receipt + receipt, receiptErr := f.client.TransactionReceipt(ctx, tx.Hash()) + if receiptErr != nil { + log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", receiptErr) + return nil, nil, receiptErr + } + + // Check if the transaction failed + if receipt.Status != types.ReceiptStatusFailed { + continue + } + + signer := types.NewLondonSigner(new(big.Int).SetUint64(tx.ChainId().Uint64())) + sender, senderErr := signer.Sender(tx) + if senderErr != nil { + log.Error("get sender failed", "chain id", tx.ChainId().Uint64(), "tx hash", tx.Hash().String(), "err", senderErr) + return nil, nil, senderErr + } + + l1FailedGatewayRouterTxs = append(l1FailedGatewayRouterTxs, &orm.CrossMessage{ + L1TxHash: tx.Hash().String(), + MessageType: int(orm.MessageTypeL1SentMessage), + Sender: sender.String(), + Receiver: (*tx.To()).String(), + L1BlockNumber: receipt.BlockNumber.Uint64(), + BlockTimestamp: block.Time(), + TxStatus: int(orm.TxStatusTypeSentFailed), + }) + } + } + return blockTimestampsMap, l1FailedGatewayRouterTxs, nil +} + +func (f *L1FetcherLogic) l1FetcherLogs(ctx context.Context, from, to uint64) ([]types.Log, error) { + query := ethereum.FilterQuery{ + FromBlock: new(big.Int).SetUint64(from), // inclusive + ToBlock: new(big.Int).SetUint64(to), // inclusive + Addresses: f.addressList, + Topics: make([][]common.Hash, 1), + } + + query.Topics[0] = make([]common.Hash, 13) + query.Topics[0][0] = backendabi.L1DepositETHSig + query.Topics[0][1] = backendabi.L1DepositERC20Sig + query.Topics[0][2] = backendabi.L1DepositERC721Sig + query.Topics[0][3] = backendabi.L1DepositERC1155Sig + query.Topics[0][4] = backendabi.L1SentMessageEventSig + query.Topics[0][5] = backendabi.L1RelayedMessageEventSig + query.Topics[0][6] = backendabi.L1FailedRelayedMessageEventSig + query.Topics[0][7] = backendabi.L1CommitBatchEventSig + query.Topics[0][8] = backendabi.L1RevertBatchEventSig + query.Topics[0][9] = backendabi.L1FinalizeBatchEventSig + query.Topics[0][10] = backendabi.L1QueueTransactionEventSig + query.Topics[0][11] = backendabi.L1DequeueTransactionEventSig + query.Topics[0][12] = backendabi.L1DropTransactionEventSig + + eventLogs, err := f.client.FilterLogs(ctx, query) + if err != nil { + log.Error("failed to filter L1 event logs", "from", from, "to", to, "err", err) + return nil, err + } + return eventLogs, nil +} + +// L1Fetcher l1 fetcher +func (f *L1FetcherLogic) L1Fetcher(ctx context.Context, from, to uint64) (*L1FilterResult, error) { + log.Info("fetch and save L1 events", "from", from, "to", to) + + blockTimestampsMap, l1FailedGatewayRouterTxs, err := f.gatewayRouterFailedTxs(ctx, from, to) + if err != nil { + log.Error("L1Fetcher gatewayRouterFailedTxs failed", "from", from, "to", to, "error", err) + return nil, err + } + + eventLogs, err := f.l1FetcherLogs(ctx, from, to) + if err != nil { + log.Error("L1Fetcher l1FetcherLogs failed", "from", from, "to", to, "error", err) + return nil, err + } + + l1DepositMessages, l1RelayedMessages, err := f.parser.ParseL1CrossChainEventLogs(eventLogs, blockTimestampsMap) + if err != nil { + log.Error("failed to parse L1 cross chain event logs", "from", from, "to", to, "err", err) + return nil, err + } + + l1BatchEvents, err := f.parser.ParseL1BatchEventLogs(ctx, eventLogs, f.client) + if err != nil { + log.Error("failed to parse L1 batch event logs", "from", from, "to", to, "err", err) + return nil, err + } + + l1MessageQueueEvents, err := f.parser.ParseL1MessageQueueEventLogs(eventLogs) + if err != nil { + log.Error("failed to parse L1 message queue event logs", "from", from, "to", to, "err", err) + return nil, err + } + + res := L1FilterResult{ + FailedGatewayRouterTxs: l1FailedGatewayRouterTxs, + DepositMessages: l1DepositMessages, + RelayedMessages: l1RelayedMessages, + BatchEvents: l1BatchEvents, + MessageQueueEvents: l1MessageQueueEvents, + } + return &res, nil +} diff --git a/bridge-history-api/internal/logic/l2_event_parser.go b/bridge-history-api/internal/logic/l2_event_parser.go new file mode 100644 index 0000000000..ab76289a53 --- /dev/null +++ b/bridge-history-api/internal/logic/l2_event_parser.go @@ -0,0 +1,169 @@ +package logic + +import ( + "github.com/scroll-tech/go-ethereum/common/hexutil" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/log" + + backendabi "scroll-tech/bridge-history-api/abi" + "scroll-tech/bridge-history-api/internal/orm" + "scroll-tech/bridge-history-api/internal/utils" +) + +// L2EventParser the l2 event parser +type L2EventParser struct { +} + +// NewL2EventParser create the l2 event parser +func NewL2EventParser() *L2EventParser { + return &L2EventParser{} +} + +// ParseL2EventLogs parses L2 watched events +func (e *L2EventParser) ParseL2EventLogs(logs []types.Log, blockTimestampsMap map[uint64]uint64) ([]*orm.CrossMessage, []*orm.CrossMessage, error) { + var l2WithdrawMessages []*orm.CrossMessage + var l2RelayedMessages []*orm.CrossMessage + for _, vlog := range logs { + switch vlog.Topics[0] { + case backendabi.L2WithdrawETHSig: + event := backendabi.ETHMessageEvent{} + err := utils.UnpackLog(backendabi.IL2ETHGatewayABI, &event, "WithdrawETH", vlog) + if err != nil { + log.Warn("Failed to unpack WithdrawETH event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeETH) + lastMessage.TokenAmounts = event.Amount.String() + case backendabi.L2WithdrawERC20Sig: + event := backendabi.ERC20MessageEvent{} + err := utils.UnpackLog(backendabi.IL2ERC20GatewayABI, &event, "WithdrawERC20", vlog) + if err != nil { + log.Warn("Failed to unpack WithdrawERC20 event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeERC20) + lastMessage.L1TokenAddress = event.L1Token.String() + lastMessage.L2TokenAddress = event.L2Token.String() + lastMessage.TokenAmounts = event.Amount.String() + case backendabi.L2WithdrawERC721Sig: + event := backendabi.ERC721MessageEvent{} + err := utils.UnpackLog(backendabi.IL2ERC721GatewayABI, &event, "WithdrawERC721", vlog) + if err != nil { + log.Warn("Failed to unpack WithdrawERC721 event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeERC721) + lastMessage.L1TokenAddress = event.L1Token.String() + lastMessage.L2TokenAddress = event.L2Token.String() + lastMessage.TokenIDs = event.TokenID.String() + case backendabi.L2BatchWithdrawERC721Sig: + event := backendabi.BatchERC721MessageEvent{} + err := utils.UnpackLog(backendabi.IL2ERC721GatewayABI, &event, "BatchWithdrawERC721", vlog) + if err != nil { + log.Warn("Failed to unpack BatchWithdrawERC721 event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeERC721) + lastMessage.L1TokenAddress = event.L1Token.String() + lastMessage.L2TokenAddress = event.L2Token.String() + lastMessage.TokenIDs = utils.ConvertBigIntArrayToString(event.TokenIDs) + case backendabi.L2WithdrawERC1155Sig: + event := backendabi.ERC1155MessageEvent{} + err := utils.UnpackLog(backendabi.IL2ERC1155GatewayABI, &event, "WithdrawERC1155", vlog) + if err != nil { + log.Warn("Failed to unpack WithdrawERC1155 event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeERC1155) + lastMessage.L1TokenAddress = event.L1Token.String() + lastMessage.L2TokenAddress = event.L2Token.String() + lastMessage.TokenIDs = event.TokenID.String() + lastMessage.TokenAmounts = event.Amount.String() + case backendabi.L2BatchWithdrawERC1155Sig: + event := backendabi.BatchERC1155MessageEvent{} + err := utils.UnpackLog(backendabi.IL2ERC1155GatewayABI, &event, "BatchWithdrawERC1155", vlog) + if err != nil { + log.Warn("Failed to unpack BatchWithdrawERC1155 event", "err", err) + return nil, nil, err + } + lastMessage := l2WithdrawMessages[len(l2WithdrawMessages)-1] + lastMessage.Sender = event.From.String() + lastMessage.Receiver = event.To.String() + lastMessage.TokenType = int(orm.TokenTypeERC1155) + lastMessage.L1TokenAddress = event.L1Token.String() + lastMessage.L2TokenAddress = event.L2Token.String() + lastMessage.TokenIDs = utils.ConvertBigIntArrayToString(event.TokenIDs) + lastMessage.TokenAmounts = utils.ConvertBigIntArrayToString(event.TokenAmounts) + case backendabi.L2SentMessageEventSig: + event := backendabi.L2SentMessageEvent{} + err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "SentMessage", vlog) + if err != nil { + log.Warn("Failed to unpack SentMessage event", "err", err) + return nil, nil, err + } + // Use this messageHash as next deposit event's messageHash + messageHash := utils.ComputeMessageHash(event.Sender, event.Target, event.Value, event.MessageNonce, event.Message) + l2WithdrawMessages = append(l2WithdrawMessages, &orm.CrossMessage{ + MessageHash: messageHash.String(), + Sender: event.Sender.String(), + Receiver: event.Target.String(), + TokenType: int(orm.TokenTypeETH), + L2TxHash: vlog.TxHash.String(), + TokenAmounts: event.Value.String(), + MessageFrom: event.Sender.String(), + MessageTo: event.Target.String(), + MessageValue: event.Value.String(), + MessageNonce: event.MessageNonce.Uint64(), + MessageData: hexutil.Encode(event.Message), + MessageType: int(orm.MessageTypeL2SentMessage), + TxStatus: int(orm.TxStatusTypeSent), + BlockTimestamp: blockTimestampsMap[vlog.BlockNumber], + L2BlockNumber: vlog.BlockNumber, + }) + case backendabi.L2RelayedMessageEventSig: + event := backendabi.L2RelayedMessageEvent{} + err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "RelayedMessage", vlog) + if err != nil { + log.Warn("Failed to unpack RelayedMessage event", "err", err) + return nil, nil, err + } + l2RelayedMessages = append(l2RelayedMessages, &orm.CrossMessage{ + MessageHash: event.MessageHash.String(), + L2BlockNumber: vlog.BlockNumber, + L2TxHash: vlog.TxHash.String(), + TxStatus: int(orm.TxStatusTypeRelayed), + MessageType: int(orm.MessageTypeL1SentMessage), + }) + case backendabi.L2FailedRelayedMessageEventSig: + event := backendabi.L2RelayedMessageEvent{} + err := utils.UnpackLog(backendabi.IL2ScrollMessengerABI, &event, "FailedRelayedMessage", vlog) + if err != nil { + log.Warn("Failed to unpack FailedRelayedMessage event", "err", err) + return nil, nil, err + } + l2RelayedMessages = append(l2RelayedMessages, &orm.CrossMessage{ + MessageHash: event.MessageHash.String(), + L2BlockNumber: vlog.BlockNumber, + L2TxHash: vlog.TxHash.String(), + TxStatus: int(orm.TxStatusTypeFailedRelayed), + MessageType: int(orm.MessageTypeL1SentMessage), + }) + } + } + return l2WithdrawMessages, l2RelayedMessages, nil +} diff --git a/bridge-history-api/internal/logic/l2_fetcher.go b/bridge-history-api/internal/logic/l2_fetcher.go new file mode 100644 index 0000000000..7428360ffd --- /dev/null +++ b/bridge-history-api/internal/logic/l2_fetcher.go @@ -0,0 +1,202 @@ +package logic + +import ( + "context" + "math/big" + + "github.com/scroll-tech/go-ethereum" + "github.com/scroll-tech/go-ethereum/common" + "github.com/scroll-tech/go-ethereum/core/types" + "github.com/scroll-tech/go-ethereum/crypto" + "github.com/scroll-tech/go-ethereum/ethclient" + "github.com/scroll-tech/go-ethereum/log" + "gorm.io/gorm" + + backendabi "scroll-tech/bridge-history-api/abi" + "scroll-tech/bridge-history-api/internal/config" + "scroll-tech/bridge-history-api/internal/orm" + "scroll-tech/bridge-history-api/internal/utils" +) + +// L2FilterResult the l2 filter result +type L2FilterResult struct { + FailedGatewayRouterTxs []*orm.CrossMessage + RevertedRelayedMessages []*orm.CrossMessage + WithdrawMessages []*orm.CrossMessage + RelayedMessages []*orm.CrossMessage +} + +// L2FetcherLogic the l2 fetcher's logic +type L2FetcherLogic struct { + cfg *config.LayerConfig + client *ethclient.Client + addressList []common.Address + parser *L2EventParser + db *gorm.DB + crossMessageOrm *orm.CrossMessage + batchEventOrm *orm.BatchEvent +} + +// NewL2FetcherLogic create l2 fetcher logic +func NewL2FetcherLogic(cfg *config.LayerConfig, db *gorm.DB, client *ethclient.Client) *L2FetcherLogic { + addressList := []common.Address{ + common.HexToAddress(cfg.ETHGatewayAddr), + + common.HexToAddress(cfg.StandardERC20GatewayAddr), + common.HexToAddress(cfg.CustomERC20GatewayAddr), + common.HexToAddress(cfg.WETHGatewayAddr), + common.HexToAddress(cfg.DAIGatewayAddr), + + common.HexToAddress(cfg.ERC721GatewayAddr), + common.HexToAddress(cfg.ERC1155GatewayAddr), + + common.HexToAddress(cfg.MessengerAddr), + } + + // Optional erc20 gateways. + if cfg.USDCGatewayAddr != "" { + addressList = append(addressList, common.HexToAddress(cfg.USDCGatewayAddr)) + } + + if cfg.LIDOGatewayAddr != "" { + addressList = append(addressList, common.HexToAddress(cfg.LIDOGatewayAddr)) + } + + return &L2FetcherLogic{ + db: db, + crossMessageOrm: orm.NewCrossMessage(db), + batchEventOrm: orm.NewBatchEvent(db), + cfg: cfg, + client: client, + addressList: addressList, + parser: NewL2EventParser(), + } +} + +func (f *L2FetcherLogic) gatewayRouterFailedTxs(ctx context.Context, from, to uint64) (map[uint64]uint64, []*orm.CrossMessage, []*orm.CrossMessage, error) { + var l2FailedGatewayRouterTxs []*orm.CrossMessage + var l2RevertedRelayedMessages []*orm.CrossMessage + blockTimestampsMap := make(map[uint64]uint64) + + blocks, err := utils.GetL2BlocksInRange(ctx, f.client, from, to) + if err != nil { + log.Error("failed to get L2 blocks in range", "from", from, "to", to, "err", err) + return nil, nil, nil, err + } + + for i := from; i <= to; i++ { + block := blocks[i-from] + blockTimestampsMap[block.NumberU64()] = block.Time() + + for _, tx := range block.Transactions() { + txTo := tx.To() + if txTo == nil { + continue + } + toAddress := txTo.String() + + if toAddress == f.cfg.GatewayRouterAddr { + receipt, receiptErr := f.client.TransactionReceipt(ctx, tx.Hash()) + if receiptErr != nil { + log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", receiptErr) + return nil, nil, nil, receiptErr + } + + // Check if the transaction failed + if receipt.Status == types.ReceiptStatusFailed { + signer := types.NewLondonSigner(new(big.Int).SetUint64(tx.ChainId().Uint64())) + sender, signerErr := signer.Sender(tx) + if signerErr != nil { + log.Error("get sender failed", "chain id", tx.ChainId().Uint64(), "tx hash", tx.Hash().String(), "err", signerErr) + return nil, nil, nil, signerErr + } + + l2FailedGatewayRouterTxs = append(l2FailedGatewayRouterTxs, &orm.CrossMessage{ + L2TxHash: tx.Hash().String(), + MessageType: int(orm.MessageTypeL2SentMessage), + Sender: sender.String(), + Receiver: (*tx.To()).String(), + L2BlockNumber: receipt.BlockNumber.Uint64(), + BlockTimestamp: block.Time(), + TxStatus: int(orm.TxStatusTypeSentFailed), + }) + } + } + + if tx.Type() == types.L1MessageTxType { + receipt, receiptErr := f.client.TransactionReceipt(ctx, tx.Hash()) + if receiptErr != nil { + log.Error("Failed to get transaction receipt", "txHash", tx.Hash().String(), "err", receiptErr) + return nil, nil, nil, receiptErr + } + + // Check if the transaction failed + if receipt.Status == types.ReceiptStatusFailed { + l2RevertedRelayedMessages = append(l2RevertedRelayedMessages, &orm.CrossMessage{ + MessageHash: "0x" + common.Bytes2Hex(crypto.Keccak256(tx.AsL1MessageTx().Data)), + L2TxHash: tx.Hash().String(), + TxStatus: int(orm.TxStatusTypeRelayedTxReverted), + L2BlockNumber: receipt.BlockNumber.Uint64(), + MessageType: int(orm.MessageTypeL1SentMessage), + }) + } + } + } + } + return blockTimestampsMap, l2FailedGatewayRouterTxs, l2RevertedRelayedMessages, nil +} + +func (f *L2FetcherLogic) l2FetcherLogs(ctx context.Context, from, to uint64) ([]types.Log, error) { + query := ethereum.FilterQuery{ + FromBlock: new(big.Int).SetUint64(from), // inclusive + ToBlock: new(big.Int).SetUint64(to), // inclusive + Addresses: f.addressList, + Topics: make([][]common.Hash, 1), + } + query.Topics[0] = make([]common.Hash, 7) + query.Topics[0][0] = backendabi.L2WithdrawETHSig + query.Topics[0][1] = backendabi.L2WithdrawERC20Sig + query.Topics[0][2] = backendabi.L2WithdrawERC721Sig + query.Topics[0][3] = backendabi.L2WithdrawERC1155Sig + query.Topics[0][4] = backendabi.L2SentMessageEventSig + query.Topics[0][5] = backendabi.L2RelayedMessageEventSig + query.Topics[0][6] = backendabi.L2FailedRelayedMessageEventSig + + eventLogs, err := f.client.FilterLogs(ctx, query) + if err != nil { + log.Error("Failed to filter L2 event logs", "from", from, "to", to, "err", err) + return nil, err + } + return eventLogs, nil +} + +// L2Fetcher l2 fetcher +func (f *L2FetcherLogic) L2Fetcher(ctx context.Context, from, to uint64) (*L2FilterResult, error) { + log.Info("fetch and save L1 events", "from", from, "to", to) + + blockTimestampsMap, l2FailedGatewayRouterTxs, l2RevertedRelayedMessages, routerErr := f.gatewayRouterFailedTxs(ctx, from, to) + if routerErr != nil { + log.Error("L2Fetcher gatewayRouterFailedTxs failed", "from", from, "to", to, "error", routerErr) + return nil, routerErr + } + + eventLogs, err := f.l2FetcherLogs(ctx, from, to) + if err != nil { + log.Error("L2Fetcher l2FetcherLogs failed", "from", from, "to", to, "error", err) + return nil, err + } + + l2WithdrawMessages, l2RelayedMessages, err := f.parser.ParseL2EventLogs(eventLogs, blockTimestampsMap) + if err != nil { + log.Error("failed to parse L2 event logs", "from", from, "to", to, "err", err) + return nil, err + } + + res := L2FilterResult{ + FailedGatewayRouterTxs: l2FailedGatewayRouterTxs, + RevertedRelayedMessages: l2RevertedRelayedMessages, + WithdrawMessages: l2WithdrawMessages, + RelayedMessages: l2RelayedMessages, + } + return &res, nil +} diff --git a/bridge-history-api/internal/utils/utils.go b/bridge-history-api/internal/utils/utils.go index 9136b5e65d..ae3b4ec696 100644 --- a/bridge-history-api/internal/utils/utils.go +++ b/bridge-history-api/internal/utils/utils.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "math/big" + "strings" "github.com/scroll-tech/go-ethereum/accounts/abi" "github.com/scroll-tech/go-ethereum/common" @@ -178,3 +179,26 @@ func GetL2BlocksInRange(ctx context.Context, cli *ethclient.Client, start, end u } return blocks, nil } + +func ConvertBigIntArrayToString(array []*big.Int) string { + stringArray := make([]string, len(array)) + for i, num := range array { + stringArray[i] = num.String() + } + + result := strings.Join(stringArray, ", ") + return result +} + +func GetSkippedQueueIndices(startIndex uint64, skippedBitmap *big.Int) []uint64 { + var indices []uint64 + for i := 0; i < 256; i++ { + index := startIndex + uint64(i) + bit := new(big.Int).Rsh(skippedBitmap, uint(i)) + if bit.Bit(0) == 0 { + continue + } + indices = append(indices, index) + } + return indices +} diff --git a/go.work.sum b/go.work.sum index cf01661790..5a45b21ed2 100644 --- a/go.work.sum +++ b/go.work.sum @@ -90,6 +90,7 @@ github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDm github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/ClickHouse/ch-go v0.55.0/go.mod h1:kQT2f+yp2p+sagQA/7kS6G3ukym+GQ5KAu1kuFAFDiU= @@ -113,7 +114,6 @@ github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXY github.com/Joker/hpp v1.0.0 h1:65+iuJYdRXv/XyN62C1uEmmOx3432rNG/rKlX6V7Kkc= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7 h1:mreN1m/5VJ/Zc3b4pzj9qU6D9SRQ6Vm+3KfI328t3S8= github.com/Joker/jade v1.0.1-0.20190614124447-d475f43051e7/go.mod h1:6E6s8o2AE4KhCrqr6GRJjdC/gNfTdxkIXvuGZZda2VM= -github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -204,6 +204,7 @@ github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40 h1:y4B3+GPxKlrigF1ha5FFErxK+sr6sWxQovRMzwMhejo= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= +github.com/btcsuite/btcd/btcec/v2 v2.2.0 h1:fzn1qaOt32TuLjFlkzYSsBC35Q3KUjT1SwPxiMSCF5k= github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= @@ -218,8 +219,6 @@ github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= -github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/c-bata/go-prompt v0.2.2 h1:uyKRz6Z6DUyj49QVijyM339UJV9yhbr70gESwbNU3e0= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= @@ -231,8 +230,6 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U= -github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA= -github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM= github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY= @@ -300,6 +297,7 @@ github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vs github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= @@ -313,7 +311,6 @@ github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KP github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8 h1:akOQj8IVgoeFfBTzGOEQakCYshWD6RNo1M5pivFXt70= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= -github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4= github.com/djherbis/atime v1.1.0 h1:rgwVbP/5by8BvvjBNrbh64Qz33idKT3pSnMSJsxhi0g= github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+XJPdBE= @@ -328,11 +325,9 @@ github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32Paq github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v23.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48 h1:iZOop7pqsg+56twTopWgwCGxdB5SI2yDO8Ti7eTRliQ= github.com/dop251/goja v0.0.0-20211011172007-d99e4b8cbf48/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ= @@ -434,9 +429,6 @@ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/j github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-playground/validator/v10 v10.15.5/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= -github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= @@ -494,7 +486,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= @@ -519,7 +510,6 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= @@ -603,9 +593,7 @@ github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76 github.com/jackc/pgx/v4 v4.17.0 h1:Hsx+baY8/zU2WtPLQyZi8WbecgcsWEeyoK1jvg/WgIo= github.com/jackc/pgx/v4 v4.17.0/go.mod h1:Gd6RmOhtFLTu8cp/Fhq4kP195KrshxYJH3oW8AWJ1pw= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= -github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle/v2 v2.2.0 h1:RdcDk92EJBuBS55nQMMYFXTxwstHug4jkhT5pq8VxPk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM= @@ -645,6 +633,7 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5 h1:PJr+ZMXIecYc1Ey2zucXdR73SMBtgjPgwa31099IMv0= github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef h1:2jNeR4YUziVtswNP9sEFAI913cVrzH85T+8Q6LpYbT0= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 h1:uC1QfSlInpQF+M0ao65imhwqKnz3Q2z/d8PWZRMQvDM= +github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559 h1:0VWDXPNE0brOek1Q8bLfzKkvOzwbQE/snjGojlCr8CY= github.com/karalabe/usb v0.0.0-20211005121534-4c5740d64559/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4= github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= @@ -688,16 +677,18 @@ github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9 github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5 h1:2U0HzY8BJ8hVwDKIzp7y4voR9CX/nvcfymLmg2UiOio= github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg= github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada h1:3L+neHp83cTjegPdCiOxVOJtRIy7/8RldvMTsyPYH10= -github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/knz/go-libedit v1.10.1 h1:0pHpWtx9vcvC0xGZqEQlQdfSQs7WRlAjuPvk3fOZDCo= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY= github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g= github.com/labstack/echo/v4 v4.2.1 h1:LF5Iq7t/jrtUuSutNuiEWtB5eiHfZ5gSe2pcu5exjQw= @@ -729,7 +720,6 @@ github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HN github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104 h1:d8RFOZ2IiFtFWBcKEHAFYJcPTf0wY5q0exFNJZVWa1U= github.com/mattn/goveralls v0.0.2 h1:7eJB6EqsPhRVxvwEXGnqdO2sJI0PTsrWoTMXEk9/OQc= @@ -744,6 +734,7 @@ github.com/mediocregopher/radix/v3 v3.8.0/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg= github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= github.com/microsoft/go-mssqldb v0.21.0/go.mod h1:+4wZTUnz/SV6nffv+RRRB/ss8jPng5Sho2SmM1l2ts4= +github.com/microsoft/go-mssqldb v1.6.0 h1:mM3gYdVwEPFrlg/Dvr2DNVEgYFG7L42l+dGc67NNNpc= github.com/microsoft/go-mssqldb v1.6.0/go.mod h1:00mDtPbeQCRGC1HwOOR5K/gr30P1NcEG0vx6Kbv2aJU= github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g= github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= @@ -787,7 +778,6 @@ github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1ls github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow= github.com/onsi/ginkgo/v2 v2.8.1 h1:xFTEVwOFa1D/Ty24Ws1npBWkDYEV9BqZrsDxVrVkrrU= github.com/onsi/ginkgo/v2 v2.8.1/go.mod h1:N1/NbDngAFcSLdyZ+/aYTYGSlq9qMCS/cNKGJjy+csc= -github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= @@ -804,9 +794,9 @@ github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKf github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= -github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/penglongli/gin-metrics v0.1.10/go.mod h1:wxGsGUwpVGv3hmYSxQn2GZgRL3YuCgiRFq2d0X6+EOU= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= @@ -822,7 +812,6 @@ github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4 github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/pressly/goose/v3 v3.11.2 h1:QgTP45FhBBHdmf7hWKlbWFHtwPtxo0phSDkwDKGUrYs= github.com/pressly/goose/v3 v3.11.2/go.mod h1:LWQzSc4vwfHA/3B8getTp8g3J5Z8tFBxgxinmGlMlJk= -github.com/pressly/goose/v3 v3.16.0/go.mod h1:JwdKVnmCRhnF6XLQs2mHEQtucFD49cQBdRM4UiwkxsM= github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x7enabFceM= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= @@ -842,7 +831,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7 h1:cZC+usqsYgHtlBaGulVnZ1hfKAi8iWtujBnRLQE698c= github.com/protolambda/bls12-381-util v0.0.0-20220416220906-d8552aa452c7/go.mod h1:IToEjHuttnUzwZI5KBSM/LOOW3qLbbrHOEfp3SbECGY= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -874,7 +862,6 @@ github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y= github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI= @@ -894,6 +881,8 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI= github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= @@ -956,7 +945,6 @@ github.com/yudai/pp v2.0.1+incompatible h1:Q4//iY4pNF6yPLZIigmvcl7k/bPgrcTPIFIcm github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/gofail v0.1.0 h1:XItAMIhOojXFQMgrxjnd2EIIHun/d5qL0Pf7FzVTkFg= @@ -977,10 +965,8 @@ go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.5.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -994,11 +980,13 @@ golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0 golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299 h1:zQpM52jfKHG6II1ISZY1ZcpygvuSFZpLwfluuF89XOg= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= @@ -1006,7 +994,6 @@ golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 h1:4+4C/Iv2U4fMZBiMCc98MG golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -1032,7 +1019,6 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8= @@ -1121,7 +1107,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= -golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= @@ -1161,9 +1146,9 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 h1:R1r5J0u6Cx+RNl/6mezTw6oA14cmKC96FeUwL6A9bd4= +google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f h1:Vn+VyHU5guc9KjB5KrjI2q0wCOWEOIh0OEsleqakHJg= google.golang.org/genproto v0.0.0-20231120223509-83a465c0220f/go.mod h1:nWSwAFPb+qfNJXsoeO3Io7zf4tMSfN8EA8RlDA04GhY= google.golang.org/genproto/googleapis/rpc v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:oQ5rr10WTTMvP4A36n8JpR1OrO1BEiV4f78CneXZxkA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4/go.mod h1:eJVxU6o+4G1PSczBr85xmyvSNYAKvAYgkub40YGomFM= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1198,7 +1183,6 @@ gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= gotest.tools v1.4.0 h1:BjtEgfuw8Qyd+jPvQz8CfoxiO/UjFEidWinwEXZiWv0= gotest.tools v1.4.0/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM= @@ -1230,7 +1214,7 @@ modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= moul.io/http2curl v1.0.0 h1:6XwpyZOYsgZJrU8exnG87ncVkU1FVCcTRpwzOkTDUi8= moul.io/http2curl v1.0.0/go.mod h1:f6cULg+e4Md/oW1cYmwW4IWQOVl2lGbmCNGOHvzX2kE= -nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +nullprogram.com/x/optparse v1.0.0 h1:xGFgVi5ZaWOnYdac2foDT3vg0ZZC9ErXFV57mr4OHrI= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/pdf v0.1.1 h1:k1MczvYDUvJBe93bYd7wrZLLUEcLZAuF824/I4e5Xr4= rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= diff --git a/tests/integration-test/go.sum b/tests/integration-test/go.sum index 8a87ee9521..817ddd9ef3 100644 --- a/tests/integration-test/go.sum +++ b/tests/integration-test/go.sum @@ -32,6 +32,7 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb h1:PBC98N2aIaM3XXiurYmW7fx4GZkL8feAMVq7nEjURHk= github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs= @@ -91,6 +92,7 @@ github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0h github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= @@ -115,3 +117,4 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= +gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=