diff --git a/api/api_full.go b/api/api_full.go index 7a477a874..034e8f996 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -164,6 +164,9 @@ type FullNode interface { // Use with extreme caution. SyncMarkBad(ctx context.Context, bcid cid.Cid) error + // SyncUnmarkBad unmarks a blocks as bad, making it possible to be validated and synced again. + SyncUnmarkBad(ctx context.Context, bcid cid.Cid) 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 bfd99ab0f..6361e60b3 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -107,6 +107,7 @@ type FullNodeStruct struct { SyncIncomingBlocks func(ctx context.Context) (<-chan *types.BlockHeader, error) `perm:"read"` 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"` SyncCheckBad func(ctx context.Context, bcid cid.Cid) (string, error) `perm:"read"` MpoolGetConfig func(context.Context) (*types.MpoolConfig, error) `perm:"read"` @@ -713,6 +714,10 @@ func (c *FullNodeStruct) SyncMarkBad(ctx context.Context, bcid cid.Cid) error { return c.Internal.SyncMarkBad(ctx, bcid) } +func (c *FullNodeStruct) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error { + return c.Internal.SyncUnmarkBad(ctx, bcid) +} + 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 103237307..3c5bf05ef 100644 --- a/chain/badtscache.go +++ b/chain/badtscache.go @@ -56,6 +56,10 @@ func (bts *BadBlockCache) Add(c cid.Cid, bbr BadBlockReason) { bts.badBlocks.Add(c, bbr) } +func (bts *BadBlockCache) Remove(c cid.Cid) { + bts.badBlocks.Remove(c) +} + 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 47c8c55c9..ccc97e12f 100644 --- a/chain/sync.go +++ b/chain/sync.go @@ -1680,6 +1680,11 @@ func (syncer *Syncer) MarkBad(blk cid.Cid) { syncer.bad.Add(blk, NewBadBlockReason([]cid.Cid{blk}, "manually marked bad")) } +// UnmarkBad manually adds a block to the "bad blocks" cache. +func (syncer *Syncer) UnmarkBad(blk cid.Cid) { + syncer.bad.Remove(blk) +} + func (syncer *Syncer) CheckBadBlockCache(blk cid.Cid) (string, bool) { bbr, ok := syncer.bad.Has(blk) return bbr.String(), ok diff --git a/node/impl/full/sync.go b/node/impl/full/sync.go index 9fe73220e..7f7fd48be 100644 --- a/node/impl/full/sync.go +++ b/node/impl/full/sync.go @@ -108,6 +108,12 @@ func (a *SyncAPI) SyncMarkBad(ctx context.Context, bcid cid.Cid) error { return nil } +func (a *SyncAPI) SyncUnmarkBad(ctx context.Context, bcid cid.Cid) error { + log.Warnf("Unmarking block %s as bad", bcid) + a.Syncer.UnmarkBad(bcid) + return nil +} + func (a *SyncAPI) SyncCheckBad(ctx context.Context, bcid cid.Cid) (string, error) { reason, ok := a.Syncer.CheckBadBlockCache(bcid) if !ok {