diff --git a/.gitignore b/.gitignore index d620e557b..a40ab0bd5 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ build/paramfetch.sh *.snap devgen.car localnet.json +/*.ndjson *-fuzz.zip /chain/types/work_msg/ diff --git a/chain/types/fil.go b/chain/types/fil.go index d20b3c021..960a42f28 100644 --- a/chain/types/fil.go +++ b/chain/types/fil.go @@ -6,6 +6,8 @@ import ( "math/big" "strings" + "github.com/invopop/jsonschema" + "github.com/filecoin-project/lotus/build" ) @@ -138,5 +140,12 @@ func MustParseFIL(s string) FIL { return n } +func (f FIL) JSONSchema() *jsonschema.Schema { + return &jsonschema.Schema{ + Type: "string", + Pattern: `^((\d+(\.\d+)?|0x[0-9a-fA-F]+))( ([aA]([tT][tT][oO])?)?[fF][iI][lL])?$`, + } +} + var _ encoding.TextMarshaler = (*FIL)(nil) var _ encoding.TextUnmarshaler = (*FIL)(nil) diff --git a/cli/mpool.go b/cli/mpool.go index c83fb4b61..f38a900fb 100644 --- a/cli/mpool.go +++ b/cli/mpool.go @@ -491,7 +491,7 @@ var MpoolReplaceCmd = &cli.Command{ msg.GasFeeCap = big.Max(retm.GasFeeCap, msg.GasPremium) mff := func() (abi.TokenAmount, error) { - return abi.TokenAmount(config.DefaultDefaultMaxFee), nil + return abi.TokenAmount(config.DefaultDefaultMaxFee()), nil } messagepool.CapGasFee(mff, &msg, mss) diff --git a/cmd/curio/cli.go b/cmd/curio/cli.go index 3eec4b617..6c9cb7ec6 100644 --- a/cmd/curio/cli.go +++ b/cmd/curio/cli.go @@ -40,6 +40,9 @@ var cliCmd = &cli.Command{ // set already return nil } + if os.Getenv("LOTUS_DOCS_GENERATION") == "1" { + return nil + } db, err := deps.MakeDB(cctx) if err != nil { diff --git a/cmd/curio/config_test.go b/cmd/curio/config_test.go index e476f23d0..f5037abf4 100644 --- a/cmd/curio/config_test.go +++ b/cmd/curio/config_test.go @@ -1,8 +1,11 @@ package main import ( + "reflect" "testing" + "time" + "github.com/invopop/jsonschema" "github.com/samber/lo" "github.com/stretchr/testify/require" @@ -414,3 +417,22 @@ func TestConfig(t *testing.T) { require.NoError(t, err) } + +func TestCustomConfigDurationJson(t *testing.T) { + ref := new(jsonschema.Reflector) + ref.Mapper = func(i reflect.Type) *jsonschema.Schema { + if i == reflect.TypeOf(config.Duration(time.Second)) { + return &jsonschema.Schema{ + Type: "string", + Format: "duration", + } + } + return nil + } + + sch := ref.Reflect(config.CurioConfig{}) + definitions := sch.Definitions["CurioProvingConfig"] + prop, ok := definitions.Properties.Get("SingleCheckTimeout") + require.True(t, ok) + require.Equal(t, prop.Type, "string") +} diff --git a/cmd/curio/deps/deps.go b/cmd/curio/deps/deps.go index 79881ebb8..2050a1caf 100644 --- a/cmd/curio/deps/deps.go +++ b/cmd/curio/deps/deps.go @@ -165,6 +165,7 @@ func GetDeps(ctx context.Context, cctx *cli.Context) (*Deps, error) { } type Deps struct { + Layers []string Cfg *config.CurioConfig // values DB *harmonydb.DB // has itest capability Full api.FullNode @@ -212,6 +213,9 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context, return err } } + if deps.Layers == nil { + deps.Layers = append([]string{"base"}, cctx.StringSlice("layers")...) // Always stack on top of "base" layer + } if deps.Cfg == nil { // The config feeds into task runners & their helpers diff --git a/cmd/curio/guidedsetup/guidedsetup.go b/cmd/curio/guidedsetup/guidedsetup.go index 1af49d868..1bdb8e784 100644 --- a/cmd/curio/guidedsetup/guidedsetup.go +++ b/cmd/curio/guidedsetup/guidedsetup.go @@ -244,7 +244,7 @@ type MigrationData struct { func complete(d *MigrationData) { stepCompleted(d, d.T("Lotus-Miner to Curio Migration.")) - 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.", code.Render("curio run --layers=gui")) d.say(plain, "You can now migrate your market node (%s), if applicable.", "Boost") } @@ -279,7 +279,7 @@ func configToDB(d *MigrationData) { chainApiInfo := fmt.Sprintf("%s:%s", string(token), ainfo.Addr) - d.MinerID, err = SaveConfigToLayer(d.MinerConfigPath, "", false, chainApiInfo) + d.MinerID, err = SaveConfigToLayer(d.MinerConfigPath, chainApiInfo) if err != nil { d.say(notice, "Error saving config to layer: %s. Aborting Migration", err.Error()) os.Exit(1) @@ -423,7 +423,7 @@ func verifySectors(d *MigrationData) { time.Sleep(5 * time.Second) } d.say(plain, "The sectors are in the database. The database is ready for %s.", "Curio") - d.say(notice, "Now shut down lotus-miner and move the systems to %s.", "Curio") + d.say(notice, "Now shut down lotus-miner and lotus-worker and use run %s instead.", code.Render("curio run")) _, err = (&promptui.Prompt{Label: d.T("Press return to continue")}).Run() if err != nil { diff --git a/cmd/curio/guidedsetup/shared.go b/cmd/curio/guidedsetup/shared.go index e4b840bf2..6e7d81c03 100644 --- a/cmd/curio/guidedsetup/shared.go +++ b/cmd/curio/guidedsetup/shared.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/base64" - "errors" "fmt" "os" "path" @@ -30,7 +29,7 @@ const ( const FlagMinerRepoDeprecation = "storagerepo" -func SaveConfigToLayer(minerRepoPath, layerName string, overwrite bool, chainApiInfo string) (minerAddress address.Address, err error) { +func SaveConfigToLayer(minerRepoPath, chainApiInfo string) (minerAddress address.Address, err error) { _, say := SetupLanguage() ctx := context.Background() @@ -165,6 +164,12 @@ func SaveConfigToLayer(minerRepoPath, layerName string, overwrite bool, chainApi baseCfg.Addresses = lo.Filter(baseCfg.Addresses, func(a config.CurioAddresses, _ int) bool { return len(a.MinerAddresses) > 0 }) + if baseCfg.Apis.ChainApiInfo == nil { + baseCfg.Apis.ChainApiInfo = append(baseCfg.Apis.ChainApiInfo, chainApiInfo) + } + if baseCfg.Apis.StorageRPCSecret == "" { + baseCfg.Apis.StorageRPCSecret = curioCfg.Apis.StorageRPCSecret + } cb, err := config.ConfigUpdate(baseCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv()) if err != nil { @@ -174,44 +179,33 @@ func SaveConfigToLayer(minerRepoPath, layerName string, overwrite bool, chainApi if err != nil { return minerAddress, xerrors.Errorf("cannot update base config: %w", err) } - say(plain, "Configuration 'base' was updated to include this miner's address and its wallet setup.") + say(plain, "Configuration 'base' was updated to include this miner's address (%s) and its wallet setup.", minerAddress) } say(plain, "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.", "base", "mig-"+curioCfg.Addresses[0].MinerAddresses[0]) skipWritingToBase: - } else if layerName == "" { - cfg, err := deps.GetDefaultConfig(true) - if err != nil { - return minerAddress, xerrors.Errorf("Cannot get default config: %w", err) - } + } else { _, err = db.Exec(ctx, `INSERT INTO harmony_config (title, config) VALUES ('base', $1) - ON CONFLICT(title) DO UPDATE SET config=EXCLUDED.config`, cfg) + ON CONFLICT(title) DO UPDATE SET config=EXCLUDED.config`, configTOML) if err != nil { return minerAddress, xerrors.Errorf("Cannot insert base config: %w", err) } - say(notice, "Configuration 'base' was created to include this miner's address and its wallet setup.") + say(notice, "Configuration 'base' was created to resemble this lotus-miner's config.toml .") } - if layerName == "" { // only make mig if base exists and we are different. // compare to base. - layerName = fmt.Sprintf("mig-%s", curioCfg.Addresses[0].MinerAddresses[0]) - overwrite = true - } else { - if lo.Contains(titles, layerName) && !overwrite { - return minerAddress, errors.New("the overwrite flag is needed to replace existing layer: " + layerName) - } - } - if overwrite { - _, err := db.Exec(ctx, "DELETE FROM harmony_config WHERE title=$1", layerName) + { // make a layer representing the migration + layerName := fmt.Sprintf("mig-%s", curioCfg.Addresses[0].MinerAddresses[0]) + _, err = db.Exec(ctx, "DELETE FROM harmony_config WHERE title=$1", layerName) if err != nil { return minerAddress, xerrors.Errorf("Cannot delete existing layer: %w", err) } - } - _, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ($1, $2)", layerName, configTOML.String()) - if err != nil { - return minerAddress, xerrors.Errorf("Cannot insert layer after layer created message: %w", err) + _, err = db.Exec(ctx, "INSERT INTO harmony_config (title, config) VALUES ($1, $2)", layerName, configTOML.String()) + if err != nil { + return minerAddress, xerrors.Errorf("Cannot insert layer after layer created message: %w", err) + } + say(plain, "Layer %s created. ", layerName) } - say(plain, "Layer %s created. ", layerName) dbSettings := getDBSettings(*smCfg) say(plain, "To work with the config: ") diff --git a/cmd/curio/internal/translations/catalog.go b/cmd/curio/internal/translations/catalog.go index 44c97dfac..6e0ad3087 100644 --- a/cmd/curio/internal/translations/catalog.go +++ b/cmd/curio/internal/translations/catalog.go @@ -48,9 +48,9 @@ var messageKeyToIndex = map[string]int{ "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, "Confidence epochs": 86, "Confidence epochs: %d": 76, - "Configuration 'base' was created to include this miner's address and its wallet setup.": 117, - "Configuration 'base' was updated to include this miner's address": 99, - "Configuration 'base' was updated to include this miner's address and its wallet setup.": 115, + "Configuration 'base' was created to resemble this lotus-miner's config.toml .": 117, + "Configuration 'base' was updated to include this miner's address": 99, + "Configuration 'base' was updated to include this miner's address (%s) and its wallet setup.": 115, "Connected to Yugabyte": 59, "Connected to Yugabyte. Schema is current.": 47, "Continue to connect and update schema.": 109, @@ -125,7 +125,7 @@ var messageKeyToIndex = map[string]int{ "No path provided, abandoning migration ": 64, "No value provided": 84, "Nothing.": 24, - "Now shut down lotus-miner and move the systems to %s.": 43, + "Now shut down lotus-miner and lotus-worker and use run %s instead.": 43, "One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 37, "Other": 62, "Owner Address: %s": 72, @@ -177,31 +177,31 @@ var enIndex = []uint32{ // 122 elements 0x0000063c, 0x00000650, 0x000006bb, 0x000006fb, 0x00000724, 0x0000079b, 0x000007ec, 0x00000838, 0x0000086a, 0x00000898, 0x000008b7, 0x000008f9, - 0x00000932, 0x0000094b, 0x0000095f, 0x0000098f, - 0x000009b9, 0x000009e3, 0x00000a05, 0x00000a7c, - 0x00000a98, 0x00000ac5, 0x00000ae7, 0x00000b08, - 0x00000b29, 0x00000b4a, 0x00000b6b, 0x00000b85, - 0x00000b9b, 0x00000be8, 0x00000c22, 0x00000c28, + 0x0000093f, 0x00000958, 0x0000096c, 0x0000099c, + 0x000009c6, 0x000009f0, 0x00000a12, 0x00000a89, + 0x00000aa5, 0x00000ad2, 0x00000af4, 0x00000b15, + 0x00000b36, 0x00000b57, 0x00000b78, 0x00000b92, + 0x00000ba8, 0x00000bf5, 0x00000c2f, 0x00000c35, // Entry 40 - 5F - 0x00000c64, 0x00000c90, 0x00000cd9, 0x00000d19, - 0x00000d6a, 0x00000d7c, 0x00000d96, 0x00000db6, - 0x00000ddb, 0x00000df0, 0x00000e06, 0x00000e1c, - 0x00000e2f, 0x00000e48, 0x00000e87, 0x00000eb1, - 0x00000ec9, 0x00000edd, 0x00000f00, 0x00000f14, - 0x00000f2a, 0x00000f3c, 0x00000f5f, 0x00000f71, - 0x00000f93, 0x00000fbb, 0x00000fdc, 0x00000ff7, - 0x00001020, 0x00001042, 0x00001074, 0x0000110b, + 0x00000c71, 0x00000c9d, 0x00000ce6, 0x00000d26, + 0x00000d77, 0x00000d89, 0x00000da3, 0x00000dc3, + 0x00000de8, 0x00000dfd, 0x00000e13, 0x00000e29, + 0x00000e3c, 0x00000e55, 0x00000e94, 0x00000ebe, + 0x00000ed6, 0x00000eea, 0x00000f0d, 0x00000f21, + 0x00000f37, 0x00000f49, 0x00000f6c, 0x00000f7e, + 0x00000fa0, 0x00000fc8, 0x00000fe9, 0x00001004, + 0x0000102d, 0x0000104f, 0x00001081, 0x00001118, // 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, + 0x00001143, 0x0000117b, 0x000011a4, 0x000011dc, + 0x0000121d, 0x0000124d, 0x00001270, 0x00001298, + 0x000012fa, 0x00001306, 0x00001312, 0x00001322, + 0x00001332, 0x00001342, 0x00001369, 0x000013aa, + 0x000013ce, 0x000013df, 0x00001401, 0x0000142e, + 0x0000148d, 0x0000152a, 0x00001578, 0x00001592, + 0x000015b0, 0x00001610, } // Size: 512 bytes -const enData string = "" + // Size: 5636 bytes +const enData string = "" + // Size: 5648 bytes "\x04\x00\x01 0\x02Use the arrow keys to navigate: ↓ ↑ → ←\x02This intera" + "ctive tool creates a new miner actor and creates the basic configuration" + " layer for it.\x02This process is partially idempotent. Once a new miner" + @@ -236,207 +236,208 @@ const enData string = "" + // Size: 5636 bytes "re in %[2]s.\x02Waiting for %[1]s to write sectors into Yugabyte.\x02Err" + "or interpreting miner ID: %[1]s: ID: %[2]s\x02Error verifying sectors: %" + "[1]s\x02The sectors are in the database. The database is ready for %[1]s" + - ".\x02Now shut down lotus-miner and move the systems to %[1]s.\x02Press r" + - "eturn to continue\x02Aborting migration.\x02Sectors verified. %[1]d sect" + - "or locations found.\x02Connected to Yugabyte. Schema is current.\x02Enab" + - "ling Sector Indexing in the database.\x02Error encoding config.toml: %[1" + - "]s\x02Press return to update %[1]s with Yugabyte info. A Backup file wil" + - "l be written to that folder before changes are made.\x02Error expanding " + - "path: %[1]s\x02Error reading filemode of config.toml: %[1]s\x02Error cre" + - "ating backup file: %[1]s\x02Error reading config.toml: %[1]s\x02Error wr" + - "iting backup file: %[1]s\x02Error closing backup file: %[1]s\x02Error wr" + - "iting config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus Miner.\x02Con" + - "nected to Yugabyte\x02To start, ensure your sealing pipeline is drained " + - "and shut-down lotus-miner.\x02Select the location of your lotus-miner co" + - "nfig directory?\x02Other\x02Enter the path to the configuration director" + - "y used by %[1]s\x04\x00\x01 '\x02No path provided, abandoning migration" + - "\x02Cannot read the config.toml file in the provided directory, Error: %" + - "[1]s\x02Could not create repo from directory: %[1]s. Aborting migration" + - "\x02Could not lock miner repo. Your miner must be stopped: %[1]s\x0a Abo" + - "rting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02Step Complet" + - "e: %[1]s\x02Initializing a new miner actor.\x02Enter the info to create " + - "a new miner\x02Owner Address: %[1]s\x02Worker Address: %[1]s\x02Sender A" + - "ddress: %[1]s\x02Sector Size: %[1]d\x02Confidence epochs: %[1]d\x02Conti" + - "nue to verify the addresses and create a new miner actor.\x04\x00\x01 %" + - "\x02Miner creation error occurred: %[1]s\x02Enter the owner address\x02N" + - "o address provided\x02Failed to parse the address: %[1]s\x02Enter %[1]s " + - "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):" + ".\x02Now shut down lotus-miner and lotus-worker and use run %[1]s instea" + + "d.\x02Press return to continue\x02Aborting migration.\x02Sectors verifie" + + "d. %[1]d sector locations found.\x02Connected to Yugabyte. Schema is cur" + + "rent.\x02Enabling Sector Indexing in the database.\x02Error encoding con" + + "fig.toml: %[1]s\x02Press return to update %[1]s with Yugabyte info. A Ba" + + "ckup file will be written to that folder before changes are made.\x02Err" + + "or expanding path: %[1]s\x02Error reading filemode of config.toml: %[1]s" + + "\x02Error creating backup file: %[1]s\x02Error reading config.toml: %[1]" + + "s\x02Error writing backup file: %[1]s\x02Error closing backup file: %[1]" + + "s\x02Error writing config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus " + + "Miner.\x02Connected to Yugabyte\x02To start, ensure your sealing pipelin" + + "e is drained and shut-down lotus-miner.\x02Select the location of your l" + + "otus-miner config directory?\x02Other\x02Enter the path to the configura" + + "tion directory used by %[1]s\x04\x00\x01 '\x02No path provided, abandoni" + + "ng migration\x02Cannot read the config.toml file in the provided directo" + + "ry, Error: %[1]s\x02Could not create repo from directory: %[1]s. Abortin" + + "g migration\x02Could not lock miner repo. Your miner must be stopped: %[" + + "1]s\x0a Aborting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02S" + + "tep Complete: %[1]s\x02Initializing a new miner actor.\x02Enter the info" + + " to create a new miner\x02Owner Address: %[1]s\x02Worker Address: %[1]s" + + "\x02Sender Address: %[1]s\x02Sector Size: %[1]d\x02Confidence epochs: %[" + + "1]d\x02Continue to verify the addresses and create a new miner actor." + + "\x04\x00\x01 %\x02Miner creation error occurred: %[1]s\x02Enter the owne" + + "r address\x02No address provided\x02Failed to parse the address: %[1]s" + + "\x02Enter %[1]s 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\x02M" + + "iner %[1]s created successfully\x02Cannot reach the DB: %[1]s\x02Error c" + + "onnecting to full node API: %[1]s\x02Pre-initialization steps complete" + + "\x02Failed to generate random bytes for secret: %[1]s\x02Please do not r" + + "un guided-setup again as miner creation is not idempotent. You need to r" + + "un 'curio config new-cluster %[1]s' to finish the configuration\x02Faile" + + "d 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\x02" + + "Failed to insert 'base' config layer in database: %[1]s\x02Configuration" + + " 'base' was updated to include this miner's address\x02Failed to load ba" + + "se config from database: %[1]s\x02Failed to parse base config: %[1]s\x02" + + "Failed to regenerate base config: %[1]s\x02Enter the info to connect to " + + "your Yugabyte database installation (https://download.yugabyte.com/)\x02" + + "Host: %[1]s\x02Port: %[1]s\x02Username: %[1]s\x02Password: %[1]s\x02Data" + + "base: %[1]s\x02Continue to connect and update schema.\x04\x00\x01 <\x02D" + + "atabase config error occurred, abandoning migration: %[1]s\x02Enter the " + + "Yugabyte database host(s)\x02No host provided\x02Enter the Yugabyte data" + + "base %[1]s\x02Error connecting to Yugabyte database: %[1]s\x02Configurat" + + "ion 'base' was updated to include this miner's address (%[1]s) and its w" + + "allet setup.\x02Compare the configurations %[1]s to %[2]s. Changes betwe" + + "en the miner IDs other than wallet addreses should be a new, minimal lay" + + "er for runners that need it.\x02Configuration 'base' was created to rese" + + "mble this lotus-miner's config.toml .\x04\x00\x01 \x15\x02Layer %[1]s cr" + + "eated.\x04\x00\x01 \x19\x02To work with the config:\x02To run Curio: Wit" + + "h machine or cgroup isolation, use the command (with example layer selec" + + "tion):" var koIndex = []uint32{ // 122 elements // Entry 0 - 1F 0x00000000, 0x00000044, 0x000000c1, 0x000001c1, 0x0000020e, 0x00000289, 0x000002aa, 0x000002bc, 0x000002e5, 0x00000300, 0x00000325, 0x00000348, - 0x000003a2, 0x000003f2, 0x00000418, 0x00000471, - 0x00000490, 0x000004cc, 0x000004fc, 0x00000554, - 0x000005e0, 0x00000619, 0x0000066f, 0x000006ad, - 0x000006fb, 0x00000716, 0x00000750, 0x00000783, - 0x000007bd, 0x000007e7, 0x00000811, 0x00000853, + 0x000003b2, 0x00000402, 0x00000428, 0x00000481, + 0x000004a0, 0x000004dc, 0x0000050c, 0x00000564, + 0x000005f0, 0x00000629, 0x0000067f, 0x000006bd, + 0x0000070b, 0x00000726, 0x00000760, 0x00000793, + 0x000007cd, 0x000007f7, 0x00000821, 0x00000863, // Entry 20 - 3F - 0x00000877, 0x00000884, 0x0000090a, 0x0000095c, - 0x00000983, 0x00000a1f, 0x00000ab1, 0x00000b2c, - 0x00000b70, 0x00000bae, 0x00000bd5, 0x00000c40, - 0x00000c8a, 0x00000cb1, 0x00000ccc, 0x00000d1b, - 0x00000d5c, 0x00000d9c, 0x00000de3, 0x00000e89, - 0x00000eb9, 0x00000f08, 0x00000f2b, 0x00000f4c, - 0x00000f6f, 0x00000f92, 0x00000fd0, 0x00000ff4, - 0x0000100a, 0x00001075, 0x000010c4, 0x000010cb, + 0x00000887, 0x00000894, 0x0000091a, 0x0000096c, + 0x00000993, 0x00000a2f, 0x00000ac1, 0x00000b3c, + 0x00000b80, 0x00000bbe, 0x00000be5, 0x00000c50, + 0x00000c9d, 0x00000cc4, 0x00000cdf, 0x00000d2e, + 0x00000d6f, 0x00000daf, 0x00000df6, 0x00000e9c, + 0x00000ecc, 0x00000f1b, 0x00000f3e, 0x00000f5f, + 0x00000f82, 0x00000fa5, 0x00000fe3, 0x00001007, + 0x0000101d, 0x00001088, 0x000010d7, 0x000010de, // Entry 40 - 5F - 0x00001113, 0x00001165, 0x000011bf, 0x00001229, - 0x000012ba, 0x000012d2, 0x000012ec, 0x00001310, - 0x00001343, 0x0000135b, 0x00001373, 0x0000138b, - 0x000013a0, 0x000013b8, 0x0000140f, 0x0000143a, - 0x00001452, 0x00001479, 0x0000149c, 0x000014b0, - 0x000014c5, 0x000014e9, 0x00001513, 0x00001524, - 0x0000154a, 0x00001570, 0x000015a9, 0x000015e1, - 0x00001619, 0x00001638, 0x00001684, 0x00001742, + 0x00001126, 0x00001178, 0x000011d2, 0x0000123c, + 0x000012cd, 0x000012e5, 0x000012ff, 0x00001323, + 0x00001356, 0x0000136e, 0x00001386, 0x0000139e, + 0x000013b3, 0x000013cb, 0x00001422, 0x0000144d, + 0x00001465, 0x0000148c, 0x000014af, 0x000014c3, + 0x000014d8, 0x000014fc, 0x00001526, 0x00001537, + 0x0000155d, 0x00001583, 0x000015bc, 0x000015f4, + 0x0000162c, 0x0000164b, 0x00001697, 0x00001755, // 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, + 0x000017a1, 0x000017ef, 0x00001812, 0x0000186e, + 0x000018be, 0x00001913, 0x00001956, 0x00001995, + 0x00001a03, 0x00001a14, 0x00001a22, 0x00001a3a, + 0x00001a4e, 0x00001a68, 0x00001a92, 0x00001af5, + 0x00001b31, 0x00001b5b, 0x00001b93, 0x00001be7, + 0x00001c60, 0x00001d1a, 0x00001d71, 0x00001da0, + 0x00001dc7, 0x00001e53, } // Size: 512 bytes -const koData string = "" + // Size: 7742 bytes +const koData string = "" + // Size: 7763 bytes "\x04\x00\x01 ?\x02화살표 키를 사용하여 이동하세요: ↓ ↑ → ←\x02이 대화형 도구는 새로운 채굴자 액터를 생성" + "하고 그에 대한 기본 구성 레이어를 생성합니다.\x02이 프로세스는 부분적으로 항등원적입니다. 새로운 채굴자 액터가 생성되었고" + " 후속 단계가 실패하는 경우 사용자는 구성을 완료하기 위해 'curio config new-cluster < 채굴자 ID >'를 " + "실행해야 합니다.\x02이 대화형 도구는 5분 안에 lotus-miner를 Curio로 이주합니다.\x02각 단계는 확인이 필" + "요하며 되돌릴 수 있습니다. 언제든지 Ctrl+C를 눌러 종료할 수 있습니다.\x02터미널에서 Ctrl+C가 눌림\x02나는 " + "원한다:\x02기존의 Lotus-Miner에서 이전하기\x02새로운 채굴자 생성\x02나머지 단계를 중단합니다.\x02Lotu" + - "s-Miner에서 Curio로 이주.\x02더 많은 안내를 위해 %[1]s를 사용하여 웹 인터페이스를 시도하세요.\x02해당하는 " + - "경우 이제 시장 노드를 이주할 수 있습니다 (%[1]s).\x02새로운 채굴자 초기화 완료.\x02lotus-miner con" + - "fig.toml을 Curio의 데이터베이스 구성으로 이전 중입니다.\x02API 가져오기 오류: %[1]s\x02FullNode의" + - " API 정보를 가져올 수 없습니다: %[1]w\x02토큰을 가져오는 중 오류 발생: %[1]s\x02레이어에 구성을 저장하는 중" + - " 오류 발생: %[1]s. 마이그레이션 중단\x02Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀에게 `%[1" + - "]s`를 사용 중이라고 알려주세요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 채굴자 ID, Cur" + - "io 버전, 체인 (%[1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 체인, 및 채굴자 파워 (버킷).\x02힌트:" + - " 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02마이너 파워를 가져오는 중 오류 발생: " + - "%[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생: %[1]s\x02메시지 " + - "서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =\x02메시지 전송 중 오" + - "류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02문서:\x02'%[1]" + - "s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니다.\x02기계별 구성 변" + - "경을 위해 다른 레이어를 추가할 수 있습니다.\x02Filecoin %[1]s 채널: %[2]s 및 %[3]s\x02신뢰성 향" + - "상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio run --layers" + - "=post'\x02한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 대해 마이그레이션을 실" + - "행하세요.\x02데이터베이스 자격 증명이 %[2]s에 입력되었으므로 지금 %[1]s을 시작하거나 다시 시작하세요.\x02%[1" + - "]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02광부 ID를 해석하는 중 오류 발생: %[1]s: ID: %[2]" + - "s\x02섹터 확인 중 오류 발생: %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1]s를 위해 준비되었습니다" + - ".\x02이제 lotus-miner를 종료하고 시스템을 %[1]s로 이동하세요.\x02계속하려면 리턴을 누르세요\x02마이그레이션" + - " 중단.\x02섹터가 확인되었습니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Yugabyte에 연결되었습니다. 스키마가 현재" + - "입니다.\x02데이터베이스에서 Sector Indexing을 활성화합니다.\x02config.toml을 인코딩하는 중 오류가 " + - "발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로 업데이트하려면 리턴 키를 누르세요. 변경 사항을 적용하기 전" + - "에 해당 폴더에 백업 파일이 작성됩니다.\x02경로를 확장하는 중 오류 발생: %[1]s\x02config.toml의 파일 모" + - "드를 읽는 중 오류가 발생했습니다: %[1]s\x02백업 파일 생성 오류: %[1]s\x02config.toml 읽기 오류: " + - "%[1]s\x02백업 파일 쓰기 오류: %[1]s\x02백업 파일 닫기 오류: %[1]s\x02config.toml을 쓰는 중 오" + - "류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이너 재시작.\x02Yugabyte에 연결됨\x02" + - "시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.\x02로터스 마이너 구성 디렉토리의 위" + - "치를 선택하시겠습니까?\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 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께" + - "):" + "s-Miner에서 Curio로 이주.\x02%[1]s를 사용하여 웹 인터페이스를 시도하고 더 나은 안내된 개선을 진행하세요." + + "\x02해당하는 경우 이제 시장 노드를 이주할 수 있습니다 (%[1]s).\x02새로운 채굴자 초기화 완료.\x02lotus-mi" + + "ner config.toml을 Curio의 데이터베이스 구성으로 이전 중입니다.\x02API 가져오기 오류: %[1]s\x02Fu" + + "llNode의 API 정보를 가져올 수 없습니다: %[1]w\x02토큰을 가져오는 중 오류 발생: %[1]s\x02레이어에 구성을" + + " 저장하는 중 오류 발생: %[1]s. 마이그레이션 중단\x02Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀" + + "에게 `%[1]s`를 사용 중이라고 알려주세요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 채굴" + + "자 ID, Curio 버전, 체인 (%[1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 체인, 및 채굴자 파워 (" + + "버킷).\x02힌트: 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02마이너 파워를 가" + + "져오는 중 오류 발생: %[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생" + + ": %[1]s\x02메시지 서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =" + + "\x02메시지 전송 중 오류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02" + + "문서:\x02'%[1]s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니" + + "다.\x02기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.\x02Filecoin %[1]s 채널: %[2]s 및 " + + "%[3]s\x02신뢰성 향상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio " + + "run --layers=post'\x02한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 " + + "대해 마이그레이션을 실행하세요.\x02데이터베이스 자격 증명이 %[2]s에 입력되었으므로 지금 %[1]s을 시작하거나 다시 시" + + "작하세요.\x02%[1]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02광부 ID를 해석하는 중 오류 발생: %" + + "[1]s: ID: %[2]s\x02섹터 확인 중 오류 발생: %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1" + + "]s를 위해 준비되었습니다.\x02이제 lotus-miner와 lotus-worker를 종료하고 %[1]s을 실행하세요.\x02계" + + "속하려면 리턴을 누르세요\x02마이그레이션 중단.\x02섹터가 확인되었습니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Y" + + "ugabyte에 연결되었습니다. 스키마가 현재입니다.\x02데이터베이스에서 Sector Indexing을 활성화합니다.\x02co" + + "nfig.toml을 인코딩하는 중 오류가 발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로 업데이트하려면 리턴 키" + + "를 누르세요. 변경 사항을 적용하기 전에 해당 폴더에 백업 파일이 작성됩니다.\x02경로를 확장하는 중 오류 발생: %[1]s" + + "\x02config.toml의 파일 모드를 읽는 중 오류가 발생했습니다: %[1]s\x02백업 파일 생성 오류: %[1]s\x02" + + "config.toml 읽기 오류: %[1]s\x02백업 파일 쓰기 오류: %[1]s\x02백업 파일 닫기 오류: %[1]s\x02" + + "config.toml을 쓰는 중 오류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이너 재시작.\x02" + + "Yugabyte에 연결됨\x02시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.\x02로터스" + + " 마이너 구성 디렉토리의 위치를 선택하시겠습니까?\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마이너 생성은 idempotent하지 않으므로 가이드 설정을 다시 실행하지 마십시오. 구성을 완료하려면 'curio" + + " config new-cluster %[1]s'를 실행해야 합니다.\x02FullNode에 대한 API 정보를 가져오는 데 실패했" + + "습니다: %[1]w\x02데몬 노드로부터 인증 토큰을 확인하는 중 오류 발생: %[1]s\x02기본 구성 생성 실패: %[1]" + + "s\x02데이터베이스에 'base' 구성 레이어를 삽입하는 데 실패했습니다: %[1]s\x02이 마이너 주소를 포함한 구성 'ba" + + "se'가 업데이트되었습니다.\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\x02Yuga" + + "byte 데이터베이스 호스트를 입력하십시오\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하" + + "십시오\x02Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02기본 설정 'base'가 이 마이" + + "너의 주소(%[1]s) 및 지갑 설정을 포함하도록 업데이트되었습니다.\x02구성 %[1]s를 %[2]s과 비교하세요. 지갑 주" + + "소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이어여야 합니다.\x02'base' 설정이 " + + "이 lotus-miner의 config.toml과 유사하게 만들어졌습니다.\x04\x00\x01 *\x02레이어 %[1]s가 " + + "생성되었습니다.\x04\x00\x01 \x22\x02구성 파일을 사용하려면:\x02Curio를 실행하려면: 기계 또는 cgro" + + "up 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께):" var zhIndex = []uint32{ // 122 elements // Entry 0 - 1F 0x00000000, 0x00000033, 0x0000008b, 0x00000134, 0x0000017c, 0x000001cb, 0x000001e4, 0x000001f1, 0x00000211, 0x0000022a, 0x00000240, 0x0000025d, - 0x0000029c, 0x000002dd, 0x000002f9, 0x0000033e, - 0x0000035b, 0x00000384, 0x000003a2, 0x000003db, - 0x0000042f, 0x0000045c, 0x000004ab, 0x000004e6, - 0x0000051b, 0x00000525, 0x00000549, 0x00000567, - 0x0000058b, 0x000005a9, 0x000005c7, 0x000005fc, + 0x000002a5, 0x000002e6, 0x00000302, 0x00000347, + 0x00000364, 0x0000038d, 0x000003ab, 0x000003e4, + 0x00000438, 0x00000465, 0x000004b4, 0x000004ef, + 0x00000524, 0x0000052e, 0x00000552, 0x00000570, + 0x00000594, 0x000005b2, 0x000005d0, 0x00000605, // Entry 20 - 3F - 0x0000060f, 0x0000061e, 0x00000678, 0x000006b5, - 0x000006dd, 0x0000073c, 0x0000078c, 0x000007df, - 0x00000805, 0x00000832, 0x00000850, 0x0000088c, - 0x000008be, 0x000008ce, 0x000008de, 0x00000911, - 0x0000093e, 0x00000963, 0x00000986, 0x000009fe, - 0x00000a1c, 0x00000a4b, 0x00000a6f, 0x00000a94, - 0x00000ab8, 0x00000adc, 0x00000aff, 0x00000b1f, - 0x00000b34, 0x00000b7f, 0x00000baf, 0x00000bb6, + 0x00000618, 0x00000627, 0x00000681, 0x000006be, + 0x000006e6, 0x00000745, 0x00000795, 0x000007e8, + 0x0000080e, 0x0000083b, 0x00000859, 0x00000895, + 0x000008d9, 0x000008e9, 0x000008f9, 0x0000092c, + 0x00000959, 0x0000097e, 0x000009a1, 0x00000a19, + 0x00000a37, 0x00000a66, 0x00000a8a, 0x00000aaf, + 0x00000ad3, 0x00000af7, 0x00000b1a, 0x00000b3a, + 0x00000b4f, 0x00000b9a, 0x00000bca, 0x00000bd1, // Entry 40 - 5F - 0x00000be0, 0x00000c04, 0x00000c48, 0x00000c7a, - 0x00000cc3, 0x00000cd6, 0x00000cf0, 0x00000d0f, - 0x00000d34, 0x00000d4c, 0x00000d61, 0x00000d79, - 0x00000d8d, 0x00000da4, 0x00000dd5, 0x00000dfa, - 0x00000e10, 0x00000e20, 0x00000e3a, 0x00000e4e, - 0x00000e61, 0x00000e6e, 0x00000e8e, 0x00000e9e, - 0x00000ebb, 0x00000edb, 0x00000ef5, 0x00000f12, - 0x00000f43, 0x00000f5c, 0x00000f85, 0x00001012, + 0x00000bfb, 0x00000c1f, 0x00000c63, 0x00000c95, + 0x00000cde, 0x00000cf1, 0x00000d0b, 0x00000d2a, + 0x00000d4f, 0x00000d67, 0x00000d7c, 0x00000d94, + 0x00000da8, 0x00000dbf, 0x00000df0, 0x00000e15, + 0x00000e2b, 0x00000e3b, 0x00000e55, 0x00000e69, + 0x00000e7c, 0x00000e89, 0x00000ea9, 0x00000eb9, + 0x00000ed6, 0x00000ef6, 0x00000f10, 0x00000f2d, + 0x00000f5e, 0x00000f77, 0x00000fa0, 0x0000102d, // 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, + 0x00001059, 0x00001094, 0x000010b4, 0x000010e5, + 0x00001118, 0x00001145, 0x00001166, 0x0000118c, + 0x000011e6, 0x000011f5, 0x00001204, 0x00001216, + 0x00001225, 0x00001237, 0x00001256, 0x0000128e, + 0x000012b3, 0x000012c3, 0x000012e1, 0x0000130d, + 0x0000135e, 0x000013e0, 0x00001427, 0x00001441, + 0x00001459, 0x000014b0, } // Size: 512 bytes -const zhData string = "" + // Size: 5269 bytes +const zhData string = "" + // Size: 5296 bytes "\x04\x00\x01 .\x02使用箭头键进行导航:↓ ↑ → ←\x02此交互式工具将创建一个新的矿工角色,并为其创建基本配置层。\x02" + "该过程部分幂等。一旦创建了新的矿工角色,并且随后的步骤失败,用户需要运行 'curio config new-cluster < 矿工 ID" + " >' 来完成配置。\x02这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。\x02每一步都需要您的确认,并且可以撤销。随" + "时按Ctrl+C退出。\x02在终端中按下Ctrl+C\x02我想要:\x02从现有的 Lotus-Miner 迁移\x02创建一个新的矿工" + - "\x02中止剩余步骤。\x02Lotus-Miner到Curio迁移。\x02尝试使用%[1]s的Web界面进行进一步引导式改进。\x02如果适" + - "用,您现在可以迁移您的市场节点(%[1]s)。\x02新矿工初始化完成。\x02将 lotus-miner config.toml 迁移到 " + - "Curio 的数据库配置中。\x02获取 API 时出错:%[1]s\x02无法获取FullNode的API信息:%[1]w\x02获取令牌时出" + - "错:%[1]s\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Curio 团队希望改进您使用的软件。告诉团队您正在使用 `%[1" + - "]s`。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工 ID,Curio 版本,链(%[1]s 或 %[2]s)。签名。" + + "\x02中止剩余步骤。\x02Lotus-Miner到Curio迁移。\x02尝试使用%[1]s的网络界面进行更进一步的指导性改进。\x02如果" + + "适用,您现在可以迁移您的市场节点(%[1]s)。\x02新矿工初始化完成。\x02将 lotus-miner config.toml 迁移到" + + " Curio 的数据库配置中。\x02获取 API 时出错:%[1]s\x02无法获取FullNode的API信息:%[1]w\x02获取令牌时" + + "出错:%[1]s\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Curio 团队希望改进您使用的软件。告诉团队您正在使用 `%[" + + "1]s`。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工 ID,Curio 版本,链(%[1]s 或 %[2]s)。签名。" + "\x02聚合-匿名:版本,链和矿工算力(分桶)。\x02提示:我是在任何链上运行 Curio 的人。\x02没有。\x02获取矿工功率时出错:%" + "[1]s\x02整理消息时出错:%[1]s\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%[1]s\x02发送消息时出错:%[1" + "]s\x04\x00\x01 0\x02发送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04\x00\x01 \x0a\x02文档" + @@ -444,32 +445,32 @@ const zhData string = "" + // Size: 5269 bytes "\x02Filecoin %[1]s 频道:%[2]s 和 %[3]s\x02通过冗余增加可靠性:使用至少后层启动多台机器:'curio run" + " --layers=post'\x02一个数据库可以服务多个矿工ID:为每个lotus-miner运行迁移。\x02请立即启动(或重新启动)%[" + "1]s,因为数据库凭据已在%[2]s中。\x02等待%[1]s将扇区写入Yugabyte。\x02解释矿工ID时出错:%[1]s:ID:%[2]" + - "s\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-miner并将系统移至%[" + - "1]s。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02已连接到Yugabyte。模式是当前的。" + - "\x02在数据库中启用扇区索引。\x02编码config.toml时出错:%[1]s\x02按回车键更新 %[1]s 以包含 Yugabyte " + - "信息。在进行更改之前,将在该文件夹中写入备份文件。\x02扩展路径时出错:%[1]s\x02读取config.toml文件模式时出错:%[1" + - "]s\x02创建备份文件时出错:%[1]s\x02读取 config.toml 时出错:%[1]s\x02写入备份文件时出错:%[1]s\x02" + - "关闭备份文件时出错:%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b\x02重新启动Lotu" + - "s Miner。\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。\x02选择您的lotu" + - "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隔离,使用命令(" + - "附带示例层选择):" + "s\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-miner和lotus-w" + + "orker,改为使用%[1]s运行。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02已连接到Yuga" + + "byte。模式是当前的。\x02在数据库中启用扇区索引。\x02编码config.toml时出错:%[1]s\x02按回车键更新 %[1]s 以" + + "包含 Yugabyte 信息。在进行更改之前,将在该文件夹中写入备份文件。\x02扩展路径时出错:%[1]s\x02读取config.tom" + + "l文件模式时出错:%[1]s\x02创建备份文件时出错:%[1]s\x02读取 config.toml 时出错:%[1]s\x02写入备份文件时" + + "出错:%[1]s\x02关闭备份文件时出错:%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b" + + "\x02重新启动Lotus Miner。\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。" + + "\x02选择您的lotus-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 的 API 信息: %[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://download.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输入Yugabyte数据库主机(S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s\x02连接到Yug" + + "abyte数据库时出错:%[1]s\x02'base'配置已更新,包括该矿工的地址(%[1]s)及其钱包设置。\x02比较配置%[1]s和%[2" + + "]s。矿工ID之间除了钱包地址的变化应该是需要的运行者的一个新的、最小的层。\x02'base'配置已创建,以类似于这个lotus-miner的" + + "config.toml。\x04\x00\x01 \x15\x02层%[1]s已创建。\x04\x00\x01 \x13\x02要使用配置:" + + "\x02运行Curio:使用机器或cgroup隔离,使用命令(附带示例层选择):" - // Total table size 20183 bytes (19KiB); checksum: 4FD3E25A + // Total table size 20243 bytes (19KiB); checksum: AB52E150 diff --git a/cmd/curio/internal/translations/locales/en/out.gotext.json b/cmd/curio/internal/translations/locales/en/out.gotext.json index db8a264ee..604678622 100644 --- a/cmd/curio/internal/translations/locales/en/out.gotext.json +++ b/cmd/curio/internal/translations/locales/en/out.gotext.json @@ -89,18 +89,18 @@ "fuzzy": true }, { - "id": "Try the web interface with {__layersgui} for further guided improvements.", - "message": "Try the web interface with {__layersgui} for further guided improvements.", - "translation": "Try the web interface with {__layersgui} for further guided improvements.", + "id": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "message": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "translation": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", "translatorComment": "Copied from source.", "placeholders": [ { - "id": "__layersgui", + "id": "Rendercurio_run___layersgui", "string": "%[1]s", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "\"--layers=gui\"" + "expr": "code.Render(\"curio run --layers=gui\")" } ], "fuzzy": true @@ -579,18 +579,18 @@ "fuzzy": true }, { - "id": "Now shut down lotus-miner and move the systems to {Curio}.", - "message": "Now shut down lotus-miner and move the systems to {Curio}.", - "translation": "Now shut down lotus-miner and move the systems to {Curio}.", + "id": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "message": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "translation": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", "translatorComment": "Copied from source.", "placeholders": [ { - "id": "Curio", + "id": "Rendercurio_run", "string": "%[1]s", "type": "string", "underlyingType": "string", "argNum": 1, - "expr": "\"Curio\"" + "expr": "code.Render(\"curio run\")" } ], "fuzzy": true @@ -1553,10 +1553,20 @@ "fuzzy": true }, { - "id": "Configuration 'base' was updated to include this miner's address and its wallet setup.", - "message": "Configuration 'base' was updated to include this miner's address and its wallet setup.", - "translation": "Configuration 'base' was updated to include this miner's address and its wallet setup.", + "id": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "message": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "translation": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", "translatorComment": "Copied from source.", + "placeholders": [ + { + "id": "MinerAddress", + "string": "%[1]s", + "type": "github.com/filecoin-project/go-address.Address", + "underlyingType": "struct{str string}", + "argNum": 1, + "expr": "minerAddress" + } + ], "fuzzy": true }, { @@ -1585,9 +1595,9 @@ "fuzzy": true }, { - "id": "Configuration 'base' was created to include this miner's address and its wallet setup.", - "message": "Configuration 'base' was created to include this miner's address and its wallet setup.", - "translation": "Configuration 'base' was created to include this miner's address and its wallet setup.", + "id": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "message": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "translation": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", "translatorComment": "Copied from source.", "fuzzy": true }, diff --git a/cmd/curio/internal/translations/locales/ko/messages.gotext.json b/cmd/curio/internal/translations/locales/ko/messages.gotext.json index 61107880c..bac1140e8 100644 --- a/cmd/curio/internal/translations/locales/ko/messages.gotext.json +++ b/cmd/curio/internal/translations/locales/ko/messages.gotext.json @@ -1077,6 +1077,30 @@ "translation": "기본 구성을 구문 분석하는 데 실패했습니다: {Error}", "message": "Failed to parse base config: {Error}", "placeholder": null + }, + { + "id": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "translation": "{Rendercurio_run___layersgui}를 사용하여 웹 인터페이스를 시도하고 더 나은 안내된 개선을 진행하세요.", + "message": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "placeholder": null + }, + { + "id": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "translation": "이제 lotus-miner와 lotus-worker를 종료하고 {Rendercurio_run}을 실행하세요.", + "message": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "placeholder": null + }, + { + "id": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "translation": "기본 설정 'base'가 이 마이너의 주소({MinerAddress}) 및 지갑 설정을 포함하도록 업데이트되었습니다.", + "message": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "placeholder": null + }, + { + "id": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "translation": "'base' 설정이 이 lotus-miner의 config.toml과 유사하게 만들어졌습니다.", + "message": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "placeholder": null } ] } \ No newline at end of file diff --git a/cmd/curio/internal/translations/locales/zh/messages.gotext.json b/cmd/curio/internal/translations/locales/zh/messages.gotext.json index fc9a0f313..1e2608fa8 100644 --- a/cmd/curio/internal/translations/locales/zh/messages.gotext.json +++ b/cmd/curio/internal/translations/locales/zh/messages.gotext.json @@ -1047,6 +1047,30 @@ "translation": "解析基本配置失败:{Error}", "message": "Failed to parse base config: {Error}", "placeholder": null + }, + { + "id": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "translation": "尝试使用{Rendercurio_run___layersgui}的网络界面进行更进一步的指导性改进。", + "message": "Try the web interface with {Rendercurio_run___layersgui} for further guided improvements.", + "placeholder": null + }, + { + "id": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "translation": "现在关闭lotus-miner和lotus-worker,改为使用{Rendercurio_run}运行。", + "message": "Now shut down lotus-miner and lotus-worker and use run {Rendercurio_run} instead.", + "placeholder": null + }, + { + "id": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "translation": "'base'配置已更新,包括该矿工的地址({MinerAddress})及其钱包设置。", + "message": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.", + "placeholder": null + }, + { + "id": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "translation": "'base'配置已创建,以类似于这个lotus-miner的config.toml。", + "message": "Configuration 'base' was created to resemble this lotus-miner's config.toml .", + "placeholder": null } ] } \ No newline at end of file diff --git a/cmd/curio/rpc/rpc.go b/cmd/curio/rpc/rpc.go index d210a93ac..f45e276c3 100644 --- a/cmd/curio/rpc/rpc.go +++ b/cmd/curio/rpc/rpc.go @@ -252,7 +252,12 @@ func ListenAndServe(ctx context.Context, dependencies *deps.Deps, shutdownChan c } log.Warn("Graceful shutdown successful") }() - log.Infof("Setting up web server at %s", dependencies.Cfg.Subsystems.GuiAddress) + + uiAddress := dependencies.Cfg.Subsystems.GuiAddress + if uiAddress == "" || uiAddress[0] == ':' { + uiAddress = "localhost" + uiAddress + } + log.Infof("GUI: http://%s", uiAddress) eg.Go(web.ListenAndServe) } return eg.Wait() diff --git a/cmd/curio/run.go b/cmd/curio/run.go index d360b6af4..cacacfc0f 100644 --- a/cmd/curio/run.go +++ b/cmd/curio/run.go @@ -62,8 +62,9 @@ var runCmd = &cli.Command{ Value: "~/.curio/", }, &cli.StringSliceFlag{ - Name: "layers", - Usage: "list of layers to be interpreted (atop defaults). Default: base", + Name: "layers", + Aliases: []string{"l", "layer"}, + Usage: "list of layers to be interpreted (atop defaults). Default: base", }, }, Action: func(cctx *cli.Context) (err error) { @@ -169,6 +170,7 @@ var webCmd = &cli.Command{ }, }, Action: func(cctx *cli.Context) error { + db, err := deps.MakeDB(cctx) if err != nil { return err diff --git a/cmd/curio/stop.go b/cmd/curio/stop.go index 5c7bb9880..eb61a34fa 100644 --- a/cmd/curio/stop.go +++ b/cmd/curio/stop.go @@ -13,6 +13,7 @@ var stopCmd = &cli.Command{ Usage: "Stop a running Curio process", Flags: []cli.Flag{}, Action: func(cctx *cli.Context) error { + api, closer, err := lcli.GetAPI(cctx) if err != nil { return err diff --git a/cmd/curio/tasks/tasks.go b/cmd/curio/tasks/tasks.go index 35faba765..3b262efa8 100644 --- a/cmd/curio/tasks/tasks.go +++ b/cmd/curio/tasks/tasks.go @@ -3,9 +3,13 @@ package tasks import ( "context" + "sort" + "strings" + "time" logging "github.com/ipfs/go-log/v2" "github.com/samber/lo" + "golang.org/x/exp/maps" "golang.org/x/xerrors" "github.com/filecoin-project/go-address" @@ -22,6 +26,7 @@ import ( "github.com/filecoin-project/lotus/lib/lazy" "github.com/filecoin-project/lotus/lib/must" "github.com/filecoin-project/lotus/node/modules" + "github.com/filecoin-project/lotus/node/modules/dtypes" ) var log = logging.Logger("curio/deps") @@ -157,6 +162,7 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task if err != nil { return nil, err } + go machineDetails(dependencies, activeTasks, ht.ResourcesAvailable().MachineID) if hasAnySealingTask { watcher, err := message.NewMessageWatcher(db, ht, chainSched, full) @@ -172,3 +178,56 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task return ht, nil } + +func machineDetails(deps *deps.Deps, activeTasks []harmonytask.TaskInterface, machineID int) { + taskNames := lo.Map(activeTasks, func(item harmonytask.TaskInterface, _ int) string { + return item.TypeDetails().Name + }) + + miners := lo.Map(maps.Keys(deps.Maddrs), func(item dtypes.MinerAddress, _ int) string { + return address.Address(item).String() + }) + sort.Strings(miners) + + _, err := deps.DB.Exec(context.Background(), `INSERT INTO harmony_machine_details + (tasks, layers, startup_time, miners, machine_id) VALUES ($1, $2, $3, $4, $5) + ON CONFLICT (machine_id) DO UPDATE SET tasks=$1, layers=$2, startup_time=$3, miners=$4`, + strings.Join(taskNames, ","), strings.Join(deps.Layers, ","), + time.Now(), strings.Join(miners, ","), machineID) + + if err != nil { + log.Errorf("failed to update machine details: %s", err) + return + } + + // maybePostWarning + if !lo.Contains(taskNames, "WdPost") && !lo.Contains(taskNames, "WinPost") { + // Maybe we aren't running a PoSt for these miners? + var allMachines []struct { + MachineID int `db:"machine_id"` + Miners string `db:"miners"` + Tasks string `db:"tasks"` + } + err := deps.DB.Select(context.Background(), &allMachines, `SELECT machine_id, miners, tasks FROM harmony_machine_details`) + if err != nil { + log.Errorf("failed to get machine details: %s", err) + return + } + + for _, miner := range miners { + var myPostIsHandled bool + for _, m := range allMachines { + if !lo.Contains(strings.Split(m.Miners, ","), miner) { + continue + } + if lo.Contains(strings.Split(m.Tasks, ","), "WdPost") && lo.Contains(strings.Split(m.Tasks, ","), "WinPost") { + myPostIsHandled = true + break + } + } + if !myPostIsHandled { + log.Errorf("No PoSt tasks are running for miner %s. Start handling PoSts immediately with:\n\tcurio run --layers=\"post\" ", miner) + } + } + } +} diff --git a/curiosrc/web/api/apihelper/apihelper.go b/curiosrc/web/api/apihelper/apihelper.go new file mode 100644 index 000000000..07c7898e8 --- /dev/null +++ b/curiosrc/web/api/apihelper/apihelper.go @@ -0,0 +1,19 @@ +package apihelper + +import ( + "net/http" + "runtime/debug" + + logging "github.com/ipfs/go-log/v2" +) + +var log = logging.Logger("lp/web/apihelper") + +func OrHTTPFail(w http.ResponseWriter, err error) { + if err != nil { + w.WriteHeader(500) + _, _ = w.Write([]byte(err.Error())) + log.Errorw("http fail", "err", err, "stack", string(debug.Stack())) + panic(err) + } +} diff --git a/curiosrc/web/api/config/config.go b/curiosrc/web/api/config/config.go new file mode 100644 index 000000000..1e18e792f --- /dev/null +++ b/curiosrc/web/api/config/config.go @@ -0,0 +1,180 @@ +package config + +import ( + "bytes" + "context" + "encoding/json" + "net/http" + "reflect" + "time" + + "github.com/BurntSushi/toml" + "github.com/gorilla/mux" + "github.com/invopop/jsonschema" + + "github.com/filecoin-project/lotus/cmd/curio/deps" + "github.com/filecoin-project/lotus/curiosrc/web/api/apihelper" + "github.com/filecoin-project/lotus/node/config" +) + +type cfg struct { + *deps.Deps +} + +func Routes(r *mux.Router, deps *deps.Deps) { + c := &cfg{deps} + // At menu.html: + r.Methods("GET").Path("/layers").HandlerFunc(c.getLayers) + r.Methods("GET").Path("/topo").HandlerFunc(c.topo) + + // At edit.html: + r.Methods("GET").Path("/schema").HandlerFunc(getSch) + r.Methods("GET").Path("/layers/{layer}").HandlerFunc(c.getLayer) + r.Methods("POST").Path("/layers/{layer}").HandlerFunc(c.setLayer) + r.Methods("GET").Path("/default").HandlerFunc(c.def) +} +func getSch(w http.ResponseWriter, r *http.Request) { + ref := jsonschema.Reflector{ + Mapper: func(i reflect.Type) *jsonschema.Schema { + if i == reflect.TypeOf(config.Duration(time.Second)) { + return &jsonschema.Schema{ + Type: "string", + Format: "duration", + } + } + return nil + }, + } + sch := ref.Reflect(config.CurioConfig{}) + //sch := jsonschema.Reflect(config.CurioConfig{}) + // add comments + for k, doc := range config.Doc { + item, ok := sch.Definitions[k] + if !ok { + continue + } + for _, line := range doc { + item, ok := item.Properties.Get(line.Name) + if !ok { + continue + } + if line.Comment != "" { + extra := make(map[string]any) + type options struct { + InfoText string `json:"infoText"` + } + opt := options{ + InfoText: line.Comment, + } + extra["options"] = opt + item.Extras = extra + } + } + } + + var allOpt func(s *jsonschema.Schema) + allOpt = func(s *jsonschema.Schema) { + s.Required = []string{} + for _, v := range s.Definitions { + v.Required = []string{} + + allOpt(v) + } + } + allOpt(sch) + + apihelper.OrHTTPFail(w, json.NewEncoder(w).Encode(sch)) +} + +func (c *cfg) getLayers(w http.ResponseWriter, r *http.Request) { + var layers []string + apihelper.OrHTTPFail(w, c.DB.Select(context.Background(), &layers, `SELECT title FROM harmony_config ORDER BY title`)) + apihelper.OrHTTPFail(w, json.NewEncoder(w).Encode(layers)) +} + +func (c *cfg) getLayer(w http.ResponseWriter, r *http.Request) { + var layer string + apihelper.OrHTTPFail(w, c.DB.QueryRow(context.Background(), `SELECT config FROM harmony_config WHERE title = $1`, mux.Vars(r)["layer"]).Scan(&layer)) + + // Read the TOML into a struct + configStruct := map[string]any{} // NOT CurioConfig b/c we want to preserve unsets + _, err := toml.Decode(layer, &configStruct) + apihelper.OrHTTPFail(w, err) + + // Encode the struct as JSON + jsonData, err := json.Marshal(configStruct) + apihelper.OrHTTPFail(w, err) + + // Write the JSON response + w.Header().Set("Content-Type", "application/json") + _, err = w.Write(jsonData) + apihelper.OrHTTPFail(w, err) +} + +func (c *cfg) setLayer(w http.ResponseWriter, r *http.Request) { + layer := mux.Vars(r)["layer"] + var configStruct map[string]any + dec := json.NewDecoder(r.Body) + dec.UseNumber() // JSON lib by default treats number is float64() + apihelper.OrHTTPFail(w, dec.Decode(&configStruct)) + + //Encode the struct as TOML + var tomlData bytes.Buffer + err := toml.NewEncoder(&tomlData).Encode(configStruct) + apihelper.OrHTTPFail(w, err) + + configStr := tomlData.String() + + // Generate a full commented string if this is base layer + if layer == "base" { + // Parse the into CurioConfig TOML + curioCfg := config.DefaultCurioConfig() + _, err = deps.LoadConfigWithUpgrades(tomlData.String(), curioCfg) + apihelper.OrHTTPFail(w, err) + cb, err := config.ConfigUpdate(curioCfg, config.DefaultCurioConfig(), config.Commented(true), config.DefaultKeepUncommented(), config.NoEnv()) + apihelper.OrHTTPFail(w, err) + configStr = string(cb) + } + + //Write the TOML to the database + _, err = c.DB.Exec(context.Background(), `INSERT INTO harmony_config (title, config) VALUES ($1, $2) ON CONFLICT (title) DO UPDATE SET config = $2`, layer, configStr) + apihelper.OrHTTPFail(w, err) +} + +func (c *cfg) topo(w http.ResponseWriter, r *http.Request) { + var topology []struct { + Server string `db:"server"` + CPU int `db:"cpu"` + GPU int `db:"gpu"` + RAM int `db:"ram"` + LayersCSV string `db:"layers"` + TasksCSV string `db:"tasks"` + } + apihelper.OrHTTPFail(w, c.DB.Select(context.Background(), &topology, ` + SELECT + m.host_and_port as server, + cpu, gpu, ram, layers, tasks + FROM harmony_machines m JOIN harmony_machine_details d ON m.id=d.machine_id + ORDER BY server`)) + w.Header().Set("Content-Type", "application/json") + apihelper.OrHTTPFail(w, json.NewEncoder(w).Encode(topology)) +} + +func (c *cfg) def(w http.ResponseWriter, r *http.Request) { + cb, err := config.ConfigUpdate(config.DefaultCurioConfig(), nil, config.Commented(false), config.DefaultKeepUncommented(), config.NoEnv()) + apihelper.OrHTTPFail(w, err) + + // Read the TOML into a struct + configStruct := map[string]any{} // NOT CurioConfig b/c we want to preserve unsets + _, err = toml.Decode(string(cb), &configStruct) + apihelper.OrHTTPFail(w, err) + + // Encode the struct as JSON + jsonData, err := json.Marshal(configStruct) + apihelper.OrHTTPFail(w, err) + + // Write the JSON response + w.Header().Set("Content-Type", "application/json") + _, err = w.Write(jsonData) + apihelper.OrHTTPFail(w, err) +} diff --git a/curiosrc/web/api/routes.go b/curiosrc/web/api/routes.go index c030f7d53..6b450055e 100644 --- a/curiosrc/web/api/routes.go +++ b/curiosrc/web/api/routes.go @@ -5,9 +5,11 @@ import ( "github.com/gorilla/mux" "github.com/filecoin-project/lotus/cmd/curio/deps" + "github.com/filecoin-project/lotus/curiosrc/web/api/config" "github.com/filecoin-project/lotus/curiosrc/web/api/debug" ) func Routes(r *mux.Router, deps *deps.Deps) { debug.Routes(r.PathPrefix("/debug").Subrouter(), deps) + config.Routes(r.PathPrefix("/config").Subrouter(), deps) } diff --git a/curiosrc/web/hapi/watch_actor.go b/curiosrc/web/hapi/watch_actor.go index a65608f14..c44dcd779 100644 --- a/curiosrc/web/hapi/watch_actor.go +++ b/curiosrc/web/hapi/watch_actor.go @@ -162,6 +162,8 @@ func (a *app) updateActor(ctx context.Context) error { return xerrors.Errorf("getting worker balance: %w", err) } + sort.Strings(cnames) + actorInfos = append(actorInfos, actorInfo{ Address: addr.String(), CLayers: cnames, diff --git a/curiosrc/web/hapi/web/root.gohtml b/curiosrc/web/hapi/web/root.gohtml index b3a41e800..562bbc209 100644 --- a/curiosrc/web/hapi/web/root.gohtml +++ b/curiosrc/web/hapi/web/root.gohtml @@ -13,9 +13,6 @@

{{.PageTitle}}

-
- version [todo] -

diff --git a/curiosrc/web/static/chain-connectivity.js b/curiosrc/web/static/chain-connectivity.mjs similarity index 100% rename from curiosrc/web/static/chain-connectivity.js rename to curiosrc/web/static/chain-connectivity.mjs diff --git a/curiosrc/web/static/config/edit.html b/curiosrc/web/static/config/edit.html new file mode 100644 index 000000000..37bc8f093 --- /dev/null +++ b/curiosrc/web/static/config/edit.html @@ -0,0 +1,150 @@ + + + + JSON Schema Editor + + + + + + + + + +
+
+
+
+ +
+ +
+ + +
+ +
+ +
+
+
+ + diff --git a/curiosrc/web/static/config/index.html b/curiosrc/web/static/config/index.html new file mode 100644 index 000000000..e93d0787c --- /dev/null +++ b/curiosrc/web/static/config/index.html @@ -0,0 +1,89 @@ + + + + + Configuration Editor + + + + + + + + +

Configuration Editor

+

Click on a layer to edit its configuration

+ +
+ + + \ No newline at end of file diff --git a/curiosrc/web/static/index.html b/curiosrc/web/static/index.html index 04050ff6e..b86c48915 100644 --- a/curiosrc/web/static/index.html +++ b/curiosrc/web/static/index.html @@ -2,7 +2,7 @@ Curio Cluster Overview - +