Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(MSFDG): adapt AttackV2 and StepV2 functions in op-challenger2 #94

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions op-challenger2/game/fault/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty
containsOracleData := action.OracleData != nil
isLocal := containsOracleData && action.OracleData.IsLocal
actionLog = actionLog.New(
"is_attack", action.IsAttack,
"attackBranch", action.AttackBranch,
"parent", action.ParentClaim.ContractIndex,
"prestate", common.Bytes2Hex(action.PreState),
"proof", common.Bytes2Hex(action.ProofData),
Expand All @@ -133,13 +133,15 @@ func (a *Agent) performAction(ctx context.Context, wg *sync.WaitGroup, action ty
if action.OracleData != nil {
actionLog = actionLog.New("oracleKey", common.Bytes2Hex(action.OracleData.OracleKey))
}
} else if action.Type == types.ActionTypeMove {
actionLog = actionLog.New("is_attack", action.IsAttack, "parent", action.ParentClaim.ContractIndex, "value", action.Value)
} else if action.Type == types.ActionTypeAttackV2 {
actionLog = actionLog.New("attackBranch", action.AttackBranch, "parent", action.ParentClaim.ContractIndex, "value", action.Value)
}

switch action.Type {
case types.ActionTypeMove:
a.metrics.RecordGameMove()
JustXxx marked this conversation as resolved.
Show resolved Hide resolved
case types.ActionTypeAttackV2:
a.metrics.RecordGameAttackV2()
case types.ActionTypeStep:
a.metrics.RecordGameStep()
case types.ActionTypeChallengeL2BlockNumber:
Expand Down
17 changes: 16 additions & 1 deletion op-challenger2/game/fault/responder/responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-challenger2/game/fault/preimages"
"github.com/ethereum-optimism/optimism/op-challenger2/game/fault/types"
Expand All @@ -19,8 +20,10 @@ type GameContract interface {
CallResolveClaim(ctx context.Context, claimIdx uint64) error
ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error)
AttackTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
AttackV2Tx(ctx context.Context, parent types.Claim, attackBranch uint64, daType uint64, claims []byte) (txmgr.TxCandidate, error)
DefendTx(ctx context.Context, parent types.Claim, pivot common.Hash) (txmgr.TxCandidate, error)
StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error)
StepV2Tx(claimIdx uint64, attackBranch uint64, stateData []byte, proof types.StepProof) (txmgr.TxCandidate, error)
ChallengeL2BlockNumberTx(challenge *types.InvalidL2BlockNumberChallenge) (txmgr.TxCandidate, error)
}

Expand Down Expand Up @@ -117,8 +120,20 @@ func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action)
} else {
candidate, err = r.contract.DefendTx(ctx, action.ParentClaim, action.Value)
}
case types.ActionTypeAttackV2:
subValues := make([]byte, 0, len(*action.SubValues))
for _, subValue := range *action.SubValues {
subValues = append(subValues, subValue[:]...)
}
daTypeUint64 := (*big.Int)(action.DAType).Uint64()
candidate, err = r.contract.AttackV2Tx(ctx, action.ParentClaim, action.AttackBranch, daTypeUint64, subValues)
case types.ActionTypeStep:
candidate, err = r.contract.StepTx(uint64(action.ParentClaim.ContractIndex), action.IsAttack, action.PreState, action.ProofData)
stepProof := types.StepProof{
PreStateItem: action.OracleData.VMStateDA.PreDA,
PostStateItem: action.OracleData.VMStateDA.PostDA,
VmProof: action.ProofData,
}
candidate, err = r.contract.StepV2Tx(uint64(action.ParentClaim.ContractIndex), action.AttackBranch, action.PreState, stepProof)
case types.ActionTypeChallengeL2BlockNumber:
candidate, err = r.contract.ChallengeL2BlockNumberTx(action.InvalidL2BlockNumberChallenge)
}
Expand Down
69 changes: 51 additions & 18 deletions op-challenger2/game/fault/responder/responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,37 +146,54 @@ func TestPerformAction(t *testing.T) {
require.Equal(t, ([]byte)("attack"), mockTxMgr.sent[0].TxData)
})

t.Run("defend", func(t *testing.T) {
t.Run("attackV2", func(t *testing.T) {
responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t)
action := types.Action{
Type: types.ActionTypeMove,
ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: false,
Value: common.Hash{0xaa},
Type: types.ActionTypeAttackV2,
ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: false,
AttackBranch: 0,
DAType: types.CallDataType,
SubValues: &[]common.Hash{{0xaa}},
}
err := responder.PerformAction(context.Background(), action)
require.NoError(t, err)

require.Len(t, mockTxMgr.sent, 1)
require.EqualValues(t, []interface{}{action.ParentClaim, action.Value}, contract.defendArgs)
require.Equal(t, ([]byte)("defend"), mockTxMgr.sent[0].TxData)
daTypeUint64 := (*big.Int)(action.DAType).Uint64()
subValues := make([]byte, 0, len(*action.SubValues))
for _, subValue := range *action.SubValues {
subValues = append(subValues, subValue[:]...)
}
require.EqualValues(t, []interface{}{action.ParentClaim, action.AttackBranch, daTypeUint64, subValues}, contract.attackV2Args)
require.Equal(t, ([]byte)("attackV2"), mockTxMgr.sent[0].TxData)
})

t.Run("step", func(t *testing.T) {
responder, mockTxMgr, contract, _, _ := newTestFaultResponder(t)
action := types.Action{
Type: types.ActionTypeStep,
ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true,
PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6},
Type: types.ActionTypeStep,
ParentClaim: types.Claim{ContractIndex: 123},
IsAttack: true,
AttackBranch: 0,
PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6},
OracleData: &types.PreimageOracleData{
VMStateDA: types.DAData{},
OutputRootDAItem: types.DAItem{},
},
}
stepProof := types.StepProof{
PreStateItem: action.OracleData.VMStateDA.PreDA,
PostStateItem: action.OracleData.VMStateDA.PostDA,
VmProof: action.ProofData,
}
err := responder.PerformAction(context.Background(), action)
require.NoError(t, err)

require.Len(t, mockTxMgr.sent, 1)
require.EqualValues(t, []interface{}{uint64(123), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs)
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData)
require.EqualValues(t, []interface{}{uint64(123), action.AttackBranch, action.PreState, stepProof}, contract.stepV2Args)
require.Equal(t, ([]byte)("stepV2"), mockTxMgr.sent[0].TxData)
})

t.Run("stepWithLocalOracleData", func(t *testing.T) {
Expand All @@ -188,15 +205,17 @@ func TestPerformAction(t *testing.T) {
PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6},
OracleData: &types.PreimageOracleData{
IsLocal: true,
IsLocal: true,
VMStateDA: types.DAData{},
OutputRootDAItem: types.DAItem{},
},
}
err := responder.PerformAction(context.Background(), action)
require.NoError(t, err)

require.Len(t, mockTxMgr.sent, 1)
require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData)
require.Equal(t, ([]byte)("stepV2"), mockTxMgr.sent[0].TxData)
require.Equal(t, 1, uploader.updates)
require.Equal(t, 0, oracle.existCalls)
})
Expand All @@ -210,15 +229,17 @@ func TestPerformAction(t *testing.T) {
PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6},
OracleData: &types.PreimageOracleData{
IsLocal: false,
IsLocal: false,
VMStateDA: types.DAData{},
OutputRootDAItem: types.DAItem{},
},
}
err := responder.PerformAction(context.Background(), action)
require.NoError(t, err)

require.Len(t, mockTxMgr.sent, 1)
require.Nil(t, contract.updateOracleArgs) // mock uploader returns nil
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData)
require.Equal(t, ([]byte)("stepV2"), mockTxMgr.sent[0].TxData)
require.Equal(t, 1, uploader.updates)
require.Equal(t, 1, oracle.existCalls)
})
Expand Down Expand Up @@ -370,8 +391,10 @@ type mockContract struct {
calls int
callFails bool
attackArgs []interface{}
attackV2Args []interface{}
defendArgs []interface{}
stepArgs []interface{}
stepV2Args []interface{}
challengeArgs []interface{}
updateOracleClaimIdx uint64
updateOracleArgs *types.PreimageOracleData
Expand Down Expand Up @@ -411,6 +434,11 @@ func (m *mockContract) AttackTx(_ context.Context, parent types.Claim, claim com
return txmgr.TxCandidate{TxData: ([]byte)("attack")}, nil
}

func (m *mockContract) AttackV2Tx(ctx context.Context, parent types.Claim, attackBranch uint64, daType uint64, claims []byte) (txmgr.TxCandidate, error) {
m.attackV2Args = []interface{}{parent, attackBranch, daType, claims}
return txmgr.TxCandidate{TxData: ([]byte)("attackV2")}, nil
}

func (m *mockContract) DefendTx(_ context.Context, parent types.Claim, claim common.Hash) (txmgr.TxCandidate, error) {
m.defendArgs = []interface{}{parent, claim}
return txmgr.TxCandidate{TxData: ([]byte)("defend")}, nil
Expand All @@ -421,6 +449,11 @@ func (m *mockContract) StepTx(claimIdx uint64, isAttack bool, stateData []byte,
return txmgr.TxCandidate{TxData: ([]byte)("step")}, nil
}

func (m *mockContract) StepV2Tx(claimIdx uint64, attackBranch uint64, stateData []byte, proof types.StepProof) (txmgr.TxCandidate, error) {
m.stepV2Args = []interface{}{claimIdx, attackBranch, stateData, proof}
return txmgr.TxCandidate{TxData: ([]byte)("stepV2")}, nil
}

func (m *mockContract) UpdateOracleTx(_ context.Context, claimIdx uint64, data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
m.updateOracleClaimIdx = claimIdx
m.updateOracleArgs = data
Expand Down
54 changes: 42 additions & 12 deletions op-challenger2/game/fault/solver/actors.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,28 @@ var correctDefendLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) {
// Must attack the root
seq.Attack2(nil, 0)
} else {
seq.Attack2(nil, 1)
seq.Attack2(nil, seq.MaxAttackBranch())
}
})

var incorrectAttackLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) {
seq.Attack2(nil, 0, test.WithValue(common.Hash{0xaa}))
incorrectSubValues := []common.Hash{}
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues = append(incorrectSubValues, common.Hash{0xaa})
}
seq.Attack2(incorrectSubValues, 0)
})

var incorrectDefendLastClaim = respondLastClaim(func(seq *test.GameBuilderSeq) {
incorrectSubValues := []common.Hash{}
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues = append(incorrectSubValues, common.Hash{0xdd})
}
if seq.IsRoot() {
// Must attack the root
seq.Attack2(nil, 0, test.WithValue(common.Hash{0xdd}))
seq.Attack2(incorrectSubValues, 0)
} else {
seq.Attack2(nil, 1, test.WithValue(common.Hash{0xdd}))
seq.Attack2(incorrectSubValues, seq.MaxAttackBranch())
}
})

Expand All @@ -77,29 +85,51 @@ var defendEverythingCorrect = respondAllClaims(func(seq *test.GameBuilderSeq) {
// Must attack root
seq.Attack2(nil, 0)
} else {
seq.Attack2(nil, 1)
seq.Attack2(nil, seq.MaxAttackBranch())
}
})

var attackEverythingIncorrect = respondAllClaims(func(seq *test.GameBuilderSeq) {
seq.Attack2(nil, 0, test.WithValue(common.Hash{0xaa}))
incorrectSubValues := []common.Hash{}
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues = append(incorrectSubValues, common.Hash{0xaa})
}
seq.Attack2(incorrectSubValues, 0)
})

var defendEverythingIncorrect = respondAllClaims(func(seq *test.GameBuilderSeq) {
incorrectSubValues := []common.Hash{}
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues = append(incorrectSubValues, common.Hash{0xbb})
}
if seq.IsRoot() {
// Must attack root
seq.Attack2(nil, 0, test.WithValue(common.Hash{0xbb}))
seq.Attack2(incorrectSubValues, 0)
} else {
seq.Attack2(nil, 1, test.WithValue(common.Hash{0xbb}))
seq.Attack2(incorrectSubValues, seq.MaxAttackBranch())
}
})

var exhaustive = respondAllClaims(func(seq *test.GameBuilderSeq) {
seq.Attack2(nil, 0)
seq.Attack2(nil, 0, test.WithValue(common.Hash{0xaa}))
if !seq.IsRoot() {
seq.Attack2(nil, 1)
seq.Attack2(nil, 1, test.WithValue(common.Hash{0xdd}))
incorrectSubValues := []common.Hash{}
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues = append(incorrectSubValues, common.Hash{0xaa})
if seq.IsSplitDepth() {
// at splitDepth, there is only one subValue
break
}
}
seq.Attack2(incorrectSubValues, 0)
if !seq.IsRoot() && !seq.IsTraceRoot() {
seq.Attack2(nil, seq.MaxAttackBranch())
for i := uint64(0); i < seq.MaxAttackBranch(); i++ {
incorrectSubValues[i] = common.Hash{0xdd}
if seq.IsSplitDepth() {
break
}
}
seq.Attack2(incorrectSubValues, seq.MaxAttackBranch())
}
})

Expand Down
1 change: 0 additions & 1 deletion op-challenger2/game/fault/solver/game_rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (

func verifyGameRules(t *testing.T, game types.Game, rootClaimCorrect bool) {
actualResult, claimTree, resolvedGame := gameResult(game)

verifyExpectedGameResult(t, rootClaimCorrect, actualResult)

verifyNoChallengerClaimsWereSuccessfullyCountered(t, resolvedGame)
Expand Down
Loading