@ -156,6 +156,7 @@ struct peer {
/* Are there outstanding responses for queries on short_channel_ids? */
/* Are there outstanding responses for queries on short_channel_ids? */
const struct short_channel_id * scid_queries ;
const struct short_channel_id * scid_queries ;
const bigsize_t * scid_query_flags ;
size_t scid_query_idx ;
size_t scid_query_idx ;
/* Are there outstanding node_announcements from scid_queries? */
/* Are there outstanding node_announcements from scid_queries? */
@ -721,6 +722,8 @@ static const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg
struct bitcoin_blkid chain ;
struct bitcoin_blkid chain ;
u8 * encoded ;
u8 * encoded ;
struct short_channel_id * scids ;
struct short_channel_id * scids ;
bigsize_t * flags ;
# if EXPERIMENTAL_FEATURES
# if EXPERIMENTAL_FEATURES
struct tlv_query_short_channel_ids_tlvs * tlvs
struct tlv_query_short_channel_ids_tlvs * tlvs
= tlv_query_short_channel_ids_tlvs_new ( tmpctx ) ;
= tlv_query_short_channel_ids_tlvs_new ( tmpctx ) ;
@ -731,12 +734,22 @@ static const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg
" Bad query_short_channel_ids w/tlvs %s " ,
" Bad query_short_channel_ids w/tlvs %s " ,
tal_hex ( tmpctx , msg ) ) ;
tal_hex ( tmpctx , msg ) ) ;
}
}
if ( tlvs - > query_flags ) {
flags = decode_scid_query_flags ( tmpctx , tlvs - > query_flags ) ;
if ( ! flags ) {
return towire_errorfmt ( peer , NULL ,
" Bad query_short_channel_ids query_flags %s " ,
tal_hex ( tmpctx , msg ) ) ;
}
} else
flags = NULL ;
# else
# else
if ( ! fromwire_query_short_channel_ids ( tmpctx , msg , & chain , & encoded ) ) {
if ( ! fromwire_query_short_channel_ids ( tmpctx , msg , & chain , & encoded ) ) {
return towire_errorfmt ( peer , NULL ,
return towire_errorfmt ( peer , NULL ,
" Bad query_short_channel_ids %s " ,
" Bad query_short_channel_ids %s " ,
tal_hex ( tmpctx , msg ) ) ;
tal_hex ( tmpctx , msg ) ) ;
}
}
flags = NULL ;
# endif
# endif
if ( ! bitcoin_blkid_eq ( & peer - > daemon - > chain_hash , & chain ) ) {
if ( ! bitcoin_blkid_eq ( & peer - > daemon - > chain_hash , & chain ) ) {
@ -765,6 +778,27 @@ static const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg
tal_hex ( tmpctx , encoded ) ) ;
tal_hex ( tmpctx , encoded ) ) ;
}
}
/* BOLT-61a1365a45cc8b463ddbbe3429d350f8eac787dd #7:
*
* The receiver :
* . . .
* - if the incoming message includes ` query_short_channel_ids_tlvs ` :
* - if ` encoded_query_flags ` does not decode to exactly one flag per
* ` short_channel_id ` :
* - MAY fail the connection .
*/
if ( ! flags ) {
/* Pretend they asked for everything. */
flags = tal_arr ( tmpctx , bigsize_t , tal_count ( scids ) ) ;
memset ( flags , 0xFF , tal_bytelen ( flags ) ) ;
} else {
if ( tal_count ( flags ) ! = tal_count ( scids ) ) {
return towire_errorfmt ( peer , NULL ,
" Bad query_short_channel_ids flags count %zu scids %zu " ,
tal_count ( flags ) , tal_count ( scids ) ) ;
}
}
/* BOLT #7:
/* BOLT #7:
*
*
* - MUST respond to each known ` short_channel_id ` with a ` channel_announcement `
* - MUST respond to each known ` short_channel_id ` with a ` channel_announcement `
@ -773,6 +807,7 @@ static const u8 *handle_query_short_channel_ids(struct peer *peer, const u8 *msg
* these .
* these .
*/
*/
peer - > scid_queries = tal_steal ( peer , scids ) ;
peer - > scid_queries = tal_steal ( peer , scids ) ;
peer - > scid_query_flags = tal_steal ( peer , flags ) ;
peer - > scid_query_idx = 0 ;
peer - > scid_query_idx = 0 ;
peer - > scid_query_nodes = tal_arr ( peer , struct node_id , 0 ) ;
peer - > scid_query_nodes = tal_arr ( peer , struct node_id , 0 ) ;
@ -1262,15 +1297,45 @@ static void maybe_create_next_scid_reply(struct peer *peer)
if ( ! chan | | ! is_chan_public ( chan ) )
if ( ! chan | | ! is_chan_public ( chan ) )
continue ;
continue ;
/* BOLT-61a1365a45cc8b463ddbbe3429d350f8eac787dd #7:
* - if bit 0 of ` query_flag ` is set :
* - MUST reply with a ` channel_announcement `
*/
if ( peer - > scid_query_flags [ i ] & SCID_QF_ANNOUNCE )
queue_peer_from_store ( peer , & chan - > bcast ) ;
queue_peer_from_store ( peer , & chan - > bcast ) ;
if ( is_halfchan_defined ( & chan - > half [ 0 ] ) )
/* BOLT-61a1365a45cc8b463ddbbe3429d350f8eac787dd #7:
* - if bit 1 of ` query_flag ` is set and it has received a
* ` channel_update ` from ` node_id_1 ` :
* - MUST reply with the latest ` channel_update ` for
* ` node_id_1 `
* - if bit 2 of ` query_flag ` is set and it has received a
* ` channel_update ` from ` node_id_2 ` :
* - MUST reply with the latest ` channel_update ` for
* ` node_id_2 ` */
if ( ( peer - > scid_query_flags [ i ] & SCID_QF_UPDATE1 )
& & is_halfchan_defined ( & chan - > half [ 0 ] ) )
queue_peer_from_store ( peer , & chan - > half [ 0 ] . bcast ) ;
queue_peer_from_store ( peer , & chan - > half [ 0 ] . bcast ) ;
if ( is_halfchan_defined ( & chan - > half [ 1 ] ) )
if ( ( peer - > scid_query_flags [ i ] & SCID_QF_UPDATE2 )
& & is_halfchan_defined ( & chan - > half [ 1 ] ) )
queue_peer_from_store ( peer , & chan - > half [ 1 ] . bcast ) ;
queue_peer_from_store ( peer , & chan - > half [ 1 ] . bcast ) ;
/* Record node ids for later transmission of node_announcement */
/* BOLT-61a1365a45cc8b463ddbbe3429d350f8eac787dd #7:
tal_arr_expand ( & peer - > scid_query_nodes , chan - > nodes [ 0 ] - > id ) ;
* - if bit 3 of ` query_flag ` is set and it has received
tal_arr_expand ( & peer - > scid_query_nodes , chan - > nodes [ 1 ] - > id ) ;
* a ` node_announcement ` from ` node_id_1 ` :
* - MUST reply with the latest ` node_announcement ` for
* ` node_id_1 `
* - if bit 4 of ` query_flag ` is set and it has received a
* ` node_announcement ` from ` node_id_2 ` :
* - MUST reply with the latest ` node_announcement ` for
* ` node_id_2 ` */
/* Save node ids for later transmission of node_announcement */
if ( peer - > scid_query_flags [ i ] & SCID_QF_NODE1 )
tal_arr_expand ( & peer - > scid_query_nodes ,
chan - > nodes [ 0 ] - > id ) ;
if ( peer - > scid_query_flags [ i ] & SCID_QF_NODE2 )
tal_arr_expand ( & peer - > scid_query_nodes ,
chan - > nodes [ 1 ] - > id ) ;
sent = true ;
sent = true ;
}
}
@ -1325,6 +1390,7 @@ static void maybe_create_next_scid_reply(struct peer *peer)
/* We're done! Clean up so we simply pass-through next time. */
/* We're done! Clean up so we simply pass-through next time. */
peer - > scid_queries = tal_free ( peer - > scid_queries ) ;
peer - > scid_queries = tal_free ( peer - > scid_queries ) ;
peer - > scid_query_flags = tal_free ( peer - > scid_query_flags ) ;
peer - > scid_query_idx = 0 ;
peer - > scid_query_idx = 0 ;
peer - > scid_query_nodes = tal_free ( peer - > scid_query_nodes ) ;
peer - > scid_query_nodes = tal_free ( peer - > scid_query_nodes ) ;
peer - > scid_query_nodes_idx = 0 ;
peer - > scid_query_nodes_idx = 0 ;