Commit 83c72f0e authored by Hamdi Allam's avatar Hamdi Allam Committed by GitHub

Merge pull request #7778 from ethereum-optimism/indexer.sb.finalization

fix(indexer) simplify standard bridge finalization check
parents 12407dfd af26334a
...@@ -29,7 +29,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M ...@@ -29,7 +29,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M
log.Info("detected transaction deposits", "size", len(optimismPortalTxDeposits)) log.Info("detected transaction deposits", "size", len(optimismPortalTxDeposits))
} }
var mintedGWEI = bigint.Zero mintedGWEI := bigint.Zero
portalDeposits := make(map[logKey]*contracts.OptimismPortalTransactionDepositEvent, len(optimismPortalTxDeposits)) portalDeposits := make(map[logKey]*contracts.OptimismPortalTransactionDepositEvent, len(optimismPortalTxDeposits))
transactionDeposits := make([]database.L1TransactionDeposit, len(optimismPortalTxDeposits)) transactionDeposits := make([]database.L1TransactionDeposit, len(optimismPortalTxDeposits))
for i := range optimismPortalTxDeposits { for i := range optimismPortalTxDeposits {
...@@ -44,7 +44,6 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M ...@@ -44,7 +44,6 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M
GasLimit: depositTx.GasLimit, GasLimit: depositTx.GasLimit,
Tx: depositTx.Tx, Tx: depositTx.Tx,
} }
} }
if len(transactionDeposits) > 0 { if len(transactionDeposits) > 0 {
...@@ -125,6 +124,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M ...@@ -125,6 +124,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L1M
} }
bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++ bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash
bridgeDeposits[i] = database.L1BridgeDeposit{ bridgeDeposits[i] = database.L1BridgeDeposit{
TransactionSourceHash: portalDeposit.DepositTx.SourceHash, TransactionSourceHash: portalDeposit.DepositTx.SourceHash,
...@@ -214,10 +214,8 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1M ...@@ -214,10 +214,8 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1M
log.Info("detected relayed messages", "size", len(crossDomainRelayedMessages)) log.Info("detected relayed messages", "size", len(crossDomainRelayedMessages))
} }
relayedMessages := make(map[logKey]*contracts.CrossDomainMessengerRelayedMessageEvent, len(crossDomainRelayedMessages))
for i := range crossDomainRelayedMessages { for i := range crossDomainRelayedMessages {
relayed := crossDomainRelayedMessages[i] relayed := crossDomainRelayedMessages[i]
relayedMessages[logKey{BlockHash: relayed.Event.BlockHash, LogIndex: relayed.Event.LogIndex}] = &relayed
message, err := db.BridgeMessages.L2BridgeMessage(relayed.MessageHash) message, err := db.BridgeMessages.L2BridgeMessage(relayed.MessageHash)
if err != nil { if err != nil {
return err return err
...@@ -236,40 +234,21 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1M ...@@ -236,40 +234,21 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L1M
} }
// (4) L1StandardBridge // (4) L1StandardBridge
// - Nothing actionable on the database. Since the StandardBridge is layered ontop of the
// CrossDomainMessenger, there's no need for any sanity or invariant checks as the previous step
// ensures a relayed message (finalized bridge) can be linked with a sent message (initiated bridge).
finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l1", l1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight) finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l1", l1Contracts.L1StandardBridgeProxy, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
if len(finalizedBridges) > 0 {
log.Info("detected finalized bridge withdrawals", "size", len(finalizedBridges))
}
finalizedTokens := make(map[common.Address]int) finalizedTokens := make(map[common.Address]int)
for i := range finalizedBridges { for i := range finalizedBridges {
// Nothing actionable on the database. However, we can treat the relayed message
// as an invariant by ensuring we can query for a deposit by the same hash
finalizedBridge := finalizedBridges[i] finalizedBridge := finalizedBridges[i]
relayedMessage, ok := relayedMessages[logKey{finalizedBridge.Event.BlockHash, finalizedBridge.Event.LogIndex + 1}]
if !ok {
log.Error("expected RelayedMessage following BridgeFinalized event", "tx_hash", finalizedBridge.Event.TransactionHash.String())
return fmt.Errorf("expected RelayedMessage following BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash.String())
} else if relayedMessage.Event.TransactionHash != finalizedBridge.Event.TransactionHash {
log.Error("correlated events tx hash mismatch", "message_tx_hash", relayedMessage.Event.TransactionHash.String(), "bridge_tx_hash", finalizedBridge.Event.TransactionHash.String())
return fmt.Errorf("correlated events tx hash mismatch")
}
// Since the message hash is computed from the relayed message, this ensures the deposit fields must match
withdrawal, err := db.BridgeTransfers.L2BridgeWithdrawalWithFilter(database.BridgeTransfer{CrossDomainMessageHash: &relayedMessage.MessageHash})
if err != nil {
return err
} else if withdrawal == nil {
log.Error("missing L2StandardBridge withdrawal on L1 finalization", "tx_hash", finalizedBridge.Event.TransactionHash.String())
return fmt.Errorf("missing L2StandardBridge withdrawal on L1 finalization. tx_hash: %s", finalizedBridge.Event.TransactionHash.String())
}
finalizedTokens[finalizedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++ finalizedTokens[finalizedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
} }
if len(finalizedBridges) > 0 { if len(finalizedBridges) > 0 {
log.Info("detected finalized bridge withdrawals", "size", len(finalizedBridges))
for tokenAddr, size := range finalizedTokens { for tokenAddr, size := range finalizedTokens {
metrics.RecordL1FinalizedBridgeTransfers(tokenAddr, size) metrics.RecordL1FinalizedBridgeTransfers(tokenAddr, size)
} }
......
package bridge package bridge
import ( import (
"errors"
"fmt" "fmt"
"math/big" "math/big"
...@@ -29,7 +28,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2M ...@@ -29,7 +28,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2M
log.Info("detected transaction withdrawals", "size", len(l2ToL1MPMessagesPassed)) log.Info("detected transaction withdrawals", "size", len(l2ToL1MPMessagesPassed))
} }
var withdrawnWEI = bigint.Zero withdrawnWEI := bigint.Zero
messagesPassed := make(map[logKey]*contracts.L2ToL1MessagePasserMessagePassed, len(l2ToL1MPMessagesPassed)) messagesPassed := make(map[logKey]*contracts.L2ToL1MessagePasserMessagePassed, len(l2ToL1MPMessagesPassed))
transactionWithdrawals := make([]database.L2TransactionWithdrawal, len(l2ToL1MPMessagesPassed)) transactionWithdrawals := make([]database.L2TransactionWithdrawal, len(l2ToL1MPMessagesPassed))
for i := range l2ToL1MPMessagesPassed { for i := range l2ToL1MPMessagesPassed {
...@@ -122,8 +121,9 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2M ...@@ -122,8 +121,9 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2M
return fmt.Errorf("correlated events tx hash mismatch") return fmt.Errorf("correlated events tx hash mismatch")
} }
initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash
bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++ bridgedTokens[initiatedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
initiatedBridge.BridgeTransfer.CrossDomainMessageHash = &sentMessage.BridgeMessage.MessageHash
bridgeWithdrawals[i] = database.L2BridgeWithdrawal{ bridgeWithdrawals[i] = database.L2BridgeWithdrawal{
TransactionWithdrawalHash: messagePassed.WithdrawalHash, TransactionWithdrawalHash: messagePassed.WithdrawalHash,
BridgeTransfer: initiatedBridge.BridgeTransfer, BridgeTransfer: initiatedBridge.BridgeTransfer,
...@@ -158,10 +158,8 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L2M ...@@ -158,10 +158,8 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L2M
log.Info("detected relayed messages", "size", len(crossDomainRelayedMessages)) log.Info("detected relayed messages", "size", len(crossDomainRelayedMessages))
} }
relayedMessages := make(map[logKey]*contracts.CrossDomainMessengerRelayedMessageEvent, len(crossDomainRelayedMessages))
for i := range crossDomainRelayedMessages { for i := range crossDomainRelayedMessages {
relayed := crossDomainRelayedMessages[i] relayed := crossDomainRelayedMessages[i]
relayedMessages[logKey{BlockHash: relayed.Event.BlockHash, LogIndex: relayed.Event.LogIndex}] = &relayed
message, err := db.BridgeMessages.L1BridgeMessage(relayed.MessageHash) message, err := db.BridgeMessages.L1BridgeMessage(relayed.MessageHash)
if err != nil { if err != nil {
return err return err
...@@ -175,45 +173,26 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L2M ...@@ -175,45 +173,26 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metrics L2M
return err return err
} }
} }
if len(relayedMessages) > 0 { if len(crossDomainRelayedMessages) > 0 {
metrics.RecordL2CrossDomainRelayedMessages(len(relayedMessages)) metrics.RecordL2CrossDomainRelayedMessages(len(crossDomainRelayedMessages))
} }
// (2) L2StandardBridge // (2) L2StandardBridge
// - Nothing actionable on the database. Since the StandardBridge is layered ontop of the
// CrossDomainMessenger, there's no need for any sanity or invariant checks as the previous step
// ensures a relayed message (finalized bridge) can be linked with a sent message (initiated bridge).
finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l2", l2Contracts.L2StandardBridge, db, fromHeight, toHeight) finalizedBridges, err := contracts.StandardBridgeFinalizedEvents("l2", l2Contracts.L2StandardBridge, db, fromHeight, toHeight)
if err != nil { if err != nil {
return err return err
} }
if len(finalizedBridges) > 0 {
log.Info("detected finalized bridge deposits", "size", len(finalizedBridges))
}
finalizedTokens := make(map[common.Address]int) finalizedTokens := make(map[common.Address]int)
for i := range finalizedBridges { for i := range finalizedBridges {
// Nothing actionable on the database. However, we can treat the relayed message
// as an invariant by ensuring we can query for a deposit by the same hash
finalizedBridge := finalizedBridges[i] finalizedBridge := finalizedBridges[i]
relayedMessage, ok := relayedMessages[logKey{finalizedBridge.Event.BlockHash, finalizedBridge.Event.LogIndex + 1}]
if !ok {
log.Error("expected RelayedMessage following BridgeFinalized event", "tx_hash", finalizedBridge.Event.TransactionHash.String())
return fmt.Errorf("expected RelayedMessage following BridgeFinalized event. tx_hash = %s", finalizedBridge.Event.TransactionHash.String())
} else if relayedMessage.Event.TransactionHash != finalizedBridge.Event.TransactionHash {
log.Error("correlated events tx hash mismatch", "message_tx_hash", relayedMessage.Event.TransactionHash.String(), "bridge_tx_hash", finalizedBridge.Event.TransactionHash.String())
return fmt.Errorf("correlated events tx hash mismatch")
}
// Since the message hash is computed from the relayed message, this ensures the withdrawal fields must match
deposit, err := db.BridgeTransfers.L1BridgeDepositWithFilter(database.BridgeTransfer{CrossDomainMessageHash: &relayedMessage.MessageHash})
if err != nil {
return err
} else if deposit == nil {
log.Error("missing L1StandardBridge deposit on L2 finalization", "tx_hash", finalizedBridge.Event.TransactionHash.String())
return errors.New("missing L1StandardBridge deposit on L2 finalization")
}
finalizedTokens[finalizedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++ finalizedTokens[finalizedBridge.BridgeTransfer.TokenPair.LocalTokenAddress]++
} }
if len(finalizedBridges) > 0 { if len(finalizedBridges) > 0 {
log.Info("detected finalized bridge deposits", "size", len(finalizedBridges))
for tokenAddr, size := range finalizedTokens { for tokenAddr, size := range finalizedTokens {
metrics.RecordL2FinalizedBridgeTransfers(tokenAddr, size) metrics.RecordL2FinalizedBridgeTransfers(tokenAddr, size)
} }
......
...@@ -335,10 +335,12 @@ func LegacyL1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri ...@@ -335,10 +335,12 @@ func LegacyL1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri
log.Warn("skipped pre-regensis relayed L2CrossDomainMessenger withdrawals", "size", skippedPreRegenesisMessages) log.Warn("skipped pre-regensis relayed L2CrossDomainMessenger withdrawals", "size", skippedPreRegenesisMessages)
} }
// (2) L2StandardBridge -- no-op for now as there's nothing actionable to do here besides // (2) L1StandardBridge
// santiy checks which is not important for legacy code. Not worth extra code pre-bedrock. // - Nothing actionable on the database. Since the StandardBridge is layered ontop of the
// The message status is already tracked via the relayed bridge messed through the cross domain messenger. // CrossDomainMessenger, there's no need for any sanity or invariant checks as the previous step
// - NOTE: This means we dont increment metrics for finalized bridge transfers // ensures a relayed message (finalized bridge) can be linked with a sent message (initiated bridge).
// - NOTE: Ignoring metrics for pre-bedrock transfers
// a-ok! // a-ok!
return nil return nil
...@@ -377,10 +379,12 @@ func LegacyL2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri ...@@ -377,10 +379,12 @@ func LegacyL2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri
metrics.RecordL2CrossDomainRelayedMessages(len(crossDomainRelayedMessages)) metrics.RecordL2CrossDomainRelayedMessages(len(crossDomainRelayedMessages))
} }
// (2) L2StandardBridge -- no-op for now as there's nothing actionable to do here besides // (2) L2StandardBridge
// santiy checks which is not important for legacy code. Not worth the extra code pre-bedorck. // - Nothing actionable on the database. Since the StandardBridge is layered ontop of the
// The message status is already tracked via the relayed bridge messed through the cross domain messenger. // CrossDomainMessenger, there's no need for any sanity or invariant checks as the previous step
// - NOTE: This means we dont increment metrics for finalized bridge transfers // ensures a relayed message (finalized bridge) can be linked with a sent message (initiated bridge).
// - NOTE: Ignoring metrics for pre-bedrock transfers
// a-ok! // a-ok!
return nil return nil
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment