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
7943c1a0
Unverified
Commit
7943c1a0
authored
Nov 09, 2023
by
Adrian Sutton
Committed by
GitHub
Nov 09, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #8070 from ethereum-optimism/aj/responder-contract-call
op-challenger: Use new contract bindings in responder
parents
24520406
37b2b0f0
Changes
13
Hide 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 @
7943c1a0
...
...
@@ -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"
)
...
...
@@ -21,6 +22,11 @@ const (
methodClaim
=
"claimData"
methodL1Head
=
"l1Head"
methodProposals
=
"proposals"
methodResolve
=
"resolve"
methodResolveClaim
=
"resolveClaim"
methodAttack
=
"attack"
methodDefend
=
"defend"
methodStep
=
"step"
)
type
FaultDisputeGameContract
struct
{
...
...
@@ -138,6 +144,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 @
7943c1a0
...
...
@@ -67,6 +67,13 @@ func TestSimpleGetters(t *testing.T) {
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
...
...
@@ -176,6 +183,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 @
7943c1a0
...
...
@@ -89,7 +89,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 @
24520406
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 @
7943c1a0
...
...
@@ -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
txMgr
txmgr
.
TxManager
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
,
log
:
logger
,
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 @
7943c1a0
...
...
@@ -3,16 +3,13 @@ package responder
import
(
"context"
"errors"
"math/big"
"testing"
"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/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
ethtypes
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
...
...
@@ -21,44 +18,34 @@ import (
)
var
(
mockFdgAddress
=
common
.
HexToAddress
(
"0x1234"
)
mockSendError
=
errors
.
New
(
"mock send error"
)
mockCallError
=
errors
.
New
(
"mock call error"
)
mockSendError
=
errors
.
New
(
"mock send error"
)
mockCallError
=
errors
.
New
(
"mock call error"
)
)
// TestCallResolve tests the [Responder.CallResolve].
func
TestCallResolve
(
t
*
testing
.
T
)
{
t
.
Run
(
"SendFails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
callFails
=
true
responder
,
_
,
contract
:=
newTestFaultResponder
(
t
)
contract
.
callFails
=
true
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockCallError
)
require
.
Equal
(
t
,
gameTypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
0
,
mockTxMgr
.
calls
)
})
t
.
Run
(
"UnpackFails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
callBytes
=
[]
byte
{
0x00
,
0x01
}
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
Error
(
t
,
err
)
require
.
Equal
(
t
,
gameTypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
0
,
contract
.
calls
)
})
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
_
,
contract
:=
newTestFaultResponder
(
t
)
status
,
err
:=
responder
.
CallResolve
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
gameTypes
.
GameStatusInProgress
,
status
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
1
,
contract
.
calls
)
})
}
// TestResolve tests the [Responder.Resolve] method.
func
TestResolve
(
t
*
testing
.
T
)
{
t
.
Run
(
"SendFails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
sendFails
=
true
err
:=
responder
.
Resolve
(
context
.
Background
())
require
.
ErrorIs
(
t
,
err
,
mockSendError
)
...
...
@@ -66,7 +53,7 @@ func TestResolve(t *testing.T) {
})
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
err
:=
responder
.
Resolve
(
context
.
Background
())
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
sends
)
...
...
@@ -75,24 +62,24 @@ func TestResolve(t *testing.T) {
func
TestCallResolveClaim
(
t
*
testing
.
T
)
{
t
.
Run
(
"SendFails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
callFails
=
true
responder
,
_
,
contract
:=
newTestFaultResponder
(
t
)
contract
.
callFails
=
true
err
:=
responder
.
CallResolveClaim
(
context
.
Background
(),
0
)
require
.
ErrorIs
(
t
,
err
,
mockCallError
)
require
.
Equal
(
t
,
0
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
0
,
contract
.
calls
)
})
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
_
,
contract
:=
newTestFaultResponder
(
t
)
err
:=
responder
.
CallResolveClaim
(
context
.
Background
(),
0
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
calls
)
require
.
Equal
(
t
,
1
,
contract
.
calls
)
})
}
func
TestResolveClaim
(
t
*
testing
.
T
)
{
t
.
Run
(
"SendFails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
sendFails
=
true
err
:=
responder
.
ResolveClaim
(
context
.
Background
(),
0
)
require
.
ErrorIs
(
t
,
err
,
mockSendError
)
...
...
@@ -100,7 +87,7 @@ func TestResolveClaim(t *testing.T) {
})
t
.
Run
(
"Success"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
err
:=
responder
.
ResolveClaim
(
context
.
Background
(),
0
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
1
,
mockTxMgr
.
sends
)
...
...
@@ -110,7 +97,7 @@ func TestResolveClaim(t *testing.T) {
// TestRespond tests the [Responder.Respond] method.
func
TestPerformAction
(
t
*
testing
.
T
)
{
t
.
Run
(
"send fails"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
mockTxMgr
.
sendFails
=
true
err
:=
responder
.
PerformAction
(
context
.
Background
(),
types
.
Action
{
Type
:
types
.
ActionTypeMove
,
...
...
@@ -123,7 +110,7 @@ func TestPerformAction(t *testing.T) {
})
t
.
Run
(
"sends response"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
_
:=
newTestFaultResponder
(
t
)
err
:=
responder
.
PerformAction
(
context
.
Background
(),
types
.
Action
{
Type
:
types
.
ActionTypeMove
,
ParentIdx
:
123
,
...
...
@@ -135,7 +122,7 @@ func TestPerformAction(t *testing.T) {
})
t
.
Run
(
"attack"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
contract
:=
newTestFaultResponder
(
t
)
action
:=
types
.
Action
{
Type
:
types
.
ActionTypeMove
,
ParentIdx
:
123
,
...
...
@@ -145,18 +132,13 @@ func TestPerformAction(t *testing.T) {
err
:=
responder
.
PerformAction
(
context
.
Background
(),
action
)
require
.
NoError
(
t
,
err
)
// Pack the tx data manually.
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
expected
,
err
:=
fdgAbi
.
Pack
(
"attack"
,
big
.
NewInt
(
int64
(
action
.
ParentIdx
)),
action
.
Value
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
mockTxMgr
.
sent
,
1
)
require
.
Equal
(
t
,
expected
,
mockTxMgr
.
sent
[
0
]
.
TxData
)
require
.
EqualValues
(
t
,
[]
interface
{}{
uint64
(
action
.
ParentIdx
),
action
.
Value
},
contract
.
attackArgs
)
require
.
Equal
(
t
,
([]
byte
)(
"attack"
),
mockTxMgr
.
sent
[
0
]
.
TxData
)
})
t
.
Run
(
"defend"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
contract
:=
newTestFaultResponder
(
t
)
action
:=
types
.
Action
{
Type
:
types
.
ActionTypeMove
,
ParentIdx
:
123
,
...
...
@@ -166,18 +148,13 @@ func TestPerformAction(t *testing.T) {
err
:=
responder
.
PerformAction
(
context
.
Background
(),
action
)
require
.
NoError
(
t
,
err
)
// Pack the tx data manually.
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
expected
,
err
:=
fdgAbi
.
Pack
(
"defend"
,
big
.
NewInt
(
int64
(
action
.
ParentIdx
)),
action
.
Value
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
mockTxMgr
.
sent
,
1
)
require
.
Equal
(
t
,
expected
,
mockTxMgr
.
sent
[
0
]
.
TxData
)
require
.
EqualValues
(
t
,
[]
interface
{}{
uint64
(
action
.
ParentIdx
),
action
.
Value
},
contract
.
defendArgs
)
require
.
Equal
(
t
,
([]
byte
)(
"defend"
),
mockTxMgr
.
sent
[
0
]
.
TxData
)
})
t
.
Run
(
"step"
,
func
(
t
*
testing
.
T
)
{
responder
,
mockTxMgr
:=
newTestFaultResponder
(
t
)
responder
,
mockTxMgr
,
contract
:=
newTestFaultResponder
(
t
)
action
:=
types
.
Action
{
Type
:
types
.
ActionTypeStep
,
ParentIdx
:
123
,
...
...
@@ -188,36 +165,29 @@ func TestPerformAction(t *testing.T) {
err
:=
responder
.
PerformAction
(
context
.
Background
(),
action
)
require
.
NoError
(
t
,
err
)
// Pack the tx data manually.
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
require
.
NoError
(
t
,
err
)
expected
,
err
:=
fdgAbi
.
Pack
(
"step"
,
big
.
NewInt
(
int64
(
action
.
ParentIdx
)),
true
,
action
.
PreState
,
action
.
ProofData
)
require
.
NoError
(
t
,
err
)
require
.
Len
(
t
,
mockTxMgr
.
sent
,
1
)
require
.
Equal
(
t
,
expected
,
mockTxMgr
.
sent
[
0
]
.
TxData
)
require
.
EqualValues
(
t
,
[]
interface
{}{
uint64
(
action
.
ParentIdx
),
action
.
IsAttack
,
action
.
PreState
,
action
.
ProofData
},
contract
.
stepArgs
)
require
.
Equal
(
t
,
([]
byte
)(
"step"
),
mockTxMgr
.
sent
[
0
]
.
TxData
)
})
}
func
newTestFaultResponder
(
t
*
testing
.
T
)
(
*
FaultResponder
,
*
mockTxManager
)
{
func
newTestFaultResponder
(
t
*
testing
.
T
)
(
*
FaultResponder
,
*
mockTxManager
,
*
mockContract
)
{
log
:=
testlog
.
Logger
(
t
,
log
.
LvlError
)
mockTxMgr
:=
&
mockTxManager
{}
responder
,
err
:=
NewFaultResponder
(
log
,
mockTxMgr
,
mockFdgAddress
)
contract
:=
&
mockContract
{}
responder
,
err
:=
NewFaultResponder
(
log
,
mockTxMgr
,
contract
)
require
.
NoError
(
t
,
err
)
return
responder
,
mockTxMgr
return
responder
,
mockTxMgr
,
contract
}
type
mockTxManager
struct
{
from
common
.
Address
sends
int
sent
[]
txmgr
.
TxCandidate
calls
int
sendFails
bool
callFails
bool
callBytes
[]
byte
}
func
(
m
*
mockTxManager
)
Send
(
ctx
context
.
Context
,
candidate
txmgr
.
TxCandidate
)
(
*
ethtypes
.
Receipt
,
error
)
{
func
(
m
*
mockTxManager
)
Send
(
_
context
.
Context
,
candidate
txmgr
.
TxCandidate
)
(
*
ethtypes
.
Receipt
,
error
)
{
if
m
.
sendFails
{
return
nil
,
mockSendError
}
...
...
@@ -230,23 +200,57 @@ func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (
),
nil
}
func
(
m
*
mockTxManager
)
Call
(
_
context
.
Context
,
_
ethereum
.
CallMsg
,
_
*
big
.
Int
)
([]
byte
,
error
)
{
func
(
m
*
mockTxManager
)
BlockNumber
(
_
context
.
Context
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
}
func
(
m
*
mockTxManager
)
From
()
common
.
Address
{
return
m
.
from
}
type
mockContract
struct
{
calls
int
callFails
bool
attackArgs
[]
interface
{}
defendArgs
[]
interface
{}
stepArgs
[]
interface
{}
}
func
(
m
*
mockContract
)
CallResolve
(
_
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
if
m
.
callFails
{
return
nil
,
mockCallError
return
gameTypes
.
GameStatusInProgress
,
mockCallError
}
m
.
calls
++
if
m
.
callBytes
!=
nil
{
return
m
.
callBytes
,
nil
return
gameTypes
.
GameStatusInProgress
,
nil
}
func
(
m
*
mockContract
)
ResolveTx
()
(
txmgr
.
TxCandidate
,
error
)
{
return
txmgr
.
TxCandidate
{},
nil
}
func
(
m
*
mockContract
)
CallResolveClaim
(
_
context
.
Context
,
_
uint64
)
error
{
if
m
.
callFails
{
return
mockCallError
}
return
common
.
Hex2Bytes
(
"0000000000000000000000000000000000000000000000000000000000000000"
,
),
nil
m
.
calls
++
return
nil
}
func
(
m
*
mock
TxManager
)
BlockNumber
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
panic
(
"not implemented"
)
func
(
m
*
mock
Contract
)
ResolveClaimTx
(
_
uint64
)
(
txmgr
.
TxCandidate
,
error
)
{
return
txmgr
.
TxCandidate
{},
nil
}
func
(
m
*
mockTxManager
)
From
()
common
.
Address
{
return
m
.
from
func
(
m
*
mockContract
)
AttackTx
(
parentClaimId
uint64
,
claim
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
m
.
attackArgs
=
[]
interface
{}{
parentClaimId
,
claim
}
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"attack"
)},
nil
}
func
(
m
*
mockContract
)
DefendTx
(
parentClaimId
uint64
,
claim
common
.
Hash
)
(
txmgr
.
TxCandidate
,
error
)
{
m
.
defendArgs
=
[]
interface
{}{
parentClaimId
,
claim
}
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"defend"
)},
nil
}
func
(
m
*
mockContract
)
StepTx
(
claimIdx
uint64
,
isAttack
bool
,
stateData
[]
byte
,
proofData
[]
byte
)
(
txmgr
.
TxCandidate
,
error
)
{
m
.
stepArgs
=
[]
interface
{}{
claimIdx
,
isAttack
,
stateData
,
proofData
}
return
txmgr
.
TxCandidate
{
TxData
:
([]
byte
)(
"step"
)},
nil
}
op-challenger/game/fault/trace/cannon/updater_test.go
View file @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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 @
7943c1a0
...
...
@@ -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