From dd6206fd59129697b4fa81b667691673afbb3f99 Mon Sep 17 00:00:00 2001 From: colin <102356659+colinlyguo@users.noreply.github.com> Date: Tue, 30 Jul 2024 21:06:38 +0800 Subject: [PATCH] feat(bridge-history-backend): track reset skipped message events (#1467) --- bridge-history-api/abi/backend_abi.go | 14 ++++++++++---- .../internal/logic/l1_event_parser.go | 10 ++++++++++ bridge-history-api/internal/logic/l1_fetcher.go | 9 +++++++-- bridge-history-api/internal/orm/cross_message.go | 8 +++++++- bridge-history-api/internal/types/events.go | 1 + common/version/version.go | 2 +- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/bridge-history-api/abi/backend_abi.go b/bridge-history-api/abi/backend_abi.go index 5d9b67112a..e92274c905 100644 --- a/bridge-history-api/abi/backend_abi.go +++ b/bridge-history-api/abi/backend_abi.go @@ -56,9 +56,10 @@ var ( L1RevertBatchEventSig common.Hash L1FinalizeBatchEventSig common.Hash - L1QueueTransactionEventSig common.Hash - L1DequeueTransactionEventSig common.Hash - L1DropTransactionEventSig common.Hash + L1QueueTransactionEventSig common.Hash + L1DequeueTransactionEventSig common.Hash + L1DropTransactionEventSig common.Hash + L1ResetDequeuedTransactionEventSig common.Hash ) func init() { @@ -114,6 +115,7 @@ func init() { L1QueueTransactionEventSig = IL1MessageQueueABI.Events["QueueTransaction"].ID L1DequeueTransactionEventSig = IL1MessageQueueABI.Events["DequeueTransaction"].ID L1DropTransactionEventSig = IL1MessageQueueABI.Events["DropTransaction"].ID + L1ResetDequeuedTransactionEventSig = IL1MessageQueueABI.Events["ResetDequeuedTransaction"].ID } var IL1ETHGatewayMetaData = &bind.MetaData{ @@ -161,7 +163,7 @@ var IScrollChainMetaData = &bind.MetaData{ } var IL1MessageQueueMetaData = &bind.MetaData{ - ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"skippedBitmap\",\"type\":\"uint256\"}],\"name\":\"DequeueTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"DropTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"queueIndex\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"QueueTransaction\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"appendCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"appendEnforcedTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"calculateIntrinsicGasFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"computeTransactionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"dropCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"estimateCrossDomainMessageFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"getCrossDomainMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"isMessageDropped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"isMessageSkipped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextCrossDomainMessageIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingQueueIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"skippedBitmap\",\"type\":\"uint256\"}],\"name\":\"popCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ErrorZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"skippedBitmap\",\"type\":\"uint256\"}],\"name\":\"DequeueTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"DropTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"finalizedIndex\",\"type\":\"uint256\"}],\"name\":\"FinalizedDequeuedTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"queueIndex\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"QueueTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"}],\"name\":\"ResetDequeuedTransaction\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldGasOracle\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newGasOracle\",\"type\":\"address\"}],\"name\":\"UpdateGasOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_oldMaxGasLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_newMaxGasLimit\",\"type\":\"uint256\"}],\"name\":\"UpdateMaxGasLimit\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"appendCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"appendEnforcedTransaction\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"calculateIntrinsicGasFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"computeTransactionHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"dropCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"}],\"name\":\"estimateCrossDomainMessageFee\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFinalizedQueueIndexPlusOne\",\"type\":\"uint256\"}],\"name\":\"finalizePoppedCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"getCrossDomainMessage\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"isMessageDropped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"queueIndex\",\"type\":\"uint256\"}],\"name\":\"isMessageSkipped\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextCrossDomainMessageIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"nextUnfinalizedQueueIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingQueueIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"skippedBitmap\",\"type\":\"uint256\"}],\"name\":\"popCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"}],\"name\":\"resetPoppedCrossDomainMessage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } // L1BatchBridgeGatewayMetaData contains all meta data concerning the L1BatchBridgeGateway contract. @@ -290,6 +292,10 @@ type L1DropTransactionEvent struct { Index *big.Int } +type L1ResetDequeuedTransactionEvent struct { + StartIndex *big.Int +} + // L1BatchBridgeGatewayDeposit represents L1 batch bridge Deposit event type L1BatchBridgeGatewayDeposit struct { Sender common.Address diff --git a/bridge-history-api/internal/logic/l1_event_parser.go b/bridge-history-api/internal/logic/l1_event_parser.go index 837ae37652..4809436894 100644 --- a/bridge-history-api/internal/logic/l1_event_parser.go +++ b/bridge-history-api/internal/logic/l1_event_parser.go @@ -320,6 +320,16 @@ func (e *L1EventParser) ParseL1MessageQueueEventLogs(logs []types.Log, l1Deposit QueueIndex: index, }) } + case backendabi.L1ResetDequeuedTransactionEventSig: + event := backendabi.L1ResetDequeuedTransactionEvent{} + if err := utils.UnpackLog(backendabi.IL1MessageQueueABI, &event, "ResetDequeuedTransaction", vlog); err != nil { + log.Error("Failed to unpack ResetDequeuedTransaction event", "err", err) + return nil, err + } + l1MessageQueueEvents = append(l1MessageQueueEvents, &orm.MessageQueueEvent{ + EventType: btypes.MessageQueueEventTypeResetDequeuedTransaction, + QueueIndex: event.StartIndex.Uint64(), + }) case backendabi.L1DropTransactionEventSig: event := backendabi.L1DropTransactionEvent{} if err := utils.UnpackLog(backendabi.IL1MessageQueueABI, &event, "DropTransaction", vlog); err != nil { diff --git a/bridge-history-api/internal/logic/l1_fetcher.go b/bridge-history-api/internal/logic/l1_fetcher.go index 8c36726947..509fba00ab 100644 --- a/bridge-history-api/internal/logic/l1_fetcher.go +++ b/bridge-history-api/internal/logic/l1_fetcher.go @@ -210,7 +210,7 @@ func (f *L1FetcherLogic) l1FetcherLogs(ctx context.Context, from, to uint64) ([] Topics: make([][]common.Hash, 1), } - query.Topics[0] = make([]common.Hash, 14) + query.Topics[0] = make([]common.Hash, 15) query.Topics[0][0] = backendabi.L1DepositETHSig query.Topics[0][1] = backendabi.L1DepositERC20Sig query.Topics[0][2] = backendabi.L1DepositERC721Sig @@ -224,7 +224,8 @@ func (f *L1FetcherLogic) l1FetcherLogs(ctx context.Context, from, to uint64) ([] query.Topics[0][10] = backendabi.L1QueueTransactionEventSig query.Topics[0][11] = backendabi.L1DequeueTransactionEventSig query.Topics[0][12] = backendabi.L1DropTransactionEventSig - query.Topics[0][13] = backendabi.L1BridgeBatchDepositSig + query.Topics[0][13] = backendabi.L1ResetDequeuedTransactionEventSig + query.Topics[0][14] = backendabi.L1BridgeBatchDepositSig eventLogs, err := f.client.FilterLogs(ctx, query) if err != nil { @@ -339,6 +340,10 @@ func (f *L1FetcherLogic) updateMetrics(res L1FilterResult) { f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_skip_message").Add(1) case btypes.MessageQueueEventTypeDropTransaction: f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_drop_message").Add(1) + // one ResetDequeuedTransaction event could indicate reset multiple skipped messages, + // this metric only counts the number of events, not the number of skipped messages. + case btypes.MessageQueueEventTypeResetDequeuedTransaction: + f.l1FetcherLogicFetchedTotal.WithLabelValues("L1_reset_skipped_messages").Add(1) } } diff --git a/bridge-history-api/internal/orm/cross_message.go b/bridge-history-api/internal/orm/cross_message.go index 786571db51..b06253aafd 100644 --- a/bridge-history-api/internal/orm/cross_message.go +++ b/bridge-history-api/internal/orm/cross_message.go @@ -217,6 +217,12 @@ func (c *CrossMessage) UpdateL1MessageQueueEventsInfo(ctx context.Context, l1Mes db = db.Where("message_nonce = ?", l1MessageQueueEvent.QueueIndex) db = db.Where("message_type = ?", btypes.MessageTypeL1SentMessage) txStatusUpdateFields["tx_status"] = types.TxStatusTypeDropped + case btypes.MessageQueueEventTypeResetDequeuedTransaction: + db = db.Where("tx_status = ?", types.TxStatusTypeSkipped) + // reset skipped messages that the nonce is greater than or equal to the queue index. + db = db.Where("message_nonce >= ?", l1MessageQueueEvent.QueueIndex) + db = db.Where("message_type = ?", btypes.MessageTypeL1SentMessage) + txStatusUpdateFields["tx_status"] = types.TxStatusTypeSent } if err := db.Updates(txStatusUpdateFields).Error; err != nil { return fmt.Errorf("failed to update tx statuses of L1 message queue events, update fields: %v, error: %w", txStatusUpdateFields, err) @@ -230,7 +236,7 @@ func (c *CrossMessage) UpdateL1MessageQueueEventsInfo(ctx context.Context, l1Mes db = db.Model(&CrossMessage{}) txHashUpdateFields := make(map[string]interface{}) switch l1MessageQueueEvent.EventType { - case btypes.MessageQueueEventTypeDequeueTransaction: + case btypes.MessageQueueEventTypeDequeueTransaction, btypes.MessageQueueEventTypeResetDequeuedTransaction: continue case btypes.MessageQueueEventTypeQueueTransaction: // only replayMessages or enforced txs (whose message hashes would not be found), sendMessages have been filtered out. diff --git a/bridge-history-api/internal/types/events.go b/bridge-history-api/internal/types/events.go index 40c84044f1..d5d195ec75 100644 --- a/bridge-history-api/internal/types/events.go +++ b/bridge-history-api/internal/types/events.go @@ -70,6 +70,7 @@ const ( MessageQueueEventTypeQueueTransaction MessageQueueEventTypeDequeueTransaction MessageQueueEventTypeDropTransaction + MessageQueueEventTypeResetDequeuedTransaction ) // BatchStatusType represents the type of batch status. diff --git a/common/version/version.go b/common/version/version.go index bec6f0ff02..a9e6ea77d0 100644 --- a/common/version/version.go +++ b/common/version/version.go @@ -5,7 +5,7 @@ import ( "runtime/debug" ) -var tag = "v4.4.35" +var tag = "v4.4.36" var commit = func() string { if info, ok := debug.ReadBuildInfo(); ok {