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
bb4fe5d5
Unverified
Commit
bb4fe5d5
authored
Feb 15, 2024
by
refcell
Committed by
GitHub
Feb 15, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(op-dispute-mon): resolution delay metric refactors (#9563)
parent
f2cf85a0
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
162 additions
and
143 deletions
+162
-143
forecast.go
op-dispute-mon/mon/forecast.go
+5
-5
resolver.go
op-dispute-mon/mon/resolver.go
+10
-47
resolver_test.go
op-dispute-mon/mon/resolver_test.go
+27
-91
tree.go
op-dispute-mon/mon/transform/tree.go
+28
-0
tree_test.go
op-dispute-mon/mon/transform/tree_test.go
+80
-0
types.go
op-dispute-mon/mon/types/types.go
+12
-0
No files found.
op-dispute-mon/mon/forecast.go
View file @
bb4fe5d5
...
...
@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/transform"
monTypes
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -15,7 +16,6 @@ var (
ErrContractCreation
=
errors
.
New
(
"failed to create contract"
)
ErrMetadataFetch
=
errors
.
New
(
"failed to fetch game metadata"
)
ErrClaimFetch
=
errors
.
New
(
"failed to fetch game claims"
)
ErrResolver
=
errors
.
New
(
"failed to resolve game"
)
ErrRootAgreement
=
errors
.
New
(
"failed to check root agreement"
)
)
...
...
@@ -78,11 +78,11 @@ func (f *forecast) forecastGame(ctx context.Context, game types.GameMetadata, me
return
fmt
.
Errorf
(
"%w: %w"
,
ErrClaimFetch
,
err
)
}
// Create the bidirectional tree of claims.
tree
:=
transform
.
CreateBidirectionalTree
(
claims
)
// Compute the resolution status of the game.
status
,
err
=
Resolve
(
claims
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"%w: %w"
,
ErrResolver
,
err
)
}
status
=
Resolve
(
tree
)
// Check the root agreement.
agreement
,
expected
,
err
:=
f
.
validator
.
CheckRootAgreement
(
ctx
,
l2BlockNum
,
rootClaim
)
...
...
op-dispute-mon/mon/resolver.go
View file @
bb4fe5d5
package
mon
import
(
"fmt"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum/go-ethereum/common"
)
type
BidirectionalClaim
struct
{
Claim
*
faultTypes
.
Claim
Children
[]
*
BidirectionalClaim
}
// Resolve creates the bidirectional tree of claims and then computes the resolved game status.
func
Resolve
(
claims
[]
faultTypes
.
Claim
)
(
types
.
GameStatus
,
error
)
{
flatBidireactionalTree
,
err
:=
createBidirectionalTree
(
claims
)
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to create bidirectional tree: %w"
,
err
)
}
return
resolveTree
(
flatBidireactionalTree
),
nil
}
// createBidirectionalTree walks backwards through the list of claims and creates a bidirectional
// tree of claims. The root claim must be at index 0. The tree is returned as a flat array so it
// can be easily traversed following the resolution process.
func
createBidirectionalTree
(
claims
[]
faultTypes
.
Claim
)
([]
*
BidirectionalClaim
,
error
)
{
claimMap
:=
make
(
map
[
int
]
*
BidirectionalClaim
)
res
:=
make
([]
*
BidirectionalClaim
,
0
,
len
(
claims
))
for
_
,
claim
:=
range
claims
{
claim
:=
claim
bidirectionalClaim
:=
&
BidirectionalClaim
{
Claim
:
&
claim
,
}
claimMap
[
claim
.
ContractIndex
]
=
bidirectionalClaim
if
!
claim
.
IsRoot
()
{
// SAFETY: the parent must exist in the list prior to the current claim.
parent
:=
claimMap
[
claim
.
ParentContractIndex
]
parent
.
Children
=
append
(
parent
.
Children
,
bidirectionalClaim
)
}
res
=
append
(
res
,
bidirectionalClaim
)
}
return
res
,
nil
}
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
monTypes
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types"
)
//
resolveTre
e iterates backwards over the bidirectional tree, iteratively
//
Resolv
e iterates backwards over the bidirectional tree, iteratively
// checking the leftmost counter of each claim, and updating the claim's counter
// claimant. Once the root claim is reached, the resolution game status is returned.
func
resolveTree
(
tree
[]
*
BidirectionalClaim
)
t
ypes
.
GameStatus
{
for
i
:=
len
(
tree
)
-
1
;
i
>=
0
;
i
--
{
claim
:=
tree
[
i
]
func
Resolve
(
tree
*
monTypes
.
BidirectionalTree
)
gameT
ypes
.
GameStatus
{
for
i
:=
len
(
tree
.
Claims
)
-
1
;
i
>=
0
;
i
--
{
claim
:=
tree
.
Claims
[
i
]
counterClaimant
:=
common
.
Address
{}
for
_
,
child
:=
range
claim
.
Children
{
if
child
.
Claim
.
CounteredBy
==
(
common
.
Address
{})
{
...
...
@@ -58,9 +21,9 @@ func resolveTree(tree []*BidirectionalClaim) types.GameStatus {
}
claim
.
Claim
.
CounteredBy
=
counterClaimant
}
if
(
len
(
tree
)
==
0
||
tree
[
0
]
.
Claim
.
CounteredBy
==
common
.
Address
{})
{
return
t
ypes
.
GameStatusDefenderWon
if
(
len
(
tree
.
Claims
)
==
0
||
tree
.
Claims
[
0
]
.
Claim
.
CounteredBy
==
common
.
Address
{})
{
return
gameT
ypes
.
GameStatusDefenderWon
}
else
{
return
t
ypes
.
GameStatusChallengerWon
return
gameT
ypes
.
GameStatusChallengerWon
}
}
op-dispute-mon/mon/resolver_test.go
View file @
bb4fe5d5
...
...
@@ -9,118 +9,54 @@ import (
"github.com/stretchr/testify/require"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
monTypes
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types"
)
func
TestResolver_Resolve
(
t
*
testing
.
T
)
{
t
.
Run
(
"NoClaims"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
Resolve
([]
faultTypes
.
Claim
{})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
types
.
GameStatusDefenderWon
,
status
)
})
t
.
Run
(
"SingleClaim"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
Resolve
(
createDeepClaimList
()[
:
1
])
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
types
.
GameStatusDefenderWon
,
status
)
})
t
.
Run
(
"MultipleClaims"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
Resolve
(
createDeepClaimList
()[
:
2
])
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
types
.
GameStatusChallengerWon
,
status
)
})
t
.
Run
(
"MultipleClaimsAndChildren"
,
func
(
t
*
testing
.
T
)
{
status
,
err
:=
Resolve
(
createDeepClaimList
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
types
.
GameStatusDefenderWon
,
status
)
})
}
func
TestResolver_CreateBidirectionalTree
(
t
*
testing
.
T
)
{
t
.
Run
(
"SingleClaim"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()[
:
1
]
claims
[
0
]
.
CounteredBy
=
common
.
Address
{}
tree
,
err
:=
createBidirectionalTree
(
claims
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
tree
,
1
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
[
0
]
.
Claim
)
require
.
Empty
(
t
,
tree
[
0
]
.
Children
)
})
t
.
Run
(
"MultipleClaims"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()[
:
2
]
claims
[
1
]
.
CounteredBy
=
common
.
Address
{}
tree
,
err
:=
createBidirectionalTree
(
claims
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
tree
,
2
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
[
0
]
.
Claim
)
require
.
Len
(
t
,
tree
[
0
]
.
Children
,
1
)
require
.
Equal
(
t
,
claims
[
1
],
*
tree
[
0
]
.
Children
[
0
]
.
Claim
)
require
.
Equal
(
t
,
claims
[
1
],
*
tree
[
1
]
.
Claim
)
require
.
Empty
(
t
,
tree
[
1
]
.
Children
)
})
t
.
Run
(
"MultipleClaimsAndChildren"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()
tree
,
err
:=
createBidirectionalTree
(
claims
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
tree
,
3
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
[
0
]
.
Claim
)
require
.
Len
(
t
,
tree
[
0
]
.
Children
,
1
)
require
.
Equal
(
t
,
tree
[
0
]
.
Children
[
0
],
tree
[
1
])
require
.
Equal
(
t
,
claims
[
1
],
*
tree
[
1
]
.
Claim
)
require
.
Len
(
t
,
tree
[
1
]
.
Children
,
1
)
require
.
Equal
(
t
,
tree
[
1
]
.
Children
[
0
],
tree
[
2
])
require
.
Equal
(
t
,
claims
[
2
],
*
tree
[
2
]
.
Claim
)
require
.
Empty
(
t
,
tree
[
2
]
.
Children
)
})
}
func
TestResolver_ResolveTree
(
t
*
testing
.
T
)
{
t
.
Run
(
"NoClaims"
,
func
(
t
*
testing
.
T
)
{
status
:=
resolveTree
([]
*
BidirectionalClaim
{})
require
.
Equal
(
t
,
types
.
GameStatusDefenderWon
,
status
)
tree
:=
&
monTypes
.
BidirectionalTree
{
Claims
:
[]
*
monTypes
.
BidirectionalClaim
{}}
status
:=
Resolve
(
tree
)
require
.
Equal
(
t
,
gameTypes
.
GameStatusDefenderWon
,
status
)
})
t
.
Run
(
"SingleRootClaim"
,
func
(
t
*
testing
.
T
)
{
list
:=
createBidirectionalClaimList
()[
:
1
]
list
[
0
]
.
Claim
.
CounteredBy
=
common
.
Address
{}
status
:=
resolveTree
(
list
)
require
.
Equal
(
t
,
t
ypes
.
GameStatusDefenderWon
,
status
)
tree
:=
createBidirectionalTree
(
1
)
tree
.
Claims
[
0
]
.
Claim
.
CounteredBy
=
common
.
Address
{}
status
:=
Resolve
(
tree
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusDefenderWon
,
status
)
})
t
.
Run
(
"ChallengerWon"
,
func
(
t
*
testing
.
T
)
{
list
:=
createBidirectionalClaimList
()[
:
2
]
list
[
1
]
.
Claim
.
CounteredBy
=
common
.
Address
{}
list
[
1
]
.
Children
=
make
([]
*
BidirectionalClaim
,
0
)
status
:=
resolveTree
(
list
)
require
.
Equal
(
t
,
t
ypes
.
GameStatusChallengerWon
,
status
)
t
.
Run
(
"
ManyClaims_
ChallengerWon"
,
func
(
t
*
testing
.
T
)
{
tree
:=
createBidirectionalTree
(
2
)
tree
.
Claims
[
1
]
.
Claim
.
CounteredBy
=
common
.
Address
{}
tree
.
Claims
[
1
]
.
Children
=
make
([]
*
monTypes
.
BidirectionalClaim
,
0
)
status
:=
Resolve
(
tree
)
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusChallengerWon
,
status
)
})
t
.
Run
(
"DefenderWon"
,
func
(
t
*
testing
.
T
)
{
status
:=
resolveTree
(
createBidirectionalClaimList
(
))
require
.
Equal
(
t
,
t
ypes
.
GameStatusDefenderWon
,
status
)
t
.
Run
(
"
ManyClaims_
DefenderWon"
,
func
(
t
*
testing
.
T
)
{
status
:=
Resolve
(
createBidirectionalTree
(
3
))
require
.
Equal
(
t
,
gameT
ypes
.
GameStatusDefenderWon
,
status
)
})
}
func
createBidirectional
ClaimList
()
[]
*
BidirectionalClaim
{
func
createBidirectional
Tree
(
claimCount
uint64
)
*
monTypes
.
BidirectionalTree
{
claimList
:=
createDeepClaimList
()
bidirectionalClaimList
:=
make
([]
*
BidirectionalClaim
,
len
(
claimList
))
bidirectionalClaimList
[
2
]
=
&
BidirectionalClaim
{
bidirectionalClaimList
:=
make
([]
*
monTypes
.
BidirectionalClaim
,
len
(
claimList
))
bidirectionalClaimList
[
2
]
=
&
monTypes
.
BidirectionalClaim
{
Claim
:
&
claimList
[
2
],
Children
:
make
([]
*
BidirectionalClaim
,
0
),
Children
:
make
([]
*
monTypes
.
BidirectionalClaim
,
0
),
}
bidirectionalClaimList
[
1
]
=
&
BidirectionalClaim
{
bidirectionalClaimList
[
1
]
=
&
monTypes
.
BidirectionalClaim
{
Claim
:
&
claimList
[
1
],
Children
:
[]
*
BidirectionalClaim
{
bidirectionalClaimList
[
2
]},
Children
:
[]
*
monTypes
.
BidirectionalClaim
{
bidirectionalClaimList
[
2
]},
}
bidirectionalClaimList
[
0
]
=
&
BidirectionalClaim
{
bidirectionalClaimList
[
0
]
=
&
monTypes
.
BidirectionalClaim
{
Claim
:
&
claimList
[
0
],
Children
:
[]
*
BidirectionalClaim
{
bidirectionalClaimList
[
1
]},
Children
:
[]
*
monTypes
.
BidirectionalClaim
{
bidirectionalClaimList
[
1
]},
}
return
bidirectionalClaimList
return
&
monTypes
.
BidirectionalTree
{
Claims
:
bidirectionalClaimList
[
:
claimCount
]}
}
func
createDeepClaimList
()
[]
faultTypes
.
Claim
{
...
...
op-dispute-mon/mon/transform/tree.go
0 → 100644
View file @
bb4fe5d5
package
transform
import
(
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
monTypes
"github.com/ethereum-optimism/optimism/op-dispute-mon/mon/types"
)
// CreateBidirectionalTree walks backwards through the list of claims and creates a bidirectional
// tree of claims. The root claim must be at index 0. The tree is returned as a flat array so it
// can be easily traversed following the resolution process.
func
CreateBidirectionalTree
(
claims
[]
types
.
Claim
)
*
monTypes
.
BidirectionalTree
{
claimMap
:=
make
(
map
[
int
]
*
monTypes
.
BidirectionalClaim
)
res
:=
make
([]
*
monTypes
.
BidirectionalClaim
,
0
,
len
(
claims
))
for
_
,
claim
:=
range
claims
{
claim
:=
claim
bidirectionalClaim
:=
&
monTypes
.
BidirectionalClaim
{
Claim
:
&
claim
,
}
claimMap
[
claim
.
ContractIndex
]
=
bidirectionalClaim
if
!
claim
.
IsRoot
()
{
// SAFETY: the parent must exist in the list prior to the current claim.
parent
:=
claimMap
[
claim
.
ParentContractIndex
]
parent
.
Children
=
append
(
parent
.
Children
,
bidirectionalClaim
)
}
res
=
append
(
res
,
bidirectionalClaim
)
}
return
&
monTypes
.
BidirectionalTree
{
Claims
:
res
}
}
op-dispute-mon/mon/transform/tree_test.go
0 → 100644
View file @
bb4fe5d5
package
transform
import
(
"math"
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
)
func
TestResolver_CreateBidirectionalTree
(
t
*
testing
.
T
)
{
t
.
Run
(
"SingleClaim"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()[
:
1
]
claims
[
0
]
.
CounteredBy
=
common
.
Address
{}
tree
:=
CreateBidirectionalTree
(
claims
)
require
.
Len
(
t
,
tree
.
Claims
,
1
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
.
Claims
[
0
]
.
Claim
)
require
.
Empty
(
t
,
tree
.
Claims
[
0
]
.
Children
)
})
t
.
Run
(
"MultipleClaims"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()[
:
2
]
claims
[
1
]
.
CounteredBy
=
common
.
Address
{}
tree
:=
CreateBidirectionalTree
(
claims
)
require
.
Len
(
t
,
tree
.
Claims
,
2
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
.
Claims
[
0
]
.
Claim
)
require
.
Len
(
t
,
tree
.
Claims
[
0
]
.
Children
,
1
)
require
.
Equal
(
t
,
claims
[
1
],
*
tree
.
Claims
[
0
]
.
Children
[
0
]
.
Claim
)
require
.
Equal
(
t
,
claims
[
1
],
*
tree
.
Claims
[
1
]
.
Claim
)
require
.
Empty
(
t
,
tree
.
Claims
[
1
]
.
Children
)
})
t
.
Run
(
"MultipleClaimsAndChildren"
,
func
(
t
*
testing
.
T
)
{
claims
:=
createDeepClaimList
()
tree
:=
CreateBidirectionalTree
(
claims
)
require
.
Len
(
t
,
tree
.
Claims
,
3
)
require
.
Equal
(
t
,
claims
[
0
],
*
tree
.
Claims
[
0
]
.
Claim
)
require
.
Len
(
t
,
tree
.
Claims
[
0
]
.
Children
,
1
)
require
.
Equal
(
t
,
tree
.
Claims
[
0
]
.
Children
[
0
],
tree
.
Claims
[
1
])
require
.
Equal
(
t
,
claims
[
1
],
*
tree
.
Claims
[
1
]
.
Claim
)
require
.
Len
(
t
,
tree
.
Claims
[
1
]
.
Children
,
1
)
require
.
Equal
(
t
,
tree
.
Claims
[
1
]
.
Children
[
0
],
tree
.
Claims
[
2
])
require
.
Equal
(
t
,
claims
[
2
],
*
tree
.
Claims
[
2
]
.
Claim
)
require
.
Empty
(
t
,
tree
.
Claims
[
2
]
.
Children
)
})
}
func
createDeepClaimList
()
[]
types
.
Claim
{
return
[]
types
.
Claim
{
{
ClaimData
:
types
.
ClaimData
{
Position
:
types
.
NewPosition
(
0
,
big
.
NewInt
(
0
)),
},
ContractIndex
:
0
,
CounteredBy
:
common
.
HexToAddress
(
"0x222222"
),
ParentContractIndex
:
math
.
MaxInt64
,
Claimant
:
common
.
HexToAddress
(
"0x111111"
),
},
{
ClaimData
:
types
.
ClaimData
{
Position
:
types
.
NewPosition
(
1
,
big
.
NewInt
(
0
)),
},
CounteredBy
:
common
.
HexToAddress
(
"0x111111"
),
ContractIndex
:
1
,
ParentContractIndex
:
0
,
Claimant
:
common
.
HexToAddress
(
"0x222222"
),
},
{
ClaimData
:
types
.
ClaimData
{
Position
:
types
.
NewPosition
(
2
,
big
.
NewInt
(
0
)),
},
ContractIndex
:
2
,
ParentContractIndex
:
1
,
Claimant
:
common
.
HexToAddress
(
"0x111111"
),
},
}
}
op-dispute-mon/mon/types/types.go
View file @
bb4fe5d5
package
types
import
(
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum/go-ethereum/common"
)
...
...
@@ -12,6 +13,17 @@ type EnrichedGameData struct {
Status
types
.
GameStatus
}
// BidirectionalTree is a tree of claims represented as a flat list of claims.
// This keeps the tree structure identical to how claims are stored in the contract.
type
BidirectionalTree
struct
{
Claims
[]
*
BidirectionalClaim
}
type
BidirectionalClaim
struct
{
Claim
*
faultTypes
.
Claim
Children
[]
*
BidirectionalClaim
}
type
StatusBatch
struct
{
InProgress
int
DefenderWon
int
...
...
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