From 6d27c54c9090315bf2a8203147bef92524901f92 Mon Sep 17 00:00:00 2001 From: Renan Santos Date: Thu, 29 Aug 2024 14:34:17 -0300 Subject: [PATCH] wip --- cmd/cartesi-rollups-advancer/main.go | 105 +++++++++++ cmd/cartesi-rollups-cli/root/app/add/add.go | 2 +- docs/config.md | 51 +++++- internal/node/config/config.go | 18 ++ internal/node/config/generate/Config.toml | 48 ++++- internal/node/config/generate/code.go | 12 ++ internal/node/config/generated.go | 96 ++++++++++ internal/repository/advancer.go | 39 ++++ internal/repository/advancer_test.go | 168 ++++++++++++++++-- internal/repository/base.go | 16 +- internal/repository/base_test.go | 6 +- ...nput_claim_output_report_nodeconfig.up.sql | 1 + internal/repository/validator_test.go | 12 +- test/advancer/advancer_test.go | 2 +- test/snapshot/snapshot.go | 6 + test/tooling/db/db.go | 2 +- 16 files changed, 555 insertions(+), 29 deletions(-) create mode 100644 cmd/cartesi-rollups-advancer/main.go diff --git a/cmd/cartesi-rollups-advancer/main.go b/cmd/cartesi-rollups-advancer/main.go new file mode 100644 index 000000000..6eccd072f --- /dev/null +++ b/cmd/cartesi-rollups-advancer/main.go @@ -0,0 +1,105 @@ +// (c) Cartesi and individual authors (see AUTHORS) +// SPDX-License-Identifier: Apache-2.0 (see LICENSE) + +package main + +import ( + "context" + "fmt" + "log/slog" + "os" + "os/signal" + "syscall" + "time" + + "github.com/cartesi/rollups-node/internal/node/advancer" + "github.com/cartesi/rollups-node/internal/node/advancer/machines" + "github.com/cartesi/rollups-node/internal/node/config" + "github.com/cartesi/rollups-node/internal/node/startup" + "github.com/cartesi/rollups-node/internal/repository" + "github.com/spf13/cobra" +) + +const CMD_NAME = "advancer" + +var ( + buildVersion = "devel" + Cmd = &cobra.Command{ + Use: CMD_NAME, + Short: "Runs the Advancer", + Long: "Runs the Advancer in standalone mode", + Run: run, + } +) + +func init() { + flags := Cmd.Flags() + flags.BytesHex("application-address", nil, "") + flags.String("server-address", "", "") + flags.String("snapshot", "", "") + flags.Int64("snapshot-input-index", -1, "") + flags.Uint64("machine-inc-cycles", 50_000_000, "") + flags.Uint64("machine-max-cycles", 5_000_000_000, "") + flags.Uint64("machine-advance-timeout", 60, "") + flags.Uint64("machine-inspect-timeout", 10, "") +} + +func main() { + err := Cmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func getDatabase(ctx context.Context, c config.NodeConfig) (*repository.Database, error) { + err := startup.ValidateSchema(c) + if err != nil { + return nil, fmt.Errorf("invalid database schema: %w", err) + } + + database, err := repository.Connect(ctx, c.PostgresEndpoint.Value) + if err != nil { + return nil, fmt.Errorf("failed to connect to the database: %w", err) + } + + return database, nil +} + +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() + startup.ConfigLogs(c) + + slog.Info("Starting the Cartesi Rollups Node Advancer", "version", buildVersion, "config", c) + + database, err := getDatabase(ctx, c) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + defer database.Close() + + repo := &repository.AdvancerRepository{Database: database} + + machines, err := machines.Load(ctx, c, repo) + if err != nil { + slog.Error(err.Error()) + os.Exit(1) + } + defer machines.Close() + + advancer, err := advancer.New(machines, repo) + + poller, err := advancer.Poller(5 * time.Second) + + ready := make(chan struct{}, 1) + + if err := poller.Start(ctx, ready); err != nil { + slog.Error("advancer exited with an error", "error", err) + os.Exit(1) + } +} diff --git a/cmd/cartesi-rollups-cli/root/app/add/add.go b/cmd/cartesi-rollups-cli/root/app/add/add.go index 0545c88b9..1d622e3de 100644 --- a/cmd/cartesi-rollups-cli/root/app/add/add.go +++ b/cmd/cartesi-rollups-cli/root/app/add/add.go @@ -118,7 +118,7 @@ func run(cmd *cobra.Command, args []string) { IConsensusAddress: common.HexToAddress(iConsensusAddress), } - err := cmdcommom.Database.InsertApplication(ctx, &application) + _, err := cmdcommom.Database.InsertApplication(ctx, &application) cobra.CheckErr(err) fmt.Printf("Application %v successfully added\n", application.ContractAddress) } diff --git a/docs/config.md b/docs/config.md index 67a4653ae..6fd5aa5d0 100644 --- a/docs/config.md +++ b/docs/config.md @@ -223,6 +223,13 @@ When enabled, will connect to postgres database via SSL. * **Type:** `bool` * **Default:** `"true"` +## `CARTESI_ADVANCER_POLLING_INTERVAL` + +How many seconds the node will wait before querying the database for new inputs. + +* **Type:** `Duration` +* **Default:** `"30"` + ## `CARTESI_EPOCH_LENGTH` Length of a rollups epoch in blocks. @@ -234,7 +241,7 @@ At the end of each epoch, the node will send claims to the blockchain. ## `CARTESI_EVM_READER_RETRY_POLICY_MAX_DELAY` -How seconds the retry policy will wait between retries. +How many seconds the retry policy will wait between retries. * **Type:** `Duration` * **Default:** `"3"` @@ -246,6 +253,13 @@ How many times some functions should be retried after an error. * **Type:** `uint64` * **Default:** `"3"` +## `CARTESI_MAX_CONCURRENT_INSPECTS` + +Maximum number of inspect-state requests that can be concurrently active. + +* **Type:** `uint8` +* **Default:** `"10"` + ## `CARTESI_VALIDATOR_POLLING_INTERVAL` How many seconds the node will wait before trying to finish epochs for all applications. @@ -258,3 +272,38 @@ How many seconds the node will wait before trying to finish epochs for all appli Path to the directory with the cartesi-machine snapshot that will be loaded by the node. * **Type:** `string` + +## `CARTESI_MACHINE_ADVANCE_TIMEOUT` + +TODO. + +* **Type:** `Duration` +* **Default:** `"60"` + +## `CARTESI_MACHINE_INC_CYCLES` + +TODO. + +* **Type:** `uint64` +* **Default:** `"50000000"` + +## `CARTESI_MACHINE_INSPECT_TIMEOUT` + +TODO. + +* **Type:** `Duration` +* **Default:** `"10"` + +## `CARTESI_MACHINE_MAX_CYCLES` + +TODO. + +* **Type:** `uint64` +* **Default:** `"5000000000"` + +## `CARTESI_MACHINE_SERVER_VERBOSITY` + +TODO. + +* **Type:** `string` +* **Default:** `"info"` diff --git a/internal/node/config/config.go b/internal/node/config/config.go index a67323e49..b7f0c8887 100644 --- a/internal/node/config/config.go +++ b/internal/node/config/config.go @@ -8,6 +8,8 @@ package config import ( "fmt" "os" + + "github.com/cartesi/rollups-node/pkg/rollupsmachine/cartesimachine" ) // NodeConfig contains all the Node variables. @@ -39,7 +41,15 @@ type NodeConfig struct { ExperimentalSunodoValidatorEnabled bool ExperimentalSunodoValidatorRedisEndpoint string Auth Auth + MaxConcurrentInspects uint8 + AdvancerPollingInterval Duration ValidatorPollingInterval Duration + // Temporary + MachineServerVerbosity cartesimachine.ServerVerbosity + MachineIncCycles uint64 + MachineMaxCycles uint64 + MachineAdvanceTimeout Duration + MachineInspectTimeout Duration } // Auth is used to sign transactions. @@ -106,7 +116,15 @@ func FromEnv() NodeConfig { if getFeatureClaimerEnabled() && !getExperimentalSunodoValidatorEnabled() { config.Auth = authFromEnv() } + config.MaxConcurrentInspects = getMaxConcurrentInspects() + config.AdvancerPollingInterval = getAdvancerPollingInterval() config.ValidatorPollingInterval = getValidatorPollingInterval() + // Temporary. + config.MachineServerVerbosity = cartesimachine.ServerVerbosity(getMachineServerVerbosity()) + config.MachineIncCycles = getMachineIncCycles() + config.MachineMaxCycles = getMachineMaxCycles() + config.MachineAdvanceTimeout = getMachineAdvanceTimeout() + config.MachineInspectTimeout = getMachineInspectTimeout() return config } diff --git a/internal/node/config/generate/Config.toml b/internal/node/config/generate/Config.toml index a1b9dfe27..c29a98448 100644 --- a/internal/node/config/generate/Config.toml +++ b/internal/node/config/generate/Config.toml @@ -54,7 +54,19 @@ How many times some functions should be retried after an error.""" default = "3" go-type = "Duration" description = """ -How seconds the retry policy will wait between retries.""" +How many seconds the retry policy will wait between retries.""" + +[rollups.CARTESI_MAX_CONCURRENT_INSPECTS] +default = "10" +go-type = "uint8" +description = """ +Maximum number of inspect-state requests that can be concurrently active.""" + +[rollups.CARTESI_ADVANCER_POLLING_INTERVAL] +default = "30" +go-type = "Duration" +description = """ +How many seconds the node will wait before querying the database for new inputs.""" [rollups.CARTESI_VALIDATOR_POLLING_INTERVAL] default = "30" @@ -250,3 +262,37 @@ go-type = "bool" description = """ When enabled, prints server-manager output to stdout and stderr directly. All other log configurations are ignored.""" + +# +# Temporary +# + +[temp.CARTESI_MACHINE_SERVER_VERBOSITY] +default = "info" +go-type = "string" +description = """ +TODO.""" + +[temp.CARTESI_MACHINE_INC_CYCLES] +default = "50000000" +go-type = "uint64" +description = """ +TODO.""" + +[temp.CARTESI_MACHINE_MAX_CYCLES] +default = "5000000000" +go-type = "uint64" +description = """ +TODO.""" + +[temp.CARTESI_MACHINE_ADVANCE_TIMEOUT] +default = "60" +go-type = "Duration" +description = """ +TODO.""" + +[temp.CARTESI_MACHINE_INSPECT_TIMEOUT] +default = "10" +go-type = "Duration" +description = """ +TODO.""" diff --git a/internal/node/config/generate/code.go b/internal/node/config/generate/code.go index 33f30e900..b7dbd0969 100644 --- a/internal/node/config/generate/code.go +++ b/internal/node/config/generate/code.go @@ -100,6 +100,16 @@ func ToInt64FromString(s string) (int64, error) { return strconv.ParseInt(s, 10, 64) } +func ToUint8FromString(s string) (uint8, error) { + value, err := strconv.ParseUint(s, 10, 8) + return uint8(value), err +} + +func ToUint32FromString(s string) (uint32, error) { + value, err := strconv.ParseUint(s, 10, 32) + return uint32(value), err +} + func ToUint64FromString(s string) (uint64, error) { value, err := strconv.ParseUint(s, 10, 64) return value, err @@ -164,6 +174,8 @@ var ( toBool = strconv.ParseBool toInt = strconv.Atoi toInt64 = ToInt64FromString + toUint8 = ToUint8FromString + toUint32 = ToUint32FromString toUint64 = ToUint64FromString toString = ToStringFromString toDuration = ToDurationFromSeconds diff --git a/internal/node/config/generated.go b/internal/node/config/generated.go index 24c899e2e..73f25822a 100644 --- a/internal/node/config/generated.go +++ b/internal/node/config/generated.go @@ -44,6 +44,16 @@ func ToInt64FromString(s string) (int64, error) { return strconv.ParseInt(s, 10, 64) } +func ToUint8FromString(s string) (uint8, error) { + value, err := strconv.ParseUint(s, 10, 8) + return uint8(value), err +} + +func ToUint32FromString(s string) (uint32, error) { + value, err := strconv.ParseUint(s, 10, 32) + return uint32(value), err +} + func ToUint64FromString(s string) (uint64, error) { value, err := strconv.ParseUint(s, 10, 64) return value, err @@ -108,6 +118,8 @@ var ( toBool = strconv.ParseBool toInt = strconv.Atoi toInt64 = ToInt64FromString + toUint8 = ToUint8FromString + toUint32 = ToUint32FromString toUint64 = ToUint64FromString toString = ToStringFromString toDuration = ToDurationFromSeconds @@ -468,6 +480,18 @@ func getPostgresSslmodeEnabled() bool { return val } +func getAdvancerPollingInterval() Duration { + s, ok := os.LookupEnv("CARTESI_ADVANCER_POLLING_INTERVAL") + if !ok { + s = "30" + } + val, err := toDuration(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_ADVANCER_POLLING_INTERVAL: %v", err)) + } + return val +} + func getEpochLength() uint64 { s, ok := os.LookupEnv("CARTESI_EPOCH_LENGTH") if !ok { @@ -504,6 +528,18 @@ func getEvmReaderRetryPolicyMaxRetries() uint64 { return val } +func getMaxConcurrentInspects() uint8 { + s, ok := os.LookupEnv("CARTESI_MAX_CONCURRENT_INSPECTS") + if !ok { + s = "10" + } + val, err := toUint8(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MAX_CONCURRENT_INSPECTS: %v", err)) + } + return val +} + func getValidatorPollingInterval() Duration { s, ok := os.LookupEnv("CARTESI_VALIDATOR_POLLING_INTERVAL") if !ok { @@ -527,3 +563,63 @@ func getSnapshotDir() string { } return val } + +func getMachineAdvanceTimeout() Duration { + s, ok := os.LookupEnv("CARTESI_MACHINE_ADVANCE_TIMEOUT") + if !ok { + s = "60" + } + val, err := toDuration(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MACHINE_ADVANCE_TIMEOUT: %v", err)) + } + return val +} + +func getMachineIncCycles() uint64 { + s, ok := os.LookupEnv("CARTESI_MACHINE_INC_CYCLES") + if !ok { + s = "50000000" + } + val, err := toUint64(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MACHINE_INC_CYCLES: %v", err)) + } + return val +} + +func getMachineInspectTimeout() Duration { + s, ok := os.LookupEnv("CARTESI_MACHINE_INSPECT_TIMEOUT") + if !ok { + s = "10" + } + val, err := toDuration(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MACHINE_INSPECT_TIMEOUT: %v", err)) + } + return val +} + +func getMachineMaxCycles() uint64 { + s, ok := os.LookupEnv("CARTESI_MACHINE_MAX_CYCLES") + if !ok { + s = "5000000000" + } + val, err := toUint64(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MACHINE_MAX_CYCLES: %v", err)) + } + return val +} + +func getMachineServerVerbosity() string { + s, ok := os.LookupEnv("CARTESI_MACHINE_SERVER_VERBOSITY") + if !ok { + s = "info" + } + val, err := toString(s) + if err != nil { + panic(fmt.Sprintf("failed to parse CARTESI_MACHINE_SERVER_VERBOSITY: %v", err)) + } + return val +} diff --git a/internal/repository/advancer.go b/internal/repository/advancer.go index d0492be9b..ab5a7e826 100644 --- a/internal/repository/advancer.go +++ b/internal/repository/advancer.go @@ -18,6 +18,45 @@ var ErrAdvancerRepository = errors.New("advancer repository error") type AdvancerRepository struct{ *Database } +type AppData struct { + AppAddress Address + InputIndex *uint64 + SnapshotPath string +} + +func (repo *AdvancerRepository) GetAppData(ctx context.Context) ([]*AppData, error) { + query := ` + SELECT DISTINCT ON (address) + a.contract_address AS address, + i.index, + COALESCE(s.uri, a.template_uri) + FROM application AS a + LEFT JOIN snapshot AS s ON (a.contract_address = s.application_address) + LEFT JOIN input AS i ON (s.input_id = i.id) + WHERE a.status = 'RUNNING' + ORDER BY address, i.index DESC + ` + rows, err := repo.db.Query(ctx, query) + if err != nil { + return nil, fmt.Errorf("%w (failed querying applications): %w", ErrAdvancerRepository, err) + } + + res := []*AppData{} + var row AppData + + scans := []any{&row.AppAddress, &row.InputIndex, &row.SnapshotPath} + _, err = pgx.ForEachRow(rows, scans, func() error { + row := row + res = append(res, &row) + return nil + }) + if err != nil { + return nil, fmt.Errorf("%w (failed reading rows): %w", ErrAdvancerRepository, err) + } + + return res, nil +} + func (repo *AdvancerRepository) GetUnprocessedInputs( ctx context.Context, apps []Address, diff --git a/internal/repository/advancer_test.go b/internal/repository/advancer_test.go index 6d9191c98..88d6544c4 100644 --- a/internal/repository/advancer_test.go +++ b/internal/repository/advancer_test.go @@ -19,17 +19,34 @@ import ( func TestAdvancerRepository(t *testing.T) { ctx := context.Background() - endpoint, err := db.Setup(ctx) - require.Nil(t, err) + t.Run("GetAppData", func(t *testing.T) { + require := require.New(t) + + endpoint, err := db.Setup(ctx) + require.Nil(err) + + database, err := Connect(ctx, endpoint) + require.Nil(err) + require.NotNil(database) - database, err := Connect(ctx, endpoint) - require.Nil(t, err) - require.NotNil(t, database) + apps, _, _, _, err := populate2(database) + require.Nil(err) + repository := &AdvancerRepository{Database: database} + + res, err := repository.GetAppData(ctx) + require.Nil(err) + require.Len(res, 2) - app, _, _, err := populate(database) - require.Nil(t, err) + appData1, appData2 := res[0], res[1] - repository := &AdvancerRepository{Database: database} + require.Equal(apps[1].ContractAddress, appData2.AppAddress) + require.Equal(uint64(6), *appData2.InputIndex) + require.Equal("path/to/snapshot/2", appData2.SnapshotPath) + + require.Equal(apps[2].ContractAddress, appData1.AppAddress) + require.Nil(appData1.InputIndex) + require.Equal("path/to/template/uri/2", appData1.SnapshotPath) + }) t.Run("GetUnprocessedInputs", func(t *testing.T) { t.Skip("TODO") @@ -42,6 +59,17 @@ func TestAdvancerRepository(t *testing.T) { t.Run("UpdateEpochs", func(t *testing.T) { require := require.New(t) + endpoint, err := db.Setup(ctx) + require.Nil(err) + + database, err := Connect(ctx, endpoint) + require.Nil(err) + require.NotNil(database) + + app, _, _, err := populate1(database) + require.Nil(err) + repository := &AdvancerRepository{Database: database} + err = repository.UpdateEpochs(ctx, app.ContractAddress) require.Nil(err) @@ -70,7 +98,7 @@ func TestAdvancerRepository(t *testing.T) { // ------------------------------------------------------------------------------------------------ -func populate(database *Database) (*Application, []*Epoch, []*Input, error) { +func populate1(database *Database) (*Application, []*Epoch, []*Input, error) { ctx := context.Background() app := &Application{ @@ -81,7 +109,7 @@ func populate(database *Database) (*Application, []*Epoch, []*Input, error) { Status: "RUNNING", } - err := database.InsertApplication(ctx, app) + _, err := database.InsertApplication(ctx, app) if err != nil { return nil, nil, nil, err } @@ -161,3 +189,123 @@ func populate(database *Database) (*Application, []*Epoch, []*Input, error) { return app, epochs, inputs, nil } + +// ------------------------------------------------------------------------------------------------ + +func populate2(database *Database) ([]*Application, []*Epoch, []*Input, []*Snapshot, error) { + ctx := context.Background() + + apps := []*Application{{ + ContractAddress: common.HexToAddress("dead"), + TemplateUri: "path/to/template/uri/0", + Status: ApplicationStatusNotRunning, + }, { + ContractAddress: common.HexToAddress("beef"), + TemplateUri: "path/to/template/uri/1", + Status: ApplicationStatusRunning, + }, { + ContractAddress: common.HexToAddress("bead"), + TemplateUri: "path/to/template/uri/2", + Status: ApplicationStatusRunning, + }} + if err := database.InsertApps(ctx, apps); err != nil { + return nil, nil, nil, nil, err + } + + epochs := []*Epoch{{ + Index: 0, + Status: EpochStatusClosed, + AppAddress: apps[1].ContractAddress, + }, { + Index: 1, + Status: EpochStatusClosed, + AppAddress: apps[1].ContractAddress, + }, { + Status: EpochStatusClosed, + AppAddress: apps[2].ContractAddress, + }} + err := database.InsertEpochs(ctx, epochs) + if err != nil { + return nil, nil, nil, nil, err + } + + inputs := []*Input{{ + Index: 0, + CompletionStatus: InputStatusAccepted, + RawData: []byte("first"), + AppAddress: apps[1].ContractAddress, + EpochId: epochs[0].Id, + }, { + Index: 6, + CompletionStatus: InputStatusAccepted, + RawData: []byte("second"), + AppAddress: apps[1].ContractAddress, + EpochId: epochs[1].Id, + }} + err = database.InsertInputs(ctx, inputs) + if err != nil { + return nil, nil, nil, nil, err + } + + snapshots := []*Snapshot{{ + URI: "path/to/snapshot/1", + InputId: inputs[0].Id, + AppAddress: apps[1].ContractAddress, + }, { + URI: "path/to/snapshot/2", + InputId: inputs[1].Id, + AppAddress: apps[1].ContractAddress, + }} + err = database.InsertSnapshots(ctx, snapshots) + if err != nil { + return nil, nil, nil, nil, err + } + + return apps, epochs, inputs, snapshots, nil +} + +// ------------------------------------------------------------------------------------------------ + +func (pg *Database) InsertApps(ctx context.Context, apps []*Application) error { + var err error + for _, app := range apps { + app.Id, err = pg.InsertApplication(ctx, app) + if err != nil { + return err + } + } + return nil +} + +func (pg *Database) InsertEpochs(ctx context.Context, epochs []*Epoch) error { + var err error + for _, epoch := range epochs { + epoch.Id, err = pg.InsertEpoch(ctx, epoch) + if err != nil { + return err + } + } + return nil +} + +func (pg *Database) InsertInputs(ctx context.Context, inputs []*Input) error { + var err error + for _, input := range inputs { + input.Id, err = pg.InsertInput(ctx, input) + if err != nil { + return err + } + } + return nil +} + +func (pg *Database) InsertSnapshots(ctx context.Context, snapshots []*Snapshot) error { + var err error + for _, snapshot := range snapshots { + snapshot.Id, err = pg.InsertSnapshot(ctx, snapshot) + if err != nil { + return err + } + } + return nil +} diff --git a/internal/repository/base.go b/internal/repository/base.go index 3cc6cf4d0..d2db371e9 100644 --- a/internal/repository/base.go +++ b/internal/repository/base.go @@ -91,35 +91,41 @@ func (pg *Database) InsertNodeConfig( func (pg *Database) InsertApplication( ctx context.Context, app *Application, -) error { +) (id uint64, _ error) { query := ` INSERT INTO application (contract_address, template_hash, + template_uri, last_processed_block, status, iconsensus_address) VALUES (@contractAddress, @templateHash, + @templateUri, @lastProcessedBlock, @status, - @iConsensusAddress)` + @iConsensusAddress) + RETURNING + id + ` args := pgx.NamedArgs{ "contractAddress": app.ContractAddress, "templateHash": app.TemplateHash, + "templateUri": app.TemplateUri, "lastProcessedBlock": app.LastProcessedBlock, "status": app.Status, "iConsensusAddress": app.IConsensusAddress, } - _, err := pg.db.Exec(ctx, query, args) + err := pg.db.QueryRow(ctx, query, args).Scan(&id) if err != nil { - return fmt.Errorf("%w: %w", ErrInsertRow, err) + return 0, fmt.Errorf("%w: %w", ErrInsertRow, err) } - return nil + return id, nil } func (pg *Database) InsertEpoch( diff --git a/internal/repository/base_test.go b/internal/repository/base_test.go index 1abd680ab..fbcb4267c 100644 --- a/internal/repository/base_test.go +++ b/internal/repository/base_test.go @@ -85,10 +85,10 @@ func (s *RepositorySuite) SetupDatabase() { Status: ApplicationStatusNotRunning, } - err = s.database.InsertApplication(s.ctx, &app) + _, err = s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) - err = s.database.InsertApplication(s.ctx, &app2) + _, err = s.database.InsertApplication(s.ctx, &app2) s.Require().Nil(err) genericHash := common.HexToHash("deadbeef") @@ -257,7 +257,7 @@ func (s *RepositorySuite) TestApplicationFailsDuplicateRow() { Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, &app) + _, err := s.database.InsertApplication(s.ctx, &app) s.Require().ErrorContains(err, "duplicate key value") } diff --git a/internal/repository/schema/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql b/internal/repository/schema/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql index a4c6483fb..7f0da3707 100644 --- a/internal/repository/schema/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql +++ b/internal/repository/schema/migrations/000001_create_application_input_claim_output_report_nodeconfig.up.sql @@ -34,6 +34,7 @@ CREATE TABLE "application" "id" SERIAL, "contract_address" BYTEA NOT NULL, "template_hash" BYTEA NOT NULL, + "template_uri" VARCHAR(4096) NOT NULL, "last_processed_block" NUMERIC(20,0) NOT NULL CHECK ("last_processed_block" >= 0 AND "last_processed_block" <= f_maxuint64()), "status" "ApplicationStatus" NOT NULL, "iconsensus_address" BYTEA NOT NULL, diff --git a/internal/repository/validator_test.go b/internal/repository/validator_test.go index 20731405c..d5983908e 100644 --- a/internal/repository/validator_test.go +++ b/internal/repository/validator_test.go @@ -24,7 +24,7 @@ func (s *RepositorySuite) TestGetOutputsProducedInBlockRange() { TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err = s.database.InsertApplication(s.ctx, &app) + _, err = s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) epoch := Epoch{ @@ -77,7 +77,7 @@ func (s *RepositorySuite) TestGetProcessedEpochs() { TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, &app) + _, err := s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) // no epochs, should return nothing @@ -123,7 +123,7 @@ func (s *RepositorySuite) TestGetLastInputOutputHash() { TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, &app) + _, err := s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) epoch := Epoch{ @@ -193,7 +193,7 @@ func (s *RepositorySuite) TestGetPreviousEpoch() { TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, app) + _, err := s.database.InsertApplication(s.ctx, app) s.Require().Nil(err) epoch := Epoch{ @@ -234,7 +234,7 @@ func (s *RepositorySuite) TestSetEpochClaimAndInsertProofsTransaction() { TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, &app) + _, err := s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) epoch := Epoch{ @@ -321,7 +321,7 @@ func (s *RepositorySuite) TestSetEpochClaimAndInsertProofsTransactionRollback() TemplateHash: common.BytesToHash([]byte("template")), Status: ApplicationStatusRunning, } - err := s.database.InsertApplication(s.ctx, &app) + _, err := s.database.InsertApplication(s.ctx, &app) s.Require().Nil(err) epoch := Epoch{ diff --git a/test/advancer/advancer_test.go b/test/advancer/advancer_test.go index aeeae06ff..a1d262e95 100644 --- a/test/advancer/advancer_test.go +++ b/test/advancer/advancer_test.go @@ -124,7 +124,7 @@ func populate(database *repository.Database) (*Application, []*Epoch, []*Input, Status: "RUNNING", } - err := database.InsertApplication(ctx, app) + _, err := database.InsertApplication(ctx, app) if err != nil { return nil, nil, nil, err } diff --git a/test/snapshot/snapshot.go b/test/snapshot/snapshot.go index 6b9a75c2b..6cba9fe3d 100644 --- a/test/snapshot/snapshot.go +++ b/test/snapshot/snapshot.go @@ -22,6 +22,12 @@ const ramLength = 64 << 20 // It can be redefined in case the files are not in the default folder. var ImagesPath = "/usr/share/cartesi-machine/images/" +func init() { + if value, ok := os.LookupEnv("TESTS_IMAGES_PATH"); ok { + ImagesPath = value + } +} + type Snapshot struct { id string // an unique id used to avoid name clashing temp string // path to the temporary directory containing snapshot relevant files diff --git a/test/tooling/db/db.go b/test/tooling/db/db.go index 2520bc83b..61123d7c6 100644 --- a/test/tooling/db/db.go +++ b/test/tooling/db/db.go @@ -22,7 +22,7 @@ const ( ) func Setup(ctx context.Context) (string, error) { - endpoint, ok := os.LookupEnv("TEST_POSTGRES_ENDPOINT") + endpoint, ok := os.LookupEnv("TESTS_POSTGRES_ENDPOINT") if !ok { container, err := SetupContainer(ctx) if err != nil {