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 (
"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/hexutil"
"github.com/stretchr/testify/require"
)
......@@ -20,26 +19,13 @@ import (
// 4. Submit the channel frame data across 2 transactions.
// 5. Instruct the sequencer to derive the L2 chain.
// 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)
tp := NewTestParams(func(tp *e2eutils.TestParams) {
// Set the channel timeout to 10 blocks, 12x lower than the sequencing window.
tp.ChannelTimeout = 10
})
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)
env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
const NumL2Blocks = 10
......@@ -119,24 +105,26 @@ func runChannelTimeoutTest(gt *testing.T, checkResult func(gt *testing.T, err er
require.EqualValues(t, NumL2Blocks, l2SafeHead.Number.Uint64())
// Run the FPP on L2 block # NumL2Blocks/2.
err := env.RunFaultProofProgram(t, NumL2Blocks/2, inputParams...)
checkResult(gt, err)
env.RunFaultProofProgram(t, NumL2Blocks/2, testCfg.CheckResult, testCfg.InputParams...)
}
func Test_ProgramAction_ChannelTimeout_HonestClaim_Granite(gt *testing.T) {
runChannelTimeoutTest(gt, func(gt *testing.T, err error) {
require.NoError(gt, err, "fault proof program should have succeeded")
})
}
func Test_ProgramAction_ChannelTimeout(gt *testing.T) {
matrix := NewMatrix[any]()
defer matrix.Run(gt)
func Test_ProgramAction_ChannelTimeout_JunkClaim_Granite(gt *testing.T) {
runChannelTimeoutTest(
gt,
func(gt *testing.T, err error) {
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed")
},
func(f *FixtureInputs) {
f.L2Claim = common.HexToHash("0xdeadbeef")
},
matrix.AddTestCase(
"HonestClaim",
nil,
LatestForkOnly,
runChannelTimeoutTest,
ExpectNoError(),
)
matrix.AddTestCase(
"JunkClaim",
nil,
LatestForkOnly,
runChannelTimeoutTest,
ExpectError(claim.ErrClaimNotValid),
WithL2Claim(common.HexToHash("0xdeadbeef")),
)
}
......@@ -16,6 +16,7 @@ import (
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"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/log"
"github.com/stretchr/testify/require"
......@@ -34,8 +35,30 @@ type L2FaultProofEnv struct {
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)
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)
jwtPath := e2eutils.WriteDefaultJWT(t)
......@@ -92,7 +115,27 @@ func NewL2FaultProofEnv(t actions.Testing, tp *e2eutils.TestParams, dp *e2eutils
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.
preRoot, err := env.sequencer.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum-1)
require.NoError(t, err)
......@@ -134,7 +177,6 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t actions.Testing, l2ClaimBlock
})
err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher)
tryDumpTestFixture(t, err, t.Name(), env, programCfg)
return err
}
type TestParam func(p *e2eutils.TestParams)
......
......@@ -7,6 +7,8 @@ import (
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"
"github.com/ethereum-optimism/optimism/op-e2e/actions"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
......@@ -51,6 +53,7 @@ func tryDumpTestFixture(t actions.Testing, result error, name string, env *L2Fau
return
}
name = convertToKebabCase(name)
rollupCfg := env.sd.RollupCfg
l2Genesis := env.sd.L2Cfg
......@@ -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, 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
import (
"fmt"
"testing"
"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/hexutil"
"github.com/stretchr/testify/require"
)
......@@ -25,26 +25,13 @@ var garbageKinds = []actions.GarbageKind{
//
// channel format ([]Frame):
// [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)
tp := NewTestParams(func(tp *e2eutils.TestParams) {
// Set the channel timeout to 10 blocks, 12x lower than the sequencing window.
tp.ChannelTimeout = 10
})
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)
env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
includeBatchTx := func(env *L2FaultProofEnv) {
// 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
expectedSecondFrame := env.batcher.ReadNextOutputFrame(t)
// 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
includeBatchTx(env)
......@@ -108,37 +95,28 @@ func runGarbageChannelTest(gt *testing.T, garbageKind actions.GarbageKind, check
require.Equal(t, uint64(NumL2Blocks), l2SafeHead.Number.Uint64())
// Run the FPP on L2 block # NumL2Blocks.
err := env.RunFaultProofProgram(t, NumL2Blocks, inputParams...)
checkResult(gt, err)
env.RunFaultProofProgram(t, NumL2Blocks, testCfg.CheckResult, testCfg.InputParams...)
}
func Test_ProgramAction_GarbageChannel_HonestClaim_Granite(gt *testing.T) {
func Test_ProgramAction_GarbageChannel(gt *testing.T) {
matrix := NewMatrix[actions.GarbageKind]()
defer matrix.Run(gt)
for _, garbageKind := range garbageKinds {
gt.Run(garbageKind.String(), func(t *testing.T) {
runGarbageChannelTest(
t,
matrix.AddTestCase(
fmt.Sprintf("HonestClaim-%s", garbageKind.String()),
garbageKind,
func(gt *testing.T, err error) {
require.NoError(gt, err, "fault proof program should not have failed")
},
LatestForkOnly,
runGarbageChannelTest,
ExpectNoError(),
)
})
}
}
func Test_ProgramAction_GarbageChannel_JunkClaim_Granite(gt *testing.T) {
for _, garbageKind := range garbageKinds {
gt.Run(garbageKind.String(), func(t *testing.T) {
runGarbageChannelTest(
t,
matrix.AddTestCase(
fmt.Sprintf("JunkClaim-%s", garbageKind.String()),
garbageKind,
func(gt *testing.T, err error) {
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed")
},
func(f *FixtureInputs) {
f.L2Claim = common.HexToHash("0xdeadbeef")
},
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 (
"testing"
"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/hexutil"
"github.com/stretchr/testify/require"
)
// 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)
tp := NewTestParams()
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)
env := NewL2FaultProofEnv(t, testCfg, tp, NewBatcherCfg())
// Mine an empty block for gas estimation purposes.
env.miner.ActEmptyBlock(t)
......@@ -59,24 +43,26 @@ func runSequenceWindowExpireTest(gt *testing.T, checkResult func(gt *testing.T,
require.Greater(t, l2SafeHead.Number.Uint64(), uint64(0))
// Run the FPP on one of the auto-derived blocks.
err := env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, inputParams...)
checkResult(gt, err)
env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64()/2, testCfg.CheckResult, testCfg.InputParams...)
}
func Test_ProgramAction_SequenceWindowExpired_HonestClaim_Granite(gt *testing.T) {
runSequenceWindowExpireTest(gt, func(gt *testing.T, err error) {
require.NoError(gt, err, "fault proof program should have succeeded")
})
}
func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) {
matrix := NewMatrix[any]()
defer matrix.Run(gt)
func Test_ProgramAction_SequenceWindowExpired_JunkClaim_Granite(gt *testing.T) {
runSequenceWindowExpireTest(
gt,
func(gt *testing.T, err error) {
require.ErrorIs(gt, err, claim.ErrClaimNotValid, "fault proof program should have failed")
},
func(f *FixtureInputs) {
f.L2Claim = common.HexToHash("0xdeadbeef")
},
matrix.AddTestCase(
"HonestClaim",
nil,
LatestForkOnly,
runSequenceWindowExpireTest,
ExpectNoError(),
)
matrix.AddTestCase(
"JunkClaim",
nil,
LatestForkOnly,
runSequenceWindowExpireTest,
ExpectNoError(),
WithL2Claim(common.HexToHash("0xdeadbeef")),
)
}
......@@ -4,29 +4,14 @@ import (
"testing"
"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/hexutil"
"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)
tp := NewTestParams()
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)
env := NewL2FaultProofEnv(t, testCfg, NewTestParams(), NewBatcherCfg())
// Build an empty block on L2
env.sequencer.ActL2StartBlock(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.
require.Equal(t, uint64(1), l2SafeHead.Number.Uint64())
err := env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64())
require.NoError(t, err, "fault proof program failed")
env.RunFaultProofProgram(t, l2SafeHead.Number.Uint64(), testCfg.CheckResult, testCfg.InputParams...)
}
func Test_ProgramAction_SimpleEmptyChain_JunkClaim_Granite(gt *testing.T) {
t := actions.NewDefaultTesting(gt)
tp := NewTestParams()
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
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")
func Test_ProgramAction_SimpleEmptyChain(gt *testing.T) {
matrix := NewMatrix[any]()
defer matrix.Run(gt)
matrix.AddTestCase(
"HonestClaim",
nil,
LatestForkOnly,
runSimpleProgramTest,
ExpectNoError(),
)
matrix.AddTestCase(
"JunkClaim",
nil,
LatestForkOnly,
runSimpleProgramTest,
ExpectError(claim.ErrClaimNotValid),
WithL2Claim(common.HexToHash("0xdeadbeef")),
)
}
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