2021-08-27 19:25:43 +00:00
|
|
|
//go:build !nodaemon
|
2019-07-18 23:18:26 +00:00
|
|
|
// +build !nodaemon
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2020-09-28 10:28:12 +00:00
|
|
|
"bufio"
|
2019-07-18 23:18:26 +00:00
|
|
|
"context"
|
2020-02-23 23:39:45 +00:00
|
|
|
"encoding/hex"
|
|
|
|
"encoding/json"
|
2020-03-04 21:21:24 +00:00
|
|
|
"fmt"
|
2020-09-28 10:28:12 +00:00
|
|
|
"io"
|
2019-07-24 23:23:06 +00:00
|
|
|
"io/ioutil"
|
2020-09-28 10:28:12 +00:00
|
|
|
"net/http"
|
2020-01-21 01:53:55 +00:00
|
|
|
"os"
|
2020-01-22 19:53:06 +00:00
|
|
|
"runtime/pprof"
|
2020-02-23 23:39:45 +00:00
|
|
|
"strings"
|
2019-07-23 22:34:13 +00:00
|
|
|
|
2021-05-23 13:48:42 +00:00
|
|
|
"github.com/filecoin-project/go-jsonrpc"
|
2020-01-02 19:08:49 +00:00
|
|
|
paramfetch "github.com/filecoin-project/go-paramfetch"
|
fix metrics wiring.
Some components like go-ds-measure, go-ipfs-blockstore and go-bitswap
expose metrics via ipfs/go-metrics-interface, but Lotus never injects
the Prometheus exporter (ipfs/go-metrics-prometheus). Therefore, those
metrics never surface in instrumentation.
Instead, Lotus uses OpenCensus directly.
This commit injects the Prometheus exporter for go-metrics-interface, and
instructs the OpenCensus Prometheus exporter to use the DefaultRegistry.
This has the effect of exposing blending the metrics of both metrics
libraries.
With this patch, the datastore, cache utilisation, and bitswap metrics
are now exported via the /debug/metrics endpoint.
This commit also fixes an issue where the metrics scope was empty, making
go-metrics-interface default to "<no-scope>". Angle brackets are inadmissible
characters for Prometheus, so it was refusing to export the affected metrics.
(These were the ARC cache metrics.)
2020-11-02 17:56:49 +00:00
|
|
|
metricsprom "github.com/ipfs/go-metrics-prometheus"
|
2020-02-12 20:00:07 +00:00
|
|
|
"github.com/mitchellh/go-homedir"
|
2019-07-18 23:18:26 +00:00
|
|
|
"github.com/multiformats/go-multiaddr"
|
2020-06-05 22:59:01 +00:00
|
|
|
"github.com/urfave/cli/v2"
|
2020-06-04 22:18:14 +00:00
|
|
|
"go.opencensus.io/plugin/runmetrics"
|
2020-02-26 00:40:07 +00:00
|
|
|
"go.opencensus.io/stats"
|
|
|
|
"go.opencensus.io/stats/view"
|
|
|
|
"go.opencensus.io/tag"
|
2019-10-02 20:29:40 +00:00
|
|
|
"golang.org/x/xerrors"
|
2020-09-28 10:17:54 +00:00
|
|
|
"gopkg.in/cheggaaa/pb.v1"
|
2019-07-18 23:18:26 +00:00
|
|
|
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/api"
|
|
|
|
"github.com/filecoin-project/lotus/build"
|
2021-09-02 16:07:23 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/consensus/filcns"
|
2020-01-21 01:53:55 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/stmgr"
|
|
|
|
"github.com/filecoin-project/lotus/chain/store"
|
2020-10-01 15:54:28 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-01-21 01:53:55 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/vm"
|
2020-06-02 18:54:24 +00:00
|
|
|
lcli "github.com/filecoin-project/lotus/cli"
|
2020-08-17 13:26:18 +00:00
|
|
|
"github.com/filecoin-project/lotus/extern/sector-storage/ffiwrapper"
|
2020-10-09 19:52:04 +00:00
|
|
|
"github.com/filecoin-project/lotus/journal"
|
2021-08-17 12:55:35 +00:00
|
|
|
"github.com/filecoin-project/lotus/journal/fsjournal"
|
2020-02-22 11:36:22 +00:00
|
|
|
"github.com/filecoin-project/lotus/lib/peermgr"
|
2020-07-02 00:09:21 +00:00
|
|
|
"github.com/filecoin-project/lotus/lib/ulimit"
|
2020-02-26 02:42:34 +00:00
|
|
|
"github.com/filecoin-project/lotus/metrics"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/node"
|
|
|
|
"github.com/filecoin-project/lotus/node/modules"
|
2020-05-14 01:10:49 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/dtypes"
|
2019-10-18 04:47:41 +00:00
|
|
|
"github.com/filecoin-project/lotus/node/modules/testing"
|
|
|
|
"github.com/filecoin-project/lotus/node/repo"
|
2019-07-18 23:18:26 +00:00
|
|
|
)
|
|
|
|
|
2019-07-24 22:49:37 +00:00
|
|
|
const (
|
2020-02-21 20:56:30 +00:00
|
|
|
makeGenFlag = "lotus-make-genesis"
|
2020-02-21 18:00:10 +00:00
|
|
|
preTemplateFlag = "genesis-template"
|
2019-07-24 22:49:37 +00:00
|
|
|
)
|
|
|
|
|
2020-06-02 15:09:18 +00:00
|
|
|
var daemonStopCmd = &cli.Command{
|
|
|
|
Name: "stop",
|
|
|
|
Usage: "Stop a running lotus daemon",
|
|
|
|
Flags: []cli.Flag{},
|
|
|
|
Action: func(cctx *cli.Context) error {
|
2020-06-02 18:54:24 +00:00
|
|
|
api, closer, err := lcli.GetAPI(cctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer closer()
|
|
|
|
|
|
|
|
err = api.Shutdown(lcli.ReqContext(cctx))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2020-06-02 15:09:18 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2019-07-18 23:18:26 +00:00
|
|
|
// DaemonCmd is the `go-lotus daemon` command
|
|
|
|
var DaemonCmd = &cli.Command{
|
|
|
|
Name: "daemon",
|
|
|
|
Usage: "Start a lotus daemon process",
|
|
|
|
Flags: []cli.Flag{
|
2019-11-12 18:31:17 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "api",
|
|
|
|
Value: "1234",
|
|
|
|
},
|
2019-07-24 22:49:37 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: makeGenFlag,
|
|
|
|
Value: "",
|
|
|
|
Hidden: true,
|
|
|
|
},
|
2019-11-25 04:45:13 +00:00
|
|
|
&cli.StringFlag{
|
2020-02-21 18:00:10 +00:00
|
|
|
Name: preTemplateFlag,
|
2019-11-25 04:45:13 +00:00
|
|
|
Hidden: true,
|
|
|
|
},
|
2020-02-23 23:39:45 +00:00
|
|
|
&cli.StringFlag{
|
2020-02-24 17:45:42 +00:00
|
|
|
Name: "import-key",
|
|
|
|
Usage: "on first run, import a default key from a given file",
|
2020-02-23 23:39:45 +00:00
|
|
|
Hidden: true,
|
|
|
|
},
|
2019-07-24 22:49:37 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "genesis",
|
|
|
|
Usage: "genesis file to use for first node run",
|
|
|
|
},
|
2019-10-09 03:16:35 +00:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "bootstrap",
|
|
|
|
Value: true,
|
|
|
|
},
|
2020-01-21 01:53:55 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "import-chain",
|
2020-09-28 10:28:12 +00:00
|
|
|
Usage: "on first run, load chain from given file or url and validate",
|
2020-01-21 01:53:55 +00:00
|
|
|
},
|
2020-09-02 03:12:21 +00:00
|
|
|
&cli.StringFlag{
|
2020-09-02 13:47:18 +00:00
|
|
|
Name: "import-snapshot",
|
2020-09-28 10:28:12 +00:00
|
|
|
Usage: "import chain state from a given chain export file or url",
|
2020-09-02 03:12:21 +00:00
|
|
|
},
|
2020-01-21 01:58:58 +00:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "halt-after-import",
|
|
|
|
Usage: "halt the process after importing chain from file",
|
|
|
|
},
|
2020-09-29 15:25:45 +00:00
|
|
|
&cli.BoolFlag{
|
2022-02-28 16:14:05 +00:00
|
|
|
Name: "lite",
|
|
|
|
Usage: "start lotus in lite mode",
|
2020-09-29 15:25:45 +00:00
|
|
|
},
|
2020-01-22 19:53:06 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "pprof",
|
|
|
|
Usage: "specify name of file for writing cpu profile to",
|
|
|
|
},
|
2020-05-14 01:10:49 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "profile",
|
|
|
|
Usage: "specify type of node",
|
|
|
|
},
|
2020-07-02 00:09:21 +00:00
|
|
|
&cli.BoolFlag{
|
|
|
|
Name: "manage-fdlimit",
|
|
|
|
Usage: "manage open file limit",
|
|
|
|
Value: true,
|
|
|
|
},
|
2020-09-30 06:56:38 +00:00
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "config",
|
|
|
|
Usage: "specify path of config file to use",
|
|
|
|
},
|
2020-11-17 13:39:53 +00:00
|
|
|
// FIXME: This is not the correct place to put this configuration
|
|
|
|
// option. Ideally it would be part of `config.toml` but at the
|
|
|
|
// moment that only applies to the node configuration and not outside
|
|
|
|
// components like the RPC server.
|
|
|
|
&cli.IntFlag{
|
|
|
|
Name: "api-max-req-size",
|
|
|
|
Usage: "maximum API request size accepted by the JSON RPC server",
|
|
|
|
},
|
2021-01-15 19:57:32 +00:00
|
|
|
&cli.PathFlag{
|
|
|
|
Name: "restore",
|
|
|
|
Usage: "restore from backup file",
|
|
|
|
},
|
|
|
|
&cli.PathFlag{
|
|
|
|
Name: "restore-config",
|
|
|
|
Usage: "config file to use when restoring from backup",
|
|
|
|
},
|
2019-07-18 23:18:26 +00:00
|
|
|
},
|
|
|
|
Action: func(cctx *cli.Context) error {
|
2020-10-08 09:24:31 +00:00
|
|
|
isLite := cctx.Bool("lite")
|
|
|
|
|
2020-06-04 22:18:14 +00:00
|
|
|
err := runmetrics.Enable(runmetrics.RunMetricOptions{
|
|
|
|
EnableCPU: true,
|
|
|
|
EnableMemory: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("enabling runtime metrics: %w", err)
|
|
|
|
}
|
2020-07-02 00:09:21 +00:00
|
|
|
|
|
|
|
if cctx.Bool("manage-fdlimit") {
|
|
|
|
if _, _, err := ulimit.ManageFdLimit(); err != nil {
|
|
|
|
log.Errorf("setting file descriptor limit: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-22 19:53:06 +00:00
|
|
|
if prof := cctx.String("pprof"); prof != "" {
|
|
|
|
profile, err := os.Create(prof)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := pprof.StartCPUProfile(profile); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer pprof.StopCPUProfile()
|
|
|
|
}
|
|
|
|
|
2020-05-14 01:10:49 +00:00
|
|
|
var isBootstrapper dtypes.Bootstrapper
|
|
|
|
switch profile := cctx.String("profile"); profile {
|
|
|
|
case "bootstrapper":
|
|
|
|
isBootstrapper = true
|
|
|
|
case "":
|
|
|
|
// do nothing
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unrecognized profile type: %q", profile)
|
|
|
|
}
|
|
|
|
|
2021-02-21 10:03:00 +00:00
|
|
|
ctx, _ := tag.New(context.Background(),
|
|
|
|
tag.Insert(metrics.Version, build.BuildVersion),
|
|
|
|
tag.Insert(metrics.Commit, build.CurrentCommit),
|
|
|
|
tag.Insert(metrics.NodeType, "chain"),
|
|
|
|
)
|
|
|
|
// Register all metric views
|
|
|
|
if err = view.Register(
|
|
|
|
metrics.ChainNodeViews...,
|
|
|
|
); err != nil {
|
|
|
|
log.Fatalf("Cannot register the view: %v", err)
|
|
|
|
}
|
|
|
|
// Set the metric to one so it is published to the exporter
|
|
|
|
stats.Record(ctx, metrics.LotusInfo.M(1))
|
|
|
|
|
2020-02-12 20:00:07 +00:00
|
|
|
{
|
|
|
|
dir, err := homedir.Expand(cctx.String("repo"))
|
|
|
|
if err != nil {
|
|
|
|
log.Warnw("could not expand repo location", "error", err)
|
|
|
|
} else {
|
|
|
|
log.Infof("lotus repo: %s", dir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-18 23:18:26 +00:00
|
|
|
r, err := repo.NewFS(cctx.String("repo"))
|
|
|
|
if err != nil {
|
2019-11-27 17:10:34 +00:00
|
|
|
return xerrors.Errorf("opening fs repo: %w", err)
|
2019-07-18 23:18:26 +00:00
|
|
|
}
|
|
|
|
|
2020-09-30 06:56:38 +00:00
|
|
|
if cctx.String("config") != "" {
|
|
|
|
r.SetConfigPath(cctx.String("config"))
|
|
|
|
}
|
|
|
|
|
2021-01-15 19:57:32 +00:00
|
|
|
err = r.Init(repo.FullNode)
|
|
|
|
if err != nil && err != repo.ErrRepoExists {
|
2019-11-27 17:10:34 +00:00
|
|
|
return xerrors.Errorf("repo init error: %w", err)
|
2019-07-18 23:18:26 +00:00
|
|
|
}
|
2021-01-15 19:57:32 +00:00
|
|
|
freshRepo := err != repo.ErrRepoExists
|
2019-07-18 23:18:26 +00:00
|
|
|
|
2020-10-08 09:24:31 +00:00
|
|
|
if !isLite {
|
2021-03-10 15:16:44 +00:00
|
|
|
if err := paramfetch.GetParams(lcli.ReqContext(cctx), build.ParametersJSON(), build.SrsJSON(), 0); err != nil {
|
2020-10-08 09:24:31 +00:00
|
|
|
return xerrors.Errorf("fetching proof parameters: %w", err)
|
|
|
|
}
|
2019-10-02 17:20:30 +00:00
|
|
|
}
|
|
|
|
|
2020-04-21 19:46:50 +00:00
|
|
|
var genBytes []byte
|
2019-07-24 22:49:37 +00:00
|
|
|
if cctx.String("genesis") != "" {
|
2019-10-02 17:20:30 +00:00
|
|
|
genBytes, err = ioutil.ReadFile(cctx.String("genesis"))
|
2019-07-24 23:23:06 +00:00
|
|
|
if err != nil {
|
2019-11-27 17:10:34 +00:00
|
|
|
return xerrors.Errorf("reading genesis: %w", err)
|
2019-07-24 23:23:06 +00:00
|
|
|
}
|
2020-04-21 19:46:50 +00:00
|
|
|
} else {
|
|
|
|
genBytes = build.MaybeGenesis()
|
2019-10-02 17:20:30 +00:00
|
|
|
}
|
|
|
|
|
2021-01-15 19:57:32 +00:00
|
|
|
if cctx.IsSet("restore") {
|
|
|
|
if !freshRepo {
|
|
|
|
return xerrors.Errorf("restoring from backup is only possible with a fresh repo!")
|
|
|
|
}
|
|
|
|
if err := restore(cctx, r); err != nil {
|
|
|
|
return xerrors.Errorf("restoring from backup: %w", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-21 01:53:55 +00:00
|
|
|
chainfile := cctx.String("import-chain")
|
2020-09-02 13:47:18 +00:00
|
|
|
snapshot := cctx.String("import-snapshot")
|
2020-09-02 03:12:21 +00:00
|
|
|
if chainfile != "" || snapshot != "" {
|
|
|
|
if chainfile != "" && snapshot != "" {
|
2020-09-02 13:47:18 +00:00
|
|
|
return fmt.Errorf("cannot specify both 'import-snapshot' and 'import-chain'")
|
2020-09-02 03:12:21 +00:00
|
|
|
}
|
2020-09-02 12:57:44 +00:00
|
|
|
var issnapshot bool
|
2020-09-02 03:12:21 +00:00
|
|
|
if chainfile == "" {
|
|
|
|
chainfile = snapshot
|
2020-09-02 12:57:44 +00:00
|
|
|
issnapshot = true
|
2020-09-02 03:12:21 +00:00
|
|
|
}
|
|
|
|
|
2020-12-30 10:04:00 +00:00
|
|
|
if err := ImportChain(ctx, r, chainfile, issnapshot); err != nil {
|
2020-01-21 01:53:55 +00:00
|
|
|
return err
|
|
|
|
}
|
2020-01-21 01:58:58 +00:00
|
|
|
if cctx.Bool("halt-after-import") {
|
2020-03-04 21:21:24 +00:00
|
|
|
fmt.Println("Chain import complete, halting as requested...")
|
2020-01-21 01:58:58 +00:00
|
|
|
return nil
|
|
|
|
}
|
2020-01-21 01:53:55 +00:00
|
|
|
}
|
|
|
|
|
2019-10-02 17:20:30 +00:00
|
|
|
genesis := node.Options()
|
|
|
|
if len(genBytes) > 0 {
|
2019-07-24 23:23:06 +00:00
|
|
|
genesis = node.Override(new(modules.Genesis), modules.LoadGenesis(genBytes))
|
2019-07-24 22:49:37 +00:00
|
|
|
}
|
2019-10-02 17:20:30 +00:00
|
|
|
if cctx.String(makeGenFlag) != "" {
|
2020-02-21 18:00:10 +00:00
|
|
|
if cctx.String(preTemplateFlag) == "" {
|
|
|
|
return xerrors.Errorf("must also pass file with genesis template to `--%s`", preTemplateFlag)
|
2019-11-25 04:45:13 +00:00
|
|
|
}
|
2020-02-21 18:00:10 +00:00
|
|
|
genesis = node.Override(new(modules.Genesis), testing.MakeGenesis(cctx.String(makeGenFlag), cctx.String(preTemplateFlag)))
|
2019-10-02 17:20:30 +00:00
|
|
|
}
|
2019-07-24 22:49:37 +00:00
|
|
|
|
2020-06-02 19:31:01 +00:00
|
|
|
shutdownChan := make(chan struct{})
|
2020-06-02 18:54:24 +00:00
|
|
|
|
2021-03-23 12:42:56 +00:00
|
|
|
// If the daemon is started in "lite mode", provide a Gateway
|
2020-10-08 09:24:31 +00:00
|
|
|
// for RPC calls
|
|
|
|
liteModeDeps := node.Options()
|
2020-09-30 14:35:06 +00:00
|
|
|
if isLite {
|
2020-09-29 15:25:45 +00:00
|
|
|
gapi, closer, err := lcli.GetGatewayAPI(cctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-09-30 14:35:06 +00:00
|
|
|
defer closer()
|
2021-03-23 12:42:56 +00:00
|
|
|
liteModeDeps = node.Override(new(api.Gateway), gapi)
|
2020-09-29 15:25:45 +00:00
|
|
|
}
|
|
|
|
|
fix metrics wiring.
Some components like go-ds-measure, go-ipfs-blockstore and go-bitswap
expose metrics via ipfs/go-metrics-interface, but Lotus never injects
the Prometheus exporter (ipfs/go-metrics-prometheus). Therefore, those
metrics never surface in instrumentation.
Instead, Lotus uses OpenCensus directly.
This commit injects the Prometheus exporter for go-metrics-interface, and
instructs the OpenCensus Prometheus exporter to use the DefaultRegistry.
This has the effect of exposing blending the metrics of both metrics
libraries.
With this patch, the datastore, cache utilisation, and bitswap metrics
are now exported via the /debug/metrics endpoint.
This commit also fixes an issue where the metrics scope was empty, making
go-metrics-interface default to "<no-scope>". Angle brackets are inadmissible
characters for Prometheus, so it was refusing to export the affected metrics.
(These were the ARC cache metrics.)
2020-11-02 17:56:49 +00:00
|
|
|
// some libraries like ipfs/go-ds-measure and ipfs/go-ipfs-blockstore
|
|
|
|
// use ipfs/go-metrics-interface. This injects a Prometheus exporter
|
|
|
|
// for those. Metrics are exported to the default registry.
|
|
|
|
if err := metricsprom.Inject(); err != nil {
|
|
|
|
log.Warnf("unable to inject prometheus ipfs/go-metrics exporter; some metrics will be unavailable; err: %s", err)
|
|
|
|
}
|
2019-10-22 17:18:06 +00:00
|
|
|
|
fix metrics wiring.
Some components like go-ds-measure, go-ipfs-blockstore and go-bitswap
expose metrics via ipfs/go-metrics-interface, but Lotus never injects
the Prometheus exporter (ipfs/go-metrics-prometheus). Therefore, those
metrics never surface in instrumentation.
Instead, Lotus uses OpenCensus directly.
This commit injects the Prometheus exporter for go-metrics-interface, and
instructs the OpenCensus Prometheus exporter to use the DefaultRegistry.
This has the effect of exposing blending the metrics of both metrics
libraries.
With this patch, the datastore, cache utilisation, and bitswap metrics
are now exported via the /debug/metrics endpoint.
This commit also fixes an issue where the metrics scope was empty, making
go-metrics-interface default to "<no-scope>". Angle brackets are inadmissible
characters for Prometheus, so it was refusing to export the affected metrics.
(These were the ARC cache metrics.)
2020-11-02 17:56:49 +00:00
|
|
|
var api api.FullNode
|
2019-09-17 14:23:08 +00:00
|
|
|
stop, err := node.New(ctx,
|
2020-10-09 16:43:22 +00:00
|
|
|
node.FullAPI(&api, node.Lite(isLite)),
|
2019-07-23 22:34:13 +00:00
|
|
|
|
2021-07-07 11:56:37 +00:00
|
|
|
node.Base(),
|
2019-07-18 23:18:26 +00:00
|
|
|
node.Repo(r),
|
|
|
|
|
2021-03-09 22:46:13 +00:00
|
|
|
node.Override(new(dtypes.Bootstrapper), isBootstrapper),
|
|
|
|
node.Override(new(dtypes.ShutdownChan), shutdownChan),
|
|
|
|
|
2019-07-24 22:49:37 +00:00
|
|
|
genesis,
|
2020-10-08 09:24:31 +00:00
|
|
|
liteModeDeps,
|
2019-07-24 22:49:37 +00:00
|
|
|
|
2019-11-12 18:31:17 +00:00
|
|
|
node.ApplyIf(func(s *node.Settings) bool { return cctx.IsSet("api") },
|
|
|
|
node.Override(node.SetApiEndpointKey, func(lr repo.LockedRepo) error {
|
|
|
|
apima, err := multiaddr.NewMultiaddr("/ip4/127.0.0.1/tcp/" +
|
|
|
|
cctx.String("api"))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return lr.SetAPIEndpoint(apima)
|
|
|
|
})),
|
2019-10-23 11:11:18 +00:00
|
|
|
node.ApplyIf(func(s *node.Settings) bool { return !cctx.Bool("bootstrap") },
|
|
|
|
node.Unset(node.RunPeerMgrKey),
|
|
|
|
node.Unset(new(*peermgr.PeerMgr)),
|
2019-10-11 00:31:06 +00:00
|
|
|
),
|
2019-07-18 23:18:26 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
2019-11-27 17:10:34 +00:00
|
|
|
return xerrors.Errorf("initializing node: %w", err)
|
2019-07-18 23:18:26 +00:00
|
|
|
}
|
|
|
|
|
2020-02-23 23:39:45 +00:00
|
|
|
if cctx.String("import-key") != "" {
|
|
|
|
if err := importKey(ctx, api, cctx.String("import-key")); err != nil {
|
|
|
|
log.Errorf("importing key failed: %+v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-12 18:31:17 +00:00
|
|
|
endpoint, err := r.APIEndpoint()
|
|
|
|
if err != nil {
|
2019-11-27 17:10:34 +00:00
|
|
|
return xerrors.Errorf("getting api endpoint: %w", err)
|
2019-11-12 18:31:17 +00:00
|
|
|
}
|
|
|
|
|
2021-05-23 13:48:42 +00:00
|
|
|
//
|
|
|
|
// Instantiate JSON-RPC endpoint.
|
|
|
|
// ----
|
|
|
|
|
|
|
|
// Populate JSON-RPC options.
|
|
|
|
serverOptions := make([]jsonrpc.ServerOption, 0)
|
|
|
|
if maxRequestSize := cctx.Int("api-max-req-size"); maxRequestSize != 0 {
|
|
|
|
serverOptions = append(serverOptions, jsonrpc.WithMaxRequestSize(int64(maxRequestSize)))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Instantiate the full node handler.
|
2021-06-09 22:42:24 +00:00
|
|
|
h, err := node.FullNodeHandler(api, true, serverOptions...)
|
2021-05-23 13:48:42 +00:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to instantiate rpc handler: %s", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Serve the RPC.
|
|
|
|
rpcStopper, err := node.ServeRPC(h, "lotus-daemon", endpoint)
|
2021-05-21 20:34:17 +00:00
|
|
|
if err != nil {
|
2021-05-23 13:48:42 +00:00
|
|
|
return fmt.Errorf("failed to start json-rpc endpoint: %s", err)
|
2021-05-21 20:34:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Monitor for shutdown.
|
|
|
|
finishCh := node.MonitorShutdown(shutdownChan,
|
|
|
|
node.ShutdownHandler{Component: "rpc server", StopFunc: rpcStopper},
|
|
|
|
node.ShutdownHandler{Component: "node", StopFunc: stop},
|
|
|
|
)
|
|
|
|
<-finishCh // fires when shutdown is complete.
|
|
|
|
|
2019-07-18 23:18:26 +00:00
|
|
|
// TODO: properly parse api endpoint (or make it a URL)
|
2021-05-21 20:34:17 +00:00
|
|
|
return nil
|
2019-07-18 23:18:26 +00:00
|
|
|
},
|
2020-06-02 15:09:18 +00:00
|
|
|
Subcommands: []*cli.Command{
|
|
|
|
daemonStopCmd,
|
2019-07-18 23:18:26 +00:00
|
|
|
},
|
|
|
|
}
|
2020-01-21 01:53:55 +00:00
|
|
|
|
2020-02-23 23:39:45 +00:00
|
|
|
func importKey(ctx context.Context, api api.FullNode, f string) error {
|
|
|
|
f, err := homedir.Expand(f)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
hexdata, err := ioutil.ReadFile(f)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := hex.DecodeString(strings.TrimSpace(string(hexdata)))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
var ki types.KeyInfo
|
|
|
|
if err := json.Unmarshal(data, &ki); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
addr, err := api.WalletImport(ctx, &ki)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := api.WalletSetDefault(ctx, addr); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-24 11:09:48 +00:00
|
|
|
log.Infof("successfully imported key for %s", addr)
|
2020-02-23 23:39:45 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-30 10:04:00 +00:00
|
|
|
func ImportChain(ctx context.Context, r repo.Repo, fname string, snapshot bool) (err error) {
|
2020-09-28 10:28:12 +00:00
|
|
|
var rd io.Reader
|
|
|
|
var l int64
|
|
|
|
if strings.HasPrefix(fname, "http://") || strings.HasPrefix(fname, "https://") {
|
|
|
|
resp, err := http.Get(fname) //nolint:gosec
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close() //nolint:errcheck
|
2020-01-21 01:53:55 +00:00
|
|
|
|
2020-09-28 10:28:12 +00:00
|
|
|
if resp.StatusCode != http.StatusOK {
|
2021-02-23 20:20:36 +00:00
|
|
|
return xerrors.Errorf("fetching chain CAR failed with non-200 response: %d", resp.StatusCode)
|
2020-09-28 10:28:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rd = resp.Body
|
|
|
|
l = resp.ContentLength
|
|
|
|
} else {
|
|
|
|
fname, err = homedir.Expand(fname)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
fi, err := os.Open(fname)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer fi.Close() //nolint:errcheck
|
|
|
|
|
|
|
|
st, err := os.Stat(fname)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
rd = fi
|
|
|
|
l = st.Size()
|
2020-09-28 10:17:54 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 01:53:55 +00:00
|
|
|
lr, err := r.Lock(repo.FullNode)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-05-27 20:53:20 +00:00
|
|
|
defer lr.Close() //nolint:errcheck
|
2020-01-21 01:53:55 +00:00
|
|
|
|
2021-02-28 22:48:36 +00:00
|
|
|
bs, err := lr.Blockstore(ctx, repo.UniversalBlockstore)
|
2020-01-21 01:53:55 +00:00
|
|
|
if err != nil {
|
2020-11-01 13:03:21 +00:00
|
|
|
return xerrors.Errorf("failed to open blockstore: %w", err)
|
2020-01-21 01:53:55 +00:00
|
|
|
}
|
|
|
|
|
2021-12-17 09:42:09 +00:00
|
|
|
mds, err := lr.Datastore(ctx, "/metadata")
|
2020-01-21 01:53:55 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-08-17 12:55:35 +00:00
|
|
|
j, err := fsjournal.OpenFSJournal(lr, journal.EnvDisabledEvents())
|
2020-10-09 19:52:04 +00:00
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("failed to open journal: %w", err)
|
|
|
|
}
|
2020-11-16 15:52:19 +00:00
|
|
|
|
2021-09-02 16:07:23 +00:00
|
|
|
cst := store.NewChainStore(bs, bs, mds, filcns.Weight, j)
|
2020-11-16 22:39:08 +00:00
|
|
|
defer cst.Close() //nolint:errcheck
|
2020-01-21 01:53:55 +00:00
|
|
|
|
2020-09-28 10:28:12 +00:00
|
|
|
log.Infof("importing chain from %s...", fname)
|
|
|
|
|
|
|
|
bufr := bufio.NewReaderSize(rd, 1<<20)
|
2020-09-28 10:17:54 +00:00
|
|
|
|
2020-09-28 10:28:12 +00:00
|
|
|
bar := pb.New64(l)
|
|
|
|
br := bar.NewProxyReader(bufr)
|
2020-09-28 10:17:54 +00:00
|
|
|
bar.ShowTimeLeft = true
|
|
|
|
bar.ShowPercent = true
|
2020-09-28 10:28:12 +00:00
|
|
|
bar.ShowSpeed = true
|
2020-09-28 10:17:54 +00:00
|
|
|
bar.Units = pb.U_BYTES
|
|
|
|
|
|
|
|
bar.Start()
|
2021-12-17 09:42:09 +00:00
|
|
|
ts, err := cst.Import(ctx, br)
|
2020-09-28 10:17:54 +00:00
|
|
|
bar.Finish()
|
|
|
|
|
2020-01-21 01:53:55 +00:00
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("importing chain failed: %w", err)
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:42:09 +00:00
|
|
|
if err := cst.FlushValidationCache(ctx); err != nil {
|
2020-10-09 20:41:34 +00:00
|
|
|
return xerrors.Errorf("flushing validation cache failed: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-12-30 10:04:00 +00:00
|
|
|
gb, err := cst.GetTipsetByHeight(ctx, 0, ts, true)
|
2020-08-29 02:15:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-12-17 09:42:09 +00:00
|
|
|
err = cst.SetGenesis(ctx, gb.Blocks()[0])
|
2020-08-29 02:15:43 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-09-18 17:57:04 +00:00
|
|
|
// TODO: We need to supply the actual beacon after v14
|
|
|
|
stm, err := stmgr.NewStateManager(cst, filcns.NewTipSetExecutor(), vm.Syscalls(ffiwrapper.ProofVerifier), filcns.DefaultUpgradeSchedule(), nil)
|
2021-09-02 16:07:23 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-01-21 01:53:55 +00:00
|
|
|
|
2020-09-02 03:12:21 +00:00
|
|
|
if !snapshot {
|
|
|
|
log.Infof("validating imported chain...")
|
2020-12-30 10:04:00 +00:00
|
|
|
if err := stm.ValidateChain(ctx, ts); err != nil {
|
2020-09-02 03:12:21 +00:00
|
|
|
return xerrors.Errorf("chain validation failed: %w", err)
|
|
|
|
}
|
2020-01-21 01:53:55 +00:00
|
|
|
}
|
|
|
|
|
2020-10-09 20:41:34 +00:00
|
|
|
log.Infof("accepting %s as new head", ts.Cids())
|
2020-12-30 10:04:00 +00:00
|
|
|
if err := cst.ForceHeadSilent(ctx, ts); err != nil {
|
2020-01-21 01:53:55 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|