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( ...@@ -77,7 +77,7 @@ func RegisterGameTypes(
registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor())) registerTasks = append(registerTasks, NewAsteriscRegisterTask(faultTypes.AsteriscGameType, cfg, m, vm.NewOpProgramServerExecutor()))
} }
if cfg.TraceTypeEnabled(faultTypes.TraceTypeAsteriscKona) { 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) { if cfg.TraceTypeEnabled(faultTypes.TraceTypeFast) {
registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType)) registerTasks = append(registerTasks, NewAlphabetRegisterTask(faultTypes.FastGameType))
......
...@@ -8,35 +8,52 @@ import ( ...@@ -8,35 +8,52 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg" "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 { func NewKonaExecutor() *KonaExecutor {
return &KonaServerExecutor{} return &KonaExecutor{nativeMode: false}
} }
func (s *KonaServerExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) { func NewNativeKonaExecutor(clientBinPath string) *KonaExecutor {
if cfg.Network == "" { return &KonaExecutor{nativeMode: true, clientBinPath: clientBinPath}
return nil, errors.New("network is not defined") }
}
chainCfg := chaincfg.ChainByName(cfg.Network) func (s *KonaExecutor) OracleCommand(cfg Config, dataDir string, inputs utils.LocalGameInputs) ([]string, error) {
args := []string{ args := []string{
cfg.Server, "--server", cfg.Server,
"--l1-node-address", cfg.L1, "--l1-node-address", cfg.L1,
"--l1-beacon-address", cfg.L1Beacon, "--l1-beacon-address", cfg.L1Beacon,
"--l2-node-address", cfg.L2, "--l2-node-address", cfg.L2,
"--data-dir", dataDir,
"--l2-chain-id", strconv.FormatUint(chainCfg.ChainID, 10),
"--l1-head", inputs.L1Head.Hex(), "--l1-head", inputs.L1Head.Hex(),
"--l2-head", inputs.L2Head.Hex(), "--l2-head", inputs.L2Head.Hex(),
"--l2-output-root", inputs.L2OutputRoot.Hex(), "--l2-output-root", inputs.L2OutputRoot.Hex(),
"--l2-claim", inputs.L2Claim.Hex(), "--l2-claim", inputs.L2Claim.Hex(),
"--l2-block-number", inputs.L2BlockNumber.Text(10), "--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 != "" { if cfg.RollupConfigPath != "" {
args = append(args, "--rollup-config-path", 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 return args, nil
......
...@@ -26,7 +26,7 @@ func TestKonaFillHostCommand(t *testing.T) { ...@@ -26,7 +26,7 @@ func TestKonaFillHostCommand(t *testing.T) {
L2Claim: common.Hash{0x44}, L2Claim: common.Hash{0x44},
L2BlockNumber: big.NewInt(3333), L2BlockNumber: big.NewInt(3333),
} }
vmConfig := NewKonaServerExecutor() vmConfig := NewKonaExecutor()
args, err := vmConfig.OracleCommand(cfg, dir, inputs) args, err := vmConfig.OracleCommand(cfg, dir, inputs)
require.NoError(t, err) require.NoError(t, err)
......
...@@ -46,7 +46,7 @@ func createTraceProvider( ...@@ -46,7 +46,7 @@ func createTraceProvider(
prestateProvider := vm.NewPrestateProvider(prestate, stateConverter) prestateProvider := vm.NewPrestateProvider(prestate, stateConverter)
return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil return asterisc.NewTraceProvider(logger, m, cfg.Asterisc, vmConfig, prestateProvider, prestate, localInputs, dir, 42), nil
case types.TraceTypeAsteriscKona: case types.TraceTypeAsteriscKona:
vmConfig := vm.NewKonaServerExecutor() vmConfig := vm.NewKonaExecutor()
stateConverter := asterisc.NewStateConverter() stateConverter := asterisc.NewStateConverter()
prestate, err := getPrestate(prestateHash, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter) prestate, err := getPrestate(prestateHash, cfg.AsteriscKonaAbsolutePreStateBaseURL, cfg.AsteriscKonaAbsolutePreState, dir, stateConverter)
if err != nil { if err != nil {
......
...@@ -52,7 +52,11 @@ func NewL1Miner(t Testing, log log.Logger, genesis *core.Genesis) *L1Miner { ...@@ -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 return s.blobStore
} }
......
...@@ -67,6 +67,8 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica { ...@@ -67,6 +67,8 @@ func NewL1Replica(t Testing, log log.Logger, genesis *core.Genesis) *L1Replica {
Name: "l1-geth", Name: "l1-geth",
WSHost: "127.0.0.1", WSHost: "127.0.0.1",
WSPort: 0, WSPort: 0,
HTTPHost: "127.0.0.1",
HTTPPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, HTTPModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
DataDir: "", // in-memory DataDir: "", // in-memory
......
...@@ -93,6 +93,8 @@ func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, o ...@@ -93,6 +93,8 @@ func newBackend(t e2eutils.TestingBase, genesis *core.Genesis, jwtPath string, o
Name: "l2-geth", Name: "l2-geth",
WSHost: "127.0.0.1", WSHost: "127.0.0.1",
WSPort: 0, WSPort: 0,
HTTPHost: "127.0.0.1",
HTTPPort: 0,
AuthAddr: "127.0.0.1", AuthAddr: "127.0.0.1",
AuthPort: 0, AuthPort: 0,
WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"}, WSModules: []string{"debug", "admin", "eth", "txpool", "net", "rpc", "web3", "personal"},
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags" 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/actions/helpers"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "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"
"github.com/ethereum-optimism/optimism/op-program/host/config" "github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/kvstore" "github.com/ethereum-optimism/optimism/op-program/host/kvstore"
...@@ -155,28 +156,44 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlock ...@@ -155,28 +156,44 @@ func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlock
apply(fixtureInputs) 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.
programCfg := NewOpProgramCfg( workDir := t.TempDir()
t, if IsKonaConfigured() {
env, fakeBeacon := fakebeacon.NewBeacon(
fixtureInputs, env.log,
) env.Miner.BlobStore(),
withInProcessPrefetcher := host.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (host.Prefetcher, error) { env.sd.L1Cfg.Timestamp,
// Set up in-process L1 sources 12,
l1Cl := env.Miner.L1Client(t, env.sd.RollupCfg) )
l1BlobFetcher := env.Miner.BlobStore() require.NoError(t, fakeBeacon.Start("127.0.0.1:0"))
defer fakeBeacon.Close()
// Set up in-process L2 source
l2ClCfg := sources.L2ClientDefaultConfig(env.sd.RollupCfg, true) err = RunKonaNative(t, workDir, env, env.Miner.HTTPEndpoint(), fakeBeacon.BeaconAddr(), env.Engine.HTTPEndpoint(), *fixtureInputs)
l2RPC := env.Engine.RPCClient() checkResult(t, err)
l2Client, err := host.NewL2Client(l2RPC, env.log, nil, &host.L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head}) } else {
require.NoError(t, err, "failed to create L2 client") programCfg := NewOpProgramCfg(
l2DebugCl := &host.L2Source{L2Client: l2Client, DebugClient: sources.NewDebugClient(l2RPC.CallContext)} t,
env,
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil fixtureInputs,
}) )
err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher) withInProcessPrefetcher := host.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (host.Prefetcher, error) {
tryDumpTestFixture(t, err, t.Name(), env, programCfg) // Set up in-process L1 sources
l1Cl := env.Miner.L1Client(t, env.sd.RollupCfg)
l1BlobFetcher := env.Miner.BlobSource()
// Set up in-process L2 source
l2ClCfg := sources.L2ClientDefaultConfig(env.sd.RollupCfg, true)
l2RPC := env.Engine.RPCClient()
l2Client, err := host.NewL2Client(l2RPC, env.log, nil, &host.L2ClientConfig{L2ClientConfig: l2ClCfg, L2Head: cfg.L2Head})
require.NoError(t, err, "failed to create L2 client")
l2DebugCl := &host.L2Source{L2Client: l2Client, DebugClient: sources.NewDebugClient(l2RPC.CallContext)}
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2DebugCl, kv), nil
})
err = host.FaultProofProgram(t.Ctx(), env.log, programCfg, withInProcessPrefetcher)
checkResult(t, err)
}
tryDumpTestFixture(t, err, t.Name(), env, *fixtureInputs, workDir)
} }
type TestParam func(p *e2eutils.TestParams) type TestParam func(p *e2eutils.TestParams)
......
...@@ -12,7 +12,6 @@ import ( ...@@ -12,7 +12,6 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" "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/client/claim"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/naoina/toml" "github.com/naoina/toml"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
...@@ -48,7 +47,14 @@ type FixtureInputs struct { ...@@ -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. // 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 // [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 { if !dumpFixtures {
return return
} }
...@@ -69,14 +75,7 @@ func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2Fau ...@@ -69,14 +75,7 @@ func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2Fau
fixture := TestFixture{ fixture := TestFixture{
Name: name, Name: name,
ExpectedStatus: expectedStatus, ExpectedStatus: expectedStatus,
Inputs: FixtureInputs{ Inputs: inputs,
L2BlockNumber: programCfg.L2ClaimBlockNumber,
L2Claim: programCfg.L2Claim,
L2Head: programCfg.L2Head,
L2OutputRoot: programCfg.L2OutputRoot,
L2ChainID: env.sd.RollupCfg.L2ChainID.Uint64(),
L1Head: programCfg.L1Head,
},
} }
fixturePath := filepath.Join(fixtureDir, name) fixturePath := filepath.Join(fixtureDir, name)
...@@ -100,7 +99,7 @@ func tryDumpTestFixture(t helpers.Testing, result error, name string, env *L2Fau ...@@ -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") require.NoError(t, os.WriteFile(rollupPath, serRollup, fs.ModePerm), "failed to write rollup")
// Copy the witness database into the fixture directory. // 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") require.NoError(t, cmd.Run(), "Failed to copy witness DB")
// Compress the genesis file. // 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 ( ...@@ -5,6 +5,7 @@ import (
actionsHelpers "github.com/ethereum-optimism/optimism/op-e2e/actions/helpers" 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-e2e/actions/proofs/helpers"
"github.com/ethereum-optimism/optimism/op-program/client/claim"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -63,7 +64,7 @@ func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) { ...@@ -63,7 +64,7 @@ func Test_ProgramAction_SequenceWindowExpired(gt *testing.T) {
nil, nil,
helpers.LatestForkOnly, helpers.LatestForkOnly,
runSequenceWindowExpireTest, runSequenceWindowExpireTest,
helpers.ExpectNoError(), helpers.ExpectError(claim.ErrClaimNotValid),
helpers.WithL2Claim(common.HexToHash("0xdeadbeef")), 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