diff --git a/cli/chain.go b/cli/chain.go index d00247364..ce1660641 100644 --- a/cli/chain.go +++ b/cli/chain.go @@ -337,25 +337,6 @@ var chainSetHeadCmd = &cli.Command{ }, } -func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.TipSet, error) { - var headers []*types.BlockHeader - for _, c := range vals { - blkc, err := cid.Decode(c) - if err != nil { - return nil, err - } - - bh, err := api.ChainGetBlock(ctx, blkc) - if err != nil { - return nil, err - } - - headers = append(headers, bh) - } - - return types.NewTipSet(headers) -} - var chainListCmd = &cli.Command{ Name: "list", Usage: "View a segment of the chain", diff --git a/cli/sync.go b/cli/sync.go index d92d6d7c6..bff34960e 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -5,6 +5,8 @@ import ( "fmt" "time" + "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/go-state-types/abi" cid "github.com/ipfs/go-cid" "github.com/urfave/cli/v2" @@ -22,6 +24,7 @@ var syncCmd = &cli.Command{ syncMarkBadCmd, syncUnmarkBadCmd, syncCheckBadCmd, + syncCheckpointCmd, }, } @@ -179,6 +182,48 @@ var syncCheckBadCmd = &cli.Command{ }, } +var syncCheckpointCmd = &cli.Command{ + Name: "checkpoint", + Usage: "mark a certain tipset as checkpointed; the node will never fork away from this tipset", + ArgsUsage: "[tipsetKey]", + Flags: []cli.Flag{ + &cli.Uint64Flag{ + Name: "epoch", + Usage: "checkpoint the tipset at the given epoch", + }, + }, + Action: func(cctx *cli.Context) error { + napi, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + var ts *types.TipSet + + if cctx.IsSet("epoch") { + ts, err = napi.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Uint64("epoch")), types.EmptyTSK) + } + if ts == nil { + ts, err = parseTipSet(ctx, napi, cctx.Args().Slice()) + } + if err != nil { + return err + } + + if ts == nil { + return fmt.Errorf("must pass cids for tipset to set as head, or specify epoch flag") + } + + if err := napi.SyncCheckpoint(ctx, ts.Key()); err != nil { + return err + } + + return nil + }, +} + func SyncWait(ctx context.Context, napi api.FullNode) error { for { state, err := napi.SyncState(ctx) diff --git a/cli/util.go b/cli/util.go new file mode 100644 index 000000000..4371f8bbc --- /dev/null +++ b/cli/util.go @@ -0,0 +1,28 @@ +package cli + +import ( + "context" + + "github.com/filecoin-project/lotus/api" + "github.com/filecoin-project/lotus/chain/types" + "github.com/ipfs/go-cid" +) + +func parseTipSet(ctx context.Context, api api.FullNode, vals []string) (*types.TipSet, error) { + var headers []*types.BlockHeader + for _, c := range vals { + blkc, err := cid.Decode(c) + if err != nil { + return nil, err + } + + bh, err := api.ChainGetBlock(ctx, blkc) + if err != nil { + return nil, err + } + + headers = append(headers, bh) + } + + return types.NewTipSet(headers) +}