@@ -7,8 +7,10 @@ import (
7
7
"encoding/hex"
8
8
"errors"
9
9
"fmt"
10
+ "maps"
10
11
"math"
11
12
"net"
13
+ "slices"
12
14
"strconv"
13
15
"sync"
14
16
"time"
@@ -92,6 +94,7 @@ type SQLQueries interface {
92
94
ListChannelsByNodeID (ctx context.Context , arg sqlc.ListChannelsByNodeIDParams ) ([]sqlc.ListChannelsByNodeIDRow , error )
93
95
ListChannelsWithPoliciesPaginated (ctx context.Context , arg sqlc.ListChannelsWithPoliciesPaginatedParams ) ([]sqlc.ListChannelsWithPoliciesPaginatedRow , error )
94
96
GetChannelsByPolicyLastUpdateRange (ctx context.Context , arg sqlc.GetChannelsByPolicyLastUpdateRangeParams ) ([]sqlc.GetChannelsByPolicyLastUpdateRangeRow , error )
97
+ GetPublicV1ChannelsBySCID (ctx context.Context , arg sqlc.GetPublicV1ChannelsBySCIDParams ) ([]sqlc.Channel , error )
95
98
96
99
CreateChannelExtraType (ctx context.Context , arg sqlc.CreateChannelExtraTypeParams ) error
97
100
InsertChannelFeature (ctx context.Context , arg sqlc.InsertChannelFeatureParams ) error
@@ -100,6 +103,7 @@ type SQLQueries interface {
100
103
Channel Policy table queries.
101
104
*/
102
105
UpsertEdgePolicy (ctx context.Context , arg sqlc.UpsertEdgePolicyParams ) (int64 , error )
106
+ GetChannelPolicyByChannelAndNode (ctx context.Context , arg sqlc.GetChannelPolicyByChannelAndNodeParams ) (sqlc.ChannelPolicy , error )
103
107
104
108
InsertChanPolicyExtraType (ctx context.Context , arg sqlc.InsertChanPolicyExtraTypeParams ) error
105
109
GetChannelPolicyExtraTypes (ctx context.Context , arg sqlc.GetChannelPolicyExtraTypesParams ) ([]sqlc.GetChannelPolicyExtraTypesRow , error )
@@ -1262,6 +1266,133 @@ func (s *SQLStore) ForEachChannel(cb func(*models.ChannelEdgeInfo,
1262
1266
}, sqldb .NoOpReset )
1263
1267
}
1264
1268
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
+
1265
1396
// forEachNodeDirectedChannel iterates through all channels of a given
1266
1397
// node, executing the passed callback on the directed edge representing the
1267
1398
// channel and its incoming policy. If the node is not found, no error is
0 commit comments