@@ -97,6 +97,7 @@ type SQLQueries interface {
97
97
GetChannelsByPolicyLastUpdateRange (ctx context.Context , arg sqlc.GetChannelsByPolicyLastUpdateRangeParams ) ([]sqlc.GetChannelsByPolicyLastUpdateRangeRow , error )
98
98
GetChannelByOutpointWithPolicies (ctx context.Context , arg sqlc.GetChannelByOutpointWithPoliciesParams ) (sqlc.GetChannelByOutpointWithPoliciesRow , error )
99
99
GetPublicV1ChannelsBySCID (ctx context.Context , arg sqlc.GetPublicV1ChannelsBySCIDParams ) ([]sqlc.Channel , error )
100
+ GetSCIDByOutpoint (ctx context.Context , arg sqlc.GetSCIDByOutpointParams ) ([]byte , error )
100
101
DeleteChannel (ctx context.Context , id int64 ) error
101
102
102
103
CreateChannelExtraType (ctx context.Context , arg sqlc.CreateChannelExtraTypeParams ) error
@@ -1833,6 +1834,162 @@ func (s *SQLStore) FetchChannelEdgesByOutpoint(op *wire.OutPoint) (
1833
1834
return edge , policy1 , policy2 , nil
1834
1835
}
1835
1836
1837
+ // HasChannelEdge returns true if the database knows of a channel edge with the
1838
+ // passed channel ID, and false otherwise. If an edge with that ID is found
1839
+ // within the graph, then two time stamps representing the last time the edge
1840
+ // was updated for both directed edges are returned along with the boolean. If
1841
+ // it is not found, then the zombie index is checked and its result is returned
1842
+ // as the second boolean.
1843
+ //
1844
+ // NOTE: part of the V1Store interface.
1845
+ func (s * SQLStore ) HasChannelEdge (chanID uint64 ) (time.Time , time.Time , bool ,
1846
+ bool , error ) {
1847
+
1848
+ ctx := context .TODO ()
1849
+
1850
+ var (
1851
+ exists bool
1852
+ isZombie bool
1853
+ node1LastUpdate time.Time
1854
+ node2LastUpdate time.Time
1855
+ )
1856
+
1857
+ // We'll query the cache with the shared lock held to allow multiple
1858
+ // readers to access values in the cache concurrently if they exist.
1859
+ s .cacheMu .RLock ()
1860
+ if entry , ok := s .rejectCache .get (chanID ); ok {
1861
+ s .cacheMu .RUnlock ()
1862
+ node1LastUpdate = time .Unix (entry .upd1Time , 0 )
1863
+ node2LastUpdate = time .Unix (entry .upd2Time , 0 )
1864
+ exists , isZombie = entry .flags .unpack ()
1865
+
1866
+ return node1LastUpdate , node2LastUpdate , exists , isZombie , nil
1867
+ }
1868
+ s .cacheMu .RUnlock ()
1869
+
1870
+ s .cacheMu .Lock ()
1871
+ defer s .cacheMu .Unlock ()
1872
+
1873
+ // The item was not found with the shared lock, so we'll acquire the
1874
+ // exclusive lock and check the cache again in case another method added
1875
+ // the entry to the cache while no lock was held.
1876
+ if entry , ok := s .rejectCache .get (chanID ); ok {
1877
+ node1LastUpdate = time .Unix (entry .upd1Time , 0 )
1878
+ node2LastUpdate = time .Unix (entry .upd2Time , 0 )
1879
+ exists , isZombie = entry .flags .unpack ()
1880
+
1881
+ return node1LastUpdate , node2LastUpdate , exists , isZombie , nil
1882
+ }
1883
+
1884
+ err := s .db .ExecTx (ctx , sqldb .ReadTxOpt (), func (db SQLQueries ) error {
1885
+ var chanIDB [8 ]byte
1886
+ byteOrder .PutUint64 (chanIDB [:], chanID )
1887
+
1888
+ channel , err := db .GetChannelBySCID (
1889
+ ctx , sqlc.GetChannelBySCIDParams {
1890
+ Scid : chanIDB [:],
1891
+ Version : int16 (ProtocolV1 ),
1892
+ },
1893
+ )
1894
+ if errors .Is (err , sql .ErrNoRows ) {
1895
+ // Check if it is a zombie channel.
1896
+ isZombie , err = db .IsZombieChannel (
1897
+ ctx , sqlc.IsZombieChannelParams {
1898
+ Scid : chanIDB [:],
1899
+ Version : int16 (ProtocolV1 ),
1900
+ },
1901
+ )
1902
+ if err != nil {
1903
+ return fmt .Errorf ("could not check if channel " +
1904
+ "is zombie: %w" , err )
1905
+ }
1906
+
1907
+ return nil
1908
+ } else if err != nil {
1909
+ return fmt .Errorf ("unable to fetch channel: %w" , err )
1910
+ }
1911
+
1912
+ exists = true
1913
+
1914
+ policy1 , err := db .GetChannelPolicyByChannelAndNode (
1915
+ ctx , sqlc.GetChannelPolicyByChannelAndNodeParams {
1916
+ Version : int16 (ProtocolV1 ),
1917
+ ChannelID : channel .ID ,
1918
+ NodeID : channel .NodeID1 ,
1919
+ },
1920
+ )
1921
+ if err != nil && ! errors .Is (err , sql .ErrNoRows ) {
1922
+ return fmt .Errorf ("unable to fetch channel policy: %w" ,
1923
+ err )
1924
+ } else if err == nil {
1925
+ node1LastUpdate = time .Unix (policy1 .LastUpdate .Int64 , 0 )
1926
+ }
1927
+
1928
+ policy2 , err := db .GetChannelPolicyByChannelAndNode (
1929
+ ctx , sqlc.GetChannelPolicyByChannelAndNodeParams {
1930
+ Version : int16 (ProtocolV1 ),
1931
+ ChannelID : channel .ID ,
1932
+ NodeID : channel .NodeID2 ,
1933
+ },
1934
+ )
1935
+ if err != nil && ! errors .Is (err , sql .ErrNoRows ) {
1936
+ return fmt .Errorf ("unable to fetch channel policy: %w" ,
1937
+ err )
1938
+ } else if err == nil {
1939
+ node2LastUpdate = time .Unix (policy2 .LastUpdate .Int64 , 0 )
1940
+ }
1941
+
1942
+ return nil
1943
+ }, sqldb .NoOpReset )
1944
+ if err != nil {
1945
+ return time.Time {}, time.Time {}, false , false ,
1946
+ fmt .Errorf ("unable to fetch channel: %w" , err )
1947
+ }
1948
+
1949
+ s .rejectCache .insert (chanID , rejectCacheEntry {
1950
+ upd1Time : node1LastUpdate .Unix (),
1951
+ upd2Time : node2LastUpdate .Unix (),
1952
+ flags : packRejectFlags (exists , isZombie ),
1953
+ })
1954
+
1955
+ return node1LastUpdate , node2LastUpdate , exists , isZombie , nil
1956
+ }
1957
+
1958
+ // ChannelID attempt to lookup the 8-byte compact channel ID which maps to the
1959
+ // passed channel point (outpoint). If the passed channel doesn't exist within
1960
+ // the database, then ErrEdgeNotFound is returned.
1961
+ //
1962
+ // NOTE: part of the V1Store interface.
1963
+ func (s * SQLStore ) ChannelID (chanPoint * wire.OutPoint ) (uint64 , error ) {
1964
+ var (
1965
+ ctx = context .TODO ()
1966
+ channelID uint64
1967
+ )
1968
+ err := s .db .ExecTx (ctx , sqldb .ReadTxOpt (), func (db SQLQueries ) error {
1969
+ chanID , err := db .GetSCIDByOutpoint (
1970
+ ctx , sqlc.GetSCIDByOutpointParams {
1971
+ Outpoint : chanPoint .String (),
1972
+ Version : int16 (ProtocolV1 ),
1973
+ },
1974
+ )
1975
+ if errors .Is (err , sql .ErrNoRows ) {
1976
+ return ErrEdgeNotFound
1977
+ } else if err != nil {
1978
+ return fmt .Errorf ("unable to fetch channel ID: %w" ,
1979
+ err )
1980
+ }
1981
+
1982
+ channelID = byteOrder .Uint64 (chanID )
1983
+
1984
+ return nil
1985
+ }, sqldb .NoOpReset )
1986
+ if err != nil {
1987
+ return 0 , fmt .Errorf ("unable to fetch channel ID: %w" , err )
1988
+ }
1989
+
1990
+ return channelID , nil
1991
+ }
1992
+
1836
1993
// forEachNodeDirectedChannel iterates through all channels of a given
1837
1994
// node, executing the passed callback on the directed edge representing the
1838
1995
// channel and its incoming policy. If the node is not found, no error is
@@ -3234,6 +3391,46 @@ func extractChannelPolicies(row any) (*sqlc.ChannelPolicy, *sqlc.ChannelPolicy,
3234
3391
3235
3392
var policy1 , policy2 * sqlc.ChannelPolicy
3236
3393
switch r := row .(type ) {
3394
+ case sqlc.GetChannelByOutpointWithPoliciesRow :
3395
+ if r .Policy1ID .Valid {
3396
+ policy1 = & sqlc.ChannelPolicy {
3397
+ ID : r .Policy1ID .Int64 ,
3398
+ Version : r .Policy1Version .Int16 ,
3399
+ ChannelID : r .Channel .ID ,
3400
+ NodeID : r .Policy1NodeID .Int64 ,
3401
+ Timelock : r .Policy1Timelock .Int32 ,
3402
+ FeePpm : r .Policy1FeePpm .Int64 ,
3403
+ BaseFeeMsat : r .Policy1BaseFeeMsat .Int64 ,
3404
+ MinHtlcMsat : r .Policy1MinHtlcMsat .Int64 ,
3405
+ MaxHtlcMsat : r .Policy1MaxHtlcMsat ,
3406
+ LastUpdate : r .Policy1LastUpdate ,
3407
+ InboundBaseFeeMsat : r .Policy1InboundBaseFeeMsat ,
3408
+ InboundFeeRateMilliMsat : r .Policy1InboundFeeRateMilliMsat ,
3409
+ Disabled : r .Policy1Disabled ,
3410
+ Signature : r .Policy1Signature ,
3411
+ }
3412
+ }
3413
+ if r .Policy2ID .Valid {
3414
+ policy2 = & sqlc.ChannelPolicy {
3415
+ ID : r .Policy2ID .Int64 ,
3416
+ Version : r .Policy2Version .Int16 ,
3417
+ ChannelID : r .Channel .ID ,
3418
+ NodeID : r .Policy2NodeID .Int64 ,
3419
+ Timelock : r .Policy2Timelock .Int32 ,
3420
+ FeePpm : r .Policy2FeePpm .Int64 ,
3421
+ BaseFeeMsat : r .Policy2BaseFeeMsat .Int64 ,
3422
+ MinHtlcMsat : r .Policy2MinHtlcMsat .Int64 ,
3423
+ MaxHtlcMsat : r .Policy2MaxHtlcMsat ,
3424
+ LastUpdate : r .Policy2LastUpdate ,
3425
+ InboundBaseFeeMsat : r .Policy2InboundBaseFeeMsat ,
3426
+ InboundFeeRateMilliMsat : r .Policy2InboundFeeRateMilliMsat ,
3427
+ Disabled : r .Policy2Disabled ,
3428
+ Signature : r .Policy2Signature ,
3429
+ }
3430
+ }
3431
+
3432
+ return policy1 , policy2 , nil
3433
+
3237
3434
case sqlc.GetChannelBySCIDWithPoliciesRow :
3238
3435
if r .Policy1ID .Valid {
3239
3436
policy1 = & sqlc.ChannelPolicy {
0 commit comments