channeldb: fix DisconnectBlockAtHeight bug for zero-conf channels

When a block is disconnected due to a reorg, DisconnectBlockAtHeight
is called for the block height. Prior to this patch, it would delete
every SCID in the graph with a block height greater than the
disconnected height. This meant that a reorg would delete every
zero-conf channel edge from the graph. The fix simply iterates up
until the StartingAlias and deletes every SCID between the
disconnected height and the StartingAlias height.
This commit is contained in:
eugene 2023-01-05 17:38:59 -05:00
parent feb8e7e64e
commit d807ff23d2
No known key found for this signature in database
GPG Key ID: 118759E83439A9B1

View File

@ -20,6 +20,7 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/aliasmgr"
"github.com/lightningnetwork/lnd/batch"
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnwire"
@ -1525,12 +1526,10 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf
BlockHeight: height,
}
// Delete everything after this height from the db.
endShortChanID := lnwire.ShortChannelID{
BlockHeight: math.MaxUint32 & 0x00ffffff,
TxIndex: math.MaxUint32 & 0x00ffffff,
TxPosition: math.MaxUint16,
}
// Delete everything after this height from the db up until the
// SCID alias range.
endShortChanID := aliasmgr.StartingAlias
// The block height will be the 3 first bytes of the channel IDs.
var chanIDStart [8]byte
byteOrder.PutUint64(chanIDStart[:], startShortChanID.ToUint64())
@ -1569,11 +1568,14 @@ func (c *ChannelGraph) DisconnectBlockAtHeight(height uint32) ([]*ChannelEdgeInf
// found edge.
// NOTE: we must delete the edges after the cursor loop, since
// modifying the bucket while traversing is not safe.
// NOTE: We use a < comparison in bytes.Compare instead of <=
// so that the StartingAlias itself isn't deleted.
var keys [][]byte
cursor := edgeIndex.ReadWriteCursor()
for k, v := cursor.Seek(chanIDStart[:]); k != nil &&
bytes.Compare(k, chanIDEnd[:]) <= 0; k, v = cursor.Next() {
//nolint:lll
for k, v := cursor.Seek(chanIDStart[:]); k != nil &&
bytes.Compare(k, chanIDEnd[:]) < 0; k, v = cursor.Next() {
edgeInfoReader := bytes.NewReader(v)
edgeInfo, err := deserializeChanEdgeInfo(edgeInfoReader)
if err != nil {