2024-01-31 15:03:11 +10:30
# include "config.h"
# include <bitcoin/script.h>
2024-02-11 21:03:41 +10:30
# include <ccan/array_size/array_size.h>
2024-01-31 15:03:11 +10:30
# include <ccan/mem/mem.h>
# include <ccan/tal/str/str.h>
# include <common/daemon_conn.h>
# include <common/gossip_store.h>
2024-01-31 16:02:25 +10:30
# include <common/gossmap.h>
2024-01-31 15:03:11 +10:30
# include <common/status.h>
2024-01-31 15:03:11 +10:30
# include <common/timeout.h>
2024-01-31 15:03:11 +10:30
# include <common/wire_error.h>
# include <errno.h>
# include <fcntl.h>
2024-01-31 16:02:25 +10:30
# include <gossipd/gossip_store.h>
# include <gossipd/gossip_store_wiregen.h>
2024-01-31 15:03:11 +10:30
# include <gossipd/gossipd.h>
# include <gossipd/gossipd_wiregen.h>
2024-01-31 16:02:25 +10:30
# include <gossipd/gossmap_manage.h>
2024-01-31 15:03:11 +10:30
# include <gossipd/seeker.h>
# include <gossipd/sigcheck.h>
# include <gossipd/txout_failures.h>
# include <string.h>
struct pending_cannounce {
const u8 * scriptpubkey ;
const u8 * channel_announcement ;
2024-02-11 21:03:41 +10:30
struct node_id node_id [ 2 ] ;
2024-01-31 15:03:11 +10:30
const struct node_id * source_peer ;
} ;
struct pending_cupdate {
struct short_channel_id scid ;
secp256k1_ecdsa_signature signature ;
u8 message_flags ;
u8 channel_flags ;
u16 cltv_expiry_delta ;
struct amount_msat htlc_minimum_msat , htlc_maximum_msat ;
u32 fee_base_msat , fee_proportional_millionths ;
u32 timestamp ;
const u8 * update ;
const struct node_id * source_peer ;
} ;
struct pending_nannounce {
struct node_id node_id ;
u32 timestamp ;
const u8 * nannounce ;
const struct node_id * source_peer ;
} ;
2024-01-31 15:03:12 +10:30
struct cannounce_map {
UINTMAP ( struct pending_cannounce * ) map ;
size_t count ;
/* Name, for flood reporting */
const char * name ;
bool flood_reported ;
} ;
2024-01-31 15:03:11 +10:30
struct gossmap_manage {
struct daemon * daemon ;
/* For us to write to gossip_store */
int fd ;
/* gossip map itself (access via gossmap_manage_get_gossmap, so it's fresh!) */
struct gossmap * raw_gossmap ;
/* Announcements we're checking, indexed by scid */
2024-01-31 15:03:12 +10:30
struct cannounce_map pending_ann_map ;
2024-01-31 15:03:11 +10:30
/* Updates we've deferred for above */
struct pending_cupdate * * pending_cupdates ;
/* Announcements which are too early to check. */
2024-01-31 15:03:12 +10:30
struct cannounce_map early_ann_map ;
2024-01-31 15:03:11 +10:30
struct pending_cupdate * * early_cupdates ;
/* Node announcements (waiting for a pending_cannounce maybe) */
struct pending_nannounce * * pending_nannounces ;
/* Lookups we've failed recently */
struct txout_failures * txf ;
/* Blockheights of scids to remove */
2024-01-31 16:38:20 +10:30
struct chan_dying * dying_channels ;
2024-01-31 15:03:11 +10:30
/* Occasional check for dead channels */
struct oneshot * prune_timer ;
2024-01-31 15:03:11 +10:30
} ;
2024-01-31 15:03:11 +10:30
/* Timer recursion */
static void start_prune_timer ( struct gossmap_manage * gm ) ;
2024-01-31 15:03:11 +10:30
static void enqueue_cupdate ( struct pending_cupdate * * * queue ,
struct short_channel_id scid ,
const secp256k1_ecdsa_signature * signature ,
u8 message_flags ,
u8 channel_flags ,
u16 cltv_expiry_delta ,
struct amount_msat htlc_minimum_msat ,
struct amount_msat htlc_maximum_msat ,
u32 fee_base_msat ,
u32 fee_proportional_millionths ,
u32 timestamp ,
const u8 * update TAKES ,
const struct node_id * source_peer TAKES )
{
struct pending_cupdate * pcu = tal ( * queue , struct pending_cupdate ) ;
pcu - > scid = scid ;
pcu - > signature = * signature ;
pcu - > message_flags = message_flags ;
pcu - > channel_flags = channel_flags ;
pcu - > cltv_expiry_delta = cltv_expiry_delta ;
pcu - > htlc_minimum_msat = htlc_minimum_msat ;
pcu - > htlc_maximum_msat = htlc_maximum_msat ;
pcu - > fee_base_msat = fee_base_msat ;
pcu - > fee_proportional_millionths = fee_proportional_millionths ;
pcu - > timestamp = timestamp ;
pcu - > update = tal_dup_talarr ( pcu , u8 , update ) ;
pcu - > source_peer = tal_dup_or_null ( pcu , struct node_id , source_peer ) ;
tal_arr_expand ( queue , pcu ) ;
}
static void enqueue_nannounce ( struct pending_nannounce * * * queue ,
const struct node_id * node_id ,
u32 timestamp ,
const u8 * nannounce TAKES ,
const struct node_id * source_peer TAKES )
{
struct pending_nannounce * pna = tal ( * queue , struct pending_nannounce ) ;
pna - > node_id = * node_id ;
pna - > timestamp = timestamp ;
pna - > nannounce = tal_dup_talarr ( pna , u8 , nannounce ) ;
pna - > source_peer = tal_dup_or_null ( pna , struct node_id , source_peer ) ;
tal_arr_expand ( queue , pna ) ;
}
2024-01-31 15:03:12 +10:30
/* Helpers to keep counters in sync with maps! */
static void map_init ( struct cannounce_map * map , const char * name )
{
uintmap_init ( & map - > map ) ;
map - > count = 0 ;
map - > name = name ;
map - > flood_reported = false ;
}
static bool map_add ( struct cannounce_map * map ,
struct short_channel_id scid ,
struct pending_cannounce * pca )
{
/* More than 10000 pending things? Stop! */
if ( map - > count > 10000 ) {
if ( ! map - > flood_reported ) {
status_unusual ( " %s being flooded by %s: dropping some " ,
map - > name ,
pca - > source_peer
2024-03-20 11:10:16 +10:30
? fmt_node_id ( tmpctx , pca - > source_peer )
2024-01-31 15:03:12 +10:30
: " unknown " ) ;
map - > flood_reported = true ;
}
return false ;
}
if ( uintmap_add ( & map - > map , scid . u64 , pca ) ) {
map - > count + + ;
return true ;
}
return false ;
}
static struct pending_cannounce * map_del ( struct cannounce_map * map ,
struct short_channel_id scid )
{
struct pending_cannounce * pca = uintmap_del ( & map - > map , scid . u64 ) ;
if ( pca ) {
assert ( map - > count ) ;
map - > count - - ;
if ( map - > flood_reported & & uintmap_empty ( & map - > map ) ) {
status_unusual ( " %s flood has subsided " , map - > name ) ;
map - > flood_reported = false ;
}
}
return pca ;
}
static bool map_empty ( const struct cannounce_map * map )
{
if ( uintmap_empty ( & map - > map ) ) {
assert ( map - > count = = 0 ) ;
return true ;
}
assert ( map - > count ! = 0 ) ;
return false ;
}
static struct pending_cannounce * map_get ( struct cannounce_map * map ,
struct short_channel_id scid )
{
return uintmap_get ( & map - > map , scid . u64 ) ;
}
2024-01-31 15:03:11 +10:30
/* Does any channel_announcement preceed this offset in the gossip_store? */
static bool any_cannounce_preceeds_offset ( struct gossmap * gossmap ,
const struct gossmap_node * node ,
const struct gossmap_chan * exclude_chan ,
u64 offset )
{
for ( size_t i = 0 ; i < node - > num_chans ; i + + ) {
struct gossmap_chan * chan = gossmap_nth_chan ( gossmap , node , i , NULL ) ;
if ( chan = = exclude_chan )
continue ;
2024-02-11 21:07:41 +10:30
if ( chan - > cann_off > offset )
continue ;
/* Dying channels don't help! */
if ( gossmap_chan_is_dying ( gossmap , chan ) )
continue ;
return true ;
2024-01-31 15:03:11 +10:30
}
return false ;
}
2024-02-11 21:05:41 +10:30
/* Are all channels associated with this node dying? (Perhaps ignoring one)*/
static bool all_node_channels_dying ( struct gossmap * gossmap ,
const struct gossmap_node * n ,
const struct gossmap_chan * ignore )
2024-02-11 21:02:41 +10:30
{
for ( size_t i = 0 ; i < n - > num_chans ; i + + ) {
const struct gossmap_chan * c = gossmap_nth_chan ( gossmap , n , i , NULL ) ;
2024-02-11 21:05:41 +10:30
if ( c ! = ignore & & ! gossmap_chan_is_dying ( gossmap , c ) )
2024-02-11 21:02:41 +10:30
return false ;
}
return true ;
}
2024-01-31 15:03:11 +10:30
/* To actually remove a channel:
* - Suppress future lookups in case we receive another channel_update .
* - Put deleted tombstone in gossip_store .
* - Mark records deleted in gossip_store .
2024-02-11 21:08:41 +10:30
* - See if node_announcement ( s ) need to be removed , marked dying , or moved .
2024-01-31 15:03:11 +10:30
*/
static void remove_channel ( struct gossmap_manage * gm ,
struct gossmap * gossmap ,
struct gossmap_chan * chan ,
struct short_channel_id scid )
{
/* Suppress any now-obsolete updates/announcements */
txout_failures_add ( gm - > txf , scid ) ;
/* Cover race where we were looking up this UTXO as it was spent. */
2024-01-31 15:03:12 +10:30
tal_free ( map_del ( & gm - > pending_ann_map , scid ) ) ;
tal_free ( map_del ( & gm - > early_ann_map , scid ) ) ;
2024-01-31 15:03:11 +10:30
/* Put in tombstone marker. */
2024-01-31 16:14:14 +10:30
gossip_store_add ( gm - > daemon - > gs ,
2024-03-20 12:29:51 +10:30
towire_gossip_store_delete_chan ( tmpctx , scid ) ,
2024-01-31 16:14:14 +10:30
0 ) ;
2024-01-31 15:03:11 +10:30
/* Delete from store */
gossip_store_del ( gm - > daemon - > gs , chan - > cann_off , WIRE_CHANNEL_ANNOUNCEMENT ) ;
for ( int dir = 0 ; dir < 2 ; dir + + ) {
if ( gossmap_chan_set ( chan , dir ) )
gossip_store_del ( gm - > daemon - > gs , chan - > cupdate_off [ dir ] , WIRE_CHANNEL_UPDATE ) ;
}
/* Check for node_announcements which should no longer be there */
for ( int dir = 0 ; dir < 2 ; dir + + ) {
struct gossmap_node * node ;
2024-02-11 21:05:41 +10:30
u64 offset ;
2024-01-31 15:03:11 +10:30
node = gossmap_nth_node ( gossmap , chan , dir ) ;
2024-02-14 16:42:41 +10:30
/* Don't get confused if a node has a channel with self! */
if ( dir = = 1 & & node = = gossmap_nth_node ( gossmap , chan , 0 ) )
continue ;
2024-01-31 15:03:11 +10:30
/* If there was a node announcement, we might need to fix things up. */
if ( ! gossmap_node_announced ( node ) )
continue ;
/* Last channel? Delete node announce */
if ( node - > num_chans = = 1 ) {
gossip_store_del ( gm - > daemon - > gs , node - > nann_off , WIRE_NODE_ANNOUNCEMENT ) ;
continue ;
}
/* Maybe this was the last channel_announcement which preceeded node_announcement? */
2024-02-11 21:08:41 +10:30
if ( chan - > cann_off < node - > nann_off
& & any_cannounce_preceeds_offset ( gossmap , node , chan , node - > nann_off ) ) {
const u8 * nannounce ;
u32 timestamp ;
2024-01-31 15:03:11 +10:30
2024-02-11 21:08:41 +10:30
/* To maintain order, delete and re-add node_announcement */
nannounce = gossmap_node_get_announce ( tmpctx , gossmap , node ) ;
timestamp = gossip_store_get_timestamp ( gm - > daemon - > gs , node - > nann_off ) ;
2024-02-11 21:05:41 +10:30
2024-02-11 21:08:41 +10:30
gossip_store_del ( gm - > daemon - > gs , node - > nann_off , WIRE_NODE_ANNOUNCEMENT ) ;
offset = gossip_store_add ( gm - > daemon - > gs , nannounce , timestamp ) ;
} else {
/* Are all remaining channels dying but we weren't?
* Can happen if we removed this channel immediately
* for our own channels , without marking them
* dying . */
if ( gossmap_chan_is_dying ( gossmap , chan ) )
continue ;
offset = node - > nann_off ;
}
2024-02-11 21:05:41 +10:30
/* Be sure to set DYING flag when we move (ignore current
* channel , we haven ' t reloaded gossmap yet ! ) */
if ( all_node_channels_dying ( gossmap , node , chan ) )
gossip_store_set_flag ( gm - > daemon - > gs , offset ,
GOSSIP_STORE_DYING_BIT ,
WIRE_NODE_ANNOUNCEMENT ) ;
2024-01-31 15:03:11 +10:30
}
}
2024-01-31 15:03:11 +10:30
static u32 get_timestamp ( struct gossmap * gossmap ,
const struct gossmap_chan * chan ,
int dir )
{
u32 timestamp ;
/* 0 is sufficient for our needs */
if ( ! gossmap_chan_set ( chan , dir ) )
return 0 ;
gossmap_chan_get_update_details ( gossmap , chan , dir ,
& timestamp ,
2024-10-11 21:30:38 +10:30
NULL , NULL , NULL , NULL , NULL , NULL , NULL ) ;
2024-01-31 15:03:11 +10:30
return timestamp ;
}
/* Every half a week we look for dead channels (faster in dev) */
static void prune_network ( struct gossmap_manage * gm )
{
u64 now = gossip_time_now ( gm - > daemon ) . ts . tv_sec ;
/* Anything below this highwater mark ought to be pruned */
const s64 highwater = now - GOSSIP_PRUNE_INTERVAL ( gm - > daemon - > dev_fast_gossip_prune ) ;
const struct gossmap_node * me ;
struct gossmap * gossmap ;
/* We reload this every time we delete a channel: that way we can tell if it's
* time to remove a node ! */
gossmap = gossmap_manage_get_gossmap ( gm ) ;
me = gossmap_find_node ( gossmap , & gm - > daemon - > id ) ;
/* Now iterate through all channels and see if it is still alive */
for ( size_t i = 0 ; i < gossmap_max_chan_idx ( gossmap ) ; i + + ) {
struct gossmap_chan * chan = gossmap_chan_byidx ( gossmap , i ) ;
u32 timestamp [ 2 ] ;
struct short_channel_id scid ;
if ( ! chan )
continue ;
/* BOLT #7:
* - if the ` timestamp ` of the latest ` channel_update ` in
* either direction is older than two weeks ( 1209600 seconds ) :
* - MAY prune the channel .
*/
/* This is a fancy way of saying "both ends must refresh!" */
timestamp [ 0 ] = get_timestamp ( gossmap , chan , 0 ) ;
timestamp [ 1 ] = get_timestamp ( gossmap , chan , 1 ) ;
if ( timestamp [ 0 ] > = highwater & & timestamp [ 1 ] > = highwater )
continue ;
scid = gossmap_chan_scid ( gossmap , chan ) ;
/* Is it one of mine? */
if ( gossmap_nth_node ( gossmap , chan , 0 ) = = me
| | gossmap_nth_node ( gossmap , chan , 1 ) = = me ) {
int local = ( gossmap_nth_node ( gossmap , chan , 1 ) = = me ) ;
status_unusual ( " Pruning local channel %s from gossip_store: local channel_update time %u, remote %u " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ,
2024-01-31 15:03:11 +10:30
timestamp [ local ] , timestamp [ ! local ] ) ;
}
status_debug ( " Pruning channel %s from network view (ages %u and %u) " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ,
2024-01-31 15:03:11 +10:30
timestamp [ 0 ] , timestamp [ 1 ] ) ;
remove_channel ( gm , gossmap , chan , scid ) ;
gossmap = gossmap_manage_get_gossmap ( gm ) ;
me = gossmap_find_node ( gossmap , & gm - > daemon - > id ) ;
}
/* Note: some nodes may have been left with no channels! Gossmap will
* remove them on next refresh . */
start_prune_timer ( gm ) ;
}
static void start_prune_timer ( struct gossmap_manage * gm )
{
/* Schedule next run now */
gm - > prune_timer = new_reltimer ( & gm - > daemon - > timers , gm ,
time_from_sec ( GOSSIP_PRUNE_INTERVAL ( gm - > daemon - > dev_fast_gossip_prune ) / 4 ) ,
prune_network , gm ) ;
}
2024-01-31 15:03:11 +10:30
static void reprocess_queued_msgs ( struct gossmap_manage * gm ) ;
static void report_bad_update ( struct gossmap * map ,
const struct short_channel_id_dir * scidd ,
u16 cltv_expiry_delta ,
u32 fee_base_msat ,
u32 fee_proportional_millionths ,
struct gossmap_manage * gm )
{
status_debug ( " Update for %s has silly values, disabling (cltv=%u, fee=%u+%u) " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id_dir ( tmpctx , scidd ) ,
2024-01-31 15:03:11 +10:30
cltv_expiry_delta , fee_base_msat , fee_proportional_millionths ) ;
}
struct gossmap_manage * gossmap_manage_new ( const tal_t * ctx ,
2024-01-31 16:38:20 +10:30
struct daemon * daemon ,
struct chan_dying * dying_channels TAKES )
2024-01-31 15:03:11 +10:30
{
struct gossmap_manage * gm = tal ( ctx , struct gossmap_manage ) ;
2024-01-31 16:38:20 +10:30
gm - > fd = gossip_store_get_fd ( daemon - > gs ) ;
2024-01-31 15:03:11 +10:30
gm - > raw_gossmap = gossmap_load_fd ( gm , gm - > fd , report_bad_update , NULL , gm ) ;
assert ( gm - > raw_gossmap ) ;
gm - > daemon = daemon ;
2024-01-31 15:03:12 +10:30
map_init ( & gm - > pending_ann_map , " pending announcements " ) ;
2024-01-31 15:03:11 +10:30
gm - > pending_cupdates = tal_arr ( gm , struct pending_cupdate * , 0 ) ;
2024-01-31 15:03:12 +10:30
map_init ( & gm - > early_ann_map , " too-early announcements " ) ;
2024-01-31 15:03:11 +10:30
gm - > early_cupdates = tal_arr ( gm , struct pending_cupdate * , 0 ) ;
gm - > pending_nannounces = tal_arr ( gm , struct pending_nannounce * , 0 ) ;
gm - > txf = txout_failures_new ( gm , daemon ) ;
2024-01-31 16:38:20 +10:30
gm - > dying_channels = tal_dup_talarr ( gm , struct chan_dying , dying_channels ) ;
2024-01-31 15:03:11 +10:30
2024-01-31 15:03:11 +10:30
start_prune_timer ( gm ) ;
2024-01-31 15:03:11 +10:30
return gm ;
}
/* Catch CI giving out-of-order gossip: definitely happens IRL though */
static void bad_gossip ( const struct node_id * source_peer , const char * str )
{
status_peer_debug ( source_peer , " Bad gossip order: %s " , str ) ;
}
/* Send peer a warning message, if non-NULL. */
static void peer_warning ( struct gossmap_manage * gm ,
const struct node_id * source_peer ,
const char * fmt , . . . )
{
va_list ap ;
char * formatted ;
va_start ( ap , fmt ) ;
formatted = tal_vfmt ( tmpctx , fmt , ap ) ;
va_end ( ap ) ;
bad_gossip ( source_peer , formatted ) ;
if ( ! source_peer )
return ;
queue_peer_msg ( gm - > daemon , source_peer ,
take ( towire_warningfmt ( NULL , NULL , " %s " , formatted ) ) ) ;
}
2024-02-11 21:03:41 +10:30
/* Subtle: if a new channel appears, it means those node announcements are no longer "dying" */
static void node_announcements_not_dying ( struct gossmap_manage * gm ,
const struct gossmap * gossmap ,
const struct pending_cannounce * pca )
{
for ( size_t i = 0 ; i < ARRAY_SIZE ( pca - > node_id ) ; i + + ) {
struct gossmap_node * n = gossmap_find_node ( gossmap , & pca - > node_id [ i ] ) ;
if ( ! n | | ! gossmap_node_announced ( n ) )
continue ;
if ( gossip_store_get_flags ( gm - > daemon - > gs , n - > nann_off , WIRE_NODE_ANNOUNCEMENT )
& GOSSIP_STORE_DYING_BIT ) {
gossip_store_clear_flag ( gm - > daemon - > gs , n - > nann_off ,
GOSSIP_STORE_DYING_BIT ,
WIRE_NODE_ANNOUNCEMENT ) ;
}
}
}
2024-01-31 15:03:11 +10:30
const char * gossmap_manage_channel_announcement ( const tal_t * ctx ,
struct gossmap_manage * gm ,
const u8 * announce TAKES ,
2024-01-31 15:03:12 +10:30
const struct node_id * source_peer TAKES ,
const struct amount_sat * known_amount )
2024-01-31 15:03:11 +10:30
{
secp256k1_ecdsa_signature node_signature_1 , node_signature_2 ;
secp256k1_ecdsa_signature bitcoin_signature_1 , bitcoin_signature_2 ;
u8 * features ;
struct bitcoin_blkid chain_hash ;
struct short_channel_id scid ;
struct node_id node_id_1 ;
struct node_id node_id_2 ;
struct pubkey bitcoin_key_1 ;
struct pubkey bitcoin_key_2 ;
struct pending_cannounce * pca ;
const char * warn ;
u32 blockheight = gm - > daemon - > current_blockheight ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
/* Make sure we own msg, even if we don't save it. */
if ( taken ( announce ) )
tal_steal ( tmpctx , announce ) ;
if ( ! fromwire_channel_announcement ( tmpctx , announce , & node_signature_1 , & node_signature_2 ,
& bitcoin_signature_1 , & bitcoin_signature_2 , & features , & chain_hash ,
& scid , & node_id_1 , & node_id_2 , & bitcoin_key_1 , & bitcoin_key_2 ) ) {
return tal_fmt ( ctx , " Malformed channel_announcement %s " ,
tal_hex ( tmpctx , announce ) ) ;
}
/* If a prior txout lookup failed there is little point it trying
* again . Just drop the announcement and walk away whistling .
*
* Happens quite a lot in CI on just - closed channels .
*/
if ( in_txout_failures ( gm - > txf , scid ) ) {
return NULL ;
}
warn = sigcheck_channel_announcement ( ctx , & node_id_1 , & node_id_2 ,
& bitcoin_key_1 , & bitcoin_key_2 ,
& node_signature_1 , & node_signature_2 ,
& bitcoin_signature_1 , & bitcoin_signature_2 ,
announce ) ;
if ( warn )
return warn ;
/* Already known? */
if ( gossmap_find_chan ( gossmap , & scid ) )
return NULL ;
pca = tal ( gm , struct pending_cannounce ) ;
pca - > scriptpubkey = scriptpubkey_p2wsh ( pca ,
bitcoin_redeem_2of2 ( tmpctx ,
& bitcoin_key_1 ,
& bitcoin_key_2 ) ) ;
pca - > channel_announcement = tal_dup_talarr ( pca , u8 , announce ) ;
pca - > source_peer = tal_dup_or_null ( pca , struct node_id , source_peer ) ;
2024-02-11 21:03:41 +10:30
pca - > node_id [ 0 ] = node_id_1 ;
pca - > node_id [ 1 ] = node_id_2 ;
2024-01-31 15:03:11 +10:30
2024-01-31 15:03:12 +10:30
/* Are we supposed to add immediately without checking with lightningd?
* Unless we already got it from a peer and we ' re processing now !
*/
if ( known_amount
2024-01-31 15:03:12 +10:30
& & ! map_get ( & gm - > pending_ann_map , scid )
& & ! map_get ( & gm - > early_ann_map , scid ) ) {
2024-01-31 15:03:12 +10:30
/* Set with timestamp 0 (we will update once we have a channel_update) */
2024-01-31 16:14:14 +10:30
gossip_store_add ( gm - > daemon - > gs , announce , 0 ) ;
gossip_store_add ( gm - > daemon - > gs ,
towire_gossip_store_channel_amount ( tmpctx , * known_amount ) , 0 ) ;
2024-02-11 21:03:41 +10:30
node_announcements_not_dying ( gm , gossmap , pca ) ;
2024-01-31 15:03:12 +10:30
tal_free ( pca ) ;
return NULL ;
}
2024-01-31 15:03:11 +10:30
/* Don't know blockheight yet, or not yet deep enough? Don't even ask */
2024-03-20 12:29:51 +10:30
if ( ! is_scid_depth_announceable ( scid , blockheight ) ) {
2024-01-31 15:03:11 +10:30
/* Don't expect to be more than 12 blocks behind! */
if ( blockheight ! = 0
2024-03-20 12:29:51 +10:30
& & short_channel_id_blocknum ( scid ) > blockheight + 12 ) {
2024-01-31 15:03:11 +10:30
return tal_fmt ( ctx ,
" Bad gossip order: ignoring channel_announcement %s at blockheight %u " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ,
2024-01-31 15:03:11 +10:30
blockheight ) ;
}
2024-01-31 15:03:12 +10:30
if ( ! map_add ( & gm - > early_ann_map , scid , pca ) ) {
2024-01-31 15:03:11 +10:30
/* Already pending? Ignore */
tal_free ( pca ) ;
return NULL ;
}
/* We will retry in gossip_manage_new_block */
return NULL ;
}
status_debug ( " channel_announcement: Adding %s to pending... " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:12 +10:30
if ( ! map_add ( & gm - > pending_ann_map , scid , pca ) ) {
2024-01-31 15:03:11 +10:30
/* Already pending? Ignore */
tal_free ( pca ) ;
return NULL ;
}
/* Ask lightningd about this scid: see
* gossmap_manage_handle_get_txout_reply */
daemon_conn_send ( gm - > daemon - > master ,
2024-03-20 12:29:51 +10:30
take ( towire_gossipd_get_txout ( NULL , scid ) ) ) ;
2024-01-31 15:03:11 +10:30
return NULL ;
}
/*~ We queue incoming channel_announcement pending confirmation from lightningd
* that it really is an unspent output . Here ' s its reply . */
void gossmap_manage_handle_get_txout_reply ( struct gossmap_manage * gm , const u8 * msg )
{
struct short_channel_id scid ;
u8 * outscript ;
struct amount_sat sat ;
struct pending_cannounce * pca ;
2024-02-11 21:03:41 +10:30
struct gossmap * gossmap ;
2024-01-31 15:03:11 +10:30
if ( ! fromwire_gossipd_get_txout_reply ( msg , msg , & scid , & sat , & outscript ) )
master_badmsg ( WIRE_GOSSIPD_GET_TXOUT_REPLY , msg ) ;
status_debug ( " channel_announcement: got reply for %s... " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
2024-01-31 15:03:12 +10:30
pca = map_del ( & gm - > pending_ann_map , scid ) ;
2024-01-31 15:03:11 +10:30
if ( ! pca ) {
/* If we looking specifically for this, we no longer
* are ( but don ' t penalize sender : we don ' t know if it was
* good or bad ) . */
remove_unknown_scid ( gm - > daemon - > seeker , & scid , true ) ;
/* Was it deleted because we saw channel close? */
if ( ! in_txout_failures ( gm - > txf , scid ) )
status_broken ( " get_txout_reply with unknown scid %s? " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
return ;
}
/* BOLT #7:
*
* The receiving node :
* . . .
* - if the ` short_channel_id ` ' s output . . . is spent :
* - MUST ignore the message .
*/
if ( tal_count ( outscript ) = = 0 ) {
peer_warning ( gm , pca - > source_peer ,
" channel_announcement: no unspent txout %s " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
goto bad ;
}
2024-02-14 20:08:33 +10:30
if ( ! tal_arr_eq ( outscript , pca - > scriptpubkey ) ) {
2024-01-31 15:03:11 +10:30
peer_warning ( gm , pca - > source_peer ,
" channel_announcement: txout %s expected %s, got %s " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ,
2024-01-31 15:03:11 +10:30
tal_hex ( tmpctx , pca - > scriptpubkey ) ,
tal_hex ( tmpctx , outscript ) ) ;
goto bad ;
}
2024-05-23 10:55:59 +09:30
/* We have reports of doubled-up channel_announcements, hence this check! */
struct gossmap_chan * chan ;
2024-10-08 15:27:54 +10:30
u64 before_length_processed , before_total_length ;
2024-05-23 10:55:59 +09:30
before_length_processed = gossmap_lengths ( gm - > raw_gossmap , & before_total_length ) ;
chan = gossmap_find_chan ( gm - > raw_gossmap , & scid ) ;
if ( chan ) {
2024-10-08 15:27:54 +10:30
status_broken ( " Redundant channel_announce for scid %s at off % " PRIu64 " (gossmap % " PRIu64 " /% " PRIu64 " , store % " PRIu64 " ) " ,
2024-05-23 10:55:59 +09:30
fmt_short_channel_id ( tmpctx , scid ) , chan - > cann_off ,
before_length_processed , before_total_length ,
gossip_store_len_written ( gm - > daemon - > gs ) ) ;
goto out ;
} else {
2024-10-08 15:27:54 +10:30
u64 after_length_processed , after_total_length ;
2024-05-23 10:55:59 +09:30
/* Good, now try refreshing in case it somehow slipped in! */
gossmap = gossmap_manage_get_gossmap ( gm ) ;
after_length_processed = gossmap_lengths ( gm - > raw_gossmap , & after_total_length ) ;
chan = gossmap_find_chan ( gm - > raw_gossmap , & scid ) ;
if ( chan ) {
2024-10-08 15:27:54 +10:30
status_broken ( " Redundant channel_announce *AFTER REFRESH* for scid %s at off % " PRIu64 " (gossmap was % " PRIu64 " /% " PRIu64 " , now % " PRIu64 " /% " PRIu64 " , store % " PRIu64 " ) " ,
2024-05-23 10:55:59 +09:30
fmt_short_channel_id ( tmpctx , scid ) , chan - > cann_off ,
before_length_processed , before_total_length ,
after_length_processed , after_total_length ,
gossip_store_len_written ( gm - > daemon - > gs ) ) ;
goto out ;
}
}
2024-01-31 15:03:11 +10:30
/* Set with timestamp 0 (we will update once we have a channel_update) */
2024-01-31 16:14:14 +10:30
gossip_store_add ( gm - > daemon - > gs , pca - > channel_announcement , 0 ) ;
gossip_store_add ( gm - > daemon - > gs ,
towire_gossip_store_channel_amount ( tmpctx , sat ) , 0 ) ;
2024-01-31 15:03:11 +10:30
/* If we looking specifically for this, we no longer are. */
remove_unknown_scid ( gm - > daemon - > seeker , & scid , true ) ;
2024-02-11 21:03:41 +10:30
gossmap = gossmap_manage_get_gossmap ( gm ) ;
/* If node_announcements were dying, they no longer are. */
node_announcements_not_dying ( gm , gossmap , pca ) ;
tal_free ( pca ) ;
2024-01-31 15:03:11 +10:30
/* When all pending requests are done, we reconsider queued messages */
reprocess_queued_msgs ( gm ) ;
return ;
bad :
txout_failures_add ( gm - > txf , scid ) ;
2024-05-23 10:55:59 +09:30
out :
tal_free ( pca ) ;
2024-01-31 15:03:11 +10:30
/* If we looking specifically for this, we no longer are. */
remove_unknown_scid ( gm - > daemon - > seeker , & scid , false ) ;
}
/* This is called both from when we receive the channel update, and if
* we had to defer . */
static const char * process_channel_update ( const tal_t * ctx ,
struct gossmap_manage * gm ,
struct short_channel_id scid ,
const secp256k1_ecdsa_signature * signature ,
u8 message_flags ,
u8 channel_flags ,
u16 cltv_expiry_delta ,
struct amount_msat htlc_minimum_msat ,
struct amount_msat htlc_maximum_msat ,
u32 fee_base_msat ,
u32 fee_proportional_millionths ,
u32 timestamp ,
const u8 * update ,
const struct node_id * source_peer )
{
struct gossmap_chan * chan ;
struct node_id node_id , remote_id ;
const char * err ;
int dir = ( channel_flags & ROUTING_FLAGS_DIRECTION ) ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
2024-02-11 21:04:41 +10:30
u64 offset ;
2024-01-31 15:03:11 +10:30
chan = gossmap_find_chan ( gossmap , & scid ) ;
if ( ! chan ) {
/* Did we explicitly reject announce? Ignore completely. */
if ( in_txout_failures ( gm - > txf , scid ) )
return NULL ;
/* Seeker may want to ask about this. */
query_unknown_channel ( gm - > daemon , source_peer , scid ) ;
/* Don't send them warning, it can happen. */
bad_gossip ( source_peer ,
tal_fmt ( tmpctx , " Unknown channel %s " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ) ;
2024-01-31 15:03:11 +10:30
return NULL ;
}
/* Now we know node, we can check signature. */
gossmap_node_get_id ( gossmap ,
gossmap_nth_node ( gossmap , chan , dir ) ,
& node_id ) ;
err = sigcheck_channel_update ( ctx , & node_id , signature , update ) ;
if ( err )
return err ;
/* Don't allow private updates on public channels! */
if ( message_flags & ROUTING_OPT_DONT_FORWARD ) {
return tal_fmt ( ctx , " Do not set DONT_FORWARD on public channel_updates (%s) " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
}
/* Do we have same or earlier update? */
if ( gossmap_chan_set ( chan , dir ) ) {
u32 prev_timestamp
= gossip_store_get_timestamp ( gm - > daemon - > gs , chan - > cupdate_off [ dir ] ) ;
if ( prev_timestamp > = timestamp ) {
/* Too old, ignore */
return NULL ;
}
} else {
/* Is this the first update in either direction? If so,
* rewrite channel_announcement so timestamp is correct . */
if ( ! gossmap_chan_set ( chan , dir ) )
gossip_store_set_timestamp ( gm - > daemon - > gs , chan - > cann_off , timestamp ) ;
}
/* OK, apply the new one */
2024-02-11 21:04:41 +10:30
offset = gossip_store_add ( gm - > daemon - > gs , update , timestamp ) ;
/* If channel is dying, make sure update is also marked dying! */
if ( gossmap_chan_is_dying ( gossmap , chan ) ) {
gossip_store_set_flag ( gm - > daemon - > gs ,
offset ,
GOSSIP_STORE_DYING_BIT ,
WIRE_CHANNEL_UPDATE ) ;
}
2024-01-31 15:03:11 +10:30
/* Now delete old */
if ( gossmap_chan_set ( chan , dir ) )
gossip_store_del ( gm - > daemon - > gs , chan - > cupdate_off [ dir ] , WIRE_CHANNEL_UPDATE ) ;
/* Is this an update for an incoming channel? If so, keep lightningd updated */
gossmap_node_get_id ( gossmap ,
gossmap_nth_node ( gossmap , chan , ! dir ) ,
& remote_id ) ;
if ( node_id_eq ( & remote_id , & gm - > daemon - > id ) ) {
tell_lightningd_peer_update ( gm - > daemon , source_peer ,
scid , fee_base_msat ,
fee_proportional_millionths ,
cltv_expiry_delta , htlc_minimum_msat ,
htlc_maximum_msat ) ;
}
status_peer_debug ( source_peer ,
" Received channel_update for channel %s/%d now %s " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ,
2024-01-31 15:03:11 +10:30
dir ,
channel_flags & ROUTING_FLAGS_DISABLED ? " DISABLED " : " ACTIVE " ) ;
return NULL ;
}
const char * gossmap_manage_channel_update ( const tal_t * ctx ,
struct gossmap_manage * gm ,
const u8 * update TAKES ,
const struct node_id * source_peer TAKES )
{
secp256k1_ecdsa_signature signature ;
struct short_channel_id scid ;
u32 timestamp ;
u8 message_flags , channel_flags ;
u16 cltv_expiry_delta ;
struct amount_msat htlc_minimum_msat , htlc_maximum_msat ;
u32 fee_base_msat ;
u32 fee_proportional_millionths ;
struct bitcoin_blkid chain_hash ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
if ( taken ( update ) )
tal_steal ( tmpctx , update ) ;
if ( taken ( source_peer ) )
tal_steal ( tmpctx , source_peer ) ;
if ( ! fromwire_channel_update ( update , & signature ,
& chain_hash , & scid ,
& timestamp , & message_flags ,
& channel_flags , & cltv_expiry_delta ,
& htlc_minimum_msat , & fee_base_msat ,
& fee_proportional_millionths ,
& htlc_maximum_msat ) ) {
return tal_fmt ( ctx , " channel_update: malformed %s " ,
tal_hex ( tmpctx , update ) ) ;
}
/* Don't accept ancient or far-future timestamps. */
if ( ! timestamp_reasonable ( gm - > daemon , timestamp ) )
return NULL ;
/* Still waiting? */
2024-01-31 15:03:12 +10:30
if ( map_get ( & gm - > pending_ann_map , scid ) ) {
2024-01-31 15:03:11 +10:30
enqueue_cupdate ( & gm - > pending_cupdates ,
scid ,
& signature ,
message_flags ,
channel_flags ,
cltv_expiry_delta ,
htlc_minimum_msat ,
htlc_maximum_msat ,
fee_base_msat ,
fee_proportional_millionths ,
timestamp ,
take ( update ) ,
source_peer ) ;
return NULL ;
}
/* Too early? */
2024-01-31 15:03:12 +10:30
if ( map_get ( & gm - > early_ann_map , scid ) ) {
2024-01-31 15:03:11 +10:30
enqueue_cupdate ( & gm - > early_cupdates ,
scid ,
& signature ,
message_flags ,
channel_flags ,
cltv_expiry_delta ,
htlc_minimum_msat ,
htlc_maximum_msat ,
fee_base_msat ,
fee_proportional_millionths ,
timestamp ,
take ( update ) ,
source_peer ) ;
return NULL ;
}
/* Private channel_updates are not always marked as such. So check if it's an unknown
* channel , and signed by the peer itself . */
if ( ! gossmap_find_chan ( gossmap , & scid )
& & source_peer
& & sigcheck_channel_update ( tmpctx , source_peer , & signature , update ) = = NULL ) {
tell_lightningd_peer_update ( gm - > daemon , source_peer ,
scid , fee_base_msat ,
fee_proportional_millionths ,
cltv_expiry_delta , htlc_minimum_msat ,
htlc_maximum_msat ) ;
return NULL ;
}
return process_channel_update ( ctx , gm , scid , & signature ,
message_flags , channel_flags ,
cltv_expiry_delta ,
htlc_minimum_msat ,
htlc_maximum_msat ,
fee_base_msat ,
fee_proportional_millionths ,
timestamp , update , source_peer ) ;
}
static void process_node_announcement ( struct gossmap_manage * gm ,
2024-02-11 21:06:41 +10:30
struct gossmap * gossmap ,
2024-01-31 15:03:11 +10:30
const struct gossmap_node * node ,
u32 timestamp ,
const struct node_id * node_id ,
const u8 * nannounce ,
const struct node_id * source_peer )
{
2024-02-11 21:06:41 +10:30
u64 offset ;
2024-01-31 15:03:11 +10:30
/* Do we have a later one? If so, ignore */
if ( gossmap_node_announced ( node ) ) {
u32 prev_timestamp
= gossip_store_get_timestamp ( gm - > daemon - > gs , node - > nann_off ) ;
if ( prev_timestamp > = timestamp ) {
/* Too old, ignore */
return ;
}
}
/* OK, apply the new one */
2024-02-11 21:06:41 +10:30
offset = gossip_store_add ( gm - > daemon - > gs , nannounce , timestamp ) ;
/* If all channels are dying, make sure this is marked too. */
if ( all_node_channels_dying ( gossmap , node , NULL ) ) {
gossip_store_set_flag ( gm - > daemon - > gs , offset ,
GOSSIP_STORE_DYING_BIT ,
WIRE_NODE_ANNOUNCEMENT ) ;
}
2024-01-31 15:03:11 +10:30
/* Now delete old */
if ( gossmap_node_announced ( node ) )
gossip_store_del ( gm - > daemon - > gs , node - > nann_off , WIRE_NODE_ANNOUNCEMENT ) ;
status_peer_debug ( source_peer ,
" Received node_announcement for node %s " ,
2024-03-20 11:17:52 +10:30
fmt_node_id ( tmpctx , node_id ) ) ;
2024-01-31 15:03:11 +10:30
}
const char * gossmap_manage_node_announcement ( const tal_t * ctx ,
struct gossmap_manage * gm ,
const u8 * nannounce TAKES ,
const struct node_id * source_peer TAKES )
{
secp256k1_ecdsa_signature signature ;
u32 timestamp ;
struct node_id node_id ;
u8 rgb_color [ 3 ] ;
u8 alias [ 32 ] ;
u8 * features , * addresses ;
struct wireaddr * wireaddrs ;
struct tlv_node_ann_tlvs * na_tlv ;
struct gossmap_node * node ;
const char * err ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
if ( taken ( nannounce ) )
tal_steal ( tmpctx , nannounce ) ;
if ( taken ( source_peer ) )
tal_steal ( tmpctx , source_peer ) ;
if ( ! fromwire_node_announcement ( tmpctx , nannounce ,
& signature , & features , & timestamp ,
& node_id , rgb_color , alias ,
& addresses ,
& na_tlv ) ) {
/* BOLT #7:
*
* - if ` node_id ` is NOT a valid compressed public key :
* - SHOULD send a ` warning ` .
* - MAY close the connection .
* - MUST NOT process the message further .
*/
return tal_fmt ( ctx , " node_announcement: malformed %s " ,
tal_hex ( tmpctx , nannounce ) ) ;
}
wireaddrs = fromwire_wireaddr_array ( tmpctx , addresses ) ;
if ( ! wireaddrs ) {
/* BOLT #7:
*
* - if ` addrlen ` is insufficient to hold the address
* descriptors of the known types :
* - SHOULD send a ` warning ` .
* - MAY close the connection .
*/
return tal_fmt ( ctx ,
" node_announcement: malformed wireaddrs %s in %s " ,
tal_hex ( tmpctx , wireaddrs ) ,
tal_hex ( tmpctx , nannounce ) ) ;
}
err = sigcheck_node_announcement ( ctx , & node_id , & signature ,
nannounce ) ;
if ( err )
return err ;
node = gossmap_find_node ( gossmap , & node_id ) ;
if ( ! node ) {
/* Still waiting for some channel_announcement? */
2024-01-31 15:03:12 +10:30
if ( ! map_empty ( & gm - > pending_ann_map )
| | ! map_empty ( & gm - > early_ann_map ) ) {
2024-01-31 15:03:11 +10:30
enqueue_nannounce ( & gm - > pending_nannounces ,
& node_id ,
timestamp ,
take ( nannounce ) ,
source_peer ) ;
return NULL ;
}
/* Seeker may want to ask about this. */
query_unknown_node ( gm - > daemon , source_peer , & node_id ) ;
/* Don't complain to them: this can happen. */
bad_gossip ( source_peer ,
tal_fmt ( tmpctx ,
" node_announcement: unknown node %s " ,
2024-03-20 11:10:16 +10:30
fmt_node_id ( tmpctx , & node_id ) ) ) ;
2024-01-31 15:03:11 +10:30
return NULL ;
}
2024-02-11 21:06:41 +10:30
process_node_announcement ( gm , gossmap , node , timestamp , & node_id , nannounce , source_peer ) ;
2024-01-31 15:03:11 +10:30
return NULL ;
}
static void process_pending_cupdate ( struct gossmap_manage * gm ,
struct pending_cupdate * pcu )
{
const char * err ;
err = process_channel_update ( tmpctx , gm ,
pcu - > scid ,
& pcu - > signature ,
pcu - > message_flags ,
pcu - > channel_flags ,
pcu - > cltv_expiry_delta ,
pcu - > htlc_minimum_msat ,
pcu - > htlc_maximum_msat ,
pcu - > fee_base_msat ,
pcu - > fee_proportional_millionths ,
pcu - > timestamp ,
pcu - > update ,
pcu - > source_peer ) ;
if ( err )
peer_warning ( gm , pcu - > source_peer ,
" channel_update: %s " , err ) ;
}
/* No channel_announcement now pending, so process every update which was waiting. */
static void reprocess_pending_cupdates ( struct gossmap_manage * gm )
{
/* Grab current array and reset to empty */
struct pending_cupdate * * pcus = gm - > pending_cupdates ;
gm - > pending_cupdates = tal_arr ( gm , struct pending_cupdate * , 0 ) ;
/* Now we can canonically process any pending channel_updates */
for ( size_t i = 0 ; i < tal_count ( pcus ) ; i + + )
process_pending_cupdate ( gm , pcus [ i ] ) ;
tal_free ( pcus ) ;
}
/* No channel_announcement are early, so process every update which was for those. */
static void reprocess_early_cupdates ( struct gossmap_manage * gm )
{
/* Grab current array and reset to empty */
struct pending_cupdate * * pcus = gm - > early_cupdates ;
gm - > early_cupdates = tal_arr ( gm , struct pending_cupdate * , 0 ) ;
for ( size_t i = 0 ; i < tal_count ( pcus ) ; i + + ) {
/* Is announcement now pending? Add directly to pending queue. */
2024-01-31 15:03:12 +10:30
if ( map_get ( & gm - > pending_ann_map , pcus [ i ] - > scid ) ) {
2024-01-31 15:03:11 +10:30
tal_arr_expand ( & gm - > pending_cupdates ,
tal_steal ( gm - > pending_cupdates , pcus [ i ] ) ) ;
continue ;
}
process_pending_cupdate ( gm , pcus [ i ] ) ;
}
tal_free ( pcus ) ;
}
static void reprocess_queued_msgs ( struct gossmap_manage * gm )
{
bool pending_ann_empty , early_ann_empty ;
2024-01-31 15:03:12 +10:30
pending_ann_empty = map_empty ( & gm - > pending_ann_map ) ;
early_ann_empty = map_empty ( & gm - > early_ann_map ) ;
2024-01-31 15:03:11 +10:30
if ( pending_ann_empty ) {
reprocess_pending_cupdates ( gm ) ;
/* This should have been final! */
2024-01-31 15:03:12 +10:30
assert ( map_empty ( & gm - > pending_ann_map ) ) ;
2024-01-31 15:03:11 +10:30
}
if ( early_ann_empty ) {
/* reprocess_pending_cupdates should not have added any! */
2024-01-31 15:03:12 +10:30
assert ( map_empty ( & gm - > early_ann_map ) ) ;
2024-01-31 15:03:11 +10:30
reprocess_early_cupdates ( gm ) ;
/* Won't add any more */
2024-01-31 15:03:12 +10:30
assert ( map_empty ( & gm - > early_ann_map ) ) ;
2024-01-31 15:03:11 +10:30
}
/* Nothing at all outstanding? All node_announcements can now be processed */
if ( early_ann_empty & & pending_ann_empty ) {
struct pending_nannounce * * pnas = gm - > pending_nannounces ;
gm - > pending_nannounces = tal_arr ( gm , struct pending_nannounce * , 0 ) ;
for ( size_t i = 0 ; i < tal_count ( pnas ) ; i + + ) {
struct gossmap_node * node ;
2024-06-04 19:55:38 +09:30
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
2024-01-31 15:03:11 +10:30
node = gossmap_find_node ( gossmap , & pnas [ i ] - > node_id ) ;
if ( ! node ) {
/* Seeker may want to ask about this. */
query_unknown_node ( gm - > daemon ,
pnas [ i ] - > source_peer , & pnas [ i ] - > node_id ) ;
/* Don't complain to them: this can happen. */
bad_gossip ( pnas [ i ] - > source_peer ,
tal_fmt ( tmpctx ,
" node_announcement: unknown node %s " ,
2024-03-20 11:10:16 +10:30
fmt_node_id ( tmpctx , & pnas [ i ] - > node_id ) ) ) ;
2024-01-31 15:03:11 +10:30
continue ;
}
2024-02-11 21:06:41 +10:30
process_node_announcement ( gm , gossmap , node ,
2024-01-31 15:03:11 +10:30
pnas [ i ] - > timestamp ,
& pnas [ i ] - > node_id ,
pnas [ i ] - > nannounce ,
pnas [ i ] - > source_peer ) ;
}
/* Won't add any new ones */
2024-01-31 15:03:12 +10:30
assert ( map_empty ( & gm - > pending_ann_map ) ) ;
assert ( map_empty ( & gm - > early_ann_map ) ) ;
2024-01-31 15:03:11 +10:30
tal_free ( pnas ) ;
}
}
static void kill_spent_channel ( struct gossmap_manage * gm ,
struct gossmap * gossmap ,
struct short_channel_id scid )
{
struct gossmap_chan * chan ;
chan = gossmap_find_chan ( gossmap , & scid ) ;
if ( ! chan ) {
status_broken ( " Dying channel %s already deleted? " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
return ;
}
status_debug ( " Deleting channel %s due to the funding outpoint being "
" spent " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
remove_channel ( gm , gossmap , chan , scid ) ;
}
void gossmap_manage_new_block ( struct gossmap_manage * gm , u32 new_blockheight )
{
u64 idx ;
2024-01-31 15:03:12 +10:30
for ( struct pending_cannounce * pca = uintmap_first ( & gm - > early_ann_map . map , & idx ) ;
2024-01-31 15:03:11 +10:30
pca ! = NULL ;
2024-01-31 15:03:12 +10:30
pca = uintmap_after ( & gm - > early_ann_map . map , & idx ) ) {
2024-01-31 15:03:11 +10:30
struct short_channel_id scid ;
scid . u64 = idx ;
/* Stop when we are at unreachable heights */
2024-03-20 12:29:51 +10:30
if ( ! is_scid_depth_announceable ( scid , new_blockheight ) )
2024-01-31 15:03:11 +10:30
break ;
2024-01-31 15:03:12 +10:30
map_del ( & gm - > early_ann_map , scid ) ;
2024-01-31 15:03:11 +10:30
2024-01-31 15:03:12 +10:30
if ( ! map_add ( & gm - > pending_ann_map , scid , pca ) ) {
2024-01-31 15:03:11 +10:30
/* Already pending? Ignore */
tal_free ( pca ) ;
continue ;
}
status_debug ( " gossmap_manage: new block, adding %s to pending... " ,
2024-03-20 11:10:16 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
/* Ask lightningd about this scid: see
* gossmap_manage_handle_get_txout_reply */
daemon_conn_send ( gm - > daemon - > master ,
2024-03-20 12:29:51 +10:30
take ( towire_gossipd_get_txout ( NULL , scid ) ) ) ;
2024-01-31 15:03:11 +10:30
}
for ( size_t i = 0 ; i < tal_count ( gm - > dying_channels ) ; i + + ) {
2024-02-14 16:47:56 +10:30
struct gossmap * gossmap ;
2024-01-31 16:38:20 +10:30
if ( gm - > dying_channels [ i ] . deadline > new_blockheight )
2024-01-31 15:03:11 +10:30
continue ;
2024-02-14 16:47:56 +10:30
/* Refresh gossmap each time in case we move things in the loop:
* in particular , we might move a node_announcement twice ! */
gossmap = gossmap_manage_get_gossmap ( gm ) ;
2024-01-31 15:03:11 +10:30
kill_spent_channel ( gm , gossmap , gm - > dying_channels [ i ] . scid ) ;
gossip_store_del ( gm - > daemon - > gs ,
2024-01-31 16:14:14 +10:30
gm - > dying_channels [ i ] . gossmap_offset ,
2024-01-31 15:03:11 +10:30
WIRE_GOSSIP_STORE_CHAN_DYING ) ;
tal_arr_remove ( & gm - > dying_channels , i ) ;
}
}
void gossmap_manage_channel_spent ( struct gossmap_manage * gm ,
u32 blockheight ,
struct short_channel_id scid )
{
struct gossmap_chan * chan ;
const struct gossmap_node * me ;
const u8 * msg ;
2024-01-31 16:38:20 +10:30
struct chan_dying cd ;
2024-01-31 15:03:11 +10:30
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
chan = gossmap_find_chan ( gossmap , & scid ) ;
if ( ! chan )
return ;
me = gossmap_find_node ( gossmap , & gm - > daemon - > id ) ;
/* We delete our own channels immediately, since we have local knowledge */
if ( gossmap_nth_node ( gossmap , chan , 0 ) = = me
| | gossmap_nth_node ( gossmap , chan , 1 ) = = me ) {
kill_spent_channel ( gm , gossmap , scid ) ;
return ;
}
/* BOLT #7:
* - once its funding output has been spent OR reorganized out :
* - SHOULD forget a channel after a 12 - block delay .
*/
2024-01-31 16:38:20 +10:30
cd . deadline = blockheight + 12 ;
cd . scid = scid ;
2024-01-31 15:03:11 +10:30
/* Remember locally so we can kill it in 12 blocks */
status_debug ( " channel %s closing soon due "
" to the funding outpoint being spent " ,
2024-03-20 11:17:52 +10:30
fmt_short_channel_id ( tmpctx , scid ) ) ;
2024-01-31 15:03:11 +10:30
/* Save to gossip_store in case we restart */
2024-03-20 12:29:51 +10:30
msg = towire_gossip_store_chan_dying ( tmpctx , cd . scid , cd . deadline ) ;
2024-01-31 16:38:20 +10:30
cd . gossmap_offset = gossip_store_add ( gm - > daemon - > gs , msg , 0 ) ;
tal_arr_expand ( & gm - > dying_channels , cd ) ;
2024-01-31 15:03:11 +10:30
/* Mark it dying, so we don't gossip it */
2024-01-31 16:14:14 +10:30
gossip_store_set_flag ( gm - > daemon - > gs , chan - > cann_off ,
GOSSIP_STORE_DYING_BIT ,
WIRE_CHANNEL_ANNOUNCEMENT ) ;
2024-01-31 15:03:11 +10:30
/* Channel updates too! */
for ( int dir = 0 ; dir < 2 ; dir + + ) {
if ( ! gossmap_chan_set ( chan , dir ) )
continue ;
2024-01-31 16:14:14 +10:30
gossip_store_set_flag ( gm - > daemon - > gs ,
chan - > cupdate_off [ dir ] ,
GOSSIP_STORE_DYING_BIT ,
WIRE_CHANNEL_UPDATE ) ;
2024-01-31 15:03:11 +10:30
}
2024-02-11 21:02:41 +10:30
/* If all channels associated with either node are dying, node_announcement is dying
too ( so we don ' t broadcast ) */
for ( int dir = 0 ; dir < 2 ; dir + + ) {
struct gossmap_node * n = gossmap_nth_node ( gossmap , chan , dir ) ;
if ( ! gossmap_node_announced ( n ) )
continue ;
/* Don't get confused if a node has a channel with self! */
if ( dir = = 1 & & n = = gossmap_nth_node ( gossmap , chan , 0 ) )
continue ;
2024-02-11 21:05:41 +10:30
/* Are all (other) channels dying? */
if ( all_node_channels_dying ( gossmap , n , chan ) ) {
2024-02-11 21:02:41 +10:30
gossip_store_set_flag ( gm - > daemon - > gs ,
n - > nann_off ,
GOSSIP_STORE_DYING_BIT ,
WIRE_NODE_ANNOUNCEMENT ) ;
}
}
2024-01-31 15:03:11 +10:30
}
struct gossmap * gossmap_manage_get_gossmap ( struct gossmap_manage * gm )
{
gossmap_refresh ( gm - > raw_gossmap , NULL ) ;
return gm - > raw_gossmap ;
}
/* BOLT #7:
2024-06-19 10:06:41 +09:30
* A node :
2024-01-31 15:03:11 +10:30
* - MUST NOT relay any gossip messages it did not generate itself ,
* unless explicitly requested .
*/
/* i.e. the strong implication is that we spam our own gossip aggressively!
* " Look at me! " " Look at me!!!! " .
*/
/* Statistically, how many peers to we tell about each channel? */
# define GOSSIP_SPAM_REDUNDANCY 5
void gossmap_manage_new_peer ( struct gossmap_manage * gm ,
const struct node_id * peer )
{
struct gossmap_node * me ;
const u8 * msg ;
u64 send_threshold ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
/* Find ourselves; if no channels, nothing to send */
me = gossmap_find_node ( gossmap , & gm - > daemon - > id ) ;
if ( ! me )
return ;
send_threshold = - 1ULL ;
/* Just in case we have many peers and not all are connecting or
* some other corner case , send everything to first few . */
if ( peer_node_id_map_count ( gm - > daemon - > peers ) > GOSSIP_SPAM_REDUNDANCY
& & me - > num_chans > GOSSIP_SPAM_REDUNDANCY ) {
send_threshold = - 1ULL / me - > num_chans * GOSSIP_SPAM_REDUNDANCY ;
}
for ( size_t i = 0 ; i < me - > num_chans ; i + + ) {
struct gossmap_chan * chan = gossmap_nth_chan ( gossmap , me , i , NULL ) ;
/* We set this so we'll send a fraction of all our channels */
if ( pseudorand_u64 ( ) > send_threshold )
continue ;
/* Send channel_announce */
msg = gossmap_chan_get_announce ( NULL , gossmap , chan ) ;
queue_peer_msg ( gm - > daemon , peer , take ( msg ) ) ;
/* Send both channel_updates (if they exist): both help people
* use our channel , so we care ! */
for ( int dir = 0 ; dir < 2 ; dir + + ) {
if ( ! gossmap_chan_set ( chan , dir ) )
continue ;
msg = gossmap_chan_get_update ( NULL , gossmap , chan , dir ) ;
queue_peer_msg ( gm - > daemon , peer , take ( msg ) ) ;
}
}
/* If we have one, we should send our own node_announcement */
msg = gossmap_node_get_announce ( NULL , gossmap , me ) ;
if ( msg )
queue_peer_msg ( gm - > daemon , peer , take ( msg ) ) ;
}
2024-01-31 15:03:11 +10:30
2024-01-31 15:03:12 +10:30
void gossmap_manage_tell_lightningd_locals ( struct daemon * daemon ,
struct gossmap_manage * gm )
{
struct gossmap_node * me ;
const u8 * nannounce ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
/* Find ourselves; if no channels, nothing to send */
me = gossmap_find_node ( gossmap , & gm - > daemon - > id ) ;
if ( ! me )
return ;
for ( size_t i = 0 ; i < me - > num_chans ; i + + ) {
2024-10-14 18:13:40 +10:30
int dir ;
struct gossmap_chan * chan = gossmap_nth_chan ( gossmap , me , i , & dir ) ;
2024-01-31 15:03:12 +10:30
struct short_channel_id scid ;
const u8 * cupdate ;
scid = gossmap_chan_scid ( gossmap , chan ) ;
2024-10-14 18:13:40 +10:30
cupdate = gossmap_chan_get_update ( tmpctx , gossmap , chan , dir ) ;
2024-01-31 15:03:12 +10:30
if ( cupdate )
daemon_conn_send ( daemon - > master ,
take ( towire_gossipd_init_cupdate ( NULL ,
2024-03-20 12:29:51 +10:30
scid ,
2024-01-31 15:03:12 +10:30
cupdate ) ) ) ;
2024-10-14 18:13:40 +10:30
cupdate = gossmap_chan_get_update ( tmpctx , gossmap , chan , ! dir ) ;
if ( cupdate ) {
struct peer_update peer_update ;
secp256k1_ecdsa_signature signature ;
u32 timestamp ;
u8 message_flags , channel_flags ;
struct bitcoin_blkid chain_hash ;
if ( ! fromwire_channel_update ( cupdate , & signature ,
& chain_hash , & peer_update . scid ,
& timestamp , & message_flags ,
& channel_flags , & peer_update . cltv_delta ,
& peer_update . htlc_minimum_msat ,
& peer_update . fee_base ,
& peer_update . fee_ppm ,
& peer_update . htlc_maximum_msat ) ) {
status_broken ( " Invalid remote cupdate in store: %s " ,
tal_hex ( tmpctx , cupdate ) ) ;
continue ;
}
2024-01-31 15:03:12 +10:30
daemon_conn_send ( daemon - > master ,
2024-10-14 18:13:40 +10:30
take ( towire_gossipd_remote_channel_update ( NULL ,
NULL ,
& peer_update ) ) ) ;
}
2024-01-31 15:03:12 +10:30
}
/* Tell lightningd about our current node_announcement, if any */
nannounce = gossmap_node_get_announce ( tmpctx , gossmap , me ) ;
if ( nannounce )
daemon_conn_send ( daemon - > master ,
take ( towire_gossipd_init_nannounce ( NULL ,
nannounce ) ) ) ;
}
2024-01-31 15:03:11 +10:30
struct wireaddr * gossmap_manage_get_node_addresses ( const tal_t * ctx ,
struct gossmap_manage * gm ,
const struct node_id * node_id )
{
struct gossmap_node * node ;
u8 * nannounce ;
struct node_id id ;
secp256k1_ecdsa_signature signature ;
u32 timestamp ;
u8 * addresses , * features ;
u8 rgb_color [ 3 ] , alias [ 32 ] ;
struct tlv_node_ann_tlvs * na_tlvs ;
struct wireaddr * wireaddrs ;
struct gossmap * gossmap = gossmap_manage_get_gossmap ( gm ) ;
node = gossmap_find_node ( gossmap , node_id ) ;
if ( ! node )
return NULL ;
nannounce = gossmap_node_get_announce ( tmpctx , gossmap ,
node ) ;
if ( ! nannounce )
return NULL ;
if ( ! fromwire_node_announcement ( tmpctx , nannounce ,
& signature , & features ,
& timestamp ,
& id , rgb_color , alias ,
& addresses ,
& na_tlvs ) ) {
status_broken ( " Bad node_announcement for %s in gossip_store: %s " ,
2024-03-20 11:10:16 +10:30
fmt_node_id ( tmpctx , node_id ) ,
2024-01-31 15:03:11 +10:30
tal_hex ( tmpctx , nannounce ) ) ;
return NULL ;
}
wireaddrs = fromwire_wireaddr_array ( ctx , addresses ) ;
if ( ! wireaddrs ) {
status_broken ( " Bad wireaddrs in node_announcement in gossip_store: %s " ,
tal_hex ( tmpctx , nannounce ) ) ;
return NULL ;
}
return wireaddrs ;
}