Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
38d3505b
Commit
38d3505b
authored
Sep 15, 2023
by
Hamdi Allam
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bridge metrics
parent
be3952fa
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
480 additions
and
190 deletions
+480
-190
etl.go
indexer/etl/etl.go
+6
-5
metrics.go
indexer/etl/metrics.go
+1
-6
indexer.go
indexer/indexer.go
+2
-1
metrics.go
indexer/node/metrics.go
+1
-0
bridge.go
indexer/processors/bridge.go
+123
-121
l1_bridge_processor.go
indexer/processors/bridge/l1_bridge_processor.go
+36
-12
l2_bridge_processor.go
indexer/processors/bridge/l2_bridge_processor.go
+33
-14
legacy_bridge_processor.go
indexer/processors/bridge/legacy_bridge_processor.go
+49
-27
metrics.go
indexer/processors/bridge/metrics.go
+221
-0
legacy_standard_bridge.go
indexer/processors/contracts/legacy_standard_bridge.go
+8
-4
No files found.
indexer/etl/etl.go
View file @
38d3505b
...
...
@@ -71,10 +71,10 @@ func (etl *ETL) Start(ctx context.Context) error {
etl
.
log
.
Error
(
"error querying for headers"
,
"err"
,
err
)
}
else
if
len
(
newHeaders
)
==
0
{
etl
.
log
.
Warn
(
"no new headers. processor unexpectedly at head..."
)
}
else
{
headers
=
newHeaders
etl
.
metrics
.
RecordBatchHeaders
(
len
(
newHeaders
))
}
headers
=
newHeaders
etl
.
metrics
.
RecordBatchHeaders
(
len
(
newHeaders
))
}
// only clear the reference if we were able to process this batch
...
...
@@ -107,7 +107,7 @@ func (etl *ETL) processBatch(headers []types.Header) error {
headersWithLog
:=
make
(
map
[
common
.
Hash
]
bool
,
len
(
headers
))
logs
,
err
:=
etl
.
EthClient
.
FilterLogs
(
ethereum
.
FilterQuery
{
FromBlock
:
firstHeader
.
Number
,
ToBlock
:
lastHeader
.
Number
,
Addresses
:
etl
.
contracts
})
if
err
!=
nil
{
batchLog
.
Info
(
"
unable
to extract logs"
,
"err"
,
err
)
batchLog
.
Info
(
"
failed
to extract logs"
,
"err"
,
err
)
return
err
}
if
len
(
logs
)
>
0
{
...
...
@@ -118,7 +118,8 @@ func (etl *ETL) processBatch(headers []types.Header) error {
log
:=
logs
[
i
]
if
_
,
ok
:=
headerMap
[
log
.
BlockHash
];
!
ok
{
// NOTE. Definitely an error state if the none of the headers were re-orged out in between
// the blocks and logs retrieval operations. However, we need to gracefully handle reorgs
// the blocks and logs retrieval operations. Unlikely as long as the confirmation depth has
// been appropriately set or when we get to natively handling reorgs.
batchLog
.
Error
(
"log found with block hash not in the batch"
,
"block_hash"
,
logs
[
i
]
.
BlockHash
,
"log_index"
,
logs
[
i
]
.
Index
)
return
errors
.
New
(
"parsed log with a block hash not in the batch"
)
}
...
...
indexer/etl/metrics.go
View file @
38d3505b
...
...
@@ -16,7 +16,6 @@ type Metricer interface {
RecordInterval
()
(
done
func
(
err
error
))
// Batch Extraction
RecordBatchFailure
()
RecordBatchLatestHeight
(
height
*
big
.
Int
)
RecordBatchHeaders
(
size
int
)
RecordBatchLog
(
contractAddress
common
.
Address
)
...
...
@@ -108,17 +107,13 @@ func (m *etlMetrics) RecordInterval() func(error) {
timer
:=
prometheus
.
NewTimer
(
m
.
intervalDuration
)
return
func
(
err
error
)
{
if
err
!=
nil
{
m
.
RecordBatchFailure
()
m
.
batchFailures
.
Inc
()
}
timer
.
ObserveDuration
()
}
}
func
(
m
*
etlMetrics
)
RecordBatchFailure
()
{
m
.
batchFailures
.
Inc
()
}
func
(
m
*
etlMetrics
)
RecordBatchLatestHeight
(
height
*
big
.
Int
)
{
m
.
batchLatestHeight
.
Set
(
float64
(
height
.
Uint64
()))
}
...
...
indexer/indexer.go
View file @
38d3505b
...
...
@@ -20,6 +20,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/etl"
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processors"
"github.com/ethereum-optimism/optimism/indexer/processors/bridge"
"github.com/ethereum-optimism/optimism/op-service/httputil"
"github.com/ethereum-optimism/optimism/op-service/metrics"
)
...
...
@@ -82,7 +83,7 @@ func NewIndexer(
}
// Bridge
bridgeProcessor
,
err
:=
processors
.
NewBridgeProcessor
(
log
,
db
,
l1Etl
,
chainConfig
)
bridgeProcessor
,
err
:=
processors
.
NewBridgeProcessor
(
log
,
db
,
bridge
.
NewMetrics
(
metricsRegistry
),
l1Etl
,
chainConfig
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
indexer/node/metrics.go
View file @
38d3505b
...
...
@@ -7,6 +7,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/rpc"
"github.com/prometheus/client_golang/prometheus"
)
...
...
indexer/processors/bridge.go
View file @
38d3505b
This diff is collapsed.
Click to expand it.
indexer/processors/bridge/l1_bridge_processor.go
View file @
38d3505b
...
...
@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)
...
...
@@ -17,7 +18,7 @@ import (
// 1. OptimismPortal
// 2. L1CrossDomainMessenger
// 3. L1StandardBridge
func
L1ProcessInitiatedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
l1Contracts
config
.
L1Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
func
L1ProcessInitiatedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
metrics
L1Metricer
,
l1Contracts
config
.
L1Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
// (1) OptimismPortal
optimismPortalTxDeposits
,
err
:=
contracts
.
OptimismPortalTransactionDepositEvents
(
l1Contracts
.
OptimismPortalProxy
,
db
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
...
...
@@ -44,6 +45,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
if
err
:=
db
.
BridgeTransactions
.
StoreL1TransactionDeposits
(
transactionDeposits
);
err
!=
nil
{
return
err
}
metrics
.
RecordL1TransactionDeposits
(
len
(
transactionDeposits
))
}
// (2) L1CrossDomainMessenger
...
...
@@ -56,7 +58,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
}
sentMessages
:=
make
(
map
[
logKey
]
*
contracts
.
CrossDomainMessengerSentMessageEvent
,
len
(
crossDomainSentMessages
))
l1B
ridgeMessages
:=
make
([]
database
.
L1BridgeMessage
,
len
(
crossDomainSentMessages
))
b
ridgeMessages
:=
make
([]
database
.
L1BridgeMessage
,
len
(
crossDomainSentMessages
))
for
i
:=
range
crossDomainSentMessages
{
sentMessage
:=
crossDomainSentMessages
[
i
]
sentMessages
[
logKey
{
sentMessage
.
Event
.
BlockHash
,
sentMessage
.
Event
.
LogIndex
}]
=
&
sentMessage
...
...
@@ -68,12 +70,13 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
return
fmt
.
Errorf
(
"expected TransactionDeposit preceding SentMessage event. tx_hash = %s"
,
sentMessage
.
Event
.
TransactionHash
.
String
())
}
l1B
ridgeMessages
[
i
]
=
database
.
L1BridgeMessage
{
TransactionSourceHash
:
portalDeposit
.
DepositTx
.
SourceHash
,
BridgeMessage
:
sentMessage
.
BridgeMessage
}
b
ridgeMessages
[
i
]
=
database
.
L1BridgeMessage
{
TransactionSourceHash
:
portalDeposit
.
DepositTx
.
SourceHash
,
BridgeMessage
:
sentMessage
.
BridgeMessage
}
}
if
len
(
l1B
ridgeMessages
)
>
0
{
if
err
:=
db
.
BridgeMessages
.
StoreL1BridgeMessages
(
l1B
ridgeMessages
);
err
!=
nil
{
if
len
(
b
ridgeMessages
)
>
0
{
if
err
:=
db
.
BridgeMessages
.
StoreL1BridgeMessages
(
b
ridgeMessages
);
err
!=
nil
{
return
err
}
metrics
.
RecordL1CrossDomainSentMessages
(
len
(
bridgeMessages
))
}
// (3) L1StandardBridge
...
...
@@ -85,7 +88,8 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
log
.
Info
(
"detected bridge deposits"
,
"size"
,
len
(
initiatedBridges
))
}
l1BridgeDeposits
:=
make
([]
database
.
L1BridgeDeposit
,
len
(
initiatedBridges
))
bridgedTokens
:=
make
(
map
[
common
.
Address
]
int
)
bridgeDeposits
:=
make
([]
database
.
L1BridgeDeposit
,
len
(
initiatedBridges
))
for
i
:=
range
initiatedBridges
{
initiatedBridge
:=
initiatedBridges
[
i
]
...
...
@@ -102,15 +106,19 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
}
initiatedBridge
.
BridgeTransfer
.
CrossDomainMessageHash
=
&
sentMessage
.
BridgeMessage
.
MessageHash
l1BridgeDeposits
[
i
]
=
database
.
L1BridgeDeposit
{
bridgedTokens
[
initiatedBridge
.
BridgeTransfer
.
TokenPair
.
LocalTokenAddress
]
++
bridgeDeposits
[
i
]
=
database
.
L1BridgeDeposit
{
TransactionSourceHash
:
portalDeposit
.
DepositTx
.
SourceHash
,
BridgeTransfer
:
initiatedBridge
.
BridgeTransfer
,
}
}
if
len
(
l1B
ridgeDeposits
)
>
0
{
if
err
:=
db
.
BridgeTransfers
.
StoreL1BridgeDeposits
(
l1B
ridgeDeposits
);
err
!=
nil
{
if
len
(
b
ridgeDeposits
)
>
0
{
if
err
:=
db
.
BridgeTransfers
.
StoreL1BridgeDeposits
(
b
ridgeDeposits
);
err
!=
nil
{
return
err
}
for
tokenAddr
,
size
:=
range
bridgedTokens
{
metrics
.
RecordL1InitiatedBridgeTransfers
(
tokenAddr
,
size
)
}
}
return
nil
...
...
@@ -121,7 +129,7 @@ func L1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
// 1. OptimismPortal (Bedrock prove & finalize steps)
// 2. L1CrossDomainMessenger (relayMessage marker)
// 3. L1StandardBridge (no-op, since this is simply a wrapper over the L1CrossDomainMessenger)
func
L1ProcessFinalizedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
l1Contracts
config
.
L1Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
func
L1ProcessFinalizedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
metrics
L1Metricer
,
l1Contracts
config
.
L1Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
// (1) OptimismPortal (proven withdrawals)
provenWithdrawals
,
err
:=
contracts
.
OptimismPortalWithdrawalProvenEvents
(
l1Contracts
.
OptimismPortalProxy
,
db
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
...
...
@@ -146,6 +154,9 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
return
err
}
}
if
len
(
provenWithdrawals
)
>
0
{
metrics
.
RecordL1ProvenWithdrawals
(
len
(
provenWithdrawals
))
}
// (2) OptimismPortal (finalized withdrawals)
finalizedWithdrawals
,
err
:=
contracts
.
OptimismPortalWithdrawalFinalizedEvents
(
l1Contracts
.
OptimismPortalProxy
,
db
,
fromHeight
,
toHeight
)
...
...
@@ -171,6 +182,9 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
return
err
}
}
if
len
(
finalizedWithdrawals
)
>
0
{
metrics
.
RecordL1FinalizedWithdrawals
(
len
(
finalizedWithdrawals
))
}
// (3) L1CrossDomainMessenger
crossDomainRelayedMessages
,
err
:=
contracts
.
CrossDomainMessengerRelayedMessageEvents
(
"l1"
,
l1Contracts
.
L1CrossDomainMessengerProxy
,
db
,
fromHeight
,
toHeight
)
...
...
@@ -198,6 +212,9 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
return
err
}
}
if
len
(
crossDomainRelayedMessages
)
>
0
{
metrics
.
RecordL1CrossDomainRelayedMessages
(
len
(
crossDomainRelayedMessages
))
}
// (4) L1StandardBridge
finalizedBridges
,
err
:=
contracts
.
StandardBridgeFinalizedEvents
(
"l1"
,
l1Contracts
.
L1StandardBridgeProxy
,
db
,
fromHeight
,
toHeight
)
...
...
@@ -208,6 +225,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
log
.
Info
(
"detected finalized bridge withdrawals"
,
"size"
,
len
(
finalizedBridges
))
}
finalizedTokens
:=
make
(
map
[
common
.
Address
]
int
)
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
...
...
@@ -218,8 +236,7 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
return
fmt
.
Errorf
(
"expected RelayedMessage following BridgeFinalized event. tx_hash = %s"
,
finalizedBridge
.
Event
.
TransactionHash
.
String
())
}
// Since the message hash is computed from the relayed message, this ensures the deposit fields must match. For good measure,
// we may choose to make sure `withdrawal.BridgeTransfer` matches with the finalized bridge
// 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
...
...
@@ -227,6 +244,13 @@ func L1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l1Contracts
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
]
++
}
if
len
(
finalizedBridges
)
>
0
{
for
tokenAddr
,
size
:=
range
finalizedTokens
{
metrics
.
RecordL1FinalizedBridgeTransfers
(
tokenAddr
,
size
)
}
}
// a-ok!
...
...
indexer/processors/bridge/l2_bridge_processor.go
View file @
38d3505b
...
...
@@ -9,6 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
...
...
@@ -17,7 +18,7 @@ import (
// 1. OptimismPortal
// 2. L2CrossDomainMessenger
// 3. L2StandardBridge
func
L2ProcessInitiatedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
l2Contracts
config
.
L2Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
func
L2ProcessInitiatedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
metrics
L2Metricer
,
l2Contracts
config
.
L2Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
// (1) L2ToL1MessagePasser
l2ToL1MPMessagesPassed
,
err
:=
contracts
.
L2ToL1MessagePasserMessagePassedEvents
(
l2Contracts
.
L2ToL1MessagePasser
,
db
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
...
...
@@ -44,6 +45,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
if
err
:=
db
.
BridgeTransactions
.
StoreL2TransactionWithdrawals
(
transactionWithdrawals
);
err
!=
nil
{
return
err
}
metrics
.
RecordL2TransactionWithdrawals
(
len
(
transactionWithdrawals
))
}
// (2) L2CrossDomainMessenger
...
...
@@ -56,7 +58,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
}
sentMessages
:=
make
(
map
[
logKey
]
*
contracts
.
CrossDomainMessengerSentMessageEvent
,
len
(
crossDomainSentMessages
))
l2B
ridgeMessages
:=
make
([]
database
.
L2BridgeMessage
,
len
(
crossDomainSentMessages
))
b
ridgeMessages
:=
make
([]
database
.
L2BridgeMessage
,
len
(
crossDomainSentMessages
))
for
i
:=
range
crossDomainSentMessages
{
sentMessage
:=
crossDomainSentMessages
[
i
]
sentMessages
[
logKey
{
sentMessage
.
Event
.
BlockHash
,
sentMessage
.
Event
.
LogIndex
}]
=
&
sentMessage
...
...
@@ -68,13 +70,13 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
return
fmt
.
Errorf
(
"expected MessagePassedEvent preceding SentMessage. tx_hash = %s"
,
sentMessage
.
Event
.
TransactionHash
.
String
())
}
l2B
ridgeMessages
[
i
]
=
database
.
L2BridgeMessage
{
TransactionWithdrawalHash
:
messagePassed
.
WithdrawalHash
,
BridgeMessage
:
sentMessage
.
BridgeMessage
}
b
ridgeMessages
[
i
]
=
database
.
L2BridgeMessage
{
TransactionWithdrawalHash
:
messagePassed
.
WithdrawalHash
,
BridgeMessage
:
sentMessage
.
BridgeMessage
}
}
if
len
(
l2BridgeMessages
)
>
0
{
if
err
:=
db
.
BridgeMessages
.
StoreL2BridgeMessages
(
l2BridgeMessages
);
err
!=
nil
{
if
len
(
bridgeMessages
)
>
0
{
if
err
:=
db
.
BridgeMessages
.
StoreL2BridgeMessages
(
bridgeMessages
);
err
!=
nil
{
return
err
}
metrics
.
RecordL2CrossDomainSentMessages
(
len
(
bridgeMessages
))
}
// (3) L2StandardBridge
...
...
@@ -86,7 +88,8 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
log
.
Info
(
"detected bridge withdrawals"
,
"size"
,
len
(
initiatedBridges
))
}
l2BridgeWithdrawals
:=
make
([]
database
.
L2BridgeWithdrawal
,
len
(
initiatedBridges
))
bridgedTokens
:=
make
(
map
[
common
.
Address
]
int
)
bridgeWithdrawals
:=
make
([]
database
.
L2BridgeWithdrawal
,
len
(
initiatedBridges
))
for
i
:=
range
initiatedBridges
{
initiatedBridge
:=
initiatedBridges
[
i
]
...
...
@@ -103,13 +106,19 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
}
initiatedBridge
.
BridgeTransfer
.
CrossDomainMessageHash
=
&
sentMessage
.
BridgeMessage
.
MessageHash
l2BridgeWithdrawals
[
i
]
=
database
.
L2BridgeWithdrawal
{
TransactionWithdrawalHash
:
messagePassed
.
WithdrawalHash
,
BridgeTransfer
:
initiatedBridge
.
BridgeTransfer
}
bridgedTokens
[
initiatedBridge
.
BridgeTransfer
.
TokenPair
.
LocalTokenAddress
]
++
bridgeWithdrawals
[
i
]
=
database
.
L2BridgeWithdrawal
{
TransactionWithdrawalHash
:
messagePassed
.
WithdrawalHash
,
BridgeTransfer
:
initiatedBridge
.
BridgeTransfer
,
}
}
if
len
(
l2BridgeWithdrawals
)
>
0
{
if
err
:=
db
.
BridgeTransfers
.
StoreL2BridgeWithdrawals
(
l2BridgeWithdrawals
);
err
!=
nil
{
if
len
(
bridgeWithdrawals
)
>
0
{
if
err
:=
db
.
BridgeTransfers
.
StoreL2BridgeWithdrawals
(
bridgeWithdrawals
);
err
!=
nil
{
return
err
}
for
tokenAddr
,
size
:=
range
bridgedTokens
{
metrics
.
RecordL2InitiatedBridgeTransfers
(
tokenAddr
,
size
)
}
}
// a-ok!
...
...
@@ -122,7 +131,7 @@ func L2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
// 2. L2StandardBridge (no-op, since this is simply a wrapper over the L2CrossDomainMEssenger)
//
// NOTE: Unlike L1, there's no L2ToL1MessagePasser stage since transaction deposits are apart of the block derivation process.
func
L2ProcessFinalizedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
l2Contracts
config
.
L2Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
func
L2ProcessFinalizedBridgeEvents
(
log
log
.
Logger
,
db
*
database
.
DB
,
metrics
L2Metricer
,
l2Contracts
config
.
L2Contracts
,
fromHeight
,
toHeight
*
big
.
Int
)
error
{
// (1) L2CrossDomainMessenger
crossDomainRelayedMessages
,
err
:=
contracts
.
CrossDomainMessengerRelayedMessageEvents
(
"l2"
,
l2Contracts
.
L2CrossDomainMessenger
,
db
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
...
...
@@ -149,6 +158,9 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
return
err
}
}
if
len
(
relayedMessages
)
>
0
{
metrics
.
RecordL2CrossDomainRelayedMessages
(
len
(
relayedMessages
))
}
// (2) L2StandardBridge
finalizedBridges
,
err
:=
contracts
.
StandardBridgeFinalizedEvents
(
"l2"
,
l2Contracts
.
L2StandardBridge
,
db
,
fromHeight
,
toHeight
)
...
...
@@ -159,6 +171,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
log
.
Info
(
"detected finalized bridge deposits"
,
"size"
,
len
(
finalizedBridges
))
}
finalizedTokens
:=
make
(
map
[
common
.
Address
]
int
)
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
...
...
@@ -169,8 +182,7 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
return
fmt
.
Errorf
(
"expected RelayedMessage following BridgeFinalized event. tx_hash = %s"
,
finalizedBridge
.
Event
.
TransactionHash
.
String
())
}
// Since the message hash is computed from the relayed message, this ensures the withdrawal fields must match. For good measure,
// we may choose to make sure `deposit.BridgeTransfer` matches with the finalized bridge
// 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
...
...
@@ -178,6 +190,13 @@ func L2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, l2Contracts
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
]
++
}
if
len
(
finalizedBridges
)
>
0
{
for
tokenAddr
,
size
:=
range
finalizedTokens
{
metrics
.
RecordL2FinalizedBridgeTransfers
(
tokenAddr
,
size
)
}
}
// a-ok!
...
...
indexer/processors/bridge/legacy_bridge_processor.go
View file @
38d3505b
This diff is collapsed.
Click to expand it.
indexer/processors/bridge/metrics.go
0 → 100644
View file @
38d3505b
package
bridge
import
(
"math/big"
"github.com/ethereum-optimism/optimism/op-service/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/prometheus/client_golang/prometheus"
)
var
(
MetricsNamespace
string
=
"bridge"
)
type
L1Metricer
interface
{
RecordLatestIndexedL1Height
(
height
*
big
.
Int
)
RecordL1TransactionDeposits
(
size
int
)
RecordL1ProvenWithdrawals
(
size
int
)
RecordL1FinalizedWithdrawals
(
size
int
)
RecordL1CrossDomainSentMessages
(
size
int
)
RecordL1CrossDomainRelayedMessages
(
size
int
)
RecordL1InitiatedBridgeTransfers
(
token
common
.
Address
,
size
int
)
RecordL1FinalizedBridgeTransfers
(
token
common
.
Address
,
size
int
)
}
type
L2Metricer
interface
{
RecordLatestIndexedL2Height
(
height
*
big
.
Int
)
RecordL2TransactionWithdrawals
(
size
int
)
RecordL2CrossDomainSentMessages
(
size
int
)
RecordL2CrossDomainRelayedMessages
(
size
int
)
RecordL2InitiatedBridgeTransfers
(
token
common
.
Address
,
size
int
)
RecordL2FinalizedBridgeTransfers
(
token
common
.
Address
,
size
int
)
}
type
Metricer
interface
{
L1Metricer
L2Metricer
RecordInterval
()
(
done
func
(
err
error
))
}
type
bridgeMetrics
struct
{
intervalTick
prometheus
.
Counter
intervalDuration
prometheus
.
Histogram
intervalFailures
prometheus
.
Counter
latestL1Height
prometheus
.
Gauge
latestL2Height
prometheus
.
Gauge
txDeposits
prometheus
.
Counter
txWithdrawals
prometheus
.
Counter
provenWithdrawals
prometheus
.
Counter
finalizedWithdrawals
prometheus
.
Counter
sentMessages
*
prometheus
.
CounterVec
relayedMessages
*
prometheus
.
CounterVec
initiatedBridgeTransfers
*
prometheus
.
CounterVec
finalizedBridgeTransfers
*
prometheus
.
CounterVec
}
func
NewMetrics
(
registry
*
prometheus
.
Registry
)
Metricer
{
factory
:=
metrics
.
With
(
registry
)
return
&
bridgeMetrics
{
intervalTick
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"intervals_total"
,
Help
:
"number of times processing loop has run"
,
}),
intervalDuration
:
factory
.
NewHistogram
(
prometheus
.
HistogramOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"interval_seconds"
,
Help
:
"duration elapsed in the processing loop"
,
}),
intervalFailures
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"failures_total"
,
Help
:
"number of failures encountered"
,
}),
latestL1Height
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
MetricsNamespace
,
Subsystem
:
"l1"
,
Name
:
"height"
,
Help
:
"the latest processed l1 block height"
,
}),
latestL2Height
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
MetricsNamespace
,
Subsystem
:
"l2"
,
Name
:
"height"
,
Help
:
"the latest processed l2 block height"
,
}),
txDeposits
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"tx_deposits"
,
Help
:
"number of processed transactions deposited from l1"
,
}),
txWithdrawals
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"tx_withdrawals"
,
Help
:
"number of processed transactions withdrawn from l2"
,
}),
provenWithdrawals
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"proven_withdrawals"
,
Help
:
"number of proven tx withdrawals on l1"
,
}),
finalizedWithdrawals
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"finalized_withdrawals"
,
Help
:
"number of finalized tx withdrawals on l1"
,
}),
sentMessages
:
factory
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"sent_messages"
,
Help
:
"number of bridged messages between l1 and l2"
,
},
[]
string
{
"chain"
,
}),
relayedMessages
:
factory
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"relayed_messages"
,
Help
:
"number of relayed messages between l1 and l2"
,
},
[]
string
{
"chain"
,
}),
initiatedBridgeTransfers
:
factory
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"initiated_token_transfers"
,
Help
:
"number of bridged tokens between l1 and l2"
,
},
[]
string
{
"chain"
,
"token_address"
,
}),
finalizedBridgeTransfers
:
factory
.
NewCounterVec
(
prometheus
.
CounterOpts
{
Namespace
:
MetricsNamespace
,
Name
:
"finalized_token_transfers"
,
Help
:
"number of finalized token transfers between l1 and l2"
,
},
[]
string
{
"chain"
,
"token_address"
,
}),
}
}
func
(
m
*
bridgeMetrics
)
RecordInterval
()
func
(
error
)
{
m
.
intervalTick
.
Inc
()
timer
:=
prometheus
.
NewTimer
(
m
.
intervalDuration
)
return
func
(
err
error
)
{
timer
.
ObserveDuration
()
if
err
!=
nil
{
m
.
intervalFailures
.
Inc
()
}
}
}
// L1Metricer
func
(
m
*
bridgeMetrics
)
RecordLatestIndexedL1Height
(
height
*
big
.
Int
)
{
m
.
latestL1Height
.
Set
(
float64
(
height
.
Uint64
()))
}
func
(
m
*
bridgeMetrics
)
RecordL1TransactionDeposits
(
size
int
)
{
m
.
txDeposits
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1ProvenWithdrawals
(
size
int
)
{
m
.
provenWithdrawals
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1FinalizedWithdrawals
(
size
int
)
{
m
.
finalizedWithdrawals
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1CrossDomainSentMessages
(
size
int
)
{
m
.
sentMessages
.
WithLabelValues
(
"l1"
)
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1CrossDomainRelayedMessages
(
size
int
)
{
m
.
relayedMessages
.
WithLabelValues
(
"l1"
)
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1InitiatedBridgeTransfers
(
tokenAddr
common
.
Address
,
size
int
)
{
m
.
initiatedBridgeTransfers
.
WithLabelValues
(
"l1"
,
tokenAddr
.
String
())
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL1FinalizedBridgeTransfers
(
tokenAddr
common
.
Address
,
size
int
)
{
m
.
finalizedBridgeTransfers
.
WithLabelValues
(
"l1"
,
tokenAddr
.
String
())
.
Add
(
float64
(
size
))
}
// L2Metricer
func
(
m
*
bridgeMetrics
)
RecordLatestIndexedL2Height
(
height
*
big
.
Int
)
{
m
.
latestL2Height
.
Set
(
float64
(
height
.
Uint64
()))
}
func
(
m
*
bridgeMetrics
)
RecordL2TransactionWithdrawals
(
size
int
)
{
m
.
txWithdrawals
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL2CrossDomainSentMessages
(
size
int
)
{
m
.
sentMessages
.
WithLabelValues
(
"l2"
)
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL2CrossDomainRelayedMessages
(
size
int
)
{
m
.
relayedMessages
.
WithLabelValues
(
"l2"
)
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL2InitiatedBridgeTransfers
(
tokenAddr
common
.
Address
,
size
int
)
{
m
.
initiatedBridgeTransfers
.
WithLabelValues
(
"l2"
,
tokenAddr
.
String
())
.
Add
(
float64
(
size
))
}
func
(
m
*
bridgeMetrics
)
RecordL2FinalizedBridgeTransfers
(
tokenAddr
common
.
Address
,
size
int
)
{
m
.
finalizedBridgeTransfers
.
WithLabelValues
(
"l2"
,
tokenAddr
.
String
())
.
Add
(
float64
(
size
))
}
indexer/processors/contracts/legacy_standard_bridge.go
View file @
38d3505b
...
...
@@ -15,21 +15,23 @@ type LegacyBridgeEvent struct {
}
func
L1StandardBridgeLegacyDepositInitiatedEvents
(
contractAddress
common
.
Address
,
db
*
database
.
DB
,
fromHeight
,
toHeight
*
big
.
Int
)
([]
LegacyBridgeEvent
,
error
)
{
// The L1StandardBridge ABI contains the legacy events
l1StandardBridgeAbi
,
err
:=
bindings
.
L1StandardBridgeMetaData
.
GetAbi
()
if
err
!=
nil
{
return
nil
,
err
}
// The L1StandardBridge contains the legacy events
ethDepositEventAbi
:=
l1StandardBridgeAbi
.
Events
[
"ETHDepositInitiated"
]
erc20DepositEventAbi
:=
l1StandardBridgeAbi
.
Events
[
"ERC20DepositInitiated"
]
// Grab both ETH & ERC20 Events
ethDepositEvents
,
err
:=
db
.
ContractEvents
.
L1ContractEventsWithFilter
(
database
.
ContractEvent
{
ContractAddress
:
contractAddress
,
EventSignature
:
ethDepositEventAbi
.
ID
},
fromHeight
,
toHeight
)
contractEventFilter
:=
database
.
ContractEvent
{
ContractAddress
:
contractAddress
,
EventSignature
:
ethDepositEventAbi
.
ID
}
ethDepositEvents
,
err
:=
db
.
ContractEvents
.
L1ContractEventsWithFilter
(
contractEventFilter
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
return
nil
,
err
}
erc20DepositEvents
,
err
:=
db
.
ContractEvents
.
L1ContractEventsWithFilter
(
database
.
ContractEvent
{
ContractAddress
:
contractAddress
,
EventSignature
:
erc20DepositEventAbi
.
ID
},
fromHeight
,
toHeight
)
contractEventFilter
.
EventSignature
=
erc20DepositEventAbi
.
ID
erc20DepositEvents
,
err
:=
db
.
ContractEvents
.
L1ContractEventsWithFilter
(
contractEventFilter
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
@@ -81,13 +83,15 @@ func L1StandardBridgeLegacyDepositInitiatedEvents(contractAddress common.Address
}
func
L2StandardBridgeLegacyWithdrawalInitiatedEvents
(
contractAddress
common
.
Address
,
db
*
database
.
DB
,
fromHeight
,
toHeight
*
big
.
Int
)
([]
LegacyBridgeEvent
,
error
)
{
// The L2StandardBridge ABI contains the legacy events
l2StandardBridgeAbi
,
err
:=
bindings
.
L2StandardBridgeMetaData
.
GetAbi
()
if
err
!=
nil
{
return
nil
,
err
}
withdrawalInitiatedEventAbi
:=
l2StandardBridgeAbi
.
Events
[
"WithdrawalInitiated"
]
withdrawalEvents
,
err
:=
db
.
ContractEvents
.
L2ContractEventsWithFilter
(
database
.
ContractEvent
{
ContractAddress
:
contractAddress
,
EventSignature
:
withdrawalInitiatedEventAbi
.
ID
},
fromHeight
,
toHeight
)
contractEventFilter
:=
database
.
ContractEvent
{
ContractAddress
:
contractAddress
,
EventSignature
:
withdrawalInitiatedEventAbi
.
ID
}
withdrawalEvents
,
err
:=
db
.
ContractEvents
.
L2ContractEventsWithFilter
(
contractEventFilter
,
fromHeight
,
toHeight
)
if
err
!=
nil
{
return
nil
,
err
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment