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
388a4174
Unverified
Commit
388a4174
authored
Nov 30, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
challenger: Add contract adapter for OutputBisectionGame.
Support creating different contract wrappers.
parent
a78776a1
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
732 additions
and
444 deletions
+732
-444
disputegame.go
op-challenger/game/fault/contracts/disputegame.go
+213
-0
disputegame_test.go
op-challenger/game/fault/contracts/disputegame_test.go
+254
-0
faultdisputegame.go
op-challenger/game/fault/contracts/faultdisputegame.go
+7
-199
faultdisputegame_test.go
op-challenger/game/fault/contracts/faultdisputegame_test.go
+14
-220
outputbisectiongame.go
op-challenger/game/fault/contracts/outputbisectiongame.go
+91
-0
outputbisectiongame_test.go
...allenger/game/fault/contracts/outputbisectiongame_test.go
+102
-0
player.go
op-challenger/game/fault/player.go
+14
-4
register.go
op-challenger/game/fault/register.go
+24
-11
responder.go
op-challenger/game/fault/responder/responder.go
+2
-2
responder_test.go
op-challenger/game/fault/responder/responder_test.go
+10
-7
output_cannon.go
op-challenger/game/fault/trace/outputs/output_cannon.go
+1
-1
No files found.
op-challenger/game/fault/contracts/disputegame.go
0 → 100644
View file @
388a4174
package
contracts
import
(
"context"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
const
(
methodGameDuration
=
"GAME_DURATION"
methodMaxGameDepth
=
"MAX_GAME_DEPTH"
methodAbsolutePrestate
=
"ABSOLUTE_PRESTATE"
methodStatus
=
"status"
methodClaimCount
=
"claimDataLen"
methodClaim
=
"claimData"
methodL1Head
=
"l1Head"
methodResolve
=
"resolve"
methodResolveClaim
=
"resolveClaim"
methodAttack
=
"attack"
methodDefend
=
"defend"
methodStep
=
"step"
methodAddLocalData
=
"addLocalData"
methodVM
=
"VM"
)
type
DisputeGameContract
struct
{
multiCaller
*
batching
.
MultiCaller
contract
*
batching
.
BoundContract
}
// contractProposal matches the structure for output root proposals used by the contracts.
// It must exactly match the contract structure. The exposed API uses Proposal to decouple the contract
// and challenger representations of the proposal data.
type
contractProposal
struct
{
Index
*
big
.
Int
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
type
Proposal
struct
{
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
func
asProposal
(
p
contractProposal
)
Proposal
{
return
Proposal
{
L2BlockNumber
:
p
.
L2BlockNumber
,
OutputRoot
:
p
.
OutputRoot
,
}
}
func
(
f
*
DisputeGameContract
)
GetGameDuration
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodGameDuration
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch game duration: %w"
,
err
)
}
return
result
.
GetUint64
(
0
),
nil
}
func
(
f
*
DisputeGameContract
)
GetMaxGameDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodMaxGameDepth
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch max game depth: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
DisputeGameContract
)
GetAbsolutePrestateHash
(
ctx
context
.
Context
)
(
common
.
Hash
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodAbsolutePrestate
))
if
err
!=
nil
{
return
common
.
Hash
{},
fmt
.
Errorf
(
"failed to fetch absolute prestate hash: %w"
,
err
)
}
return
result
.
GetHash
(
0
),
nil
}
func
(
f
*
DisputeGameContract
)
GetL1Head
(
ctx
context
.
Context
)
(
common
.
Hash
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodL1Head
))
if
err
!=
nil
{
return
common
.
Hash
{},
fmt
.
Errorf
(
"failed to fetch L1 head: %w"
,
err
)
}
return
result
.
GetHash
(
0
),
nil
}
func
(
f
*
DisputeGameContract
)
GetStatus
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodStatus
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch status: %w"
,
err
)
}
return
gameTypes
.
GameStatusFromUint8
(
result
.
GetUint8
(
0
))
}
func
(
f
*
DisputeGameContract
)
GetClaimCount
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodClaimCount
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch claim count: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
DisputeGameContract
)
GetClaim
(
ctx
context
.
Context
,
idx
uint64
)
(
types
.
Claim
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodClaim
,
new
(
big
.
Int
)
.
SetUint64
(
idx
)))
if
err
!=
nil
{
return
types
.
Claim
{},
fmt
.
Errorf
(
"failed to fetch claim %v: %w"
,
idx
,
err
)
}
return
f
.
decodeClaim
(
result
,
int
(
idx
)),
nil
}
func
(
f
*
DisputeGameContract
)
GetAllClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
{
count
,
err
:=
f
.
GetClaimCount
(
ctx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load claim count: %w"
,
err
)
}
calls
:=
make
([]
*
batching
.
ContractCall
,
count
)
for
i
:=
uint64
(
0
);
i
<
count
;
i
++
{
calls
[
i
]
=
f
.
contract
.
Call
(
methodClaim
,
new
(
big
.
Int
)
.
SetUint64
(
i
))
}
results
,
err
:=
f
.
multiCaller
.
Call
(
ctx
,
batching
.
BlockLatest
,
calls
...
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch claim data: %w"
,
err
)
}
var
claims
[]
types
.
Claim
for
idx
,
result
:=
range
results
{
claims
=
append
(
claims
,
f
.
decodeClaim
(
result
,
idx
))
}
return
claims
,
nil
}
func
(
f
*
DisputeGameContract
)
vm
(
ctx
context
.
Context
)
(
*
VMContract
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodVM
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch VM addr: %w"
,
err
)
}
vmAddr
:=
result
.
GetAddress
(
0
)
return
NewVMContract
(
vmAddr
,
f
.
multiCaller
)
}
func
(
f
*
DisputeGameContract
)
AttackTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodAttack
,
new
(
big
.
Int
)
.
SetUint64
(
parentContractIndex
),
pivot
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
DefendTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodDefend
,
new
(
big
.
Int
)
.
SetUint64
(
parentContractIndex
),
pivot
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
StepTx
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proof
[]
byte
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodStep
,
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
),
isAttack
,
stateData
,
proof
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
CallResolveClaim
(
ctx
context
.
Context
,
claimIdx
uint64
)
error
{
call
:=
f
.
resolveClaimCall
(
claimIdx
)
_
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
call
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to call resolve claim: %w"
,
err
)
}
return
nil
}
func
(
f
*
DisputeGameContract
)
ResolveClaimTx
(
claimIdx
uint64
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
resolveClaimCall
(
claimIdx
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
resolveClaimCall
(
claimIdx
uint64
)
*
batching
.
ContractCall
{
return
f
.
contract
.
Call
(
methodResolveClaim
,
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
))
}
func
(
f
*
DisputeGameContract
)
CallResolve
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
call
:=
f
.
resolveCall
()
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
call
)
if
err
!=
nil
{
return
gameTypes
.
GameStatusInProgress
,
fmt
.
Errorf
(
"failed to call resolve: %w"
,
err
)
}
return
gameTypes
.
GameStatusFromUint8
(
result
.
GetUint8
(
0
))
}
func
(
f
*
DisputeGameContract
)
ResolveTx
()
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
resolveCall
()
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
resolveCall
()
*
batching
.
ContractCall
{
return
f
.
contract
.
Call
(
methodResolve
)
}
func
(
f
*
DisputeGameContract
)
decodeClaim
(
result
*
batching
.
CallResult
,
contractIndex
int
)
types
.
Claim
{
parentIndex
:=
result
.
GetUint32
(
0
)
countered
:=
result
.
GetBool
(
1
)
claim
:=
result
.
GetHash
(
2
)
position
:=
result
.
GetBigInt
(
3
)
clock
:=
result
.
GetBigInt
(
4
)
return
types
.
Claim
{
ClaimData
:
types
.
ClaimData
{
Value
:
claim
,
Position
:
types
.
NewPositionFromGIndex
(
position
),
},
Countered
:
countered
,
Clock
:
clock
.
Uint64
(),
ContractIndex
:
contractIndex
,
ParentContractIndex
:
int
(
parentIndex
),
}
}
op-challenger/game/fault/contracts/disputegame_test.go
0 → 100644
View file @
388a4174
package
contracts
import
(
"context"
"math"
"math/big"
"testing"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
batchingTest
"github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
var
(
fdgAddr
=
common
.
HexToAddress
(
"0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB"
)
vmAddr
=
common
.
HexToAddress
(
"0x33332842371dFC380576ebb09Ae16Cb6B6c3333"
)
oracleAddr
=
common
.
HexToAddress
(
"0x44442842371dFC380576ebb09Ae16Cb6B6ca4444"
)
)
type
disputeGameSetupFunc
func
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
DisputeGameContract
)
func
runCommonDisputeGameTests
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
tests
:=
[]
struct
{
name
string
method
func
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
}{
{
"SimpleGetters"
,
runSimpleGettersTest
},
{
"GetClaim"
,
runGetClaimTest
},
{
"GetAllClaims"
,
runGetAllClaimsTest
},
{
"CallResolveClaim"
,
runCallResolveClaimTest
},
{
"ResolveClaimTx"
,
runResolveClaimTxTest
},
{
"ResolveTx"
,
runResolveTxTest
},
{
"AttackTx"
,
runAttackTxTest
},
{
"DefendTx"
,
runDefendTxTest
},
{
"StepTx"
,
runStepTxTest
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
t
.
Run
(
test
.
name
,
func
(
t
*
testing
.
T
)
{
test
.
method
(
t
,
setup
)
})
}
}
func
runSimpleGettersTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
tests
:=
[]
struct
{
method
string
args
[]
interface
{}
result
interface
{}
expected
interface
{}
// Defaults to expecting the same as result
call
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
}{
{
method
:
methodStatus
,
result
:
types
.
GameStatusChallengerWon
,
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetStatus
(
context
.
Background
())
},
},
{
method
:
methodGameDuration
,
result
:
uint64
(
5566
),
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetGameDuration
(
context
.
Background
())
},
},
{
method
:
methodMaxGameDepth
,
result
:
big
.
NewInt
(
128
),
expected
:
uint64
(
128
),
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetMaxGameDepth
(
context
.
Background
())
},
},
{
method
:
methodAbsolutePrestate
,
result
:
common
.
Hash
{
0xab
},
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetAbsolutePrestateHash
(
context
.
Background
())
},
},
{
method
:
methodClaimCount
,
result
:
big
.
NewInt
(
9876
),
expected
:
uint64
(
9876
),
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetClaimCount
(
context
.
Background
())
},
},
{
method
:
methodL1Head
,
result
:
common
.
Hash
{
0xdd
,
0xbb
},
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetL1Head
(
context
.
Background
())
},
},
{
method
:
methodResolve
,
result
:
types
.
GameStatusInProgress
,
call
:
func
(
game
*
DisputeGameContract
)
(
any
,
error
)
{
return
game
.
CallResolve
(
context
.
Background
())
},
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
t
.
Run
(
test
.
method
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
test
.
method
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
test
.
result
})
status
,
err
:=
test
.
call
(
game
)
require
.
NoError
(
t
,
err
)
expected
:=
test
.
expected
if
expected
==
nil
{
expected
=
test
.
result
}
require
.
Equal
(
t
,
expected
,
status
)
})
}
}
func
runGetClaimTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
idx
:=
big
.
NewInt
(
2
)
parentIndex
:=
uint32
(
1
)
countered
:=
true
value
:=
common
.
Hash
{
0xab
}
position
:=
big
.
NewInt
(
2
)
clock
:=
big
.
NewInt
(
1234
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
idx
},
[]
interface
{}{
parentIndex
,
countered
,
value
,
position
,
clock
})
status
,
err
:=
game
.
GetClaim
(
context
.
Background
(),
idx
.
Uint64
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
value
,
Position
:
faultTypes
.
NewPositionFromGIndex
(
position
),
},
Countered
:
true
,
Clock
:
1234
,
ContractIndex
:
int
(
idx
.
Uint64
()),
ParentContractIndex
:
1
,
},
status
)
}
func
runGetAllClaimsTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
claim0
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xaa
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
1
)),
},
Countered
:
true
,
Clock
:
1234
,
ContractIndex
:
0
,
ParentContractIndex
:
math
.
MaxUint32
,
}
claim1
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xab
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
2
)),
},
Countered
:
true
,
Clock
:
4455
,
ContractIndex
:
1
,
ParentContractIndex
:
0
,
}
claim2
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xbb
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
6
)),
},
Countered
:
false
,
Clock
:
7777
,
ContractIndex
:
2
,
ParentContractIndex
:
1
,
}
expectedClaims
:=
[]
faultTypes
.
Claim
{
claim0
,
claim1
,
claim2
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaimCount
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
big
.
NewInt
(
int64
(
len
(
expectedClaims
)))})
for
_
,
claim
:=
range
expectedClaims
{
expectGetClaim
(
stubRpc
,
claim
)
}
claims
,
err
:=
game
.
GetAllClaims
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
expectedClaims
,
claims
)
}
func
runCallResolveClaimTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolveClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
123
)},
nil
)
err
:=
game
.
CallResolveClaim
(
context
.
Background
(),
123
)
require
.
NoError
(
t
,
err
)
}
func
runResolveClaimTxTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolveClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
123
)},
nil
)
tx
,
err
:=
game
.
ResolveClaimTx
(
123
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
runResolveTxTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolve
,
batching
.
BlockLatest
,
nil
,
nil
)
tx
,
err
:=
game
.
ResolveTx
()
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
runAttackTxTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
value
:=
common
.
Hash
{
0xaa
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodAttack
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
value
},
nil
)
tx
,
err
:=
game
.
AttackTx
(
111
,
value
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
runDefendTxTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
value
:=
common
.
Hash
{
0xaa
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodDefend
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
value
},
nil
)
tx
,
err
:=
game
.
DefendTx
(
111
,
value
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
runStepTxTest
(
t
*
testing
.
T
,
setup
disputeGameSetupFunc
)
{
stubRpc
,
game
:=
setup
(
t
)
stateData
:=
[]
byte
{
1
,
2
,
3
}
proofData
:=
[]
byte
{
4
,
5
,
6
,
7
,
8
,
9
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodStep
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
true
,
stateData
,
proofData
},
nil
)
tx
,
err
:=
game
.
StepTx
(
111
,
true
,
stateData
,
proofData
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
expectGetClaim
(
stubRpc
*
batchingTest
.
AbiBasedRpc
,
claim
faultTypes
.
Claim
)
{
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
int64
(
claim
.
ContractIndex
))},
[]
interface
{}{
uint32
(
claim
.
ParentContractIndex
),
claim
.
Countered
,
claim
.
Value
,
claim
.
Position
.
ToGIndex
(),
big
.
NewInt
(
int64
(
claim
.
Clock
)),
})
}
op-challenger/game/fault/contracts/faultdisputegame.go
View file @
388a4174
...
@@ -7,54 +7,17 @@ import (
...
@@ -7,54 +7,17 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
)
)
const
(
const
(
methodGameDuration
=
"GAME_DURATION"
methodProposals
=
"proposals"
methodMaxGameDepth
=
"MAX_GAME_DEPTH"
methodAbsolutePrestate
=
"ABSOLUTE_PRESTATE"
methodStatus
=
"status"
methodClaimCount
=
"claimDataLen"
methodClaim
=
"claimData"
methodL1Head
=
"l1Head"
methodProposals
=
"proposals"
methodResolve
=
"resolve"
methodResolveClaim
=
"resolveClaim"
methodAttack
=
"attack"
methodDefend
=
"defend"
methodStep
=
"step"
methodAddLocalData
=
"addLocalData"
methodVM
=
"VM"
)
)
type
FaultDisputeGameContract
struct
{
type
FaultDisputeGameContract
struct
{
multiCaller
*
batching
.
MultiCaller
DisputeGameContract
contract
*
batching
.
BoundContract
}
// contractProposal matches the structure for output root proposals used by the contracts.
// It must exactly match the contract structure. The exposed API uses Proposal to decouple the contract
// and challenger representations of the proposal data.
type
contractProposal
struct
{
Index
*
big
.
Int
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
type
Proposal
struct
{
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
func
asProposal
(
p
contractProposal
)
Proposal
{
return
Proposal
{
L2BlockNumber
:
p
.
L2BlockNumber
,
OutputRoot
:
p
.
OutputRoot
,
}
}
}
func
NewFaultDisputeGameContract
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
*
FaultDisputeGameContract
,
error
)
{
func
NewFaultDisputeGameContract
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
*
FaultDisputeGameContract
,
error
)
{
...
@@ -64,43 +27,13 @@ func NewFaultDisputeGameContract(addr common.Address, caller *batching.MultiCall
...
@@ -64,43 +27,13 @@ func NewFaultDisputeGameContract(addr common.Address, caller *batching.MultiCall
}
}
return
&
FaultDisputeGameContract
{
return
&
FaultDisputeGameContract
{
multiCaller
:
caller
,
DisputeGameContract
:
DisputeGameContract
{
contract
:
batching
.
NewBoundContract
(
fdgAbi
,
addr
),
multiCaller
:
caller
,
contract
:
batching
.
NewBoundContract
(
fdgAbi
,
addr
),
},
},
nil
},
nil
}
}
func
(
f
*
FaultDisputeGameContract
)
GetGameDuration
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodGameDuration
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch game duration: %w"
,
err
)
}
return
result
.
GetUint64
(
0
),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetMaxGameDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodMaxGameDepth
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch max game depth: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetAbsolutePrestateHash
(
ctx
context
.
Context
)
(
common
.
Hash
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodAbsolutePrestate
))
if
err
!=
nil
{
return
common
.
Hash
{},
fmt
.
Errorf
(
"failed to fetch absolute prestate hash: %w"
,
err
)
}
return
result
.
GetHash
(
0
),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetL1Head
(
ctx
context
.
Context
)
(
common
.
Hash
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodL1Head
))
if
err
!=
nil
{
return
common
.
Hash
{},
fmt
.
Errorf
(
"failed to fetch L1 head: %w"
,
err
)
}
return
result
.
GetHash
(
0
),
nil
}
// GetProposals returns the agreed and disputed proposals
// GetProposals returns the agreed and disputed proposals
func
(
f
*
FaultDisputeGameContract
)
GetProposals
(
ctx
context
.
Context
)
(
Proposal
,
Proposal
,
error
)
{
func
(
f
*
FaultDisputeGameContract
)
GetProposals
(
ctx
context
.
Context
)
(
Proposal
,
Proposal
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodProposals
))
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodProposals
))
...
@@ -114,114 +47,7 @@ func (f *FaultDisputeGameContract) GetProposals(ctx context.Context) (Proposal,
...
@@ -114,114 +47,7 @@ func (f *FaultDisputeGameContract) GetProposals(ctx context.Context) (Proposal,
return
asProposal
(
agreed
),
asProposal
(
disputed
),
nil
return
asProposal
(
agreed
),
asProposal
(
disputed
),
nil
}
}
func
(
f
*
FaultDisputeGameContract
)
GetStatus
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
func
(
f
*
FaultDisputeGameContract
)
UpdateOracleTx
(
ctx
context
.
Context
,
claimIdx
uint64
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodStatus
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch status: %w"
,
err
)
}
return
gameTypes
.
GameStatusFromUint8
(
result
.
GetUint8
(
0
))
}
func
(
f
*
FaultDisputeGameContract
)
GetClaimCount
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodClaimCount
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch claim count: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetClaim
(
ctx
context
.
Context
,
idx
uint64
)
(
types
.
Claim
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodClaim
,
new
(
big
.
Int
)
.
SetUint64
(
idx
)))
if
err
!=
nil
{
return
types
.
Claim
{},
fmt
.
Errorf
(
"failed to fetch claim %v: %w"
,
idx
,
err
)
}
return
f
.
decodeClaim
(
result
,
int
(
idx
)),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetAllClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
{
count
,
err
:=
f
.
GetClaimCount
(
ctx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load claim count: %w"
,
err
)
}
calls
:=
make
([]
*
batching
.
ContractCall
,
count
)
for
i
:=
uint64
(
0
);
i
<
count
;
i
++
{
calls
[
i
]
=
f
.
contract
.
Call
(
methodClaim
,
new
(
big
.
Int
)
.
SetUint64
(
i
))
}
results
,
err
:=
f
.
multiCaller
.
Call
(
ctx
,
batching
.
BlockLatest
,
calls
...
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch claim data: %w"
,
err
)
}
var
claims
[]
types
.
Claim
for
idx
,
result
:=
range
results
{
claims
=
append
(
claims
,
f
.
decodeClaim
(
result
,
idx
))
}
return
claims
,
nil
}
func
(
f
*
FaultDisputeGameContract
)
vm
(
ctx
context
.
Context
)
(
*
VMContract
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
f
.
contract
.
Call
(
methodVM
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch VM addr: %w"
,
err
)
}
vmAddr
:=
result
.
GetAddress
(
0
)
return
NewVMContract
(
vmAddr
,
f
.
multiCaller
)
}
func
(
f
*
FaultDisputeGameContract
)
AttackTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodAttack
,
new
(
big
.
Int
)
.
SetUint64
(
parentContractIndex
),
pivot
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
FaultDisputeGameContract
)
DefendTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodDefend
,
new
(
big
.
Int
)
.
SetUint64
(
parentContractIndex
),
pivot
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
FaultDisputeGameContract
)
StepTx
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proof
[]
byte
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodStep
,
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
),
isAttack
,
stateData
,
proof
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
FaultDisputeGameContract
)
CallResolveClaim
(
ctx
context
.
Context
,
claimIdx
uint64
)
error
{
call
:=
f
.
resolveClaimCall
(
claimIdx
)
_
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
call
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to call resolve claim: %w"
,
err
)
}
return
nil
}
func
(
f
*
FaultDisputeGameContract
)
ResolveClaimTx
(
claimIdx
uint64
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
resolveClaimCall
(
claimIdx
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
FaultDisputeGameContract
)
resolveClaimCall
(
claimIdx
uint64
)
*
batching
.
ContractCall
{
return
f
.
contract
.
Call
(
methodResolveClaim
,
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
))
}
func
(
f
*
FaultDisputeGameContract
)
CallResolve
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
call
:=
f
.
resolveCall
()
result
,
err
:=
f
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
call
)
if
err
!=
nil
{
return
gameTypes
.
GameStatusInProgress
,
fmt
.
Errorf
(
"failed to call resolve: %w"
,
err
)
}
return
gameTypes
.
GameStatusFromUint8
(
result
.
GetUint8
(
0
))
}
func
(
f
*
FaultDisputeGameContract
)
ResolveTx
()
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
resolveCall
()
return
call
.
ToTxCandidate
()
}
func
(
f
*
FaultDisputeGameContract
)
resolveCall
()
*
batching
.
ContractCall
{
return
f
.
contract
.
Call
(
methodResolve
)
}
func
(
f
*
FaultDisputeGameContract
)
UpdateOracleTx
(
ctx
context
.
Context
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
if
data
.
IsLocal
{
if
data
.
IsLocal
{
return
f
.
addLocalDataTx
(
data
)
return
f
.
addLocalDataTx
(
data
)
}
}
...
@@ -249,21 +75,3 @@ func (f *FaultDisputeGameContract) addGlobalDataTx(ctx context.Context, data *ty
...
@@ -249,21 +75,3 @@ func (f *FaultDisputeGameContract) addGlobalDataTx(ctx context.Context, data *ty
}
}
return
oracle
.
AddGlobalDataTx
(
data
)
return
oracle
.
AddGlobalDataTx
(
data
)
}
}
func
(
f
*
FaultDisputeGameContract
)
decodeClaim
(
result
*
batching
.
CallResult
,
contractIndex
int
)
types
.
Claim
{
parentIndex
:=
result
.
GetUint32
(
0
)
countered
:=
result
.
GetBool
(
1
)
claim
:=
result
.
GetHash
(
2
)
position
:=
result
.
GetBigInt
(
3
)
clock
:=
result
.
GetBigInt
(
4
)
return
types
.
Claim
{
ClaimData
:
types
.
ClaimData
{
Value
:
claim
,
Position
:
types
.
NewPositionFromGIndex
(
position
),
},
Countered
:
countered
,
Clock
:
clock
.
Uint64
(),
ContractIndex
:
contractIndex
,
ParentContractIndex
:
int
(
parentIndex
),
}
}
op-challenger/game/fault/contracts/faultdisputegame_test.go
View file @
388a4174
...
@@ -2,103 +2,26 @@ package contracts
...
@@ -2,103 +2,26 @@ package contracts
import
(
import
(
"context"
"context"
"math"
"math/big"
"math/big"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
batchingTest
"github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
batchingTest
"github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
)
)
var
(
func
TestFaultDisputeGameContract_CommonTests
(
t
*
testing
.
T
)
{
fdgAddr
=
common
.
HexToAddress
(
"0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB"
)
runCommonDisputeGameTests
(
t
,
func
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
DisputeGameContract
)
{
vmAddr
=
common
.
HexToAddress
(
"0x33332842371dFC380576ebb09Ae16Cb6B6c3333"
)
stubRpc
,
contract
:=
setupFaultDisputeGameTest
(
t
)
oracleAddr
=
common
.
HexToAddress
(
"0x44442842371dFC380576ebb09Ae16Cb6B6ca4444"
)
return
stubRpc
,
&
contract
.
DisputeGameContract
)
})
func
TestSimpleGetters
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
method
string
args
[]
interface
{}
result
interface
{}
expected
interface
{}
// Defaults to expecting the same as result
call
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
}{
{
method
:
methodStatus
,
result
:
types
.
GameStatusChallengerWon
,
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetStatus
(
context
.
Background
())
},
},
{
method
:
methodGameDuration
,
result
:
uint64
(
5566
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetGameDuration
(
context
.
Background
())
},
},
{
method
:
methodMaxGameDepth
,
result
:
big
.
NewInt
(
128
),
expected
:
uint64
(
128
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetMaxGameDepth
(
context
.
Background
())
},
},
{
method
:
methodAbsolutePrestate
,
result
:
common
.
Hash
{
0xab
},
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetAbsolutePrestateHash
(
context
.
Background
())
},
},
{
method
:
methodClaimCount
,
result
:
big
.
NewInt
(
9876
),
expected
:
uint64
(
9876
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetClaimCount
(
context
.
Background
())
},
},
{
method
:
methodL1Head
,
result
:
common
.
Hash
{
0xdd
,
0xbb
},
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetL1Head
(
context
.
Background
())
},
},
{
method
:
methodResolve
,
result
:
types
.
GameStatusInProgress
,
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
CallResolve
(
context
.
Background
())
},
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
t
.
Run
(
test
.
method
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
test
.
method
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
test
.
result
})
status
,
err
:=
test
.
call
(
game
)
require
.
NoError
(
t
,
err
)
expected
:=
test
.
expected
if
expected
==
nil
{
expected
=
test
.
result
}
require
.
Equal
(
t
,
expected
,
status
)
})
}
}
}
func
TestGetProposals
(
t
*
testing
.
T
)
{
func
TestGetProposals
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
,
game
:=
setup
FaultDisputeGameTest
(
t
)
agreedIndex
:=
big
.
NewInt
(
5
)
agreedIndex
:=
big
.
NewInt
(
5
)
agreedBlockNum
:=
big
.
NewInt
(
6
)
agreedBlockNum
:=
big
.
NewInt
(
6
)
agreedRoot
:=
common
.
Hash
{
0xaa
}
agreedRoot
:=
common
.
Hash
{
0xaa
}
...
@@ -132,125 +55,9 @@ func TestGetProposals(t *testing.T) {
...
@@ -132,125 +55,9 @@ func TestGetProposals(t *testing.T) {
require
.
Equal
(
t
,
expectedDisputed
,
actualDisputed
)
require
.
Equal
(
t
,
expectedDisputed
,
actualDisputed
)
}
}
func
TestGetClaim
(
t
*
testing
.
T
)
{
func
TestFaultDisputeGame_UpdateOracleTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
idx
:=
big
.
NewInt
(
2
)
parentIndex
:=
uint32
(
1
)
countered
:=
true
value
:=
common
.
Hash
{
0xab
}
position
:=
big
.
NewInt
(
2
)
clock
:=
big
.
NewInt
(
1234
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
idx
},
[]
interface
{}{
parentIndex
,
countered
,
value
,
position
,
clock
})
status
,
err
:=
game
.
GetClaim
(
context
.
Background
(),
idx
.
Uint64
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
value
,
Position
:
faultTypes
.
NewPositionFromGIndex
(
position
),
},
Countered
:
true
,
Clock
:
1234
,
ContractIndex
:
int
(
idx
.
Uint64
()),
ParentContractIndex
:
1
,
},
status
)
}
func
TestGetAllClaims
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
claim0
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xaa
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
1
)),
},
Countered
:
true
,
Clock
:
1234
,
ContractIndex
:
0
,
ParentContractIndex
:
math
.
MaxUint32
,
}
claim1
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xab
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
2
)),
},
Countered
:
true
,
Clock
:
4455
,
ContractIndex
:
1
,
ParentContractIndex
:
0
,
}
claim2
:=
faultTypes
.
Claim
{
ClaimData
:
faultTypes
.
ClaimData
{
Value
:
common
.
Hash
{
0xbb
},
Position
:
faultTypes
.
NewPositionFromGIndex
(
big
.
NewInt
(
6
)),
},
Countered
:
false
,
Clock
:
7777
,
ContractIndex
:
2
,
ParentContractIndex
:
1
,
}
expectedClaims
:=
[]
faultTypes
.
Claim
{
claim0
,
claim1
,
claim2
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaimCount
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
big
.
NewInt
(
int64
(
len
(
expectedClaims
)))})
for
_
,
claim
:=
range
expectedClaims
{
expectGetClaim
(
stubRpc
,
claim
)
}
claims
,
err
:=
game
.
GetAllClaims
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
expectedClaims
,
claims
)
}
func
TestCallResolveClaim
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolveClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
123
)},
nil
)
err
:=
game
.
CallResolveClaim
(
context
.
Background
(),
123
)
require
.
NoError
(
t
,
err
)
}
func
TestResolveClaimTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolveClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
123
)},
nil
)
tx
,
err
:=
game
.
ResolveClaimTx
(
123
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
TestResolveTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolve
,
batching
.
BlockLatest
,
nil
,
nil
)
tx
,
err
:=
game
.
ResolveTx
()
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
TestAttackTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
value
:=
common
.
Hash
{
0xaa
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodAttack
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
value
},
nil
)
tx
,
err
:=
game
.
AttackTx
(
111
,
value
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
TestDefendTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
value
:=
common
.
Hash
{
0xaa
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodDefend
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
value
},
nil
)
tx
,
err
:=
game
.
DefendTx
(
111
,
value
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
TestStepTx
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stateData
:=
[]
byte
{
1
,
2
,
3
}
proofData
:=
[]
byte
{
4
,
5
,
6
,
7
,
8
,
9
}
stubRpc
.
SetResponse
(
fdgAddr
,
methodStep
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
111
),
true
,
stateData
,
proofData
},
nil
)
tx
,
err
:=
game
.
StepTx
(
111
,
true
,
stateData
,
proofData
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
}
func
TestUpdateOracleTx
(
t
*
testing
.
T
)
{
t
.
Run
(
"Local"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"Local"
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
,
game
:=
setup
FaultDisputeGameTest
(
t
)
data
:=
&
faultTypes
.
PreimageOracleData
{
data
:=
&
faultTypes
.
PreimageOracleData
{
IsLocal
:
true
,
IsLocal
:
true
,
LocalContext
:
common
.
Hash
{
0x02
},
LocalContext
:
common
.
Hash
{
0x02
},
...
@@ -258,52 +65,39 @@ func TestUpdateOracleTx(t *testing.T) {
...
@@ -258,52 +65,39 @@ func TestUpdateOracleTx(t *testing.T) {
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
},
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
},
OracleOffset
:
16
,
OracleOffset
:
16
,
}
}
claimIdx
:=
uint64
(
6
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodAddLocalData
,
batching
.
BlockLatest
,
[]
interface
{}{
stubRpc
.
SetResponse
(
fdgAddr
,
methodAddLocalData
,
batching
.
BlockLatest
,
[]
interface
{}{
data
.
GetIdent
(),
data
.
GetIdent
(),
data
.
LocalContext
,
data
.
LocalContext
,
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
},
nil
)
},
nil
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
data
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
claimIdx
,
data
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
stubRpc
.
VerifyTxCandidate
(
tx
)
})
})
t
.
Run
(
"Global"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"Global"
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
,
game
:=
setup
FaultDisputeGameTest
(
t
)
data
:=
&
faultTypes
.
PreimageOracleData
{
data
:=
&
faultTypes
.
PreimageOracleData
{
IsLocal
:
false
,
IsLocal
:
false
,
OracleKey
:
common
.
Hash
{
0xbc
}
.
Bytes
(),
OracleKey
:
common
.
Hash
{
0xbc
}
.
Bytes
(),
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
9
,
10
,
11
,
12
,
13
,
14
,
15
},
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
9
,
10
,
11
,
12
,
13
,
14
,
15
},
OracleOffset
:
16
,
OracleOffset
:
16
,
}
}
claimIdx
:=
uint64
(
6
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodVM
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
vmAddr
})
stubRpc
.
SetResponse
(
fdgAddr
,
methodVM
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
vmAddr
})
stubRpc
.
SetResponse
(
vmAddr
,
methodOracle
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
oracleAddr
})
stubRpc
.
SetResponse
(
vmAddr
,
methodOracle
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
oracleAddr
})
stubRpc
.
SetResponse
(
oracleAddr
,
methodLoadKeccak256PreimagePart
,
batching
.
BlockLatest
,
[]
interface
{}{
stubRpc
.
SetResponse
(
oracleAddr
,
methodLoadKeccak256PreimagePart
,
batching
.
BlockLatest
,
[]
interface
{}{
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
data
.
GetPreimageWithoutSize
(),
data
.
GetPreimageWithoutSize
(),
},
nil
)
},
nil
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
data
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
claimIdx
,
data
)
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
stubRpc
.
VerifyTxCandidate
(
tx
)
})
})
}
}
func
expectGetClaim
(
stubRpc
*
batchingTest
.
AbiBasedRpc
,
claim
faultTypes
.
Claim
)
{
func
setupFaultDisputeGameTest
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
FaultDisputeGameContract
)
{
stubRpc
.
SetResponse
(
fdgAddr
,
methodClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
int64
(
claim
.
ContractIndex
))},
[]
interface
{}{
uint32
(
claim
.
ParentContractIndex
),
claim
.
Countered
,
claim
.
Value
,
claim
.
Position
.
ToGIndex
(),
big
.
NewInt
(
int64
(
claim
.
Clock
)),
})
}
func
setup
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
FaultDisputeGameContract
)
{
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
...
...
op-challenger/game/fault/contracts/outputbisectiongame.go
0 → 100644
View file @
388a4174
package
contracts
import
(
"context"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
var
(
methodGenesisBlockNumber
=
"GENESIS_BLOCK_NUMBER"
methodSplitDepth
=
"SPLIT_DEPTH"
methodL2BlockNumber
=
"l2BlockNumber"
)
type
OutputBisectionGameContract
struct
{
DisputeGameContract
}
func
NewOutputBisectionGameContract
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
*
OutputBisectionGameContract
,
error
)
{
contractAbi
,
err
:=
bindings
.
OutputBisectionGameMetaData
.
GetAbi
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load fault dispute game ABI: %w"
,
err
)
}
return
&
OutputBisectionGameContract
{
DisputeGameContract
:
DisputeGameContract
{
multiCaller
:
caller
,
contract
:
batching
.
NewBoundContract
(
contractAbi
,
addr
),
},
},
nil
}
func
(
c
*
OutputBisectionGameContract
)
GetBlockRange
(
ctx
context
.
Context
)
(
prestateBlock
uint64
,
poststateBlock
uint64
,
retErr
error
)
{
results
,
err
:=
c
.
multiCaller
.
Call
(
ctx
,
batching
.
BlockLatest
,
c
.
contract
.
Call
(
methodGenesisBlockNumber
),
c
.
contract
.
Call
(
methodL2BlockNumber
))
if
err
!=
nil
{
retErr
=
fmt
.
Errorf
(
"failed to retrieve game block range: %w"
,
err
)
return
}
if
len
(
results
)
!=
2
{
retErr
=
fmt
.
Errorf
(
"expected 2 results but got %v"
,
len
(
results
))
return
}
prestateBlock
=
results
[
0
]
.
GetBigInt
(
0
)
.
Uint64
()
poststateBlock
=
results
[
1
]
.
GetBigInt
(
0
)
.
Uint64
()
return
}
func
(
c
*
OutputBisectionGameContract
)
GetSplitDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
splitDepth
,
err
:=
c
.
multiCaller
.
SingleCall
(
ctx
,
batching
.
BlockLatest
,
c
.
contract
.
Call
(
methodSplitDepth
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to retrieve split depth: %w"
,
err
)
}
return
splitDepth
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
OutputBisectionGameContract
)
UpdateOracleTx
(
ctx
context
.
Context
,
claimIdx
uint64
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
if
data
.
IsLocal
{
return
f
.
addLocalDataTx
(
claimIdx
,
data
)
}
return
f
.
addGlobalDataTx
(
ctx
,
data
)
}
func
(
f
*
OutputBisectionGameContract
)
addLocalDataTx
(
claimIdx
uint64
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
call
:=
f
.
contract
.
Call
(
methodAddLocalData
,
data
.
GetIdent
(),
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
),
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
)
return
call
.
ToTxCandidate
()
}
func
(
f
*
DisputeGameContract
)
addGlobalDataTx
(
ctx
context
.
Context
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
vm
,
err
:=
f
.
vm
(
ctx
)
if
err
!=
nil
{
return
txmgr
.
TxCandidate
{},
err
}
oracle
,
err
:=
vm
.
Oracle
(
ctx
)
if
err
!=
nil
{
return
txmgr
.
TxCandidate
{},
err
}
return
oracle
.
AddGlobalDataTx
(
data
)
}
op-challenger/game/fault/contracts/outputbisectiongame_test.go
0 → 100644
View file @
388a4174
package
contracts
import
(
"context"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
faultTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
batchingTest
"github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func
TestOutputBisectionGameContract_CommonTests
(
t
*
testing
.
T
)
{
runCommonDisputeGameTests
(
t
,
func
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
DisputeGameContract
)
{
stubRpc
,
contract
:=
setupOutputBisectionGameTest
(
t
)
return
stubRpc
,
&
contract
.
DisputeGameContract
})
}
func
TestGetBlockRange
(
t
*
testing
.
T
)
{
stubRpc
,
contract
:=
setupOutputBisectionGameTest
(
t
)
expectedStart
:=
uint64
(
65
)
expectedEnd
:=
uint64
(
102
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodGenesisBlockNumber
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
new
(
big
.
Int
)
.
SetUint64
(
expectedStart
)})
stubRpc
.
SetResponse
(
fdgAddr
,
methodL2BlockNumber
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
new
(
big
.
Int
)
.
SetUint64
(
expectedEnd
)})
start
,
end
,
err
:=
contract
.
GetBlockRange
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
expectedStart
,
start
)
require
.
Equal
(
t
,
expectedEnd
,
end
)
}
func
TestGetSplitDepth
(
t
*
testing
.
T
)
{
stubRpc
,
contract
:=
setupOutputBisectionGameTest
(
t
)
expectedSplitDepth
:=
uint64
(
15
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodSplitDepth
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
new
(
big
.
Int
)
.
SetUint64
(
expectedSplitDepth
)})
splitDepth
,
err
:=
contract
.
GetSplitDepth
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
expectedSplitDepth
,
splitDepth
)
}
func
TestOutputBisectionGame_UpdateOracleTx
(
t
*
testing
.
T
)
{
t
.
Run
(
"Local"
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setupOutputBisectionGameTest
(
t
)
data
:=
&
faultTypes
.
PreimageOracleData
{
IsLocal
:
true
,
LocalContext
:
common
.
Hash
{
0x02
},
OracleKey
:
common
.
Hash
{
0xbc
}
.
Bytes
(),
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
},
OracleOffset
:
16
,
}
claimIdx
:=
uint64
(
6
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodAddLocalData
,
batching
.
BlockLatest
,
[]
interface
{}{
data
.
GetIdent
(),
new
(
big
.
Int
)
.
SetUint64
(
claimIdx
),
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
},
nil
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
claimIdx
,
data
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
})
t
.
Run
(
"Global"
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setupOutputBisectionGameTest
(
t
)
data
:=
&
faultTypes
.
PreimageOracleData
{
IsLocal
:
false
,
OracleKey
:
common
.
Hash
{
0xbc
}
.
Bytes
(),
OracleData
:
[]
byte
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
9
,
10
,
11
,
12
,
13
,
14
,
15
},
OracleOffset
:
16
,
}
claimIdx
:=
uint64
(
6
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodVM
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
vmAddr
})
stubRpc
.
SetResponse
(
vmAddr
,
methodOracle
,
batching
.
BlockLatest
,
nil
,
[]
interface
{}{
oracleAddr
})
stubRpc
.
SetResponse
(
oracleAddr
,
methodLoadKeccak256PreimagePart
,
batching
.
BlockLatest
,
[]
interface
{}{
new
(
big
.
Int
)
.
SetUint64
(
uint64
(
data
.
OracleOffset
)),
data
.
GetPreimageWithoutSize
(),
},
nil
)
tx
,
err
:=
game
.
UpdateOracleTx
(
context
.
Background
(),
claimIdx
,
data
)
require
.
NoError
(
t
,
err
)
stubRpc
.
VerifyTxCandidate
(
tx
)
})
}
func
setupOutputBisectionGameTest
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
OutputBisectionGameContract
)
{
fdgAbi
,
err
:=
bindings
.
OutputBisectionGameMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
vmAbi
,
err
:=
bindings
.
MIPSMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
oracleAbi
,
err
:=
bindings
.
PreimageOracleMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
stubRpc
:=
batchingTest
.
NewAbiBasedRpc
(
t
,
fdgAddr
,
fdgAbi
)
stubRpc
.
AddContract
(
vmAddr
,
vmAbi
)
stubRpc
.
AddContract
(
oracleAddr
,
oracleAbi
)
caller
:=
batching
.
NewMultiCaller
(
stubRpc
,
batching
.
DefaultBatchSize
)
game
,
err
:=
NewOutputBisectionGameContract
(
fdgAddr
,
caller
)
require
.
NoError
(
t
,
err
)
return
stubRpc
,
game
}
op-challenger/game/fault/player.go
View file @
388a4174
...
@@ -5,7 +5,6 @@ import (
...
@@ -5,7 +5,6 @@ import (
"context"
"context"
"fmt"
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/responder"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
gameTypes
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
...
@@ -26,7 +25,7 @@ type GameInfo interface {
...
@@ -26,7 +25,7 @@ type GameInfo interface {
// gameValidator checks that the specific game instance is compatible with the configuration.
// gameValidator checks that the specific game instance is compatible with the configuration.
// Typically, this is done by verifying the absolute prestate of the game matches the local absolute prestate.
// Typically, this is done by verifying the absolute prestate of the game matches the local absolute prestate.
type
gameValidator
func
(
ctx
context
.
Context
,
gameContract
*
contracts
.
FaultDispute
GameContract
)
error
type
gameValidator
func
(
ctx
context
.
Context
,
gameContract
GameContract
)
error
type
GamePlayer
struct
{
type
GamePlayer
struct
{
act
actor
act
actor
...
@@ -35,7 +34,17 @@ type GamePlayer struct {
...
@@ -35,7 +34,17 @@ type GamePlayer struct {
status
gameTypes
.
GameStatus
status
gameTypes
.
GameStatus
}
}
type
resourceCreator
func
(
addr
common
.
Address
,
contract
*
contracts
.
FaultDisputeGameContract
,
gameDepth
uint64
,
dir
string
)
(
types
.
TraceAccessor
,
gameValidator
,
error
)
type
GameContract
interface
{
responder
.
GameContract
GameInfo
ClaimLoader
GetStatus
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
GetMaxGameDepth
(
ctx
context
.
Context
)
(
uint64
,
error
)
}
type
contractCreator
func
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
GameContract
,
error
)
type
resourceCreator
func
(
addr
common
.
Address
,
contract
GameContract
,
gameDepth
uint64
,
dir
string
)
(
types
.
TraceAccessor
,
gameValidator
,
error
)
func
NewGamePlayer
(
func
NewGamePlayer
(
ctx
context
.
Context
,
ctx
context
.
Context
,
...
@@ -45,11 +54,12 @@ func NewGamePlayer(
...
@@ -45,11 +54,12 @@ func NewGamePlayer(
addr
common
.
Address
,
addr
common
.
Address
,
txMgr
txmgr
.
TxManager
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
,
client
*
ethclient
.
Client
,
contractCreator
contractCreator
,
creator
resourceCreator
,
creator
resourceCreator
,
)
(
*
GamePlayer
,
error
)
{
)
(
*
GamePlayer
,
error
)
{
logger
=
logger
.
New
(
"game"
,
addr
)
logger
=
logger
.
New
(
"game"
,
addr
)
loader
,
err
:=
contract
s
.
NewFaultDisputeGameContract
(
addr
,
batching
.
NewMultiCaller
(
client
.
Client
(),
batching
.
DefaultBatchSize
))
loader
,
err
:=
contract
Creator
(
addr
,
batching
.
NewMultiCaller
(
client
.
Client
(),
batching
.
DefaultBatchSize
))
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create fault dispute game contract wrapper: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"failed to create fault dispute game contract wrapper: %w"
,
err
)
}
}
...
...
op-challenger/game/fault/register.go
View file @
388a4174
...
@@ -14,6 +14,7 @@ import (
...
@@ -14,6 +14,7 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient"
...
@@ -72,8 +73,13 @@ func registerOutputCannon(
...
@@ -72,8 +73,13 @@ func registerOutputCannon(
txMgr
txmgr
.
TxManager
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
,
client
*
ethclient
.
Client
,
l2Client
cannon
.
L2HeaderSource
)
{
l2Client
cannon
.
L2HeaderSource
)
{
resourceCreator
:=
func
(
addr
common
.
Address
,
contract
*
contracts
.
FaultDisputeGameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
// Currently still using the old fault dispute game contracts for output_cannon
contractCreator
:=
func
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
GameContract
,
error
)
{
return
contracts
.
NewFaultDisputeGameContract
(
addr
,
caller
)
}
resourceCreator
:=
func
(
addr
common
.
Address
,
genericContract
GameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
logger
:=
logger
.
New
(
"game"
,
addr
)
logger
:=
logger
.
New
(
"game"
,
addr
)
contract
:=
genericContract
.
(
*
contracts
.
FaultDisputeGameContract
)
// TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks
// TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks
agreed
,
disputed
,
err
:=
contract
.
GetProposals
(
ctx
)
agreed
,
disputed
,
err
:=
contract
.
GetProposals
(
ctx
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -84,13 +90,13 @@ func registerOutputCannon(
...
@@ -84,13 +90,13 @@ func registerOutputCannon(
return
nil
,
nil
,
err
return
nil
,
nil
,
err
}
}
// TODO(client-pod#44): Validate absolute pre-state for split games
// TODO(client-pod#44): Validate absolute pre-state for split games
noopValidator
:=
func
(
ctx
context
.
Context
,
gameContract
*
contracts
.
FaultDispute
GameContract
)
error
{
noopValidator
:=
func
(
ctx
context
.
Context
,
gameContract
GameContract
)
error
{
return
nil
return
nil
}
}
return
accessor
,
noopValidator
,
nil
return
accessor
,
noopValidator
,
nil
}
}
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
resourceCreator
)
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
contractCreator
,
resourceCreator
)
}
}
registry
.
RegisterGameType
(
outputCannonGameType
,
playerCreator
)
registry
.
RegisterGameType
(
outputCannonGameType
,
playerCreator
)
}
}
...
@@ -104,20 +110,24 @@ func registerCannon(
...
@@ -104,20 +110,24 @@ func registerCannon(
txMgr
txmgr
.
TxManager
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
,
client
*
ethclient
.
Client
,
l2Client
cannon
.
L2HeaderSource
)
{
l2Client
cannon
.
L2HeaderSource
)
{
resourceCreator
:=
func
(
addr
common
.
Address
,
contract
*
contracts
.
FaultDisputeGameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
contractCreator
:=
func
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
GameContract
,
error
)
{
return
contracts
.
NewFaultDisputeGameContract
(
addr
,
caller
)
}
resourceCreator
:=
func
(
addr
common
.
Address
,
genericContract
GameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
logger
:=
logger
.
New
(
"game"
,
addr
)
logger
:=
logger
.
New
(
"game"
,
addr
)
contract
:=
genericContract
.
(
*
contracts
.
FaultDisputeGameContract
)
localInputs
,
err
:=
cannon
.
FetchLocalInputs
(
ctx
,
contract
,
l2Client
)
localInputs
,
err
:=
cannon
.
FetchLocalInputs
(
ctx
,
contract
,
l2Client
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
nil
,
fmt
.
Errorf
(
"failed to fetch cannon local inputs: %w"
,
err
)
return
nil
,
nil
,
fmt
.
Errorf
(
"failed to fetch cannon local inputs: %w"
,
err
)
}
}
provider
:=
cannon
.
NewTraceProvider
(
logger
,
m
,
cfg
,
faultTypes
.
NoLocalContext
,
localInputs
,
dir
,
gameDepth
)
provider
:=
cannon
.
NewTraceProvider
(
logger
,
m
,
cfg
,
faultTypes
.
NoLocalContext
,
localInputs
,
dir
,
gameDepth
)
validator
:=
func
(
ctx
context
.
Context
,
contract
*
contracts
.
FaultDispute
GameContract
)
error
{
validator
:=
func
(
ctx
context
.
Context
,
contract
GameContract
)
error
{
return
ValidateAbsolutePrestate
(
ctx
,
provider
,
contract
)
return
ValidateAbsolutePrestate
(
ctx
,
provider
,
contract
.
(
*
contracts
.
FaultDisputeGameContract
)
)
}
}
return
trace
.
NewSimpleTraceAccessor
(
provider
),
validator
,
nil
return
trace
.
NewSimpleTraceAccessor
(
provider
),
validator
,
nil
}
}
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
resourceCreator
)
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
contractCreator
,
resourceCreator
)
}
}
registry
.
RegisterGameType
(
cannonGameType
,
playerCreator
)
registry
.
RegisterGameType
(
cannonGameType
,
playerCreator
)
}
}
...
@@ -130,15 +140,18 @@ func registerAlphabet(
...
@@ -130,15 +140,18 @@ func registerAlphabet(
cfg
*
config
.
Config
,
cfg
*
config
.
Config
,
txMgr
txmgr
.
TxManager
,
txMgr
txmgr
.
TxManager
,
client
*
ethclient
.
Client
)
{
client
*
ethclient
.
Client
)
{
resourceCreator
:=
func
(
addr
common
.
Address
,
contract
*
contracts
.
FaultDisputeGameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
contractCreator
:=
func
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
GameContract
,
error
)
{
return
contracts
.
NewFaultDisputeGameContract
(
addr
,
caller
)
}
resourceCreator
:=
func
(
addr
common
.
Address
,
contract
GameContract
,
gameDepth
uint64
,
dir
string
)
(
faultTypes
.
TraceAccessor
,
gameValidator
,
error
)
{
provider
:=
alphabet
.
NewTraceProvider
(
cfg
.
AlphabetTrace
,
gameDepth
)
provider
:=
alphabet
.
NewTraceProvider
(
cfg
.
AlphabetTrace
,
gameDepth
)
validator
:=
func
(
ctx
context
.
Context
,
contract
*
contracts
.
FaultDispute
GameContract
)
error
{
validator
:=
func
(
ctx
context
.
Context
,
contract
GameContract
)
error
{
return
ValidateAbsolutePrestate
(
ctx
,
provider
,
contract
)
return
ValidateAbsolutePrestate
(
ctx
,
provider
,
contract
.
(
*
contracts
.
FaultDisputeGameContract
)
)
}
}
return
trace
.
NewSimpleTraceAccessor
(
provider
),
validator
,
nil
return
trace
.
NewSimpleTraceAccessor
(
provider
),
validator
,
nil
}
}
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
playerCreator
:=
func
(
game
types
.
GameMetadata
,
dir
string
)
(
scheduler
.
GamePlayer
,
error
)
{
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
resourceCreator
)
return
NewGamePlayer
(
ctx
,
logger
,
m
,
dir
,
game
.
Proxy
,
txMgr
,
client
,
contractCreator
,
resourceCreator
)
}
}
registry
.
RegisterGameType
(
alphabetGameType
,
playerCreator
)
registry
.
RegisterGameType
(
alphabetGameType
,
playerCreator
)
}
}
op-challenger/game/fault/responder/responder.go
View file @
388a4174
...
@@ -21,7 +21,7 @@ type GameContract interface {
...
@@ -21,7 +21,7 @@ type GameContract interface {
AttackTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
AttackTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
DefendTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
DefendTx
(
parentContractIndex
uint64
,
pivot
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
StepTx
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proof
[]
byte
)
(
txmgr
.
TxCandidate
,
error
)
StepTx
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proof
[]
byte
)
(
txmgr
.
TxCandidate
,
error
)
UpdateOracleTx
(
ctx
context
.
Context
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
UpdateOracleTx
(
ctx
context
.
Context
,
claimIdx
uint64
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
}
}
// FaultResponder implements the [Responder] interface to send onchain transactions.
// FaultResponder implements the [Responder] interface to send onchain transactions.
...
@@ -75,7 +75,7 @@ func (r *FaultResponder) ResolveClaim(ctx context.Context, claimIdx uint64) erro
...
@@ -75,7 +75,7 @@ func (r *FaultResponder) ResolveClaim(ctx context.Context, claimIdx uint64) erro
func
(
r
*
FaultResponder
)
PerformAction
(
ctx
context
.
Context
,
action
types
.
Action
)
error
{
func
(
r
*
FaultResponder
)
PerformAction
(
ctx
context
.
Context
,
action
types
.
Action
)
error
{
if
action
.
OracleData
!=
nil
{
if
action
.
OracleData
!=
nil
{
r
.
log
.
Info
(
"Updating oracle data"
,
"key"
,
action
.
OracleData
.
OracleKey
)
r
.
log
.
Info
(
"Updating oracle data"
,
"key"
,
action
.
OracleData
.
OracleKey
)
candidate
,
err
:=
r
.
contract
.
UpdateOracleTx
(
ctx
,
action
.
OracleData
)
candidate
,
err
:=
r
.
contract
.
UpdateOracleTx
(
ctx
,
uint64
(
action
.
ParentIdx
),
action
.
OracleData
)
if
err
!=
nil
{
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to create pre-image oracle tx: %w"
,
err
)
return
fmt
.
Errorf
(
"failed to create pre-image oracle tx: %w"
,
err
)
}
}
...
...
op-challenger/game/fault/responder/responder_test.go
View file @
388a4174
...
@@ -188,6 +188,7 @@ func TestPerformAction(t *testing.T) {
...
@@ -188,6 +188,7 @@ func TestPerformAction(t *testing.T) {
require
.
Len
(
t
,
mockTxMgr
.
sent
,
2
)
require
.
Len
(
t
,
mockTxMgr
.
sent
,
2
)
require
.
EqualValues
(
t
,
action
.
OracleData
,
contract
.
updateOracleArgs
)
require
.
EqualValues
(
t
,
action
.
OracleData
,
contract
.
updateOracleArgs
)
require
.
EqualValues
(
t
,
action
.
ParentIdx
,
contract
.
updateOracleClaimIdx
)
require
.
EqualValues
(
t
,
[]
interface
{}{
uint64
(
action
.
ParentIdx
),
action
.
IsAttack
,
action
.
PreState
,
action
.
ProofData
},
contract
.
stepArgs
)
require
.
EqualValues
(
t
,
[]
interface
{}{
uint64
(
action
.
ParentIdx
),
action
.
IsAttack
,
action
.
PreState
,
action
.
ProofData
},
contract
.
stepArgs
)
// Important that the oracle is updated first
// Important that the oracle is updated first
require
.
Equal
(
t
,
([]
byte
)(
"updateOracle"
),
mockTxMgr
.
sent
[
0
]
.
TxData
)
require
.
Equal
(
t
,
([]
byte
)(
"updateOracle"
),
mockTxMgr
.
sent
[
0
]
.
TxData
)
...
@@ -236,12 +237,13 @@ func (m *mockTxManager) Close() {
...
@@ -236,12 +237,13 @@ func (m *mockTxManager) Close() {
}
}
type
mockContract
struct
{
type
mockContract
struct
{
calls
int
calls
int
callFails
bool
callFails
bool
attackArgs
[]
interface
{}
attackArgs
[]
interface
{}
defendArgs
[]
interface
{}
defendArgs
[]
interface
{}
stepArgs
[]
interface
{}
stepArgs
[]
interface
{}
updateOracleArgs
*
types
.
PreimageOracleData
updateOracleClaimIdx
uint64
updateOracleArgs
*
types
.
PreimageOracleData
}
}
func
(
m
*
mockContract
)
CallResolve
(
_
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
func
(
m
*
mockContract
)
CallResolve
(
_
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
...
@@ -283,7 +285,8 @@ func (m *mockContract) StepTx(claimIdx uint64, isAttack bool, stateData []byte,
...
@@ -283,7 +285,8 @@ func (m *mockContract) StepTx(claimIdx uint64, isAttack bool, stateData []byte,
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"step"
)},
nil
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"step"
)},
nil
}
}
func
(
m
*
mockContract
)
UpdateOracleTx
(
_
context
.
Context
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
func
(
m
*
mockContract
)
UpdateOracleTx
(
_
context
.
Context
,
claimIdx
uint64
,
data
*
types
.
PreimageOracleData
)
(
txmgr
.
TxCandidate
,
error
)
{
m
.
updateOracleClaimIdx
=
claimIdx
m
.
updateOracleArgs
=
data
m
.
updateOracleArgs
=
data
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"updateOracle"
)},
nil
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"updateOracle"
)},
nil
}
}
op-challenger/game/fault/trace/outputs/output_cannon.go
View file @
388a4174
...
@@ -22,7 +22,7 @@ func NewOutputCannonTraceAccessor(
...
@@ -22,7 +22,7 @@ func NewOutputCannonTraceAccessor(
m
metrics
.
Metricer
,
m
metrics
.
Metricer
,
cfg
*
config
.
Config
,
cfg
*
config
.
Config
,
l2Client
cannon
.
L2HeaderSource
,
l2Client
cannon
.
L2HeaderSource
,
contract
*
contracts
.
FaultDisputeGameContract
,
contract
cannon
.
L1HeadSource
,
dir
string
,
dir
string
,
gameDepth
uint64
,
gameDepth
uint64
,
prestateBlock
uint64
,
prestateBlock
uint64
,
...
...
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