Skip to content

Commit

Permalink
feat(evm-reader): Add evm-reader command
Browse files Browse the repository at this point in the history
  • Loading branch information
fmoura committed Jul 18, 2024
1 parent 054b38e commit ad1b09b
Showing 1 changed file with 229 additions and 0 deletions.
229 changes: 229 additions & 0 deletions cmd/cartesi-rollups-evm-reader/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package main

import (
"context"
"errors"
"log/slog"
"os"
"os/signal"
"syscall"
"time"

"github.com/cartesi/rollups-node/internal/evmreader/service"
"github.com/cartesi/rollups-node/internal/node/config"
. "github.com/cartesi/rollups-node/internal/node/model"
"github.com/cartesi/rollups-node/internal/repository"
"github.com/jackc/pgx/v5"

"github.com/ethereum/go-ethereum/common"
"github.com/lmittmann/tint"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"
)

var (
// Should be overridden during the final release build with ldflags
// to contain the actual version number
buildVersion = "devel"
)

const (
CMD_NAME = "evm-reader"
devnetInputBoxDeploymentBlockNumber = uint64(16)
)

var Cmd = &cobra.Command{
Use: CMD_NAME,
Short: "Runs EVM Reader",
Long: `Runs EVM Reader in standalone mode`,
Run: run,
}
var (
defaultBlock string
postgresEndpoint string
blockchainHttpEndpoint string
blockchainWsEndpoint string
inputBoxAddress string
inputBoxDeploymentBlockNumber uint64
verbose bool
)

func init() {

Cmd.Flags().StringVarP(&defaultBlock,
"default-block",
"d",
"",
`Default block to be used when fetching new blocks.
One of 'latest', 'safe', 'pending', 'finalized'`)

Cmd.Flags().StringVarP(&postgresEndpoint,
"postgres-endpoint",
"p",
"",
"Postgres endpoint")

Cmd.Flags().StringVarP(&blockchainHttpEndpoint,
"blockchain-http-endpoint",
"b",
"",
"Blockchain HTTP Endpoint")

Cmd.Flags().StringVarP(&blockchainWsEndpoint,
"blockchain-ws-endpoint",
"w",
"",
"Blockchain WS Endpoint")

Cmd.Flags().StringVarP(&inputBoxAddress,
"inputbox-address",
"i",
"",
"Input Box contract address")

Cmd.Flags().Uint64VarP(&inputBoxDeploymentBlockNumber,
"inputbox-block-number",
"n",
0,
"Input Box deployment block number")

Cmd.Flags().BoolVarP(&verbose,
"verbose",
"v",
false,
"enable verbose logging")
}

func main() {
err := Cmd.Execute()
if err != nil {
os.Exit(1)
}
}

func run(cmd *cobra.Command, args []string) {
startTime := time.Now()

ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()

c := config.FromEnv()

// Override configs
if verbose {
c.LogLevel = slog.LevelDebug
}
if postgresEndpoint != "" {
c.PostgresEndpoint = config.Redacted[string]{Value: postgresEndpoint}
}
if blockchainHttpEndpoint != "" {
c.BlockchainHttpEndpoint = config.Redacted[string]{Value: blockchainHttpEndpoint}
}
if blockchainWsEndpoint != "" {
c.BlockchainWsEndpoint = config.Redacted[string]{Value: blockchainWsEndpoint}
}
if defaultBlock != "" {
evmReaderDefaultBlock, err := config.ToDefaultBlockFromString(defaultBlock)
cobra.CheckErr(err)
c.EvmReaderDefaultBlock = evmReaderDefaultBlock
}

// setup log
opts := &tint.Options{
Level: c.LogLevel,
AddSource: c.LogLevel == slog.LevelDebug,
NoColor: !c.LogPrettyEnabled || !isatty.IsTerminal(os.Stdout.Fd()),
TimeFormat: "2006-01-02T15:04:05.000", // RFC3339 with milliseconds and without timezone
}
handler := tint.NewHandler(os.Stdout, opts)
logger := slog.New(handler)
slog.SetDefault(logger)
slog.Info("Starting the Cartesi Rollups Node", "version", buildVersion, "config", c)

// Validate Schema
schemaManager, err := repository.NewSchemaManager(c.PostgresEndpoint.Value)
if err != nil {
slog.Error("Node exited with an error", "error", err)
schemaManager.Close()
os.Exit(1)
}
err = schemaManager.ValidateSchemaVersion()
if err != nil {
slog.Error("Node exited with an error", "error", err)
schemaManager.Close()
os.Exit(1)
}
schemaManager.Close()

database, err := repository.Connect(ctx, c.PostgresEndpoint.Value)
if err != nil {
slog.Error("Node couldn't connect to the database", "error", err)
os.Exit(1)
}
defer database.Close()

nodePersistentConfig, err := database.GetNodeConfig(ctx)
if err != nil {
if !errors.Is(err, pgx.ErrNoRows) {
slog.Error("Could not retrieve config from Database", "error", err)
os.Exit(1)
}
}

if nodePersistentConfig == nil {
nodePersistentConfig = &NodePersistentConfig{
DefaultBlock: c.EvmReaderDefaultBlock,
InputBoxDeploymentBlock: uint64(c.ContractsInputBoxDeploymentBlockNumber),
InputBoxAddress: common.HexToAddress(c.ContractsInputBoxAddress),
ChainId: c.BlockchainID,
IConsensusAddress: common.HexToAddress(c.ContractsIConsensusAddress),
}
slog.Info(
"No persistent config found at the database. Setting it up",
"persistent config",
nodePersistentConfig,
)

err = database.InsertNodeConfig(ctx, nodePersistentConfig)
if err != nil {
slog.Error("Node couldn't insert database config", "error", err)
database.Close()
os.Exit(1)
}
} else {
slog.Info(
"Node was already configured. Using previous persistent config",
"persistent config",
nodePersistentConfig,
)
}

// create EVM Reader Service
service := service.NewEvmReaderService(
c.BlockchainHttpEndpoint.Value,
c.BlockchainWsEndpoint.Value,
database,
c.EvmReaderRetryPolicyMaxRetries,
c.EvmReaderRetryPolicyMaxDelay,
)

// logs startup time
ready := make(chan struct{}, 1)
go func() {
select {
case <-ready:
duration := time.Since(startTime)
slog.Info("EVM Reader is ready", "after", duration)
case <-ctx.Done():
}
}()

// start service
if err := service.Start(ctx, ready); err != nil {
slog.Error("EVM Reader exited with an error", "error", err)
os.Exit(1)
}
}

0 comments on commit ad1b09b

Please sign in to comment.