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
75056361
Unverified
Commit
75056361
authored
Nov 07, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-challenger: Use new contract bindings in responder
parent
6cce3728
Changes
13
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
275 additions
and
334 deletions
+275
-334
faultdisputegame.go
op-challenger/game/fault/contracts/faultdisputegame.go
+57
-0
faultdisputegame_test.go
op-challenger/game/fault/contracts/faultdisputegame_test.go
+58
-0
player.go
op-challenger/game/fault/player.go
+1
-1
abi_test.go
op-challenger/game/fault/responder/abi_test.go
+0
-104
responder.go
op-challenger/game/fault/responder/responder.go
+30
-97
responder_test.go
op-challenger/game/fault/responder/responder_test.go
+77
-73
updater_test.go
op-challenger/game/fault/trace/cannon/updater_test.go
+0
-6
l2_proposer.go
op-e2e/actions/l2_proposer.go
+0
-3
call.go
op-service/sources/batching/call.go
+12
-0
call_test.go
op-service/sources/batching/call_test.go
+16
-0
stubs.go
op-service/sources/batching/test/stubs.go
+24
-11
TxManager.go
op-service/txmgr/mocks/TxManager.go
+0
-29
txmgr.go
op-service/txmgr/txmgr.go
+0
-10
No files found.
op-challenger/game/fault/contracts/faultdisputegame.go
View file @
75056361
...
...
@@ -9,6 +9,7 @@ import (
"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"
)
...
...
@@ -19,6 +20,11 @@ const (
methodStatus
=
"status"
methodClaimCount
=
"claimDataLen"
methodClaim
=
"claimData"
methodResolve
=
"resolve"
methodResolveClaim
=
"resolveClaim"
methodAttack
=
"attack"
methodDefend
=
"defend"
methodStep
=
"step"
)
type
FaultDisputeGameContract
struct
{
...
...
@@ -109,6 +115,57 @@ func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Cl
return
claims
,
nil
}
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
)
...
...
op-challenger/game/fault/contracts/faultdisputegame_test.go
View file @
75056361
...
...
@@ -60,6 +60,13 @@ func TestSimpleGetters(t *testing.T) {
return
game
.
GetClaimCount
(
context
.
Background
())
},
},
{
method
:
methodResolve
,
result
:
types
.
GameStatusInProgress
,
call
:
func
(
game
*
FaultDisputeGameContract
)
(
any
,
error
)
{
return
game
.
CallResolve
(
context
.
Background
())
},
},
}
for
_
,
test
:=
range
tests
{
test
:=
test
...
...
@@ -142,6 +149,57 @@ func TestGetAllClaims(t *testing.T) {
require
.
Equal
(
t
,
expectedClaims
,
claims
)
}
func
TestCallResolveClaim
(
t
*
testing
.
T
)
{
stubRpc
,
game
:=
setup
(
t
)
stubRpc
.
SetResponse
(
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
(
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
(
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
(
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
(
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
(
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
(
methodClaim
,
...
...
op-challenger/game/fault/player.go
View file @
75056361
...
...
@@ -85,7 +85,7 @@ func NewGamePlayer(
return
nil
,
fmt
.
Errorf
(
"failed to validate absolute prestate: %w"
,
err
)
}
responder
,
err
:=
responder
.
NewFaultResponder
(
logger
,
txMgr
,
add
r
)
responder
,
err
:=
responder
.
NewFaultResponder
(
logger
,
txMgr
,
loade
r
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to create the responder: %w"
,
err
)
}
...
...
op-challenger/game/fault/responder/abi_test.go
deleted
100644 → 0
View file @
6cce3728
package
responder
import
(
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
// setupFaultDisputeGame deploys the FaultDisputeGame contract to a simulated backend
func
setupFaultDisputeGame
()
(
common
.
Address
,
*
bind
.
TransactOpts
,
*
backends
.
SimulatedBackend
,
*
bindings
.
FaultDisputeGame
,
error
)
{
privateKey
,
err
:=
crypto
.
GenerateKey
()
from
:=
crypto
.
PubkeyToAddress
(
privateKey
.
PublicKey
)
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
nil
,
err
}
opts
,
err
:=
bind
.
NewKeyedTransactorWithChainID
(
privateKey
,
big
.
NewInt
(
1337
))
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
nil
,
err
}
backend
:=
backends
.
NewSimulatedBackend
(
core
.
GenesisAlloc
{
from
:
{
Balance
:
big
.
NewInt
(
params
.
Ether
)}},
50
_000_000
,
)
blockHashOracle
,
_
,
_
,
err
:=
bindings
.
DeployBlockOracle
(
opts
,
backend
)
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
nil
,
err
}
_
,
_
,
contract
,
err
:=
bindings
.
DeployFaultDisputeGame
(
opts
,
backend
,
uint8
(
0
),
// Game Type ID
[
32
]
byte
{
0x01
},
// Absolute Prestate Claim
big
.
NewInt
(
15
),
// Max Game Depth
uint64
(
604800
),
// 7 days
common
.
Address
{
0xdd
},
// VM
common
.
Address
{
0xee
},
// L2OutputOracle (Not used in Alphabet Game)
blockHashOracle
,
// Block hash oracle
)
if
err
!=
nil
{
return
common
.
Address
{},
nil
,
nil
,
nil
,
err
}
return
from
,
opts
,
backend
,
contract
,
nil
}
// TestBuildFaultDefendData ensures that the manual ABI packing is the same as going through the bound contract.
func
TestBuildFaultDefendData
(
t
*
testing
.
T
)
{
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
resp
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
resp
.
buildFaultDefendData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
opts
.
GasLimit
=
100
_000
tx
,
err
:=
contract
.
Defend
(
opts
,
big
.
NewInt
(
1
),
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
data
,
tx
.
Data
())
}
// TestBuildFaultAttackData ensures that the manual ABI packing is the same as going through the bound contract.
func
TestBuildFaultAttackData
(
t
*
testing
.
T
)
{
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
resp
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
resp
.
buildFaultAttackData
(
1
,
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
opts
.
GasLimit
=
100
_000
tx
,
err
:=
contract
.
Attack
(
opts
,
big
.
NewInt
(
1
),
[
32
]
byte
{
0x02
,
0x03
})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
data
,
tx
.
Data
())
}
// TestBuildFaultStepData ensures that the manual ABI packing is the same as going through the bound contract.
func
TestBuildFaultStepData
(
t
*
testing
.
T
)
{
_
,
opts
,
_
,
contract
,
err
:=
setupFaultDisputeGame
()
require
.
NoError
(
t
,
err
)
resp
,
_
:=
newTestFaultResponder
(
t
)
data
,
err
:=
resp
.
buildStepTxData
(
2
,
false
,
[]
byte
{
0x01
},
[]
byte
{
0x02
})
require
.
NoError
(
t
,
err
)
opts
.
GasLimit
=
100
_000
tx
,
err
:=
contract
.
Step
(
opts
,
big
.
NewInt
(
2
),
false
,
[]
byte
{
0x01
},
[]
byte
{
0x02
})
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
data
,
tx
.
Data
())
}
op-challenger/game/fault/responder/responder.go
View file @
75056361
...
...
@@ -2,153 +2,97 @@ package responder
import
(
"context"
"math/big"
"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/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
ethtypes
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)
type
GameContract
interface
{
CallResolve
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
ResolveTx
()
(
txmgr
.
TxCandidate
,
error
)
CallResolveClaim
(
ctx
context
.
Context
,
claimIdx
uint64
)
error
ResolveClaimTx
(
claimIdx
uint64
)
(
txmgr
.
TxCandidate
,
error
)
AttackTx
(
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
)
}
// FaultResponder implements the [Responder] interface to send onchain transactions.
type
FaultResponder
struct
{
log
log
.
Logger
txMgr
txmgr
.
TxManager
fdgAddr
common
.
Address
fdgAbi
*
abi
.
ABI
contract
GameContract
}
// NewFaultResponder returns a new [FaultResponder].
func
NewFaultResponder
(
logger
log
.
Logger
,
txManagr
txmgr
.
TxManager
,
fdgAddr
common
.
Address
)
(
*
FaultResponder
,
error
)
{
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
if
err
!=
nil
{
return
nil
,
err
}
func
NewFaultResponder
(
logger
log
.
Logger
,
txMgr
txmgr
.
TxManager
,
contract
GameContract
)
(
*
FaultResponder
,
error
)
{
return
&
FaultResponder
{
log
:
logger
,
txMgr
:
txManagr
,
fdgAddr
:
fdgAddr
,
fdgAbi
:
fdgAbi
,
txMgr
:
txMgr
,
contract
:
contract
,
},
nil
}
// buildFaultDefendData creates the transaction data for the Defend function.
func
(
r
*
FaultResponder
)
buildFaultDefendData
(
parentContractIndex
int
,
pivot
[
32
]
byte
)
([]
byte
,
error
)
{
return
r
.
fdgAbi
.
Pack
(
"defend"
,
big
.
NewInt
(
int64
(
parentContractIndex
)),
pivot
,
)
}
// buildFaultAttackData creates the transaction data for the Attack function.
func
(
r
*
FaultResponder
)
buildFaultAttackData
(
parentContractIndex
int
,
pivot
[
32
]
byte
)
([]
byte
,
error
)
{
return
r
.
fdgAbi
.
Pack
(
"attack"
,
big
.
NewInt
(
int64
(
parentContractIndex
)),
pivot
,
)
}
// buildResolveData creates the transaction data for the Resolve function.
func
(
r
*
FaultResponder
)
buildResolveData
()
([]
byte
,
error
)
{
return
r
.
fdgAbi
.
Pack
(
"resolve"
)
}
// CallResolve determines if the resolve function on the fault dispute game contract
// would succeed. Returns the game status if the call would succeed, errors otherwise.
func
(
r
*
FaultResponder
)
CallResolve
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
txData
,
err
:=
r
.
buildResolveData
()
if
err
!=
nil
{
return
gameTypes
.
GameStatusInProgress
,
err
}
res
,
err
:=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
To
:
&
r
.
fdgAddr
,
Data
:
txData
,
},
nil
)
if
err
!=
nil
{
return
gameTypes
.
GameStatusInProgress
,
err
}
var
status
uint8
if
err
=
r
.
fdgAbi
.
UnpackIntoInterface
(
&
status
,
"resolve"
,
res
);
err
!=
nil
{
return
gameTypes
.
GameStatusInProgress
,
err
}
return
gameTypes
.
GameStatusFromUint8
(
status
)
return
r
.
contract
.
CallResolve
(
ctx
)
}
// Resolve executes a resolve transaction to resolve a fault dispute game.
func
(
r
*
FaultResponder
)
Resolve
(
ctx
context
.
Context
)
error
{
txData
,
err
:=
r
.
buildResolveData
()
candidate
,
err
:=
r
.
contract
.
ResolveTx
()
if
err
!=
nil
{
return
err
}
return
r
.
sendTxAndWait
(
ctx
,
txData
)
}
// buildResolveClaimData creates the transaction data for the ResolveClaim function.
func
(
r
*
FaultResponder
)
buildResolveClaimData
(
claimIdx
uint64
)
([]
byte
,
error
)
{
return
r
.
fdgAbi
.
Pack
(
"resolveClaim"
,
big
.
NewInt
(
int64
(
claimIdx
)))
return
r
.
sendTxAndWait
(
ctx
,
candidate
)
}
// CallResolveClaim determines if the resolveClaim function on the fault dispute game contract
// would succeed.
func
(
r
*
FaultResponder
)
CallResolveClaim
(
ctx
context
.
Context
,
claimIdx
uint64
)
error
{
txData
,
err
:=
r
.
buildResolveClaimData
(
claimIdx
)
if
err
!=
nil
{
return
err
}
_
,
err
=
r
.
txMgr
.
Call
(
ctx
,
ethereum
.
CallMsg
{
To
:
&
r
.
fdgAddr
,
Data
:
txData
,
},
nil
)
return
err
return
r
.
contract
.
CallResolveClaim
(
ctx
,
claimIdx
)
}
// ResolveClaim executes a resolveClaim transaction to resolve a fault dispute game.
func
(
r
*
FaultResponder
)
ResolveClaim
(
ctx
context
.
Context
,
claimIdx
uint64
)
error
{
txData
,
err
:=
r
.
buildResolveClaimData
(
claimIdx
)
candidate
,
err
:=
r
.
contract
.
ResolveClaimTx
(
claimIdx
)
if
err
!=
nil
{
return
err
}
return
r
.
sendTxAndWait
(
ctx
,
txData
)
return
r
.
sendTxAndWait
(
ctx
,
candidate
)
}
func
(
r
*
FaultResponder
)
PerformAction
(
ctx
context
.
Context
,
action
types
.
Action
)
error
{
var
txData
[]
by
te
var
candidate
txmgr
.
TxCandida
te
var
err
error
switch
action
.
Type
{
case
types
.
ActionTypeMove
:
if
action
.
IsAttack
{
txData
,
err
=
r
.
buildFaultAttackData
(
action
.
ParentIdx
,
action
.
Value
)
candidate
,
err
=
r
.
contract
.
AttackTx
(
uint64
(
action
.
ParentIdx
)
,
action
.
Value
)
}
else
{
txData
,
err
=
r
.
buildFaultDefendData
(
action
.
ParentIdx
,
action
.
Value
)
candidate
,
err
=
r
.
contract
.
DefendTx
(
uint64
(
action
.
ParentIdx
)
,
action
.
Value
)
}
case
types
.
ActionTypeStep
:
txData
,
err
=
r
.
buildStepTxData
(
uint64
(
action
.
ParentIdx
),
action
.
IsAttack
,
action
.
PreState
,
action
.
ProofData
)
candidate
,
err
=
r
.
contract
.
StepTx
(
uint64
(
action
.
ParentIdx
),
action
.
IsAttack
,
action
.
PreState
,
action
.
ProofData
)
}
if
err
!=
nil
{
return
err
}
return
r
.
sendTxAndWait
(
ctx
,
txData
)
return
r
.
sendTxAndWait
(
ctx
,
candidate
)
}
// sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt.
// This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr].
func
(
r
*
FaultResponder
)
sendTxAndWait
(
ctx
context
.
Context
,
txData
[]
byte
)
error
{
receipt
,
err
:=
r
.
txMgr
.
Send
(
ctx
,
txmgr
.
TxCandidate
{
To
:
&
r
.
fdgAddr
,
TxData
:
txData
,
GasLimit
:
0
,
})
func
(
r
*
FaultResponder
)
sendTxAndWait
(
ctx
context
.
Context
,
candidate
txmgr
.
TxCandidate
)
error
{
receipt
,
err
:=
r
.
txMgr
.
Send
(
ctx
,
candidate
)
if
err
!=
nil
{
return
err
}
...
...
@@ -159,14 +103,3 @@ func (r *FaultResponder) sendTxAndWait(ctx context.Context, txData []byte) error
}
return
nil
}
// buildStepTxData creates the transaction data for the step function.
func
(
r
*
FaultResponder
)
buildStepTxData
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proof
[]
byte
)
([]
byte
,
error
)
{
return
r
.
fdgAbi
.
Pack
(
"step"
,
big
.
NewInt
(
int64
(
claimIdx
)),
isAttack
,
stateData
,
proof
,
)
}
op-challenger/game/fault/responder/responder_test.go
View file @
75056361
This diff is collapsed.
Click to expand it.
op-challenger/game/fault/trace/cannon/updater_test.go
View file @
75056361
...
...
@@ -3,7 +3,6 @@ package cannon
import
(
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
...
...
@@ -11,7 +10,6 @@ import (
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
ethtypes
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -47,10 +45,6 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (
),
nil
}
func
(
m
*
mockTxManager
)
Call
(
_
context
.
Context
,
_
ethereum
.
CallMsg
,
_
*
big
.
Int
)
([]
byte
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockTxManager
)
BlockNumber
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
}
...
...
op-e2e/actions/l2_proposer.go
View file @
75056361
...
...
@@ -48,9 +48,6 @@ type fakeTxMgr struct {
func
(
f
fakeTxMgr
)
From
()
common
.
Address
{
return
f
.
from
}
func
(
f
fakeTxMgr
)
Call
(
_
context
.
Context
,
_
ethereum
.
CallMsg
,
_
*
big
.
Int
)
([]
byte
,
error
)
{
panic
(
"unimplemented"
)
}
func
(
f
fakeTxMgr
)
BlockNumber
(
_
context
.
Context
)
(
uint64
,
error
)
{
panic
(
"unimplemented"
)
}
...
...
op-service/sources/batching/call.go
View file @
75056361
...
...
@@ -4,6 +4,7 @@ import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
...
...
@@ -86,6 +87,17 @@ func toCallArg(msg ethereum.CallMsg) interface{} {
return
arg
}
func
(
c
*
ContractCall
)
ToTxCandidate
()
(
txmgr
.
TxCandidate
,
error
)
{
data
,
err
:=
c
.
Pack
()
if
err
!=
nil
{
return
txmgr
.
TxCandidate
{},
fmt
.
Errorf
(
"failed to pack arguments: %w"
,
err
)
}
return
txmgr
.
TxCandidate
{
TxData
:
data
,
To
:
&
c
.
Addr
,
},
nil
}
type
CallResult
struct
{
out
[]
interface
{}
}
...
...
op-service/sources/batching/call_test.go
View file @
75056361
...
...
@@ -30,6 +30,22 @@ func TestContractCall_ToCallArgs(t *testing.T) {
require
.
NotContains
(
t
,
argMap
,
"gasPrice"
)
}
func
TestContractCall_ToTxCandidate
(
t
*
testing
.
T
)
{
addr
:=
common
.
Address
{
0xbd
}
testAbi
,
err
:=
bindings
.
ERC20MetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
call
:=
NewContractCall
(
testAbi
,
addr
,
"approve"
,
common
.
Address
{
0xcc
},
big
.
NewInt
(
1234444
))
candidate
,
err
:=
call
.
ToTxCandidate
()
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
candidate
.
To
,
&
addr
)
expectedData
,
err
:=
call
.
Pack
()
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
candidate
.
TxData
,
expectedData
)
require
.
Nil
(
t
,
candidate
.
Value
)
require
.
Zero
(
t
,
candidate
.
GasLimit
)
}
func
TestContractCall_Pack
(
t
*
testing
.
T
)
{
addr
:=
common
.
Address
{
0xbd
}
testAbi
,
err
:=
bindings
.
ERC20MetaData
.
GetAbi
()
...
...
op-service/sources/batching/test/stubs.go
View file @
75056361
...
...
@@ -8,6 +8,7 @@ import (
"testing"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
...
...
@@ -73,6 +74,11 @@ func (l *AbiBasedRpc) BatchCallContext(ctx context.Context, b []rpc.BatchElem) e
return
errors
.
Join
(
errs
...
)
}
func
(
l
*
AbiBasedRpc
)
VerifyTxCandidate
(
candidate
txmgr
.
TxCandidate
)
{
require
.
EqualValues
(
l
.
t
,
&
l
.
addr
,
candidate
.
To
,
"Incorrect To address"
)
l
.
findExpectedCall
(
candidate
.
TxData
,
batching
.
BlockLatest
.
ArgValue
())
}
func
(
l
*
AbiBasedRpc
)
CallContext
(
_
context
.
Context
,
out
interface
{},
method
string
,
args
...
interface
{})
error
{
require
.
Equal
(
l
.
t
,
"eth_call"
,
method
)
require
.
Len
(
l
.
t
,
args
,
2
)
...
...
@@ -82,11 +88,27 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str
require
.
Equal
(
l
.
t
,
&
l
.
addr
,
callOpts
[
"to"
])
data
,
ok
:=
callOpts
[
"input"
]
.
(
hexutil
.
Bytes
)
require
.
True
(
l
.
t
,
ok
)
call
,
abiMethod
:=
l
.
findExpectedCall
(
data
,
actualBlockRef
)
output
,
err
:=
abiMethod
.
Outputs
.
Pack
(
call
.
outputs
...
)
require
.
NoErrorf
(
l
.
t
,
err
,
"Invalid outputs for method %v: %v"
,
abiMethod
.
Name
,
call
.
outputs
)
// I admit I do not understand Go reflection.
// So leverage json.Unmarshal to set the out value correctly.
j
,
err
:=
json
.
Marshal
(
hexutil
.
Bytes
(
output
))
require
.
NoError
(
l
.
t
,
err
)
require
.
NoError
(
l
.
t
,
json
.
Unmarshal
(
j
,
out
))
return
nil
}
func
(
l
*
AbiBasedRpc
)
findExpectedCall
(
data
[]
byte
,
actualBlockRef
interface
{})
(
*
expectedCall
,
*
abi
.
Method
)
{
abiMethod
,
err
:=
l
.
abi
.
MethodById
(
data
[
0
:
4
])
require
.
NoError
(
l
.
t
,
err
)
argData
:=
data
[
4
:
]
args
,
err
=
abiMethod
.
Inputs
.
Unpack
(
argData
)
args
,
err
:
=
abiMethod
.
Inputs
.
Unpack
(
argData
)
require
.
NoError
(
l
.
t
,
err
)
require
.
Len
(
l
.
t
,
args
,
len
(
abiMethod
.
Inputs
))
...
...
@@ -100,14 +122,5 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str
}
}
require
.
NotNilf
(
l
.
t
,
call
,
"No expected calls to %v at block %v with arguments: %v
\n
Expected calls: %v"
,
abiMethod
.
Name
,
actualBlockRef
,
args
,
expectedCalls
)
output
,
err
:=
abiMethod
.
Outputs
.
Pack
(
call
.
outputs
...
)
require
.
NoErrorf
(
l
.
t
,
err
,
"Invalid outputs for method %v: %v"
,
abiMethod
.
Name
,
call
.
outputs
)
// I admit I do not understand Go reflection.
// So leverage json.Unmarshal to set the out value correctly.
j
,
err
:=
json
.
Marshal
(
hexutil
.
Bytes
(
output
))
require
.
NoError
(
l
.
t
,
err
)
require
.
NoError
(
l
.
t
,
json
.
Unmarshal
(
j
,
out
))
return
nil
return
call
,
abiMethod
}
op-service/txmgr/mocks/TxManager.go
View file @
75056361
...
...
@@ -4,12 +4,9 @@ package mocks
import
(
context
"context"
big
"math/big"
common
"github.com/ethereum/go-ethereum/common"
ethereum
"github.com/ethereum/go-ethereum"
mock
"github.com/stretchr/testify/mock"
txmgr
"github.com/ethereum-optimism/optimism/op-service/txmgr"
...
...
@@ -46,32 +43,6 @@ func (_m *TxManager) BlockNumber(ctx context.Context) (uint64, error) {
return
r0
,
r1
}
// Call provides a mock function with given fields: ctx, msg, blockNumber
func
(
_m
*
TxManager
)
Call
(
ctx
context
.
Context
,
msg
ethereum
.
CallMsg
,
blockNumber
*
big
.
Int
)
([]
byte
,
error
)
{
ret
:=
_m
.
Called
(
ctx
,
msg
,
blockNumber
)
var
r0
[]
byte
var
r1
error
if
rf
,
ok
:=
ret
.
Get
(
0
)
.
(
func
(
context
.
Context
,
ethereum
.
CallMsg
,
*
big
.
Int
)
([]
byte
,
error
));
ok
{
return
rf
(
ctx
,
msg
,
blockNumber
)
}
if
rf
,
ok
:=
ret
.
Get
(
0
)
.
(
func
(
context
.
Context
,
ethereum
.
CallMsg
,
*
big
.
Int
)
[]
byte
);
ok
{
r0
=
rf
(
ctx
,
msg
,
blockNumber
)
}
else
{
if
ret
.
Get
(
0
)
!=
nil
{
r0
=
ret
.
Get
(
0
)
.
([]
byte
)
}
}
if
rf
,
ok
:=
ret
.
Get
(
1
)
.
(
func
(
context
.
Context
,
ethereum
.
CallMsg
,
*
big
.
Int
)
error
);
ok
{
r1
=
rf
(
ctx
,
msg
,
blockNumber
)
}
else
{
r1
=
ret
.
Error
(
1
)
}
return
r0
,
r1
}
// From provides a mock function with given fields:
func
(
_m
*
TxManager
)
From
()
common
.
Address
{
ret
:=
_m
.
Called
()
...
...
op-service/txmgr/txmgr.go
View file @
75056361
...
...
@@ -43,10 +43,6 @@ type TxManager interface {
// NOTE: Send can be called concurrently, the nonce will be managed internally.
Send
(
ctx
context
.
Context
,
candidate
TxCandidate
)
(
*
types
.
Receipt
,
error
)
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
Call
(
ctx
context
.
Context
,
msg
ethereum
.
CallMsg
,
blockNumber
*
big
.
Int
)
([]
byte
,
error
)
// From returns the sending address associated with the instance of the transaction manager.
// It is static for a single instance of a TxManager.
From
()
common
.
Address
...
...
@@ -169,12 +165,6 @@ func (m *SimpleTxManager) Send(ctx context.Context, candidate TxCandidate) (*typ
return
receipt
,
err
}
// Call is used to call a contract.
// Internally, it uses the [ethclient.Client.CallContract] method.
func
(
m
*
SimpleTxManager
)
Call
(
ctx
context
.
Context
,
msg
ethereum
.
CallMsg
,
blockNumber
*
big
.
Int
)
([]
byte
,
error
)
{
return
m
.
backend
.
CallContract
(
ctx
,
msg
,
blockNumber
)
}
// send performs the actual transaction creation and sending.
func
(
m
*
SimpleTxManager
)
send
(
ctx
context
.
Context
,
candidate
TxCandidate
)
(
*
types
.
Receipt
,
error
)
{
if
m
.
cfg
.
TxSendTimeout
!=
0
{
...
...
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