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
04a2b4e3
Unverified
Commit
04a2b4e3
authored
Aug 10, 2023
by
mergify[bot]
Committed by
GitHub
Aug 10, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into dependabot/go_modules/github.com/hashicorp/golang-lru-1.0.2
parents
c65355f4
56751b5b
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
207 additions
and
33 deletions
+207
-33
loader.go
op-challenger/fault/loader.go
+26
-9
loader_test.go
op-challenger/fault/loader_test.go
+52
-21
service.go
op-challenger/fault/service.go
+24
-3
service_test.go
op-challenger/fault/service_test.go
+105
-0
No files found.
op-challenger/fault/loader.go
View file @
04a2b4e3
...
...
@@ -8,9 +8,9 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
)
//
ClaimFetch
er is a minimal interface around [bindings.FaultDisputeGameCaller].
//
MinimalFaultDisputeGameCall
er is a minimal interface around [bindings.FaultDisputeGameCaller].
// This needs to be updated if the [bindings.FaultDisputeGameCaller] interface changes.
type
ClaimFetch
er
interface
{
type
MinimalFaultDisputeGameCall
er
interface
{
ClaimData
(
opts
*
bind
.
CallOpts
,
arg0
*
big
.
Int
)
(
struct
{
ParentIndex
uint32
Countered
bool
...
...
@@ -20,23 +20,25 @@ type ClaimFetcher interface {
},
error
)
ClaimDataLen
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
MAXGAMEDEPTH
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
ABSOLUTEPRESTATE
(
opts
*
bind
.
CallOpts
)
([
32
]
byte
,
error
)
}
// Loader is a minimal interface for loading onchain [Claim] data.
type
Loader
interface
{
FetchClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
FetchGameDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
FetchAbsolutePrestateHash
(
ctx
context
.
Context
)
([]
byte
,
error
)
}
// loader pulls in fault dispute game claim data periodically and over subscriptions.
type
loader
struct
{
c
laimFetcher
ClaimFetch
er
c
aller
MinimalFaultDisputeGameCall
er
}
// NewLoader creates a new [loader].
func
NewLoader
(
c
laimFetcher
ClaimFetch
er
)
*
loader
{
func
NewLoader
(
c
aller
MinimalFaultDisputeGameCall
er
)
*
loader
{
return
&
loader
{
c
laimFetcher
:
claimFetch
er
,
c
aller
:
call
er
,
}
}
...
...
@@ -46,7 +48,7 @@ func (l *loader) FetchGameDepth(ctx context.Context) (uint64, error) {
Context
:
ctx
,
}
gameDepth
,
err
:=
l
.
c
laimFetch
er
.
MAXGAMEDEPTH
(
&
callOpts
)
gameDepth
,
err
:=
l
.
c
all
er
.
MAXGAMEDEPTH
(
&
callOpts
)
if
err
!=
nil
{
return
0
,
err
}
...
...
@@ -60,7 +62,7 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim,
Context
:
ctx
,
}
fetchedClaim
,
err
:=
l
.
c
laimFetch
er
.
ClaimData
(
&
callOpts
,
new
(
big
.
Int
)
.
SetUint64
(
arrIndex
))
fetchedClaim
,
err
:=
l
.
c
all
er
.
ClaimData
(
&
callOpts
,
new
(
big
.
Int
)
.
SetUint64
(
arrIndex
))
if
err
!=
nil
{
return
types
.
Claim
{},
err
}
...
...
@@ -78,7 +80,7 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim,
if
!
claim
.
IsRootPosition
()
{
parentIndex
:=
uint64
(
fetchedClaim
.
ParentIndex
)
parentClaim
,
err
:=
l
.
c
laimFetch
er
.
ClaimData
(
&
callOpts
,
new
(
big
.
Int
)
.
SetUint64
(
parentIndex
))
parentClaim
,
err
:=
l
.
c
all
er
.
ClaimData
(
&
callOpts
,
new
(
big
.
Int
)
.
SetUint64
(
parentIndex
))
if
err
!=
nil
{
return
types
.
Claim
{},
err
}
...
...
@@ -94,7 +96,7 @@ func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim,
// FetchClaims fetches all claims from the fault dispute game.
func
(
l
*
loader
)
FetchClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
{
// Get the current claim count.
claimCount
,
err
:=
l
.
c
laimFetch
er
.
ClaimDataLen
(
&
bind
.
CallOpts
{
claimCount
,
err
:=
l
.
c
all
er
.
ClaimDataLen
(
&
bind
.
CallOpts
{
Context
:
ctx
,
})
if
err
!=
nil
{
...
...
@@ -113,3 +115,18 @@ func (l *loader) FetchClaims(ctx context.Context) ([]types.Claim, error) {
return
claimList
,
nil
}
// FetchAbsolutePrestateHash fetches the hashed absolute prestate from the fault dispute game.
func
(
l
*
loader
)
FetchAbsolutePrestateHash
(
ctx
context
.
Context
)
([]
byte
,
error
)
{
callOpts
:=
bind
.
CallOpts
{
Context
:
ctx
,
}
absolutePrestate
,
err
:=
l
.
caller
.
ABSOLUTEPRESTATE
(
&
callOpts
)
if
err
!=
nil
{
return
nil
,
err
}
returnValue
:=
absolutePrestate
[
:
]
return
returnValue
,
nil
}
op-challenger/fault/loader_test.go
View file @
04a2b4e3
...
...
@@ -7,7 +7,9 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
...
...
@@ -15,12 +17,14 @@ var (
mockClaimDataError
=
fmt
.
Errorf
(
"claim data errored"
)
mockClaimLenError
=
fmt
.
Errorf
(
"claim len errored"
)
mockMaxGameDepthError
=
fmt
.
Errorf
(
"max game depth errored"
)
mockPrestateError
=
fmt
.
Errorf
(
"prestate errored"
)
)
type
mockC
laimFetch
er
struct
{
type
mockC
all
er
struct
{
claimDataError
bool
claimLenError
bool
maxGameDepthError
bool
prestateError
bool
maxGameDepth
uint64
currentIndex
uint64
returnClaims
[]
struct
{
...
...
@@ -32,8 +36,8 @@ type mockClaimFetcher struct {
}
}
func
newMockC
laimFetcher
()
*
mockClaimFetch
er
{
return
&
mockC
laimFetch
er
{
func
newMockC
aller
()
*
mockCall
er
{
return
&
mockC
all
er
{
returnClaims
:
[]
struct
{
ParentIndex
uint32
Countered
bool
...
...
@@ -63,7 +67,7 @@ func newMockClaimFetcher() *mockClaimFetcher {
}
}
func
(
m
*
mockC
laimFetch
er
)
ClaimData
(
opts
*
bind
.
CallOpts
,
arg0
*
big
.
Int
)
(
struct
{
func
(
m
*
mockC
all
er
)
ClaimData
(
opts
*
bind
.
CallOpts
,
arg0
*
big
.
Int
)
(
struct
{
ParentIndex
uint32
Countered
bool
Claim
[
32
]
byte
...
...
@@ -84,46 +88,73 @@ func (m *mockClaimFetcher) ClaimData(opts *bind.CallOpts, arg0 *big.Int) (struct
return
returnClaim
,
nil
}
func
(
m
*
mockC
laimFetch
er
)
ClaimDataLen
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
{
func
(
m
*
mockC
all
er
)
ClaimDataLen
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
{
if
m
.
claimLenError
{
return
big
.
NewInt
(
0
),
mockClaimLenError
}
return
big
.
NewInt
(
int64
(
len
(
m
.
returnClaims
))),
nil
}
func
(
m
*
mockC
laimFetch
er
)
MAXGAMEDEPTH
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
{
func
(
m
*
mockC
all
er
)
MAXGAMEDEPTH
(
opts
*
bind
.
CallOpts
)
(
*
big
.
Int
,
error
)
{
if
m
.
maxGameDepthError
{
return
nil
,
mockMaxGameDepthError
}
return
big
.
NewInt
(
int64
(
m
.
maxGameDepth
)),
nil
}
func
(
m
*
mockCaller
)
ABSOLUTEPRESTATE
(
opts
*
bind
.
CallOpts
)
([
32
]
byte
,
error
)
{
if
m
.
prestateError
{
return
[
32
]
byte
{},
mockPrestateError
}
return
common
.
HexToHash
(
"0xdEad"
),
nil
}
// TestLoader_FetchGameDepth tests [loader.FetchGameDepth].
func
TestLoader_FetchGameDepth
(
t
*
testing
.
T
)
{
t
.
Run
(
"Succeeds"
,
func
(
t
*
testing
.
T
)
{
mockC
laimFetcher
:=
newMockClaimFetch
er
()
mockC
laimFetch
er
.
maxGameDepth
=
10
loader
:=
NewLoader
(
mockC
laimFetch
er
)
mockC
aller
:=
newMockCall
er
()
mockC
all
er
.
maxGameDepth
=
10
loader
:=
NewLoader
(
mockC
all
er
)
depth
,
err
:=
loader
.
FetchGameDepth
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
uint64
(
10
),
depth
)
})
t
.
Run
(
"Errors"
,
func
(
t
*
testing
.
T
)
{
mockC
laimFetcher
:=
newMockClaimFetch
er
()
mockC
laimFetch
er
.
maxGameDepthError
=
true
loader
:=
NewLoader
(
mockC
laimFetch
er
)
mockC
aller
:=
newMockCall
er
()
mockC
all
er
.
maxGameDepthError
=
true
loader
:=
NewLoader
(
mockC
all
er
)
depth
,
err
:=
loader
.
FetchGameDepth
(
context
.
Background
())
require
.
ErrorIs
(
t
,
mockMaxGameDepthError
,
err
)
require
.
Equal
(
t
,
depth
,
uint64
(
0
))
})
}
// TestLoader_FetchAbsolutePrestateHash tests the [loader.FetchAbsolutePrestateHash] function.
func
TestLoader_FetchAbsolutePrestateHash
(
t
*
testing
.
T
)
{
t
.
Run
(
"Succeeds"
,
func
(
t
*
testing
.
T
)
{
mockCaller
:=
newMockCaller
()
loader
:=
NewLoader
(
mockCaller
)
prestate
,
err
:=
loader
.
FetchAbsolutePrestateHash
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
ElementsMatch
(
t
,
common
.
HexToHash
(
"0xdEad"
),
prestate
)
})
t
.
Run
(
"Errors"
,
func
(
t
*
testing
.
T
)
{
mockCaller
:=
newMockCaller
()
mockCaller
.
prestateError
=
true
loader
:=
NewLoader
(
mockCaller
)
prestate
,
err
:=
loader
.
FetchAbsolutePrestateHash
(
context
.
Background
())
require
.
Error
(
t
,
err
)
require
.
ElementsMatch
(
t
,
common
.
Hash
{},
prestate
)
})
}
// TestLoader_FetchClaims_Succeeds tests [loader.FetchClaims].
func
TestLoader_FetchClaims_Succeeds
(
t
*
testing
.
T
)
{
mockC
laimFetcher
:=
newMockClaimFetch
er
()
expectedClaims
:=
mockC
laimFetch
er
.
returnClaims
loader
:=
NewLoader
(
mockC
laimFetch
er
)
mockC
aller
:=
newMockCall
er
()
expectedClaims
:=
mockC
all
er
.
returnClaims
loader
:=
NewLoader
(
mockC
all
er
)
claims
,
err
:=
loader
.
FetchClaims
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
ElementsMatch
(
t
,
[]
types
.
Claim
{
...
...
@@ -172,9 +203,9 @@ func TestLoader_FetchClaims_Succeeds(t *testing.T) {
// TestLoader_FetchClaims_ClaimDataErrors tests [loader.FetchClaims]
// when the claim fetcher [ClaimData] function call errors.
func
TestLoader_FetchClaims_ClaimDataErrors
(
t
*
testing
.
T
)
{
mockC
laimFetcher
:=
newMockClaimFetch
er
()
mockC
laimFetch
er
.
claimDataError
=
true
loader
:=
NewLoader
(
mockC
laimFetch
er
)
mockC
aller
:=
newMockCall
er
()
mockC
all
er
.
claimDataError
=
true
loader
:=
NewLoader
(
mockC
all
er
)
claims
,
err
:=
loader
.
FetchClaims
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockClaimDataError
)
require
.
Empty
(
t
,
claims
)
...
...
@@ -183,9 +214,9 @@ func TestLoader_FetchClaims_ClaimDataErrors(t *testing.T) {
// TestLoader_FetchClaims_ClaimLenErrors tests [loader.FetchClaims]
// when the claim fetcher [ClaimDataLen] function call errors.
func
TestLoader_FetchClaims_ClaimLenErrors
(
t
*
testing
.
T
)
{
mockC
laimFetcher
:=
newMockClaimFetch
er
()
mockC
laimFetch
er
.
claimLenError
=
true
loader
:=
NewLoader
(
mockC
laimFetch
er
)
mockC
aller
:=
newMockCall
er
()
mockC
all
er
.
claimLenError
=
true
loader
:=
NewLoader
(
mockC
all
er
)
claims
,
err
:=
loader
.
FetchClaims
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockClaimLenError
)
require
.
Empty
(
t
,
claims
)
...
...
op-challenger/fault/service.go
View file @
04a2b4e3
package
fault
import
(
"bytes"
"context"
"fmt"
...
...
@@ -11,6 +12,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
)
...
...
@@ -78,6 +80,10 @@ func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*se
// newTypedService creates a new Service from a provided trace provider.
func
newTypedService
(
ctx
context
.
Context
,
logger
log
.
Logger
,
cfg
*
config
.
Config
,
loader
Loader
,
gameDepth
uint64
,
client
*
ethclient
.
Client
,
provider
types
.
TraceProvider
,
updater
types
.
OracleUpdater
,
txMgr
txmgr
.
TxManager
)
(
*
service
,
error
)
{
if
err
:=
ValidateAbsolutePrestate
(
ctx
,
provider
,
loader
);
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to validate absolute prestate: %w"
,
err
)
}
gameLogger
:=
logger
.
New
(
"game"
,
cfg
.
GameAddress
)
responder
,
err
:=
NewFaultResponder
(
gameLogger
,
txMgr
,
cfg
.
GameAddress
)
if
err
!=
nil
{
...
...
@@ -89,16 +95,31 @@ func newTypedService(ctx context.Context, logger log.Logger, cfg *config.Config,
return
nil
,
fmt
.
Errorf
(
"failed to bind the fault contract: %w"
,
err
)
}
agent
:=
NewAgent
(
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
gameLogger
)
return
&
service
{
agent
:
agent
,
agent
:
NewAgent
(
loader
,
int
(
gameDepth
),
provider
,
responder
,
updater
,
cfg
.
AgreeWithProposedOutput
,
gameLogger
)
,
agreeWithProposedOutput
:
cfg
.
AgreeWithProposedOutput
,
caller
:
caller
,
logger
:
gameLogger
,
},
nil
}
// ValidateAbsolutePrestate validates the absolute prestate of the fault game.
func
ValidateAbsolutePrestate
(
ctx
context
.
Context
,
trace
types
.
TraceProvider
,
loader
Loader
)
error
{
providerPrestate
,
err
:=
trace
.
AbsolutePreState
(
ctx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to get the trace provider's absolute prestate: %w"
,
err
)
}
providerPrestateHash
:=
crypto
.
Keccak256
(
providerPrestate
)
onchainPrestate
,
err
:=
loader
.
FetchAbsolutePrestateHash
(
ctx
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to get the onchain absolute prestate: %w"
,
err
)
}
if
!
bytes
.
Equal
(
providerPrestateHash
,
onchainPrestate
)
{
return
fmt
.
Errorf
(
"trace provider's absolute prestate does not match onchain absolute prestate"
)
}
return
nil
}
// MonitorGame monitors the fault dispute game and attempts to progress it.
func
(
s
*
service
)
MonitorGame
(
ctx
context
.
Context
)
error
{
return
MonitorGame
(
ctx
,
s
.
logger
,
s
.
agreeWithProposedOutput
,
s
.
agent
,
s
.
caller
)
...
...
op-challenger/fault/service_test.go
0 → 100644
View file @
04a2b4e3
package
fault
import
(
"context"
"fmt"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)
var
(
mockTraceProviderError
=
fmt
.
Errorf
(
"mock trace provider error"
)
mockLoaderError
=
fmt
.
Errorf
(
"mock loader error"
)
)
// TestValidateAbsolutePrestate tests that the absolute prestate is validated
// correctly by the service component.
func
TestValidateAbsolutePrestate
(
t
*
testing
.
T
)
{
t
.
Run
(
"ValidPrestates"
,
func
(
t
*
testing
.
T
)
{
prestate
:=
[]
byte
{
0x00
,
0x01
,
0x02
,
0x03
}
prestateHash
:=
crypto
.
Keccak256
(
prestate
)
mockTraceProvider
:=
newMockTraceProvider
(
false
,
prestate
)
mockLoader
:=
newMockLoader
(
false
,
prestateHash
)
err
:=
ValidateAbsolutePrestate
(
context
.
Background
(),
mockTraceProvider
,
mockLoader
)
require
.
NoError
(
t
,
err
)
})
t
.
Run
(
"TraceProviderErrors"
,
func
(
t
*
testing
.
T
)
{
prestate
:=
[]
byte
{
0x00
,
0x01
,
0x02
,
0x03
}
mockTraceProvider
:=
newMockTraceProvider
(
true
,
prestate
)
mockLoader
:=
newMockLoader
(
false
,
prestate
)
err
:=
ValidateAbsolutePrestate
(
context
.
Background
(),
mockTraceProvider
,
mockLoader
)
require
.
ErrorIs
(
t
,
err
,
mockTraceProviderError
)
})
t
.
Run
(
"LoaderErrors"
,
func
(
t
*
testing
.
T
)
{
prestate
:=
[]
byte
{
0x00
,
0x01
,
0x02
,
0x03
}
mockTraceProvider
:=
newMockTraceProvider
(
false
,
prestate
)
mockLoader
:=
newMockLoader
(
true
,
prestate
)
err
:=
ValidateAbsolutePrestate
(
context
.
Background
(),
mockTraceProvider
,
mockLoader
)
require
.
ErrorIs
(
t
,
err
,
mockLoaderError
)
})
t
.
Run
(
"PrestateMismatch"
,
func
(
t
*
testing
.
T
)
{
mockTraceProvider
:=
newMockTraceProvider
(
false
,
[]
byte
{
0x00
,
0x01
,
0x02
,
0x03
})
mockLoader
:=
newMockLoader
(
false
,
[]
byte
{
0x00
})
err
:=
ValidateAbsolutePrestate
(
context
.
Background
(),
mockTraceProvider
,
mockLoader
)
require
.
Error
(
t
,
err
)
})
}
type
mockTraceProvider
struct
{
prestateErrors
bool
prestate
[]
byte
}
func
newMockTraceProvider
(
prestateErrors
bool
,
prestate
[]
byte
)
*
mockTraceProvider
{
return
&
mockTraceProvider
{
prestateErrors
:
prestateErrors
,
prestate
:
prestate
,
}
}
func
(
m
*
mockTraceProvider
)
Get
(
ctx
context
.
Context
,
i
uint64
)
(
common
.
Hash
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockTraceProvider
)
GetOracleData
(
ctx
context
.
Context
,
i
uint64
)
(
*
types
.
PreimageOracleData
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockTraceProvider
)
GetPreimage
(
ctx
context
.
Context
,
i
uint64
)
(
preimage
[]
byte
,
proofData
[]
byte
,
err
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockTraceProvider
)
AbsolutePreState
(
ctx
context
.
Context
)
([]
byte
,
error
)
{
if
m
.
prestateErrors
{
return
nil
,
mockTraceProviderError
}
return
m
.
prestate
,
nil
}
type
mockLoader
struct
{
prestateError
bool
prestate
[]
byte
}
func
newMockLoader
(
prestateError
bool
,
prestate
[]
byte
)
*
mockLoader
{
return
&
mockLoader
{
prestateError
:
prestateError
,
prestate
:
prestate
,
}
}
func
(
m
*
mockLoader
)
FetchClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockLoader
)
FetchGameDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockLoader
)
FetchAbsolutePrestateHash
(
ctx
context
.
Context
)
([]
byte
,
error
)
{
if
m
.
prestateError
{
return
nil
,
mockLoaderError
}
return
m
.
prestate
,
nil
}
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