@@ -7,8 +7,10 @@ import (
77 "encoding/hex"
88 "errors"
99 "fmt"
10+ "maps"
1011 "math"
1112 "net"
13+ "slices"
1214 "strconv"
1315 "sync"
1416 "time"
@@ -92,6 +94,7 @@ type SQLQueries interface {
9294 ListChannelsByNodeID (ctx context.Context , arg sqlc.ListChannelsByNodeIDParams ) ([]sqlc.ListChannelsByNodeIDRow , error )
9395 ListChannelsWithPoliciesPaginated (ctx context.Context , arg sqlc.ListChannelsWithPoliciesPaginatedParams ) ([]sqlc.ListChannelsWithPoliciesPaginatedRow , error )
9496 GetChannelsByPolicyLastUpdateRange (ctx context.Context , arg sqlc.GetChannelsByPolicyLastUpdateRangeParams ) ([]sqlc.GetChannelsByPolicyLastUpdateRangeRow , error )
97+ GetPublicV1ChannelsBySCID (ctx context.Context , arg sqlc.GetPublicV1ChannelsBySCIDParams ) ([]sqlc.Channel , error )
9598
9699 CreateChannelExtraType (ctx context.Context , arg sqlc.CreateChannelExtraTypeParams ) error
97100 InsertChannelFeature (ctx context.Context , arg sqlc.InsertChannelFeatureParams ) error
@@ -100,6 +103,7 @@ type SQLQueries interface {
100103 Channel Policy table queries.
101104 */
102105 UpsertEdgePolicy (ctx context.Context , arg sqlc.UpsertEdgePolicyParams ) (int64 , error )
106+ GetChannelPolicyByChannelAndNode (ctx context.Context , arg sqlc.GetChannelPolicyByChannelAndNodeParams ) (sqlc.ChannelPolicy , error )
103107
104108 InsertChanPolicyExtraType (ctx context.Context , arg sqlc.InsertChanPolicyExtraTypeParams ) error
105109 GetChannelPolicyExtraTypes (ctx context.Context , arg sqlc.GetChannelPolicyExtraTypesParams ) ([]sqlc.GetChannelPolicyExtraTypesRow , error )
@@ -1262,6 +1266,133 @@ func (s *SQLStore) ForEachChannel(cb func(*models.ChannelEdgeInfo,
12621266 }, sqldb .NoOpReset )
12631267}
12641268
1269+ // FilterChannelRange returns the channel ID's of all known channels which were
1270+ // mined in a block height within the passed range. The channel IDs are grouped
1271+ // by their common block height. This method can be used to quickly share with a
1272+ // peer the set of channels we know of within a particular range to catch them
1273+ // up after a period of time offline. If withTimestamps is true then the
1274+ // timestamp info of the latest received channel update messages of the channel
1275+ // will be included in the response.
1276+ //
1277+ // NOTE: This is part of the V1Store interface.
1278+ func (s * SQLStore ) FilterChannelRange (startHeight , endHeight uint32 ,
1279+ withTimestamps bool ) ([]BlockChannelRange , error ) {
1280+
1281+ var (
1282+ ctx = context .TODO ()
1283+ startSCID = & lnwire.ShortChannelID {
1284+ BlockHeight : startHeight ,
1285+ }
1286+ endSCID = lnwire.ShortChannelID {
1287+ BlockHeight : endHeight ,
1288+ TxIndex : math .MaxUint32 & 0x00ffffff ,
1289+ TxPosition : math .MaxUint16 ,
1290+ }
1291+ )
1292+
1293+ var chanIDStart [8 ]byte
1294+ byteOrder .PutUint64 (chanIDStart [:], startSCID .ToUint64 ())
1295+ var chanIDEnd [8 ]byte
1296+ byteOrder .PutUint64 (chanIDEnd [:], endSCID .ToUint64 ())
1297+
1298+ // 1) get all channels where channelID is between start and end chan ID.
1299+ // 2) skip if not public (ie, no channel_proof)
1300+ // 3) collect that channel.
1301+ // 4) if timestamps are wanted, fetch both policies for node 1 and node2
1302+ // and add those timestamps to the collected channel.
1303+ channelsPerBlock := make (map [uint32 ][]ChannelUpdateInfo )
1304+ err := s .db .ExecTx (ctx , sqldb .ReadTxOpt (), func (db SQLQueries ) error {
1305+ dbChans , err := db .GetPublicV1ChannelsBySCID (
1306+ ctx , sqlc.GetPublicV1ChannelsBySCIDParams {
1307+ StartScid : chanIDStart [:],
1308+ EndScid : chanIDEnd [:],
1309+ },
1310+ )
1311+ if err != nil {
1312+ return fmt .Errorf ("unable to fetch channel range: %w" ,
1313+ err )
1314+ }
1315+
1316+ for _ , dbChan := range dbChans {
1317+ cid := lnwire .NewShortChanIDFromInt (
1318+ byteOrder .Uint64 (dbChan .Scid ),
1319+ )
1320+ chanInfo := NewChannelUpdateInfo (
1321+ cid , time.Time {}, time.Time {},
1322+ )
1323+
1324+ if ! withTimestamps {
1325+ channelsPerBlock [cid .BlockHeight ] = append (
1326+ channelsPerBlock [cid .BlockHeight ],
1327+ chanInfo ,
1328+ )
1329+
1330+ continue
1331+ }
1332+
1333+ //nolint:ll
1334+ node1Policy , err := db .GetChannelPolicyByChannelAndNode (
1335+ ctx , sqlc.GetChannelPolicyByChannelAndNodeParams {
1336+ Version : int16 (ProtocolV1 ),
1337+ ChannelID : dbChan .ID ,
1338+ NodeID : dbChan .NodeID1 ,
1339+ },
1340+ )
1341+ if err != nil && ! errors .Is (err , sql .ErrNoRows ) {
1342+ return fmt .Errorf ("unable to fetch node1 " +
1343+ "policy: %w" , err )
1344+ } else if err == nil {
1345+ chanInfo .Node1UpdateTimestamp = time .Unix (
1346+ node1Policy .LastUpdate .Int64 , 0 ,
1347+ )
1348+ }
1349+
1350+ //nolint:ll
1351+ node2Policy , err := db .GetChannelPolicyByChannelAndNode (
1352+ ctx , sqlc.GetChannelPolicyByChannelAndNodeParams {
1353+ Version : int16 (ProtocolV1 ),
1354+ ChannelID : dbChan .ID ,
1355+ NodeID : dbChan .NodeID2 ,
1356+ },
1357+ )
1358+ if err != nil && ! errors .Is (err , sql .ErrNoRows ) {
1359+ return fmt .Errorf ("unable to fetch node2 " +
1360+ "policy: %w" , err )
1361+ } else if err == nil {
1362+ chanInfo .Node2UpdateTimestamp = time .Unix (
1363+ node2Policy .LastUpdate .Int64 , 0 ,
1364+ )
1365+ }
1366+
1367+ channelsPerBlock [cid .BlockHeight ] = append (
1368+ channelsPerBlock [cid .BlockHeight ], chanInfo ,
1369+ )
1370+ }
1371+
1372+ return nil
1373+ }, func () {
1374+ channelsPerBlock = make (map [uint32 ][]ChannelUpdateInfo )
1375+ })
1376+ if err != nil {
1377+ return nil , fmt .Errorf ("unable to fetch channel range: %w" , err )
1378+ }
1379+
1380+ if len (channelsPerBlock ) == 0 {
1381+ return nil , nil
1382+ }
1383+
1384+ // Return the channel ranges in ascending block height order.
1385+ blocks := slices .Collect (maps .Keys (channelsPerBlock ))
1386+ slices .Sort (blocks )
1387+
1388+ return fn .Map (blocks , func (block uint32 ) BlockChannelRange {
1389+ return BlockChannelRange {
1390+ Height : block ,
1391+ Channels : channelsPerBlock [block ],
1392+ }
1393+ }), nil
1394+ }
1395+
12651396// forEachNodeDirectedChannel iterates through all channels of a given
12661397// node, executing the passed callback on the directed edge representing the
12671398// channel and its incoming policy. If the node is not found, no error is
0 commit comments