v1.27.0-a #10
@ -554,6 +554,12 @@ workflows:
|
|||||||
- build
|
- build
|
||||||
suite: itest-cli
|
suite: itest-cli
|
||||||
target: "./itests/cli_test.go"
|
target: "./itests/cli_test.go"
|
||||||
|
- test:
|
||||||
|
name: test-itest-curio
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
suite: itest-curio
|
||||||
|
target: "./itests/curio_test.go"
|
||||||
- test:
|
- test:
|
||||||
name: test-itest-deadlines
|
name: test-itest-deadlines
|
||||||
requires:
|
requires:
|
||||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -124,7 +124,7 @@ jobs:
|
|||||||
# A list of test groups that require YugabyteDB to be running
|
# A list of test groups that require YugabyteDB to be running
|
||||||
# In CircleCI, all jobs had yugabytedb running as a sidecar.
|
# In CircleCI, all jobs had yugabytedb running as a sidecar.
|
||||||
yugabytedb: |
|
yugabytedb: |
|
||||||
["itest-harmonydb", "itest-harmonytask"]
|
["itest-harmonydb", "itest-harmonytask", "itest-curio"]
|
||||||
# A list of test groups that require Proof Parameters to be fetched
|
# A list of test groups that require Proof Parameters to be fetched
|
||||||
# In CircleCI, only the following jobs had get-params set:
|
# In CircleCI, only the following jobs had get-params set:
|
||||||
# - unit-cli (✅)
|
# - unit-cli (✅)
|
||||||
|
@ -2,9 +2,11 @@ package spcli
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/docker/go-units"
|
||||||
cbor "github.com/ipfs/go-ipld-cbor"
|
cbor "github.com/ipfs/go-ipld-cbor"
|
||||||
"github.com/libp2p/go-libp2p/core/peer"
|
"github.com/libp2p/go-libp2p/core/peer"
|
||||||
ma "github.com/multiformats/go-multiaddr"
|
ma "github.com/multiformats/go-multiaddr"
|
||||||
@ -19,16 +21,20 @@ import (
|
|||||||
"github.com/filecoin-project/go-state-types/builtin"
|
"github.com/filecoin-project/go-state-types/builtin"
|
||||||
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
"github.com/filecoin-project/go-state-types/builtin/v9/miner"
|
||||||
"github.com/filecoin-project/go-state-types/network"
|
"github.com/filecoin-project/go-state-types/network"
|
||||||
|
power2 "github.com/filecoin-project/specs-actors/v2/actors/builtin/power"
|
||||||
|
power6 "github.com/filecoin-project/specs-actors/v6/actors/builtin/power"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
|
||||||
lapi "github.com/filecoin-project/lotus/api"
|
lapi "github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/api/v1api"
|
||||||
"github.com/filecoin-project/lotus/blockstore"
|
"github.com/filecoin-project/lotus/blockstore"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/actors"
|
"github.com/filecoin-project/lotus/chain/actors"
|
||||||
"github.com/filecoin-project/lotus/chain/actors/adt"
|
"github.com/filecoin-project/lotus/chain/actors/adt"
|
||||||
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
lminer "github.com/filecoin-project/lotus/chain/actors/builtin/miner"
|
||||||
|
"github.com/filecoin-project/lotus/chain/actors/builtin/power"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
lcli "github.com/filecoin-project/lotus/cli"
|
lcli "github.com/filecoin-project/lotus/cli"
|
||||||
|
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||||
"github.com/filecoin-project/lotus/node/impl"
|
"github.com/filecoin-project/lotus/node/impl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1225,7 +1231,7 @@ func ActorCompactAllocatedCmd(getActor ActorAddressGetter) *cli.Command {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isController(mi api.MinerInfo, addr address.Address) bool {
|
func isController(mi lapi.MinerInfo, addr address.Address) bool {
|
||||||
if addr == mi.Owner || addr == mi.Worker {
|
if addr == mi.Owner || addr == mi.Worker {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -1238,3 +1244,190 @@ func isController(mi api.MinerInfo, addr address.Address) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ActorNewMinerCmd = &cli.Command{
|
||||||
|
Name: "new-miner",
|
||||||
|
Usage: "Initializes a new miner actor",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "worker",
|
||||||
|
Aliases: []string{"w"},
|
||||||
|
Usage: "worker key to use for new miner initialisation",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "owner",
|
||||||
|
Aliases: []string{"o"},
|
||||||
|
Usage: "owner key to use for new miner initialisation",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "from",
|
||||||
|
Aliases: []string{"f"},
|
||||||
|
Usage: "address to send actor(miner) creation message from",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "sector-size",
|
||||||
|
Usage: "specify sector size to use for new miner initialisation",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
ctx := cctx.Context
|
||||||
|
|
||||||
|
full, closer, err := cliutil.GetFullNodeAPIV1(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("connecting to full node: %w", err)
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
|
||||||
|
var owner address.Address
|
||||||
|
if cctx.String("owner") == "" {
|
||||||
|
return xerrors.Errorf("must provide a owner address")
|
||||||
|
}
|
||||||
|
owner, err = address.NewFromString(cctx.String("owner"))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
worker := owner
|
||||||
|
if cctx.String("worker") != "" {
|
||||||
|
worker, err = address.NewFromString(cctx.String("worker"))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("could not parse worker address: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sender := owner
|
||||||
|
if fromstr := cctx.String("from"); fromstr != "" {
|
||||||
|
faddr, err := address.NewFromString(fromstr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("could not parse from address: %w", err)
|
||||||
|
}
|
||||||
|
sender = faddr
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cctx.IsSet("sector-size") {
|
||||||
|
return xerrors.Errorf("must define sector size")
|
||||||
|
}
|
||||||
|
|
||||||
|
sectorSizeInt, err := units.RAMInBytes(cctx.String("sector-size"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ssize := abi.SectorSize(sectorSizeInt)
|
||||||
|
|
||||||
|
_, err = CreateStorageMiner(ctx, full, owner, worker, sender, ssize, cctx.Uint64("confidence"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateStorageMiner(ctx context.Context, fullNode v1api.FullNode, owner, worker, sender address.Address, ssize abi.SectorSize, confidence uint64) (address.Address, error) {
|
||||||
|
// make sure the sender account exists on chain
|
||||||
|
_, err := fullNode.StateLookupID(ctx, owner, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("sender must exist on chain: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the worker account exists on chain
|
||||||
|
_, err = fullNode.StateLookupID(ctx, worker, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
signed, err := fullNode.MpoolPushMessage(ctx, &types.Message{
|
||||||
|
From: sender,
|
||||||
|
To: worker,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("push worker init: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Initializing worker account %s, message: %s\n", worker, signed.Cid())
|
||||||
|
fmt.Println("Waiting for confirmation")
|
||||||
|
|
||||||
|
mw, err := fullNode.StateWaitMsg(ctx, signed.Cid(), confidence, 2000, true)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("waiting for worker init: %w", err)
|
||||||
|
}
|
||||||
|
if mw.Receipt.ExitCode != 0 {
|
||||||
|
return address.Undef, xerrors.Errorf("initializing worker account failed: exit code %d", mw.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure the owner account exists on chain
|
||||||
|
_, err = fullNode.StateLookupID(ctx, owner, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
signed, err := fullNode.MpoolPushMessage(ctx, &types.Message{
|
||||||
|
From: sender,
|
||||||
|
To: owner,
|
||||||
|
Value: types.NewInt(0),
|
||||||
|
}, nil)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("push owner init: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Initializing owner account %s, message: %s\n", worker, signed.Cid())
|
||||||
|
fmt.Println("Waiting for confirmation")
|
||||||
|
|
||||||
|
mw, err := fullNode.StateWaitMsg(ctx, signed.Cid(), confidence, 2000, true)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("waiting for owner init: %w", err)
|
||||||
|
}
|
||||||
|
if mw.Receipt.ExitCode != 0 {
|
||||||
|
return address.Undef, xerrors.Errorf("initializing owner account failed: exit code %d", mw.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: the correct thing to do would be to call SealProofTypeFromSectorSize if actors version is v3 or later, but this still works
|
||||||
|
nv, err := fullNode.StateNetworkVersion(ctx, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("failed to get network version: %w", err)
|
||||||
|
}
|
||||||
|
spt, err := lminer.WindowPoStProofTypeFromSectorSize(ssize, nv)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("getting post proof type: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
params, err := actors.SerializeParams(&power6.CreateMinerParams{
|
||||||
|
Owner: owner,
|
||||||
|
Worker: worker,
|
||||||
|
WindowPoStProofType: spt,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
createStorageMinerMsg := &types.Message{
|
||||||
|
To: power.Address,
|
||||||
|
From: sender,
|
||||||
|
Value: big.Zero(),
|
||||||
|
|
||||||
|
Method: power.Methods.CreateMiner,
|
||||||
|
Params: params,
|
||||||
|
}
|
||||||
|
|
||||||
|
signed, err := fullNode.MpoolPushMessage(ctx, createStorageMinerMsg, nil)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("pushing createMiner message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Pushed CreateMiner message: %s\n", signed.Cid())
|
||||||
|
fmt.Println("Waiting for confirmation")
|
||||||
|
|
||||||
|
mw, err := fullNode.StateWaitMsg(ctx, signed.Cid(), confidence, 2000, true)
|
||||||
|
if err != nil {
|
||||||
|
return address.Undef, xerrors.Errorf("waiting for createMiner message: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if mw.Receipt.ExitCode != 0 {
|
||||||
|
return address.Undef, xerrors.Errorf("create miner failed: exit code %d", mw.Receipt.ExitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
var retval power2.CreateMinerReturn
|
||||||
|
if err := retval.UnmarshalCBOR(bytes.NewReader(mw.Receipt.Return)); err != nil {
|
||||||
|
return address.Undef, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("New miners address is: %s (%s)\n", retval.IDAddress, retval.RobustAddress)
|
||||||
|
return retval.IDAddress, nil
|
||||||
|
}
|
||||||
|
@ -352,15 +352,6 @@ var configEditCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDefaultConfig(comment bool) (string, error) {
|
|
||||||
c := config.DefaultCurioConfig()
|
|
||||||
cb, err := config.ConfigUpdate(c, nil, config.Commented(comment), config.DefaultKeepUncommented(), config.NoEnv())
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return string(cb), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func diff(sourceConf, newConf string) (string, error) {
|
func diff(sourceConf, newConf string) (string, error) {
|
||||||
lpSrc := config.DefaultCurioConfig()
|
lpSrc := config.DefaultCurioConfig()
|
||||||
lpNew := config.DefaultCurioConfig()
|
lpNew := config.DefaultCurioConfig()
|
||||||
|
@ -1,25 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"crypto/rand"
|
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
|
||||||
"github.com/fatih/color"
|
|
||||||
"github.com/samber/lo"
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
|
||||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||||
"github.com/filecoin-project/lotus/node/config"
|
|
||||||
"github.com/filecoin-project/lotus/node/repo"
|
"github.com/filecoin-project/lotus/node/repo"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -36,10 +25,8 @@ var configNewCmd = &cli.Command{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: func(cctx *cli.Context) error {
|
Action: func(cctx *cli.Context) error {
|
||||||
configColor := color.New(color.FgHiGreen).SprintFunc()
|
|
||||||
|
|
||||||
if cctx.Args().Len() < 1 {
|
if cctx.Args().Len() < 1 {
|
||||||
return xerrors.New("must specify at least one SP actor address. Use 'lotus-shed miner create'")
|
return xerrors.New("must specify at least one SP actor address. Use 'lotus-shed miner create' or use 'curio guided-setup'")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := cctx.Context
|
ctx := cctx.Context
|
||||||
@ -55,57 +42,6 @@ var configNewCmd = &cli.Command{
|
|||||||
}
|
}
|
||||||
defer closer()
|
defer closer()
|
||||||
|
|
||||||
var titles []string
|
|
||||||
err = db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("miner cannot reach the db. Ensure the config toml's HarmonyDB entry"+
|
|
||||||
" is setup to reach Yugabyte correctly: %s", err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
name := cctx.String("to-layer")
|
|
||||||
if name == "" {
|
|
||||||
name = fmt.Sprintf("cluster%d", len(titles))
|
|
||||||
} else {
|
|
||||||
if lo.Contains(titles, name) && !cctx.Bool("overwrite") {
|
|
||||||
return xerrors.New("the overwrite flag is needed to replace existing layer: " + name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg := "Layer " + configColor(name) + ` created. `
|
|
||||||
|
|
||||||
// setup config
|
|
||||||
lpCfg := config.DefaultCurioConfig()
|
|
||||||
|
|
||||||
for _, addr := range cctx.Args().Slice() {
|
|
||||||
maddr, err := address.NewFromString(addr)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("Invalid address: %s", addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = full.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("Failed to get miner info: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
lpCfg.Addresses = append(lpCfg.Addresses, config.CurioAddresses{
|
|
||||||
PreCommitControl: nil,
|
|
||||||
CommitControl: nil,
|
|
||||||
TerminateControl: nil,
|
|
||||||
DisableOwnerFallback: false,
|
|
||||||
DisableWorkerFallback: false,
|
|
||||||
MinerAddresses: []string{addr},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
sk, err := io.ReadAll(io.LimitReader(rand.Reader, 32))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
lpCfg.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(sk)
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ainfo, err := cliutil.GetAPIInfo(cctx, repo.FullNode)
|
ainfo, err := cliutil.GetAPIInfo(cctx, repo.FullNode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return xerrors.Errorf("could not get API info for FullNode: %w", err)
|
return xerrors.Errorf("could not get API info for FullNode: %w", err)
|
||||||
@ -116,44 +52,6 @@ var configNewCmd = &cli.Command{
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
lpCfg.Apis.ChainApiInfo = append(lpCfg.Apis.ChainApiInfo, 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))
|
||||||
}
|
|
||||||
|
|
||||||
// write config
|
|
||||||
|
|
||||||
configTOML := &bytes.Buffer{}
|
|
||||||
if err = toml.NewEncoder(configTOML).Encode(lpCfg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !lo.Contains(titles, "base") {
|
|
||||||
cfg, err := getDefaultConfig(true)
|
|
||||||
if err != nil {
|
|
||||||
return xerrors.Errorf("Cannot get default config: %w", err)
|
|
||||||
}
|
|
||||||
_, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ('base', $1)", cfg)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cctx.Bool("overwrite") {
|
|
||||||
i, err := db.Exec(ctx, "DELETE FROM harmony_config WHERE title=$1", name)
|
|
||||||
if i != 0 {
|
|
||||||
fmt.Println("Overwriting existing layer")
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Got error while deleting existing layer: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ($1, $2)", name, configTOML.String())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(msg)
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
416
cmd/curio/config_test.go
Normal file
416
cmd/curio/config_test.go
Normal file
@ -0,0 +1,416 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||||
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baseText string = `
|
||||||
|
[Subsystems]
|
||||||
|
# EnableWindowPost enables window post to be executed on this lotus-provider instance. Each machine in the cluster
|
||||||
|
# with WindowPoSt enabled will also participate in the window post scheduler. It is possible to have multiple
|
||||||
|
# machines with WindowPoSt enabled which will provide redundancy, and in case of multiple partitions per deadline,
|
||||||
|
# will allow for parallel processing of partitions.
|
||||||
|
#
|
||||||
|
# It is possible to have instances handling both WindowPoSt and WinningPoSt, which can provide redundancy without
|
||||||
|
# the need for additional machines. In setups like this it is generally recommended to run
|
||||||
|
# partitionsPerDeadline+1 machines.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableWindowPost = false
|
||||||
|
|
||||||
|
# type: int
|
||||||
|
#WindowPostMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableWinningPost enables winning post to be executed on this lotus-provider instance.
|
||||||
|
# Each machine in the cluster with WinningPoSt enabled will also participate in the winning post scheduler.
|
||||||
|
# It is possible to mix machines with WindowPoSt and WinningPoSt enabled, for details see the EnableWindowPost
|
||||||
|
# documentation.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableWinningPost = false
|
||||||
|
|
||||||
|
# type: int
|
||||||
|
#WinningPostMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableParkPiece enables the "piece parking" task to run on this node. This task is responsible for fetching
|
||||||
|
# pieces from the network and storing them in the storage subsystem until sectors are sealed. This task is
|
||||||
|
# only applicable when integrating with boost, and should be enabled on nodes which will hold deal data
|
||||||
|
# from boost until sectors containing the related pieces have the TreeD/TreeR constructed.
|
||||||
|
# Note that future Curio implementations will have a separate task type for fetching pieces from the internet.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableParkPiece = false
|
||||||
|
|
||||||
|
# type: int
|
||||||
|
#ParkPieceMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableSealSDR enables SDR tasks to run. SDR is the long sequential computation
|
||||||
|
# creating 11 layer files in sector cache directory.
|
||||||
|
#
|
||||||
|
# SDR is the first task in the sealing pipeline. It's inputs are just the hash of the
|
||||||
|
# unsealed data (CommD), sector number, miner id, and the seal proof type.
|
||||||
|
# It's outputs are the 11 layer files in the sector cache directory.
|
||||||
|
#
|
||||||
|
# In lotus-miner this was run as part of PreCommit1.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableSealSDR = false
|
||||||
|
|
||||||
|
# The maximum amount of SDR tasks that can run simultaneously. Note that the maximum number of tasks will
|
||||||
|
# also be bounded by resources available on the machine.
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#SealSDRMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableSealSDRTrees enables the SDR pipeline tree-building task to run.
|
||||||
|
# This task handles encoding of unsealed data into last sdr layer and building
|
||||||
|
# of TreeR, TreeC and TreeD.
|
||||||
|
#
|
||||||
|
# This task runs after SDR
|
||||||
|
# TreeD is first computed with optional input of unsealed data
|
||||||
|
# TreeR is computed from replica, which is first computed as field
|
||||||
|
# addition of the last SDR layer and the bottom layer of TreeD (which is the unsealed data)
|
||||||
|
# TreeC is computed from the 11 SDR layers
|
||||||
|
# The 3 trees will later be used to compute the PoRep proof.
|
||||||
|
#
|
||||||
|
# In case of SyntheticPoRep challenges for PoRep will be pre-generated at this step, and trees and layers
|
||||||
|
# will be dropped. SyntheticPoRep works by pre-generating a very large set of challenges (~30GiB on disk)
|
||||||
|
# then using a small subset of them for the actual PoRep computation. This allows for significant scratch space
|
||||||
|
# saving between PreCommit and PoRep generation at the expense of more computation (generating challenges in this step)
|
||||||
|
#
|
||||||
|
# In lotus-miner this was run as part of PreCommit2 (TreeD was run in PreCommit1).
|
||||||
|
# Note that nodes with SDRTrees enabled will also answer to Finalize tasks,
|
||||||
|
# which just remove unneeded tree data after PoRep is computed.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableSealSDRTrees = false
|
||||||
|
|
||||||
|
# The maximum amount of SealSDRTrees tasks that can run simultaneously. Note that the maximum number of tasks will
|
||||||
|
# also be bounded by resources available on the machine.
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#SealSDRTreesMaxTasks = 0
|
||||||
|
|
||||||
|
# FinalizeMaxTasks is the maximum amount of finalize tasks that can run simultaneously.
|
||||||
|
# The finalize task is enabled on all machines which also handle SDRTrees tasks. Finalize ALWAYS runs on whichever
|
||||||
|
# machine holds sector cache files, as it removes unneeded tree data after PoRep is computed.
|
||||||
|
# Finalize will run in parallel with the SubmitCommitMsg task.
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#FinalizeMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableSendPrecommitMsg enables the sending of precommit messages to the chain
|
||||||
|
# from this lotus-provider instance.
|
||||||
|
# This runs after SDRTrees and uses the output CommD / CommR (roots of TreeD / TreeR) for the message
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableSendPrecommitMsg = false
|
||||||
|
|
||||||
|
# EnablePoRepProof enables the computation of the porep proof
|
||||||
|
#
|
||||||
|
# This task runs after interactive-porep seed becomes available, which happens 150 epochs (75min) after the
|
||||||
|
# precommit message lands on chain. This task should run on a machine with a GPU. Vanilla PoRep proofs are
|
||||||
|
# requested from the machine which holds sector cache files which most likely is the machine which ran the SDRTrees
|
||||||
|
# task.
|
||||||
|
#
|
||||||
|
# In lotus-miner this was Commit1 / Commit2
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnablePoRepProof = false
|
||||||
|
|
||||||
|
# The maximum amount of PoRepProof tasks that can run simultaneously. Note that the maximum number of tasks will
|
||||||
|
# also be bounded by resources available on the machine.
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#PoRepProofMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableSendCommitMsg enables the sending of commit messages to the chain
|
||||||
|
# from this lotus-provider instance.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableSendCommitMsg = false
|
||||||
|
|
||||||
|
# EnableMoveStorage enables the move-into-long-term-storage task to run on this lotus-provider instance.
|
||||||
|
# This tasks should only be enabled on nodes with long-term storage.
|
||||||
|
#
|
||||||
|
# The MoveStorage task is the last task in the sealing pipeline. It moves the sealed sector data from the
|
||||||
|
# SDRTrees machine into long-term storage. This task runs after the Finalize task.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableMoveStorage = false
|
||||||
|
|
||||||
|
# The maximum amount of MoveStorage tasks that can run simultaneously. Note that the maximum number of tasks will
|
||||||
|
# also be bounded by resources available on the machine. It is recommended that this value is set to a number which
|
||||||
|
# uses all available network (or disk) bandwidth on the machine without causing bottlenecks.
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#MoveStorageMaxTasks = 0
|
||||||
|
|
||||||
|
# EnableWebGui enables the web GUI on this lotus-provider instance. The UI has minimal local overhead, but it should
|
||||||
|
# only need to be run on a single machine in the cluster.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#EnableWebGui = false
|
||||||
|
|
||||||
|
# The address that should listen for Web GUI requests.
|
||||||
|
#
|
||||||
|
# type: string
|
||||||
|
#GuiAddress = ":4701"
|
||||||
|
|
||||||
|
|
||||||
|
[Fees]
|
||||||
|
# type: types.FIL
|
||||||
|
#DefaultMaxFee = "0.07 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#MaxPreCommitGasFee = "0.025 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#MaxCommitGasFee = "0.05 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#MaxTerminateGasFee = "0.5 FIL"
|
||||||
|
|
||||||
|
# WindowPoSt is a high-value operation, so the default fee should be high.
|
||||||
|
#
|
||||||
|
# type: types.FIL
|
||||||
|
#MaxWindowPoStGasFee = "5 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#MaxPublishDealsFee = "0.05 FIL"
|
||||||
|
|
||||||
|
[Fees.MaxPreCommitBatchGasFee]
|
||||||
|
# type: types.FIL
|
||||||
|
#Base = "0 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#PerSector = "0.02 FIL"
|
||||||
|
|
||||||
|
[Fees.MaxCommitBatchGasFee]
|
||||||
|
# type: types.FIL
|
||||||
|
#Base = "0 FIL"
|
||||||
|
|
||||||
|
# type: types.FIL
|
||||||
|
#PerSector = "0.03 FIL"
|
||||||
|
|
||||||
|
[[Addresses]]
|
||||||
|
#PreCommitControl = []
|
||||||
|
|
||||||
|
#CommitControl = []
|
||||||
|
|
||||||
|
#TerminateControl = []
|
||||||
|
|
||||||
|
#DisableOwnerFallback = false
|
||||||
|
|
||||||
|
#DisableWorkerFallback = false
|
||||||
|
|
||||||
|
MinerAddresses = ["t01013"]
|
||||||
|
|
||||||
|
|
||||||
|
[[Addresses]]
|
||||||
|
#PreCommitControl = []
|
||||||
|
|
||||||
|
#CommitControl = []
|
||||||
|
|
||||||
|
#TerminateControl = []
|
||||||
|
|
||||||
|
#DisableOwnerFallback = false
|
||||||
|
|
||||||
|
#DisableWorkerFallback = false
|
||||||
|
|
||||||
|
#MinerAddresses = []
|
||||||
|
|
||||||
|
|
||||||
|
[[Addresses]]
|
||||||
|
#PreCommitControl = []
|
||||||
|
|
||||||
|
#CommitControl = []
|
||||||
|
|
||||||
|
#TerminateControl = []
|
||||||
|
|
||||||
|
#DisableOwnerFallback = false
|
||||||
|
|
||||||
|
#DisableWorkerFallback = false
|
||||||
|
|
||||||
|
MinerAddresses = ["t01006"]
|
||||||
|
|
||||||
|
|
||||||
|
[Proving]
|
||||||
|
# Maximum number of sector checks to run in parallel. (0 = unlimited)
|
||||||
|
#
|
||||||
|
# WARNING: Setting this value too high may make the node crash by running out of stack
|
||||||
|
# WARNING: Setting this value too low may make sector challenge reading much slower, resulting in failed PoSt due
|
||||||
|
# to late submission.
|
||||||
|
#
|
||||||
|
# After changing this option, confirm that the new value works in your setup by invoking
|
||||||
|
# 'lotus-miner proving compute window-post 0'
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#ParallelCheckLimit = 32
|
||||||
|
|
||||||
|
# Maximum amount of time a proving pre-check can take for a sector. If the check times out the sector will be skipped
|
||||||
|
#
|
||||||
|
# WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the
|
||||||
|
# test challenge took longer than this timeout
|
||||||
|
# WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this sector are
|
||||||
|
# blocked (e.g. in case of disconnected NFS mount)
|
||||||
|
#
|
||||||
|
# type: Duration
|
||||||
|
#SingleCheckTimeout = "10m0s"
|
||||||
|
|
||||||
|
# Maximum amount of time a proving pre-check can take for an entire partition. If the check times out, sectors in
|
||||||
|
# the partition which didn't get checked on time will be skipped
|
||||||
|
#
|
||||||
|
# WARNING: Setting this value too low risks in sectors being skipped even though they are accessible, just reading the
|
||||||
|
# test challenge took longer than this timeout
|
||||||
|
# WARNING: Setting this value too high risks missing PoSt deadline in case IO operations related to this partition are
|
||||||
|
# blocked or slow
|
||||||
|
#
|
||||||
|
# type: Duration
|
||||||
|
#PartitionCheckTimeout = "20m0s"
|
||||||
|
|
||||||
|
# Disable Window PoSt computation on the lotus-miner process even if no window PoSt workers are present.
|
||||||
|
#
|
||||||
|
# WARNING: If no windowPoSt workers are connected, window PoSt WILL FAIL resulting in faulty sectors which will need
|
||||||
|
# to be recovered. Before enabling this option, make sure your PoSt workers work correctly.
|
||||||
|
#
|
||||||
|
# After changing this option, confirm that the new value works in your setup by invoking
|
||||||
|
# 'lotus-miner proving compute window-post 0'
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#DisableBuiltinWindowPoSt = false
|
||||||
|
|
||||||
|
# Disable Winning PoSt computation on the lotus-miner process even if no winning PoSt workers are present.
|
||||||
|
#
|
||||||
|
# WARNING: If no WinningPoSt workers are connected, Winning PoSt WILL FAIL resulting in lost block rewards.
|
||||||
|
# Before enabling this option, make sure your PoSt workers work correctly.
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#DisableBuiltinWinningPoSt = false
|
||||||
|
|
||||||
|
# Disable WindowPoSt provable sector readability checks.
|
||||||
|
#
|
||||||
|
# In normal operation, when preparing to compute WindowPoSt, lotus-miner will perform a round of reading challenges
|
||||||
|
# from all sectors to confirm that those sectors can be proven. Challenges read in this process are discarded, as
|
||||||
|
# we're only interested in checking that sector data can be read.
|
||||||
|
#
|
||||||
|
# When using builtin proof computation (no PoSt workers, and DisableBuiltinWindowPoSt is set to false), this process
|
||||||
|
# can save a lot of time and compute resources in the case that some sectors are not readable - this is caused by
|
||||||
|
# the builtin logic not skipping snark computation when some sectors need to be skipped.
|
||||||
|
#
|
||||||
|
# When using PoSt workers, this process is mostly redundant, with PoSt workers challenges will be read once, and
|
||||||
|
# if challenges for some sectors aren't readable, those sectors will just get skipped.
|
||||||
|
#
|
||||||
|
# Disabling sector pre-checks will slightly reduce IO load when proving sectors, possibly resulting in shorter
|
||||||
|
# time to produce window PoSt. In setups with good IO capabilities the effect of this option on proving time should
|
||||||
|
# be negligible.
|
||||||
|
#
|
||||||
|
# NOTE: It likely is a bad idea to disable sector pre-checks in setups with no PoSt workers.
|
||||||
|
#
|
||||||
|
# NOTE: Even when this option is enabled, recovering sectors will be checked before recovery declaration message is
|
||||||
|
# sent to the chain
|
||||||
|
#
|
||||||
|
# After changing this option, confirm that the new value works in your setup by invoking
|
||||||
|
# 'lotus-miner proving compute window-post 0'
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#DisableWDPoStPreChecks = false
|
||||||
|
|
||||||
|
# Maximum number of partitions to prove in a single SubmitWindowPoSt messace. 0 = network limit (3 in nv21)
|
||||||
|
#
|
||||||
|
# A single partition may contain up to 2349 32GiB sectors, or 2300 64GiB sectors.
|
||||||
|
# //
|
||||||
|
# Note that setting this value lower may result in less efficient gas use - more messages will be sent,
|
||||||
|
# to prove each deadline, resulting in more total gas use (but each message will have lower gas limit)
|
||||||
|
#
|
||||||
|
# Setting this value above the network limit has no effect
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#MaxPartitionsPerPoStMessage = 0
|
||||||
|
|
||||||
|
# In some cases when submitting DeclareFaultsRecovered messages,
|
||||||
|
# there may be too many recoveries to fit in a BlockGasLimit.
|
||||||
|
# In those cases it may be necessary to set this value to something low (eg 1);
|
||||||
|
# Note that setting this value lower may result in less efficient gas use - more messages will be sent than needed,
|
||||||
|
# resulting in more total gas use (but each message will have lower gas limit)
|
||||||
|
#
|
||||||
|
# type: int
|
||||||
|
#MaxPartitionsPerRecoveryMessage = 0
|
||||||
|
|
||||||
|
# Enable single partition per PoSt Message for partitions containing recovery sectors
|
||||||
|
#
|
||||||
|
# In cases when submitting PoSt messages which contain recovering sectors, the default network limit may still be
|
||||||
|
# too high to fit in the block gas limit. In those cases, it becomes useful to only house the single partition
|
||||||
|
# with recovering sectors in the post message
|
||||||
|
#
|
||||||
|
# Note that setting this value lower may result in less efficient gas use - more messages will be sent,
|
||||||
|
# to prove each deadline, resulting in more total gas use (but each message will have lower gas limit)
|
||||||
|
#
|
||||||
|
# type: bool
|
||||||
|
#SingleRecoveringPartitionPerPostMessage = false
|
||||||
|
|
||||||
|
|
||||||
|
[Journal]
|
||||||
|
# Events of the form: "system1:event1,system1:event2[,...]"
|
||||||
|
#
|
||||||
|
# type: string
|
||||||
|
#DisabledEvents = ""
|
||||||
|
|
||||||
|
|
||||||
|
[Apis]
|
||||||
|
# ChainApiInfo is the API endpoint for the Lotus daemon.
|
||||||
|
#
|
||||||
|
# type: []string
|
||||||
|
ChainApiInfo = ["eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJBbGxvdyI6WyJyZWFkIiwid3JpdGUiLCJzaWduIiwiYWRtaW4iXX0.T_jmG4DTs9Zjd7rr78862lT7D2U63uz-zqcUKHwcqaU:/dns/localhost/tcp/1234/http"]
|
||||||
|
|
||||||
|
# RPC Secret for the storage subsystem.
|
||||||
|
# If integrating with lotus-miner this must match the value from
|
||||||
|
# cat ~/.lotusminer/keystore/MF2XI2BNNJ3XILLQOJUXMYLUMU | jq -r .PrivateKey
|
||||||
|
#
|
||||||
|
# type: string
|
||||||
|
StorageRPCSecret = "HxHe8YLHiY0LjHVw/WT/4XQkPGgRyCEYk+xiFi0Ob0o="
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestConfig(t *testing.T) {
|
||||||
|
baseCfg := config.DefaultCurioConfig()
|
||||||
|
|
||||||
|
addr1 := config.CurioAddresses{
|
||||||
|
PreCommitControl: []string{},
|
||||||
|
CommitControl: []string{},
|
||||||
|
TerminateControl: []string{"t3qroiebizgkz7pvj26reg5r5mqiftrt5hjdske2jzjmlacqr2qj7ytjncreih2mvujxoypwpfusmwpipvxncq"},
|
||||||
|
DisableOwnerFallback: false,
|
||||||
|
DisableWorkerFallback: false,
|
||||||
|
MinerAddresses: []string{"t01000"},
|
||||||
|
}
|
||||||
|
|
||||||
|
addr2 := config.CurioAddresses{
|
||||||
|
MinerAddresses: []string{"t01001"},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := deps.LoadConfigWithUpgrades(baseText, baseCfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
baseCfg.Addresses = append(baseCfg.Addresses, addr1)
|
||||||
|
baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
baseCfg.Addresses = append(baseCfg.Addresses, addr2)
|
||||||
|
baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
_, err = config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
}
|
@ -3,10 +3,12 @@ package deps
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
@ -29,6 +31,8 @@ import (
|
|||||||
"github.com/filecoin-project/go-statestore"
|
"github.com/filecoin-project/go-statestore"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
|
"github.com/filecoin-project/lotus/api/v1api"
|
||||||
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
curio "github.com/filecoin-project/lotus/curiosrc"
|
curio "github.com/filecoin-project/lotus/curiosrc"
|
||||||
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
"github.com/filecoin-project/lotus/curiosrc/multictladdr"
|
||||||
"github.com/filecoin-project/lotus/journal"
|
"github.com/filecoin-project/lotus/journal"
|
||||||
@ -434,3 +438,96 @@ func GetDepsCLI(ctx context.Context, cctx *cli.Context) (*Deps, error) {
|
|||||||
Full: full,
|
Full: full,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CreateMinerConfig(ctx context.Context, full v1api.FullNode, db *harmonydb.DB, miners []string, 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()
|
||||||
|
|
||||||
|
for _, addr := range miners {
|
||||||
|
maddr, err := address.NewFromString(addr)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("Invalid address: %s", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = full.StateMinerInfo(ctx, maddr, types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("Failed to get miner info: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
curioConfig.Addresses = append(curioConfig.Addresses, config.CurioAddresses{
|
||||||
|
PreCommitControl: []string{},
|
||||||
|
CommitControl: []string{},
|
||||||
|
TerminateControl: []string{},
|
||||||
|
DisableOwnerFallback: false,
|
||||||
|
DisableWorkerFallback: false,
|
||||||
|
MinerAddresses: []string{addr},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
curioConfig.Addresses = lo.Filter(curioConfig.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// If no base layer is present
|
||||||
|
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.Printf("The base layer has been updated with miner[s] %s\n", miners)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// if base layer is present
|
||||||
|
baseCfg := config.DefaultCurioConfig()
|
||||||
|
var baseText string
|
||||||
|
err = db.QueryRow(ctx, "SELECT config FROM harmony_config WHERE title='base'").Scan(&baseText)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("Cannot load base config from database: %w", err)
|
||||||
|
}
|
||||||
|
_, err = LoadConfigWithUpgrades(baseText, baseCfg)
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("Cannot parse base config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseCfg.Addresses = append(baseCfg.Addresses, curioConfig.Addresses...)
|
||||||
|
baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
cb, err := config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("cannot interpret config: %w", err)
|
||||||
|
}
|
||||||
|
_, err = db.Exec(ctx, "UPDATE harmony_config SET config=$1 WHERE title='base'", string(cb))
|
||||||
|
if err != nil {
|
||||||
|
return xerrors.Errorf("cannot update base config: %w", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("The base layer has been updated with miner[s] %s\n", miners)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -8,6 +8,7 @@ package guidedsetup
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -18,12 +19,14 @@ import (
|
|||||||
"os/signal"
|
"os/signal"
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/docker/go-units"
|
||||||
"github.com/manifoldco/promptui"
|
"github.com/manifoldco/promptui"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
@ -33,12 +36,15 @@ import (
|
|||||||
|
|
||||||
"github.com/filecoin-project/go-address"
|
"github.com/filecoin-project/go-address"
|
||||||
"github.com/filecoin-project/go-jsonrpc"
|
"github.com/filecoin-project/go-jsonrpc"
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
"github.com/filecoin-project/lotus/api"
|
"github.com/filecoin-project/lotus/api"
|
||||||
"github.com/filecoin-project/lotus/api/v0api"
|
"github.com/filecoin-project/lotus/api/v1api"
|
||||||
"github.com/filecoin-project/lotus/build"
|
"github.com/filecoin-project/lotus/build"
|
||||||
"github.com/filecoin-project/lotus/chain/types"
|
"github.com/filecoin-project/lotus/chain/types"
|
||||||
|
"github.com/filecoin-project/lotus/cli/spcli"
|
||||||
cliutil "github.com/filecoin-project/lotus/cli/util"
|
cliutil "github.com/filecoin-project/lotus/cli/util"
|
||||||
|
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||||
_ "github.com/filecoin-project/lotus/cmd/curio/internal/translations"
|
_ "github.com/filecoin-project/lotus/cmd/curio/internal/translations"
|
||||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||||
"github.com/filecoin-project/lotus/node/config"
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
@ -50,7 +56,7 @@ const DeveloperFocusRequestURL = "https://curiostorage.org/cgi-bin/savedata.php"
|
|||||||
|
|
||||||
var GuidedsetupCmd = &cli.Command{
|
var GuidedsetupCmd = &cli.Command{
|
||||||
Name: "guided-setup",
|
Name: "guided-setup",
|
||||||
Usage: "Run the guided setup for migrating from lotus-miner to Curio",
|
Usage: "Run the guided setup for migrating from lotus-miner to Curio or Creating a new Curio miner",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
&cli.StringFlag{ // for cliutil.GetFullNodeAPI
|
&cli.StringFlag{ // for cliutil.GetFullNodeAPI
|
||||||
Name: "repo",
|
Name: "repo",
|
||||||
@ -63,9 +69,6 @@ var GuidedsetupCmd = &cli.Command{
|
|||||||
T, say := SetupLanguage()
|
T, say := SetupLanguage()
|
||||||
setupCtrlC(say)
|
setupCtrlC(say)
|
||||||
|
|
||||||
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.")
|
|
||||||
|
|
||||||
// Run the migration steps
|
// Run the migration steps
|
||||||
migrationData := MigrationData{
|
migrationData := MigrationData{
|
||||||
T: T,
|
T: T,
|
||||||
@ -74,10 +77,25 @@ var GuidedsetupCmd = &cli.Command{
|
|||||||
Help: T("Use the arrow keys to navigate: ↓ ↑ → ← "),
|
Help: T("Use the arrow keys to navigate: ↓ ↑ → ← "),
|
||||||
},
|
},
|
||||||
cctx: cctx,
|
cctx: cctx,
|
||||||
|
ctx: cctx.Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newOrMigrate(&migrationData)
|
||||||
|
if migrationData.init {
|
||||||
|
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 {
|
||||||
|
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.")
|
||||||
|
|
||||||
for _, step := range migrationSteps {
|
for _, step := range migrationSteps {
|
||||||
step(&migrationData)
|
step(&migrationData)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _, closer := range migrationData.closers {
|
for _, closer := range migrationData.closers {
|
||||||
closer()
|
closer()
|
||||||
}
|
}
|
||||||
@ -164,6 +182,23 @@ func SetupLanguage() (func(key message.Reference, a ...interface{}) string, func
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newOrMigrate(d *MigrationData) {
|
||||||
|
i, _, err := (&promptui.Select{
|
||||||
|
Label: d.T("I want to:"),
|
||||||
|
Items: []string{
|
||||||
|
d.T("Migrate from existing Lotus-Miner"),
|
||||||
|
d.T("Create a new miner")},
|
||||||
|
Templates: d.selectTemplates,
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Aborting remaining steps.", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if i == 1 {
|
||||||
|
d.init = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type migrationStep func(*MigrationData)
|
type migrationStep func(*MigrationData)
|
||||||
|
|
||||||
var migrationSteps = []migrationStep{
|
var migrationSteps = []migrationStep{
|
||||||
@ -176,6 +211,17 @@ var migrationSteps = []migrationStep{
|
|||||||
complete,
|
complete,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type newMinerStep func(data *MigrationData)
|
||||||
|
|
||||||
|
var newMinerSteps = []newMinerStep{
|
||||||
|
stepPresteps,
|
||||||
|
stepCreateActor,
|
||||||
|
stepNewMinerConfig,
|
||||||
|
doc,
|
||||||
|
oneLastThing,
|
||||||
|
completeInit,
|
||||||
|
}
|
||||||
|
|
||||||
type MigrationData struct {
|
type MigrationData struct {
|
||||||
T func(key message.Reference, a ...interface{}) string
|
T func(key message.Reference, a ...interface{}) string
|
||||||
say func(style lipgloss.Style, key message.Reference, a ...interface{})
|
say func(style lipgloss.Style, key message.Reference, a ...interface{})
|
||||||
@ -184,9 +230,16 @@ type MigrationData struct {
|
|||||||
MinerConfig *config.StorageMiner
|
MinerConfig *config.StorageMiner
|
||||||
DB *harmonydb.DB
|
DB *harmonydb.DB
|
||||||
MinerID address.Address
|
MinerID address.Address
|
||||||
full v0api.FullNode
|
full v1api.FullNode
|
||||||
cctx *cli.Context
|
cctx *cli.Context
|
||||||
closers []jsonrpc.ClientCloser
|
closers []jsonrpc.ClientCloser
|
||||||
|
ctx context.Context
|
||||||
|
owner address.Address
|
||||||
|
worker address.Address
|
||||||
|
sender address.Address
|
||||||
|
ssize abi.SectorSize
|
||||||
|
confidence uint64
|
||||||
|
init bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func complete(d *MigrationData) {
|
func complete(d *MigrationData) {
|
||||||
@ -194,13 +247,19 @@ func complete(d *MigrationData) {
|
|||||||
d.say(plain, "Try the web interface with %s for further guided improvements.", "--layers=gui")
|
d.say(plain, "Try the web interface with %s for further guided improvements.", "--layers=gui")
|
||||||
d.say(plain, "You can now migrate your market node (%s), if applicable.", "Boost")
|
d.say(plain, "You can now migrate your market node (%s), if applicable.", "Boost")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func completeInit(d *MigrationData) {
|
||||||
|
stepCompleted(d, d.T("New Miner initialization complete."))
|
||||||
|
d.say(plain, "Try the web interface with %s for further guided improvements.", "--layers=gui")
|
||||||
|
}
|
||||||
|
|
||||||
func configToDB(d *MigrationData) {
|
func configToDB(d *MigrationData) {
|
||||||
d.say(section, "Migrating lotus-miner config.toml to Curio in-database configuration.")
|
d.say(section, "Migrating lotus-miner config.toml to Curio in-database configuration.")
|
||||||
|
|
||||||
{
|
{
|
||||||
var closer jsonrpc.ClientCloser
|
var closer jsonrpc.ClientCloser
|
||||||
var err error
|
var err error
|
||||||
d.full, closer, err = cliutil.GetFullNodeAPI(d.cctx)
|
d.full, closer, err = cliutil.GetFullNodeAPIV1(d.cctx)
|
||||||
d.closers = append(d.closers, closer)
|
d.closers = append(d.closers, closer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.say(notice, "Error getting API: %s", err.Error())
|
d.say(notice, "Error getting API: %s", err.Error())
|
||||||
@ -329,7 +388,7 @@ func doc(d *MigrationData) {
|
|||||||
|
|
||||||
d.say(plain, "Filecoin %s channels: %s and %s", "Slack", "#fil-curio-help", "#fil-curio-dev")
|
d.say(plain, "Filecoin %s channels: %s and %s", "Slack", "#fil-curio-help", "#fil-curio-dev")
|
||||||
|
|
||||||
d.say(plain, "Start multiple Curio instances with the '%s' layer to redundancy.", "post")
|
d.say(plain, "Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'")
|
||||||
//d.say(plain, "Point your browser to your web GUI to complete setup with %s and advanced featues.", "Boost")
|
//d.say(plain, "Point your browser to your web GUI to complete setup with %s and advanced featues.", "Boost")
|
||||||
d.say(plain, "One database can serve multiple miner IDs: Run a migration for each lotus-miner.")
|
d.say(plain, "One database can serve multiple miner IDs: Run a migration for each lotus-miner.")
|
||||||
}
|
}
|
||||||
@ -381,69 +440,11 @@ func yugabyteConnect(d *MigrationData) {
|
|||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
d.DB, err = harmonydb.NewFromConfig(harmonyCfg)
|
d.DB, err = harmonydb.NewFromConfig(harmonyCfg)
|
||||||
if err == nil {
|
|
||||||
goto yugabyteConnected
|
|
||||||
}
|
|
||||||
for {
|
|
||||||
i, _, err := (&promptui.Select{
|
|
||||||
Label: d.T("Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)"),
|
|
||||||
Items: []string{
|
|
||||||
d.T("Host: %s", strings.Join(harmonyCfg.Hosts, ",")),
|
|
||||||
d.T("Port: %s", harmonyCfg.Port),
|
|
||||||
d.T("Username: %s", harmonyCfg.Username),
|
|
||||||
d.T("Password: %s", harmonyCfg.Password),
|
|
||||||
d.T("Database: %s", harmonyCfg.Database),
|
|
||||||
d.T("Continue to connect and update schema.")},
|
|
||||||
Size: 6,
|
|
||||||
Templates: d.selectTemplates,
|
|
||||||
}).Run()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.say(notice, "Database config error occurred, abandoning migration: %s ", err.Error())
|
hcfg := getDBDetails(d)
|
||||||
os.Exit(1)
|
harmonyCfg = *hcfg
|
||||||
}
|
|
||||||
switch i {
|
|
||||||
case 0:
|
|
||||||
host, err := (&promptui.Prompt{
|
|
||||||
Label: d.T("Enter the Yugabyte database host(s)"),
|
|
||||||
}).Run()
|
|
||||||
if err != nil {
|
|
||||||
d.say(notice, "No host provided")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
harmonyCfg.Hosts = strings.Split(host, ",")
|
|
||||||
case 1, 2, 3, 4:
|
|
||||||
val, err := (&promptui.Prompt{
|
|
||||||
Label: d.T("Enter the Yugabyte database %s", []string{"port", "username", "password", "database"}[i-1]),
|
|
||||||
}).Run()
|
|
||||||
if err != nil {
|
|
||||||
d.say(notice, "No value provided")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
switch i {
|
|
||||||
case 1:
|
|
||||||
harmonyCfg.Port = val
|
|
||||||
case 2:
|
|
||||||
harmonyCfg.Username = val
|
|
||||||
case 3:
|
|
||||||
harmonyCfg.Password = val
|
|
||||||
case 4:
|
|
||||||
harmonyCfg.Database = val
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
case 5:
|
|
||||||
d.DB, err = harmonydb.NewFromConfig(harmonyCfg)
|
|
||||||
if err != nil {
|
|
||||||
if err.Error() == "^C" {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
d.say(notice, "Error connecting to Yugabyte database: %s", err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
goto yugabyteConnected
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
yugabyteConnected:
|
|
||||||
d.say(plain, "Connected to Yugabyte. Schema is current.")
|
d.say(plain, "Connected to Yugabyte. Schema is current.")
|
||||||
if !reflect.DeepEqual(harmonyCfg, d.MinerConfig.HarmonyDB) || !d.MinerConfig.Subsystems.EnableSectorIndexDB {
|
if !reflect.DeepEqual(harmonyCfg, d.MinerConfig.HarmonyDB) || !d.MinerConfig.Subsystems.EnableSectorIndexDB {
|
||||||
d.MinerConfig.HarmonyDB = harmonyCfg
|
d.MinerConfig.HarmonyDB = harmonyCfg
|
||||||
@ -588,3 +589,293 @@ func stepCompleted(d *MigrationData, step string) {
|
|||||||
fmt.Print(green.Render("✔ "))
|
fmt.Print(green.Render("✔ "))
|
||||||
d.say(plain, "Step Complete: %s\n", step)
|
d.say(plain, "Step Complete: %s\n", step)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func stepCreateActor(d *MigrationData) {
|
||||||
|
d.say(plain, "Initializing a new miner actor.")
|
||||||
|
|
||||||
|
for {
|
||||||
|
i, _, err := (&promptui.Select{
|
||||||
|
Label: d.T("Enter the info to create a new miner"),
|
||||||
|
Items: []string{
|
||||||
|
d.T("Owner Address: %s", d.owner.String()),
|
||||||
|
d.T("Worker Address: %s", d.worker.String()),
|
||||||
|
d.T("Sender Address: %s", d.sender.String()),
|
||||||
|
d.T("Sector Size: %d", d.ssize),
|
||||||
|
d.T("Confidence epochs: %d", d.confidence),
|
||||||
|
d.T("Continue to verify the addresses and create a new miner actor.")},
|
||||||
|
Size: 6,
|
||||||
|
Templates: d.selectTemplates,
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Miner creation error occurred: %s ", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
owner, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Enter the owner address"),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "No address provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ownerAddr, err := address.NewFromString(owner)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to parse the address: %s", err.Error())
|
||||||
|
}
|
||||||
|
d.owner = ownerAddr
|
||||||
|
case 1, 2:
|
||||||
|
val, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Enter %s address", []string{"worker", "sender"}[i-1]),
|
||||||
|
Default: d.owner.String(),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addr, err := address.NewFromString(val)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to parse the address: %s", err.Error())
|
||||||
|
}
|
||||||
|
switch i {
|
||||||
|
case 1:
|
||||||
|
d.worker = addr
|
||||||
|
case 2:
|
||||||
|
d.sender = addr
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case 3:
|
||||||
|
val, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Enter the sector size"),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "No value provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
sectorSize, err := units.RAMInBytes(val)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to parse sector size: %s", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d.ssize = abi.SectorSize(sectorSize)
|
||||||
|
continue
|
||||||
|
case 4:
|
||||||
|
confidenceStr, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Confidence epochs"),
|
||||||
|
Default: strconv.Itoa(5),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
confidence, err := strconv.ParseUint(confidenceStr, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to parse confidence: %s", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d.confidence = confidence
|
||||||
|
goto minerInit // break out of the for loop once we have all the values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
minerInit:
|
||||||
|
miner, err := spcli.CreateStorageMiner(d.ctx, d.full, d.owner, d.worker, d.sender, d.ssize, d.confidence)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to create the miner actor: %s", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
d.MinerID = miner
|
||||||
|
stepCompleted(d, d.T("Miner %s created successfully", miner.String()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepPresteps(d *MigrationData) {
|
||||||
|
|
||||||
|
// Setup and connect to YugabyteDB
|
||||||
|
_ = getDBDetails(d)
|
||||||
|
|
||||||
|
// Verify HarmonyDB connection
|
||||||
|
var titles []string
|
||||||
|
err := d.DB.Select(d.ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Cannot reach the DB: %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)
|
||||||
|
stepCompleted(d, d.T("Pre-initialization steps complete"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func stepNewMinerConfig(d *MigrationData) {
|
||||||
|
curioCfg := config.DefaultCurioConfig()
|
||||||
|
curioCfg.Addresses = append(curioCfg.Addresses, config.CurioAddresses{
|
||||||
|
PreCommitControl: []string{},
|
||||||
|
CommitControl: []string{},
|
||||||
|
TerminateControl: []string{},
|
||||||
|
DisableOwnerFallback: false,
|
||||||
|
DisableWorkerFallback: false,
|
||||||
|
MinerAddresses: []string{d.MinerID.String()},
|
||||||
|
})
|
||||||
|
|
||||||
|
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())
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
curioCfg.Apis.StorageRPCSecret = base64.StdEncoding.EncodeToString(sk)
|
||||||
|
|
||||||
|
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, api.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
curioCfg.Apis.ChainApiInfo = append(curioCfg.Apis.ChainApiInfo, fmt.Sprintf("%s:%s", string(token), ainfo.Addr))
|
||||||
|
|
||||||
|
// write config
|
||||||
|
var titles []string
|
||||||
|
err = d.DB.Select(d.ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Cannot reach the DB: %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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If 'base' layer is not present
|
||||||
|
if !lo.Contains(titles, "base") {
|
||||||
|
curioCfg.Addresses = lo.Filter(curioCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
cb, err := config.ConfigUpdate(curioCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to generate default config: %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)
|
||||||
|
}
|
||||||
|
_, 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())
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
stepCompleted(d, d.T("Configuration 'base' was updated to include this miner's address"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If base layer is already present
|
||||||
|
baseCfg := config.DefaultCurioConfig()
|
||||||
|
var baseText string
|
||||||
|
|
||||||
|
err = d.DB.QueryRow(d.ctx, "SELECT config FROM harmony_config WHERE title='base'").Scan(&baseText)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to load base config from database: %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)
|
||||||
|
}
|
||||||
|
_, err = deps.LoadConfigWithUpgrades(baseText, baseCfg)
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to parse base config: %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)
|
||||||
|
}
|
||||||
|
|
||||||
|
baseCfg.Addresses = append(baseCfg.Addresses, curioCfg.Addresses...)
|
||||||
|
baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool {
|
||||||
|
return len(a.MinerAddresses) > 0
|
||||||
|
})
|
||||||
|
|
||||||
|
cb, err := config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv())
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to regenerate base config: %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)
|
||||||
|
}
|
||||||
|
_, err = d.DB.Exec(d.ctx, "UPDATE harmony_config SET config=$1 WHERE title='base'", string(cb))
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Failed to insert 'base' config layer in database: %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)
|
||||||
|
}
|
||||||
|
|
||||||
|
stepCompleted(d, d.T("Configuration 'base' was updated to include this miner's address"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDBDetails(d *MigrationData) *config.HarmonyDB {
|
||||||
|
harmonyCfg := config.DefaultStorageMiner().HarmonyDB
|
||||||
|
for {
|
||||||
|
i, _, err := (&promptui.Select{
|
||||||
|
Label: d.T("Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)"),
|
||||||
|
Items: []string{
|
||||||
|
d.T("Host: %s", strings.Join(harmonyCfg.Hosts, ",")),
|
||||||
|
d.T("Port: %s", harmonyCfg.Port),
|
||||||
|
d.T("Username: %s", harmonyCfg.Username),
|
||||||
|
d.T("Password: %s", harmonyCfg.Password),
|
||||||
|
d.T("Database: %s", harmonyCfg.Database),
|
||||||
|
d.T("Continue to connect and update schema.")},
|
||||||
|
Size: 6,
|
||||||
|
Templates: d.selectTemplates,
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "Database config error occurred, abandoning migration: %s ", err.Error())
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
host, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Enter the Yugabyte database host(s)"),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "No host provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
harmonyCfg.Hosts = strings.Split(host, ",")
|
||||||
|
case 1, 2, 3, 4:
|
||||||
|
val, err := (&promptui.Prompt{
|
||||||
|
Label: d.T("Enter the Yugabyte database %s", []string{"port", "username", "password", "database"}[i-1]),
|
||||||
|
}).Run()
|
||||||
|
if err != nil {
|
||||||
|
d.say(notice, "No value provided")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch i {
|
||||||
|
case 1:
|
||||||
|
harmonyCfg.Port = val
|
||||||
|
case 2:
|
||||||
|
harmonyCfg.Username = val
|
||||||
|
case 3:
|
||||||
|
harmonyCfg.Password = val
|
||||||
|
case 4:
|
||||||
|
harmonyCfg.Database = val
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
case 5:
|
||||||
|
db, err := harmonydb.NewFromConfig(harmonyCfg)
|
||||||
|
if err != nil {
|
||||||
|
if err.Error() == "^C" {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
d.say(notice, "Error connecting to Yugabyte database: %s", err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d.DB = db
|
||||||
|
return &harmonyCfg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,292 +40,436 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var messageKeyToIndex = map[string]int{
|
var messageKeyToIndex = map[string]int{
|
||||||
"Aborting migration.": 41,
|
"Aborting migration.": 45,
|
||||||
"Aborting remaining steps.": 19,
|
"Aborting remaining steps.": 9,
|
||||||
"Aggregate-Anonymous: version, net, and Miner power (bucketed).": 16,
|
"Aggregate-Anonymous: version, chain, and Miner power (bucketed).": 22,
|
||||||
"Cannot read the config.toml file in the provided directory, Error: %s": 70,
|
"Cannot reach the DB: %s": 90,
|
||||||
"Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.": 76,
|
"Cannot read the config.toml file in the provided directory, Error: %s": 65,
|
||||||
"Configuration 'base' was created to include this miner's address and its wallet setup.": 77,
|
"Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.": 116,
|
||||||
"Configuration 'base' was updated to include this miner's address and its wallet setup.": 75,
|
"Confidence epochs": 86,
|
||||||
"Connected to Yugabyte": 64,
|
"Confidence epochs: %d": 76,
|
||||||
"Connected to Yugabyte. Schema is current.": 56,
|
"Configuration 'base' was created to include this miner's address and its wallet setup.": 117,
|
||||||
"Continue to connect and update schema.": 49,
|
"Configuration 'base' was updated to include this miner's address": 99,
|
||||||
"Could not create repo from directory: %s. Aborting migration": 71,
|
"Configuration 'base' was updated to include this miner's address and its wallet setup.": 115,
|
||||||
"Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration": 72,
|
"Connected to Yugabyte": 59,
|
||||||
"Ctrl+C pressed in Terminal": 3,
|
"Connected to Yugabyte. Schema is current.": 47,
|
||||||
"Database config error occurred, abandoning migration: %s ": 50,
|
"Continue to connect and update schema.": 109,
|
||||||
"Database: %s": 48,
|
"Continue to verify the addresses and create a new miner actor.": 77,
|
||||||
"Documentation: ": 27,
|
"Could not create repo from directory: %s. Aborting migration": 66,
|
||||||
"Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.": 1,
|
"Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration": 67,
|
||||||
"Enabling Sector Indexing in the database.": 57,
|
"Create a new miner": 8,
|
||||||
"Enter the Yugabyte database %s": 53,
|
"Ctrl+C pressed in Terminal": 5,
|
||||||
"Enter the Yugabyte database host(s)": 51,
|
"Database config error occurred, abandoning migration: %s ": 110,
|
||||||
"Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)": 43,
|
"Database: %s": 108,
|
||||||
"Enter the path to the configuration directory used by %s": 68,
|
"Documentation: ": 32,
|
||||||
"Error connecting to Yugabyte database: %s": 55,
|
"Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.": 4,
|
||||||
"Error connecting to lotus node: %s %s": 9,
|
"Enabling Sector Indexing in the database.": 48,
|
||||||
"Error encoding config.toml: %s": 58,
|
"Enter %s address": 82,
|
||||||
"Error expanding path: %s": 60,
|
"Enter the Yugabyte database %s": 113,
|
||||||
"Error getting miner info: %s": 22,
|
"Enter the Yugabyte database host(s)": 111,
|
||||||
"Error getting miner power: %s": 20,
|
"Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)": 103,
|
||||||
"Error getting token: %s": 11,
|
"Enter the info to create a new miner": 71,
|
||||||
"Error interpreting miner ID: %s: ID: %s": 36,
|
"Enter the owner address": 79,
|
||||||
"Error marshalling message: %s": 21,
|
"Enter the path to the configuration directory used by %s": 63,
|
||||||
"Error reading filemode of config.toml: %s": 61,
|
"Enter the sector size": 83,
|
||||||
"Error reading from database: %s. Aborting Migration.": 8,
|
"Error closing backup file: %s": 56,
|
||||||
"Error saving config to layer: %s. Aborting Migration": 12,
|
"Error connecting to Yugabyte database: %s": 114,
|
||||||
"Error sending message: %s": 24,
|
"Error connecting to full node API: %s": 91,
|
||||||
"Error sending message: Status %s, Message: ": 25,
|
"Error creating backup file: %s": 53,
|
||||||
"Error signing message: %s": 23,
|
"Error encoding config.toml: %s": 49,
|
||||||
"Error verifying sectors: %s": 37,
|
"Error expanding path: %s": 51,
|
||||||
"Error writing config.toml: %s": 62,
|
"Error getting API: %s": 15,
|
||||||
"Filecoin %s channels: %s and %s": 30,
|
"Error getting miner info: %s": 27,
|
||||||
"Hint: I am someone running Curio on net.": 17,
|
"Error getting miner power: %s": 25,
|
||||||
"Host: %s": 44,
|
"Error getting token: %s": 17,
|
||||||
"Individual Data: Miner ID, Curio version, net (%s or %s). Signed.": 15,
|
"Error interpreting miner ID: %s: ID: %s": 40,
|
||||||
"Layer %s created. ": 78,
|
"Error marshalling message: %s": 26,
|
||||||
"Lotus-Miner to Curio Migration.": 4,
|
"Error reading config.toml: %s": 54,
|
||||||
"Message sent.": 26,
|
"Error reading filemode of config.toml: %s": 52,
|
||||||
"Migrating config.toml to database.": 7,
|
"Error saving config to layer: %s. Aborting Migration": 18,
|
||||||
"No host provided": 52,
|
"Error sending message: %s": 29,
|
||||||
"No path provided, abandoning migration ": 69,
|
"Error sending message: Status %s, Message: ": 30,
|
||||||
"No value provided": 54,
|
"Error signing message: %s": 28,
|
||||||
"Nothing.": 18,
|
"Error verifying sectors: %s": 41,
|
||||||
"Now shut down lotus-miner and move the systems to %s.": 39,
|
"Error writing backup file: %s": 55,
|
||||||
"One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 33,
|
"Error writing config.toml: %s": 57,
|
||||||
"Other": 67,
|
"Failed to create the miner actor: %s": 88,
|
||||||
"Password: %s": 47,
|
"Failed to generate default config: %s": 97,
|
||||||
"Please start (or restart) %s now that database credentials are in %s.": 34,
|
"Failed to generate random bytes for secret: %s": 93,
|
||||||
"Point your browser to your web GUI to complete setup with %s and advanced featues.": 32,
|
"Failed to get API info for FullNode: %w": 95,
|
||||||
"Port: %s": 45,
|
"Failed to insert 'base' config layer in database: %s": 98,
|
||||||
"Press return to continue": 40,
|
"Failed to load base config from database: %s": 100,
|
||||||
"Press return to update %s with Yugabyte info. Backup the file now.": 59,
|
"Failed to parse base config: %s": 101,
|
||||||
"Protocol Labs wants to improve the software you use. Tell the team you're using Curio.": 13,
|
"Failed to parse confidence: %s": 87,
|
||||||
"Read Miner Config": 73,
|
"Failed to parse sector size: %s": 85,
|
||||||
"Restart Lotus Miner. ": 63,
|
"Failed to parse the address: %s": 81,
|
||||||
"Sectors verified. %d sector locations found.": 42,
|
"Failed to regenerate base config: %s": 102,
|
||||||
"Select the location of your lotus-miner config directory?": 66,
|
"Failed to verify the auth token from daemon node: %s": 96,
|
||||||
"Select what you want to share with the Curio team.": 14,
|
"Filecoin %s channels: %s and %s": 35,
|
||||||
"Start multiple Curio instances with the '%s' layer to redundancy.": 31,
|
"Hint: I am someone running Curio on whichever chain.": 23,
|
||||||
"Step Complete: %s\n": 74,
|
"Host: %s": 104,
|
||||||
"The '%s' layer stores common configuration. All curio instances can include it in their %s argument.": 28,
|
"I want to:": 6,
|
||||||
"The sectors are in the database. The database is ready for %s.": 38,
|
"Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'": 36,
|
||||||
"This interactive tool migrates lotus-miner to Curio in 5 minutes.": 0,
|
"Individual Data: Miner ID, Curio version, chain (%s or %s). Signed.": 21,
|
||||||
"To run Curio: With machine or cgroup isolation, use the command (with example layer selection):": 80,
|
"Initializing a new miner actor.": 70,
|
||||||
"To start, ensure your sealing pipeline is drained and shut-down lotus-miner.": 65,
|
"Layer %s created. ": 118,
|
||||||
"To work with the config: ": 79,
|
"Lotus-Miner to Curio Migration.": 10,
|
||||||
"Try the web interface with %s for further guided improvements.": 5,
|
"Message sent.": 31,
|
||||||
"Use the arrow keys to navigate: ↓ ↑ → ← ": 2,
|
"Migrate from existing Lotus-Miner": 7,
|
||||||
"Username: %s": 46,
|
"Migrating lotus-miner config.toml to Curio in-database configuration.": 14,
|
||||||
"Waiting for %s to write sectors into Yugabyte.": 35,
|
"Miner %s created successfully": 89,
|
||||||
"You can add other layers for per-machine configuration changes.": 29,
|
"Miner creation error occurred: %s ": 78,
|
||||||
"You can now migrate your market node (%s), if applicable.": 6,
|
"New Miner initialization complete.": 13,
|
||||||
"could not get API info for FullNode: %w": 10,
|
"No address provided": 80,
|
||||||
|
"No host provided": 112,
|
||||||
|
"No path provided, abandoning migration ": 64,
|
||||||
|
"No value provided": 84,
|
||||||
|
"Nothing.": 24,
|
||||||
|
"Now shut down lotus-miner and move the systems to %s.": 43,
|
||||||
|
"One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 37,
|
||||||
|
"Other": 62,
|
||||||
|
"Owner Address: %s": 72,
|
||||||
|
"Password: %s": 107,
|
||||||
|
"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": 94,
|
||||||
|
"Please start (or restart) %s now that database credentials are in %s.": 38,
|
||||||
|
"Port: %s": 105,
|
||||||
|
"Pre-initialization steps complete": 92,
|
||||||
|
"Press return to continue": 44,
|
||||||
|
"Press return to update %s with Yugabyte info. A Backup file will be written to that folder before changes are made.": 50,
|
||||||
|
"Read Miner Config": 68,
|
||||||
|
"Restart Lotus Miner. ": 58,
|
||||||
|
"Sector Size: %d": 75,
|
||||||
|
"Sectors verified. %d sector locations found.": 46,
|
||||||
|
"Select the location of your lotus-miner config directory?": 61,
|
||||||
|
"Select what you want to share with the Curio team.": 20,
|
||||||
|
"Sender Address: %s": 74,
|
||||||
|
"Step Complete: %s\n": 69,
|
||||||
|
"The '%s' layer stores common configuration. All curio instances can include it in their %s argument.": 33,
|
||||||
|
"The Curio team wants to improve the software you use. Tell the team you're using `%s`.": 19,
|
||||||
|
"The sectors are in the database. The database is ready for %s.": 42,
|
||||||
|
"This interactive tool creates a new miner actor and creates the basic configuration layer for it.": 1,
|
||||||
|
"This interactive tool migrates lotus-miner to Curio in 5 minutes.": 3,
|
||||||
|
"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.": 2,
|
||||||
|
"To run Curio: With machine or cgroup isolation, use the command (with example layer selection):": 120,
|
||||||
|
"To start, ensure your sealing pipeline is drained and shut-down lotus-miner.": 60,
|
||||||
|
"To work with the config: ": 119,
|
||||||
|
"Try the web interface with %s for further guided improvements.": 11,
|
||||||
|
"Use the arrow keys to navigate: ↓ ↑ → ← ": 0,
|
||||||
|
"Username: %s": 106,
|
||||||
|
"Waiting for %s to write sectors into Yugabyte.": 39,
|
||||||
|
"Worker Address: %s": 73,
|
||||||
|
"You can add other layers for per-machine configuration changes.": 34,
|
||||||
|
"You can now migrate your market node (%s), if applicable.": 12,
|
||||||
|
"could not get API info for FullNode: %w": 16,
|
||||||
}
|
}
|
||||||
|
|
||||||
var enIndex = []uint32{ // 82 elements
|
var enIndex = []uint32{ // 122 elements
|
||||||
// Entry 0 - 1F
|
// Entry 0 - 1F
|
||||||
0x00000000, 0x00000042, 0x0000009b, 0x000000d0,
|
0x00000000, 0x00000035, 0x00000097, 0x0000015a,
|
||||||
0x000000eb, 0x0000010b, 0x0000014d, 0x0000018a,
|
0x0000019c, 0x000001f5, 0x00000210, 0x0000021b,
|
||||||
0x000001ad, 0x000001e5, 0x00000211, 0x0000023c,
|
0x0000023d, 0x00000250, 0x0000026a, 0x0000028a,
|
||||||
0x00000257, 0x0000028f, 0x000002e6, 0x00000319,
|
0x000002cc, 0x00000309, 0x0000032c, 0x00000372,
|
||||||
0x00000361, 0x000003a0, 0x000003c9, 0x000003d2,
|
0x0000038b, 0x000003b6, 0x000003d1, 0x00000409,
|
||||||
0x000003ec, 0x0000040d, 0x0000042e, 0x0000044e,
|
0x00000463, 0x00000496, 0x000004e0, 0x00000521,
|
||||||
0x0000046b, 0x00000488, 0x000004bb, 0x000004c9,
|
0x00000556, 0x0000055f, 0x00000580, 0x000005a1,
|
||||||
0x000004dd, 0x00000548, 0x00000588, 0x000005b1,
|
0x000005c1, 0x000005de, 0x000005fb, 0x0000062e,
|
||||||
// Entry 20 - 3F
|
// Entry 20 - 3F
|
||||||
0x000005f6, 0x0000064c, 0x0000069d, 0x000006e9,
|
0x0000063c, 0x00000650, 0x000006bb, 0x000006fb,
|
||||||
0x0000071b, 0x00000749, 0x00000768, 0x000007aa,
|
0x00000724, 0x0000079b, 0x000007ec, 0x00000838,
|
||||||
0x000007e3, 0x000007fc, 0x00000810, 0x00000840,
|
0x0000086a, 0x00000898, 0x000008b7, 0x000008f9,
|
||||||
0x000008a2, 0x000008ae, 0x000008ba, 0x000008ca,
|
0x00000932, 0x0000094b, 0x0000095f, 0x0000098f,
|
||||||
0x000008da, 0x000008ea, 0x00000911, 0x00000952,
|
0x000009b9, 0x000009e3, 0x00000a05, 0x00000a7c,
|
||||||
0x00000976, 0x00000987, 0x000009a9, 0x000009bb,
|
0x00000a98, 0x00000ac5, 0x00000ae7, 0x00000b08,
|
||||||
0x000009e8, 0x00000a12, 0x00000a3c, 0x00000a5e,
|
0x00000b29, 0x00000b4a, 0x00000b6b, 0x00000b85,
|
||||||
0x00000aa4, 0x00000ac0, 0x00000aed, 0x00000b0e,
|
0x00000b9b, 0x00000be8, 0x00000c22, 0x00000c28,
|
||||||
// Entry 40 - 5F
|
// Entry 40 - 5F
|
||||||
0x00000b28, 0x00000b3e, 0x00000b8b, 0x00000bc5,
|
0x00000c64, 0x00000c90, 0x00000cd9, 0x00000d19,
|
||||||
0x00000bcb, 0x00000c07, 0x00000c33, 0x00000c7c,
|
0x00000d6a, 0x00000d7c, 0x00000d96, 0x00000db6,
|
||||||
0x00000cbc, 0x00000d0d, 0x00000d1f, 0x00000d39,
|
0x00000ddb, 0x00000df0, 0x00000e06, 0x00000e1c,
|
||||||
0x00000d90, 0x00000e2d, 0x00000e84, 0x00000e9e,
|
0x00000e2f, 0x00000e48, 0x00000e87, 0x00000eb1,
|
||||||
0x00000ebc, 0x00000f1c,
|
0x00000ec9, 0x00000edd, 0x00000f00, 0x00000f14,
|
||||||
} // Size: 352 bytes
|
0x00000f2a, 0x00000f3c, 0x00000f5f, 0x00000f71,
|
||||||
|
0x00000f93, 0x00000fbb, 0x00000fdc, 0x00000ff7,
|
||||||
|
0x00001020, 0x00001042, 0x00001074, 0x0000110b,
|
||||||
|
// Entry 60 - 7F
|
||||||
|
0x00001136, 0x0000116e, 0x00001197, 0x000011cf,
|
||||||
|
0x00001210, 0x00001240, 0x00001263, 0x0000128b,
|
||||||
|
0x000012ed, 0x000012f9, 0x00001305, 0x00001315,
|
||||||
|
0x00001325, 0x00001335, 0x0000135c, 0x0000139d,
|
||||||
|
0x000013c1, 0x000013d2, 0x000013f4, 0x00001421,
|
||||||
|
0x00001478, 0x00001515, 0x0000156c, 0x00001586,
|
||||||
|
0x000015a4, 0x00001604,
|
||||||
|
} // Size: 512 bytes
|
||||||
|
|
||||||
const enData string = "" + // Size: 3868 bytes
|
const enData string = "" + // Size: 5636 bytes
|
||||||
"\x02This interactive tool migrates lotus-miner to Curio in 5 minutes." +
|
"\x04\x00\x01 0\x02Use the arrow keys to navigate: ↓ ↑ → ←\x02This intera" +
|
||||||
"\x02Each step needs your confirmation and can be reversed. Press Ctrl+C " +
|
"ctive tool creates a new miner actor and creates the basic configuration" +
|
||||||
"to exit at any time.\x04\x00\x01 0\x02Use the arrow keys to navigate: ↓ " +
|
" layer for it.\x02This process is partially idempotent. Once a new miner" +
|
||||||
"↑ → ←\x02Ctrl+C pressed in Terminal\x02Lotus-Miner to Curio Migration." +
|
" actor has been created and subsequent steps fail, the user need to run " +
|
||||||
"\x02Try the web interface with %[1]s for further guided improvements." +
|
"'curio config new-cluster < miner ID >' to finish the configuration.\x02" +
|
||||||
"\x02You can now migrate your market node (%[1]s), if applicable.\x02Migr" +
|
"This interactive tool migrates lotus-miner to Curio in 5 minutes.\x02Eac" +
|
||||||
"ating config.toml to database.\x02Error reading from database: %[1]s. Ab" +
|
"h step needs your confirmation and can be reversed. Press Ctrl+C to exit" +
|
||||||
"orting Migration.\x02Error connecting to lotus node: %[1]s %[2]s\x02coul" +
|
" at any time.\x02Ctrl+C pressed in Terminal\x02I want to:\x02Migrate fro" +
|
||||||
"d not get API info for FullNode: %[1]w\x02Error getting token: %[1]s\x02" +
|
"m existing Lotus-Miner\x02Create a new miner\x02Aborting remaining steps" +
|
||||||
"Error saving config to layer: %[1]s. Aborting Migration\x02Protocol Labs" +
|
".\x02Lotus-Miner to Curio Migration.\x02Try the web interface with %[1]s" +
|
||||||
" wants to improve the software you use. Tell the team you're using Curio" +
|
" for further guided improvements.\x02You can now migrate your market nod" +
|
||||||
".\x02Select what you want to share with the Curio team.\x02Individual Da" +
|
"e (%[1]s), if applicable.\x02New Miner initialization complete.\x02Migra" +
|
||||||
"ta: Miner ID, Curio version, net (%[1]s or %[2]s). Signed.\x02Aggregate-" +
|
"ting lotus-miner config.toml to Curio in-database configuration.\x02Erro" +
|
||||||
"Anonymous: version, net, and Miner power (bucketed).\x02Hint: I am someo" +
|
"r getting API: %[1]s\x02could not get API info for FullNode: %[1]w\x02Er" +
|
||||||
"ne running Curio on net.\x02Nothing.\x02Aborting remaining steps.\x02Err" +
|
"ror getting token: %[1]s\x02Error saving config to layer: %[1]s. Abortin" +
|
||||||
"or getting miner power: %[1]s\x02Error marshalling message: %[1]s\x02Err" +
|
"g Migration\x02The Curio team wants to improve the software you use. Tel" +
|
||||||
"or getting miner info: %[1]s\x02Error signing message: %[1]s\x02Error se" +
|
"l the team you're using `%[1]s`.\x02Select what you want to share with t" +
|
||||||
"nding message: %[1]s\x04\x00\x01 .\x02Error sending message: Status %[1]" +
|
"he Curio team.\x02Individual Data: Miner ID, Curio version, chain (%[1]s" +
|
||||||
"s, Message:\x02Message sent.\x04\x00\x01 \x0f\x02Documentation:\x02The '" +
|
" or %[2]s). Signed.\x02Aggregate-Anonymous: version, chain, and Miner po" +
|
||||||
"%[1]s' layer stores common configuration. All curio instances can includ" +
|
"wer (bucketed).\x02Hint: I am someone running Curio on whichever chain." +
|
||||||
"e it in their %[2]s argument.\x02You can add other layers for per-machin" +
|
"\x02Nothing.\x02Error getting miner power: %[1]s\x02Error marshalling me" +
|
||||||
"e configuration changes.\x02Filecoin %[1]s channels: %[2]s and %[3]s\x02" +
|
"ssage: %[1]s\x02Error getting miner info: %[1]s\x02Error signing message" +
|
||||||
"Start multiple Curio instances with the '%[1]s' layer to redundancy.\x02" +
|
": %[1]s\x02Error sending message: %[1]s\x04\x00\x01 .\x02Error sending m" +
|
||||||
"Point your browser to your web GUI to complete setup with %[1]s and adva" +
|
"essage: Status %[1]s, Message:\x02Message sent.\x04\x00\x01 \x0f\x02Docu" +
|
||||||
"nced featues.\x02One database can serve multiple miner IDs: Run a migrat" +
|
"mentation:\x02The '%[1]s' layer stores common configuration. All curio i" +
|
||||||
"ion for each lotus-miner.\x02Please start (or restart) %[1]s now that da" +
|
"nstances can include it in their %[2]s argument.\x02You can add other la" +
|
||||||
"tabase credentials are in %[2]s.\x02Waiting for %[1]s to write sectors i" +
|
"yers for per-machine configuration changes.\x02Filecoin %[1]s channels: " +
|
||||||
"nto Yugabyte.\x02Error interpreting miner ID: %[1]s: ID: %[2]s\x02Error " +
|
"%[2]s and %[3]s\x02Increase reliability using redundancy: start multiple" +
|
||||||
"verifying sectors: %[1]s\x02The sectors are in the database. The databas" +
|
" machines with at-least the post layer: 'curio run --layers=post'\x02One" +
|
||||||
"e is ready for %[1]s.\x02Now shut down lotus-miner and move the systems " +
|
" database can serve multiple miner IDs: Run a migration for each lotus-m" +
|
||||||
"to %[1]s.\x02Press return to continue\x02Aborting migration.\x02Sectors " +
|
"iner.\x02Please start (or restart) %[1]s now that database credentials a" +
|
||||||
"verified. %[1]d sector locations found.\x02Enter the info to connect to " +
|
"re in %[2]s.\x02Waiting for %[1]s to write sectors into Yugabyte.\x02Err" +
|
||||||
"your Yugabyte database installation (https://download.yugabyte.com/)\x02" +
|
"or interpreting miner ID: %[1]s: ID: %[2]s\x02Error verifying sectors: %" +
|
||||||
"Host: %[1]s\x02Port: %[1]s\x02Username: %[1]s\x02Password: %[1]s\x02Data" +
|
"[1]s\x02The sectors are in the database. The database is ready for %[1]s" +
|
||||||
"base: %[1]s\x02Continue to connect and update schema.\x04\x00\x01 <\x02D" +
|
".\x02Now shut down lotus-miner and move the systems to %[1]s.\x02Press r" +
|
||||||
"atabase config error occurred, abandoning migration: %[1]s\x02Enter the " +
|
"eturn to continue\x02Aborting migration.\x02Sectors verified. %[1]d sect" +
|
||||||
"Yugabyte database host(s)\x02No host provided\x02Enter the Yugabyte data" +
|
"or locations found.\x02Connected to Yugabyte. Schema is current.\x02Enab" +
|
||||||
"base %[1]s\x02No value provided\x02Error connecting to Yugabyte database" +
|
"ling Sector Indexing in the database.\x02Error encoding config.toml: %[1" +
|
||||||
": %[1]s\x02Connected to Yugabyte. Schema is current.\x02Enabling Sector " +
|
"]s\x02Press return to update %[1]s with Yugabyte info. A Backup file wil" +
|
||||||
"Indexing in the database.\x02Error encoding config.toml: %[1]s\x02Press " +
|
"l be written to that folder before changes are made.\x02Error expanding " +
|
||||||
"return to update %[1]s with Yugabyte info. Backup the file now.\x02Error" +
|
"path: %[1]s\x02Error reading filemode of config.toml: %[1]s\x02Error cre" +
|
||||||
" expanding path: %[1]s\x02Error reading filemode of config.toml: %[1]s" +
|
"ating backup file: %[1]s\x02Error reading config.toml: %[1]s\x02Error wr" +
|
||||||
"\x02Error writing config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus M" +
|
"iting backup file: %[1]s\x02Error closing backup file: %[1]s\x02Error wr" +
|
||||||
"iner.\x02Connected to Yugabyte\x02To start, ensure your sealing pipeline" +
|
"iting config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus Miner.\x02Con" +
|
||||||
" is drained and shut-down lotus-miner.\x02Select the location of your lo" +
|
"nected to Yugabyte\x02To start, ensure your sealing pipeline is drained " +
|
||||||
"tus-miner config directory?\x02Other\x02Enter the path to the configurat" +
|
"and shut-down lotus-miner.\x02Select the location of your lotus-miner co" +
|
||||||
"ion directory used by %[1]s\x04\x00\x01 '\x02No path provided, abandonin" +
|
"nfig directory?\x02Other\x02Enter the path to the configuration director" +
|
||||||
"g migration\x02Cannot read the config.toml file in the provided director" +
|
"y used by %[1]s\x04\x00\x01 '\x02No path provided, abandoning migration" +
|
||||||
"y, Error: %[1]s\x02Could not create repo from directory: %[1]s. Aborting" +
|
"\x02Cannot read the config.toml file in the provided directory, Error: %" +
|
||||||
" migration\x02Could not lock miner repo. Your miner must be stopped: %[1" +
|
"[1]s\x02Could not create repo from directory: %[1]s. Aborting migration" +
|
||||||
"]s\x0a Aborting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02St" +
|
"\x02Could not lock miner repo. Your miner must be stopped: %[1]s\x0a Abo" +
|
||||||
"ep Complete: %[1]s\x02Configuration 'base' was updated to include this m" +
|
"rting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02Step Complet" +
|
||||||
"iner's address and its wallet setup.\x02Compare the configurations %[1]s" +
|
"e: %[1]s\x02Initializing a new miner actor.\x02Enter the info to create " +
|
||||||
" to %[2]s. Changes between the miner IDs other than wallet addreses shou" +
|
"a new miner\x02Owner Address: %[1]s\x02Worker Address: %[1]s\x02Sender A" +
|
||||||
"ld be a new, minimal layer for runners that need it.\x02Configuration 'b" +
|
"ddress: %[1]s\x02Sector Size: %[1]d\x02Confidence epochs: %[1]d\x02Conti" +
|
||||||
"ase' was created to include this miner's address and its wallet setup." +
|
"nue to verify the addresses and create a new miner actor.\x04\x00\x01 %" +
|
||||||
"\x04\x00\x01 \x15\x02Layer %[1]s created.\x04\x00\x01 \x19\x02To work wi" +
|
"\x02Miner creation error occurred: %[1]s\x02Enter the owner address\x02N" +
|
||||||
"th the config:\x02To run Curio: With machine or cgroup isolation, use th" +
|
"o address provided\x02Failed to parse the address: %[1]s\x02Enter %[1]s " +
|
||||||
"e command (with example layer selection):"
|
"address\x02Enter the sector size\x02No value provided\x02Failed to parse" +
|
||||||
|
" sector size: %[1]s\x02Confidence epochs\x02Failed to parse confidence: " +
|
||||||
|
"%[1]s\x02Failed to create the miner actor: %[1]s\x02Miner %[1]s created " +
|
||||||
|
"successfully\x02Cannot reach the DB: %[1]s\x02Error connecting to full n" +
|
||||||
|
"ode API: %[1]s\x02Pre-initialization steps complete\x02Failed to generat" +
|
||||||
|
"e random bytes for secret: %[1]s\x02Please do not run guided-setup again" +
|
||||||
|
" as miner creation is not idempotent. You need to run 'curio config new-" +
|
||||||
|
"cluster %[1]s' to finish the configuration\x02Failed to get API info for" +
|
||||||
|
" FullNode: %[1]w\x02Failed to verify the auth token from daemon node: %[" +
|
||||||
|
"1]s\x02Failed to generate default config: %[1]s\x02Failed to insert 'bas" +
|
||||||
|
"e' config layer in database: %[1]s\x02Configuration 'base' was updated t" +
|
||||||
|
"o include this miner's address\x02Failed to load base config from databa" +
|
||||||
|
"se: %[1]s\x02Failed to parse base config: %[1]s\x02Failed to regenerate " +
|
||||||
|
"base config: %[1]s\x02Enter the info to connect to your Yugabyte databas" +
|
||||||
|
"e installation (https://download.yugabyte.com/)\x02Host: %[1]s\x02Port: " +
|
||||||
|
"%[1]s\x02Username: %[1]s\x02Password: %[1]s\x02Database: %[1]s\x02Contin" +
|
||||||
|
"ue to connect and update schema.\x04\x00\x01 <\x02Database config error " +
|
||||||
|
"occurred, abandoning migration: %[1]s\x02Enter the Yugabyte database hos" +
|
||||||
|
"t(s)\x02No host provided\x02Enter the Yugabyte database %[1]s\x02Error c" +
|
||||||
|
"onnecting to Yugabyte database: %[1]s\x02Configuration 'base' was update" +
|
||||||
|
"d to include this miner's address and its wallet setup.\x02Compare the c" +
|
||||||
|
"onfigurations %[1]s to %[2]s. Changes between the miner IDs other than w" +
|
||||||
|
"allet addreses should be a new, minimal layer for runners that need it." +
|
||||||
|
"\x02Configuration 'base' was created to include this miner's address and" +
|
||||||
|
" its wallet setup.\x04\x00\x01 \x15\x02Layer %[1]s created.\x04\x00\x01 " +
|
||||||
|
"\x19\x02To work with the config:\x02To run Curio: With machine or cgroup" +
|
||||||
|
" isolation, use the command (with example layer selection):"
|
||||||
|
|
||||||
var koIndex = []uint32{ // 82 elements
|
var koIndex = []uint32{ // 122 elements
|
||||||
// Entry 0 - 1F
|
// Entry 0 - 1F
|
||||||
0x00000000, 0x0000004d, 0x000000c8, 0x0000010c,
|
0x00000000, 0x00000044, 0x000000c1, 0x000001c1,
|
||||||
0x0000012d, 0x00000150, 0x00000150, 0x000001a0,
|
0x0000020e, 0x00000289, 0x000002aa, 0x000002bc,
|
||||||
0x000001da, 0x0000022f, 0x0000022f, 0x0000022f,
|
0x000002e5, 0x00000300, 0x00000325, 0x00000348,
|
||||||
0x0000022f, 0x00000287, 0x00000315, 0x0000034e,
|
0x000003a2, 0x000003f2, 0x00000418, 0x00000471,
|
||||||
0x000003aa, 0x000003f4, 0x00000437, 0x00000452,
|
0x00000490, 0x000004cc, 0x000004fc, 0x00000554,
|
||||||
0x00000477, 0x000004b1, 0x000004e4, 0x0000051e,
|
0x000005e0, 0x00000619, 0x0000066f, 0x000006ad,
|
||||||
0x00000548, 0x00000572, 0x000005b4, 0x000005d8,
|
0x000006fb, 0x00000716, 0x00000750, 0x00000783,
|
||||||
0x000005e5, 0x0000066b, 0x000006bd, 0x000006bd,
|
0x000007bd, 0x000007e7, 0x00000811, 0x00000853,
|
||||||
// Entry 20 - 3F
|
// Entry 20 - 3F
|
||||||
0x000006bd, 0x0000071e, 0x0000071e, 0x0000071e,
|
0x00000877, 0x00000884, 0x0000090a, 0x0000095c,
|
||||||
0x00000762, 0x00000762, 0x00000789, 0x000007f4,
|
0x00000983, 0x00000a1f, 0x00000ab1, 0x00000b2c,
|
||||||
0x0000083e, 0x00000865, 0x00000880, 0x000008cf,
|
0x00000b70, 0x00000bae, 0x00000bd5, 0x00000c40,
|
||||||
0x0000093d, 0x0000094e, 0x0000095c, 0x00000974,
|
0x00000c8a, 0x00000cb1, 0x00000ccc, 0x00000d1b,
|
||||||
0x00000988, 0x000009a2, 0x000009cc, 0x00000a2f,
|
0x00000d5c, 0x00000d9c, 0x00000de3, 0x00000e89,
|
||||||
0x00000a6b, 0x00000a95, 0x00000acd, 0x00000af1,
|
0x00000eb9, 0x00000f08, 0x00000f2b, 0x00000f4c,
|
||||||
0x00000b45, 0x00000b86, 0x00000b86, 0x00000bcd,
|
0x00000f6f, 0x00000f92, 0x00000fd0, 0x00000ff4,
|
||||||
0x00000c39, 0x00000c39, 0x00000c88, 0x00000cc6,
|
0x0000100a, 0x00001075, 0x000010c4, 0x000010cb,
|
||||||
// Entry 40 - 5F
|
// Entry 40 - 5F
|
||||||
0x00000cea, 0x00000d00, 0x00000d6b, 0x00000dba,
|
0x00001113, 0x00001165, 0x000011bf, 0x00001229,
|
||||||
0x00000dc1, 0x00000e09, 0x00000e5b, 0x00000eb5,
|
0x000012ba, 0x000012d2, 0x000012ec, 0x00001310,
|
||||||
0x00000eb5, 0x00000eb5, 0x00000ecd, 0x00000ee7,
|
0x00001343, 0x0000135b, 0x00001373, 0x0000138b,
|
||||||
0x00000f51, 0x0000100b, 0x0000106f, 0x0000109e,
|
0x000013a0, 0x000013b8, 0x0000140f, 0x0000143a,
|
||||||
0x0000109e, 0x0000112a,
|
0x00001452, 0x00001479, 0x0000149c, 0x000014b0,
|
||||||
} // Size: 352 bytes
|
0x000014c5, 0x000014e9, 0x00001513, 0x00001524,
|
||||||
|
0x0000154a, 0x00001570, 0x000015a9, 0x000015e1,
|
||||||
|
0x00001619, 0x00001638, 0x00001684, 0x00001742,
|
||||||
|
// Entry 60 - 7F
|
||||||
|
0x0000178e, 0x000017dc, 0x000017ff, 0x0000185b,
|
||||||
|
0x000018ab, 0x00001900, 0x00001943, 0x00001982,
|
||||||
|
0x000019f0, 0x00001a01, 0x00001a0f, 0x00001a27,
|
||||||
|
0x00001a3b, 0x00001a55, 0x00001a7f, 0x00001ae2,
|
||||||
|
0x00001b1e, 0x00001b48, 0x00001b80, 0x00001bd4,
|
||||||
|
0x00001c3e, 0x00001cf8, 0x00001d5c, 0x00001d8b,
|
||||||
|
0x00001db2, 0x00001e3e,
|
||||||
|
} // Size: 512 bytes
|
||||||
|
|
||||||
const koData string = "" + // Size: 4394 bytes
|
const koData string = "" + // Size: 7742 bytes
|
||||||
"\x02이 대화형 도구는 5분 안에 lotus-miner를 Curio로 이주합니다.\x02각 단계는 확인이 필요하며 되돌릴 수 있" +
|
"\x04\x00\x01 ?\x02화살표 키를 사용하여 이동하세요: ↓ ↑ → ←\x02이 대화형 도구는 새로운 채굴자 액터를 생성" +
|
||||||
"습니다. 언제든지 Ctrl+C를 눌러 종료할 수 있습니다.\x04\x00\x01 ?\x02화살표 키를 사용하여 이동하세요: ↓" +
|
"하고 그에 대한 기본 구성 레이어를 생성합니다.\x02이 프로세스는 부분적으로 항등원적입니다. 새로운 채굴자 액터가 생성되었고" +
|
||||||
" ↑ → ←\x02터미널에서 Ctrl+C가 눌림\x02Lotus-Miner에서 Curio로 이주.\x02해당하는 경우 이제 시장 " +
|
" 후속 단계가 실패하는 경우 사용자는 구성을 완료하기 위해 'curio config new-cluster < 채굴자 ID >'를 " +
|
||||||
"노드를 이주할 수 있습니다 (%[1]s).\x02config.toml을 데이터베이스로 이주 중입니다.\x02데이터베이스에서 읽" +
|
"실행해야 합니다.\x02이 대화형 도구는 5분 안에 lotus-miner를 Curio로 이주합니다.\x02각 단계는 확인이 필" +
|
||||||
"는 중 오류 발생: %[1]s. 마이그레이션 중단.\x02레이어에 구성을 저장하는 중 오류 발생: %[1]s. 마이그레이션 중" +
|
"요하며 되돌릴 수 있습니다. 언제든지 Ctrl+C를 눌러 종료할 수 있습니다.\x02터미널에서 Ctrl+C가 눌림\x02나는 " +
|
||||||
"단\x02Protocol Labs는 당신이 사용하는 소프트웨어를 개선하고 싶어합니다. Curio를 사용 중이라고 팀에 알려주세" +
|
"원한다:\x02기존의 Lotus-Miner에서 이전하기\x02새로운 채굴자 생성\x02나머지 단계를 중단합니다.\x02Lotu" +
|
||||||
"요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 마이너 ID, Curio 버전, 네트워크 (%[" +
|
"s-Miner에서 Curio로 이주.\x02더 많은 안내를 위해 %[1]s를 사용하여 웹 인터페이스를 시도하세요.\x02해당하는 " +
|
||||||
"1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 네트워크, 그리고 마이너 파워 (버킷).\x02힌트: 네트워크에서 C" +
|
"경우 이제 시장 노드를 이주할 수 있습니다 (%[1]s).\x02새로운 채굴자 초기화 완료.\x02lotus-miner con" +
|
||||||
"urio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02나머지 단계를 중단합니다.\x02마이너 파워를 가져오는 중 오류 " +
|
"fig.toml을 Curio의 데이터베이스 구성으로 이전 중입니다.\x02API 가져오기 오류: %[1]s\x02FullNode의" +
|
||||||
"발생: %[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생: %[1]s" +
|
" API 정보를 가져올 수 없습니다: %[1]w\x02토큰을 가져오는 중 오류 발생: %[1]s\x02레이어에 구성을 저장하는 중" +
|
||||||
"\x02메시지 서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =\x02메시지 " +
|
" 오류 발생: %[1]s. 마이그레이션 중단\x02Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀에게 `%[1" +
|
||||||
"전송 중 오류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02문서:" +
|
"]s`를 사용 중이라고 알려주세요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 채굴자 ID, Cur" +
|
||||||
"\x02'%[1]s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니다." +
|
"io 버전, 체인 (%[1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 체인, 및 채굴자 파워 (버킷).\x02힌트:" +
|
||||||
"\x02기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.\x02브라우저를 웹 GUI로 이동하여 %[1]s 및 고급 기능" +
|
" 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02마이너 파워를 가져오는 중 오류 발생: " +
|
||||||
"으로 설정을 완료하세요.\x02%[1]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02섹터 확인 중 오류 발생:" +
|
"%[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생: %[1]s\x02메시지 " +
|
||||||
" %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1]s를 위해 준비되었습니다.\x02이제 lotus-miner" +
|
"서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =\x02메시지 전송 중 오" +
|
||||||
"를 종료하고 시스템을 %[1]s로 이동하세요.\x02계속하려면 리턴을 누르세요\x02마이그레이션 중단.\x02섹터가 확인되었습" +
|
"류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02문서:\x02'%[1]" +
|
||||||
"니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Yugabyte 데이터베이스 설치에 연결할 정보를 입력하십시오 (https" +
|
"s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니다.\x02기계별 구성 변" +
|
||||||
"://download.yugabyte.com/)\x02호스트: %[1]s\x02포트: %[1]s\x02사용자 이름: %[1]s" +
|
"경을 위해 다른 레이어를 추가할 수 있습니다.\x02Filecoin %[1]s 채널: %[2]s 및 %[3]s\x02신뢰성 향" +
|
||||||
"\x02비밀번호: %[1]s\x02데이터베이스: %[1]s\x02계속 연결 및 스키마 업데이트.\x04\x00\x01 ^\x02데" +
|
"상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio run --layers" +
|
||||||
"이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: %[1]s\x02Yugabyte 데이터베이스 호스트를 입력하십시오" +
|
"=post'\x02한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 대해 마이그레이션을 실" +
|
||||||
"\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하십시오\x02값이 제공되지 않았습니다" +
|
"행하세요.\x02데이터베이스 자격 증명이 %[2]s에 입력되었으므로 지금 %[1]s을 시작하거나 다시 시작하세요.\x02%[1" +
|
||||||
"\x02Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02Yugabyte에 연결되었습니다. 스키마가" +
|
"]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02광부 ID를 해석하는 중 오류 발생: %[1]s: ID: %[2]" +
|
||||||
" 현재입니다.\x02config.toml을 인코딩하는 중 오류가 발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로" +
|
"s\x02섹터 확인 중 오류 발생: %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1]s를 위해 준비되었습니다" +
|
||||||
" 업데이트하려면 리턴을 누르세요. 지금 파일을 백업하세요.\x02config.toml의 파일 모드를 읽는 중 오류가 발생했습니다:" +
|
".\x02이제 lotus-miner를 종료하고 시스템을 %[1]s로 이동하세요.\x02계속하려면 리턴을 누르세요\x02마이그레이션" +
|
||||||
" %[1]s\x02config.toml을 쓰는 중 오류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이" +
|
" 중단.\x02섹터가 확인되었습니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Yugabyte에 연결되었습니다. 스키마가 현재" +
|
||||||
"너 재시작.\x02Yugabyte에 연결됨\x02시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확" +
|
"입니다.\x02데이터베이스에서 Sector Indexing을 활성화합니다.\x02config.toml을 인코딩하는 중 오류가 " +
|
||||||
"인하세요.\x02로터스 마이너 구성 디렉토리의 위치를 선택하시겠습니까?\x02기타\x02%[1]s에서 사용하는 구성 디렉터리 " +
|
"발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로 업데이트하려면 리턴 키를 누르세요. 변경 사항을 적용하기 전" +
|
||||||
"경로를 입력하세요.\x04\x00\x01 M\x02경로가 제공되지 않았으므로 마이그레이션을 포기합니다\x02제공된 디렉토리에서" +
|
"에 해당 폴더에 백업 파일이 작성됩니다.\x02경로를 확장하는 중 오류 발생: %[1]s\x02config.toml의 파일 모" +
|
||||||
" config.toml 파일을 읽을 수 없습니다. 오류: %[1]s\x02마이너 구성 읽기\x04\x00\x01\x0a\x15" +
|
"드를 읽는 중 오류가 발생했습니다: %[1]s\x02백업 파일 생성 오류: %[1]s\x02config.toml 읽기 오류: " +
|
||||||
"\x02단계 완료: %[1]s\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 업데이트되었습니다.\x02구성 " +
|
"%[1]s\x02백업 파일 쓰기 오류: %[1]s\x02백업 파일 닫기 오류: %[1]s\x02config.toml을 쓰는 중 오" +
|
||||||
"%[1]s를 %[2]s과 비교하세요. 지갑 주소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이" +
|
"류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이너 재시작.\x02Yugabyte에 연결됨\x02" +
|
||||||
"어여야 합니다.\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 생성되었습니다.\x04\x00\x01 *" +
|
"시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.\x02로터스 마이너 구성 디렉토리의 위" +
|
||||||
"\x02레이어 %[1]s가 생성되었습니다.\x02Curio를 실행하려면: 기계 또는 cgroup 격리를 사용하여 다음 명령을 사용" +
|
"치를 선택하시겠습니까?\x02기타\x02%[1]s에서 사용하는 구성 디렉터리 경로를 입력하세요.\x04\x00\x01 M" +
|
||||||
"하세요 (예제 레이어 선택과 함께):"
|
"\x02경로가 제공되지 않았으므로 마이그레이션을 포기합니다\x02제공된 디렉토리에서 config.toml 파일을 읽을 수 없습니다" +
|
||||||
|
". 오류: %[1]s\x02디렉토리에서 저장소를 생성할 수 없습니다: %[1]s. 마이그레이션을 중단합니다.\x02광부 저장소를 " +
|
||||||
|
"잠금 해제할 수 없습니다. 귀하의 광부를 중지해야 합니다: %[1]s\x0a 마이그레이션을 중단합니다.\x02마이너 구성 읽기" +
|
||||||
|
"\x04\x00\x01\x0a\x15\x02단계 완료: %[1]s\x02새 채굴자 액터 초기화 중.\x02새 채굴자를 생성하기 위" +
|
||||||
|
"한 정보 입력\x02소유자 주소: %[1]s\x02작업자 주소: %[1]s\x02송신자 주소: %[1]s\x02섹터 크기: %" +
|
||||||
|
"[1]d\x02신뢰 에포크: %[1]d\x02주소를 확인하고 새 채굴자 액터를 생성하려면 계속 진행하세요.\x04\x00\x01 " +
|
||||||
|
"&\x02채굴자 생성 오류 발생: %[1]s\x02소유자 주소 입력\x02주소가 제공되지 않았습니다\x02주소 구문 분석 실패: " +
|
||||||
|
"%[1]s\x02%[1]s 주소 입력\x02섹터 크기 입력\x02값이 제공되지 않았습니다\x02섹터 크기 구문 분석 실패: %[1" +
|
||||||
|
"]s\x02신뢰 에포크\x02신뢰도 구문 분석 실패: %[1]s\x02채굴자 액터 생성 실패: %[1]s\x02%[1]s 채굴자가" +
|
||||||
|
" 성공적으로 생성되었습니다\x02데이터베이스에 연결할 수 없습니다: %[1]s\x02풀 노드 API에 연결하는 중 오류 발생: %" +
|
||||||
|
"[1]s\x02사전 초기화 단계 완료\x02비밀번호를 위한 랜덤 바이트 생성에 실패했습니다: %[1]s\x02마이너 생성은 ide" +
|
||||||
|
"mpotent하지 않으므로 가이드 설정을 다시 실행하지 마십시오. 구성을 완료하려면 'curio config new-cluster" +
|
||||||
|
" %[1]s'를 실행해야 합니다.\x02FullNode에 대한 API 정보를 가져오는 데 실패했습니다: %[1]w\x02데몬 노드" +
|
||||||
|
"로부터 인증 토큰을 확인하는 중 오류 발생: %[1]s\x02기본 구성 생성 실패: %[1]s\x02데이터베이스에 'base'" +
|
||||||
|
" 구성 레이어를 삽입하는 데 실패했습니다: %[1]s\x02이 마이너 주소를 포함한 구성 'base'가 업데이트되었습니다.\x02" +
|
||||||
|
"데이터베이스에서 기본 구성을 로드하는 데 실패했습니다: %[1]s\x02기본 구성을 구문 분석하는 데 실패했습니다: %[1]s" +
|
||||||
|
"\x02기본 구성을 재생성하는 데 실패했습니다: %[1]s\x02Yugabyte 데이터베이스 설치에 연결할 정보를 입력하십시오 (" +
|
||||||
|
"https://download.yugabyte.com/)\x02호스트: %[1]s\x02포트: %[1]s\x02사용자 이름: %[" +
|
||||||
|
"1]s\x02비밀번호: %[1]s\x02데이터베이스: %[1]s\x02계속 연결 및 스키마 업데이트.\x04\x00\x01 ^" +
|
||||||
|
"\x02데이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: %[1]s\x02Yugabyte 데이터베이스 호스트를 입력하십" +
|
||||||
|
"시오\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하십시오\x02Yugabyte 데이터" +
|
||||||
|
"베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 업데" +
|
||||||
|
"이트되었습니다.\x02구성 %[1]s를 %[2]s과 비교하세요. 지갑 주소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행" +
|
||||||
|
"자를 위한 새로운 최소한의 레이어여야 합니다.\x02이 마이너의 주소와 지갑 설정을 포함하도록 구성 'base'가 생성되었습니" +
|
||||||
|
"다.\x04\x00\x01 *\x02레이어 %[1]s가 생성되었습니다.\x04\x00\x01 \x22\x02구성 파일을 사용하" +
|
||||||
|
"려면:\x02Curio를 실행하려면: 기계 또는 cgroup 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께" +
|
||||||
|
"):"
|
||||||
|
|
||||||
var zhIndex = []uint32{ // 82 elements
|
var zhIndex = []uint32{ // 122 elements
|
||||||
// Entry 0 - 1F
|
// Entry 0 - 1F
|
||||||
0x00000000, 0x00000048, 0x00000097, 0x000000ca,
|
0x00000000, 0x00000033, 0x0000008b, 0x00000134,
|
||||||
0x000000e3, 0x00000100, 0x00000100, 0x00000141,
|
0x0000017c, 0x000001cb, 0x000001e4, 0x000001f1,
|
||||||
0x0000016b, 0x000001a4, 0x000001a4, 0x000001a4,
|
0x00000211, 0x0000022a, 0x00000240, 0x0000025d,
|
||||||
0x000001a4, 0x000001dd, 0x0000022f, 0x0000025c,
|
0x0000029c, 0x000002dd, 0x000002f9, 0x0000033e,
|
||||||
0x000002a9, 0x000002e7, 0x00000317, 0x00000321,
|
0x0000035b, 0x00000384, 0x000003a2, 0x000003db,
|
||||||
0x00000337, 0x0000035b, 0x00000379, 0x0000039d,
|
0x0000042f, 0x0000045c, 0x000004ab, 0x000004e6,
|
||||||
0x000003bb, 0x000003d9, 0x0000040e, 0x00000421,
|
0x0000051b, 0x00000525, 0x00000549, 0x00000567,
|
||||||
0x00000430, 0x0000048a, 0x000004c7, 0x000004c7,
|
0x0000058b, 0x000005a9, 0x000005c7, 0x000005fc,
|
||||||
// Entry 20 - 3F
|
// Entry 20 - 3F
|
||||||
0x000004c7, 0x0000051e, 0x0000051e, 0x0000051e,
|
0x0000060f, 0x0000061e, 0x00000678, 0x000006b5,
|
||||||
0x00000544, 0x00000544, 0x00000562, 0x0000059e,
|
0x000006dd, 0x0000073c, 0x0000078c, 0x000007df,
|
||||||
0x000005d0, 0x000005e0, 0x000005f0, 0x00000623,
|
0x00000805, 0x00000832, 0x00000850, 0x0000088c,
|
||||||
0x0000067d, 0x0000068c, 0x0000069b, 0x000006ad,
|
0x000008be, 0x000008ce, 0x000008de, 0x00000911,
|
||||||
0x000006bc, 0x000006ce, 0x000006ed, 0x00000725,
|
0x0000093e, 0x00000963, 0x00000986, 0x000009fe,
|
||||||
0x0000074a, 0x0000075a, 0x00000778, 0x00000785,
|
0x00000a1c, 0x00000a4b, 0x00000a6f, 0x00000a94,
|
||||||
0x000007b1, 0x000007de, 0x000007de, 0x00000801,
|
0x00000ab8, 0x00000adc, 0x00000aff, 0x00000b1f,
|
||||||
0x00000845, 0x00000845, 0x00000874, 0x00000897,
|
0x00000b34, 0x00000b7f, 0x00000baf, 0x00000bb6,
|
||||||
// Entry 40 - 5F
|
// Entry 40 - 5F
|
||||||
0x000008b7, 0x000008cc, 0x00000917, 0x00000947,
|
0x00000be0, 0x00000c04, 0x00000c48, 0x00000c7a,
|
||||||
0x0000094e, 0x00000978, 0x0000099c, 0x000009e0,
|
0x00000cc3, 0x00000cd6, 0x00000cf0, 0x00000d0f,
|
||||||
0x000009e0, 0x000009e0, 0x000009f3, 0x00000a0d,
|
0x00000d34, 0x00000d4c, 0x00000d61, 0x00000d79,
|
||||||
0x00000a59, 0x00000adb, 0x00000b27, 0x00000b41,
|
0x00000d8d, 0x00000da4, 0x00000dd5, 0x00000dfa,
|
||||||
0x00000b41, 0x00000b98,
|
0x00000e10, 0x00000e20, 0x00000e3a, 0x00000e4e,
|
||||||
} // Size: 352 bytes
|
0x00000e61, 0x00000e6e, 0x00000e8e, 0x00000e9e,
|
||||||
|
0x00000ebb, 0x00000edb, 0x00000ef5, 0x00000f12,
|
||||||
|
0x00000f43, 0x00000f5c, 0x00000f85, 0x00001012,
|
||||||
|
// Entry 60 - 7F
|
||||||
|
0x0000103e, 0x00001079, 0x00001099, 0x000010ca,
|
||||||
|
0x000010fd, 0x0000112a, 0x0000114b, 0x00001171,
|
||||||
|
0x000011cb, 0x000011da, 0x000011e9, 0x000011fb,
|
||||||
|
0x0000120a, 0x0000121c, 0x0000123b, 0x00001273,
|
||||||
|
0x00001298, 0x000012a8, 0x000012c6, 0x000012f2,
|
||||||
|
0x0000133e, 0x000013c0, 0x0000140c, 0x00001426,
|
||||||
|
0x0000143e, 0x00001495,
|
||||||
|
} // Size: 512 bytes
|
||||||
|
|
||||||
const zhData string = "" + // Size: 2968 bytes
|
const zhData string = "" + // Size: 5269 bytes
|
||||||
"\x02这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。\x02每一步都需要您的确认,并且可以撤销。随时按Ctrl+C退出" +
|
"\x04\x00\x01 .\x02使用箭头键进行导航:↓ ↑ → ←\x02此交互式工具将创建一个新的矿工角色,并为其创建基本配置层。\x02" +
|
||||||
"。\x04\x00\x01 .\x02使用箭头键进行导航:↓ ↑ → ←\x02在终端中按下Ctrl+C\x02Lotus-Miner到Cu" +
|
"该过程部分幂等。一旦创建了新的矿工角色,并且随后的步骤失败,用户需要运行 'curio config new-cluster < 矿工 ID" +
|
||||||
"rio迁移。\x02如果适用,您现在可以迁移您的市场节点(%[1]s)。\x02正在将config.toml迁移到数据库。\x02读取数据库时出" +
|
" >' 来完成配置。\x02这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。\x02每一步都需要您的确认,并且可以撤销。随" +
|
||||||
"错:%[1]s。正在中止迁移。\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Protocol Labs希望改进您使用的软件。告" +
|
"时按Ctrl+C退出。\x02在终端中按下Ctrl+C\x02我想要:\x02从现有的 Lotus-Miner 迁移\x02创建一个新的矿工" +
|
||||||
"诉团队您正在使用Curio。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工ID、Curio版本、网络(%[1]s或%[2" +
|
"\x02中止剩余步骤。\x02Lotus-Miner到Curio迁移。\x02尝试使用%[1]s的Web界面进行进一步引导式改进。\x02如果适" +
|
||||||
"]s)。已签名。\x02聚合-匿名:版本、网络和矿工功率(分桶)。\x02提示:我是在网络上运行Curio的人。\x02没有。\x02中止剩余步" +
|
"用,您现在可以迁移您的市场节点(%[1]s)。\x02新矿工初始化完成。\x02将 lotus-miner config.toml 迁移到 " +
|
||||||
"骤。\x02获取矿工功率时出错:%[1]s\x02整理消息时出错:%[1]s\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%" +
|
"Curio 的数据库配置中。\x02获取 API 时出错:%[1]s\x02无法获取FullNode的API信息:%[1]w\x02获取令牌时出" +
|
||||||
"[1]s\x02发送消息时出错:%[1]s\x04\x00\x01 0\x02发送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04" +
|
"错:%[1]s\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Curio 团队希望改进您使用的软件。告诉团队您正在使用 `%[1" +
|
||||||
"\x00\x01 \x0a\x02文档:\x02'%[1]s'层存储通用配置。所有Curio实例都可以在其%[2]s参数中包含它。\x02您可以" +
|
"]s`。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工 ID,Curio 版本,链(%[1]s 或 %[2]s)。签名。" +
|
||||||
"添加其他层进行每台机器的配置更改。\x02将您的浏览器指向您的网络GUI,以使用%[1]s和高级功能完成设置。\x02等待%[1]s将扇区写" +
|
"\x02聚合-匿名:版本,链和矿工算力(分桶)。\x02提示:我是在任何链上运行 Curio 的人。\x02没有。\x02获取矿工功率时出错:%" +
|
||||||
"入Yugabyte。\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-mi" +
|
"[1]s\x02整理消息时出错:%[1]s\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%[1]s\x02发送消息时出错:%[1" +
|
||||||
"ner并将系统移至%[1]s。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02输入连接到您的Yuga" +
|
"]s\x04\x00\x01 0\x02发送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04\x00\x01 \x0a\x02文档" +
|
||||||
"byte数据库安装的信息(https://download.yugabyte.com/)\x02主机:%[1]s\x02端口:%[1]s\x02" +
|
":\x02'%[1]s'层存储通用配置。所有Curio实例都可以在其%[2]s参数中包含它。\x02您可以添加其他层进行每台机器的配置更改。" +
|
||||||
"用户名:%[1]s\x02密码:%[1]s\x02数据库:%[1]s\x02继续连接和更新架构。\x04\x00\x01 3\x02发生数据" +
|
"\x02Filecoin %[1]s 频道:%[2]s 和 %[3]s\x02通过冗余增加可靠性:使用至少后层启动多台机器:'curio run" +
|
||||||
"库配置错误,放弃迁移:%[1]s\x02输入Yugabyte数据库主机(S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s" +
|
" --layers=post'\x02一个数据库可以服务多个矿工ID:为每个lotus-miner运行迁移。\x02请立即启动(或重新启动)%[" +
|
||||||
"\x02未提供值\x02连接到Yugabyte数据库时出错:%[1]s\x02已连接到Yugabyte。模式是当前的。\x02编码config." +
|
"1]s,因为数据库凭据已在%[2]s中。\x02等待%[1]s将扇区写入Yugabyte。\x02解释矿工ID时出错:%[1]s:ID:%[2]" +
|
||||||
"toml时出错:%[1]s\x02按回车更新%[1]s以获取Yugabyte信息。现在备份文件。\x02读取config.toml文件模式时出错" +
|
"s\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-miner并将系统移至%[" +
|
||||||
":%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b\x02重新启动Lotus Miner。" +
|
"1]s。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02已连接到Yugabyte。模式是当前的。" +
|
||||||
"\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。\x02选择您的lotus-miner配" +
|
"\x02在数据库中启用扇区索引。\x02编码config.toml时出错:%[1]s\x02按回车键更新 %[1]s 以包含 Yugabyte " +
|
||||||
"置目录的位置?\x02其他\x02输入%[1]s使用的配置目录的路径\x04\x00\x01 \x1f\x02未提供路径,放弃迁移\x02无" +
|
"信息。在进行更改之前,将在该文件夹中写入备份文件。\x02扩展路径时出错:%[1]s\x02读取config.toml文件模式时出错:%[1" +
|
||||||
"法读取提供的目录中的config.toml文件,错误:%[1]s\x02读取矿工配置\x04\x00\x01\x0a\x15\x02步骤完成" +
|
"]s\x02创建备份文件时出错:%[1]s\x02读取 config.toml 时出错:%[1]s\x02写入备份文件时出错:%[1]s\x02" +
|
||||||
":%[1]s\x02配置'base'已更新,包含了这个矿工的地址和其钱包设置。\x02比较配置%[1]s和%[2]s。矿工ID之间除了钱包地" +
|
"关闭备份文件时出错:%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b\x02重新启动Lotu" +
|
||||||
"址的变化应该是需要的运行者的一个新的、最小的层。\x02配置'base'已创建,包括了这个矿工的地址和其钱包设置。\x04\x00\x01 " +
|
"s Miner。\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。\x02选择您的lotu" +
|
||||||
"\x15\x02层%[1]s已创建。\x02运行Curio:使用机器或cgroup隔离,使用命令(附带示例层选择):"
|
"s-miner配置目录的位置?\x02其他\x02输入%[1]s使用的配置目录的路径\x04\x00\x01 \x1f\x02未提供路径,放弃迁" +
|
||||||
|
"移\x02无法读取提供的目录中的config.toml文件,错误:%[1]s\x02无法从目录创建repo:%[1]s。 中止迁移\x02无" +
|
||||||
|
"法锁定矿工repo。 您的矿工必须停止:%[1]s\x0a 中止迁移\x02读取矿工配置\x04\x00\x01\x0a\x15\x02步骤" +
|
||||||
|
"完成:%[1]s\x02初始化新的矿工角色。\x02输入创建新矿工所需的信息\x02所有者地址:%[1]s\x02工作地址:%[1]s" +
|
||||||
|
"\x02发送者地址:%[1]s\x02扇区大小: %[1]d\x02置信度时期: %[1]d\x02继续验证地址并创建新的矿工角色。\x04" +
|
||||||
|
"\x00\x01 \x02矿工创建错误发生: %[1]s\x02输入所有者地址\x02未提供地址\x02解析地址失败: %[1]s\x02输入" +
|
||||||
|
" %[1]s 地址\x02输入扇区大小\x02未提供值\x02解析扇区大小失败: %[1]s\x02置信度时期\x02解析置信度失败: %[1]" +
|
||||||
|
"s\x02创建矿工角色失败: %[1]s\x02矿工 %[1]s 创建成功\x02无法访问数据库: %[1]s\x02连接到完整节点 API 时" +
|
||||||
|
"发生错误: %[1]s\x02预初始化步骤完成\x02生成密码的随机字节失败: %[1]s\x02请不要再次运行引导设置,因为矿工创建不是幂" +
|
||||||
|
"等的。 您需要运行 'curio config new-cluster %[1]s' 来完成配置。\x02无法获取 FullNode 的 A" +
|
||||||
|
"PI 信息: %[1]w\x02无法验证来自守护进程节点的授权令牌: %[1]s\x02无法生成默认配置: %[1]s\x02无法将 'base" +
|
||||||
|
"' 配置层插入数据库: %[1]s\x02配置 'base' 已更新以包含此矿工的地址\x02从数据库加载基本配置失败:%[1]s\x02解析基" +
|
||||||
|
"本配置失败:%[1]s\x02重新生成基本配置失败: %[1]s\x02输入连接到您的Yugabyte数据库安装的信息(https://do" +
|
||||||
|
"wnload.yugabyte.com/)\x02主机:%[1]s\x02端口:%[1]s\x02用户名:%[1]s\x02密码:%[1]s" +
|
||||||
|
"\x02数据库:%[1]s\x02继续连接和更新架构。\x04\x00\x01 3\x02发生数据库配置错误,放弃迁移:%[1]s\x02输入Y" +
|
||||||
|
"ugabyte数据库主机(S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s\x02连接到Yugabyte数据库时出错:%[1" +
|
||||||
|
"]s\x02配置'base'已更新,包含了这个矿工的地址和其钱包设置。\x02比较配置%[1]s和%[2]s。矿工ID之间除了钱包地址的变化应该" +
|
||||||
|
"是需要的运行者的一个新的、最小的层。\x02配置'base'已创建,包括了这个矿工的地址和其钱包设置。\x04\x00\x01 \x15" +
|
||||||
|
"\x02层%[1]s已创建。\x04\x00\x01 \x13\x02要使用配置:\x02运行Curio:使用机器或cgroup隔离,使用命令(" +
|
||||||
|
"附带示例层选择):"
|
||||||
|
|
||||||
// Total table size 12286 bytes (11KiB); checksum: 15B16994
|
// Total table size 20183 bytes (19KiB); checksum: 4FD3E25A
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -699,6 +699,384 @@
|
|||||||
"translation": "구성 파일을 사용하려면:",
|
"translation": "구성 파일을 사용하려면:",
|
||||||
"message": "To work with the config:",
|
"message": "To work with the config:",
|
||||||
"placeholder": null
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "This interactive tool creates a new miner actor and creates the basic configuration layer for it.",
|
||||||
|
"translation": "이 대화형 도구는 새로운 채굴자 액터를 생성하고 그에 대한 기본 구성 레이어를 생성합니다.",
|
||||||
|
"message": "This interactive tool creates a new miner actor and creates the basic configuration layer for it.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "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 {Arg_1}' to finish the configuration.",
|
||||||
|
"translation": "이 프로세스는 부분적으로 idempotent합니다. 새로운 채굴자 액터가 생성되었고 후속 단계가 실패하면 사용자는 구성을 완료하기 위해 'curio config new-cluster {Arg_1}'를 실행해야 합니다.",
|
||||||
|
"message": "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 {Arg_1}' to finish the configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Choose if you with to create a new miner or migrate from existing Lotus-Miner",
|
||||||
|
"translation": "새 채굴자를 생성할지 기존의 Lotus-Miner에서 이전할지 선택하세요.",
|
||||||
|
"message": "Choose if you with to create a new miner or migrate from existing Lotus-Miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Migrate from existing Lotus-Miner",
|
||||||
|
"translation": "기존의 Lotus-Miner에서 이전하기",
|
||||||
|
"message": "Migrate from existing Lotus-Miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Create a new miner",
|
||||||
|
"translation": "새로운 채굴자 생성",
|
||||||
|
"message": "Create a new miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "New Miner initialization complete.",
|
||||||
|
"translation": "새로운 채굴자 초기화 완료.",
|
||||||
|
"message": "New Miner initialization complete.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Migrating lotus-miner config.toml to Curio in-database configuration.",
|
||||||
|
"translation": "lotus-miner config.toml을 Curio의 데이터베이스 구성으로 이전 중입니다.",
|
||||||
|
"message": "Migrating lotus-miner config.toml to Curio in-database configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error getting API: {Error}",
|
||||||
|
"translation": "API 가져오기 오류: {Error}",
|
||||||
|
"message": "Error getting API: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "The Curio team wants to improve the software you use. Tell the team you're using {Curio}.",
|
||||||
|
"translation": "Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀에게 {Curio}를 사용 중이라고 알려주세요.",
|
||||||
|
"message": "The Curio team wants to improve the software you use. Tell the team you're using {Curio}.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Individual Data: Miner ID, Curio version, chain ({Mainnet} or {Calibration}). Signed.",
|
||||||
|
"translation": "개별 데이터: 채굴자 ID, Curio 버전, 체인 ({Mainnet} 또는 {Calibration}). 서명됨.",
|
||||||
|
"message": "Individual Data: Miner ID, Curio version, chain ({Mainnet} or {Calibration}). Signed.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Aggregate-Anonymous: version, chain, and Miner power (bucketed).",
|
||||||
|
"translation": "집계-익명: 버전, 체인, 및 채굴자 파워 (버킷).",
|
||||||
|
"message": "Aggregate-Anonymous: version, chain, and Miner power (bucketed).",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Hint: I am someone running Curio on whichever chain.",
|
||||||
|
"translation": "힌트: 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.",
|
||||||
|
"message": "Hint: I am someone running Curio on whichever chain.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Press return to update {Toml} with Yugabyte info. A Backup file will be written to that folder before changes are made.",
|
||||||
|
"translation": "{Toml}을 Yugabyte 정보로 업데이트하려면 리턴 키를 누르세요. 변경 사항을 적용하기 전에 해당 폴더에 백업 파일이 작성됩니다.",
|
||||||
|
"message": "Press return to update {Toml} with Yugabyte info. A Backup file will be written to that folder before changes are made.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error creating backup file: {Error}",
|
||||||
|
"translation": "백업 파일 생성 오류: {Error}",
|
||||||
|
"message": "Error creating backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error reading config.toml: {Error}",
|
||||||
|
"translation": "config.toml 읽기 오류: {Error}",
|
||||||
|
"message": "Error reading config.toml: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error writing backup file: {Error}",
|
||||||
|
"translation": "백업 파일 쓰기 오류: {Error}",
|
||||||
|
"message": "Error writing backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error closing backup file: {Error}",
|
||||||
|
"translation": "백업 파일 닫기 오류: {Error}",
|
||||||
|
"message": "Error closing backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Initializing a new miner actor.",
|
||||||
|
"translation": "새 채굴자 액터 초기화 중.",
|
||||||
|
"message": "Initializing a new miner actor.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the info to create a new miner",
|
||||||
|
"translation": "새 채굴자를 생성하기 위한 정보 입력",
|
||||||
|
"message": "Enter the info to create a new miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Owner Address: {String}",
|
||||||
|
"translation": "소유자 주소: {String}",
|
||||||
|
"message": "Owner Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Worker Address: {String}",
|
||||||
|
"translation": "작업자 주소: {String}",
|
||||||
|
"message": "Worker Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Sender Address: {String}",
|
||||||
|
"translation": "송신자 주소: {String}",
|
||||||
|
"message": "Sender Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Sector Size: {Ssize}",
|
||||||
|
"translation": "섹터 크기: {Ssize}",
|
||||||
|
"message": "Sector Size: {Ssize}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Confidence: {Confidence}",
|
||||||
|
"translation": "신뢰도: {Confidence}",
|
||||||
|
"message": "Confidence: {Confidence}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Continue to verify the addresses and create a new miner actor.",
|
||||||
|
"translation": "주소를 확인하고 새 채굴자 액터를 생성하려면 계속 진행하세요.",
|
||||||
|
"message": "Continue to verify the addresses and create a new miner actor.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Miner creation error occurred: {Error}",
|
||||||
|
"translation": "채굴자 생성 오류 발생: {Error}",
|
||||||
|
"message": "Miner creation error occurred: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the owner address",
|
||||||
|
"translation": "소유자 주소 입력",
|
||||||
|
"message": "Enter the owner address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "No address provided",
|
||||||
|
"translation": "주소가 제공되지 않았습니다",
|
||||||
|
"message": "No address provided",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse the address: {Error}",
|
||||||
|
"translation": "주소 구문 분석 실패: {Error}",
|
||||||
|
"message": "Failed to parse the address: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter {Stringworker_senderi_1} address",
|
||||||
|
"translation": "{Stringworker_senderi_1} 주소 입력",
|
||||||
|
"message": "Enter {Stringworker_senderi_1} address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the sector size",
|
||||||
|
"translation": "섹터 크기 입력",
|
||||||
|
"message": "Enter the sector size",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse sector size: {Error}",
|
||||||
|
"translation": "섹터 크기 구문 분석 실패: {Error}",
|
||||||
|
"message": "Failed to parse sector size: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the confidence",
|
||||||
|
"translation": "신뢰도 입력",
|
||||||
|
"message": "Enter the confidence",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse confidence: {Error}",
|
||||||
|
"translation": "신뢰도 구문 분석 실패: {Error}",
|
||||||
|
"message": "Failed to parse confidence: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to create the miner actor: {Error}",
|
||||||
|
"translation": "채굴자 액터 생성 실패: {Error}",
|
||||||
|
"message": "Failed to create the miner actor: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Miner {String} created successfully",
|
||||||
|
"translation": "{String} 채굴자가 성공적으로 생성되었습니다",
|
||||||
|
"message": "Miner {String} created successfully",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Cannot reach the DB: {Error}",
|
||||||
|
"translation": "데이터베이스에 연결할 수 없습니다: {Error}",
|
||||||
|
"message": "Cannot reach the DB: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error connecting to full node API: {Error}",
|
||||||
|
"translation": "풀 노드 API에 연결하는 중 오류 발생: {Error}",
|
||||||
|
"message": "Error connecting to full node API: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Pre-initialization steps complete",
|
||||||
|
"translation": "사전 초기화 단계 완료",
|
||||||
|
"message": "Pre-initialization steps complete",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to random bytes for secret: {Error}",
|
||||||
|
"translation": "비밀을 위한 랜덤 바이트 생성 실패: {Error}",
|
||||||
|
"message": "Failed to random bytes for secret: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster {String}' to finish the configuration",
|
||||||
|
"translation": "마이너 생성은 idempotent하지 않으므로 가이드 설정을 다시 실행하지 마십시오. 구성을 완료하려면 'curio config new-cluster {String}'를 실행해야 합니다.",
|
||||||
|
"message": "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster {String}' to finish the configuration",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to verify the auth token from daemon node: {Error}",
|
||||||
|
"translation": "데몬 노드로부터 인증 토큰을 확인하는 중 오류 발생: {Error}",
|
||||||
|
"message": "Failed to verify the auth token from daemon node: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to encode the config: {Error}",
|
||||||
|
"translation": "구성을 인코딩하는 중 오류 발생: {Error}",
|
||||||
|
"message": "Failed to encode the config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to generate default config: {Error}",
|
||||||
|
"translation": "기본 구성 생성 실패: {Error}",
|
||||||
|
"message": "Failed to generate default config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to inset 'base' config layer in database: {Error}",
|
||||||
|
"translation": "데이터베이스에 'base' 구성 레이어 삽입 실패: {Error}",
|
||||||
|
"message": "Failed to inset 'base' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to inset '{String}' config layer in database: {Error}",
|
||||||
|
"translation": "데이터베이스에 '{String}' 구성 레이어 삽입 실패: {Error}",
|
||||||
|
"message": "Failed to inset '{String}' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "New Curio configuration layer '{String}' created",
|
||||||
|
"translation": "새로운 Curio 구성 레이어 '{String}'가 생성되었습니다",
|
||||||
|
"message": "New Curio configuration layer '{String}' created",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "The Curio team wants to improve the software you use. Tell the team you're using `{Curio}`.",
|
||||||
|
"translation": "Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀에게 `{Curio}`를 사용 중이라고 알려주세요.",
|
||||||
|
"message": "The Curio team wants to improve the software you use. Tell the team you're using `{Curio}`.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Confidence epochs: {Confidence}",
|
||||||
|
"translation": "신뢰 에포크: {Confidence}",
|
||||||
|
"message": "Confidence epochs: {Confidence}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to generate random bytes for secret: {Error}",
|
||||||
|
"translation": "비밀번호를 위한 랜덤 바이트 생성에 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to generate random bytes for secret: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to get API info for FullNode: {Err}",
|
||||||
|
"translation": "FullNode에 대한 API 정보를 가져오는 데 실패했습니다: {Err}",
|
||||||
|
"message": "Failed to get API info for FullNode: {Err}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to insert 'base' config layer in database: {Error}",
|
||||||
|
"translation": "데이터베이스에 'base' 구성 레이어를 삽입하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to insert 'base' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to insert '{String}' config layer in database: {Error}",
|
||||||
|
"translation": "데이터베이스에 '{String}' 구성 레이어를 삽입하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to insert '{String}' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "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 \u003c miner ID \u003e' to finish the configuration.",
|
||||||
|
"translation": "이 프로세스는 부분적으로 항등원적입니다. 새로운 채굴자 액터가 생성되었고 후속 단계가 실패하는 경우 사용자는 구성을 완료하기 위해 'curio config new-cluster \u003c 채굴자 ID \u003e'를 실행해야 합니다.",
|
||||||
|
"message": "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 \u003c miner ID \u003e' to finish the configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Confidence epochs",
|
||||||
|
"translation": "신뢰 에포크",
|
||||||
|
"message": "Confidence epochs",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'",
|
||||||
|
"translation": "신뢰성 향상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio run --layers=post'",
|
||||||
|
"message": "Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "I want to:",
|
||||||
|
"translation": "나는 원한다:",
|
||||||
|
"message": "I want to:",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Configuration 'base' was updated to include this miner's address",
|
||||||
|
"translation": "이 마이너 주소를 포함한 구성 'base'가 업데이트되었습니다.",
|
||||||
|
"message": "Configuration 'base' was updated to include this miner's address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Cannot load base config: {Error}",
|
||||||
|
"translation": "기본 구성을 불러올 수 없습니다: {Error}",
|
||||||
|
"message": "Cannot load base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to load base config: {Error}",
|
||||||
|
"translation": "기본 구성을 로드하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to load base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to regenerate base config: {Error}",
|
||||||
|
"translation": "기본 구성을 재생성하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to regenerate base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to load base config from database: {Error}",
|
||||||
|
"translation": "데이터베이스에서 기본 구성을 로드하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to load base config from database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse base config: {Error}",
|
||||||
|
"translation": "기본 구성을 구문 분석하는 데 실패했습니다: {Error}",
|
||||||
|
"message": "Failed to parse base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,89 +1,4 @@
|
|||||||
{
|
{
|
||||||
"language": "ko",
|
"language": "ko",
|
||||||
"messages": [
|
"messages": []
|
||||||
{
|
|
||||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "could not get API info for FullNode: {Err}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "could not get API info for FullNode: {Err}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error getting token: {Error}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error getting token: {Error}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Enabling Sector Indexing in the database.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Enabling Sector Indexing in the database.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error expanding path: {Error}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error expanding path: {Error}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "To work with the config:",
|
|
||||||
"translation": "",
|
|
||||||
"message": "To work with the config:",
|
|
||||||
"placeholder": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -699,6 +699,354 @@
|
|||||||
"translation": "要使用配置:",
|
"translation": "要使用配置:",
|
||||||
"message": "To work with the config:",
|
"message": "To work with the config:",
|
||||||
"placeholder": null
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "This interactive tool creates a new miner actor and creates the basic configuration layer for it.",
|
||||||
|
"translation": "此交互式工具将创建一个新的矿工角色,并为其创建基本配置层。",
|
||||||
|
"message": "This interactive tool creates a new miner actor and creates the basic configuration layer for it.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "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 {Arg_1}' to finish the configuration.",
|
||||||
|
"translation": "此过程在某种程度上是幂等的。一旦创建了新的矿工角色,并且后续步骤失败,用户需要运行'curio config new-cluster {Arg_1}'来完成配置。",
|
||||||
|
"message": "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 {Arg_1}' to finish the configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Choose if you with to create a new miner or migrate from existing Lotus-Miner",
|
||||||
|
"translation": "选择您是否要创建新矿工或从现有的 Lotus-Miner 迁移",
|
||||||
|
"message": "Choose if you with to create a new miner or migrate from existing Lotus-Miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Migrate from existing Lotus-Miner",
|
||||||
|
"translation": "从现有的 Lotus-Miner 迁移",
|
||||||
|
"message": "Migrate from existing Lotus-Miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Create a new miner",
|
||||||
|
"translation": "创建一个新的矿工",
|
||||||
|
"message": "Create a new miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "New Miner initialization complete.",
|
||||||
|
"translation": "新矿工初始化完成。",
|
||||||
|
"message": "New Miner initialization complete.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Migrating lotus-miner config.toml to Curio in-database configuration.",
|
||||||
|
"translation": "将 lotus-miner config.toml 迁移到 Curio 的数据库配置中。",
|
||||||
|
"message": "Migrating lotus-miner config.toml to Curio in-database configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error getting API: {Error}",
|
||||||
|
"translation": "获取 API 时出错:{Error}",
|
||||||
|
"message": "Error getting API: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "The Curio team wants to improve the software you use. Tell the team you're using `{Curio}`.",
|
||||||
|
"translation": "Curio 团队希望改进您使用的软件。告诉团队您正在使用 `{Curio}`。",
|
||||||
|
"message": "The Curio team wants to improve the software you use. Tell the team you're using `{Curio}`.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Individual Data: Miner ID, Curio version, chain ({Mainnet} or {Calibration}). Signed.",
|
||||||
|
"translation": "个人数据:矿工 ID,Curio 版本,链({Mainnet} 或 {Calibration})。签名。",
|
||||||
|
"message": "Individual Data: Miner ID, Curio version, chain ({Mainnet} or {Calibration}). Signed.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Aggregate-Anonymous: version, chain, and Miner power (bucketed).",
|
||||||
|
"translation": "聚合-匿名:版本,链和矿工算力(分桶)。",
|
||||||
|
"message": "Aggregate-Anonymous: version, chain, and Miner power (bucketed).",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Hint: I am someone running Curio on whichever chain.",
|
||||||
|
"translation": "提示:我是在任何链上运行 Curio 的人。",
|
||||||
|
"message": "Hint: I am someone running Curio on whichever chain.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Press return to update {Toml} with Yugabyte info. A Backup file will be written to that folder before changes are made.",
|
||||||
|
"translation": "按回车键更新 {Toml} 以包含 Yugabyte 信息。在进行更改之前,将在该文件夹中写入备份文件。",
|
||||||
|
"message": "Press return to update {Toml} with Yugabyte info. A Backup file will be written to that folder before changes are made.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error creating backup file: {Error}",
|
||||||
|
"translation": "创建备份文件时出错:{Error}",
|
||||||
|
"message": "Error creating backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error reading config.toml: {Error}",
|
||||||
|
"translation": "读取 config.toml 时出错:{Error}",
|
||||||
|
"message": "Error reading config.toml: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error writing backup file: {Error}",
|
||||||
|
"translation": "写入备份文件时出错:{Error}",
|
||||||
|
"message": "Error writing backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error closing backup file: {Error}",
|
||||||
|
"translation": "关闭备份文件时出错:{Error}",
|
||||||
|
"message": "Error closing backup file: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Initializing a new miner actor.",
|
||||||
|
"translation": "初始化新的矿工角色。",
|
||||||
|
"message": "Initializing a new miner actor.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the info to create a new miner",
|
||||||
|
"translation": "输入创建新矿工所需的信息",
|
||||||
|
"message": "Enter the info to create a new miner",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Owner Address: {String}",
|
||||||
|
"translation": "所有者地址:{String}",
|
||||||
|
"message": "Owner Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Worker Address: {String}",
|
||||||
|
"translation": "工作地址:{String}",
|
||||||
|
"message": "Worker Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Sender Address: {String}",
|
||||||
|
"translation": "发送者地址:{String}",
|
||||||
|
"message": "Sender Address: {String}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Sector Size: {Ssize}",
|
||||||
|
"translation": "扇区大小: {Ssize}",
|
||||||
|
"message": "Sector Size: {Ssize}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Confidence epochs: {Confidence}",
|
||||||
|
"translation": "置信度时期: {Confidence}",
|
||||||
|
"message": "Confidence epochs: {Confidence}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Continue to verify the addresses and create a new miner actor.",
|
||||||
|
"translation": "继续验证地址并创建新的矿工角色。",
|
||||||
|
"message": "Continue to verify the addresses and create a new miner actor.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Miner creation error occurred: {Error}",
|
||||||
|
"translation": "矿工创建错误发生: {Error}",
|
||||||
|
"message": "Miner creation error occurred: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the owner address",
|
||||||
|
"translation": "输入所有者地址",
|
||||||
|
"message": "Enter the owner address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "No address provided",
|
||||||
|
"translation": "未提供地址",
|
||||||
|
"message": "No address provided",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse the address: {Error}",
|
||||||
|
"translation": "解析地址失败: {Error}",
|
||||||
|
"message": "Failed to parse the address: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter {Stringworker_senderi_1} address",
|
||||||
|
"translation": "输入 {Stringworker_senderi_1} 地址",
|
||||||
|
"message": "Enter {Stringworker_senderi_1} address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the sector size",
|
||||||
|
"translation": "输入扇区大小",
|
||||||
|
"message": "Enter the sector size",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse sector size: {Error}",
|
||||||
|
"translation": "解析扇区大小失败: {Error}",
|
||||||
|
"message": "Failed to parse sector size: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Enter the confidence",
|
||||||
|
"translation": "输入置信度",
|
||||||
|
"message": "Enter the confidence",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse confidence: {Error}",
|
||||||
|
"translation": "解析置信度失败: {Error}",
|
||||||
|
"message": "Failed to parse confidence: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to create the miner actor: {Error}",
|
||||||
|
"translation": "创建矿工角色失败: {Error}",
|
||||||
|
"message": "Failed to create the miner actor: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Miner {String} created successfully",
|
||||||
|
"translation": "矿工 {String} 创建成功",
|
||||||
|
"message": "Miner {String} created successfully",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Cannot reach the DB: {Error}",
|
||||||
|
"translation": "无法访问数据库: {Error}",
|
||||||
|
"message": "Cannot reach the DB: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Error connecting to full node API: {Error}",
|
||||||
|
"translation": "连接到完整节点 API 时发生错误: {Error}",
|
||||||
|
"message": "Error connecting to full node API: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Pre-initialization steps complete",
|
||||||
|
"translation": "预初始化步骤完成",
|
||||||
|
"message": "Pre-initialization steps complete",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to generate random bytes for secret: {Error}",
|
||||||
|
"translation": "生成密码的随机字节失败: {Error}",
|
||||||
|
"message": "Failed to generate random bytes for secret: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster {String}' to finish the configuration",
|
||||||
|
"translation": "请不要再次运行引导设置,因为矿工创建不是幂等的。 您需要运行 'curio config new-cluster {String}' 来完成配置。",
|
||||||
|
"message": "Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster {String}' to finish the configuration",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to get API info for FullNode: {Err}",
|
||||||
|
"translation": "无法获取 FullNode 的 API 信息: {Err}",
|
||||||
|
"message": "Failed to get API info for FullNode: {Err}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to verify the auth token from daemon node: {Error}",
|
||||||
|
"translation": "无法验证来自守护进程节点的授权令牌: {Error}",
|
||||||
|
"message": "Failed to verify the auth token from daemon node: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to encode the config: {Error}",
|
||||||
|
"translation": "无法编码配置: {Error}",
|
||||||
|
"message": "Failed to encode the config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to generate default config: {Error}",
|
||||||
|
"translation": "无法生成默认配置: {Error}",
|
||||||
|
"message": "Failed to generate default config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to insert 'base' config layer in database: {Error}",
|
||||||
|
"translation": "无法将 'base' 配置层插入数据库: {Error}",
|
||||||
|
"message": "Failed to insert 'base' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to insert '{String}' config layer in database: {Error}",
|
||||||
|
"translation": "无法将 '{String}' 配置层插入数据库: {Error}",
|
||||||
|
"message": "Failed to insert '{String}' config layer in database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "New Curio configuration layer '{String}' created",
|
||||||
|
"translation": "新的 Curio 配置层 '{String}' 已创建",
|
||||||
|
"message": "New Curio configuration layer '{String}' created",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "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 \u003c miner ID \u003e' to finish the configuration.",
|
||||||
|
"translation": "该过程部分幂等。一旦创建了新的矿工角色,并且随后的步骤失败,用户需要运行 'curio config new-cluster \u003c 矿工 ID \u003e' 来完成配置。",
|
||||||
|
"message": "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 \u003c miner ID \u003e' to finish the configuration.",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Confidence epochs",
|
||||||
|
"translation": "置信度时期",
|
||||||
|
"message": "Confidence epochs",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'",
|
||||||
|
"translation": "通过冗余增加可靠性:使用至少后层启动多台机器:'curio run --layers=post'",
|
||||||
|
"message": "Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "I want to:",
|
||||||
|
"translation": "我想要:",
|
||||||
|
"message": "I want to:",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Configuration 'base' was updated to include this miner's address",
|
||||||
|
"translation": "配置 'base' 已更新以包含此矿工的地址",
|
||||||
|
"message": "Configuration 'base' was updated to include this miner's address",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Cannot load base config: {Error}",
|
||||||
|
"translation": "无法加载基本配置: {Error}",
|
||||||
|
"message": "Cannot load base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to load base config: {Error}",
|
||||||
|
"translation": "加载基本配置失败: {Error}",
|
||||||
|
"message": "Failed to load base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to regenerate base config: {Error}",
|
||||||
|
"translation": "重新生成基本配置失败: {Error}",
|
||||||
|
"message": "Failed to regenerate base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to load base config from database: {Error}",
|
||||||
|
"translation": "从数据库加载基本配置失败:{Error}",
|
||||||
|
"message": "Failed to load base config from database: {Error}",
|
||||||
|
"placeholder": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "Failed to parse base config: {Error}",
|
||||||
|
"translation": "解析基本配置失败:{Error}",
|
||||||
|
"message": "Failed to parse base config: {Error}",
|
||||||
|
"placeholder": null
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -1,89 +1,4 @@
|
|||||||
{
|
{
|
||||||
"language": "zh",
|
"language": "zh",
|
||||||
"messages": [
|
"messages": []
|
||||||
{
|
|
||||||
"id": "Try the web interface with {__layersgui} for further guided improvements.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Try the web interface with {__layersgui} for further guided improvements.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error connecting to lotus node: {Error} {Error_1}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error connecting to lotus node: {Error} {Error_1}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "could not get API info for FullNode: {Err}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "could not get API info for FullNode: {Err}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error getting token: {Error}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error getting token: {Error}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Filecoin {Slack} channels: {Fil_curio_help} and {Fil_curio_dev}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Start multiple Curio instances with the '{Post}' layer to redundancy.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "One database can serve multiple miner IDs: Run a migration for each lotus-miner.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Please start (or restart) {Lotus_miner} now that database credentials are in {Toml}.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error interpreting miner ID: {Error}: ID: {String}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error interpreting miner ID: {Error}: ID: {String}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Enabling Sector Indexing in the database.",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Enabling Sector Indexing in the database.",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Error expanding path: {Error}",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Error expanding path: {Error}",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Could not create repo from directory: {Error}. Aborting migration",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Could not create repo from directory: {Error}. Aborting migration",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
|
||||||
"translation": "",
|
|
||||||
"message": "Could not lock miner repo. Your miner must be stopped: {Error}\n Aborting migration",
|
|
||||||
"placeholder": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "To work with the config:",
|
|
||||||
"translation": "",
|
|
||||||
"message": "To work with the config:",
|
|
||||||
"placeholder": null
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#OP: Only run if some file in ../guidedsetup* is newer than catalog.go
|
#OP: Only run if some file in ../guidedsetup* is newer than catalog.go
|
||||||
# Change this condition if using translations more widely.
|
# Change this condition if using translations more widely.
|
||||||
if [ "$(find ../../guidedsetup/* -newermt "$(date -d '1 minute ago')" -newer catalog.go)" ] || [ "$(find locales/* -newermt "$(date -d '1 minute ago')" -newer catalog.go)" ]; then
|
if [ "$(find ../../guidedsetup/* -newer catalog.go)" ] || [ "$(find locales/* -newer catalog.go)" ]; then
|
||||||
gotext -srclang=en update -out=catalog.go -lang=en,zh,ko github.com/filecoin-project/lotus/cmd/curio/guidedsetup
|
gotext -srclang=en update -out=catalog.go -lang=en,zh,ko github.com/filecoin-project/lotus/cmd/curio/guidedsetup
|
||||||
go run knowns/main.go locales/zh locales/ko
|
go run knowns/main.go locales/zh locales/ko
|
||||||
fi
|
fi
|
||||||
|
@ -111,7 +111,7 @@ func main() {
|
|||||||
Name: "db-host",
|
Name: "db-host",
|
||||||
EnvVars: []string{"CURIO_DB_HOST", "CURIO_HARMONYDB_HOSTS"},
|
EnvVars: []string{"CURIO_DB_HOST", "CURIO_HARMONYDB_HOSTS"},
|
||||||
Usage: "Command separated list of hostnames for yugabyte cluster",
|
Usage: "Command separated list of hostnames for yugabyte cluster",
|
||||||
Value: "yugabyte",
|
Value: "127.0.0.1",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "db-name",
|
Name: "db-name",
|
||||||
@ -131,7 +131,6 @@ func main() {
|
|||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "db-port",
|
Name: "db-port",
|
||||||
EnvVars: []string{"CURIO_DB_PORT", "CURIO_HARMONYDB_PORT"},
|
EnvVars: []string{"CURIO_DB_PORT", "CURIO_HARMONYDB_PORT"},
|
||||||
Hidden: true,
|
|
||||||
Value: "5433",
|
Value: "5433",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
|
@ -32,6 +32,7 @@ var actorCmd = &cli.Command{
|
|||||||
spcli.ActorCompactAllocatedCmd(SPTActorGetter),
|
spcli.ActorCompactAllocatedCmd(SPTActorGetter),
|
||||||
spcli.ActorProposeChangeBeneficiaryCmd(SPTActorGetter),
|
spcli.ActorProposeChangeBeneficiaryCmd(SPTActorGetter),
|
||||||
spcli.ActorConfirmChangeBeneficiaryCmd(SPTActorGetter),
|
spcli.ActorConfirmChangeBeneficiaryCmd(SPTActorGetter),
|
||||||
|
spcli.ActorNewMinerCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,6 @@ var sectorsListCmd = &cli.Command{
|
|||||||
|
|
||||||
for _, st := range sset {
|
for _, st := range sset {
|
||||||
s := st.SectorNumber
|
s := st.SectorNumber
|
||||||
|
|
||||||
_, inSSet := commitedIDs[s]
|
_, inSSet := commitedIDs[s]
|
||||||
_, inASet := activeIDs[s]
|
_, inASet := activeIDs[s]
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ COMMANDS:
|
|||||||
config Manage node config by layers. The layer 'base' will always be applied at Curio start-up.
|
config Manage node config by layers. The layer 'base' will always be applied at Curio start-up.
|
||||||
test Utility functions for testing
|
test Utility functions for testing
|
||||||
web Start Curio web interface
|
web Start Curio web interface
|
||||||
guided-setup Run the guided setup for migrating from lotus-miner to Curio
|
guided-setup Run the guided setup for migrating from lotus-miner to Curio or Creating a new Curio miner
|
||||||
seal Manage the sealing pipeline
|
seal Manage the sealing pipeline
|
||||||
market
|
market
|
||||||
auth Manage RPC permissions
|
auth Manage RPC permissions
|
||||||
@ -28,10 +28,11 @@ COMMANDS:
|
|||||||
|
|
||||||
GLOBAL OPTIONS:
|
GLOBAL OPTIONS:
|
||||||
--color use color in display output (default: depends on output being a TTY)
|
--color use color in display output (default: depends on output being a TTY)
|
||||||
--db-host value Command separated list of hostnames for yugabyte cluster (default: "yugabyte") [$CURIO_DB_HOST, $CURIO_HARMONYDB_HOSTS]
|
--db-host value Command separated list of hostnames for yugabyte cluster (default: "127.0.0.1") [$CURIO_DB_HOST, $CURIO_HARMONYDB_HOSTS]
|
||||||
--db-name value (default: "yugabyte") [$CURIO_DB_NAME, $CURIO_HARMONYDB_NAME]
|
--db-name value (default: "yugabyte") [$CURIO_DB_NAME, $CURIO_HARMONYDB_NAME]
|
||||||
--db-user value (default: "yugabyte") [$CURIO_DB_USER, $CURIO_HARMONYDB_USERNAME]
|
--db-user value (default: "yugabyte") [$CURIO_DB_USER, $CURIO_HARMONYDB_USERNAME]
|
||||||
--db-password value (default: "yugabyte") [$CURIO_DB_PASSWORD, $CURIO_HARMONYDB_PASSWORD]
|
--db-password value (default: "yugabyte") [$CURIO_DB_PASSWORD, $CURIO_HARMONYDB_PASSWORD]
|
||||||
|
--db-port value (default: "5433") [$CURIO_DB_PORT, $CURIO_HARMONYDB_PORT]
|
||||||
--repo-path value (default: "~/.curio") [$CURIO_REPO_PATH]
|
--repo-path value (default: "~/.curio") [$CURIO_REPO_PATH]
|
||||||
--vv enables very verbose mode, useful for debugging the CLI (default: false)
|
--vv enables very verbose mode, useful for debugging the CLI (default: false)
|
||||||
--help, -h show help
|
--help, -h show help
|
||||||
@ -305,7 +306,7 @@ OPTIONS:
|
|||||||
## curio guided-setup
|
## curio guided-setup
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
curio guided-setup - Run the guided setup for migrating from lotus-miner to Curio
|
curio guided-setup - Run the guided setup for migrating from lotus-miner to Curio or Creating a new Curio miner
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
curio guided-setup [command options] [arguments...]
|
curio guided-setup [command options] [arguments...]
|
||||||
|
@ -43,6 +43,7 @@ COMMANDS:
|
|||||||
compact-allocated compact allocated sectors bitfield
|
compact-allocated compact allocated sectors bitfield
|
||||||
propose-change-beneficiary Propose a beneficiary address change
|
propose-change-beneficiary Propose a beneficiary address change
|
||||||
confirm-change-beneficiary Confirm a beneficiary address change
|
confirm-change-beneficiary Confirm a beneficiary address change
|
||||||
|
new-miner Initializes a new miner actor
|
||||||
help, h Shows a list of commands or help for one command
|
help, h Shows a list of commands or help for one command
|
||||||
|
|
||||||
OPTIONS:
|
OPTIONS:
|
||||||
@ -231,6 +232,22 @@ OPTIONS:
|
|||||||
--help, -h show help
|
--help, -h show help
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### sptool actor new-miner
|
||||||
|
```
|
||||||
|
NAME:
|
||||||
|
sptool actor new-miner - Initializes a new miner actor
|
||||||
|
|
||||||
|
USAGE:
|
||||||
|
sptool actor new-miner [command options] [arguments...]
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
--worker value, -w value worker key to use for new miner initialisation
|
||||||
|
--owner value, -o value owner key to use for new miner initialisation
|
||||||
|
--from value, -f value address to send actor(miner) creation message from
|
||||||
|
--sector-size value specify sector size to use for new miner initialisation
|
||||||
|
--help, -h show help
|
||||||
|
```
|
||||||
|
|
||||||
## sptool info
|
## sptool info
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
|
2
go.mod
2
go.mod
@ -69,6 +69,7 @@ require (
|
|||||||
github.com/georgysavva/scany/v2 v2.0.0
|
github.com/georgysavva/scany/v2 v2.0.0
|
||||||
github.com/go-openapi/spec v0.19.11
|
github.com/go-openapi/spec v0.19.11
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
|
github.com/google/go-cmp v0.6.0
|
||||||
github.com/google/uuid v1.5.0
|
github.com/google/uuid v1.5.0
|
||||||
github.com/gorilla/mux v1.8.1
|
github.com/gorilla/mux v1.8.1
|
||||||
github.com/gorilla/websocket v1.5.1
|
github.com/gorilla/websocket v1.5.1
|
||||||
@ -222,7 +223,6 @@ require (
|
|||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||||
github.com/golang/protobuf v1.5.3 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
|
||||||
github.com/google/gopacket v1.1.19 // indirect
|
github.com/google/gopacket v1.1.19 // indirect
|
||||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 // indirect
|
||||||
github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c // indirect
|
github.com/hannahhoward/cbor-gen-for v0.0.0-20230214144701-5d17c9d5243c // indirect
|
||||||
|
67
itests/curio_test.go
Normal file
67
itests/curio_test.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package itests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/docker/go-units"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/go-state-types/abi"
|
||||||
|
|
||||||
|
"github.com/filecoin-project/lotus/cli/spcli"
|
||||||
|
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||||
|
"github.com/filecoin-project/lotus/itests/kit"
|
||||||
|
"github.com/filecoin-project/lotus/node/config"
|
||||||
|
"github.com/filecoin-project/lotus/node/impl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestCurioNewActor(t *testing.T) {
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
full, miner, esemble := kit.EnsembleMinimal(t,
|
||||||
|
kit.LatestActorsAt(-1),
|
||||||
|
kit.MockProofs(),
|
||||||
|
kit.WithSectorIndexDB(),
|
||||||
|
)
|
||||||
|
|
||||||
|
esemble.Start()
|
||||||
|
blockTime := 100 * time.Millisecond
|
||||||
|
esemble.BeginMining(blockTime)
|
||||||
|
|
||||||
|
db := miner.BaseAPI.(*impl.StorageMinerAPI).HarmonyDB
|
||||||
|
|
||||||
|
var titles []string
|
||||||
|
err := db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotEmpty(t, titles)
|
||||||
|
require.NotContains(t, titles, "base")
|
||||||
|
|
||||||
|
addr := miner.OwnerKey.Address
|
||||||
|
sectorSizeInt, err := units.RAMInBytes("8MiB")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
maddr, err := spcli.CreateStorageMiner(ctx, full, addr, addr, addr, abi.SectorSize(sectorSizeInt), 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = deps.CreateMinerConfig(ctx, full, db, []string{maddr.String()}, "FULL NODE API STRING")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = db.Select(ctx, &titles, `SELECT title FROM harmony_config WHERE LENGTH(config) > 0`)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, titles, "base")
|
||||||
|
baseCfg := config.DefaultCurioConfig()
|
||||||
|
var baseText string
|
||||||
|
|
||||||
|
err = db.QueryRow(ctx, "SELECT config FROM harmony_config WHERE title='base'").Scan(&baseText)
|
||||||
|
require.NoError(t, err)
|
||||||
|
_, err = deps.LoadConfigWithUpgrades(baseText, baseCfg)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.NotNil(t, baseCfg.Addresses)
|
||||||
|
require.GreaterOrEqual(t, len(baseCfg.Addresses), 1)
|
||||||
|
|
||||||
|
require.Contains(t, baseCfg.Addresses[0].MinerAddresses, maddr.String())
|
||||||
|
}
|
@ -4,13 +4,17 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
"github.com/kelseyhightower/envconfig"
|
"github.com/kelseyhightower/envconfig"
|
||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
@ -395,8 +399,22 @@ func ConfigUpdate(cfgCur, cfgDef interface{}, opts ...UpdateCfgOpt) ([]byte, err
|
|||||||
return nil, xerrors.Errorf("parsing updated config: %w", err)
|
return nil, xerrors.Errorf("parsing updated config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(cfgCur, cfgUpdated) {
|
opts := []cmp.Option{
|
||||||
return nil, xerrors.Errorf("updated config didn't match current config:")
|
// This equality function compares big.Int
|
||||||
|
cmpopts.IgnoreUnexported(big.Int{}),
|
||||||
|
cmp.Comparer(func(x, y []string) bool {
|
||||||
|
tx, ty := reflect.TypeOf(x), reflect.TypeOf(y)
|
||||||
|
if tx.Kind() == reflect.Slice && ty.Kind() == reflect.Slice && tx.Elem().Kind() == reflect.String && ty.Elem().Kind() == reflect.String {
|
||||||
|
sort.Strings(x)
|
||||||
|
sort.Strings(y)
|
||||||
|
return strings.Join(x, "\n") == strings.Join(y, "\n")
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cmp.Equal(cfgUpdated, cfgCur, opts...) {
|
||||||
|
return nil, xerrors.Errorf("updated config didn't match current config")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user