@ -120,11 +120,14 @@ bool node_map_node_eq(const struct node *n, const struct pubkey *key)
static void destroy_node ( struct node * node , struct routing_state * rstate )
{
struct chan_map_iter i ;
struct chan * c ;
node_map_del ( rstate - > nodes , node ) ;
/* These remove themselves from the array. */
while ( tal_count ( node - > chans ) )
tal_free ( node - > chans [ 0 ] ) ;
/* These remove themselves from the map. */
while ( ( c = chan_map_first ( & node - > chans , & i ) ) ! = NULL )
tal_free ( c ) ;
chan_map_clear ( & node - > chans ) ;
}
struct node * get_node ( struct routing_state * rstate , const struct pubkey * id )
@ -141,7 +144,7 @@ static struct node *new_node(struct routing_state *rstate,
n = tal ( rstate , struct node ) ;
n - > id = * id ;
n - > chans = tal_arr ( n , struct chan * , 0 ) ;
chan_map_init ( & n - > chans ) ;
n - > globalfeatures = NULL ;
n - > node_announcement = NULL ;
n - > node_announcement_index = 0 ;
@ -156,9 +159,15 @@ static struct node *new_node(struct routing_state *rstate,
/* We've received a channel_announce for a channel attached to this node */
static bool node_has_public_channels ( struct node * node )
{
for ( size_t i = 0 ; i < tal_count ( node - > chans ) ; i + + )
if ( is_chan_public ( node - > chans [ i ] ) )
struct chan_map_iter i ;
struct chan * c ;
for ( c = chan_map_first ( & node - > chans , & i ) ;
c ;
c = chan_map_next ( & node - > chans , & i ) ) {
if ( is_chan_public ( c ) )
return true ;
}
return false ;
}
@ -166,39 +175,33 @@ static bool node_has_public_channels(struct node *node)
* we only send once we have a channel_update . */
static bool node_has_broadcastable_channels ( struct node * node )
{
for ( size_t i = 0 ; i < tal_count ( node - > chans ) ; i + + ) {
if ( ! is_chan_public ( node - > chans [ i ] ) )
continue ;
if ( is_halfchan_defined ( & node - > chans [ i ] - > half [ 0 ] )
| | is_halfchan_defined ( & node - > chans [ i ] - > half [ 1 ] ) )
return true ;
}
return false ;
}
static bool remove_channel_from_array ( struct chan * * * chans , const struct chan * c )
{
size_t i , n ;
struct chan_map_iter i ;
struct chan * c ;
n = tal_count ( * chans ) ;
for ( i = 0 ; i < n ; i + + ) {
if ( ( * chans ) [ i ] ! = c )
for ( c = chan_map_first ( & node - > chans , & i ) ;
c ;
c = chan_map_next ( & node - > chans , & i ) ) {
if ( ! is_chan_public ( c ) )
continue ;
n - - ;
memmove ( * chans + i , * chans + i + 1 , sizeof ( * * chans ) * ( n - i ) ) ;
tal_resize ( chans , n ) ;
return true ;
if ( is_halfchan_defined ( & c - > half [ 0 ] )
| | is_halfchan_defined ( & c - > half [ 1 ] ) )
return true ;
}
return false ;
}
static bool node_announce_predates_channels ( const struct node * node )
{
for ( size_t i = 0 ; i < tal_count ( node - > chans ) ; i + + ) {
if ( ! is_chan_announced ( node - > chans [ i ] ) )
struct chan_map_iter i ;
struct chan * c ;
for ( c = chan_map_first ( & node - > chans , & i ) ;
c ;
c = chan_map_next ( & node - > chans , & i ) ) {
if ( ! is_chan_announced ( c ) )
continue ;
if ( node - > chans [ i ] - > channel_announcement_index
if ( c - > channel_announcement_index
< node - > node_announcement_index )
return false ;
}
@ -216,11 +219,11 @@ static u64 persistent_broadcast(struct routing_state *rstate, const u8 *msg, u32
static void remove_chan_from_node ( struct routing_state * rstate ,
struct node * node , const struct chan * chan )
{
if ( ! remove_channel_from_array ( & node - > chans , chan ) )
if ( ! chan_map_del ( & node - > chans , chan ) )
abort ( ) ;
/* Last channel? Simply delete node (and associated announce) */
if ( tal_count ( node - > chans ) = = 0 ) {
if ( node - > chans . raw . elems = = 0 ) {
tal_free ( node ) ;
return ;
}
@ -308,8 +311,8 @@ struct chan *new_chan(struct routing_state *rstate,
chan - > sat = satoshis ;
chan - > local_disabled = false ;
tal_arr_expan d( & n2 - > chans , chan ) ;
tal_arr_expan d( & n1 - > chans , chan ) ;
chan_map_ad d( & n2 - > chans , chan ) ;
chan_map_ad d( & n1 - > chans , chan ) ;
/* Populate with (inactive) connections */
init_half_chan ( rstate , chan , n1idx ) ;
@ -520,15 +523,20 @@ find_route(const tal_t *ctx, struct routing_state *rstate,
for ( n = node_map_first ( rstate - > nodes , & it ) ;
n ;
n = node_map_next ( rstate - > nodes , & it ) ) {
size_t num_edges = tal_count ( n - > chans ) ;
for ( i = 0 ; i < num_edges ; i + + ) {
struct chan * chan = n - > chans [ i ] ;
struct chan_map_iter i ;
struct chan * chan ;
for ( chan = chan_map_first ( & n - > chans , & i ) ;
chan ;
chan = chan_map_next ( & n - > chans , & i ) ) {
int idx = half_chan_to ( n , chan ) ;
SUPERVERBOSE ( " Node %s edge %i/%zu " ,
SUPERVERBOSE ( " Node %s edge %s " ,
type_to_string ( tmpctx , struct pubkey ,
& n - > id ) ,
i , num_edges ) ;
type_to_string ( tmpctx ,
struct short_channel_id ,
& c - > scid ) ) ;
if ( ! hc_is_routable ( chan , idx ) ) {
SUPERVERBOSE ( " ...unroutable (local_disabled = %i, is_halfchan_enabled = %i, unroutable_until = %i " ,
@ -1669,13 +1677,18 @@ void routing_failure(struct routing_state *rstate,
type_to_string ( tmpctx , struct pubkey ,
erring_node_pubkey ) ) ;
} else {
struct chan_map_iter i ;
struct chan * c ;
status_trace ( " Deleting node %s " ,
type_to_string ( tmpctx ,
struct pubkey ,
& node - > id ) ) ;
for ( size_t i = 0 ; i < tal_count ( node - > chans ) ; + + i ) {
for ( c = chan_map_first ( & node - > chans , & i ) ;
c ;
c = chan_map_next ( & node - > chans , & i ) ) {
/* Set it up to be pruned. */
tal_steal ( tmpctx , node - > chans [ i ] ) ;
tal_steal ( tmpctx , c ) ;
}
}
} else {
@ -1745,9 +1758,18 @@ void route_prune(struct routing_state *rstate)
void memleak_remove_routing_tables ( struct htable * memtable ,
const struct routing_state * rstate )
{
struct node * n ;
struct node_map_iter nit ;
memleak_remove_htable ( memtable , & rstate - > nodes - > raw ) ;
memleak_remove_htable ( memtable , & rstate - > pending_node_map - > raw ) ;
memleak_remove_uintmap ( memtable , & rstate - > broadcasts - > broadcasts ) ;
for ( n = node_map_first ( rstate - > nodes , & nit ) ;
n ;
n = node_map_next ( rstate - > nodes , & nit ) ) {
memleak_remove_htable ( memtable , & n - > chans . raw ) ;
}
}
# endif /* DEVELOPER */