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
f3970260
Unverified
Commit
f3970260
authored
Jan 04, 2024
by
Adrian Sutton
Committed by
GitHub
Jan 03, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-challenger: Consolidate fault dispute contract code. (#8815)
parent
1e5d3907
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
401 additions
and
469 deletions
+401
-469
disputegame.go
op-challenger/game/fault/contracts/disputegame.go
+0
-197
disputegame_test.go
op-challenger/game/fault/contracts/disputegame_test.go
+0
-262
faultdisputegame.go
op-challenger/game/fault/contracts/faultdisputegame.go
+180
-5
faultdisputegame_test.go
op-challenger/game/fault/contracts/faultdisputegame_test.go
+221
-5
No files found.
op-challenger/game/fault/contracts/disputegame.go
deleted
100644 → 0
View file @
1e5d3907
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
=
"gameDuration"
methodMaxGameDepth
=
"maxGameDepth"
methodAbsolutePrestate
=
"absolutePrestate"
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
}
type
Proposal
struct
{
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
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
deleted
100644 → 0
View file @
1e5d3907
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
{
methodAlias
string
method
string
args
[]
interface
{}
result
interface
{}
expected
interface
{}
// Defaults to expecting the same as result
call
func
(
game
*
disputeGameContract
)
(
any
,
error
)
}{
{
methodAlias
:
"status"
,
method
:
methodStatus
,
result
:
types
.
GameStatusChallengerWon
,
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetStatus
(
context
.
Background
())
},
},
{
methodAlias
:
"gameDuration"
,
method
:
methodGameDuration
,
result
:
uint64
(
5566
),
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetGameDuration
(
context
.
Background
())
},
},
{
methodAlias
:
"maxGameDepth"
,
method
:
methodMaxGameDepth
,
result
:
big
.
NewInt
(
128
),
expected
:
uint64
(
128
),
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetMaxGameDepth
(
context
.
Background
())
},
},
{
methodAlias
:
"absolutePrestate"
,
method
:
methodAbsolutePrestate
,
result
:
common
.
Hash
{
0xab
},
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetAbsolutePrestateHash
(
context
.
Background
())
},
},
{
methodAlias
:
"claimCount"
,
method
:
methodClaimCount
,
result
:
big
.
NewInt
(
9876
),
expected
:
uint64
(
9876
),
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetClaimCount
(
context
.
Background
())
},
},
{
methodAlias
:
"l1Head"
,
method
:
methodL1Head
,
result
:
common
.
Hash
{
0xdd
,
0xbb
},
call
:
func
(
game
*
disputeGameContract
)
(
any
,
error
)
{
return
game
.
GetL1Head
(
context
.
Background
())
},
},
{
methodAlias
:
"resolve"
,
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
.
methodAlias
,
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 @
f3970260
...
...
@@ -7,12 +7,27 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"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"
)
var
(
methodGameDuration
=
"gameDuration"
methodMaxGameDepth
=
"maxGameDepth"
methodAbsolutePrestate
=
"absolutePrestate"
methodStatus
=
"status"
methodClaimCount
=
"claimDataLen"
methodClaim
=
"claimData"
methodL1Head
=
"l1Head"
methodResolve
=
"resolve"
methodResolveClaim
=
"resolveClaim"
methodAttack
=
"attack"
methodDefend
=
"defend"
methodStep
=
"step"
methodAddLocalData
=
"addLocalData"
methodVM
=
"vm"
methodGenesisBlockNumber
=
"genesisBlockNumber"
methodGenesisOutputRoot
=
"genesisOutputRoot"
methodSplitDepth
=
"splitDepth"
...
...
@@ -20,7 +35,13 @@ var (
)
type
FaultDisputeGameContract
struct
{
disputeGameContract
multiCaller
*
batching
.
MultiCaller
contract
*
batching
.
BoundContract
}
type
Proposal
struct
{
L2BlockNumber
*
big
.
Int
OutputRoot
common
.
Hash
}
func
NewFaultDisputeGameContract
(
addr
common
.
Address
,
caller
*
batching
.
MultiCaller
)
(
*
FaultDisputeGameContract
,
error
)
{
...
...
@@ -30,10 +51,8 @@ func NewFaultDisputeGameContract(addr common.Address, caller *batching.MultiCall
}
return
&
FaultDisputeGameContract
{
disputeGameContract
:
disputeGameContract
{
multiCaller
:
caller
,
contract
:
batching
.
NewBoundContract
(
contractAbi
,
addr
),
},
multiCaller
:
caller
,
contract
:
batching
.
NewBoundContract
(
contractAbi
,
addr
),
},
nil
}
...
...
@@ -100,3 +119,159 @@ func (f *FaultDisputeGameContract) addGlobalDataTx(ctx context.Context, data *ty
}
return
oracle
.
AddGlobalDataTx
(
data
)
}
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
}
func
(
f
*
FaultDisputeGameContract
)
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
*
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
)
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 @
f3970260
...
...
@@ -2,22 +2,238 @@ package contracts
import
(
"context"
"math"
"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-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"
)
func
TestFaultDisputeGameContract_CommonTests
(
t
*
testing
.
T
)
{
runCommonDisputeGameTests
(
t
,
func
(
t
*
testing
.
T
)
(
*
batchingTest
.
AbiBasedRpc
,
*
disputeGameContract
)
{
stubRpc
,
contract
:=
setupFaultDisputeGameTest
(
t
)
return
stubRpc
,
&
contract
.
disputeGameContract
})
var
(
fdgAddr
=
common
.
HexToAddress
(
"0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB"
)
vmAddr
=
common
.
HexToAddress
(
"0x33332842371dFC380576ebb09Ae16Cb6B6c3333"
)
oracleAddr
=
common
.
HexToAddress
(
"0x44442842371dFC380576ebb09Ae16Cb6B6ca4444"
)
)
func
TestSimpleGetters
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
methodAlias
string
method
string
args
[]
interface
{}
result
interface
{}
expected
interface
{}
// Defaults to expecting the same as result
call
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
}{
{
methodAlias
:
"status"
,
method
:
methodStatus
,
result
:
types
.
GameStatusChallengerWon
,
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetStatus
(
context
.
Background
())
},
},
{
methodAlias
:
"gameDuration"
,
method
:
methodGameDuration
,
result
:
uint64
(
5566
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetGameDuration
(
context
.
Background
())
},
},
{
methodAlias
:
"maxGameDepth"
,
method
:
methodMaxGameDepth
,
result
:
big
.
NewInt
(
128
),
expected
:
uint64
(
128
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetMaxGameDepth
(
context
.
Background
())
},
},
{
methodAlias
:
"absolutePrestate"
,
method
:
methodAbsolutePrestate
,
result
:
common
.
Hash
{
0xab
},
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetAbsolutePrestateHash
(
context
.
Background
())
},
},
{
methodAlias
:
"claimCount"
,
method
:
methodClaimCount
,
result
:
big
.
NewInt
(
9876
),
expected
:
uint64
(
9876
),
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetClaimCount
(
context
.
Background
())
},
},
{
methodAlias
:
"l1Head"
,
method
:
methodL1Head
,
result
:
common
.
Hash
{
0xdd
,
0xbb
},
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
GetL1Head
(
context
.
Background
())
},
},
{
methodAlias
:
"resolve"
,
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
.
methodAlias
,
func
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setupFaultDisputeGameTest
(
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
TestGetClaim
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
t
)
stubRpc
.
SetResponse
(
fdgAddr
,
methodResolveClaim
,
batching
.
BlockLatest
,
[]
interface
{}{
big
.
NewInt
(
123
)},
nil
)
err
:=
game
.
CallResolveClaim
(
context
.
Background
(),
123
)
require
.
NoError
(
t
,
err
)
}
func
TestResolveClaimTxTest
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
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
:=
setupFaultDisputeGameTest
(
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
)),
})
}
func
TestGetBlockRange
(
t
*
testing
.
T
)
{
...
...
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