@ -1,12 +1,16 @@
# include "../channel.c"
# include "../invoice.c"
# include "../peer_control.c"
# include "../routehint.c"
# include <ccan/alignof/alignof.h>
# include <common/errcode.h>
bool deprecated_apis = false ;
/* AUTOGENERATED MOCKS START */
/* Generated stub for active_channel_by_scid */
struct channel * active_channel_by_scid ( struct lightningd * ld UNNEEDED ,
const struct short_channel_id * scid UNNEEDED )
{ fprintf ( stderr , " active_channel_by_scid called! \n " ) ; abort ( ) ; }
/* Generated stub for bitcoind_getutxout_ */
void bitcoind_getutxout_ ( struct bitcoind * bitcoind UNNEEDED ,
const struct bitcoin_txid * txid UNNEEDED , const u32 outnum UNNEEDED ,
@ -36,6 +40,41 @@ void broadcast_tx(struct chain_topology *topo UNNEEDED,
bool success UNNEEDED ,
const char * err ) )
{ fprintf ( stderr , " broadcast_tx called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_fail_forget */
void channel_fail_forget ( struct channel * channel UNNEEDED , const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " channel_fail_forget called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_fail_permanent */
void channel_fail_permanent ( struct channel * channel UNNEEDED , const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " channel_fail_permanent called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_fail_reconnect */
void channel_fail_reconnect ( struct channel * channel UNNEEDED ,
const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " channel_fail_reconnect called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_fail_reconnect_later */
void channel_fail_reconnect_later ( struct channel * channel UNNEEDED ,
const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " channel_fail_reconnect_later called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_has_htlc_in */
struct htlc_in * channel_has_htlc_in ( struct channel * channel UNNEEDED )
{ fprintf ( stderr , " channel_has_htlc_in called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_has_htlc_out */
struct htlc_out * channel_has_htlc_out ( struct channel * channel UNNEEDED )
{ fprintf ( stderr , " channel_has_htlc_out called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_internal_error */
void channel_internal_error ( struct channel * channel UNNEEDED , const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " channel_internal_error called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_set_billboard */
void channel_set_billboard ( struct channel * channel UNNEEDED , bool perm UNNEEDED ,
const char * str TAKES UNNEEDED )
{ fprintf ( stderr , " channel_set_billboard called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_set_state */
void channel_set_state ( struct channel * channel UNNEEDED ,
enum channel_state old_state UNNEEDED ,
enum channel_state state UNNEEDED )
{ fprintf ( stderr , " channel_set_state called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_state_name */
const char * channel_state_name ( const struct channel * channel UNNEEDED )
{ fprintf ( stderr , " channel_state_name called! \n " ) ; abort ( ) ; }
/* Generated stub for channel_tell_depth */
bool channel_tell_depth ( struct lightningd * ld UNNEEDED ,
struct channel * channel UNNEEDED ,
@ -75,14 +114,13 @@ void connect_succeeded(struct lightningd *ld UNNEEDED, const struct peer *peer U
void delay_then_reconnect ( struct channel * channel UNNEEDED , u32 seconds_delay UNNEEDED ,
const struct wireaddr_internal * addrhint TAKES UNNEEDED )
{ fprintf ( stderr , " delay_then_reconnect called! \n " ) ; abort ( ) ; }
/* Generated stub for delete_channel */
void delete_channel ( struct channel * channel STEALS UNNEEDED )
{ fprintf ( stderr , " delete_channel called! \n " ) ; abort ( ) ; }
/* Generated stub for derive_channel_id */
void derive_channel_id ( struct channel_id * channel_id UNNEEDED ,
const struct bitcoin_txid * txid UNNEEDED , u16 txout UNNEEDED )
{ fprintf ( stderr , " derive_channel_id called! \n " ) ; abort ( ) ; }
/* Generated stub for dup_fee_states */
struct fee_states * dup_fee_states ( const tal_t * ctx UNNEEDED ,
const struct fee_states * fee_states TAKES UNNEEDED )
{ fprintf ( stderr , " dup_fee_states called! \n " ) ; abort ( ) ; }
/* Generated stub for encode_scriptpubkey_to_addr */
char * encode_scriptpubkey_to_addr ( const tal_t * ctx UNNEEDED ,
const struct chainparams * chainparams UNNEEDED ,
@ -119,9 +157,6 @@ bool fromwire_connectd_peer_connected(const tal_t *ctx UNNEEDED, const void *p U
/* Generated stub for fromwire_gossipd_get_incoming_channels_reply */
bool fromwire_gossipd_get_incoming_channels_reply ( const tal_t * ctx UNNEEDED , const void * p UNNEEDED , struct route_info * * public_route_info UNNEEDED , bool * * public_deadends UNNEEDED , struct route_info * * private_route_info UNNEEDED , bool * * private_deadends UNNEEDED )
{ fprintf ( stderr , " fromwire_gossipd_get_incoming_channels_reply called! \n " ) ; abort ( ) ; }
/* Generated stub for fromwire_hsmd_get_channel_basepoints_reply */
bool fromwire_hsmd_get_channel_basepoints_reply ( const void * p UNNEEDED , struct basepoints * basepoints UNNEEDED , struct pubkey * funding_pubkey UNNEEDED )
{ fprintf ( stderr , " fromwire_hsmd_get_channel_basepoints_reply called! \n " ) ; abort ( ) ; }
/* Generated stub for fromwire_hsmd_sign_commitment_tx_reply */
bool fromwire_hsmd_sign_commitment_tx_reply ( const void * p UNNEEDED , struct bitcoin_signature * sig UNNEEDED )
{ fprintf ( stderr , " fromwire_hsmd_sign_commitment_tx_reply called! \n " ) ; abort ( ) ; }
@ -287,11 +322,6 @@ void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED,
struct bolt11 * new_bolt11 ( const tal_t * ctx UNNEEDED ,
const struct amount_msat * msat TAKES UNNEEDED )
{ fprintf ( stderr , " new_bolt11 called! \n " ) ; abort ( ) ; }
/* Generated stub for new_log */
struct log * new_log ( const tal_t * ctx UNNEEDED , struct log_book * record UNNEEDED ,
const struct node_id * default_node_id UNNEEDED ,
const char * fmt UNNEEDED , . . . )
{ fprintf ( stderr , " new_log called! \n " ) ; abort ( ) ; }
/* Generated stub for new_reltimer_ */
struct oneshot * new_reltimer_ ( struct timers * timers UNNEEDED ,
const tal_t * ctx UNNEEDED ,
@ -416,12 +446,18 @@ struct command_result *param_u64(struct command *cmd UNNEEDED, const char *name
const char * buffer UNNEEDED , const jsmntok_t * tok UNNEEDED ,
uint64_t * * num UNNEEDED )
{ fprintf ( stderr , " param_u64 called! \n " ) ; abort ( ) ; }
/* Generated stub for peer_active_channel */
struct channel * peer_active_channel ( struct peer * peer UNNEEDED )
{ fprintf ( stderr , " peer_active_channel called! \n " ) ; abort ( ) ; }
/* Generated stub for peer_get_owning_subd */
struct subd * peer_get_owning_subd ( struct peer * peer UNNEEDED )
{ fprintf ( stderr , " peer_get_owning_subd called! \n " ) ; abort ( ) ; }
/* Generated stub for peer_memleak_done */
void peer_memleak_done ( struct command * cmd UNNEEDED , struct subd * leaker UNNEEDED )
{ fprintf ( stderr , " peer_memleak_done called! \n " ) ; abort ( ) ; }
/* Generated stub for peer_normal_channel */
struct channel * peer_normal_channel ( struct peer * peer UNNEEDED )
{ fprintf ( stderr , " peer_normal_channel called! \n " ) ; abort ( ) ; }
/* Generated stub for peer_start_channeld */
void peer_start_channeld ( struct channel * channel UNNEEDED ,
struct per_peer_state * pps UNNEEDED ,
@ -447,9 +483,6 @@ void per_peer_state_set_fds(struct per_peer_state *pps UNNEEDED,
bool plugin_hook_call_ ( struct lightningd * ld UNNEEDED , const struct plugin_hook * hook UNNEEDED ,
tal_t * cb_arg STEALS UNNEEDED )
{ fprintf ( stderr , " plugin_hook_call_ called! \n " ) ; abort ( ) ; }
/* Generated stub for subd_release_channel */
void subd_release_channel ( struct subd * owner UNNEEDED , void * channel UNNEEDED )
{ fprintf ( stderr , " subd_release_channel called! \n " ) ; abort ( ) ; }
/* Generated stub for subd_req_ */
void subd_req_ ( const tal_t * ctx UNNEEDED ,
struct subd * sd UNNEEDED ,
@ -482,9 +515,6 @@ u8 *towire_channeld_specific_feerates(const tal_t *ctx UNNEEDED, u32 feerate_bas
/* Generated stub for towire_connectd_connect_to_peer */
u8 * towire_connectd_connect_to_peer ( const tal_t * ctx UNNEEDED , const struct node_id * id UNNEEDED , u32 seconds_waited UNNEEDED , const struct wireaddr_internal * addrhint UNNEEDED )
{ fprintf ( stderr , " towire_connectd_connect_to_peer called! \n " ) ; abort ( ) ; }
/* Generated stub for towire_connectd_peer_disconnected */
u8 * towire_connectd_peer_disconnected ( const tal_t * ctx UNNEEDED , const struct node_id * id UNNEEDED )
{ fprintf ( stderr , " towire_connectd_peer_disconnected called! \n " ) ; abort ( ) ; }
/* Generated stub for towire_errorfmt */
u8 * towire_errorfmt ( const tal_t * ctx UNNEEDED ,
const struct channel_id * channel UNNEEDED ,
@ -493,9 +523,6 @@ u8 *towire_errorfmt(const tal_t *ctx UNNEEDED,
/* Generated stub for towire_gossipd_get_incoming_channels */
u8 * towire_gossipd_get_incoming_channels ( const tal_t * ctx UNNEEDED )
{ fprintf ( stderr , " towire_gossipd_get_incoming_channels called! \n " ) ; abort ( ) ; }
/* Generated stub for towire_hsmd_get_channel_basepoints */
u8 * towire_hsmd_get_channel_basepoints ( const tal_t * ctx UNNEEDED , const struct node_id * peerid UNNEEDED , u64 dbid UNNEEDED )
{ fprintf ( stderr , " towire_hsmd_get_channel_basepoints called! \n " ) ; abort ( ) ; }
/* Generated stub for towire_hsmd_sign_commitment_tx */
u8 * towire_hsmd_sign_commitment_tx ( const tal_t * ctx UNNEEDED , const struct node_id * peer_id UNNEEDED , u64 channel_dbid UNNEEDED , const struct bitcoin_tx * tx UNNEEDED , const struct pubkey * remote_funding_key UNNEEDED )
{ fprintf ( stderr , " towire_hsmd_sign_commitment_tx called! \n " ) ; abort ( ) ; }
@ -518,9 +545,6 @@ const char *version(void)
void wallet_annotate_txout ( struct wallet * w UNNEEDED , const struct bitcoin_txid * txid UNNEEDED ,
int outnum UNNEEDED , enum wallet_tx_type type UNNEEDED , u64 channel UNNEEDED )
{ fprintf ( stderr , " wallet_annotate_txout called! \n " ) ; abort ( ) ; }
/* Generated stub for wallet_channel_close */
void wallet_channel_close ( struct wallet * w UNNEEDED , u64 wallet_id UNNEEDED )
{ fprintf ( stderr , " wallet_channel_close called! \n " ) ; abort ( ) ; }
/* Generated stub for wallet_channel_save */
void wallet_channel_save ( struct wallet * w UNNEEDED , struct channel * chan UNNEEDED )
{ fprintf ( stderr , " wallet_channel_save called! \n " ) ; abort ( ) ; }
@ -663,18 +687,27 @@ bool dev_disconnect_permanent(struct lightningd *ld UNNEEDED)
{ fprintf ( stderr , " dev_disconnect_permanent called! \n " ) ; abort ( ) ; }
# endif
static void add_inchan ( struct route_info * * inchans , int n )
static void add_candidate ( struct routehint_candidate * * candidates , int n ,
struct channel * c )
{
struct route_info r ;
memset ( & r . pubkey , n , sizeof ( r . pubkey ) ) ;
memset ( & r . short_channel_id , n , sizeof ( r . short_channel_id ) ) ;
r . fee_base_msat = r . fee_proportional_millionths = r . cltv_expiry_delta
struct routehint_candidate candidate ;
candidate . r = tal ( * candidates , struct route_info ) ;
memset ( & candidate . r - > pubkey , n , sizeof ( candidate . r - > pubkey ) ) ;
memset ( & candidate . r - > short_channel_id , n ,
sizeof ( candidate . r - > short_channel_id ) ) ;
candidate . r - > fee_base_msat
= candidate . r - > fee_proportional_millionths
= candidate . r - > cltv_expiry_delta
= n ;
tal_arr_expand ( inchans , r ) ;
candidate . c = c ;
candidate . capacity = amount_msat ( n * 1000 - 1 ) ;
tal_arr_expand ( candidates , candidate ) ;
}
static void add_peer ( struct lightningd * ld , int n , enum channel_state state ,
bool connected )
static struct channel * add_peer ( struct lightningd * ld , int n ,
enum channel_state state ,
bool connected )
{
struct peer * peer = tal ( ld , struct peer ) ;
struct channel * c = tal ( peer , struct channel ) ;
@ -695,6 +728,8 @@ static void add_peer(struct lightningd *ld, int n, enum channel_state state,
c - > our_config . htlc_minimum = AMOUNT_MSAT ( 0 ) ;
c - > channel_info . their_config . channel_reserve = AMOUNT_SAT ( 0 ) ;
list_add_tail ( & peer - > channels , & c - > list ) ;
return c ;
}
/* There *is* padding in this structure, after pubkey and after cltv_expiry_delta. */
@ -709,9 +744,7 @@ STRUCTEQ_DEF(route_info,
int main ( void )
{
struct lightningd * ld ;
bool any_offline ;
struct route_info * inchans ;
bool * deadends ;
struct routehint_candidate * candidates ;
struct route_info * * ret ;
size_t n ;
@ -725,70 +758,51 @@ int main(void)
htlc_in_map_init ( & ld - > htlcs_in ) ;
chainparams = chainparams_for_network ( " regtest " ) ;
inchans = tal_arr ( tmpctx , struct route_info , 0 ) ;
deadends = tal_arrz ( tmpctx , bool , 100 ) ;
candidates = tal_arr ( tmpctx , struct routehint_candidate , 0 ) ;
/* 1. Nothing to choose from -> NULL result. */
assert ( select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) = = NULL ) ;
assert ( any_offline = = false ) ;
/* 2. inchan but no corresponding peer -> NULL result. */
add_inchan ( & inchans , 0 ) ;
assert ( select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) = = NULL ) ;
assert ( any_offline = = false ) ;
/* 3. inchan but its peer in awaiting lockin -> NULL result. */
add_peer ( ld , 0 , CHANNELD_AWAITING_LOCKIN , true ) ;
assert ( select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) = = NULL ) ;
assert ( any_offline = = false ) ;
/* 4. connected peer but no corresponding inchan -> NULL result. */
add_peer ( ld , 1 , CHANNELD_NORMAL , true ) ;
assert ( select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) = = NULL ) ;
assert ( any_offline = = false ) ;
/* 5. inchan but its peer (replaced with one) offline -> NULL result. */
list_del_from ( & ld - > peers , & list_tail ( & ld - > peers , struct peer , list ) - > list ) ;
add_peer ( ld , 1 , CHANNELD_NORMAL , false ) ;
add_inchan ( & inchans , 1 ) ;
assert ( select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) = = NULL ) ;
assert ( any_offline = = true ) ;
/* 6. Finally, a correct peer! */
add_inchan ( & inchans , 2 ) ;
add_peer ( ld , 2 , CHANNELD_NORMAL , true ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , inchans , deadends , & any_offline ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 0 ) , candidates ) ;
assert ( tal_count ( ret ) = = 0 ) ;
/* 2. One peer (999 msat capacity) */
add_candidate ( & candidates , 1 , add_peer ( ld , 1 , CHANNELD_NORMAL , true ) ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1000 ) , candidates ) ;
assert ( tal_count ( ret ) = = 0 ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 999 ) , candidates ) ;
assert ( tal_count ( ret ) = = 1 ) ;
assert ( tal_count ( ret [ 0 ] ) = = 1 ) ;
assert ( route_info_eq ( ret [ 0 ] , candidates [ 0 ] . r ) ) ;
/* 3. Two peers (999 msat capacity and 1999 msat) */
add_candidate ( & candidates , 2 , add_peer ( ld , 2 , CHANNELD_NORMAL , true ) ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1000 ) , candidates ) ;
assert ( tal_count ( ret ) = = 1 ) ;
assert ( tal_count ( ret [ 0 ] ) = = 1 ) ;
assert ( any_offline = = true ) ; /* Peer 1 is offline */
assert ( route_info_eq ( ret [ 0 ] , & inchans [ 2 ] ) ) ;
assert ( route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r ) ) ;
/* 7. Correct peer with just enough capacity_to_pay_us */
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1999 ) , inchans , deadends , & any_offline ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1999 ) , candidates ) ;
assert ( tal_count ( ret ) = = 1 ) ;
assert ( tal_count ( ret [ 0 ] ) = = 1 ) ;
assert ( any_offline = = false ) ; /* Other candidate insufficient funds. */
assert ( route_info_eq ( ret [ 0 ] , & inchans [ 2 ] ) ) ;
assert ( route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r ) ) ;
/* 8. Not if we ask for too much! Our balance is 1msat. */
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 2000 ) , inchans , deadends , & any_offline ) ;
assert ( ret = = NULL ) ;
assert ( any_offline = = false ) ; /* Other candidate insufficient funds. */
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 2000 ) , candidates ) ;
assert ( tal_count ( ret ) = = 0 ) ;
/* 9. Add another peer */
add_inchan ( & inchans , 3 ) ;
add_peer ( ld , 3 , CHANNELD_NORMAL , true ) ;
/* 9. Add another peer (2999 capacity) */
add_candidate ( & candidates , 3 , add_peer ( ld , 3 , CHANNELD_NORMAL , true ) ) ;
/* Simulate selection ratios between excesses 25% and 50% of capacity*/
for ( size_t i = n = 0 ; i < 1000 ; i + + ) {
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1499 ) , inchans , deadends , & any_offline ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1499 ) , candidates ) ;
assert ( tal_count ( ret ) = = 1 ) ;
assert ( tal_count ( ret [ 0 ] ) = = 1 ) ;
assert ( any_offline = = false ) ; /* Other candidate insufficient funds. */
assert ( route_info_eq ( ret [ 0 ] , & inchans [ 2 ] )
| | route_info_eq ( ret [ 0 ] , & inchans [ 3 ] ) ) ;
n + = route_info_eq ( ret [ 0 ] , & inchans [ 2 ] ) ;
assert ( route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r )
| | route_info_eq ( ret [ 0 ] , candidates [ 2 ] . r ) ) ;
n + = route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r ) ;
}
/* Handwave over probability of this happening! Within 20% */
@ -797,20 +811,16 @@ int main(void)
n , 1000 - n ) ;
assert ( n > 333 - 66 & & n < 333 + 66 ) ;
/* 10. Last peer's capacity goes from 3 to 2 sat*/
list_tail ( & list_tail ( & ld - > peers , struct peer , list ) - > channels , struct channel , list ) - >
channel_info . their_config . channel_reserve = AMOUNT_SAT ( 1 ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1499 ) , inchans , deadends , & any_offline ) ;
/* 10. Last peer's capacity goes from 3 to 2 sat */
candidates [ 2 ] . c - > channel_info . their_config . channel_reserve = AMOUNT_SAT ( 1 ) ;
/* Simulate selection ratios between excesses 25% and 75% of capacity*/
for ( size_t i = n = 0 ; i < 1000 ; i + + ) {
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1499 ) , inchans , deadends , & any_offline ) ;
ret = select_inchan ( tmpctx , ld , AMOUNT_MSAT ( 1499 ) , candidates ) ;
assert ( tal_count ( ret ) = = 1 ) ;
assert ( tal_count ( ret [ 0 ] ) = = 1 ) ;
assert ( any_offline = = false ) ; /* Other candidate insufficient funds. */
assert ( route_info_eq ( ret [ 0 ] , & inchans [ 2 ] )
| | route_info_eq ( ret [ 0 ] , & inchans [ 3 ] ) ) ;
n + = route_info_eq ( ret [ 0 ] , & inchans [ 2 ] ) ;
assert ( route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r )
| | route_info_eq ( ret [ 0 ] , candidates [ 2 ] . r ) ) ;
n + = route_info_eq ( ret [ 0 ] , candidates [ 1 ] . r ) ;
}
/* Handwave over probability of this happening! Within 20% */