channeldb: ensure that when we delete a channel we delete entry in edge update index
In this commit, we ensure that all indexes for a particular channel have any relevant keys deleted once a channel is removed from the database. Before this commit, if we pruned a channel due to closing, then its entry in the channel update index would ever be removed.
This commit is contained in:
parent
55dfc17c05
commit
70dffe7e99
@ -586,6 +586,10 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
nodes, err := tx.CreateBucketIfNotExists(nodeBucket)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// For each of the outpoints that have been spent within the
|
// For each of the outpoints that have been spent within the
|
||||||
// block, we attempt to delete them from the graph as if that
|
// block, we attempt to delete them from the graph as if that
|
||||||
@ -619,8 +623,9 @@ func (c *ChannelGraph) PruneGraph(spentOutputs []*wire.OutPoint,
|
|||||||
// will be returned if that outpoint isn't known to be
|
// will be returned if that outpoint isn't known to be
|
||||||
// a channel. If no error is returned, then a channel
|
// a channel. If no error is returned, then a channel
|
||||||
// was successfully pruned.
|
// was successfully pruned.
|
||||||
err = delChannelByEdge(edges, edgeIndex, chanIndex,
|
err = delChannelByEdge(
|
||||||
chanPoint)
|
edges, edgeIndex, chanIndex, nodes, chanPoint,
|
||||||
|
)
|
||||||
if err != nil && err != ErrEdgeNotFound {
|
if err != nil && err != ErrEdgeNotFound {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -690,16 +695,18 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
edgeIndex, err := edges.CreateBucketIfNotExists(edgeIndexBucket)
|
edgeIndex, err := edges.CreateBucketIfNotExists(edgeIndexBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
chanIndex, err := edges.CreateBucketIfNotExists(channelPointBucket)
|
chanIndex, err := edges.CreateBucketIfNotExists(channelPointBucket)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
nodes, err := tx.CreateBucketIfNotExists(nodeBucket)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Scan from chanIDStart to chanIDEnd, deleting every
|
// Scan from chanIDStart to chanIDEnd, deleting every
|
||||||
// found edge.
|
// found edge.
|
||||||
@ -713,7 +720,7 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = delChannelByEdge(
|
err = delChannelByEdge(
|
||||||
edges, edgeIndex, chanIndex, &edgeInfo.ChannelPoint,
|
edges, edgeIndex, chanIndex, nodes, &edgeInfo.ChannelPoint,
|
||||||
)
|
)
|
||||||
if err != nil && err != ErrEdgeNotFound {
|
if err != nil && err != ErrEdgeNotFound {
|
||||||
return err
|
return err
|
||||||
@ -823,8 +830,12 @@ func (c *ChannelGraph) DeleteChannelEdge(chanPoint *wire.OutPoint) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
nodes, err := tx.CreateBucketIfNotExists(nodeBucket)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return delChannelByEdge(edges, edgeIndex, chanIndex, chanPoint)
|
return delChannelByEdge(edges, edgeIndex, chanIndex, nodes, chanPoint)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1236,38 +1247,76 @@ func (c *ChannelGraph) FetchChanInfos(chanIDs []uint64) ([]ChannelEdge, error) {
|
|||||||
return chanEdges, nil
|
return chanEdges, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func delEdgeUpdateIndexEntry(edgesBucket *bolt.Bucket, chanID uint64,
|
||||||
|
edge1, edge2 *ChannelEdgePolicy) error {
|
||||||
|
|
||||||
|
// First, we'll fetch the edge update index bucket which currently
|
||||||
|
// stores an entry for the channel we're about to delete.
|
||||||
|
updateIndex, err := edgesBucket.CreateBucketIfNotExists(
|
||||||
|
edgeUpdateIndexBucket,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now that we have the bucket, we'll attempt to construct a template
|
||||||
|
// for the index key: updateTime || chanid.
|
||||||
|
var indexKey [8 + 8]byte
|
||||||
|
byteOrder.PutUint64(indexKey[8:], chanID)
|
||||||
|
|
||||||
|
// With the template constructed, we'll attempt to delete an entry that
|
||||||
|
// would have been created by both edges: we'll alternate the update
|
||||||
|
// times, as one may had overridden the other.
|
||||||
|
if edge1 != nil {
|
||||||
|
byteOrder.PutUint64(indexKey[:8], uint64(edge1.LastUpdate.Unix()))
|
||||||
|
if err := updateIndex.Delete(indexKey[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We'll also attempt to delete the entry that may have been created by
|
||||||
|
// the second edge.
|
||||||
|
if edge2 != nil {
|
||||||
|
byteOrder.PutUint64(indexKey[:8], uint64(edge2.LastUpdate.Unix()))
|
||||||
|
if err := updateIndex.Delete(indexKey[:]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func delChannelByEdge(edges *bolt.Bucket, edgeIndex *bolt.Bucket,
|
func delChannelByEdge(edges *bolt.Bucket, edgeIndex *bolt.Bucket,
|
||||||
chanIndex *bolt.Bucket, chanPoint *wire.OutPoint) error {
|
chanIndex *bolt.Bucket, nodes *bolt.Bucket, chanPoint *wire.OutPoint) error {
|
||||||
var b bytes.Buffer
|
var b bytes.Buffer
|
||||||
if err := writeOutpoint(&b, chanPoint); err != nil {
|
if err := writeOutpoint(&b, chanPoint); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the channel's outpoint doesn't exist within the outpoint
|
// If the channel's outpoint doesn't exist within the outpoint index,
|
||||||
// index, then the edge does not exist.
|
// then the edge does not exist.
|
||||||
chanID := chanIndex.Get(b.Bytes())
|
chanID := chanIndex.Get(b.Bytes())
|
||||||
if chanID == nil {
|
if chanID == nil {
|
||||||
return ErrEdgeNotFound
|
return ErrEdgeNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we obtain the two public keys from the mapping:
|
// Otherwise we obtain the two public keys from the mapping: chanID ->
|
||||||
// chanID -> pubKey1 || pubKey2. With this, we can construct
|
// pubKey1 || pubKey2. With this, we can construct the keys which house
|
||||||
// the keys which house both of the directed edges for this
|
// both of the directed edges for this channel.
|
||||||
// channel.
|
|
||||||
nodeKeys := edgeIndex.Get(chanID)
|
nodeKeys := edgeIndex.Get(chanID)
|
||||||
if nodeKeys == nil {
|
if nodeKeys == nil {
|
||||||
return fmt.Errorf("could not find nodekeys for chanID %v",
|
return fmt.Errorf("could not find nodekeys for chanID %v",
|
||||||
chanID)
|
chanID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The edge key is of the format pubKey || chanID. First we
|
// The edge key is of the format pubKey || chanID. First we construct
|
||||||
// construct the latter half, populating the channel ID.
|
// the latter half, populating the channel ID.
|
||||||
var edgeKey [33 + 8]byte
|
var edgeKey [33 + 8]byte
|
||||||
copy(edgeKey[33:], chanID)
|
copy(edgeKey[33:], chanID)
|
||||||
|
|
||||||
// With the latter half constructed, copy over the first public
|
// With the latter half constructed, copy over the first public key to
|
||||||
// key to delete the edge in this direction, then the second to
|
// delete the edge in this direction, then the second to delete the
|
||||||
// delete the edge in the opposite direction.
|
// edge in the opposite direction.
|
||||||
copy(edgeKey[:33], nodeKeys[:33])
|
copy(edgeKey[:33], nodeKeys[:33])
|
||||||
if edges.Get(edgeKey[:]) != nil {
|
if edges.Get(edgeKey[:]) != nil {
|
||||||
if err := edges.Delete(edgeKey[:]); err != nil {
|
if err := edges.Delete(edgeKey[:]); err != nil {
|
||||||
@ -1281,8 +1330,21 @@ func delChannelByEdge(edges *bolt.Bucket, edgeIndex *bolt.Bucket,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, with the edge data deleted, we can purge the
|
// We'll also remove the entry in the edge update index bucket.
|
||||||
// information from the two edge indexes.
|
cid := byteOrder.Uint64(chanID)
|
||||||
|
edge1, edge2, err := fetchChanEdgePolicies(
|
||||||
|
edgeIndex, edges, nodes, chanID, nil,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = delEdgeUpdateIndexEntry(edges, cid, edge1, edge2)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, with the edge data deleted, we can purge the information
|
||||||
|
// from the two edge indexes.
|
||||||
if err := edgeIndex.Delete(chanID); err != nil {
|
if err := edgeIndex.Delete(chanID); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user