diff --git a/internal/inputreader/inputbox.go b/internal/inputreader/inputbox.go new file mode 100644 index 000000000..f3394de6f --- /dev/null +++ b/internal/inputreader/inputbox.go @@ -0,0 +1,55 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package inputreader + +import ( + "math/big" + + "github.com/cartesi/rollups-node/pkg/contracts/inputbox" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// InputBox Wrapper +type InputBoxInputSource struct { + inputbox *inputbox.InputBox +} + +func NewInputBoxInputSource( + inputBoxAddress common.Address, + client *ethclient.Client, +) (*InputBoxInputSource, error) { + inputbox, err := inputbox.NewInputBox(inputBoxAddress, client) + if err != nil { + return nil, err + } + return &InputBoxInputSource{ + inputbox: inputbox, + }, nil +} + +func (i *InputBoxInputSource) RetrieveInputs( + opts *bind.FilterOpts, + appContract []common.Address, + index []*big.Int, +) ([]*inputbox.InputBoxInputAdded, error) { + + itr, err := i.inputbox.FilterInputAdded(opts, appContract, index) + if err != nil { + return nil, err + } + defer itr.Close() + + var events []*inputbox.InputBoxInputAdded + for itr.Next() { + inputAddedEvent := itr.Event + events = append(events, inputAddedEvent) + } + err = itr.Error() + if err != nil { + return nil, err + } + return events, nil +} diff --git a/internal/inputreader/inputreader_service.go b/internal/inputreader/inputreader_service.go new file mode 100644 index 000000000..db6dccdf0 --- /dev/null +++ b/internal/inputreader/inputreader_service.go @@ -0,0 +1,76 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package inputreader + +import ( + "context" + + "github.com/cartesi/rollups-node/internal/repository" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/ethclient" +) + +// Service to manage InputReader lifecycle +type InputReaderService struct { + blockchainHttpEndpoint string + postgresEndpoint string + inputBoxAddress common.Address + inputBoxBlockNumber uint64 + applicationAddress common.Address +} + +func NewInputReaderService( + blockchainHttpEndpoint string, + postgresEndpoint string, + inputBoxAddress common.Address, + inputBoxBlockNumber uint64, + applicationAddress common.Address, +) InputReaderService { + return InputReaderService{ + blockchainHttpEndpoint: blockchainHttpEndpoint, + postgresEndpoint: postgresEndpoint, + inputBoxAddress: inputBoxAddress, + inputBoxBlockNumber: inputBoxBlockNumber, + applicationAddress: applicationAddress, + } +} + +func (s InputReaderService) Start( + ctx context.Context, + ready chan<- struct{}, +) error { + + db, err := repository.Connect(ctx, s.postgresEndpoint) + + if err != nil { + return err + } + + client, err := ethclient.DialContext(ctx, s.blockchainHttpEndpoint) + + if err != nil { + return err + } + + inputBoxWrapper, err := NewInputBoxInputSource(s.inputBoxAddress, client) + + if err != nil { + return err + } + + reader := newInputReader( + client, + inputBoxWrapper, + db, + s.inputBoxAddress, + s.inputBoxBlockNumber, + s.applicationAddress, + ) + + return reader.Start(ctx, ready) +} + +func (s InputReaderService) String() string { + return "input-reader" +} diff --git a/internal/node/services.go b/internal/node/services.go index cd5cd46af..42fecf370 100644 --- a/internal/node/services.go +++ b/internal/node/services.go @@ -8,8 +8,10 @@ import ( "log/slog" "os" + "github.com/cartesi/rollups-node/internal/inputreader" "github.com/cartesi/rollups-node/internal/node/config" "github.com/cartesi/rollups-node/internal/services" + "github.com/ethereum/go-ethereum/common" ) // We use an enum to define the ports of each service and avoid conflicts. @@ -125,6 +127,7 @@ func newSupervisorService(c config.NodeConfig, workDir string) services.Supervis s = append(s, newHttpService(c)) s = append(s, newPostgraphileService(c, workDir)) + s = append(s, newInputReaderService(c)) supervisor := services.SupervisorService{ Name: "rollups-node", @@ -164,3 +167,13 @@ func newPostgraphileService(c config.NodeConfig, workDir string) services.Comman s.WorkDir = workDir return s } + +func newInputReaderService(c config.NodeConfig) services.Service { + return inputreader.NewInputReaderService( + c.BlockchainHttpEndpoint.Value, + c.PostgresEndpoint.Value, + common.HexToAddress(c.ContractsInputBoxAddress), + uint64(c.ContractsInputBoxDeploymentBlockNumber), + common.HexToAddress(c.ContractsApplicationAddress), + ) +}