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