diff --git a/anvil/anvil.go b/anvil/anvil.go index e86a23ec..893463f1 100644 --- a/anvil/anvil.go +++ b/anvil/anvil.go @@ -9,6 +9,7 @@ import ( "math/big" "os" "os/exec" + "path/filepath" "strconv" "strings" "sync/atomic" @@ -93,6 +94,8 @@ func (a *Anvil) Start(ctx context.Context) error { if len(a.cfg.GenesisJSON) > 0 && a.cfg.ForkConfig == nil { tempFile, err := os.CreateTemp("", "genesis-*.json") + defer a.removeFile(tempFile) + if err != nil { return fmt.Errorf("error creating temporary genesis file: %w", err) } @@ -120,10 +123,32 @@ func (a *Anvil) Start(ctx context.Context) error { // and see what port anvil eventually binds to when started anvilPortCh := make(chan uint64) - // Handle stdout/stderr - logFile, err := os.CreateTemp("", fmt.Sprintf("anvil-chain-%d-", a.cfg.ChainID)) - if err != nil { - return fmt.Errorf("failed to create temp log file: %w", err) + var logFile *os.File + + // Empty LogsDirectory defaults to temp file + if a.cfg.LogsDirectory == "" { + tempLogFile, err := os.CreateTemp("", fmt.Sprintf("anvil-chain-%d-", a.cfg.ChainID)) + if err != nil { + return fmt.Errorf("failed to create temp log file: %w", err) + } + + logFile = tempLogFile + // Clean up the temp log file + defer a.removeFile(logFile) + } else { + // Expand the path to the log file + absFilePath, err := filepath.Abs(fmt.Sprintf("%s/anvil-%d.log", a.cfg.LogsDirectory, a.cfg.ChainID)) + if err != nil { + return fmt.Errorf("failed to expand path: %w", err) + } + + // Handle logs in the specified directory + specifiedLogFile, err := os.Create(absFilePath) + if err != nil { + return fmt.Errorf("failed to create log file: %w", err) + } + logFile = specifiedLogFile + // Don't delete the log file if directory is specified } a.logFilePath = logFile.Name() @@ -301,3 +326,9 @@ func (a *Anvil) SimulatedLogs(ctx context.Context, tx *types.Transaction) ([]typ return logs, err } + +func (a *Anvil) removeFile(file *os.File) { + if err := os.Remove(file.Name()); err != nil { + a.log.Warn("failed to remove temp genesis file", "file.path", file.Name(), "err", err) + } +} diff --git a/config/chain.go b/config/chain.go index 227ac7c4..68bbff37 100644 --- a/config/chain.go +++ b/config/chain.go @@ -57,6 +57,9 @@ type ChainConfig struct { // Optional StartingTimestamp uint64 + + // Optional + LogsDirectory string } type NetworkConfig struct { @@ -90,7 +93,7 @@ type Chain interface { Stop(ctx context.Context) error } -func GetDefaultNetworkConfig(startingTimestamp uint64) NetworkConfig { +func GetDefaultNetworkConfig(startingTimestamp uint64, logsDirectory string) NetworkConfig { return NetworkConfig{ // Enabled by default as it is included in genesis InteropEnabled: true, @@ -101,6 +104,7 @@ func GetDefaultNetworkConfig(startingTimestamp uint64) NetworkConfig { SecretsConfig: DefaultSecretsConfig, GenesisJSON: genesis.GeneratedGenesisDeployment.L1.GenesisJSON, StartingTimestamp: startingTimestamp, + LogsDirectory: logsDirectory, }, L2Configs: []ChainConfig{ { @@ -114,6 +118,7 @@ func GetDefaultNetworkConfig(startingTimestamp uint64) NetworkConfig { DependencySet: []uint64{genesis.GeneratedGenesisDeployment.L2s[1].ChainID}, }, StartingTimestamp: startingTimestamp, + LogsDirectory: logsDirectory, }, { Name: "OPChainB", @@ -126,6 +131,7 @@ func GetDefaultNetworkConfig(startingTimestamp uint64) NetworkConfig { DependencySet: []uint64{genesis.GeneratedGenesisDeployment.L2s[0].ChainID}, }, StartingTimestamp: startingTimestamp, + LogsDirectory: logsDirectory, }, }, } diff --git a/config/cli.go b/config/cli.go index bb5c8eee..a7ee6e02 100644 --- a/config/cli.go +++ b/config/cli.go @@ -21,6 +21,8 @@ const ( NetworkFlagName = "network" L2StartingPortFlagName = "l2.starting.port" + LogsDirectoryFlagName = "logs.directory" + InteropEnabledFlagName = "interop.enabled" InteropAutoRelayFlagName = "interop.autorelay" ) @@ -43,7 +45,13 @@ func BaseCLIFlags(envPrefix string) []cli.Flag { Name: InteropAutoRelayFlagName, Value: false, Usage: "Automatically relay messages sent to the L2ToL2CrossDomainMessenger using account 0xa0Ee7A142d267C1f36714E4a8F75612F20a79720", - EnvVars: opservice.PrefixEnvVar(envPrefix, "AUTORELAY"), + EnvVars: opservice.PrefixEnvVar(envPrefix, "INTEROP_AUTORELAY"), + }, + &cli.StringFlag{ + Name: LogsDirectoryFlagName, + Usage: "Directory to store logs", + Value: "", + EnvVars: opservice.PrefixEnvVar(envPrefix, "LOGS_DIRECTORY"), }, } } @@ -93,6 +101,8 @@ type CLIConfig struct { InteropAutoRelay bool + LogsDirectory string + ForkConfig *ForkCLIConfig } @@ -102,6 +112,8 @@ func ReadCLIConfig(ctx *cli.Context) (*CLIConfig, error) { L2StartingPort: ctx.Uint64(L2StartingPortFlagName), InteropAutoRelay: ctx.Bool(InteropAutoRelayFlagName), + + LogsDirectory: ctx.String(LogsDirectoryFlagName), } if ctx.Command.Name == ForkCommandName { diff --git a/orchestrator/orchestrator_test.go b/orchestrator/orchestrator_test.go index f1787cea..5c3f0ef8 100644 --- a/orchestrator/orchestrator_test.go +++ b/orchestrator/orchestrator_test.go @@ -21,7 +21,7 @@ type TestSuite struct { } func createTestSuite(t *testing.T) *TestSuite { - networkConfig := config.GetDefaultNetworkConfig(uint64(time.Now().Unix())) + networkConfig := config.GetDefaultNetworkConfig(uint64(time.Now().Unix()), "") testlog := testlog.Logger(t, log.LevelInfo) ctx, closeApp := context.WithCancelCause(context.Background()) diff --git a/supersim.go b/supersim.go index baf8c25e..d03e6e3c 100644 --- a/supersim.go +++ b/supersim.go @@ -24,7 +24,7 @@ type Supersim struct { } func NewSupersim(log log.Logger, envPrefix string, closeApp context.CancelCauseFunc, cliConfig *config.CLIConfig) (*Supersim, error) { - networkConfig := config.GetDefaultNetworkConfig(uint64(time.Now().Unix())) + networkConfig := config.GetDefaultNetworkConfig(uint64(time.Now().Unix()), cliConfig.LogsDirectory) // If Forking, override the network config with the generated fork config if cliConfig.ForkConfig != nil {