Commit 4e2fdf37 authored by clabby's avatar clabby Committed by GitHub

feat(op-e2e): Kona FPP actions test adapter (#11936)

* feat(op-e2e): Kona FPP actions test adapter

* rebase

* lint

* review

* fix result check
parent 994f6347
......@@ -77,7 +77,7 @@ func RegisterGameTypes(
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) {
registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaServerExecutor()))
registerTasks = append(registerTasks, NewAsteriscKonaRegisterTask(faultTypes.AsteriscKonaGameType, cfg, m, vm.NewKonaExecutor()))
}
if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) {
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType))
......
......@@ -8,35 +8,52 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
)
type KonaServerExecutor struct{}
type KonaExecutor struct {
nativeMode bool
clientBinPath string
}
var _ OracleServerExecutor = (*KonaServerExecutor)(nil)
var _ OracleServerExecutor = (*KonaExecutor)(nil)
func NewKonaServerExecutor() *KonaServerExecutor {
return &KonaServerExecutor{}
func NewKonaExecutor() *KonaExecutor {
return &KonaExecutor{nativeMode: false}
}
func (s *KonaServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
if cfg.Network == "" {
return nil, errors.New("network is not defined")
}
func NewNativeKonaExecutor(clientBinPath string) *KonaExecutor {
return &KonaExecutor{nativeMode: true, clientBinPath: clientBinPath}
}
chainCfg := chaincfg.ChainByName(cfg.Network)
func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
args := []string{
cfg.Server, "--server",
cfg.Server,
"--l1-node-address", cfg.L1,
"--l1-beacon-address", cfg.L1Beacon,
"--l2-node-address", cfg.L2,
"--data-dir", dataDir,
"--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10),
"--l1-head", inputs.L1Head.Hex(),
"--l2-head", inputs.L2Head.Hex(),
"--l2-output-root", inputs.L2OutputRoot.Hex(),
"--l2-claim", inputs.L2Claim.Hex(),
"--l2-block-number", inputs.L2BlockNumber.Text(10),
"-v",
}
if s.nativeMode {
args = append(args, "--exec", s.clientBinPath)
} else {
args = append(args, "--server")
args = append(args, "--data-dir", dataDir)
}
if cfg.RollupConfigPath != "" {
args = append(args, "--rollup-config-path", cfg.RollupConfigPath)
args = append(args, "--l2-chain-id", "0")
} else {
if cfg.Network == "" {
return nil, errors.New("network is not defined")
}
chainCfg := chaincfg.ChainByName(cfg.Network)
args = append(args, "--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10))
}
return args, nil
......
......@@ -26,7 +26,7 @@ func TestKonaFillHostCommand(t *testing.T) {
L2Claim: common.Hash{0x44},
L2BlockNumber: big.NewInt(3333),
}
vmConfig := NewKonaServerExecutor()
vmConfig := NewKonaExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err)
......
......@@ -46,7 +46,7 @@ func createTraceProvider(
prestateProvider := vm.NewPrestateProvider(prestate, stateConverter)
return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil
case types.TraceTypeAsteriscKona:
vmConfig := vm.NewKonaServerExecutor()
vmConfig := vm.NewKonaExecutor()
stateConverter := asterisc.NewStateConverter()
prestate, err := getPrestate(prestateHash, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter)
if err != nil {
......
......@@ -52,7 +52,11 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner {
}
}
func (s *L1Miner) BlobStore() prefetcher.L1BlobSource {
func (s *L1Miner) BlobSource() prefetcher.L1BlobSource {
return s.blobStore
}
func (s *L1Miner) BlobStore() *e2eutils.BlobsStore {
return s.blobStore
}
......
......@@ -67,6 +67,8 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica {
Name: "l1-geth",
WSHost: "127.0.0.1",
WSPort: 0,
HTTPHost: "127.0.0.1",
HTTPPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
DataDir: "", // in-memory
......
......@@ -93,6 +93,8 @@ func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, o
Name: "l2-geth",
WSHost: "127.0.0.1",
WSPort: 0,
HTTPHost: "127.0.0.1",
HTTPPort: 0,
AuthAddr: "127.0.0.1",
AuthPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
......
......@@ -8,6 +8,7 @@ import (
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon"
"github.com/ethereum-optimism/optimism/op-program/host"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore"
......@@ -155,7 +156,21 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlock
apply(fixtureInputs)
}
// Run the fault proof program from the state transition from L2 block 0 -> 1.
// Run the fault proof program from the state transition from L2 block l2ClaimBlockNum - 1 -> l2ClaimBlockNum.
workDir := t.TempDir()
if IsKonaConfigured() {
fakeBeacon := fakebeacon.NewBeacon(
env.log,
env.Miner.BlobStore(),
env.sd.L1Cfg.Timestamp,
12,
)
require.NoError(t, fakeBeacon.Start("127.0.0.1:0"))
defer fakeBeacon.Close()
err = RunKonaNative(t, workDir, env, env.Miner.HTTPEndpoint(), fakeBeacon.BeaconAddr(), env.Engine.HTTPEndpoint(), *fixtureInputs)
checkResult(t, err)
} else {
programCfg := NewOpProgramCfg(
t,
env,
......@@ -164,7 +179,7 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlock
withInProcessPrefetcher := host.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (host.Prefetcher, error) {
// Set up in-process L1 sources
l1Cl := env.Miner.L1Client(t, env.sd.RollupCfg)
l1BlobFetcher := env.Miner.BlobStore()
l1BlobFetcher := env.Miner.BlobSource()
// Set up in-process L2 source
l2ClCfg := sources.L2ClientDefaultConfig(env.sd.RollupCfg, true)
......@@ -176,7 +191,9 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlock
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil
})
err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher)
tryDumpTestFixture(t, err, t.Name(), env, programCfg)
checkResult(t, err)
}
tryDumpTestFixture(t, err, t.Name(), env, *fixtureInputs, workDir)
}
type TestParam func(p *e2eutils.TestParams)
......
......@@ -12,7 +12,6 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common"
"github.com/naoina/toml"
"github.com/stretchr/testify/require"
......@@ -48,7 +47,14 @@ type FixtureInputs struct {
// Dumps a `fp-tests` test fixture to disk if the `OP_E2E_DUMP_FIXTURES` environment variable is set.
//
// [fp-tests]: https://github.com/ethereum-optimism/fp-tests
func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2FaultProofEnv, programCfg *config.Config) {
func tryDumpTestFixture(
t helpers.Testing,
result error,
name string,
env *L2FaultProofEnv,
inputs FixtureInputs,
workDir string,
) {
if !dumpFixtures {
return
}
......@@ -69,14 +75,7 @@ func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2Fau
fixture := TestFixture{
Name: name,
ExpectedStatus: expectedStatus,
Inputs: FixtureInputs{
L2BlockNumber: programCfg.L2ClaimBlockNumber,
L2Claim: programCfg.L2Claim,
L2Head: programCfg.L2Head,
L2OutputRoot: programCfg.L2OutputRoot,
L2ChainID: env.sd.RollupCfg.L2ChainID.Uint64(),
L1Head: programCfg.L1Head,
},
Inputs: inputs,
}
fixturePath := filepath.Join(fixtureDir, name)
......@@ -100,7 +99,7 @@ func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2Fau
require.NoError(t, os.WriteFile(rollupPath, serRollup, fs.ModePerm), "failed to write rollup")
// Copy the witness database into the fixture directory.
cmd := exec.Command("cp", "-r", programCfg.DataDir, filepath.Join(fixturePath, "witness-db"))
cmd := exec.Command("cp", "-r", workDir, filepath.Join(fixturePath, "witness-db"))
require.NoError(t, cmd.Run(), "Failed to copy witness DB")
// Compress the genesis file.
......
package helpers
import (
"encoding/json"
"fmt"
"io/fs"
"math/big"
"os"
"os/exec"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/utils"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/vm"
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/stretchr/testify/require"
)
var konaHostPath, konaClientPath string
func init() {
konaHostPath = os.Getenv("KONA_HOST_PATH")
konaClientPath = os.Getenv("KONA_CLIENT_PATH")
}
func IsKonaConfigured() bool {
return konaHostPath != "" && konaClientPath != ""
}
func RunKonaNative(
t helpers.Testing,
workDir string,
env *L2FaultProofEnv,
l1Rpc string,
l1BeaconRpc string,
l2Rpc string,
fixtureInputs FixtureInputs,
) error {
// Write rollup config to tempdir.
rollupConfigPath := filepath.Join(workDir, "rollup.json")
ser, err := json.Marshal(env.sd.RollupCfg)
require.NoError(t, err)
require.NoError(t, os.WriteFile(rollupConfigPath, ser, fs.ModePerm))
// Run the fault proof program from the state transition from L2 block L2Blocknumber - 1 -> L2BlockNumber.
vmCfg := vm.Config{
L1: l1Rpc,
L1Beacon: l1BeaconRpc,
L2: l2Rpc,
RollupConfigPath: rollupConfigPath,
Server: konaHostPath,
}
inputs := utils.LocalGameInputs{
L1Head: fixtureInputs.L1Head,
L2Head: fixtureInputs.L2Head,
L2OutputRoot: fixtureInputs.L2OutputRoot,
L2Claim: fixtureInputs.L2Claim,
L2BlockNumber: big.NewInt(int64(fixtureInputs.L2BlockNumber)),
}
hostCmd, err := vm.NewNativeKonaExecutor(konaClientPath).OracleCommand(vmCfg, workDir, inputs)
require.NoError(t, err)
cmd := exec.Command(hostCmd[0], hostCmd[1:]...)
cmd.Dir = workDir
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
status := cmd.Run()
switch status := status.(type) {
case *exec.ExitError:
if status.ExitCode() == 1 {
return claim.ErrClaimNotValid
}
return fmt.Errorf("kona exited with status %d", status.ExitCode())
default:
return status
}
}
......@@ -5,6 +5,7 @@ import (
actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
"github.com/ethereum-optimism/optimism/op-e2e/actions/proofs/helpers"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
......@@ -63,7 +64,7 @@ func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) {
nil,
helpers.LatestForkOnly,
runSequenceWindowExpireTest,
helpers.ExpectNoError(),
helpers.ExpectError(claim.ErrClaimNotValid),
helpers.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