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

MSFDG: adapt AttackV2 and StepV2 functions in op-challenger2 and alphabet E2E test #105

Open
wants to merge 24 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9541939
Merge remote-tracking branch 'origin/po/common-datatypes' into bill/o…
JustXxx Nov 2, 2024
ad007d7
feat(MSFDG): add getSubValues
dajuguan Nov 3, 2024
854429a
Merge remote-tracking branch 'origin/develop' into bill/op-challenger…
JustXxx Nov 3, 2024
6c1e5b9
op-challenger2 add attackV2
JustXxx Nov 3, 2024
5d65304
Merge remote-tracking branch 'origin/po/getsubclaims' into bill/op-ch…
JustXxx Nov 3, 2024
360b88b
op-challenger2 add stepV2
JustXxx Nov 10, 2024
ef4cc9e
merge po/oracle_proof
JustXxx Nov 10, 2024
42d3a98
add getStepData tests for solver_test.go
dajuguan Nov 15, 2024
53c81ac
modify test
JustXxx Nov 16, 2024
94d5923
merge
JustXxx Nov 16, 2024
97e5c1c
fix step maxAttackBranch test case
dajuguan Nov 16, 2024
591fa5d
fix bug by rules
JustXxx Nov 17, 2024
1cab66d
Merge remote-tracking branch 'origin/bill/op-challenger2-attackv2' in…
JustXxx Nov 17, 2024
0805fd4
add getstepData testcase
dajuguan Nov 21, 2024
6b7839b
Merge remote-tracking branch 'origin/bill/op-challenger2-attackv2' in…
JustXxx Nov 21, 2024
f65fdc3
modify unittest TestCalculateNextActions
JustXxx Nov 22, 2024
c026566
Merge remote-tracking branch 'origin/develop' into bill/op-challenger…
JustXxx Nov 23, 2024
32ca079
fix: TestMultipleRoundsWithNbits1/2
dajuguan Nov 27, 2024
0176d08
fix tests: responder_test and TestGetStepDataWithOutputRoot test
dajuguan Nov 27, 2024
670ca68
fix: getTxByHash and filterLog call in devnet env
dajuguan Nov 29, 2024
162ec26
contract:
dajuguan Nov 29, 2024
2716b1e
fix: VMStateRoot only has one subValue
dajuguan Nov 30, 2024
772c2ac
op-challenger2: cosmatic and pass all tests
dajuguan Nov 30, 2024
c1513a0
test: alphabet game e2etest for MSFDG
dajuguan Nov 30, 2024
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()
case types.ActionTypeAttackV2:
a.metrics.RecordGameAttackV2()
case types.ActionTypeStep:
a.metrics.RecordGameStep()
case types.ActionTypeChallengeL2BlockNumber:
Expand Down
43 changes: 32 additions & 11 deletions op-challenger2/game/fault/contracts/faultdisputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ var (
methodAttack = "attack"
methodDefend = "defend"
methodStep = "step"
methodAddLocalData = "addLocalData"
methodAddLocalData = "addLocalData2"
methodVM = "vm"
methodStartingBlockNumber = "startingBlockNumber"
methodStartingRootHash = "startingRootHash"
Expand Down Expand Up @@ -75,6 +75,8 @@ type FaultDisputeGameContractLatest struct {
metrics metrics.ContractMetricer
multiCaller *batching.MultiCaller
contract *batching.BoundContract
nbits uint64
splitDepth types.Depth
}

type Proposal struct {
Expand Down Expand Up @@ -130,11 +132,23 @@ func NewFaultDisputeGameContract(ctx context.Context, metrics metrics.ContractMe
},
}, nil
} else {
return &FaultDisputeGameContractLatest{

contract := &FaultDisputeGameContractLatest{
metrics: metrics,
multiCaller: caller,
contract: batching.NewBoundContract(contractAbi, addr),
}, nil
}
nbits, err := contract.GetNBits(ctx)
if err != nil {
return nil, err
}
splitDepth, err := contract.GetSplitDepth(ctx)
if err != nil {
return nil, err
}
contract.nbits = nbits
contract.splitDepth = splitDepth
return contract, nil
}
}

Expand Down Expand Up @@ -349,6 +363,9 @@ func (f *FaultDisputeGameContractLatest) UpdateOracleTx(ctx context.Context, cla
}

func (f *FaultDisputeGameContractLatest) addLocalDataTx(claimIdx uint64, data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
if data.OutputRootDAItem.DaType == nil {
return txmgr.TxCandidate{}, fmt.Errorf("DaType isn't set")
}
call := f.contract.Call(
methodAddLocalData,
data.GetIdent(),
Expand Down Expand Up @@ -479,6 +496,11 @@ func (f *FaultDisputeGameContractLatest) GetAllClaimsWithSubValues(ctx context.C
return nil, err
}
for idx, claim := range claims {
if claim.IsRoot() { // root claim contains no subValues in DA, we create subvalues manually
claim.SubValues = &[]common.Hash{claim.Value}
claims[idx] = claim
continue
}
subValues, attackBranch, err := f.getSubValuesAndAttackBranch(ctx, &claim)
if err != nil {
return nil, fmt.Errorf("failed to load subValues: %w", err)
Expand Down Expand Up @@ -510,7 +532,6 @@ func (f *FaultDisputeGameContractLatest) getSubValuesAndAttackBranch(ctx context
return nil, 0, fmt.Errorf("failed to get move event log: %w", moveIter.Error())
}
txHash := moveIter.Event.Raw.TxHash

getTxByHashCall := batching.NewTxGetByHash(f.contract.Abi(), txHash, methodAttackV2)
result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, getTxByHashCall)
if err != nil {
Expand All @@ -535,9 +556,13 @@ func (f *FaultDisputeGameContractLatest) getSubValuesAndAttackBranch(ctx context
if err != nil {
return nil, 0, err
}
valuesBytesLen := uint(32 * maxAttackBranch)
nelements := maxAttackBranch
if aggClaim.Position.Depth() == types.Depth(f.nbits)+f.splitDepth {
nelements = 1
}
valuesBytesLen := uint(32 * nelements)
bytes := abi.ConvertType(inputMap[fieldSubValues], make([]byte, valuesBytesLen)).([]byte)
for i := uint64(0); i < maxAttackBranch; i++ {
for i := uint64(0); i < nelements; i++ {
hash := common.BytesToHash(bytes[i*32 : (i+1)*32])
subValues = append(subValues, hash)
}
Expand Down Expand Up @@ -715,17 +740,13 @@ func (f *FaultDisputeGameContractLatest) GetMaxAttackBranch(ctx context.Context)
}

func (f *FaultDisputeGameContractLatest) AttackV2Tx(ctx context.Context, parent types.Claim, attackBranch uint64, daType uint64, claims []byte) (txmgr.TxCandidate, error) {
nBits, err := f.GetNBits(ctx)
if err != nil {
return txmgr.TxCandidate{}, fmt.Errorf("failed to retrieve nbits: %w", err)
}
call := f.contract.Call(methodAttackV2,
parent.Value,
big.NewInt(int64(parent.ContractIndex)),
new(big.Int).SetUint64(attackBranch),
new(big.Int).SetUint64(daType),
claims)
return f.txWithBond(ctx, parent.Position.MoveN(nBits, attackBranch), call)
return f.txWithBond(ctx, parent.Position.MoveN(f.nbits, attackBranch), call)
}

func (f *FaultDisputeGameContractLatest) StepV2Tx(claimIdx uint64, attackBranch uint64, stateData []byte, proof types.StepProof) (txmgr.TxCandidate, error) {
Expand Down
24 changes: 6 additions & 18 deletions op-challenger2/game/fault/contracts/faultdisputegame_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,20 +481,6 @@ func TestGetBlockRange(t *testing.T) {
}
}

func TestGetSplitDepth(t *testing.T) {
for _, version := range versions {
version := version
t.Run(version.version, func(t *testing.T) {
stubRpc, contract := setupFaultDisputeGameTest(t, version)
expectedSplitDepth := faultTypes.Depth(15)
stubRpc.SetResponse(fdgAddr, methodSplitDepth, rpcblock.Latest, nil, []interface{}{new(big.Int).SetUint64(uint64(expectedSplitDepth))})
splitDepth, err := contract.GetSplitDepth(context.Background())
require.NoError(t, err)
require.Equal(t, expectedSplitDepth, splitDepth)
})
}
}

func TestGetGameMetadata(t *testing.T) {
for _, version := range versions {
version := version
Expand Down Expand Up @@ -794,6 +780,9 @@ func setupFaultDisputeGameTest(t *testing.T, version contractVersion) (*batching
caller := batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize)

stubRpc.SetResponse(fdgAddr, methodVersion, rpcblock.Latest, nil, []interface{}{version.version})
nbitOrSplitDepth := big.NewInt(2)
stubRpc.SetResponse(fdgAddr, methodNBits, rpcblock.Latest, nil, []interface{}{nbitOrSplitDepth})
stubRpc.SetResponse(fdgAddr, methodSplitDepth, rpcblock.Latest, nil, []interface{}{nbitOrSplitDepth})
game, err := NewFaultDisputeGameContract(context.Background(), contractMetrics.NoopContractMetrics, fdgAddr, caller)
require.NoError(t, err)
return stubRpc, game
Expand Down Expand Up @@ -874,6 +863,7 @@ func TestGetAllClaimsWithSubValues(t *testing.T) {
attackBranch := big.NewInt(0)
parent := faultTypes.Claim{ClaimData: faultTypes.ClaimData{Value: common.Hash{0xbb}, Position: parentPos}, ContractIndex: 111}
stubRpc.SetResponse(fdgAddr, methodNBits, block, nil, []interface{}{new(big.Int).SetUint64(nBits)})
stubRpc.SetResponse(fdgAddr, methodSplitDepth, block, nil, []interface{}{new(big.Int).SetUint64(nBits)})
stubRpc.SetResponse(fdgAddr, methodRequiredBond, block, []interface{}{parent.Position.MoveN(nBits, attackBranch.Uint64()).ToGIndex()}, []interface{}{bond})
stubRpc.SetResponse(fdgAddr, methodAttackV2, block, []interface{}{parent.Value, big.NewInt(111), attackBranch, daType, claimsBytes[:]}, nil)
txCandidate, err := game.AttackV2Tx(context.Background(), parent, attackBranch.Uint64(), daType.Uint64(), claimsBytes[:])
Expand All @@ -886,10 +876,8 @@ func TestGetAllClaimsWithSubValues(t *testing.T) {
Value: big.NewInt(111),
Data: txCandidate.TxData,
})
packed, err := tx.MarshalBinary()
require.NoError(t, err)
txHash := tx.Hash()
stubRpc.SetGetTxByHashResponse(txHash, packed)
stubRpc.SetGetTxByHashResponse(txHash, tx)

// mock eventLog
eventName := eventMove
Expand All @@ -915,7 +903,7 @@ func TestGetAllClaimsWithSubValues(t *testing.T) {
},
}

stubRpc.SetFilterLogResponse(topics, fdgAddr, block, out)
stubRpc.SetFilterLogResponse(topics, []common.Address{fdgAddr}, block, out)
stubRpc.SetResponse(fdgAddr, methodClaimCount, block, nil, []interface{}{big.NewInt(1)})
stubRpc.SetResponse(fdgAddr, methodMaxAttackBranch, block, nil, []interface{}{big.NewInt(1<<nBits - 1)})
claim0 := faultTypes.Claim{
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
71 changes: 52 additions & 19 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) {
t.Run("stepV2", 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
Loading
Loading