diff --git a/.github/image/Dockerfile b/.github/image/Dockerfile index 1e08d5eb3..e523a1b69 100644 --- a/.github/image/Dockerfile +++ b/.github/image/Dockerfile @@ -23,7 +23,7 @@ RUN git submodule update --init RUN go mod download # Stage 2: Install Lotus binary -FROM ghcr.io/filecoin-shipyard/lotus-containers:lotus-v1.32.1-devnet AS lotus-test +FROM ghcr.io/filecoin-shipyard/lotus-containers:lotus-v1.32.2-devnet AS lotus-test # Stage 3: Build the final image FROM myoung34/github-runner AS curio-github-runner diff --git a/Makefile b/Makefile index d20f59d88..319bbbd70 100644 --- a/Makefile +++ b/Makefile @@ -270,7 +270,7 @@ build_lotus?=0 curio_docker_user?=curio curio_base_image=$(curio_docker_user)/curio-all-in-one:latest-debug ffi_from_source?=0 -lotus_version?=v1.32.1 +lotus_version?=v1.32.2 ifeq ($(build_lotus),1) # v1: building lotus image with provided lotus version diff --git a/cmd/curio/config_new.go b/cmd/curio/config_new.go index 059d3f2e6..12a9de0b3 100644 --- a/cmd/curio/config_new.go +++ b/cmd/curio/config_new.go @@ -25,9 +25,13 @@ var configNewCmd = &cli.Command{ Hidden: true, Value: "~/.lotus", }, + &cli.BoolFlag{ + Name: "pdp", + Usage: "initiate a PDP only cluster", + }, }, Action: func(cctx *cli.Context) error { - if cctx.Args().Len() < 1 { + if !cctx.Bool("pdp") && cctx.Args().Len() < 1 { return xerrors.New("must specify at least one SP actor address. Use 'lotus-shed miner create' or use 'curio guided-setup'") } @@ -54,6 +58,10 @@ var configNewCmd = &cli.Command{ return err } + if cctx.Bool("pdp") { + return deps.CreatePDPConfig(ctx, db, fmt.Sprintf("%s:%s", string(token), ainfo.Addr)) + } + return deps.CreateMinerConfig(ctx, full, db, cctx.Args().Slice(), fmt.Sprintf("%s:%s", string(token), ainfo.Addr)) }, } diff --git a/cmd/curio/guidedsetup/guidedsetup.go b/cmd/curio/guidedsetup/guidedsetup.go index fff2a713c..e275f7f14 100644 --- a/cmd/curio/guidedsetup/guidedsetup.go +++ b/cmd/curio/guidedsetup/guidedsetup.go @@ -79,12 +79,20 @@ var GuidedsetupCmd = &cli.Command{ } newOrMigrate(&migrationData) - if migrationData.init { + if migrationData.init && !migrationData.initPDP { say(header, "This interactive tool creates a new miner actor and creates the basic configuration layer for it.") say(notice, "This process is partially idempotent. Once a new miner actor has been created and subsequent steps fail, the user need to run 'curio config new-cluster < miner ID >' to finish the configuration.") for _, step := range newMinerSteps { step(&migrationData) } + } else if !migrationData.init && migrationData.initPDP { + say(header, "This interactive tool creates a new PDP only provider and creates the basic configuration layer for it.") + for _, step := range newPDPSteps { + step(&migrationData) + } + } else if migrationData.init && migrationData.initPDP { + say(header, "This interactive tool does not support creating a new miner and PDP only provider at the same time.") + os.Exit(1) } else { say(header, "This interactive tool migrates lotus-miner to Curio in 5 minutes.") say(notice, "Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.") @@ -149,7 +157,8 @@ func newOrMigrate(d *MigrationData) { Label: d.T("I want to:"), Items: []string{ d.T("Migrate from existing Lotus-Miner"), - d.T("Create a new miner")}, + d.T("Create a new miner"), + d.T("Create a PDP only provider")}, Templates: d.selectTemplates, }).Run() if err != nil { @@ -159,6 +168,9 @@ func newOrMigrate(d *MigrationData) { if i == 1 { d.init = true } + if i == 2 { + d.initPDP = true + } } type migrationStep func(*MigrationData) @@ -185,6 +197,14 @@ var newMinerSteps = []newMinerStep{ afterRan, } +type newPDPStep func(data *MigrationData) + +var newPDPSteps = []newPDPStep{ + pdp, + doc, + afterRan, +} + type MigrationData struct { T func(key message.Reference, a ...interface{}) string say func(style lipgloss.Style, key message.Reference, a ...interface{}) @@ -202,6 +222,7 @@ type MigrationData struct { sender address.Address ssize string init bool + initPDP bool } func complete(d *MigrationData) { @@ -786,3 +807,100 @@ func getDBDetails(d *MigrationData) { } } } + +func pdp(d *MigrationData) { + // Setup and connect to YugabyteDB + getDBDetails(d) + + // Check that we don't have a miner address + var titles []struct { + Title string `db:"title"` + Config string `db:"config"` + } + + var configs []string + + err := d.DB.Select(d.ctx, &titles, `SELECT title, config FROM harmony_config WHERE LENGTH(config) > 0`) + if err != nil { + d.say(notice, "Cannot reach the DB: %s", err.Error()) + os.Exit(1) + } + + curioConfig := config.DefaultCurioConfig() + + for _, t := range titles { + _, err := deps.LoadConfigWithUpgrades(t.Config, curioConfig) + if err != nil { + d.say(notice, "Cannot parse config %s: %s", t.Title, err.Error()) + os.Exit(1) + } + configs = append(configs, t.Title) + } + + if len(curioConfig.Addresses) > 0 { + if curioConfig.Addresses[0].MinerAddresses[0] != "" { + d.say(notice, "Miner address already exists in the config. Cannot initiate a new PDP only cluster") + os.Exit(1) + } + } + + curioConfig = config.DefaultCurioConfig() + curioConfig.Addresses = append(curioConfig.Addresses, config.CurioAddresses{ + PreCommitControl: []string{}, + CommitControl: []string{}, + DealPublishControl: []string{}, + TerminateControl: []string{}, + DisableOwnerFallback: false, + DisableWorkerFallback: false, + MinerAddresses: []string{}, + BalanceManager: config.DefaultBalanceManager(), + }) + + sk, err := io.ReadAll(io.LimitReader(rand.Reader, 32)) + if err != nil { + d.say(notice, "Failed to generate random bytes for secret: %s", err.Error()) + os.Exit(1) + } + + // Get full node API + full, closer, err := cliutil.GetFullNodeAPIV1(d.cctx) + if err != nil { + d.say(notice, "Error connecting to full node API: %s", err.Error()) + os.Exit(1) + } + d.full = full + d.closers = append(d.closers, closer) + + ainfo, err := cliutil.GetAPIInfo(d.cctx, repo.FullNode) + if err != nil { + d.say(notice, "Failed to get API info for FullNode: %w", err) + d.say(notice, "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster %s' to finish the configuration", d.MinerID.String()) + os.Exit(1) + } + + token, err := d.full.AuthNew(d.ctx, lapi.AllPermissions) + if err != nil { + d.say(notice, "Failed to verify the auth token from daemon node: %s", err.Error()) + d.say(notice, "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster %s' to finish the configuration", d.MinerID.String()) + os.Exit(1) + } + + curioConfig.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(sk) + + curioConfig.Apis.ChainApiInfo = append(curioConfig.Apis.ChainApiInfo, fmt.Sprintf("%s:%s", string(token), ainfo.Addr)) + + if !lo.Contains(configs, "base") { + cb, err := config.ConfigUpdate(curioConfig, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv()) + if err != nil { + d.say(notice, "Failed to generate default config: %s", err.Error()) + os.Exit(1) + } + _, err = d.DB.Exec(d.ctx, "INSERT INTO harmony_config (title, config) VALUES ('base', $1)", string(cb)) + if err != nil { + d.say(notice, "Failed to insert 'base' config layer in database: %s", err.Error()) + os.Exit(1) + } + } + + stepCompleted(d, d.T("Initialization steps complete")) +} diff --git a/deps/deps.go b/deps/deps.go index 839e56427..2df457677 100644 --- a/deps/deps.go +++ b/deps/deps.go @@ -719,3 +719,47 @@ func CreateMinerConfig(ctx context.Context, full CreateMinerConfigChainAPI, db * fmt.Printf("The base layer has been updated with miner[s] %s\n", miners) return nil } +func CreatePDPConfig(ctx context.Context, db *harmonydb.DB, info string) error { + var titles []string + err := db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`) + if err != nil { + return fmt.Errorf("cannot reach the db. Ensure that Yugabyte flags are set correctly to"+ + " reach Yugabyte: %s", err.Error()) + } + + // setup config + curioConfig := config.DefaultCurioConfig() + curioConfig.Addresses = append(curioConfig.Addresses, config.CurioAddresses{ + PreCommitControl: []string{}, + CommitControl: []string{}, + DealPublishControl: []string{}, + TerminateControl: []string{}, + DisableOwnerFallback: false, + DisableWorkerFallback: false, + MinerAddresses: []string{}, + BalanceManager: config.DefaultBalanceManager(), + }) + + sk, err := io.ReadAll(io.LimitReader(rand.Reader, 32)) + if err != nil { + return err + } + + curioConfig.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(sk) + + curioConfig.Apis.ChainApiInfo = append(curioConfig.Apis.ChainApiInfo, info) + if !lo.Contains(titles, "base") { + cb, err := config.ConfigUpdate(curioConfig, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv()) + if err != nil { + return xerrors.Errorf("Failed to generate default config: %w", err) + } + cfg := string(cb) + _, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ('base', $1)", cfg) + if err != nil { + return xerrors.Errorf("failed to insert the 'base' into the database: %w", err) + } + fmt.Println("The base layer has been created for PDP only provider") + return nil + } + return xerrors.Errorf("base layer already exists") +} diff --git a/docker/curio/entrypoint.sh b/docker/curio/entrypoint.sh index 339f8182c..87306bca8 100755 --- a/docker/curio/entrypoint.sh +++ b/docker/curio/entrypoint.sh @@ -83,5 +83,5 @@ if [ ! -f $CURIO_REPO_PATH/.init.curio ]; then fi echo Starting curio node ... -exec curio run --nosync --name devnet --layers seal,post,market,gui +exec curio run --nosync --name devnet --layers market,gui