2017-01-10 06:08:33 +01:00
# include "lightningd.h"
# include "peer_control.h"
2017-03-10 11:49:43 +01:00
# include "subd.h"
2017-10-23 06:14:38 +02:00
# include <arpa/inet.h>
2017-03-07 02:03:55 +01:00
# include <bitcoin/script.h>
2017-02-24 06:52:56 +01:00
# include <bitcoin/tx.h>
2018-02-23 06:53:47 +01:00
# include <ccan/array_size/array_size.h>
2017-01-10 06:08:33 +01:00
# include <ccan/io/io.h>
# include <ccan/noerr/noerr.h>
2017-09-04 05:41:34 +02:00
# include <ccan/str/str.h>
2017-01-10 06:08:33 +01:00
# include <ccan/take/take.h>
2017-01-10 06:08:33 +01:00
# include <ccan/tal/str/str.h>
2017-08-29 06:12:04 +02:00
# include <channeld/gen_channel_wire.h>
2017-08-28 18:05:01 +02:00
# include <common/dev_disconnect.h>
2018-01-12 14:35:52 +01:00
# include <common/features.h>
2017-08-28 18:02:01 +02:00
# include <common/initial_commit_tx.h>
2018-03-26 02:08:15 +02:00
# include <common/json_escaped.h>
2017-08-28 18:05:01 +02:00
# include <common/key_derive.h>
# include <common/status.h>
2017-08-28 18:04:01 +02:00
# include <common/timeout.h>
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
# include <common/wire_error.h>
2017-01-10 06:08:33 +01:00
# include <errno.h>
2017-06-24 08:25:51 +02:00
# include <fcntl.h>
2017-08-29 06:12:04 +02:00
# include <gossipd/gen_gossip_wire.h>
2018-01-25 11:44:30 +01:00
# include <gossipd/routing.h>
2017-11-30 17:07:38 +01:00
# include <hsmd/gen_hsm_client_wire.h>
2017-01-10 06:08:33 +01:00
# include <inttypes.h>
2018-02-06 15:46:34 +01:00
# include <lightningd/bitcoind.h>
2017-02-24 06:52:56 +01:00
# include <lightningd/build_utxos.h>
2017-08-28 18:04:01 +02:00
# include <lightningd/chaintopology.h>
2018-02-20 21:59:09 +01:00
# include <lightningd/channel_control.h>
2018-02-20 21:59:09 +01:00
# include <lightningd/closing_control.h>
2018-02-20 21:59:09 +01:00
# include <lightningd/connect_control.h>
2017-06-24 08:50:23 +02:00
# include <lightningd/hsm_control.h>
2018-03-16 04:45:08 +01:00
# include <lightningd/json.h>
2017-08-28 18:04:01 +02:00
# include <lightningd/jsonrpc.h>
# include <lightningd/log.h>
2017-10-23 06:17:38 +02:00
# include <lightningd/netaddress.h>
2018-02-20 21:59:09 +01:00
# include <lightningd/onchain_control.h>
2018-02-20 21:59:04 +01:00
# include <lightningd/opening_control.h>
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
# include <lightningd/options.h>
2017-06-20 07:45:03 +02:00
# include <lightningd/peer_htlcs.h>
2017-06-24 08:25:51 +02:00
# include <unistd.h>
2017-05-23 13:07:42 +02:00
# include <wally_bip32.h>
2017-04-01 12:58:30 +02:00
# include <wire/gen_onion_wire.h>
2017-06-24 08:25:51 +02:00
2018-04-10 08:03:15 +02:00
struct close_command {
/* Inside struct lightningd close_commands. */
struct list_node list ;
/* Command structure. This is the parent of the close command. */
struct command * cmd ;
/* Channel being closed. */
struct channel * channel ;
/* Should we force the close on timeout? */
bool force ;
} ;
2018-02-20 21:59:09 +01:00
static void destroy_peer ( struct peer * peer )
{
list_del_from ( & peer - > ld - > peers , & peer - > list ) ;
}
/* We copy per-peer entries above --log-level into the main log. */
2018-02-12 11:12:55 +01:00
static void copy_to_parent_log ( const char * prefix ,
enum log_level level ,
bool continued ,
2018-02-21 16:06:07 +01:00
const struct timeabs * time UNUSED ,
2018-02-12 11:12:55 +01:00
const char * str ,
const u8 * io ,
2018-02-20 21:59:09 +01:00
struct log * parent_log )
2017-01-10 06:08:33 +01:00
{
2018-02-20 21:59:09 +01:00
if ( level = = LOG_IO_IN | | level = = LOG_IO_OUT )
log_io ( parent_log , level , prefix , io , tal_len ( io ) ) ;
else if ( continued )
log_add ( parent_log , " %s ... %s " , prefix , str ) ;
else
log_ ( parent_log , level , " %s %s " , prefix , str ) ;
2017-01-10 06:08:33 +01:00
}
2018-02-12 11:12:55 +01:00
struct peer * new_peer ( struct lightningd * ld , u64 dbid ,
const struct pubkey * id ,
const struct wireaddr * addr )
{
2018-02-12 11:13:04 +01:00
/* We are owned by our channels, and freed manually by destroy_channel */
struct peer * peer = tal ( NULL , struct peer ) ;
2018-02-12 11:12:55 +01:00
peer - > ld = ld ;
peer - > dbid = dbid ;
peer - > id = * id ;
2018-02-19 02:06:02 +01:00
peer - > uncommitted_channel = NULL ;
2018-02-12 11:12:55 +01:00
if ( addr )
peer - > addr = * addr ;
else
peer - > addr . type = ADDR_TYPE_PADDING ;
list_head_init ( & peer - > channels ) ;
peer - > direction = get_channel_direction ( & peer - > ld - > id , & peer - > id ) ;
2018-04-03 09:19:42 +02:00
# if DEVELOPER
peer - > ignore_htlcs = false ;
# endif
2018-02-12 11:12:55 +01:00
/* Max 128k per peer. */
2018-02-18 13:56:46 +01:00
peer - > log_book = new_log_book ( 128 * 1024 , get_log_level ( ld - > log_book ) ) ;
2018-02-18 13:58:46 +01:00
set_log_outfn ( peer - > log_book , copy_to_parent_log , ld - > log ) ;
2018-02-12 11:12:55 +01:00
list_add_tail ( & ld - > peers , & peer - > list ) ;
tal_add_destructor ( peer , destroy_peer ) ;
return peer ;
}
2018-02-14 02:53:04 +01:00
void delete_peer ( struct peer * peer )
{
assert ( list_empty ( & peer - > channels ) ) ;
2018-02-19 02:06:02 +01:00
assert ( ! peer - > uncommitted_channel ) ;
/* If it only ever existed because of uncommitted channel, it won't
* be in the database */
if ( peer - > dbid ! = 0 )
wallet_peer_delete ( peer - > ld - > wallet , peer - > dbid ) ;
2018-02-14 02:53:04 +01:00
tal_free ( peer ) ;
}
2018-02-12 11:12:55 +01:00
struct peer * find_peer_by_dbid ( struct lightningd * ld , u64 dbid )
{
struct peer * p ;
list_for_each ( & ld - > peers , p , list )
if ( p - > dbid = = dbid )
return p ;
return NULL ;
}
2018-02-20 21:59:09 +01:00
struct peer * peer_by_id ( struct lightningd * ld , const struct pubkey * id )
{
struct peer * p ;
list_for_each ( & ld - > peers , p , list )
if ( pubkey_eq ( & p - > id , id ) )
return p ;
return NULL ;
}
struct peer * peer_from_json ( struct lightningd * ld ,
const char * buffer ,
jsmntok_t * peeridtok )
{
struct pubkey peerid ;
if ( ! json_tok_pubkey ( buffer , peeridtok , & peerid ) )
return NULL ;
return peer_by_id ( ld , & peerid ) ;
}
u8 * p2wpkh_for_keyidx ( const tal_t * ctx , struct lightningd * ld , u64 keyidx )
{
struct pubkey shutdownkey ;
if ( ! bip32_pubkey ( ld - > wallet - > bip32_base , & shutdownkey , keyidx ) )
return NULL ;
return scriptpubkey_p2wpkh ( ctx , & shutdownkey ) ;
}
u32 feerate_min ( struct lightningd * ld )
{
if ( ld - > config . ignore_fee_limits )
return 1 ;
/* Set this to average of slow and normal.*/
return ( get_feerate ( ld - > topology , FEERATE_SLOW )
+ get_feerate ( ld - > topology , FEERATE_NORMAL ) ) / 2 ;
}
/* BOLT #2:
*
* Given the variance in fees , and the fact that the transaction may
* be spent in the future , it ' s a good idea for the fee payer to keep
* a good margin , say 5 x the expected fee requirement */
u32 feerate_max ( struct lightningd * ld )
{
if ( ld - > config . ignore_fee_limits )
return UINT_MAX ;
return get_feerate ( ld - > topology , FEERATE_IMMEDIATE ) * 5 ;
}
2018-02-12 11:13:04 +01:00
static void sign_last_tx ( struct channel * channel )
2017-06-20 08:17:03 +02:00
{
2017-08-18 06:43:52 +02:00
u8 * funding_wscript ;
struct pubkey local_funding_pubkey ;
struct secrets secrets ;
secp256k1_ecdsa_signature sig ;
2018-02-12 11:12:55 +01:00
assert ( ! channel - > last_tx - > input [ 0 ] . witness ) ;
2017-12-15 11:29:37 +01:00
2018-02-12 11:12:55 +01:00
derive_basepoints ( & channel - > seed , & local_funding_pubkey , NULL , & secrets ,
2017-08-18 06:43:52 +02:00
NULL ) ;
funding_wscript = bitcoin_redeem_2of2 ( tmpctx ,
& local_funding_pubkey ,
2018-02-19 02:06:12 +01:00
& channel - > channel_info . remote_fundingkey ) ;
2017-08-18 06:43:52 +02:00
/* Need input amount for signing */
2018-02-12 11:12:55 +01:00
channel - > last_tx - > input [ 0 ] . amount = tal_dup ( channel - > last_tx - > input , u64 ,
& channel - > funding_satoshi ) ;
sign_tx_input ( channel - > last_tx , 0 , NULL , funding_wscript ,
2017-08-18 06:43:52 +02:00
& secrets . funding_privkey ,
& local_funding_pubkey ,
& sig ) ;
2018-02-12 11:12:55 +01:00
channel - > last_tx - > input [ 0 ] . witness
= bitcoin_witness_2of2 ( channel - > last_tx - > input ,
2018-02-19 02:06:12 +01:00
& channel - > last_sig ,
2017-08-18 06:43:52 +02:00
& sig ,
2018-02-19 02:06:12 +01:00
& channel - > channel_info . remote_fundingkey ,
2017-08-18 06:43:52 +02:00
& local_funding_pubkey ) ;
2017-09-26 06:57:31 +02:00
}
2017-12-15 11:29:37 +01:00
static void remove_sig ( struct bitcoin_tx * signed_tx )
{
signed_tx - > input [ 0 ] . amount = tal_free ( signed_tx - > input [ 0 ] . amount ) ;
signed_tx - > input [ 0 ] . witness = tal_free ( signed_tx - > input [ 0 ] . witness ) ;
}
2018-04-10 08:03:15 +02:00
/* Resolve a single close command. */
static void
resolve_one_close_command ( struct close_command * cc , bool cooperative )
{
struct json_result * result = new_json_result ( cc ) ;
u8 * tx = linearize_tx ( result , cc - > channel - > last_tx ) ;
struct bitcoin_txid txid ;
bitcoin_txid ( cc - > channel - > last_tx , & txid ) ;
json_object_start ( result , NULL ) ;
json_add_hex ( result , " tx " , tx , tal_len ( tx ) ) ;
json_add_txid ( result , " txid " , & txid ) ;
if ( cooperative )
json_add_string ( result , " type " , " mutual " ) ;
else
json_add_string ( result , " type " , " unilateral " ) ;
json_object_end ( result ) ;
command_success ( cc - > cmd , result ) ;
}
/* Resolve a close command for a channel that will be closed soon. */
static void
resolve_close_command ( struct lightningd * ld , struct channel * channel ,
bool cooperative )
{
struct close_command * cc ;
struct close_command * n ;
list_for_each_safe ( & ld - > close_commands , cc , n , list ) {
if ( cc - > channel ! = channel )
continue ;
resolve_one_close_command ( cc , cooperative ) ;
}
}
/* Destroy the close command structure in reaction to the
* channel being destroyed . */
static void
destroy_close_command_on_channel_destroy ( struct channel * _ UNUSED ,
struct close_command * cc )
{
/* The cc has the command as parent, so resolving the
* command destroys the cc and triggers destroy_close_command .
* Clear the cc - > channel first so that we will not try to
* remove a destructor . */
cc - > channel = NULL ;
command_fail ( cc - > cmd , " Channel forgotten before proper close. " ) ;
}
/* Destroy the close command structure. */
static void
destroy_close_command ( struct close_command * cc )
{
list_del ( & cc - > list ) ;
/* If destroy_close_command_on_channel_destroy was
* triggered beforehand , it will have cleared
* the channel field , preventing us from removing it
* from an already - destroyed channel . */
if ( ! cc - > channel )
return ;
tal_del_destructor2 ( cc - > channel ,
& destroy_close_command_on_channel_destroy ,
cc ) ;
}
/* Handle timeout. */
static void
close_command_timeout ( struct close_command * cc )
{
if ( cc - > force )
/* This will trigger drop_to_chain, which will trigger
* resolution of the command and destruction of the
* close_command . */
channel_fail_permanent ( cc - > channel ,
" Forcibly closed by 'close' command timeout " ) ;
else
/* Fail the command directly, which will resolve the
* command and destroy the close_command . */
command_fail ( cc - > cmd ,
" Channel close negotiation not finished "
" before timeout " ) ;
}
/* Construct a close command structure and add to ld. */
static void
register_close_command ( struct lightningd * ld ,
struct command * cmd ,
struct channel * channel ,
unsigned int timeout ,
bool force )
{
struct close_command * cc ;
assert ( channel ) ;
cc = tal ( cmd , struct close_command ) ;
list_add_tail ( & ld - > close_commands , & cc - > list ) ;
cc - > cmd = cmd ;
cc - > channel = channel ;
cc - > force = force ;
tal_add_destructor ( cc , & destroy_close_command ) ;
tal_add_destructor2 ( channel ,
& destroy_close_command_on_channel_destroy ,
cc ) ;
new_reltimer ( & ld - > timers , cc , time_from_sec ( timeout ) ,
& close_command_timeout , cc ) ;
}
void drop_to_chain ( struct lightningd * ld , struct channel * channel ,
bool cooperative )
2017-09-26 06:57:31 +02:00
{
2018-02-12 11:13:04 +01:00
sign_last_tx ( channel ) ;
2017-09-26 06:57:31 +02:00
2017-08-18 06:43:52 +02:00
/* Keep broadcasting until we say stop (can fail due to dup,
* if they beat us to the broadcast ) . */
2018-02-12 11:13:04 +01:00
broadcast_tx ( ld - > topology , channel , channel - > last_tx , NULL ) ;
2018-04-10 08:03:15 +02:00
resolve_close_command ( ld , channel , cooperative ) ;
2018-02-12 11:13:04 +01:00
remove_sig ( channel - > last_tx ) ;
2017-05-22 09:28:07 +02:00
}
2018-02-20 21:59:09 +01:00
void channel_errmsg ( struct channel * channel ,
int peer_fd , int gossip_fd ,
const struct crypto_state * cs ,
2018-02-21 16:06:07 +01:00
const struct channel_id * channel_id UNUSED ,
2018-02-20 21:59:09 +01:00
const char * desc ,
const u8 * err_for_them )
2018-02-19 02:06:15 +01:00
{
struct lightningd * ld = channel - > peer - > ld ;
u8 * msg ;
2018-02-18 13:59:46 +01:00
2018-02-19 02:06:15 +01:00
/* No peer fd means a subd crash or disconnection. */
if ( peer_fd = = - 1 ) {
channel_fail_transient ( channel , " %s: %s " ,
channel - > owner - > name , desc ) ;
return ;
2018-02-18 13:59:46 +01:00
}
2018-02-19 02:06:15 +01:00
/* Do we have an error to send? */
if ( err_for_them & & ! channel - > error )
channel - > error = tal_dup_arr ( channel , u8 ,
err_for_them ,
tal_len ( err_for_them ) , 0 ) ;
2018-04-26 06:51:01 +02:00
/* Make sure channel_fail_permanent doesn't tell gossipd we died! */
channel - > connected = false ;
2018-02-19 02:06:15 +01:00
/* BOLT #1:
*
* A sending node :
* . . .
* - when ` channel_id ` is 0 :
* - MUST fail all channels .
* - MUST close the connection .
*/
/* FIXME: Gossipd closes connection, but doesn't fail channels. */
/* BOLT #1:
*
* A sending node :
* - when sending ` error ` :
* - MUST fail the channel referred to by the error message .
* . . .
* The receiving node :
* - upon receiving ` error ` :
* - MUST fail the channel referred to by the error message .
*/
2018-02-19 02:06:02 +01:00
channel_fail_permanent ( channel , " %s: %s ERROR %s " ,
channel - > owner - > name ,
2018-02-19 02:06:15 +01:00
err_for_them ? " sent " : " received " , desc ) ;
/* Hand back to gossipd, with any error packet. */
msg = towire_gossipctl_hand_back_peer ( NULL , & channel - > peer - > id ,
2018-04-26 06:51:01 +02:00
cs , err_for_them ) ;
2018-02-19 02:06:15 +01:00
subd_send_msg ( ld - > gossip , take ( msg ) ) ;
subd_send_fd ( ld - > gossip , peer_fd ) ;
subd_send_fd ( ld - > gossip , gossip_fd ) ;
2018-02-18 13:59:46 +01:00
}
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
/* Gossipd tells us a peer has connected */
void peer_connected ( struct lightningd * ld , const u8 * msg ,
int peer_fd , int gossip_fd )
2017-01-10 06:08:33 +01:00
{
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
struct pubkey id ;
struct crypto_state cs ;
u8 * gfeatures , * lfeatures ;
u8 * error ;
2018-03-13 16:41:55 +01:00
u8 * global_features ;
u8 * local_features ;
2018-02-12 11:13:04 +01:00
struct channel * channel ;
2017-10-23 06:17:38 +02:00
struct wireaddr addr ;
2018-02-19 02:06:02 +01:00
struct uncommitted_channel * uc ;
2017-01-10 06:08:33 +01:00
2018-02-20 21:59:09 +01:00
if ( ! fromwire_gossip_peer_connected ( msg , msg ,
2018-04-26 06:51:01 +02:00
& id , & addr , & cs ,
2017-10-23 06:13:38 +02:00
& gfeatures , & lfeatures ) )
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
fatal ( " Gossip gave bad GOSSIP_PEER_CONNECTED message %s " ,
tal_hex ( msg , msg ) ) ;
2018-03-13 16:41:55 +01:00
if ( ! features_supported ( gfeatures , lfeatures ) ) {
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
log_unusual ( ld - > log , " peer %s offers unsupported features %s/%s " ,
type_to_string ( msg , struct pubkey , & id ) ,
tal_hex ( msg , gfeatures ) ,
tal_hex ( msg , lfeatures ) ) ;
2018-03-13 16:41:55 +01:00
global_features = get_offered_global_features ( msg ) ;
local_features = get_offered_local_features ( msg ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
error = towire_errorfmt ( msg , NULL ,
2018-03-13 16:41:55 +01:00
" We only offer globalfeatures %s "
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
" and localfeatures %s " ,
tal_hexstr ( msg ,
2018-03-13 16:41:55 +01:00
global_features ,
tal_len ( global_features ) ) ,
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
tal_hexstr ( msg ,
2018-03-13 16:41:55 +01:00
local_features ,
tal_len ( local_features ) ) ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
goto send_error ;
}
2018-04-23 12:08:01 +02:00
/* Were we trying to open a channel, and we've raced? */
2018-04-26 06:51:01 +02:00
if ( handle_opening_channel ( ld , & id , & addr , & cs ,
2018-04-23 12:08:01 +02:00
gfeatures , lfeatures , peer_fd , gossip_fd ) )
return ;
2018-02-12 11:13:04 +01:00
/* If we're already dealing with this peer, hand off to correct
* subdaemon . Otherwise , we ' ll respond iff they ask about an inactive
* channel . */
2018-02-19 02:06:02 +01:00
channel = active_channel_by_id ( ld , & id , & uc ) ;
/* Opening now? Kill it */
if ( uc ) {
2018-02-20 21:59:04 +01:00
kill_uncommitted_channel ( uc , " Peer reconnected " ) ;
2018-02-19 02:06:02 +01:00
goto return_to_gossipd ;
}
2018-02-12 11:13:04 +01:00
if ( channel ) {
2018-02-12 11:13:04 +01:00
log_debug ( channel - > log , " Peer has reconnected, state %s " ,
2018-02-12 11:12:55 +01:00
channel_state_name ( channel ) ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
2018-02-12 11:13:04 +01:00
/* If we have a canned error, deliver it now. */
2018-02-12 11:12:55 +01:00
if ( channel - > error ) {
error = channel - > error ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
goto send_error ;
}
2017-05-23 14:17:19 +02:00
2017-10-28 04:19:10 +02:00
# if DEVELOPER
if ( dev_disconnect_permanent ( ld ) ) {
2018-02-12 11:13:04 +01:00
channel_internal_error ( channel , " dev_disconnect permfail " ) ;
2018-02-12 11:12:55 +01:00
error = channel - > error ;
2017-10-28 04:19:10 +02:00
goto send_error ;
}
# endif
2018-02-12 11:12:55 +01:00
switch ( channel - > state ) {
2018-02-23 07:23:51 +01:00
case ONCHAIN :
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
case FUNDING_SPEND_SEEN :
2018-02-12 11:13:04 +01:00
case CLOSINGD_COMPLETE :
/* Channel is active! */
abort ( ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
case CHANNELD_AWAITING_LOCKIN :
case CHANNELD_NORMAL :
case CHANNELD_SHUTTING_DOWN :
/* Stop any existing daemon, without triggering error
* on this peer . */
2018-02-12 11:13:04 +01:00
channel_set_owner ( channel , NULL ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
2018-02-12 11:13:04 +01:00
channel - > peer - > addr = addr ;
2018-04-26 06:51:01 +02:00
peer_start_channeld ( channel , & cs ,
2017-12-11 04:33:16 +01:00
peer_fd , gossip_fd , NULL ,
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
true ) ;
2018-04-26 06:50:58 +02:00
return ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
case CLOSINGD_SIGEXCHANGE :
/* Stop any existing daemon, without triggering error
* on this peer . */
2018-02-12 11:13:04 +01:00
channel_set_owner ( channel , NULL ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
2018-02-12 11:13:04 +01:00
channel - > peer - > addr = addr ;
2018-04-26 06:51:01 +02:00
peer_start_closingd ( channel , & cs ,
2017-12-11 04:33:16 +01:00
peer_fd , gossip_fd ,
2018-04-23 12:08:02 +02:00
true , NULL ) ;
2018-04-26 06:50:58 +02:00
return ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
}
abort ( ) ;
}
2017-05-22 13:26:49 +02:00
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
return_to_gossipd :
2018-04-26 06:50:58 +02:00
/* No err, all good. */
error = NULL ;
2017-08-12 16:46:50 +02:00
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
send_error :
/* Hand back to gossipd, with an error packet. */
2018-04-26 06:51:01 +02:00
msg = towire_gossipctl_hand_back_peer ( msg , & id , & cs , error ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
subd_send_msg ( ld - > gossip , take ( msg ) ) ;
subd_send_fd ( ld - > gossip , peer_fd ) ;
2017-12-11 04:16:50 +01:00
subd_send_fd ( ld - > gossip , gossip_fd ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
}
2018-02-12 11:13:04 +01:00
static struct channel * channel_by_channel_id ( struct peer * peer ,
const struct channel_id * channel_id )
{
struct channel * channel ;
list_for_each ( & peer - > channels , channel , list ) {
struct channel_id cid ;
derive_channel_id ( & cid ,
2018-02-19 02:06:12 +01:00
& channel - > funding_txid ,
2018-02-12 11:13:04 +01:00
channel - > funding_outnum ) ;
if ( structeq ( & cid , channel_id ) )
return channel ;
}
return NULL ;
}
/* We only get here IF we weren't trying to connect to it. */
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
void peer_sent_nongossip ( struct lightningd * ld ,
const struct pubkey * id ,
2017-10-23 06:17:38 +02:00
const struct wireaddr * addr ,
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
const struct crypto_state * cs ,
const u8 * gfeatures ,
const u8 * lfeatures ,
int peer_fd , int gossip_fd ,
const u8 * in_msg )
{
struct channel_id * channel_id , extracted_channel_id ;
struct peer * peer ;
u8 * error , * msg ;
if ( ! extract_channel_id ( in_msg , & extracted_channel_id ) )
channel_id = NULL ;
else
channel_id = & extracted_channel_id ;
peer = peer_by_id ( ld , id ) ;
/* Open request? */
if ( fromwire_peektype ( in_msg ) = = WIRE_OPEN_CHANNEL ) {
2018-03-19 10:27:09 +01:00
error = peer_accept_channel ( tmpctx ,
2018-04-26 06:51:01 +02:00
ld , id , addr , cs ,
2018-02-19 02:06:02 +01:00
gfeatures , lfeatures ,
peer_fd , gossip_fd , channel_id ,
in_msg ) ;
if ( error )
2018-02-12 11:13:04 +01:00
goto send_error ;
2017-05-22 13:26:49 +02:00
return ;
2017-01-10 06:08:33 +01:00
}
2017-08-17 15:30:24 +02:00
2018-02-12 11:13:04 +01:00
/* If they are talking about a specific channel id, we may have an
* error for them . */
if ( peer & & channel_id ) {
struct channel * channel ;
channel = channel_by_channel_id ( peer , channel_id ) ;
if ( channel & & channel - > error ) {
error = channel - > error ;
goto send_error ;
}
2018-04-23 12:08:02 +02:00
/* Reestablish for a now-closed channel? They might have
* missed final update , so do the closing negotiation dance
* again . */
if ( fromwire_peektype ( in_msg ) = = WIRE_CHANNEL_REESTABLISH
& & channel
& & channel - > state = = CLOSINGD_COMPLETE ) {
2018-04-26 06:51:01 +02:00
peer_start_closingd ( channel , cs ,
2018-04-23 12:08:02 +02:00
peer_fd , gossip_fd , true , in_msg ) ;
return ;
}
2018-02-12 11:13:04 +01:00
}
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
/* Weird request. */
2018-03-19 10:27:09 +01:00
error = towire_errorfmt ( tmpctx , channel_id ,
2018-02-12 11:13:04 +01:00
" Unexpected message %i for peer " ,
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
fromwire_peektype ( in_msg ) ) ;
2017-08-17 15:30:24 +02:00
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
send_error :
/* Hand back to gossipd, with an error packet. */
2018-04-26 06:51:01 +02:00
msg = towire_gossipctl_hand_back_peer ( ld , id , cs , error ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
subd_send_msg ( ld - > gossip , take ( msg ) ) ;
subd_send_fd ( ld - > gossip , peer_fd ) ;
2017-12-11 04:16:50 +01:00
subd_send_fd ( ld - > gossip , gossip_fd ) ;
gossipd: rewrite to do the handshake internally.
Now the flow is much simpler from a lightningd POV:
1. If we want to connect to a peer, just send gossipd `gossipctl_reach_peer`.
2. Every new peer, gossipd hands up to lightningd, with global/local features
and the peer fd and a gossip fd using `gossip_peer_connected`
3. If lightningd doesn't want it, it just hands the peerfd and global/local
features back to gossipd using `gossipctl_handle_peer`
4. If a peer sends a non-gossip msg (eg `open_channel`) the gossipd sends
it up using `gossip_peer_nongossip`.
5. If lightningd wants to fund a channel, it simply calls `release_channel`.
Notes:
* There's no more "unique_id": we use the peer id.
* For the moment, we don't ask gossipd when we're told to list peers, so
connected peers without a channel don't appear in the JSON getpeers API.
* We add a `gossipctl_peer_addrhint` for the moment, so you can connect to
a specific ip/port, but using other sources is a TODO.
* We now (correctly) only give up on reaching a peer after we exchange init
messages, which changes the test_disconnect case.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2017-10-11 12:09:49 +02:00
}
2017-05-22 13:26:49 +02:00
2018-02-12 11:13:04 +01:00
static enum watch_result funding_announce_cb ( struct channel * channel ,
2018-04-09 15:20:54 +02:00
const struct bitcoin_txid * txid UNUSED ,
2018-02-20 21:59:09 +01:00
unsigned int depth )
2017-05-23 13:00:17 +02:00
{
if ( depth < ANNOUNCE_MIN_DEPTH ) {
return KEEP_WATCHING ;
}
2017-09-04 05:41:34 +02:00
2018-02-12 11:12:55 +01:00
if ( ! channel - > owner | | ! streq ( channel - > owner - > name , " lightning_channeld " ) ) {
2018-02-12 11:13:04 +01:00
log_debug ( channel - > log ,
" Funding tx announce ready, but channel state %s "
2018-01-25 12:03:40 +01:00
" owned by %s " ,
2018-02-12 11:12:55 +01:00
channel_state_name ( channel ) ,
channel - > owner ? channel - > owner - > name : " none " ) ;
2017-05-23 13:00:17 +02:00
return KEEP_WATCHING ;
}
2017-09-04 05:41:34 +02:00
2018-02-12 11:12:55 +01:00
subd_send_msg ( channel - > owner ,
2018-02-12 11:13:04 +01:00
take ( towire_channel_funding_announce_depth ( channel ) ) ) ;
2017-05-23 13:00:17 +02:00
return DELETE_WATCH ;
}
2018-02-12 11:13:04 +01:00
static enum watch_result funding_lockin_cb ( struct channel * channel ,
2018-04-09 15:20:54 +02:00
const struct bitcoin_txid * txid ,
2018-02-20 21:59:09 +01:00
unsigned int depth )
2017-03-07 02:03:55 +01:00
{
2017-08-18 06:43:53 +02:00
const char * txidstr ;
2018-02-12 11:13:04 +01:00
struct lightningd * ld = channel - > peer - > ld ;
2017-03-07 02:05:03 +01:00
2018-04-09 15:20:54 +02:00
txidstr = type_to_string ( channel , struct bitcoin_txid , txid ) ;
2018-02-12 11:13:04 +01:00
log_debug ( channel - > log , " Funding tx %s depth %u of %u " ,
2018-02-12 11:12:55 +01:00
txidstr , depth , channel - > minimum_depth ) ;
2017-05-23 13:00:17 +02:00
tal_free ( txidstr ) ;
2017-03-07 02:31:43 +01:00
2018-02-12 11:12:55 +01:00
if ( depth < channel - > minimum_depth )
2017-03-07 02:31:43 +01:00
return KEEP_WATCHING ;
2018-01-05 03:42:31 +01:00
/* If we restart, we could already have peer->scid from database */
2018-02-12 11:12:55 +01:00
if ( ! channel - > scid ) {
2018-04-23 12:08:01 +02:00
struct txlocator * loc ;
loc = wallet_transaction_locate ( tmpctx , ld - > wallet , txid ) ;
2018-02-12 11:12:55 +01:00
channel - > scid = tal ( channel , struct short_channel_id ) ;
2018-03-01 10:22:24 +01:00
mk_short_channel_id ( channel - > scid ,
loc - > blkheight , loc - > index ,
channel - > funding_outnum ) ;
2018-04-23 12:08:01 +02:00
/* We've added scid, update */
wallet_channel_save ( ld - > wallet , channel ) ;
2018-01-05 03:42:31 +01:00
}
2017-05-02 07:26:31 +02:00
2018-04-23 12:08:01 +02:00
if ( ! channel_tell_funding_locked ( ld , channel , txid ) )
return KEEP_WATCHING ;
2017-03-20 17:09:12 +01:00
2017-06-27 04:55:01 +02:00
/* BOLT #7:
*
* If the ` open_channel ` message had the ` announce_channel ` bit set ,
* then both nodes must send the ` announcement_signatures ` message ,
* otherwise they MUST NOT .
*/
2018-02-12 11:12:55 +01:00
if ( ! ( channel - > channel_flags & CHANNEL_FLAGS_ANNOUNCE_CHANNEL ) )
2017-06-27 04:55:01 +02:00
return DELETE_WATCH ;
2017-09-04 05:41:34 +02:00
/* Tell channeld that we have reached the announce_depth and
* that it may send the announcement_signatures upon receiving
* funding_locked , or right now if it already received it
* before . If we are at the right depth , call the callback
* directly , otherwise schedule a callback */
if ( depth > = ANNOUNCE_MIN_DEPTH )
2018-04-09 15:20:54 +02:00
funding_announce_cb ( channel , txid , depth ) ;
2017-09-04 05:41:34 +02:00
else
2018-04-09 15:20:54 +02:00
watch_txid ( channel , ld - > topology , channel , txid ,
2018-02-20 21:59:09 +01:00
funding_announce_cb ) ;
2017-03-07 02:31:43 +01:00
return DELETE_WATCH ;
2017-03-07 02:03:55 +01:00
}
2018-04-16 13:20:45 +02:00
static enum watch_result funding_spent ( struct channel * channel ,
const struct bitcoin_tx * tx ,
size_t inputnum UNUSED ,
const struct block * block )
{
struct bitcoin_txid txid ;
bitcoin_txid ( tx , & txid ) ;
wallet_channeltxs_add ( channel - > peer - > ld - > wallet , channel ,
WIRE_ONCHAIN_INIT , & txid , 0 , block - > height ) ;
return onchaind_funding_spent ( channel , tx , block - > height ) ;
}
2018-02-20 21:59:04 +01:00
void channel_watch_funding ( struct lightningd * ld , struct channel * channel )
2017-02-24 06:52:56 +01:00
{
2017-08-23 03:55:16 +02:00
/* FIXME: Remove arg from cb? */
2018-02-20 21:59:04 +01:00
watch_txid ( channel , ld - > topology , channel ,
2018-02-20 21:59:09 +01:00
& channel - > funding_txid , funding_lockin_cb ) ;
2018-02-12 11:13:04 +01:00
watch_txo ( channel , ld - > topology , channel ,
2018-02-19 02:06:12 +01:00
& channel - > funding_txid , channel - > funding_outnum ,
2018-02-20 21:59:09 +01:00
funding_spent ) ;
2017-02-24 06:52:56 +01:00
}
2018-02-20 21:59:09 +01:00
struct getpeers_args {
struct command * cmd ;
/* If non-NULL, they want logs too */
enum log_level * ll ;
/* If set, only report on a specific id. */
struct pubkey * specific_id ;
} ;
2018-03-26 02:08:15 +02:00
static void json_add_node_decoration ( struct json_result * response ,
struct gossip_getnodes_entry * * nodes ,
const struct pubkey * id )
{
for ( size_t i = 0 ; i < tal_count ( nodes ) ; i + + ) {
struct json_escaped * esc ;
/* If no addresses, then this node announcement hasn't been
* received yet So no alias information either .
*/
if ( nodes [ i ] - > addresses = = NULL )
continue ;
if ( ! pubkey_eq ( & nodes [ i ] - > nodeid , id ) )
continue ;
esc = json_escape ( NULL , ( const char * ) nodes [ i ] - > alias ) ;
json_add_escaped_string ( response , " alias " , take ( esc ) ) ;
json_add_hex ( response , " color " ,
nodes [ i ] - > color , ARRAY_SIZE ( nodes [ i ] - > color ) ) ;
break ;
}
}
2018-02-20 21:59:09 +01:00
static void gossipd_getpeers_complete ( struct subd * gossip , const u8 * msg ,
2018-02-21 16:06:07 +01:00
const int * fds UNUSED ,
2018-02-20 21:59:09 +01:00
struct getpeers_args * gpa )
{
/* This is a little sneaky... */
struct pubkey * ids ;
struct wireaddr * addrs ;
2018-02-27 06:08:34 +01:00
struct gossip_getnodes_entry * * nodes ;
2018-02-20 21:59:09 +01:00
struct json_result * response = new_json_result ( gpa - > cmd ) ;
struct peer * p ;
2018-02-27 06:08:34 +01:00
if ( ! fromwire_gossip_getpeers_reply ( msg , msg , & ids , & addrs , & nodes ) ) {
2018-02-20 21:59:09 +01:00
command_fail ( gpa - > cmd , " Bad response from gossipd " ) ;
return ;
}
/* First the peers not just gossiping. */
json_object_start ( response , NULL ) ;
json_array_start ( response , " peers " ) ;
list_for_each ( & gpa - > cmd - > ld - > peers , p , list ) {
bool connected ;
struct channel * channel ;
2018-03-24 09:26:08 +01:00
struct channel_stats channel_stats ;
2018-02-20 21:59:09 +01:00
if ( gpa - > specific_id & & ! pubkey_eq ( gpa - > specific_id , & p - > id ) )
continue ;
json_object_start ( response , NULL ) ;
json_add_pubkey ( response , " id " , & p - > id ) ;
2018-03-19 00:26:07 +01:00
/* Channel is also connected if uncommitted channel */
if ( p - > uncommitted_channel )
connected = true ;
else {
channel = peer_active_channel ( p ) ;
connected = channel & & channel - > owner ;
}
2018-02-20 21:59:09 +01:00
json_add_bool ( response , " connected " , connected ) ;
if ( connected ) {
json_array_start ( response , " netaddr " ) ;
if ( p - > addr . type ! = ADDR_TYPE_PADDING )
json_add_string ( response , NULL ,
type_to_string ( response ,
struct wireaddr ,
& p - > addr ) ) ;
json_array_end ( response ) ;
}
2018-03-26 02:08:15 +02:00
json_add_node_decoration ( response , nodes , & p - > id ) ;
2018-02-20 21:59:09 +01:00
json_array_start ( response , " channels " ) ;
json_add_uncommitted_channel ( response , p - > uncommitted_channel ) ;
list_for_each ( & p - > channels , channel , list ) {
2018-03-17 00:50:54 +01:00
struct channel_id cid ;
2018-04-07 16:06:21 +02:00
u64 our_reserve_msat = channel - > channel_info . their_config . channel_reserve_satoshis * 1000 ;
2018-02-20 21:59:09 +01:00
json_object_start ( response , NULL ) ;
json_add_string ( response , " state " ,
channel_state_name ( channel ) ) ;
if ( channel - > owner )
json_add_string ( response , " owner " ,
channel - > owner - > name ) ;
if ( channel - > scid )
json_add_short_channel_id ( response ,
" short_channel_id " ,
channel - > scid ) ;
2018-03-17 00:50:54 +01:00
derive_channel_id ( & cid ,
& channel - > funding_txid ,
channel - > funding_outnum ) ;
json_add_string ( response , " channel_id " ,
type_to_string ( tmpctx ,
struct channel_id ,
& cid ) ) ;
2018-02-20 21:59:09 +01:00
json_add_txid ( response ,
" funding_txid " ,
& channel - > funding_txid ) ;
json_add_u64 ( response , " msatoshi_to_us " ,
channel - > our_msatoshi ) ;
2018-03-31 02:21:13 +02:00
json_add_u64 ( response , " msatoshi_to_us_min " ,
channel - > msatoshi_to_us_min ) ;
json_add_u64 ( response , " msatoshi_to_us_max " ,
channel - > msatoshi_to_us_max ) ;
2018-02-20 21:59:09 +01:00
json_add_u64 ( response , " msatoshi_total " ,
channel - > funding_satoshi * 1000 ) ;
/* channel config */
json_add_u64 ( response , " dust_limit_satoshis " ,
channel - > our_config . dust_limit_satoshis ) ;
json_add_u64 ( response , " max_htlc_value_in_flight_msat " ,
channel - > our_config . max_htlc_value_in_flight_msat ) ;
2018-04-07 16:06:21 +02:00
/* The `channel_reserve_satoshis` is imposed on
* the * other * side ( see ` channel_reserve_msat `
* function in , it uses ` ! side ` to flip sides ) .
* So our configuration ` channel_reserve_satoshis `
* is imposed on their side , while their
* configuration ` channel_reserve_satoshis ` is
* imposed on ours . */
json_add_u64 ( response , " their_channel_reserve_satoshis " ,
2018-02-20 21:59:09 +01:00
channel - > our_config . channel_reserve_satoshis ) ;
2018-04-07 16:06:21 +02:00
json_add_u64 ( response , " our_channel_reserve_satoshis " ,
channel - > channel_info . their_config . channel_reserve_satoshis ) ;
if ( deprecated_apis )
json_add_u64 ( response , " channel_reserve_satoshis " ,
channel - > our_config . channel_reserve_satoshis ) ;
/* Compute how much we can send via this channel. */
if ( channel - > our_msatoshi < = our_reserve_msat )
json_add_u64 ( response , " spendable_msatoshi " , 0 ) ;
else
json_add_u64 ( response , " spendable_msatoshi " ,
channel - > our_msatoshi - our_reserve_msat ) ;
2018-02-20 21:59:09 +01:00
json_add_u64 ( response , " htlc_minimum_msat " ,
channel - > our_config . htlc_minimum_msat ) ;
2018-03-12 14:25:11 +01:00
/* The `to_self_delay` is imposed on the *other*
* side , so our configuration ` to_self_delay ` is
* imposed on their side , while their configuration
* ` to_self_delay ` is imposed on ours . */
json_add_num ( response , " their_to_self_delay " ,
2018-02-20 21:59:09 +01:00
channel - > our_config . to_self_delay ) ;
2018-03-12 14:25:11 +01:00
json_add_num ( response , " our_to_self_delay " ,
channel - > channel_info . their_config . to_self_delay ) ;
if ( deprecated_apis )
json_add_num ( response , " to_self_delay " ,
channel - > our_config . to_self_delay ) ;
2018-02-20 21:59:09 +01:00
json_add_num ( response , " max_accepted_htlcs " ,
channel - > our_config . max_accepted_htlcs ) ;
2018-02-23 06:53:47 +01:00
json_array_start ( response , " status " ) ;
for ( size_t i = 0 ;
i < ARRAY_SIZE ( channel - > billboard . permanent ) ;
i + + ) {
if ( ! channel - > billboard . permanent [ i ] )
continue ;
json_add_string ( response , NULL ,
channel - > billboard . permanent [ i ] ) ;
}
if ( channel - > billboard . transient )
json_add_string ( response , NULL ,
channel - > billboard . transient ) ;
json_array_end ( response ) ;
2018-03-24 09:26:08 +01:00
/* Provide channel statistics */
wallet_channel_stats_load ( gpa - > cmd - > ld - > wallet ,
channel - > dbid ,
& channel_stats ) ;
json_add_u64 ( response , " in_payments_offered " ,
channel_stats . in_payments_offered ) ;
json_add_u64 ( response , " in_msatoshi_offered " ,
channel_stats . in_msatoshi_offered ) ;
json_add_u64 ( response , " in_payments_fulfilled " ,
channel_stats . in_payments_fulfilled ) ;
json_add_u64 ( response , " in_msatoshi_fulfilled " ,
channel_stats . in_msatoshi_fulfilled ) ;
json_add_u64 ( response , " out_payments_offered " ,
channel_stats . out_payments_offered ) ;
json_add_u64 ( response , " out_msatoshi_offered " ,
channel_stats . out_msatoshi_offered ) ;
json_add_u64 ( response , " out_payments_fulfilled " ,
channel_stats . out_payments_fulfilled ) ;
json_add_u64 ( response , " out_msatoshi_fulfilled " ,
channel_stats . out_msatoshi_fulfilled ) ;
2018-02-20 21:59:09 +01:00
json_object_end ( response ) ;
}
json_array_end ( response ) ;
if ( gpa - > ll )
2018-02-21 16:53:24 +01:00
json_add_log ( response , p - > log_book , * gpa - > ll ) ;
2018-02-20 21:59:09 +01:00
json_object_end ( response ) ;
}
for ( size_t i = 0 ; i < tal_count ( ids ) ; i + + ) {
/* Don't report peers in both, which can happen if they're
* reconnecting */
if ( peer_by_id ( gpa - > cmd - > ld , ids + i ) )
continue ;
json_object_start ( response , NULL ) ;
/* Fake state. */
json_add_string ( response , " state " , " GOSSIPING " ) ;
json_add_pubkey ( response , " id " , ids + i ) ;
2018-03-26 02:08:15 +02:00
json_add_node_decoration ( response , nodes , ids + i ) ;
2018-02-20 21:59:09 +01:00
json_array_start ( response , " netaddr " ) ;
if ( addrs [ i ] . type ! = ADDR_TYPE_PADDING )
json_add_string ( response , NULL ,
type_to_string ( response , struct wireaddr ,
addrs + i ) ) ;
json_array_end ( response ) ;
json_add_bool ( response , " connected " , true ) ;
json_add_string ( response , " owner " , gossip - > name ) ;
json_object_end ( response ) ;
}
json_array_end ( response ) ;
json_object_end ( response ) ;
command_success ( gpa - > cmd , response ) ;
}
static void json_listpeers ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * leveltok ;
struct getpeers_args * gpa = tal ( cmd , struct getpeers_args ) ;
jsmntok_t * idtok ;
gpa - > cmd = cmd ;
gpa - > specific_id = NULL ;
if ( ! json_get_params ( cmd , buffer , params ,
" ?id " , & idtok ,
" ?level " , & leveltok ,
NULL ) ) {
return ;
}
if ( idtok ) {
gpa - > specific_id = tal_arr ( cmd , struct pubkey , 1 ) ;
if ( ! json_tok_pubkey ( buffer , idtok , gpa - > specific_id ) ) {
command_fail ( cmd , " id %.*s not valid " ,
idtok - > end - idtok - > start ,
buffer + idtok - > start ) ;
return ;
}
}
if ( leveltok ) {
gpa - > ll = tal ( gpa , enum log_level ) ;
if ( ! json_tok_loglevel ( buffer , leveltok , gpa - > ll ) ) {
command_fail ( cmd , " Invalid level param " ) ;
return ;
}
} else
gpa - > ll = NULL ;
/* Get peers from gossipd. */
subd_req ( cmd , cmd - > ld - > gossip ,
take ( towire_gossip_getpeers_request ( cmd , gpa - > specific_id ) ) ,
- 1 , 0 , gossipd_getpeers_complete , gpa ) ;
command_still_pending ( cmd ) ;
}
static const struct json_command listpeers_command = {
" listpeers " ,
json_listpeers ,
" Show current peers, if {level} is set, include logs for {id} "
} ;
AUTODATA ( json_command , & listpeers_command ) ;
2017-06-26 03:16:43 +02:00
static void json_close ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * peertok ;
2018-04-10 08:03:15 +02:00
jsmntok_t * timeouttok ;
jsmntok_t * forcetok ;
2017-06-26 03:16:43 +02:00
struct peer * peer ;
2018-02-12 11:12:55 +01:00
struct channel * channel ;
2018-04-10 08:03:15 +02:00
unsigned int timeout = 30 ;
bool force = false ;
2017-06-26 03:16:43 +02:00
2018-01-29 01:34:28 +01:00
if ( ! json_get_params ( cmd , buffer , params ,
2017-06-26 03:16:43 +02:00
" id " , & peertok ,
2018-04-10 08:03:15 +02:00
" ?force " , & forcetok ,
" ?timeout " , & timeouttok ,
2017-06-26 03:16:43 +02:00
NULL ) ) {
return ;
}
2017-08-28 18:09:01 +02:00
peer = peer_from_json ( cmd - > ld , buffer , peertok ) ;
2017-06-26 03:16:43 +02:00
if ( ! peer ) {
command_fail ( cmd , " Could not find peer with that id " ) ;
return ;
}
2018-04-10 08:03:15 +02:00
if ( forcetok & & ! json_tok_bool ( buffer , forcetok , & force ) ) {
command_fail ( cmd , " Force '%.*s' must be true or false " ,
forcetok - > end - forcetok - > start ,
buffer + forcetok - > start ) ;
return ;
}
if ( timeouttok & & ! json_tok_number ( buffer , timeouttok , & timeout ) ) {
command_fail ( cmd , " Timeout '%.*s' is not a number " ,
timeouttok - > end - timeouttok - > start ,
buffer + timeouttok - > start ) ;
return ;
}
2018-02-12 11:13:04 +01:00
channel = peer_active_channel ( peer ) ;
if ( ! channel ) {
2018-02-19 02:06:02 +01:00
struct uncommitted_channel * uc = peer - > uncommitted_channel ;
if ( uc ) {
/* Easy case: peer can simply be forgotten. */
2018-02-20 21:59:04 +01:00
kill_uncommitted_channel ( uc , " close command called " ) ;
2018-02-19 02:06:02 +01:00
command_success ( cmd , null_response ( cmd ) ) ;
return ;
}
command_fail ( cmd , " Peer has no active channel " ) ;
2017-06-26 03:16:43 +02:00
return ;
}
2018-04-10 08:03:15 +02:00
/* Normal case.
* We allow states shutting down and sigexchange ; a previous
* close command may have timed out , and this current command
* will continue waiting for the effects of the previous
* close command . */
if ( channel - > state ! = CHANNELD_NORMAL & &
channel - > state ! = CHANNELD_AWAITING_LOCKIN & &
channel - > state ! = CHANNELD_SHUTTING_DOWN & &
channel - > state ! = CLOSINGD_SIGEXCHANGE )
command_fail ( cmd , " Peer is in state %s " ,
channel_state_name ( channel ) ) ;
/* If normal or locking in, transition to shutting down
* state .
* ( if already shutting down or sigexchange , just keep
* waiting ) */
2018-04-03 09:11:20 +02:00
if ( channel - > state = = CHANNELD_NORMAL | | channel - > state = = CHANNELD_AWAITING_LOCKIN ) {
2018-03-07 01:06:07 +01:00
channel_set_state ( channel ,
2018-04-03 09:11:20 +02:00
channel - > state , CHANNELD_SHUTTING_DOWN ) ;
2017-12-16 21:04:16 +01:00
2018-02-12 11:12:55 +01:00
if ( channel - > owner )
subd_send_msg ( channel - > owner ,
2018-03-07 01:06:07 +01:00
take ( towire_channel_send_shutdown ( channel ) ) ) ;
2018-04-10 08:03:15 +02:00
}
2017-06-26 03:16:43 +02:00
2018-04-10 08:03:15 +02:00
/* Register this command for later handling. */
register_close_command ( cmd - > ld , cmd , channel , timeout , force ) ;
/* Wait until close drops down to chain. */
command_still_pending ( cmd ) ;
2017-06-26 03:16:43 +02:00
}
static const struct json_command close_command = {
" close " ,
json_close ,
2018-01-22 09:55:07 +01:00
" Close the channel with peer {id} "
2017-06-26 03:16:43 +02:00
} ;
AUTODATA ( json_command , & close_command ) ;
2018-01-03 06:26:44 +01:00
static void activate_peer ( struct peer * peer )
{
2018-01-11 07:19:53 +01:00
u8 * msg ;
2018-02-12 11:13:04 +01:00
struct channel * channel ;
struct lightningd * ld = peer - > ld ;
2018-01-11 07:19:53 +01:00
/* Pass gossipd any addrhints we currently have */
msg = towire_gossipctl_peer_addrhint ( peer , & peer - > id , & peer - > addr ) ;
subd_send_msg ( peer - > ld - > gossip , take ( msg ) ) ;
2018-04-25 14:38:38 +02:00
/* We can only have one active channel: make sure gossipd
* knows to reconnect . */
2018-02-12 11:13:04 +01:00
channel = peer_active_channel ( peer ) ;
2018-04-25 14:38:38 +02:00
if ( channel )
tell_gossipd_peer_is_important ( ld , channel ) ;
2018-01-03 06:26:44 +01:00
2018-02-12 11:13:04 +01:00
list_for_each ( & peer - > channels , channel , list ) {
2018-02-20 21:59:04 +01:00
/* Watching lockin may be unnecessary, but it's harmless. */
channel_watch_funding ( ld , channel ) ;
2018-01-03 06:26:44 +01:00
}
}
void activate_peers ( struct lightningd * ld )
{
struct peer * p ;
list_for_each ( & ld - > peers , p , list )
activate_peer ( p ) ;
}
2018-03-05 17:16:20 +01:00
/* Peer has been released from gossip. */
static void gossip_peer_disconnected ( struct subd * gossip ,
const u8 * resp ,
const int * fds ,
struct command * cmd ) {
2018-03-07 14:23:43 +01:00
bool isconnected ;
2018-03-05 17:16:20 +01:00
if ( ! fromwire_gossipctl_peer_disconnect_reply ( resp ) ) {
2018-03-07 14:23:43 +01:00
if ( ! fromwire_gossipctl_peer_disconnect_replyfail ( resp , & isconnected ) )
2018-03-05 17:16:20 +01:00
fatal ( " Gossip daemon gave invalid reply %s " ,
tal_hex ( gossip , resp ) ) ;
2018-03-07 14:23:43 +01:00
if ( isconnected )
command_fail ( cmd , " Peer is not in gossip mode " ) ;
else
command_fail ( cmd , " Peer not connected " ) ;
2018-03-05 17:16:20 +01:00
} else {
/* Successfully disconnected */
command_success ( cmd , null_response ( cmd ) ) ;
}
return ;
}
static void json_disconnect ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * idtok ;
struct pubkey id ;
u8 * msg ;
if ( ! json_get_params ( cmd , buffer , params ,
" id " , & idtok ,
NULL ) ) {
return ;
}
if ( ! json_tok_pubkey ( buffer , idtok , & id ) ) {
command_fail ( cmd , " id %.*s not valid " ,
idtok - > end - idtok - > start ,
buffer + idtok - > start ) ;
return ;
}
msg = towire_gossipctl_peer_disconnect ( cmd , & id ) ;
subd_req ( cmd , cmd - > ld - > gossip , msg , - 1 , 0 , gossip_peer_disconnected , cmd ) ;
command_still_pending ( cmd ) ;
}
static const struct json_command disconnect_command = {
" disconnect " ,
json_disconnect ,
" Disconnect from {id} that has previously been connected to using connect "
} ;
AUTODATA ( json_command , & disconnect_command ) ;
2017-10-24 04:06:14 +02:00
# if DEVELOPER
static void json_sign_last_tx ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * peertok ;
struct peer * peer ;
struct json_result * response = new_json_result ( cmd ) ;
u8 * linear ;
2018-02-12 11:12:55 +01:00
struct channel * channel ;
2017-10-24 04:06:14 +02:00
2018-01-29 01:34:28 +01:00
if ( ! json_get_params ( cmd , buffer , params ,
2017-10-24 04:06:14 +02:00
" id " , & peertok ,
NULL ) ) {
return ;
}
peer = peer_from_json ( cmd - > ld , buffer , peertok ) ;
if ( ! peer ) {
command_fail ( cmd , " Could not find peer with that id " ) ;
return ;
}
2018-02-12 11:13:04 +01:00
channel = peer_active_channel ( peer ) ;
if ( ! channel ) {
command_fail ( cmd , " Could has not active channel " ) ;
return ;
}
2017-10-24 04:06:14 +02:00
2018-02-12 11:13:04 +01:00
log_debug ( channel - > log , " dev-sign-last-tx: signing tx with %zu outputs " ,
2018-02-12 11:12:55 +01:00
tal_count ( channel - > last_tx - > output ) ) ;
2018-02-12 11:13:04 +01:00
sign_last_tx ( channel ) ;
2018-02-12 11:12:55 +01:00
linear = linearize_tx ( cmd , channel - > last_tx ) ;
remove_sig ( channel - > last_tx ) ;
2017-10-24 04:06:14 +02:00
json_object_start ( response , NULL ) ;
json_add_hex ( response , " tx " , linear , tal_len ( linear ) ) ;
json_object_end ( response ) ;
command_success ( cmd , response ) ;
}
static const struct json_command dev_sign_last_tx = {
" dev-sign-last-tx " ,
json_sign_last_tx ,
2018-01-22 09:55:07 +01:00
" Sign and show the last commitment transaction with peer {id} "
2017-10-24 04:06:14 +02:00
} ;
AUTODATA ( json_command , & dev_sign_last_tx ) ;
static void json_dev_fail ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * peertok ;
struct peer * peer ;
2018-02-12 11:13:04 +01:00
struct channel * channel ;
2017-10-24 04:06:14 +02:00
2018-01-29 01:34:28 +01:00
if ( ! json_get_params ( cmd , buffer , params ,
2017-10-24 04:06:14 +02:00
" id " , & peertok ,
NULL ) ) {
return ;
}
peer = peer_from_json ( cmd - > ld , buffer , peertok ) ;
if ( ! peer ) {
command_fail ( cmd , " Could not find peer with that id " ) ;
return ;
}
2018-02-12 11:13:04 +01:00
channel = peer_active_channel ( peer ) ;
if ( ! channel ) {
command_fail ( cmd , " Could not find active channel with peer " ) ;
return ;
}
channel_internal_error ( channel , " Failing due to dev-fail command " ) ;
2017-10-24 04:06:14 +02:00
command_success ( cmd , null_response ( cmd ) ) ;
}
static const struct json_command dev_fail_command = {
" dev-fail " ,
json_dev_fail ,
2018-01-22 09:55:07 +01:00
" Fail with peer {id} "
2017-10-24 04:06:14 +02:00
} ;
AUTODATA ( json_command , & dev_fail_command ) ;
2018-02-21 16:06:07 +01:00
static void dev_reenable_commit_finished ( struct subd * channeld UNUSED ,
const u8 * resp UNUSED ,
const int * fds UNUSED ,
2017-10-24 04:06:14 +02:00
struct command * cmd )
{
command_success ( cmd , null_response ( cmd ) ) ;
}
static void json_dev_reenable_commit ( struct command * cmd ,
const char * buffer , const jsmntok_t * params )
{
jsmntok_t * peertok ;
struct peer * peer ;
u8 * msg ;
2018-02-12 11:12:55 +01:00
struct channel * channel ;
2017-10-24 04:06:14 +02:00
2018-01-29 01:34:28 +01:00
if ( ! json_get_params ( cmd , buffer , params ,
2017-10-24 04:06:14 +02:00
" id " , & peertok ,
NULL ) ) {
return ;
}
peer = peer_from_json ( cmd - > ld , buffer , peertok ) ;
if ( ! peer ) {
command_fail ( cmd , " Could not find peer with that id " ) ;
return ;
}
2018-02-12 11:13:04 +01:00
channel = peer_active_channel ( peer ) ;
if ( ! channel ) {
command_fail ( cmd , " Peer has no active channel " ) ;
return ;
}
2018-02-12 11:12:55 +01:00
if ( ! channel - > owner ) {
2017-10-24 04:06:14 +02:00
command_fail ( cmd , " Peer has no owner " ) ;
return ;
}
2018-02-12 11:12:55 +01:00
if ( ! streq ( channel - > owner - > name , " lightning_channeld " ) ) {
command_fail ( cmd , " Peer owned by %s " , channel - > owner - > name ) ;
2017-10-24 04:06:14 +02:00
return ;
}
2018-02-12 11:12:55 +01:00
msg = towire_channel_dev_reenable_commit ( channel ) ;
subd_req ( peer , channel - > owner , take ( msg ) , - 1 , 0 ,
2017-10-24 04:06:14 +02:00
dev_reenable_commit_finished , cmd ) ;
2017-12-15 11:15:54 +01:00
command_still_pending ( cmd ) ;
2017-10-24 04:06:14 +02:00
}
static const struct json_command dev_reenable_commit = {
" dev-reenable-commit " ,
json_dev_reenable_commit ,
2018-01-22 09:55:07 +01:00
" Re-enable the commit timer on peer {id} "
2017-10-24 04:06:14 +02:00
} ;
AUTODATA ( json_command , & dev_reenable_commit ) ;
2018-02-06 15:46:34 +01:00
struct dev_forget_channel_cmd {
struct short_channel_id scid ;
2018-02-12 11:13:04 +01:00
struct channel * channel ;
2018-02-06 15:46:34 +01:00
bool force ;
struct command * cmd ;
} ;
static void process_dev_forget_channel ( struct bitcoind * bitcoind UNUSED ,
const struct bitcoin_tx_output * txout ,
void * arg )
{
struct json_result * response ;
struct dev_forget_channel_cmd * forget = arg ;
if ( txout ! = NULL & & ! forget - > force ) {
command_fail ( forget - > cmd ,
" Cowardly refusing to forget channel with an "
" unspent funding output, if you know what "
" you're doing you can override with "
" `force=true`, otherwise consider `close` or "
" `dev-fail`! If you force and the channel "
" confirms we will not track the funds in the "
" channel " ) ;
return ;
}
response = new_json_result ( forget - > cmd ) ;
json_object_start ( response , NULL ) ;
json_add_bool ( response , " forced " , forget - > force ) ;
json_add_bool ( response , " funding_unspent " , txout ! = NULL ) ;
2018-02-19 02:06:12 +01:00
json_add_txid ( response , " funding_txid " , & forget - > channel - > funding_txid ) ;
2018-02-06 15:46:34 +01:00
json_object_end ( response ) ;
2018-02-21 16:50:49 +01:00
delete_channel ( forget - > channel ) ;
2018-02-06 15:46:34 +01:00
command_success ( forget - > cmd , response ) ;
}
static void json_dev_forget_channel ( struct command * cmd , const char * buffer ,
const jsmntok_t * params )
{
2018-02-12 11:13:04 +01:00
jsmntok_t * nodeidtok , * forcetok , * scidtok ;
struct peer * peer ;
struct channel * channel ;
struct short_channel_id scid ;
2018-02-06 15:46:34 +01:00
struct dev_forget_channel_cmd * forget = tal ( cmd , struct dev_forget_channel_cmd ) ;
forget - > cmd = cmd ;
if ( ! json_get_params ( cmd , buffer , params ,
" id " , & nodeidtok ,
2018-02-12 11:13:04 +01:00
" ?short_channel_id " , & scidtok ,
2018-02-06 15:46:34 +01:00
" ?force " , & forcetok ,
NULL ) ) {
2018-02-12 11:13:04 +01:00
return ;
}
if ( scidtok & & ! json_tok_short_channel_id ( buffer , scidtok , & scid ) ) {
command_fail ( cmd , " Invalid short_channel_id '%.*s' " ,
scidtok - > end - scidtok - > start ,
buffer + scidtok - > start ) ;
2018-02-06 15:46:34 +01:00
return ;
}
forget - > force = false ;
if ( forcetok )
json_tok_bool ( buffer , forcetok , & forget - > force ) ;
2018-02-12 11:13:04 +01:00
peer = peer_from_json ( cmd - > ld , buffer , nodeidtok ) ;
if ( ! peer ) {
2018-02-06 15:46:34 +01:00
command_fail ( cmd , " Could not find channel with that peer " ) ;
2018-02-12 11:13:04 +01:00
return ;
}
forget - > channel = NULL ;
list_for_each ( & peer - > channels , channel , list ) {
if ( scidtok ) {
if ( ! channel - > scid )
continue ;
2018-03-01 10:23:16 +01:00
if ( ! structeq ( channel - > scid , & scid ) )
2018-02-12 11:13:04 +01:00
continue ;
}
if ( forget - > channel ) {
command_fail ( cmd ,
" Multiple channels: "
" please specify short_channel_id " ) ;
return ;
}
forget - > channel = channel ;
}
if ( ! forget - > channel ) {
command_fail ( cmd ,
" No channels matching that short_channel_id " ) ;
return ;
}
2018-02-28 23:24:58 +01:00
if ( channel_has_htlc_out ( forget - > channel ) | |
channel_has_htlc_in ( forget - > channel ) ) {
command_fail ( cmd , " This channel has HTLCs attached and it is "
" not safe to forget it. Please use `close` "
" or `dev-fail` instead. " ) ;
return ;
}
2018-02-19 02:06:12 +01:00
bitcoind_gettxout ( cmd - > ld - > topology - > bitcoind ,
& forget - > channel - > funding_txid ,
forget - > channel - > funding_outnum ,
process_dev_forget_channel , forget ) ;
command_still_pending ( cmd ) ;
2018-02-06 15:46:34 +01:00
}
static const struct json_command dev_forget_channel_command = {
" dev-forget-channel " , json_dev_forget_channel ,
" Forget the channel with peer {id}, ignore UTXO check with {force}='true'. " , false ,
" Forget the channel with peer {id}. Checks if the channel is still active by checking its funding transaction. Check can be ignored by setting {force} to 'true' "
} ;
AUTODATA ( json_command , & dev_forget_channel_command ) ;
2017-10-24 04:06:14 +02:00
# endif /* DEVELOPER */