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
5843583a
Unverified
Commit
5843583a
authored
Jun 14, 2024
by
Adrian Sutton
Committed by
GitHub
Jun 14, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dispute-mon: Add metric to report the total withdrawable ETH for each honest actor (#10838)
parent
3aeb6bdd
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
121 additions
and
36 deletions
+121
-36
metrics.go
op-dispute-mon/metrics/metrics.go
+17
-1
noop.go
op-dispute-mon/metrics/noop.go
+2
-0
monitor.go
op-dispute-mon/mon/bonds/monitor.go
+21
-7
monitor_test.go
op-dispute-mon/mon/bonds/monitor_test.go
+48
-11
claims.go
op-dispute-mon/mon/claims.go
+3
-7
claims_test.go
op-dispute-mon/mon/claims_test.go
+2
-2
service.go
op-dispute-mon/mon/service.go
+11
-8
honest_actors.go
op-dispute-mon/mon/types/honest_actors.go
+17
-0
No files found.
op-dispute-mon/metrics/metrics.go
View file @
5843583a
...
...
@@ -163,6 +163,8 @@ type Metricer interface {
RecordCredit
(
expectation
CreditExpectation
,
count
int
)
RecordHonestWithdrawableAmounts
(
map
[
common
.
Address
]
*
big
.
Int
)
RecordClaims
(
statuses
*
ClaimStatuses
)
RecordWithdrawalRequests
(
delayedWeth
common
.
Address
,
matches
bool
,
count
int
)
...
...
@@ -208,7 +210,8 @@ type Metrics struct {
info
prometheus
.
GaugeVec
up
prometheus
.
Gauge
credits
prometheus
.
GaugeVec
credits
prometheus
.
GaugeVec
honestWithdrawableAmounts
prometheus
.
GaugeVec
lastOutputFetch
prometheus
.
Gauge
...
...
@@ -295,6 +298,13 @@ func NewMetrics() *Metrics {
"credit"
,
"withdrawable"
,
}),
honestWithdrawableAmounts
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Name
:
"honest_actor_pending_withdrawals"
,
Help
:
"Current amount of withdrawable ETH for an honest actor"
,
},
[]
string
{
"actor"
,
}),
claims
:
*
factory
.
NewGaugeVec
(
prometheus
.
GaugeOpts
{
Namespace
:
Namespace
,
Name
:
"claims"
,
...
...
@@ -453,6 +463,12 @@ func (m *Metrics) RecordCredit(expectation CreditExpectation, count int) {
m
.
credits
.
WithLabelValues
(
asLabels
(
expectation
)
...
)
.
Set
(
float64
(
count
))
}
func
(
m
*
Metrics
)
RecordHonestWithdrawableAmounts
(
amounts
map
[
common
.
Address
]
*
big
.
Int
)
{
for
addr
,
amount
:=
range
amounts
{
m
.
honestWithdrawableAmounts
.
WithLabelValues
(
addr
.
Hex
())
.
Set
(
weiToEther
(
amount
))
}
}
func
(
m
*
Metrics
)
RecordClaims
(
statuses
*
ClaimStatuses
)
{
statuses
.
ForEachStatus
(
func
(
status
ClaimStatus
,
count
int
)
{
m
.
claims
.
WithLabelValues
(
status
.
AsLabels
()
...
)
.
Set
(
float64
(
count
))
...
...
op-dispute-mon/metrics/noop.go
View file @
5843583a
...
...
@@ -28,6 +28,8 @@ func (*NoopMetricsImpl) RecordGameResolutionStatus(_ ResolutionStatus, _ int) {}
func
(
*
NoopMetricsImpl
)
RecordCredit
(
_
CreditExpectation
,
_
int
)
{}
func
(
*
NoopMetricsImpl
)
RecordHonestWithdrawableAmounts
(
map
[
common
.
Address
]
*
big
.
Int
)
{}
func
(
*
NoopMetricsImpl
)
RecordClaims
(
_
*
ClaimStatuses
)
{}
func
(
*
NoopMetricsImpl
)
RecordWithdrawalRequests
(
_
common
.
Address
,
_
bool
,
_
int
)
{}
...
...
op-dispute-mon/mon/bonds/monitor.go
View file @
5843583a
...
...
@@ -17,19 +17,22 @@ type RClock interface {
type
BondMetrics
interface
{
RecordCredit
(
expectation
metrics
.
CreditExpectation
,
count
int
)
RecordBondCollateral
(
addr
common
.
Address
,
required
*
big
.
Int
,
available
*
big
.
Int
)
RecordHonestWithdrawableAmounts
(
map
[
common
.
Address
]
*
big
.
Int
)
}
type
Bonds
struct
{
logger
log
.
Logger
clock
RClock
metrics
BondMetrics
logger
log
.
Logger
clock
RClock
metrics
BondMetrics
honestActors
types
.
HonestActors
}
func
NewBonds
(
logger
log
.
Logger
,
metrics
BondMetrics
,
clock
RClock
)
*
Bonds
{
func
NewBonds
(
logger
log
.
Logger
,
metrics
BondMetrics
,
honestActors
types
.
HonestActors
,
clock
RClock
)
*
Bonds
{
return
&
Bonds
{
logger
:
logger
,
clock
:
clock
,
metrics
:
metrics
,
logger
:
logger
,
clock
:
clock
,
metrics
:
metrics
,
honestActors
:
honestActors
,
}
}
...
...
@@ -47,6 +50,10 @@ func (b *Bonds) CheckBonds(games []*types.EnrichedGameData) {
func
(
b
*
Bonds
)
checkCredits
(
games
[]
*
types
.
EnrichedGameData
)
{
creditMetrics
:=
make
(
map
[
metrics
.
CreditExpectation
]
int
)
honestWithdrawableAmounts
:=
make
(
map
[
common
.
Address
]
*
big
.
Int
)
for
address
:=
range
b
.
honestActors
{
honestWithdrawableAmounts
[
address
]
=
big
.
NewInt
(
0
)
}
for
_
,
game
:=
range
games
{
// Check if the max duration has been reached for this game
...
...
@@ -94,6 +101,12 @@ func (b *Bonds) checkCredits(games []*types.EnrichedGameData) {
}
comparison
:=
actual
.
Cmp
(
expected
)
if
maxDurationReached
{
if
actual
.
Cmp
(
big
.
NewInt
(
0
))
>
0
&&
b
.
honestActors
.
Contains
(
recipient
)
{
total
:=
honestWithdrawableAmounts
[
recipient
]
total
=
new
(
big
.
Int
)
.
Add
(
total
,
actual
)
honestWithdrawableAmounts
[
recipient
]
=
total
b
.
logger
.
Warn
(
"Found unclaimed credit"
,
"recipient"
,
recipient
,
"game"
,
game
.
Proxy
,
"amount"
,
actual
)
}
if
comparison
>
0
{
creditMetrics
[
metrics
.
CreditAboveWithdrawable
]
+=
1
b
.
logger
.
Warn
(
"Credit above expected amount"
,
"recipient"
,
recipient
,
"expected"
,
expected
,
"actual"
,
actual
,
"game"
,
game
.
Proxy
,
"withdrawable"
,
"withdrawable"
)
...
...
@@ -123,4 +136,5 @@ func (b *Bonds) checkCredits(games []*types.EnrichedGameData) {
b
.
metrics
.
RecordCredit
(
metrics
.
CreditBelowNonWithdrawable
,
creditMetrics
[
metrics
.
CreditBelowNonWithdrawable
])
b
.
metrics
.
RecordCredit
(
metrics
.
CreditEqualNonWithdrawable
,
creditMetrics
[
metrics
.
CreditEqualNonWithdrawable
])
b
.
metrics
.
RecordCredit
(
metrics
.
CreditAboveNonWithdrawable
,
creditMetrics
[
metrics
.
CreditAboveNonWithdrawable
])
b
.
metrics
.
RecordHonestWithdrawableAmounts
(
honestWithdrawableAmounts
)
}
op-dispute-mon/mon/bonds/monitor_test.go
View file @
5843583a
...
...
@@ -17,7 +17,10 @@ import (
)
var
(
frozen
=
time
.
Unix
(
int64
(
time
.
Hour
.
Seconds
()),
0
)
frozen
=
time
.
Unix
(
int64
(
time
.
Hour
.
Seconds
()),
0
)
honestActor1
=
common
.
Address
{
0x11
,
0xaa
}
honestActor2
=
common
.
Address
{
0x22
,
0xbb
}
honestActor3
=
common
.
Address
{
0x33
,
0xcc
}
)
func
TestCheckBonds
(
t
*
testing
.
T
)
{
...
...
@@ -61,8 +64,8 @@ func TestCheckBonds(t *testing.T) {
}
func
TestCheckRecipientCredit
(
t
*
testing
.
T
)
{
addr1
:=
common
.
Address
{
0x1a
}
addr2
:=
common
.
Address
{
0x2b
}
addr1
:=
honestActor1
addr2
:=
honestActor2
addr3
:=
common
.
Address
{
0x3c
}
addr4
:=
common
.
Address
{
0x4d
}
notRootPosition
:=
types
.
NewPositionFromGIndex
(
big
.
NewInt
(
2
))
...
...
@@ -273,7 +276,7 @@ func TestCheckRecipientCredit(t *testing.T) {
MaxClockDuration
:
10
,
WETHDelay
:
10
*
time
.
Second
,
GameMetadata
:
gameTypes
.
GameMetadata
{
Proxy
:
common
.
Address
{
44
},
Proxy
:
common
.
Address
{
0x
44
},
Timestamp
:
uint64
(
frozen
.
Unix
())
-
22
,
},
BlockNumberChallenged
:
true
,
...
...
@@ -346,6 +349,14 @@ func TestCheckRecipientCredit(t *testing.T) {
require
.
Equal
(
t
,
2
,
m
.
credits
[
metrics
.
CreditEqualNonWithdrawable
],
"CreditEqualNonWithdrawable"
)
require
.
Equal
(
t
,
2
,
m
.
credits
[
metrics
.
CreditAboveNonWithdrawable
],
"CreditAboveNonWithdrawable"
)
require
.
Len
(
t
,
m
.
honestWithdrawable
,
3
)
requireBigInt
:=
func
(
name
string
,
expected
,
actual
*
big
.
Int
)
{
require
.
Truef
(
t
,
expected
.
Cmp
(
actual
)
==
0
,
"Expected %v withdrawable to be %v but was %v"
,
name
,
expected
,
actual
)
}
requireBigInt
(
"honest addr1"
,
m
.
honestWithdrawable
[
addr1
],
big
.
NewInt
(
19
))
requireBigInt
(
"honest addr2"
,
m
.
honestWithdrawable
[
addr2
],
big
.
NewInt
(
13
))
requireBigInt
(
"honest addr3"
,
m
.
honestWithdrawable
[
honestActor3
],
big
.
NewInt
(
0
))
// Logs from game1
// addr1 is correct so has no logs
// addr2 is below expected before max duration, so warn about early withdrawal
...
...
@@ -371,8 +382,18 @@ func TestCheckRecipientCredit(t *testing.T) {
testlog
.
NewAttributesFilter
(
"withdrawable"
,
"non_withdrawable"
)))
// Logs from game 2
// addr1 is below expected - no warning as withdrawals may now be possible
// addr2 is correct
// addr1 is below expected - no warning as withdrawals may now be possible, but has unclaimed credit
require
.
NotNil
(
t
,
logs
.
FindLog
(
testlog
.
NewLevelFilter
(
log
.
LevelWarn
),
testlog
.
NewMessageFilter
(
"Found unclaimed credit"
),
testlog
.
NewAttributesFilter
(
"game"
,
game2
.
Proxy
.
Hex
()),
testlog
.
NewAttributesFilter
(
"recipient"
,
addr1
.
Hex
())))
// addr2 is correct but has unclaimed credit
require
.
NotNil
(
t
,
logs
.
FindLog
(
testlog
.
NewLevelFilter
(
log
.
LevelWarn
),
testlog
.
NewMessageFilter
(
"Found unclaimed credit"
),
testlog
.
NewAttributesFilter
(
"game"
,
game2
.
Proxy
.
Hex
()),
testlog
.
NewAttributesFilter
(
"recipient"
,
addr2
.
Hex
())))
// addr3 is above expected - warn
require
.
NotNil
(
t
,
logs
.
FindLog
(
testlog
.
NewLevelFilter
(
log
.
LevelWarn
),
...
...
@@ -401,8 +422,18 @@ func TestCheckRecipientCredit(t *testing.T) {
testlog
.
NewAttributesFilter
(
"withdrawable"
,
"non_withdrawable"
)))
// Logs from game 4
// addr1 is correct so has no logs
// addr2 is below expected before max duration, no long because withdrawals may be possible
// addr1 is correct but has unclaimed credit
require
.
NotNil
(
t
,
logs
.
FindLog
(
testlog
.
NewLevelFilter
(
log
.
LevelWarn
),
testlog
.
NewMessageFilter
(
"Found unclaimed credit"
),
testlog
.
NewAttributesFilter
(
"game"
,
game4
.
Proxy
.
Hex
()),
testlog
.
NewAttributesFilter
(
"recipient"
,
addr1
.
Hex
())))
// addr2 is below expected before max duration, no log because withdrawals may be possible but warn about unclaimed
require
.
NotNil
(
t
,
logs
.
FindLog
(
testlog
.
NewLevelFilter
(
log
.
LevelWarn
),
testlog
.
NewMessageFilter
(
"Found unclaimed credit"
),
testlog
.
NewAttributesFilter
(
"game"
,
game4
.
Proxy
.
Hex
()),
testlog
.
NewAttributesFilter
(
"recipient"
,
addr2
.
Hex
())))
// addr3 is not involved so no logs
// addr4 is above expected before max duration, so warn
require
.
NotNil
(
t
,
logs
.
FindLog
(
...
...
@@ -419,13 +450,19 @@ func setupBondMetricsTest(t *testing.T) (*Bonds, *stubBondMetrics, *testlog.Capt
credits
:
make
(
map
[
metrics
.
CreditExpectation
]
int
),
recorded
:
make
(
map
[
common
.
Address
]
Collateral
),
}
bonds
:=
NewBonds
(
logger
,
metrics
,
clock
.
NewDeterministicClock
(
frozen
))
honestActors
:=
monTypes
.
NewHonestActors
([]
common
.
Address
{
honestActor1
,
honestActor2
,
honestActor3
})
bonds
:=
NewBonds
(
logger
,
metrics
,
honestActors
,
clock
.
NewDeterministicClock
(
frozen
))
return
bonds
,
metrics
,
logs
}
type
stubBondMetrics
struct
{
credits
map
[
metrics
.
CreditExpectation
]
int
recorded
map
[
common
.
Address
]
Collateral
credits
map
[
metrics
.
CreditExpectation
]
int
recorded
map
[
common
.
Address
]
Collateral
honestWithdrawable
map
[
common
.
Address
]
*
big
.
Int
}
func
(
s
*
stubBondMetrics
)
RecordHonestWithdrawableAmounts
(
values
map
[
common
.
Address
]
*
big
.
Int
)
{
s
.
honestWithdrawable
=
values
}
func
(
s
*
stubBondMetrics
)
RecordBondCollateral
(
addr
common
.
Address
,
required
*
big
.
Int
,
available
*
big
.
Int
)
{
...
...
op-dispute-mon/mon/claims.go
View file @
5843583a
...
...
@@ -25,16 +25,12 @@ type ClaimMetrics interface {
type
ClaimMonitor
struct
{
logger
log
.
Logger
clock
RClock
honestActors
map
[
common
.
Address
]
bool
// Map for efficient lookup
honestActors
types
.
HonestActors
metrics
ClaimMetrics
}
func
NewClaimMonitor
(
logger
log
.
Logger
,
clock
RClock
,
honestActors
[]
common
.
Address
,
metrics
ClaimMetrics
)
*
ClaimMonitor
{
actors
:=
make
(
map
[
common
.
Address
]
bool
)
for
_
,
actor
:=
range
honestActors
{
actors
[
actor
]
=
true
}
return
&
ClaimMonitor
{
logger
,
clock
,
actors
,
metrics
}
func
NewClaimMonitor
(
logger
log
.
Logger
,
clock
RClock
,
honestActors
types
.
HonestActors
,
metrics
ClaimMetrics
)
*
ClaimMonitor
{
return
&
ClaimMonitor
{
logger
,
clock
,
honestActors
,
metrics
}
}
func
(
c
*
ClaimMonitor
)
CheckClaims
(
games
[]
*
types
.
EnrichedGameData
)
{
...
...
op-dispute-mon/mon/claims_test.go
View file @
5843583a
...
...
@@ -194,10 +194,10 @@ func newTestClaimMonitor(t *testing.T) (*ClaimMonitor, *clock.DeterministicClock
logger
,
handler
:=
testlog
.
CaptureLogger
(
t
,
log
.
LvlInfo
)
cl
:=
clock
.
NewDeterministicClock
(
frozen
)
metrics
:=
&
stubClaimMetrics
{}
honestActors
:=
[]
common
.
Address
{
honestActors
:=
types
.
NewHonestActors
(
[]
common
.
Address
{
{
0x01
},
{
0x02
},
}
}
)
monitor
:=
NewClaimMonitor
(
logger
,
cl
,
honestActors
,
metrics
)
return
monitor
,
cl
,
metrics
,
handler
}
...
...
op-dispute-mon/mon/service.go
View file @
5843583a
...
...
@@ -8,6 +8,7 @@ import (
"sync/atomic"
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/bonds"
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -28,9 +29,10 @@ import (
)
type
Service
struct
{
logger
log
.
Logger
metrics
metrics
.
Metricer
monitor
*
gameMonitor
logger
log
.
Logger
metrics
metrics
.
Metricer
monitor
*
gameMonitor
honestActors
types
.
HonestActors
factoryContract
*
contracts
.
DisputeGameFactoryContract
...
...
@@ -56,9 +58,10 @@ type Service struct {
// NewService creates a new Service.
func
NewService
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
)
(
*
Service
,
error
)
{
s
:=
&
Service
{
cl
:
clock
.
SystemClock
,
logger
:
logger
,
metrics
:
metrics
.
NewMetrics
(),
cl
:
clock
.
SystemClock
,
logger
:
logger
,
metrics
:
metrics
.
NewMetrics
(),
honestActors
:
types
.
NewHonestActors
(
cfg
.
HonestActors
),
}
if
err
:=
s
.
initFromConfig
(
ctx
,
cfg
);
err
!=
nil
{
...
...
@@ -105,7 +108,7 @@ func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error
}
func
(
s
*
Service
)
initClaimMonitor
(
cfg
*
config
.
Config
)
{
s
.
claims
=
NewClaimMonitor
(
s
.
logger
,
s
.
cl
,
cfg
.
H
onestActors
,
s
.
metrics
)
s
.
claims
=
NewClaimMonitor
(
s
.
logger
,
s
.
cl
,
s
.
h
onestActors
,
s
.
metrics
)
}
func
(
s
*
Service
)
initResolutionMonitor
()
{
...
...
@@ -142,7 +145,7 @@ func (s *Service) initForecast(cfg *config.Config) {
}
func
(
s
*
Service
)
initBonds
()
{
s
.
bonds
=
bonds
.
NewBonds
(
s
.
logger
,
s
.
metrics
,
s
.
cl
)
s
.
bonds
=
bonds
.
NewBonds
(
s
.
logger
,
s
.
metrics
,
s
.
honestActors
,
s
.
cl
)
}
func
(
s
*
Service
)
initOutputRollupClient
(
ctx
context
.
Context
,
cfg
*
config
.
Config
)
error
{
...
...
op-dispute-mon/mon/types/honest_actors.go
0 → 100644
View file @
5843583a
package
types
import
"github.com/ethereum/go-ethereum/common"
type
HonestActors
map
[
common
.
Address
]
bool
// Map for efficient lookup
func
NewHonestActors
(
honestActors
[]
common
.
Address
)
HonestActors
{
actors
:=
make
(
map
[
common
.
Address
]
bool
)
for
_
,
actor
:=
range
honestActors
{
actors
[
actor
]
=
true
}
return
actors
}
func
(
h
HonestActors
)
Contains
(
addr
common
.
Address
)
bool
{
return
h
[
addr
]
}
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