package chain import ( "context" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/types" ) func (syncer *Syncer) SyncCheckpoint(ctx context.Context, tsk types.TipSetKey) error { if tsk == types.EmptyTSK { return xerrors.Errorf("called with empty tsk") } ts, err := syncer.ChainStore().LoadTipSet(ctx, tsk) if err != nil { tss, err := syncer.Exchange.GetBlocks(ctx, tsk, 1) if err != nil { return xerrors.Errorf("failed to fetch tipset: %w", err) } else if len(tss) != 1 { return xerrors.Errorf("expected 1 tipset, got %d", len(tss)) } ts = tss[0] } if err := syncer.switchChain(ctx, ts); err != nil { return xerrors.Errorf("failed to switch chain when syncing checkpoint: %w", err) } if err := syncer.ChainStore().SetCheckpoint(ctx, ts); err != nil { return xerrors.Errorf("failed to set the chain checkpoint: %w", err) } return nil } func (syncer *Syncer) switchChain(ctx context.Context, ts *types.TipSet) error { hts := syncer.ChainStore().GetHeaviestTipSet() if hts.Equals(ts) { return nil } if anc, err := syncer.store.IsAncestorOf(ctx, ts, hts); err == nil && anc { return nil } // Otherwise, sync the chain and set the head. if err := syncer.collectChain(ctx, ts, hts, true); err != nil { return xerrors.Errorf("failed to collect chain for checkpoint: %w", err) } if err := syncer.ChainStore().SetHead(ctx, ts); err != nil { return xerrors.Errorf("failed to set the chain head: %w", err) } return nil }