9
9
"fmt"
10
10
"math"
11
11
"net"
12
+ "sort"
12
13
"strconv"
13
14
"sync"
14
15
"time"
@@ -92,6 +93,7 @@ type SQLQueries interface {
92
93
ListChannelsByNodeID (ctx context.Context , arg sqlc.ListChannelsByNodeIDParams ) ([]sqlc.ListChannelsByNodeIDRow , error )
93
94
ListChannelsPaginated (ctx context.Context , arg sqlc.ListChannelsPaginatedParams ) ([]sqlc.ListChannelsPaginatedRow , error )
94
95
GetChannelsByPolicyLastUpdateRange (ctx context.Context , arg sqlc.GetChannelsByPolicyLastUpdateRangeParams ) ([]sqlc.GetChannelsByPolicyLastUpdateRangeRow , error )
96
+ GetPublicV1ChannelsBySCID (ctx context.Context , arg sqlc.GetPublicV1ChannelsBySCIDParams ) ([]sqlc.Channel , error )
95
97
96
98
CreateChannelExtraType (ctx context.Context , arg sqlc.CreateChannelExtraTypeParams ) error
97
99
InsertChannelFeature (ctx context.Context , arg sqlc.InsertChannelFeatureParams ) error
@@ -100,6 +102,7 @@ type SQLQueries interface {
100
102
Channel Policy table queries.
101
103
*/
102
104
UpsertEdgePolicy (ctx context.Context , arg sqlc.UpsertEdgePolicyParams ) (int64 , error )
105
+ GetChannelPolicyByChannelAndNode (ctx context.Context , arg sqlc.GetChannelPolicyByChannelAndNodeParams ) (sqlc.ChannelPolicy , error )
103
106
104
107
InsertChanPolicyExtraType (ctx context.Context , arg sqlc.InsertChanPolicyExtraTypeParams ) error
105
108
GetChannelPolicyExtraTypes (ctx context.Context , arg sqlc.GetChannelPolicyExtraTypesParams ) ([]sqlc.GetChannelPolicyExtraTypesRow , error )
@@ -1258,6 +1261,141 @@ func (s *SQLStore) ForEachChannel(cb func(*models.ChannelEdgeInfo,
1258
1261
}, sqldb .NoOpReset )
1259
1262
}
1260
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 := make ([]uint32 , 0 , len (channelsPerBlock ))
1381
+ for block := range channelsPerBlock {
1382
+ blocks = append (blocks , block )
1383
+ }
1384
+ sort .Slice (blocks , func (i , j int ) bool {
1385
+ return blocks [i ] < blocks [j ]
1386
+ })
1387
+
1388
+ channelRanges := make ([]BlockChannelRange , 0 , len (channelsPerBlock ))
1389
+ for _ , block := range blocks {
1390
+ channelRanges = append (channelRanges , BlockChannelRange {
1391
+ Height : block ,
1392
+ Channels : channelsPerBlock [block ],
1393
+ })
1394
+ }
1395
+
1396
+ return channelRanges , nil
1397
+ }
1398
+
1261
1399
// forEachNodeDirectedChannel iterates through all channels of a given
1262
1400
// node, executing the passed callback on the directed edge representing the
1263
1401
// channel and its incoming policy. If the node is not found, no error is
0 commit comments