diff --git a/cmd/cartesi-rollups-evm-reader/main.go b/cmd/cartesi-rollups-evm-reader/main.go index be71eb922..dbe065ff4 100644 --- a/cmd/cartesi-rollups-evm-reader/main.go +++ b/cmd/cartesi-rollups-evm-reader/main.go @@ -40,7 +40,6 @@ var ( defaultBlock string postgresEndpoint string blockchainHttpEndpoint string - blockchainWsEndpoint string inputBoxAddress string inputBoxDeploymentBlockNumber uint64 verbose bool @@ -67,12 +66,6 @@ func init() { "", "Blockchain HTTP Endpoint") - Cmd.Flags().StringVarP(&blockchainWsEndpoint, - "blockchain-ws-endpoint", - "w", - "", - "Blockchain WS Endpoint") - Cmd.Flags().StringVarP(&inputBoxAddress, "inputbox-address", "i", @@ -105,7 +98,7 @@ func run(cmd *cobra.Command, args []string) { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() - c := config.FromEnv() + c := config.EvmReaderConfigFromEnv() // Override configs if verbose { @@ -117,14 +110,14 @@ func run(cmd *cobra.Command, args []string) { 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 } + if inputBoxAddress != "" { + c.ContractsInputBoxAddress = inputBoxAddress + } // setup log startup.ConfigLogs(c.LogLevel, c.LogPrettyEnabled) @@ -145,7 +138,14 @@ func run(cmd *cobra.Command, args []string) { } defer database.Close() - _, err = startup.SetupNodePersistentConfig(ctx, database, c) + _, err = startup.SetupNodePersistentConfig( + ctx, + database, + c.EvmReaderDefaultBlock, + c.ContractsInputBoxAddress, + c.ContractsInputBoxDeploymentBlockNumber, + c.BlockchainID, + ) if err != nil { slog.Error("EVM Reader couldn't connect to the database", "error", err) os.Exit(1) @@ -154,10 +154,10 @@ func run(cmd *cobra.Command, args []string) { // create EVM Reader Service service := service.NewEvmReaderService( c.BlockchainHttpEndpoint.Value, - c.BlockchainWsEndpoint.Value, database, c.EvmReaderRetryPolicyMaxRetries, c.EvmReaderRetryPolicyMaxDelay, + c.EvmReaderPollingInterval, ) // logs startup time diff --git a/cmd/cartesi-rollups-node/main.go b/cmd/cartesi-rollups-node/main.go index 1a1117bc3..5793378e8 100644 --- a/cmd/cartesi-rollups-node/main.go +++ b/cmd/cartesi-rollups-node/main.go @@ -29,33 +29,35 @@ func main() { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() - config := config.FromEnv() + c := config.FromEnv() // setup log - startup.ConfigLogs(config.LogLevel, config.LogPrettyEnabled) - slog.Info("Starting the Cartesi Rollups Node", "version", buildVersion, "config", config) + startup.ConfigLogs(c.LogLevel, c.LogPrettyEnabled) + slog.Info("Starting the Cartesi Rollups Node", "version", buildVersion, "config", c) - err := startup.ValidateSchema(config.PostgresEndpoint.Value, config.PostgresSslDisabled) + err := startup.ValidateSchema(c.PostgresEndpoint.Value, c.PostgresSslDisabled) if err != nil { slog.Error("Node exited with an error", "error", err) os.Exit(1) } - database, err := repository.Connect(ctx, config.PostgresEndpoint.Value) + 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() - _, err = startup.SetupNodePersistentConfig(ctx, database, config) + _, err = startup.SetupNodePersistentConfig(ctx, database, c.EvmReaderDefaultBlock, + c.ContractsInputBoxAddress, uint64(c.ContractsInputBoxDeploymentBlockNumber), + c.BlockchainID) if err != nil { slog.Error("Node exited with an error", "error", err) os.Exit(1) } // create the node supervisor - supervisor, err := node.Setup(ctx, config, "", database) + supervisor, err := node.Setup(ctx, c, "", database) if err != nil { slog.Error("Node exited with an error", "error", err) os.Exit(1) diff --git a/cmd/cartesi-rollups-validator/main.go b/cmd/cartesi-rollups-validator/main.go index ef187be2e..42c7370b1 100644 --- a/cmd/cartesi-rollups-validator/main.go +++ b/cmd/cartesi-rollups-validator/main.go @@ -28,28 +28,31 @@ var ( Long: "Runs Validator in standalone mode", Run: run, } - inputBoxDeploymentBlockNumber int64 - pollingInterval int64 + inputBoxDeploymentBlockNumber uint64 + pollingInterval uint64 postgresEndpoint string verbose bool ) func init() { - Cmd.Flags().Int64VarP(&inputBoxDeploymentBlockNumber, + Cmd.Flags().Uint64VarP(&inputBoxDeploymentBlockNumber, "inputbox-block-number", "n", - -1, + 0, "Input Box deployment block number", ) - Cmd.Flags().Int64VarP( + Cmd.Flags().Uint64VarP( &pollingInterval, "polling-interval", "", - -1, + 0, "the amount of seconds to wait before trying to finish epochs for all applications", ) Cmd.Flags().StringVarP(&postgresEndpoint, "postgres-endpoint", "p", "", "Postgres endpoint") Cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "enable verbose logging") + + err := Cmd.MarkFlagRequired("input-box-block-number") + cobra.CheckErr(err) } func main() { @@ -68,7 +71,7 @@ func run(cmd *cobra.Command, args []string) { c := config.FromEnv() // Override configs - if inputBoxDeploymentBlockNumber >= 0 { + if inputBoxDeploymentBlockNumber > 0 { c.ContractsInputBoxDeploymentBlockNumber = inputBoxDeploymentBlockNumber } if pollingInterval > 0 { @@ -99,7 +102,8 @@ func run(cmd *cobra.Command, args []string) { } defer database.Close() - _, err = startup.SetupNodePersistentConfig(ctx, database, c) + _, err = startup.SetupNodePersistentConfig(ctx, database, c.EvmReaderDefaultBlock, + c.ContractsInputBoxAddress, c.ContractsInputBoxDeploymentBlockNumber, c.BlockchainID) if err != nil { slog.Error("configuration error", "error", err) os.Exit(1) diff --git a/docs/config.md b/docs/config.md index a758f9b54..023644b66 100644 --- a/docs/config.md +++ b/docs/config.md @@ -135,7 +135,7 @@ Address of the InputBox contract. The deployment block for the input box contract. The node will begin to read blockchain events from this block. -* **Type:** `int64` +* **Type:** `uint64` ## `CARTESI_EXPERIMENTAL_SERVER_MANAGER_LOG_BYPASS_ENABLED` @@ -239,6 +239,13 @@ At the end of each epoch, the node will send claims to the blockchain. * **Type:** `uint64` * **Default:** `"7200"` +## `CARTESI_EVMREADER_POLLING_INTERVAL` + +How many seconds the node will wait before fetching new blocks. + +* **Type:** `Duration` +* **Default:** `"1"` + ## `CARTESI_EVM_READER_RETRY_POLICY_MAX_DELAY` How many seconds the retry policy will wait between retries. diff --git a/internal/evmreader/claim_test.go b/internal/evmreader/claim_test.go index 424096c97..8b50cd494 100644 --- a/internal/evmreader/claim_test.go +++ b/internal/evmreader/claim_test.go @@ -7,7 +7,6 @@ import ( "context" "fmt" "math/big" - "time" . "github.com/cartesi/rollups-node/internal/node/model" "github.com/cartesi/rollups-node/pkg/contracts/iconsensus" @@ -18,12 +17,9 @@ import ( func (s *EvmReaderSuite) TestNoClaimsAcceptance() { - wsClient := FakeWSEhtClient{} - //New EVM Reader evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -104,30 +100,12 @@ func (s *EvmReaderSuite) TestNoClaimsAcceptance() { mock.Anything, mock.Anything, ).Return(&header1, nil).Once() - s.client.On( - "HeaderByNumber", - mock.Anything, - mock.Anything, - ).Return(&header2, nil).Once() - - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - wsClient.fireNewHead(&header1) - time.Sleep(1 * time.Second) + // Run 2 steps + err := evmReader.Step(s.ctx) + s.Require().Nil(err) + err = evmReader.Step(s.ctx) + s.Require().Nil(err) s.repository.AssertNumberOfCalls( s.T(), @@ -153,10 +131,9 @@ func (s *EvmReaderSuite) TestReadClaimAcceptance() { ).Return(consensusContract, nil) //New EVM Reader - wsClient := FakeWSEhtClient{} + evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x00, @@ -261,23 +238,9 @@ func (s *EvmReaderSuite) TestReadClaimAcceptance() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(10 * time.Second) + //Run 1 step + err := evmReader.Step(s.ctx) + s.Require().Nil(err) s.repository.AssertNumberOfCalls( s.T(), @@ -296,11 +259,8 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { appAddress := common.HexToAddress("0x2E663fe9aE92275242406A185AA4fC8174339D3E") // Contract Factory - consensusContract := &MockIConsensusContract{} - contractFactory := newEmvReaderContractFactory() - contractFactory.Unset("NewIConsensus") contractFactory.On("NewIConsensus", mock.Anything, @@ -308,12 +268,10 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -409,23 +367,8 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) repository.AssertNumberOfCalls( s.T(), @@ -455,12 +398,10 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -556,23 +497,8 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) repository.AssertNumberOfCalls( s.T(), @@ -602,12 +528,10 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -616,7 +540,6 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { ) // Prepare Claims Acceptance Events - claimEvent0 := &iconsensus.IConsensusClaimAcceptance{ AppContract: appAddress, LastProcessedBlockNumber: big.NewInt(3), @@ -697,23 +620,8 @@ func (s *EvmReaderSuite) TestCheckClaimFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) repository.AssertNumberOfCalls( s.T(), diff --git a/internal/evmreader/evmreader.go b/internal/evmreader/evmreader.go index 29aee8994..932548b29 100644 --- a/internal/evmreader/evmreader.go +++ b/internal/evmreader/evmreader.go @@ -14,7 +14,6 @@ import ( appcontract "github.com/cartesi/rollups-node/pkg/contracts/application" "github.com/cartesi/rollups-node/pkg/contracts/iconsensus" "github.com/cartesi/rollups-node/pkg/contracts/inputbox" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" @@ -62,12 +61,6 @@ type EthClient interface { HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) } -// EthWsClient mimics part of ethclient.Client functions to narrow down the -// interface needed by the EvmReader. It must be bound to a WS endpoint -type EthWsClient interface { - SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) -} - type ConsensusContract interface { GetEpochLength(opts *bind.CallOpts) (*big.Int, error) RetrieveClaimAcceptanceEvents( @@ -107,7 +100,6 @@ type application struct { // Output Executed events from the blockchain type EvmReader struct { client EthClient - wsClient EthWsClient inputSource InputSource repository EvmReaderRepository contractFactory ContractFactory @@ -123,111 +115,73 @@ func (r *EvmReader) String() string { // Creates a new EvmReader func NewEvmReader( client EthClient, - wsClient EthWsClient, inputSource InputSource, repository EvmReaderRepository, inputBoxDeploymentBlock uint64, defaultBlock DefaultBlock, contractFactory ContractFactory, -) EvmReader { - return EvmReader{ +) *EvmReader { + return &EvmReader{ client: client, - wsClient: wsClient, inputSource: inputSource, repository: repository, inputBoxDeploymentBlock: inputBoxDeploymentBlock, defaultBlock: defaultBlock, contractFactory: contractFactory, + epochLengthCache: make(map[Address]uint64), } } -func (r *EvmReader) Run(ctx context.Context, ready chan<- struct{}) error { +func (r *EvmReader) Step(ctx context.Context) error { - // Initialize epochLength cache - r.epochLengthCache = make(map[Address]uint64) + // Get All Applications + runningApps, err := r.repository.GetAllRunningApplications(ctx) + if err != nil { + slog.Error("Error retrieving running applications for new inputs", + "error", + err, + ) + return nil + } - for { - err := r.watchForNewBlocks(ctx, ready) - // If the error is a SubscriptionError, re run watchForNewBlocks - // that it will restart the websocket subscription - if _, ok := err.(*SubscriptionError); !ok { - return err + // Build Contracts + var apps []application + for _, app := range runningApps { + applicationContract, consensusContract, err := r.getAppContracts(app) + if err != nil { + slog.Error("Error retrieving application contracts", "app", app, "error", err) + continue } - slog.Error(err.Error()) - slog.Info("Restarting subscription") + apps = append(apps, application{Application: app, + applicationContract: applicationContract, + consensusContract: consensusContract}) } -} -// watchForNewBlocks watches for new blocks and reads new inputs based on the -// default block configuration, which have not been processed yet. -func (r *EvmReader) watchForNewBlocks(ctx context.Context, ready chan<- struct{}) error { - headers := make(chan *types.Header) - sub, err := r.wsClient.SubscribeNewHead(ctx, headers) - if err != nil { - return fmt.Errorf("could not start subscription: %v", err) + if len(apps) == 0 { + slog.Info("No correctly configured applications running") + return nil } - slog.Info("Subscribed to new block events") - ready <- struct{}{} - defer sub.Unsubscribe() - - for { - select { - case <-ctx.Done(): - return ctx.Err() - case err := <-sub.Err(): - return &SubscriptionError{Cause: err} - case <-headers: - - // Every time a new block arrives - - // Get All Applications - runningApps, err := r.repository.GetAllRunningApplications(ctx) - if err != nil { - slog.Error("Error retrieving running applications", - "error", - err, - ) - continue - } - - // Build Contracts - var apps []application - for _, app := range runningApps { - applicationContract, consensusContract, err := r.getAppContracts(app) - if err != nil { - slog.Error("Error retrieving application contracts", "app", app, "error", err) - continue - } - apps = append(apps, application{Application: app, - applicationContract: applicationContract, - consensusContract: consensusContract}) - } - - if len(apps) == 0 { - slog.Info("No correctly configured applications running") - continue - } - - mostRecentHeader, err := r.fetchMostRecentHeader( - ctx, - r.defaultBlock, - ) - if err != nil { - slog.Error("Error fetching most recent block", - "default block", r.defaultBlock, - "error", err) - continue - } - mostRecentBlockNumber := mostRecentHeader.Number.Uint64() - - r.checkForNewInputs(ctx, apps, mostRecentBlockNumber) - - r.checkForClaimStatus(ctx, apps, mostRecentBlockNumber) - - r.checkForOutputExecution(ctx, apps, mostRecentBlockNumber) - } + mostRecentHeader, err := r.fetchMostRecentHeader( + ctx, + r.defaultBlock, + ) + if err != nil { + slog.Error("Error fetching most recent block", + "default block", r.defaultBlock, + "error", err) + return nil } + mostRecentBlockNumber := mostRecentHeader.Number.Uint64() + + r.checkForNewInputs(ctx, apps, mostRecentBlockNumber) + + r.checkForClaimStatus(ctx, apps, mostRecentBlockNumber) + + r.checkForOutputExecution(ctx, apps, mostRecentBlockNumber) + + return nil + } // fetchMostRecentHeader fetches the most recent header up till the diff --git a/internal/evmreader/evmreader_test.go b/internal/evmreader/evmreader_test.go index 67ba494ad..d792880a4 100644 --- a/internal/evmreader/evmreader_test.go +++ b/internal/evmreader/evmreader_test.go @@ -7,7 +7,6 @@ import ( "context" _ "embed" "encoding/json" - "fmt" "math/big" "testing" "time" @@ -16,7 +15,6 @@ import ( appcontract "github.com/cartesi/rollups-node/pkg/contracts/application" "github.com/cartesi/rollups-node/pkg/contracts/iconsensus" "github.com/cartesi/rollups-node/pkg/contracts/inputbox" - "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -60,8 +58,6 @@ var ( inputAddedEvent1 = inputbox.InputBoxInputAdded{} inputAddedEvent2 = inputbox.InputBoxInputAdded{} inputAddedEvent3 = inputbox.InputBoxInputAdded{} - - subscription0 = newMockSubscription() ) type EvmReaderSuite struct { @@ -69,7 +65,6 @@ type EvmReaderSuite struct { ctx context.Context cancel context.CancelFunc client *MockEthClient - wsClient *MockEthClient inputBox *MockInputBox repository *MockRepository evmReader *EvmReader @@ -109,65 +104,21 @@ func (s *EvmReaderSuite) TearDownSuite() { func (s *EvmReaderSuite) SetupTest() { s.client = newMockEthClient() - s.wsClient = s.client s.inputBox = newMockInputBox() s.repository = newMockRepository() s.contractFactory = newEmvReaderContractFactory() - inputReader := NewEvmReader( + s.evmReader = NewEvmReader( s.client, - s.wsClient, s.inputBox, s.repository, 0, DefaultBlockStatusLatest, s.contractFactory, ) - s.evmReader = &inputReader -} - -// Service tests -func (s *EvmReaderSuite) TestItStopsWhenContextIsCanceled() { - ctx, cancel := context.WithCancel(s.ctx) - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - go func() { - errChannel <- s.evmReader.Run(ctx, ready) - }() - cancel() - - err := <-errChannel - s.Require().Equal(context.Canceled, err, "stopped for the wrong reason") -} - -func (s *EvmReaderSuite) TestItEventuallyBecomesReady() { - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - go func() { - errChannel <- s.evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - case err := <-errChannel: - s.FailNow("unexpected failure", err) - } -} - -func (s *EvmReaderSuite) TestItFailsToSubscribeForNewInputsOnStart() { - s.client.Unset("SubscribeNewHead") - emptySubscription := &MockSubscription{} - s.client.On( - "SubscribeNewHead", - mock.Anything, - mock.Anything, - ).Return(emptySubscription, fmt.Errorf("expected failure")) - s.Require().ErrorContains( - s.evmReader.Run(s.ctx, make(chan struct{}, 1)), - "expected failure") - s.client.AssertNumberOfCalls(s.T(), "SubscribeNewHead", 1) } +// Evm tests func (s *EvmReaderSuite) TestItWrongIConsensus() { consensusContract := &MockIConsensusContract{} @@ -179,11 +130,8 @@ func (s *EvmReaderSuite) TestItWrongIConsensus() { mock.Anything, ).Return(consensusContract, nil) - wsClient := FakeWSEhtClient{} - evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -223,23 +171,9 @@ func (s *EvmReaderSuite) TestItWrongIConsensus() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(time.Second) + // Run + err := evmReader.Step(s.ctx) + s.Require().Nil(err) // Should not advance input processing s.inputBox.AssertNumberOfCalls(s.T(), "RetrieveInputs", 0) @@ -271,11 +205,6 @@ func newMockEthClient() *MockEthClient { mock.Anything, ).Return(&header0, nil) - client.On("SubscribeNewHead", - mock.Anything, - mock.Anything, - ).Return(subscription0, nil) - return client } @@ -295,53 +224,6 @@ func (m *MockEthClient) HeaderByNumber( return args.Get(0).(*types.Header), args.Error(1) } -func (m *MockEthClient) SubscribeNewHead( - ctx context.Context, - ch chan<- *types.Header, -) (ethereum.Subscription, error) { - args := m.Called(ctx, ch) - return args.Get(0).(ethereum.Subscription), args.Error(1) -} - -// Mock ethereum.Subscription -type MockSubscription struct { - mock.Mock -} - -func newMockSubscription() *MockSubscription { - sub := &MockSubscription{} - - sub.On("Unsubscribe").Return() - sub.On("Err").Return(make(<-chan error)) - - return sub -} - -func (m *MockSubscription) Unsubscribe() { -} - -func (m *MockSubscription) Err() <-chan error { - args := m.Called() - return args.Get(0).(<-chan error) -} - -// FakeClient -type FakeWSEhtClient struct { - ch chan<- *types.Header -} - -func (f *FakeWSEhtClient) SubscribeNewHead( - ctx context.Context, - ch chan<- *types.Header, -) (ethereum.Subscription, error) { - f.ch = ch - return newMockSubscription(), nil -} - -func (f *FakeWSEhtClient) fireNewHead(header *types.Header) { - f.ch <- header -} - // Mock inputbox.InputBox type MockInputBox struct { mock.Mock diff --git a/internal/evmreader/input_test.go b/internal/evmreader/input_test.go index 223733900..7399a78ca 100644 --- a/internal/evmreader/input_test.go +++ b/internal/evmreader/input_test.go @@ -4,8 +4,6 @@ package evmreader import ( - "time" - . "github.com/cartesi/rollups-node/internal/node/model" "github.com/cartesi/rollups-node/pkg/contracts/inputbox" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -15,11 +13,8 @@ import ( func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { - wsClient := FakeWSEhtClient{} - evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -94,24 +89,11 @@ func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { mock.Anything, ).Return(events_1, nil) - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - wsClient.fireNewHead(&header1) - time.Sleep(time.Second) + // Run 2 steps + err := evmReader.Step(s.ctx) + s.Require().Nil(err) + err = evmReader.Step(s.ctx) + s.Require().Nil(err) s.inputBox.AssertNumberOfCalls(s.T(), "RetrieveInputs", 2) s.repository.AssertNumberOfCalls( @@ -123,11 +105,8 @@ func (s *EvmReaderSuite) TestItReadsInputsFromNewBlocks() { func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { - wsClient := FakeWSEhtClient{} - evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -202,24 +181,11 @@ func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { mock.Anything, ).Return(events_1, nil) - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - wsClient.fireNewHead(&header1) - time.Sleep(time.Second) + // Run 2 steps + err := evmReader.Step(s.ctx) + s.Require().Nil(err) + err = evmReader.Step(s.ctx) + s.Require().Nil(err) s.inputBox.AssertNumberOfCalls(s.T(), "RetrieveInputs", 2) s.repository.AssertNumberOfCalls( @@ -231,11 +197,8 @@ func (s *EvmReaderSuite) TestItUpdatesLastProcessedBlockWhenThereIsNoInputs() { func (s *EvmReaderSuite) TestItReadsMultipleInputsFromSingleNewBlock() { - wsClient := FakeWSEhtClient{} - - inputReader := NewEvmReader( + evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -297,24 +260,9 @@ func (s *EvmReaderSuite) TestItReadsMultipleInputsFromSingleNewBlock() { }).Return(make(map[uint64]uint64), make(map[uint64][]uint64), nil) - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- inputReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header2) - // Give a time for - time.Sleep(1 * time.Second) + // Run 1 step + err := evmReader.Step(s.ctx) + s.Require().Nil(err) s.inputBox.AssertNumberOfCalls(s.T(), "RetrieveInputs", 1) s.repository.AssertNumberOfCalls( @@ -326,10 +274,8 @@ func (s *EvmReaderSuite) TestItReadsMultipleInputsFromSingleNewBlock() { func (s *EvmReaderSuite) TestItStartsWhenLasProcessedBlockIsTheMostRecentBlock() { - wsClient := FakeWSEhtClient{} - inputReader := NewEvmReader( + evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -356,23 +302,9 @@ func (s *EvmReaderSuite) TestItStartsWhenLasProcessedBlockIsTheMostRecentBlock() LastProcessedBlock: 0x11, }}, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- inputReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header2) - time.Sleep(1 * time.Second) + // Run 1 setp + err := evmReader.Step(s.ctx) + s.Require().Nil(err) s.inputBox.AssertNumberOfCalls(s.T(), "RetrieveInputs", 0) s.repository.AssertNumberOfCalls( diff --git a/internal/evmreader/output_test.go b/internal/evmreader/output_test.go index 115454f23..975255795 100644 --- a/internal/evmreader/output_test.go +++ b/internal/evmreader/output_test.go @@ -6,7 +6,6 @@ package evmreader import ( "context" "errors" - "time" . "github.com/cartesi/rollups-node/internal/node/model" appcontract "github.com/cartesi/rollups-node/pkg/contracts/application" @@ -18,12 +17,9 @@ import ( func (s *EvmReaderSuite) TestOutputExecution() { - wsClient := FakeWSEhtClient{} - //New EVM Reader evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x10, @@ -107,24 +103,11 @@ func (s *EvmReaderSuite) TestOutputExecution() { mock.Anything, ).Return(&header1, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - wsClient.fireNewHead(&header1) - time.Sleep(1 * time.Second) + //Run 2 steps + err := evmReader.Step(s.ctx) + s.Require().Nil(err) + err = evmReader.Step(s.ctx) + s.Require().Nil(err) s.repository.AssertNumberOfCalls( s.T(), @@ -150,10 +133,8 @@ func (s *EvmReaderSuite) TestReadOutputExecution() { ).Return(applicationContract, nil) //New EVM Reader - wsClient := FakeWSEhtClient{} evmReader := NewEvmReader( s.client, - &wsClient, s.inputBox, s.repository, 0x00, @@ -235,23 +216,9 @@ func (s *EvmReaderSuite) TestReadOutputExecution() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(s.ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + // Run 1 step + err := evmReader.Step(s.ctx) + s.Require().Nil(err) s.repository.AssertNumberOfCalls( s.T(), @@ -269,11 +236,8 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { appAddress := common.HexToAddress("0x2E663fe9aE92275242406A185AA4fC8174339D3E") // Contract Factory - applicationContract := &MockApplicationContract{} - contractFactory := newEmvReaderContractFactory() - contractFactory.Unset("NewApplication") contractFactory.On("NewApplication", mock.Anything, @@ -281,12 +245,10 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -348,23 +310,8 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) s.repository.AssertNumberOfCalls( s.T(), @@ -393,12 +340,10 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -465,23 +410,8 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) repository.AssertNumberOfCalls( s.T(), @@ -510,12 +440,10 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { //New EVM Reader client := newMockEthClient() - wsClient := FakeWSEhtClient{} inputBox := newMockInputBox() repository := newMockRepository() evmReader := NewEvmReader( client, - &wsClient, inputBox, repository, 0x00, @@ -587,23 +515,8 @@ func (s *EvmReaderSuite) TestCheckOutputFails() { mock.Anything, ).Return(&header0, nil).Once() - // Start service - ready := make(chan struct{}, 1) - errChannel := make(chan error, 1) - - go func() { - errChannel <- evmReader.Run(ctx, ready) - }() - - select { - case <-ready: - break - case err := <-errChannel: - s.FailNow("unexpected error signal", err) - } - - wsClient.fireNewHead(&header0) - time.Sleep(1 * time.Second) + err := evmReader.Step(ctx) + s.Require().Nil(err) repository.AssertNumberOfCalls( s.T(), diff --git a/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go b/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go deleted file mode 100644 index a3feb6ebd..000000000 --- a/internal/evmreader/retrypolicy/retrypolicy_ethwsclient_delegator.go +++ /dev/null @@ -1,60 +0,0 @@ -// (c) Cartesi and individual authors (see AUTHORS) -// SPDX-License-Identifier: Apache-2.0 (see LICENSE) - -package retrypolicy - -import ( - "context" - "time" - - "github.com/cartesi/rollups-node/internal/evmreader" - "github.com/cartesi/rollups-node/internal/retry" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/core/types" -) - -type EthWsClientRetryPolicyDelegator struct { - delegate evmreader.EthWsClient - maxRetries uint64 - delayBetweenCalls time.Duration -} - -func NewEthWsClientWithRetryPolicy( - delegate evmreader.EthWsClient, - maxRetries uint64, - delayBetweenCalls time.Duration, -) *EthWsClientRetryPolicyDelegator { - return &EthWsClientRetryPolicyDelegator{ - delegate: delegate, - maxRetries: maxRetries, - delayBetweenCalls: delayBetweenCalls, - } -} - -type subscribeNewHeadArgs struct { - ctx context.Context - ch chan<- *types.Header -} - -func (d *EthWsClientRetryPolicyDelegator) SubscribeNewHead( - ctx context.Context, - ch chan<- *types.Header, -) (ethereum.Subscription, error) { - - return retry.CallFunctionWithRetryPolicy( - d.subscribeNewHead, - subscribeNewHeadArgs{ - ctx: ctx, - ch: ch, - }, - d.maxRetries, - d.delayBetweenCalls, - "EthWSClient::SubscribeNewHead", - ) -} - -func (d *EthWsClientRetryPolicyDelegator) subscribeNewHead( - args subscribeNewHeadArgs, -) (ethereum.Subscription, error) { - return d.delegate.SubscribeNewHead(args.ctx, args.ch) -} diff --git a/internal/evmreader/service/evmreader_service.go b/internal/evmreader/service/evmreader_service.go index c120243a0..6c6fa3c1d 100644 --- a/internal/evmreader/service/evmreader_service.go +++ b/internal/evmreader/service/evmreader_service.go @@ -10,6 +10,7 @@ import ( "github.com/cartesi/rollups-node/internal/evmreader" "github.com/cartesi/rollups-node/internal/evmreader/retrypolicy" "github.com/cartesi/rollups-node/internal/repository" + "github.com/cartesi/rollups-node/internal/services/poller" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" ) @@ -22,25 +23,25 @@ type ( // Service to manage InputReader lifecycle type EvmReaderService struct { blockchainHttpEndpoint string - blockchainWsEndpoint string database *repository.Database maxRetries uint64 maxDelay time.Duration + pollInterval time.Duration } func NewEvmReaderService( blockchainHttpEndpoint string, - blockchainWsEndpoint string, database *repository.Database, maxRetries uint64, maxDelay time.Duration, + pollInterval time.Duration, ) EvmReaderService { return EvmReaderService{ blockchainHttpEndpoint: blockchainHttpEndpoint, - blockchainWsEndpoint: blockchainWsEndpoint, database: database, maxRetries: maxRetries, maxDelay: maxDelay, + pollInterval: pollInterval, } } @@ -55,12 +56,6 @@ func (s EvmReaderService) Start( } defer client.Close() - wsClient, err := ethclient.DialContext(ctx, s.blockchainWsEndpoint) - if err != nil { - return err - } - defer wsClient.Close() - config, err := s.database.GetNodeConfig(ctx) if err != nil { return err @@ -75,7 +70,6 @@ func (s EvmReaderService) Start( reader := evmreader.NewEvmReader( retrypolicy.NewEhtClientWithRetryPolicy(client, s.maxRetries, s.maxDelay), - retrypolicy.NewEthWsClientWithRetryPolicy(wsClient, s.maxRetries, s.maxDelay), retrypolicy.NewInputSourceWithRetryPolicy(inputSource, s.maxRetries, s.maxDelay), s.database, config.InputBoxDeploymentBlock, @@ -83,7 +77,13 @@ func (s EvmReaderService) Start( contractFactory, ) - return reader.Run(ctx, ready) + pollerService, err := poller.New("evm-service", reader, s.pollInterval) + + if err != nil { + return err + } + ready <- struct{}{} + return pollerService.Start(ctx) } func (s EvmReaderService) String() string { diff --git a/internal/node/advancer/advancer.go b/internal/node/advancer/advancer.go index 4967aa42f..7837d3646 100644 --- a/internal/node/advancer/advancer.go +++ b/internal/node/advancer/advancer.go @@ -11,9 +11,9 @@ import ( "time" "github.com/cartesi/rollups-node/internal/node/advancer/machines" - "github.com/cartesi/rollups-node/internal/node/advancer/poller" . "github.com/cartesi/rollups-node/internal/node/model" "github.com/cartesi/rollups-node/internal/nodemachine" + "github.com/cartesi/rollups-node/internal/services/poller" ) var ( @@ -48,7 +48,7 @@ func (advancer *Advancer) Poller(pollingInterval time.Duration) (*poller.Poller, // Step steps the Advancer for one processing cycle. // It gets unprocessed inputs from the repository, // runs them through the cartesi machine, -// and updates the repository with the ouputs. +// and updates the repository with the outputs. func (advancer *Advancer) Step(ctx context.Context) error { apps := advancer.machines.Apps() diff --git a/internal/node/config/config.go b/internal/node/config/config.go index aa83c63ee..b3faf4886 100644 --- a/internal/node/config/config.go +++ b/internal/node/config/config.go @@ -29,7 +29,7 @@ type NodeConfig struct { BlockchainBlockTimeout int ContractsApplicationAddress string ContractsInputBoxAddress string - ContractsInputBoxDeploymentBlockNumber int64 + ContractsInputBoxDeploymentBlockNumber uint64 SnapshotDir string PostgresEndpoint Redacted[string] PostgresSslDisabled bool @@ -43,6 +43,7 @@ type NodeConfig struct { Auth Auth AdvancerPollingInterval Duration ValidatorPollingInterval Duration + EvmReaderPollingInterval Duration // Temporary MachineServerVerbosity cartesimachine.ServerVerbosity } @@ -115,6 +116,7 @@ func FromEnv() NodeConfig { config.ValidatorPollingInterval = getValidatorPollingInterval() // Temporary. config.MachineServerVerbosity = cartesimachine.ServerVerbosity(getMachineServerVerbosity()) + config.EvmReaderPollingInterval = getEvmreaderPollingInterval() return config } @@ -180,3 +182,37 @@ func GetAdvancerConfig() AdvancerConfig { config.MachineServerVerbosity = cartesimachine.ServerVerbosity(getMachineServerVerbosity()) return config } + +// EVM Reader + +type EvmReaderConfig struct { + LogLevel LogLevel + LogPrettyEnabled bool + PostgresEndpoint Redacted[string] + PostgresSslDisabled bool + BlockchainHttpEndpoint Redacted[string] + BlockchainID uint64 + ContractsInputBoxAddress string + ContractsInputBoxDeploymentBlockNumber uint64 + EvmReaderDefaultBlock DefaultBlock + EvmReaderRetryPolicyMaxRetries uint64 + EvmReaderRetryPolicyMaxDelay Duration + EvmReaderPollingInterval Duration +} + +func EvmReaderConfigFromEnv() EvmReaderConfig { + return EvmReaderConfig{ + LogLevel: getLogLevel(), + LogPrettyEnabled: getLogPrettyEnabled(), + PostgresEndpoint: Redacted[string]{getPostgresEndpoint()}, + PostgresSslDisabled: !getPostgresSslEnabled(), + ContractsInputBoxAddress: getContractsInputBoxAddress(), + ContractsInputBoxDeploymentBlockNumber: getContractsInputBoxDeploymentBlockNumber(), + BlockchainID: getBlockchainId(), + BlockchainHttpEndpoint: Redacted[string]{getBlockchainHttpEndpoint()}, + EvmReaderDefaultBlock: getEvmReaderDefaultBlock(), + EvmReaderRetryPolicyMaxRetries: getEvmReaderRetryPolicyMaxRetries(), + EvmReaderRetryPolicyMaxDelay: getEvmReaderRetryPolicyMaxDelay(), + EvmReaderPollingInterval: getEvmreaderPollingInterval(), + } +} diff --git a/internal/node/config/generate/Config.toml b/internal/node/config/generate/Config.toml index eefb52d85..936c3d482 100644 --- a/internal/node/config/generate/Config.toml +++ b/internal/node/config/generate/Config.toml @@ -68,6 +68,13 @@ go-type = "Duration" description = """ How many seconds the node will wait before trying to finish epochs for all applications.""" +[rollups.CARTESI_EVMREADER_POLLING_INTERVAL] +default = "1" +go-type = "Duration" +description = """ +How many seconds the node will wait before fetching new blocks.""" + + # # Blockchain # @@ -129,7 +136,7 @@ description = """ Address of the InputBox contract.""" [contracts.CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER] -go-type = "int64" +go-type = "uint64" description = """ The deployment block for the input box contract. The node will begin to read blockchain events from this block.""" diff --git a/internal/node/config/generated.go b/internal/node/config/generated.go index 593d5206c..66fb73000 100644 --- a/internal/node/config/generated.go +++ b/internal/node/config/generated.go @@ -324,12 +324,12 @@ func getContractsInputBoxAddress() string { return val } -func getContractsInputBoxDeploymentBlockNumber() int64 { +func getContractsInputBoxDeploymentBlockNumber() uint64 { s, ok := os.LookupEnv("CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER") if !ok { panic("missing env var CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER") } - val, err := toInt64(s) + val, err := toUint64(s) if err != nil { panic(fmt.Sprintf("failed to parse CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER: %v", err)) } @@ -492,6 +492,18 @@ func getEpochLength() uint64 { return val } +func getEvmreaderPollingInterval() Duration { + s, ok := os.LookupEnv("CARTESI_EVMREADER_POLLING_INTERVAL") + if !ok { + s = "1" + } + val, err := toDuration(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_EVMREADER_POLLING_INTERVAL: %v", err)) + } + return val +} + func getEvmReaderRetryPolicyMaxDelay() Duration { s, ok := os.LookupEnv("CARTESI_EVM_READER_RETRY_POLICY_MAX_DELAY") if !ok { diff --git a/internal/node/services.go b/internal/node/services.go index 7c1ac891c..765d64c79 100644 --- a/internal/node/services.go +++ b/internal/node/services.go @@ -172,10 +172,10 @@ func newPostgraphileService(c config.NodeConfig, workDir string) services.Comman func newEvmReaderService(c config.NodeConfig, database *repository.Database) services.Service { return evmreaderservice.NewEvmReaderService( c.BlockchainHttpEndpoint.Value, - c.BlockchainWsEndpoint.Value, database, c.EvmReaderRetryPolicyMaxRetries, c.EvmReaderRetryPolicyMaxDelay, + c.EvmReaderPollingInterval, ) } diff --git a/internal/node/startup/startup.go b/internal/node/startup/startup.go index 38d4bd5fa..bf658ca97 100644 --- a/internal/node/startup/startup.go +++ b/internal/node/startup/startup.go @@ -9,7 +9,6 @@ import ( "log/slog" "os" - "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/cartesi/rollups-node/internal/repository/schema" @@ -20,8 +19,9 @@ import ( ) // Validates the Node Database Schema Version -func ValidateSchema(endpoint string, sslMode bool) error { - if sslMode { +func ValidateSchema(endpoint string, sslModeDisable bool) error { + + if sslModeDisable { endpoint += "?sslmode=disable" } @@ -52,7 +52,11 @@ func ConfigLogs(logLevel slog.Level, logPrettyEnabled bool) { func SetupNodePersistentConfig( ctx context.Context, database *repository.Database, - config config.NodeConfig, + evmReaderDefaultBlock model.DefaultBlock, + inputBoxAddress string, + inputBoxDeploymentBlock uint64, + blockChainId uint64, + ) (*model.NodePersistentConfig, error) { nodePersistentConfig, err := database.GetNodeConfig(ctx) if err != nil { @@ -66,10 +70,10 @@ func SetupNodePersistentConfig( if nodePersistentConfig == nil { nodePersistentConfig = &model.NodePersistentConfig{ - DefaultBlock: config.EvmReaderDefaultBlock, - InputBoxDeploymentBlock: uint64(config.ContractsInputBoxDeploymentBlockNumber), - InputBoxAddress: common.HexToAddress(config.ContractsInputBoxAddress), - ChainId: config.BlockchainID, + DefaultBlock: evmReaderDefaultBlock, + InputBoxDeploymentBlock: inputBoxDeploymentBlock, + InputBoxAddress: common.HexToAddress(inputBoxAddress), + ChainId: blockChainId, } slog.Info( "No persistent config found at the database. Setting it up", diff --git a/internal/node/advancer/poller/poller.go b/internal/services/poller/poller.go similarity index 100% rename from internal/node/advancer/poller/poller.go rename to internal/services/poller/poller.go