diff --git a/api/api_full.go b/api/api_full.go index 7ebc8791a..1311dac6a 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -172,6 +172,9 @@ type FullNode interface { // SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again. SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error + // SyncUnmarkAllBad purges bad block cache, making it possible to sync to chains previously marked as bad + SyncUnmarkAllBad(ctx context.Context) error + // SyncCheckBad checks if a block was marked as bad, and if it was, returns // the reason. SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 348e8a6de..6bfbf43cb 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -111,6 +111,7 @@ type FullNodeStruct struct { SyncCheckpoint func(ctx context.Context, key types.TipSetKey) error `perm:"admin"` SyncMarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` SyncUnmarkBad func(ctx context.Context, bcid cid.Cid) error `perm:"admin"` + SyncUnmarkAllBad func(ctx context.Context) error `perm:"admin"` SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"` SyncValidateTipset func(ctx context.Context, tsk types.TipSetKey) (bool, error) `perm:"read"` @@ -780,6 +781,10 @@ func (c *FullNodeStruct) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error return c.Internal.SyncUnmarkBad(ctx, bcid) } +func (c *FullNodeStruct) SyncUnmarkAllBad(ctx context.Context) error { + return c.Internal.SyncUnmarkAllBad(ctx) +} + func (c *FullNodeStruct) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) { return c.Internal.SyncCheckBad(ctx, bcid) } diff --git a/chain/badtscache.go b/chain/badtscache.go index 3c5bf05ef..42564128e 100644 --- a/chain/badtscache.go +++ b/chain/badtscache.go @@ -60,6 +60,10 @@ func (bts *BadBlockCache) Remove(c cid.Cid) { bts.badBlocks.Remove(c) } +func (bts *BadBlockCache) Purge() { + bts.badBlocks.Purge() +} + func (bts *BadBlockCache) Has(c cid.Cid) (BadBlockReason, bool) { rval, ok := bts.badBlocks.Get(c) if !ok { diff --git a/chain/sync.go b/chain/sync.go index 369c65d33..23688ecb7 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -1740,6 +1740,10 @@ func (syncer *Syncer) UnmarkBad(blk cid.Cid) { syncer.bad.Remove(blk) } +func (syncer *Syncer) UnmarkAllBad() { + syncer.bad.Purge() +} + func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) { bbr, ok := syncer.bad.Has(blk) return bbr.String(), ok diff --git a/cli/sync.go b/cli/sync.go index dea96d14e..a5178441d 100644 --- a/cli/sync.go +++ b/cli/sync.go @@ -124,6 +124,12 @@ var syncMarkBadCmd = &cli.Command{ var syncUnmarkBadCmd = &cli.Command{ Name: "unmark-bad", Usage: "Unmark the given block as bad, makes it possible to sync to a chain containing it", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "all", + Usage: "drop the entire bad block cache", + }, + }, ArgsUsage: "[blockCid]", Action: func(cctx *cli.Context) error { napi, closer, err := GetFullNodeAPI(cctx) @@ -133,6 +139,10 @@ var syncUnmarkBadCmd = &cli.Command{ defer closer() ctx := ReqContext(cctx) + if cctx.Bool("all") { + return napi.SyncUnmarkAllBad(ctx) + } + if !cctx.Args().Present() { return fmt.Errorf("must specify block cid to unmark") } diff --git a/node/impl/full/sync.go b/node/impl/full/sync.go index 1bd3af415..05d4c9cb7 100644 --- a/node/impl/full/sync.go +++ b/node/impl/full/sync.go @@ -118,6 +118,12 @@ func (a *SyncAPI) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error { return nil } +func (a *SyncAPI) SyncUnmarkAllBad(ctx context.Context) error { + log.Warnf("Dropping bad block cache") + a.Syncer.UnmarkAllBad() + return nil +} + func (a *SyncAPI) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) { reason, ok := a.Syncer.CheckBadBlockCache(bcid) if !ok {