Commit 8b61225d authored by clabby's avatar clabby Committed by GitHub

feat: `op-program` actor test API improvements (#11903)

* feat: `op-program` actor test API improvements

* lint

* sort fix

* rebase
parent 0b20d8eb
...@@ -7,7 +7,6 @@ import ( ...@@ -7,7 +7,6 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/client/claim" "github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -20,26 +19,13 @@ import ( ...@@ -20,26 +19,13 @@ import (
// 4. Submit the channel frame data across 2 transactions. // 4. Submit the channel frame data across 2 transactions.
// 5. Instruct the sequencer to derive the L2 chain. // 5. Instruct the sequencer to derive the L2 chain.
// 6. Run the FPP on the safe head. // 6. Run the FPP on the safe head.
func runChannelTimeoutTest(gt *testing.T, checkResult func(gt *testing.T, err error), inputParams ...FixtureInputParam) { func runChannelTimeoutTest(gt *testing.T, testCfg *TestCfg[any]) {
t := actions.NewDefaultTesting(gt) t := actions.NewDefaultTesting(gt)
tp := NewTestParams(func(tp *e2eutils.TestParams) { tp := NewTestParams(func(tp *e2eutils.TestParams) {
// Set the channel timeout to 10 blocks, 12x lower than the sequencing window. // Set the channel timeout to 10 blocks, 12x lower than the sequencing window.
tp.ChannelTimeout = 10 tp.ChannelTimeout = 10
}) })
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) { env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
const NumL2Blocks = 10 const NumL2Blocks = 10
...@@ -119,24 +105,26 @@ func runChannelTimeoutTest(gt *testing.T, checkResult func(gt *testing.T, err er ...@@ -119,24 +105,26 @@ func runChannelTimeoutTest(gt *testing.T, checkResult func(gt *testing.T, err er
require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64()) require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64())
// Run the FPP on L2 block # NumL2Blocks/2. // Run the FPP on L2 block # NumL2Blocks/2.
err := env.RunFaultProofProgram(t, NumL2Blocks/2, inputParams...) env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...)
checkResult(gt, err)
} }
func Test_ProgramAction_ChannelTimeout_HonestClaim_Granite(gt *testing.T) { func Test_ProgramAction_ChannelTimeout(gt *testing.T) {
runChannelTimeoutTest(gt, func(gt *testing.T, err error) { matrix := NewMatrix[any]()
require.NoError(gt, err, "fault proof program should have succeeded") defer matrix.Run(gt)
})
}
func Test_ProgramAction_ChannelTimeout_JunkClaim_Granite(gt *testing.T) { matrix.AddTestCase(
runChannelTimeoutTest( "HonestClaim",
gt, nil,
func(gt *testing.T, err error) { LatestForkOnly,
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed") runChannelTimeoutTest,
}, ExpectNoError(),
func(f *FixtureInputs) { )
f.L2Claim = common.HexToHash("0xdeadbeef") matrix.AddTestCase(
}, "JunkClaim",
nil,
LatestForkOnly,
runChannelTimeoutTest,
ExpectError(claim.ErrClaimNotValid),
WithL2Claim(common.HexToHash("0xdeadbeef")),
) )
} }
...@@ -16,6 +16,7 @@ import ( ...@@ -16,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/sources" "github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog" "github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -34,8 +35,30 @@ type L2FaultProofEnv struct { ...@@ -34,8 +35,30 @@ type L2FaultProofEnv struct {
alice *actions.CrossLayerUser alice *actions.CrossLayerUser
} }
func NewL2FaultProofEnv(t actions.Testing, tp *e2eutils.TestParams, dp *e2eutils.DeployParams, batcherCfg *actions.BatcherCfg) *L2FaultProofEnv { func NewL2FaultProofEnv[c any](t actions.Testing, testCfg *TestCfg[c], tp *e2eutils.TestParams, batcherCfg *actions.BatcherCfg) *L2FaultProofEnv {
log := testlog.Logger(t, log.LvlDebug) log := testlog.Logger(t, log.LvlDebug)
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) {
genesisBlock := hexutil.Uint64(0)
// Enable cancun always
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
// Enable L2 feature.
switch testCfg.Hardfork {
case Regolith:
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
case Canyon:
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
case Delta:
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
case Ecotone:
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
case Fjord:
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
case Granite:
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
}
})
sd := e2eutils.Setup(t, dp, actions.DefaultAlloc) sd := e2eutils.Setup(t, dp, actions.DefaultAlloc)
jwtPath := e2eutils.WriteDefaultJWT(t) jwtPath := e2eutils.WriteDefaultJWT(t)
...@@ -92,7 +115,27 @@ func NewL2FaultProofEnv(t actions.Testing, tp *e2eutils.TestParams, dp *e2eutils ...@@ -92,7 +115,27 @@ func NewL2FaultProofEnv(t actions.Testing, tp *e2eutils.TestParams, dp *e2eutils
type FixtureInputParam func(f *FixtureInputs) type FixtureInputParam func(f *FixtureInputs)
func (env *L2FaultProofEnv) RunFaultProofProgram(t actions.Testing, l2ClaimBlockNum uint64, fixtureInputParams ...FixtureInputParam) error { type CheckResult func(actions.Testing, error)
func ExpectNoError() CheckResult {
return func(t actions.Testing, err error) {
require.NoError(t, err, "fault proof program should have succeeded")
}
}
func ExpectError(expectedErr error) CheckResult {
return func(t actions.Testing, err error) {
require.ErrorIs(t, err, expectedErr, "fault proof program should have failed with expected error")
}
}
func WithL2Claim(claim common.Hash) FixtureInputParam {
return func(f *FixtureInputs) {
f.L2Claim = claim
}
}
func (env *L2FaultProofEnv) RunFaultProofProgram(t actions.Testing, l2ClaimBlockNum uint64, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) {
// Fetch the pre and post output roots for the fault proof. // Fetch the pre and post output roots for the fault proof.
preRoot, err := env.sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum-1) preRoot, err := env.sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum-1)
require.NoError(t, err) require.NoError(t, err)
...@@ -134,7 +177,6 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t actions.Testing, l2ClaimBlock ...@@ -134,7 +177,6 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t actions.Testing, l2ClaimBlock
}) })
err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher) err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher)
tryDumpTestFixture(t, err, t.Name(), env, programCfg) tryDumpTestFixture(t, err, t.Name(), env, programCfg)
return err
} }
type TestParam func(p *e2eutils.TestParams) type TestParam func(p *e2eutils.TestParams)
......
...@@ -7,6 +7,8 @@ import ( ...@@ -7,6 +7,8 @@ import (
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"regexp"
"strings"
"github.com/ethereum-optimism/optimism/op-e2e/actions" "github.com/ethereum-optimism/optimism/op-e2e/actions"
"github.com/ethereum-optimism/optimism/op-program/client/claim" "github.com/ethereum-optimism/optimism/op-program/client/claim"
...@@ -51,6 +53,7 @@ func tryDumpTestFixture(t actions.Testing, result error, name string, env *L2Fau ...@@ -51,6 +53,7 @@ func tryDumpTestFixture(t actions.Testing, result error, name string, env *L2Fau
return return
} }
name = convertToKebabCase(name)
rollupCfg := env.sd.RollupCfg rollupCfg := env.sd.RollupCfg
l2Genesis := env.sd.L2Cfg l2Genesis := env.sd.L2Cfg
...@@ -117,3 +120,17 @@ func tryDumpTestFixture(t actions.Testing, result error, name string, env *L2Fau ...@@ -117,3 +120,17 @@ func tryDumpTestFixture(t actions.Testing, result error, name string, env *L2Fau
require.NoError(t, cmd.Run(), "Failed to compress witness DB") require.NoError(t, cmd.Run(), "Failed to compress witness DB")
require.NoError(t, os.RemoveAll(filepath.Join(fixturePath, "witness-db")), "Failed to remove uncompressed witness DB") require.NoError(t, os.RemoveAll(filepath.Join(fixturePath, "witness-db")), "Failed to remove uncompressed witness DB")
} }
// Convert to lower kebab case for strings containing `/`
func convertToKebabCase(input string) string {
if !strings.Contains(input, "/") {
return input
}
// Replace non-alphanumeric characters with underscores
re := regexp.MustCompile(`[^a-zA-Z0-9]+`)
snake := re.ReplaceAllString(input, "-")
// Convert to lower case
return strings.ToLower(snake)
}
package proofs package proofs
import ( import (
"fmt"
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-e2e/actions" "github.com/ethereum-optimism/optimism/op-e2e/actions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/client/claim" "github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -25,26 +25,13 @@ var garbageKinds = []actions.GarbageKind{ ...@@ -25,26 +25,13 @@ var garbageKinds = []actions.GarbageKind{
// //
// channel format ([]Frame): // channel format ([]Frame):
// [f[0 - correct] f_x[1 - bad frame] f[1 - correct]] // [f[0 - correct] f_x[1 - bad frame] f[1 - correct]]
func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, checkResult func(gt *testing.T, err error), inputParams ...FixtureInputParam) { func runGarbageChannelTest(gt *testing.T, testCfg *TestCfg[actions.GarbageKind]) {
t := actions.NewDefaultTesting(gt) t := actions.NewDefaultTesting(gt)
tp := NewTestParams(func(tp *e2eutils.TestParams) { tp := NewTestParams(func(tp *e2eutils.TestParams) {
// Set the channel timeout to 10 blocks, 12x lower than the sequencing window. // Set the channel timeout to 10 blocks, 12x lower than the sequencing window.
tp.ChannelTimeout = 10 tp.ChannelTimeout = 10
}) })
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) { env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
includeBatchTx := func(env *L2FaultProofEnv) { includeBatchTx := func(env *L2FaultProofEnv) {
// Instruct the batcher to submit the first channel frame to L1, and include the transaction. // Instruct the batcher to submit the first channel frame to L1, and include the transaction.
...@@ -90,7 +77,7 @@ func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, check ...@@ -90,7 +77,7 @@ func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, check
expectedSecondFrame := env.batcher.ReadNextOutputFrame(t) expectedSecondFrame := env.batcher.ReadNextOutputFrame(t)
// Submit a garbage frame, modified from the expected second frame. // Submit a garbage frame, modified from the expected second frame.
env.batcher.ActL2BatchSubmitGarbageRaw(t, expectedSecondFrame, garbageKind) env.batcher.ActL2BatchSubmitGarbageRaw(t, expectedSecondFrame, testCfg.Custom)
// Include the garbage second frame tx // Include the garbage second frame tx
includeBatchTx(env) includeBatchTx(env)
...@@ -108,37 +95,28 @@ func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, check ...@@ -108,37 +95,28 @@ func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, check
require.Equal(t, uint64(NumL2Blocks), l2SafeHead.Number.Uint64()) require.Equal(t, uint64(NumL2Blocks), l2SafeHead.Number.Uint64())
// Run the FPP on L2 block # NumL2Blocks. // Run the FPP on L2 block # NumL2Blocks.
err := env.RunFaultProofProgram(t, NumL2Blocks, inputParams...) env.RunFaultProofProgram(t, NumL2Blocks, testCfg.CheckResult, testCfg.InputParams...)
checkResult(gt, err)
} }
func Test_ProgramAction_GarbageChannel_HonestClaim_Granite(gt *testing.T) { func Test_ProgramAction_GarbageChannel(gt *testing.T) {
for _, garbageKind := range garbageKinds { matrix := NewMatrix[actions.GarbageKind]()
gt.Run(garbageKind.String(), func(t *testing.T) { defer matrix.Run(gt)
runGarbageChannelTest(
t,
garbageKind,
func(gt *testing.T, err error) {
require.NoError(gt, err, "fault proof program should not have failed")
},
)
})
}
}
func Test_ProgramAction_GarbageChannel_JunkClaim_Granite(gt *testing.T) {
for _, garbageKind := range garbageKinds { for _, garbageKind := range garbageKinds {
gt.Run(garbageKind.String(), func(t *testing.T) { matrix.AddTestCase(
runGarbageChannelTest( fmt.Sprintf("HonestClaim-%s", garbageKind.String()),
t, garbageKind,
garbageKind, LatestForkOnly,
func(gt *testing.T, err error) { runGarbageChannelTest,
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed") ExpectNoError(),
}, )
func(f *FixtureInputs) { matrix.AddTestCase(
f.L2Claim = common.HexToHash("0xdeadbeef") fmt.Sprintf("JunkClaim-%s", garbageKind.String()),
}, garbageKind,
) LatestForkOnly,
}) runGarbageChannelTest,
ExpectError(claim.ErrClaimNotValid),
WithL2Claim(common.HexToHash("0xdeadbeef")),
)
} }
} }
package proofs
import (
"fmt"
"testing"
)
type RunTest[cfg any] func(t *testing.T, testCfg *TestCfg[cfg])
type TestCfg[cfg any] struct {
Hardfork *Hardfork
CheckResult CheckResult
InputParams []FixtureInputParam
Custom cfg
}
type TestCase[cfg any] struct {
Name string
Cfg cfg
ForkMatrix ForkMatrix
RunTest RunTest[cfg]
InputParams []FixtureInputParam
CheckResult CheckResult
}
type TestMatrix[cfg any] struct {
CommonInputParams []FixtureInputParam
TestCases []TestCase[cfg]
}
func (suite *TestMatrix[cfg]) Run(t *testing.T) {
for _, tc := range suite.TestCases {
for _, fork := range tc.ForkMatrix {
t.Run(fmt.Sprintf("%s-%s", tc.Name, fork.Name), func(t *testing.T) {
testCfg := &TestCfg[cfg]{
Hardfork: fork,
CheckResult: tc.CheckResult,
InputParams: append(suite.CommonInputParams, tc.InputParams...),
Custom: tc.Cfg,
}
tc.RunTest(t, testCfg)
})
}
}
}
func NewMatrix[cfg any]() *TestMatrix[cfg] {
return &TestMatrix[cfg]{}
}
func (ts *TestMatrix[cfg]) WithCommonInputParams(params ...FixtureInputParam) *TestMatrix[cfg] {
ts.CommonInputParams = params
return ts
}
func (ts *TestMatrix[cfg]) AddTestCase(
name string,
testCfg cfg,
forkMatrix ForkMatrix,
runTest RunTest[cfg],
checkResult CheckResult,
inputParams ...FixtureInputParam,
) *TestMatrix[cfg] {
ts.TestCases = append(ts.TestCases, TestCase[cfg]{
Name: name,
Cfg: testCfg,
ForkMatrix: forkMatrix,
RunTest: runTest,
InputParams: inputParams,
CheckResult: checkResult,
})
return ts
}
type Hardfork struct {
Name string
Precedence int
}
type ForkMatrix = []*Hardfork
// Hardfork definitions
var (
Regolith = &Hardfork{Name: "Regolith", Precedence: 1}
Canyon = &Hardfork{Name: "Canyon", Precedence: 2}
Delta = &Hardfork{Name: "Delta", Precedence: 3}
Fjord = &Hardfork{Name: "Fjord", Precedence: 4}
Ecotone = &Hardfork{Name: "Ecotone", Precedence: 5}
Granite = &Hardfork{Name: "Granite", Precedence: 6}
)
var Hardforks = ForkMatrix{Regolith, Canyon, Delta, Fjord, Ecotone, Granite}
var LatestForkOnly = ForkMatrix{Hardforks[len(Hardforks)-1]}
func NewForkMatrix(forks ...*Hardfork) ForkMatrix {
return append(ForkMatrix{}, forks...)
}
...@@ -4,31 +4,15 @@ import ( ...@@ -4,31 +4,15 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-e2e/actions" "github.com/ethereum-optimism/optimism/op-e2e/actions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
// Run a test that proves a deposit-only block generated due to sequence window expiry. // Run a test that proves a deposit-only block generated due to sequence window expiry.
func runSequenceWindowExpireTest(gt *testing.T, checkResult func(gt *testing.T, err error), inputParams ...FixtureInputParam) { func runSequenceWindowExpireTest(gt *testing.T, testCfg *TestCfg[any]) {
t := actions.NewDefaultTesting(gt) t := actions.NewDefaultTesting(gt)
tp := NewTestParams() tp := NewTestParams()
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) { env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
// Mine an empty block for gas estimation purposes. // Mine an empty block for gas estimation purposes.
env.miner.ActEmptyBlock(t) env.miner.ActEmptyBlock(t)
...@@ -59,24 +43,26 @@ func runSequenceWindowExpireTest(gt *testing.T, checkResult func(gt *testing.T, ...@@ -59,24 +43,26 @@ func runSequenceWindowExpireTest(gt *testing.T, checkResult func(gt *testing.T,
require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0)) require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0))
// Run the FPP on one of the auto-derived blocks. // Run the FPP on one of the auto-derived blocks.
err := env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, inputParams...) env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...)
checkResult(gt, err)
} }
func Test_ProgramAction_SequenceWindowExpired_HonestClaim_Granite(gt *testing.T) { func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) {
runSequenceWindowExpireTest(gt, func(gt *testing.T, err error) { matrix := NewMatrix[any]()
require.NoError(gt, err, "fault proof program should have succeeded") defer matrix.Run(gt)
})
}
func Test_ProgramAction_SequenceWindowExpired_JunkClaim_Granite(gt *testing.T) { matrix.AddTestCase(
runSequenceWindowExpireTest( "HonestClaim",
gt, nil,
func(gt *testing.T, err error) { LatestForkOnly,
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed") runSequenceWindowExpireTest,
}, ExpectNoError(),
func(f *FixtureInputs) { )
f.L2Claim = common.HexToHash("0xdeadbeef") matrix.AddTestCase(
}, "JunkClaim",
nil,
LatestForkOnly,
runSequenceWindowExpireTest,
ExpectNoError(),
WithL2Claim(common.HexToHash("0xdeadbeef")),
) )
} }
...@@ -4,29 +4,14 @@ import ( ...@@ -4,29 +4,14 @@ import (
"testing" "testing"
"github.com/ethereum-optimism/optimism/op-e2e/actions" "github.com/ethereum-optimism/optimism/op-e2e/actions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func Test_ProgramAction_SimpleEmptyChain_HonestClaim_Granite(gt *testing.T) { func runSimpleProgramTest(gt *testing.T, testCfg *TestCfg[any]) {
t := actions.NewDefaultTesting(gt) t := actions.NewDefaultTesting(gt)
tp := NewTestParams() env := NewL2FaultProofEnv(t, testCfg, NewTestParams(), NewBatcherCfg())
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) {
genesisBlock := hexutil.Uint64(0)
// Enable Cancun on L1 & Granite on L2 at genesis
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock
})
bCfg := NewBatcherCfg()
env := NewL2FaultProofEnv(t, tp, dp, bCfg)
// Build an empty block on L2 // Build an empty block on L2
env.sequencer.ActL2StartBlock(t) env.sequencer.ActL2StartBlock(t)
...@@ -54,56 +39,26 @@ func Test_ProgramAction_SimpleEmptyChain_HonestClaim_Granite(gt *testing.T) { ...@@ -54,56 +39,26 @@ func Test_ProgramAction_SimpleEmptyChain_HonestClaim_Granite(gt *testing.T) {
// Ensure the block is marked as safe before we attempt to fault prove it. // Ensure the block is marked as safe before we attempt to fault prove it.
require.Equal(t, uint64(1), l2SafeHead.Number.Uint64()) require.Equal(t, uint64(1), l2SafeHead.Number.Uint64())
err := env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()) env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...)
require.NoError(t, err, "fault proof program failed")
} }
func Test_ProgramAction_SimpleEmptyChain_JunkClaim_Granite(gt *testing.T) { func Test_ProgramAction_SimpleEmptyChain(gt *testing.T) {
t := actions.NewDefaultTesting(gt) matrix := NewMatrix[any]()
tp := NewTestParams() defer matrix.Run(gt)
dp := NewDeployParams(t, func(dp *e2eutils.DeployParams) {
genesisBlock := hexutil.Uint64(0) matrix.AddTestCase(
"HonestClaim",
// Enable Cancun on L1 & Granite on L2 at genesis nil,
dp.DeployConfig.L1CancunTimeOffset = &genesisBlock LatestForkOnly,
dp.DeployConfig.L2GenesisRegolithTimeOffset = &genesisBlock runSimpleProgramTest,
dp.DeployConfig.L2GenesisCanyonTimeOffset = &genesisBlock ExpectNoError(),
dp.DeployConfig.L2GenesisDeltaTimeOffset = &genesisBlock )
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock matrix.AddTestCase(
dp.DeployConfig.L2GenesisFjordTimeOffset = &genesisBlock "JunkClaim",
dp.DeployConfig.L2GenesisGraniteTimeOffset = &genesisBlock nil,
}) LatestForkOnly,
bCfg := NewBatcherCfg() runSimpleProgramTest,
env := NewL2FaultProofEnv(t, tp, dp, bCfg) ExpectError(claim.ErrClaimNotValid),
WithL2Claim(common.HexToHash("0xdeadbeef")),
// Build an empty block on L2 )
env.sequencer.ActL2StartBlock(t)
env.sequencer.ActL2EndBlock(t)
// Instruct the batcher to submit the block to L1, and include the transaction.
env.batcher.ActSubmitAll(t)
env.miner.ActL1StartBlock(12)(t)
env.miner.ActL1IncludeTxByHash(env.batcher.LastSubmitted.Hash())(t)
env.miner.ActL1EndBlock(t)
// Finalize the block with the batch on L1.
env.miner.ActL1SafeNext(t)
env.miner.ActL1FinalizeNext(t)
// Instruct the sequencer to derive the L2 chain from the data on L1 that the batcher just posted.
env.sequencer.ActL1HeadSignal(t)
env.sequencer.ActL2PipelineFull(t)
l1Head := env.miner.L1Chain().CurrentBlock()
l2SafeHead := env.engine.L2Chain().CurrentSafeBlock()
// Ensure there is only 1 block on L1.
require.Equal(t, uint64(1), l1Head.Number.Uint64())
// Ensure the block is marked as safe before we attempt to fault prove it.
require.Equal(t, uint64(1), l2SafeHead.Number.Uint64())
err := env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), func(f *FixtureInputs) {
f.L2Claim = common.HexToHash("0xdeadbeef")
})
require.Error(t, err, "fault proof program should have failed")
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment