diff --git a/channeldb/graph.go b/channeldb/graph.go index fac89017..b3d1924c 100644 --- a/channeldb/graph.go +++ b/channeldb/graph.go @@ -3397,6 +3397,38 @@ func (c *ChannelGraph) NewChannelEdgePolicy() *ChannelEdgePolicy { return &ChannelEdgePolicy{db: c.db} } +// MarkEdgeZombie attempts to mark a channel identified by its channel ID as a +// zombie. This method is used on an ad-hoc basis, when channels need to be +// marked as zombies outside the normal pruning cycle. +func (c *ChannelGraph) MarkEdgeZombie(chanID uint64, + pubKey1, pubKey2 [33]byte) error { + + c.cacheMu.Lock() + defer c.cacheMu.Unlock() + + err := kvdb.Batch(c.db, func(tx kvdb.RwTx) error { + edges := tx.ReadWriteBucket(edgeBucket) + if edges == nil { + return ErrGraphNoEdgesFound + } + zombieIndex, err := edges.CreateBucketIfNotExists(zombieBucket) + if err != nil { + return fmt.Errorf("unable to create zombie "+ + "bucket: %w", err) + } + + return markEdgeZombie(zombieIndex, chanID, pubKey1, pubKey2) + }) + if err != nil { + return err + } + + c.rejectCache.remove(chanID) + c.chanCache.remove(chanID) + + return nil +} + // markEdgeZombie marks an edge as a zombie within our zombie index. The public // keys should represent the node public keys of the two parties involved in the // edge. diff --git a/channeldb/graph_test.go b/channeldb/graph_test.go index 0708c3ad..b19ea82f 100644 --- a/channeldb/graph_test.go +++ b/channeldb/graph_test.go @@ -3045,6 +3045,20 @@ func TestGraphZombieIndex(t *testing.T) { t.Fatal("expected edge to not be marked as zombie") } assertNumZombies(t, graph, 0) + + // If we mark the edge as a zombie manually, then it should show up as + // being a zombie once again. + err = graph.MarkEdgeZombie( + edge.ChannelID, node1.PubKeyBytes, node2.PubKeyBytes, + ) + if err != nil { + t.Fatalf("unable to mark edge as zombie: %v", err) + } + isZombie, _, _ = graph.IsZombieEdge(edge.ChannelID) + if !isZombie { + t.Fatal("expected edge to be marked as zombie") + } + assertNumZombies(t, graph, 1) } // compareNodes is used to compare two LightningNodes while excluding the