Skip to content

Commit

Permalink
channeldb: add PutClosedScid and IsClosedScid
Browse files Browse the repository at this point in the history
This commit adds the ability to store closed channels by scid in
the database. This will allow the gossiper to ignore channel
announcements for closed channels without having to do any
expensive validation.
  • Loading branch information
Crypt-iQ committed Aug 27, 2024
1 parent 8939a21 commit 199e83d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 0 deletions.
4 changes: 4 additions & 0 deletions channeldb/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ var (
// created.
ErrMetaNotFound = fmt.Errorf("unable to locate meta information")

// ErrClosedScidsNotFound is returned when the closed scid bucket
// hasn't been created.
ErrClosedScidsNotFound = fmt.Errorf("closed scid bucket doesn't exist")

// ErrGraphNotFound is returned when at least one of the components of
// graph doesn't exist.
ErrGraphNotFound = fmt.Errorf("graph bucket not initialized")
Expand Down
56 changes: 56 additions & 0 deletions channeldb/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ var (
// case we'll remove all entries from the prune log with a block height
// that no longer exists.
pruneLogBucket = []byte("prune-log")

// closedScidBucket is a top-level bucket that stores scids for
// channels that we know to be closed. This is used so that we don't
// need to perform expensive validation checks if we receive a channel
// announcement for the channel again.
//
// maps: scid -> []byte{}
closedScidBucket = []byte("closed-scid")
)

const (
Expand Down Expand Up @@ -318,6 +326,7 @@ var graphTopLevelBuckets = [][]byte{
nodeBucket,
edgeBucket,
graphMetaBucket,
closedScidBucket,
}

// Wipe completely deletes all saved state within all used buckets within the
Expand Down Expand Up @@ -3884,6 +3893,53 @@ func (c *ChannelGraph) NumZombies() (uint64, error) {
return numZombies, nil
}

// PutClosedScid stores a SCID for a closed channel in the database. This is so
// that we can ignore channel announcements that we know to be closed without
// having to validate them and fetch a block.
func (c *ChannelGraph) PutClosedScid(scid lnwire.ShortChannelID) error {
return kvdb.Update(c.db, func(tx kvdb.RwTx) error {
closedScids, err := tx.CreateTopLevelBucket(closedScidBucket)
if err != nil {
return err
}

var k [8]byte
byteOrder.PutUint64(k[:], scid.ToUint64())

return closedScids.Put(k[:], []byte{})
}, func() {})
}

// IsClosedScid checks whether a channel identified by the passed in scid is
// closed. This helps avoid having to perform expensive validation checks.
// TODO: Add an LRU cache to cut down on disc reads.
func (c *ChannelGraph) IsClosedScid(scid lnwire.ShortChannelID) (bool, error) {
var isClosed bool
err := kvdb.View(c.db, func(tx kvdb.RTx) error {
closedScids := tx.ReadBucket(closedScidBucket)
if closedScids == nil {
return ErrClosedScidsNotFound
}

var k [8]byte
byteOrder.PutUint64(k[:], scid.ToUint64())

if closedScids.Get(k[:]) != nil {
isClosed = true
return nil
}

return nil
}, func() {
isClosed = false
})
if err != nil {
return false, err
}

return isClosed, nil
}

func putLightningNode(nodeBucket kvdb.RwBucket, aliasBucket kvdb.RwBucket, // nolint:dupl
updateIndex kvdb.RwBucket, node *LightningNode) error {

Expand Down
25 changes: 25 additions & 0 deletions channeldb/graph_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4037,3 +4037,28 @@ func TestGraphLoading(t *testing.T) {
graphReloaded.graphCache.nodeFeatures,
)
}

// TestClosedScid tests that we can correctly insert a SCID into the index of
// closed short channel ids.
func TestClosedScid(t *testing.T) {
t.Parallel()

graph, err := MakeTestGraph(t)
require.Nil(t, err)

scid := lnwire.ShortChannelID{}

// The scid should not exist in the closedScidBucket.
exists, err := graph.IsClosedScid(scid)
require.Nil(t, err)
require.False(t, exists)

// After we call PutClosedScid, the call to IsClosedScid should return
// true.
err = graph.PutClosedScid(scid)
require.Nil(t, err)

exists, err = graph.IsClosedScid(scid)
require.Nil(t, err)
require.True(t, exists)
}

0 comments on commit 199e83d

Please sign in to comment.