2021-12-04 12:23:56 +01:00
# include "config.h"
2017-10-23 07:05:28 +02:00
# include <ccan/array_size/array_size.h>
2017-01-04 03:52:29 +01:00
# include <ccan/err/err.h>
2022-01-03 19:45:35 +01:00
# include <ccan/json_escape/json_escape.h>
2018-01-29 01:30:15 +01:00
# include <ccan/mem/mem.h>
2017-01-04 03:52:29 +01:00
# include <ccan/opt/opt.h>
2018-01-29 01:30:15 +01:00
# include <ccan/opt/private.h>
2019-07-16 23:40:14 +02:00
# include <ccan/str/hex/hex.h>
2018-02-16 03:00:41 +01:00
# include <ccan/tal/path/path.h>
2017-01-04 03:52:29 +01:00
# include <ccan/tal/str/str.h>
2021-09-16 07:00:42 +02:00
# include <common/configdir.h>
2019-08-29 03:01:55 +02:00
# include <common/features.h>
2021-01-03 12:32:43 +01:00
# include <common/hsm_encryption.h>
2018-12-08 01:39:28 +01:00
# include <common/json_command.h>
2022-07-04 05:49:38 +02:00
# include <common/json_param.h>
2021-09-16 07:00:42 +02:00
# include <common/type_to_string.h>
2017-08-28 18:02:01 +02:00
# include <common/version.h>
2017-10-23 06:17:38 +02:00
# include <common/wireaddr.h>
2021-09-16 07:00:42 +02:00
# include <dirent.h>
2017-01-04 03:52:29 +01:00
# include <errno.h>
2017-08-28 18:04:01 +02:00
# include <lightningd/chaintopology.h>
# include <lightningd/options.h>
2018-09-20 13:46:50 +02:00
# include <lightningd/plugin.h>
2017-10-06 13:57:29 +02:00
# include <lightningd/subd.h>
2017-01-04 03:52:29 +01:00
# include <sys/stat.h>
2019-08-01 08:20:43 +02:00
# include <sys/wait.h>
2017-01-04 03:52:29 +01:00
2021-12-14 22:57:21 +01:00
/* Unless overridden, we exit with status 1 when option parsing fails */
static int opt_exitcode = 1 ;
static void opt_log_stderr_exitcode ( const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
vfprintf ( stderr , fmt , ap ) ;
fprintf ( stderr , " \n " ) ;
va_end ( ap ) ;
exit ( opt_exitcode ) ;
}
2019-09-27 11:59:13 +02:00
/* Declare opt_add_addr here, because we we call opt_add_addr
* and opt_announce_addr vice versa
*/
static char * opt_add_addr ( const char * arg , struct lightningd * ld ) ;
2017-01-04 03:52:29 +01:00
/* FIXME: Put into ccan/time. */
# define TIME_FROM_SEC(sec) { { .tv_nsec = 0, .tv_sec = sec } }
# define TIME_FROM_MSEC(msec) \
{ { . tv_nsec = ( ( msec ) % 1000 ) * 1000000 , . tv_sec = ( msec ) / 1000 } }
2018-03-18 13:22:21 +01:00
static char * opt_set_u64 ( const char * arg , u64 * u )
{
char * endp ;
unsigned long long l ;
assert ( arg ! = NULL ) ;
/* This is how the manpage says to do it. Yech. */
errno = 0 ;
l = strtoull ( arg , & endp , 0 ) ;
if ( * endp | | ! arg [ 0 ] )
return tal_fmt ( NULL , " '%s' is not a number " , arg ) ;
* u = l ;
if ( errno | | * u ! = l )
return tal_fmt ( NULL , " '%s' is out of range " , arg ) ;
return NULL ;
}
2017-01-04 03:52:29 +01:00
static char * opt_set_u32 ( const char * arg , u32 * u )
{
char * endp ;
unsigned long l ;
2018-03-01 11:32:38 +01:00
assert ( arg ! = NULL ) ;
2017-01-04 03:52:29 +01:00
/* This is how the manpage says to do it. Yech. */
errno = 0 ;
l = strtoul ( arg , & endp , 0 ) ;
if ( * endp | | ! arg [ 0 ] )
return tal_fmt ( NULL , " '%s' is not a number " , arg ) ;
* u = l ;
if ( errno | | * u ! = l )
return tal_fmt ( NULL , " '%s' is out of range " , arg ) ;
return NULL ;
}
static char * opt_set_s32 ( const char * arg , s32 * u )
{
char * endp ;
long l ;
2018-03-01 11:32:38 +01:00
assert ( arg ! = NULL ) ;
2017-01-04 03:52:29 +01:00
/* This is how the manpage says to do it. Yech. */
errno = 0 ;
l = strtol ( arg , & endp , 0 ) ;
if ( * endp | | ! arg [ 0 ] )
return tal_fmt ( NULL , " '%s' is not a number " , arg ) ;
* u = l ;
if ( errno | | * u ! = l )
return tal_fmt ( NULL , " '%s' is out of range " , arg ) ;
return NULL ;
}
2020-01-24 03:20:45 +01:00
static char * opt_set_mode ( const char * arg , mode_t * m )
{
char * endp ;
long l ;
assert ( arg ! = NULL ) ;
/* Ensure length, and starts with 0. */
if ( strlen ( arg ) ! = 4 | | arg [ 0 ] ! = ' 0 ' )
return tal_fmt ( NULL , " '%s' is not a file mode " , arg ) ;
/* strtol, manpage, yech. */
errno = 0 ;
l = strtol ( arg , & endp , 8 ) ; /* Octal. */
if ( errno | | * endp )
return tal_fmt ( NULL , " '%s' is not a file mode " , arg ) ;
* m = l ;
/* Range check not needed, previous strlen checks ensures only
* 9 - bit , which fits mode_t ( unless your Unix is seriously borked ) .
*/
return NULL ;
}
2021-07-08 04:47:03 +02:00
static char * opt_force_feerates ( const char * arg , struct lightningd * ld )
{
char * * vals = tal_strsplit ( tmpctx , arg , " / " , STR_EMPTY_OK ) ;
size_t n ;
/* vals has NULL at end, enum feerate is 0 based */
if ( tal_count ( vals ) - 1 > FEERATE_PENALTY + 1 )
return " Too many values " ;
if ( ! ld - > force_feerates )
ld - > force_feerates = tal_arr ( ld , u32 , FEERATE_PENALTY + 1 ) ;
n = 0 ;
for ( size_t i = 0 ; i < tal_count ( ld - > force_feerates ) ; i + + ) {
char * err = opt_set_u32 ( vals [ n ] , & ld - > force_feerates [ i ] ) ;
if ( err )
return err ;
fprintf ( stderr , " Set feerate %zu based on val %zu \n " , i , n ) ;
if ( vals [ n + 1 ] )
n + + ;
}
return NULL ;
}
static char * fmt_force_feerates ( const tal_t * ctx , const u32 * force_feerates )
{
char * ret ;
size_t last ;
if ( ! force_feerates )
return NULL ;
ret = tal_fmt ( ctx , " %i " , force_feerates [ 0 ] ) ;
last = 0 ;
for ( size_t i = 1 ; i < tal_count ( force_feerates ) ; i + + ) {
if ( force_feerates [ i ] = = force_feerates [ i - 1 ] )
continue ;
/* Different? Catchup! */
for ( size_t j = last + 1 ; j < = i ; j + + )
tal_append_fmt ( & ret , " /%i " , force_feerates [ j ] ) ;
last = i ;
}
return ret ;
}
2021-06-17 11:52:50 +02:00
# if EXPERIMENTAL_FEATURES
static char * opt_set_accept_extra_tlv_types ( const char * arg ,
struct lightningd * ld )
{
char * endp , * * elements = tal_strsplit ( NULL , arg , " , " , STR_NO_EMPTY ) ; ;
unsigned long long l ;
u64 u ;
for ( int i = 0 ; elements [ i ] ! = NULL ; i + + ) {
/* This is how the manpage says to do it. Yech. */
errno = 0 ;
l = strtoull ( elements [ i ] , & endp , 0 ) ;
if ( * endp | | ! arg [ 0 ] )
return tal_fmt ( NULL , " '%s' is not a number " , arg ) ;
u = l ;
if ( errno | | u ! = l )
return tal_fmt ( NULL , " '%s' is out of range " , arg ) ;
tal_arr_expand ( & ld - > accept_extra_tlv_types , u ) ;
}
tal_free ( elements ) ;
return NULL ;
}
# endif
2022-01-01 14:05:58 +01:00
# if EXPERIMENTAL_FEATURES /* BOLT7 DNS RFC #911 */
/* Returns the number of wireaddr types already announced */
static size_t num_announced_types ( enum wire_addr_type type , struct lightningd * ld )
{
size_t num = 0 ;
for ( size_t i = 0 ; i < tal_count ( ld - > proposed_wireaddr ) ; i + + ) {
if ( ld - > proposed_wireaddr [ i ] . itype ! = ADDR_INTERNAL_WIREADDR )
continue ;
if ( ld - > proposed_wireaddr [ i ] . u . wireaddr . type ! = type )
continue ;
if ( ld - > proposed_listen_announce [ i ] & ADDR_ANNOUNCE )
num + + ;
}
return num ;
}
# endif
2018-05-07 06:28:12 +02:00
static char * opt_add_addr_withtype ( const char * arg ,
struct lightningd * ld ,
2018-05-10 04:39:02 +02:00
enum addr_listen_announce ala ,
bool wildcard_ok )
2017-10-11 12:04:50 +02:00
{
2018-02-25 03:30:33 +01:00
char const * err_msg ;
2019-01-15 04:51:27 +01:00
struct wireaddr_internal wi ;
2021-09-29 11:40:05 +02:00
bool dns_ok ;
2021-10-01 13:47:29 +02:00
char * address ;
u16 port ;
2017-10-23 06:15:38 +02:00
2018-03-01 11:32:38 +01:00
assert ( arg ! = NULL ) ;
2021-09-29 11:40:05 +02:00
dns_ok = ! ld - > always_use_proxy & & ld - > config . use_dns ;
2018-03-01 11:32:38 +01:00
2021-10-01 13:47:29 +02:00
if ( ! separate_address_and_port ( tmpctx , arg , & address , & port ) )
return tal_fmt ( NULL , " Unable to parse address:port '%s' " , arg ) ;
2021-12-02 08:08:48 +01:00
if ( is_ipaddr ( address )
| | is_toraddr ( address )
| | is_wildcardaddr ( address )
| | ala ! = ADDR_ANNOUNCE ) {
2021-10-01 13:47:29 +02:00
if ( ! parse_wireaddr_internal ( arg , & wi , ld - > portnum ,
wildcard_ok , dns_ok , false ,
deprecated_apis , & err_msg ) ) {
return tal_fmt ( NULL , " Unable to parse address '%s': %s " , arg , err_msg ) ;
}
/* Sanity check for exact duplicates. */
for ( size_t i = 0 ; i < tal_count ( ld - > proposed_wireaddr ) ; i + + ) {
/* Only compare announce vs announce and bind vs bind */
if ( ( ld - > proposed_listen_announce [ i ] & ala ) = = 0 )
continue ;
if ( wireaddr_internal_eq ( & ld - > proposed_wireaddr [ i ] , & wi ) )
return tal_fmt ( NULL , " Duplicate %s address %s " ,
ala & ADDR_ANNOUNCE ? " announce " : " listen " ,
type_to_string ( tmpctx , struct wireaddr_internal , & wi ) ) ;
}
tal_arr_expand ( & ld - > proposed_listen_announce , ala ) ;
tal_arr_expand ( & ld - > proposed_wireaddr , wi ) ;
2018-01-26 18:48:14 +01:00
}
2021-11-10 01:27:41 +01:00
2021-10-19 11:32:52 +02:00
# if EXPERIMENTAL_FEATURES /* BOLT7 DNS RFC #911 */
2021-10-01 13:47:29 +02:00
/* Add ADDR_TYPE_DNS to announce DNS hostnames */
if ( is_dnsaddr ( address ) & & ala & ADDR_ANNOUNCE ) {
2022-01-01 14:05:58 +01:00
/* BOLT-hostnames #7:
* The origin node :
* . . .
* - MUST NOT announce more than one ` type 5 ` DNS hostname .
*/
if ( num_announced_types ( ADDR_TYPE_DNS , ld ) > 0 ) {
return tal_fmt ( NULL , " Only one DNS can be announced " ) ;
}
2021-10-01 13:47:29 +02:00
memset ( & wi , 0 , sizeof ( wi ) ) ;
wi . itype = ADDR_INTERNAL_WIREADDR ;
wi . u . wireaddr . type = ADDR_TYPE_DNS ;
wi . u . wireaddr . addrlen = strlen ( address ) ;
strncpy ( ( char * restrict ) & wi . u . wireaddr . addr ,
address , sizeof ( wi . u . wireaddr . addr ) - 1 ) ;
2022-07-17 13:36:04 +02:00
if ( port = = 0 )
wi . u . wireaddr . port = ld - > portnum ;
else
wi . u . wireaddr . port = port ;
2021-10-01 13:47:29 +02:00
tal_arr_expand ( & ld - > proposed_listen_announce , ADDR_ANNOUNCE ) ;
tal_arr_expand ( & ld - > proposed_wireaddr , wi ) ;
2021-11-10 01:27:41 +01:00
}
2021-10-19 11:32:52 +02:00
# endif
2021-09-15 16:19:06 +02:00
2018-01-26 18:48:14 +01:00
return NULL ;
2017-10-11 12:04:50 +02:00
2017-05-08 15:15:29 +02:00
}
2018-05-07 06:28:12 +02:00
static char * opt_add_announce_addr ( const char * arg , struct lightningd * ld )
{
2018-06-24 07:16:53 +02:00
size_t n = tal_count ( ld - > proposed_wireaddr ) ;
2019-09-27 11:59:13 +02:00
char * err ;
/* Check for autotor and reroute the call to --addr */
if ( strstarts ( arg , " autotor: " ) )
return opt_add_addr ( arg , ld ) ;
2019-11-15 09:44:22 +01:00
/* Check for statictor and reroute the call to --addr */
if ( strstarts ( arg , " statictor: " ) )
return opt_add_addr ( arg , ld ) ;
2019-09-27 11:59:13 +02:00
err = opt_add_addr_withtype ( arg , ld , ADDR_ANNOUNCE , false ) ;
2018-06-24 07:16:53 +02:00
if ( err )
return err ;
/* Can't announce anything that's not a normal wireaddr. */
if ( ld - > proposed_wireaddr [ n ] . itype ! = ADDR_INTERNAL_WIREADDR )
2022-02-23 17:58:41 +01:00
return tal_fmt ( NULL , " address '%s' is not announceable " ,
2018-06-24 07:16:53 +02:00
arg ) ;
return NULL ;
2018-05-07 06:28:12 +02:00
}
2019-09-24 08:40:17 +02:00
static char * opt_add_addr ( const char * arg , struct lightningd * ld )
{
struct wireaddr_internal addr ;
/* handle in case you used the addr option with an .onion */
2021-05-20 17:45:27 +02:00
if ( parse_wireaddr_internal ( arg , & addr , 0 , true , false , true ,
deprecated_apis , NULL ) ) {
2021-11-10 01:27:41 +01:00
if ( addr . itype = = ADDR_INTERNAL_WIREADDR & &
addr . u . wireaddr . type = = ADDR_TYPE_TOR_V3 ) {
2019-09-24 08:40:17 +02:00
log_unusual ( ld - > log , " You used `--addr=%s` option with an .onion address, please use "
" `--announce-addr` ! You are lucky in this node live some wizards and "
" fairies, we have done this for you and announce, Be as hidden as wished " ,
arg ) ;
return opt_add_announce_addr ( arg , ld ) ;
}
}
/* the intended call */
return opt_add_addr_withtype ( arg , ld , ADDR_LISTEN_AND_ANNOUNCE , true ) ;
}
2020-02-04 01:14:13 +01:00
static char * opt_subdaemon ( const char * arg , struct lightningd * ld )
{
char * subdaemon ;
char * sdpath ;
/* example arg: "hsmd:remote_hsmd" */
size_t colonoff = strcspn ( arg , " : " ) ;
if ( ! arg [ colonoff ] )
return tal_fmt ( NULL , " argument must contain ':' " ) ;
subdaemon = tal_strndup ( ld , arg , colonoff ) ;
if ( ! is_subdaemon ( subdaemon ) )
return tal_fmt ( NULL , " \" %s \" is not a subdaemon " , subdaemon ) ;
/* Make the value a tal-child of the subdaemon */
sdpath = tal_strdup ( subdaemon , arg + colonoff + 1 ) ;
/* Remove any preexisting alt subdaemon mapping (and
* implicitly , the sdpath ) . */
tal_free ( strmap_del ( & ld - > alt_subdaemons , subdaemon , NULL ) ) ;
strmap_add ( & ld - > alt_subdaemons , subdaemon , sdpath ) ;
return NULL ;
}
2019-09-24 08:40:17 +02:00
static char * opt_add_bind_addr ( const char * arg , struct lightningd * ld )
{
struct wireaddr_internal addr ;
/* handle in case you used the bind option with an .onion */
2021-05-20 17:45:27 +02:00
if ( parse_wireaddr_internal ( arg , & addr , 0 , true , false , true ,
deprecated_apis , NULL ) ) {
2021-11-10 01:27:41 +01:00
if ( addr . itype = = ADDR_INTERNAL_WIREADDR & &
addr . u . wireaddr . type = = ADDR_TYPE_TOR_V3 ) {
2019-09-24 08:40:17 +02:00
log_unusual ( ld - > log , " You used `--bind-addr=%s` option with an .onion address, "
" You are lucky in this node live some wizards and "
" fairies, we have done this for you and don't announce, Be as hidden as wished " ,
arg ) ;
return NULL ;
}
}
/* the intended call */
return opt_add_addr_withtype ( arg , ld , ADDR_LISTEN , true ) ;
}
2018-03-18 13:22:21 +01:00
static void opt_show_u64 ( char buf [ OPT_SHOW_LEN ] , const u64 * u )
{
snprintf ( buf , OPT_SHOW_LEN , " % " PRIu64 , * u ) ;
}
2017-01-04 03:52:29 +01:00
static void opt_show_u32 ( char buf [ OPT_SHOW_LEN ] , const u32 * u )
{
snprintf ( buf , OPT_SHOW_LEN , " % " PRIu32 , * u ) ;
}
static void opt_show_s32 ( char buf [ OPT_SHOW_LEN ] , const s32 * u )
{
snprintf ( buf , OPT_SHOW_LEN , " % " PRIi32 , * u ) ;
}
2020-01-24 03:20:45 +01:00
static void opt_show_mode ( char buf [ OPT_SHOW_LEN ] , const mode_t * m )
{
snprintf ( buf , OPT_SHOW_LEN , " \" %04o \" " , ( int ) * m ) ;
}
2017-10-23 07:05:28 +02:00
static char * opt_set_rgb ( const char * arg , struct lightningd * ld )
{
2018-03-01 11:32:38 +01:00
assert ( arg ! = NULL ) ;
2017-10-23 07:05:28 +02:00
ld - > rgb = tal_free ( ld - > rgb ) ;
/* BOLT #7:
*
2018-06-28 04:01:21 +02:00
* - Note : the first byte of ` rgb_color ` is the red value , the second
* byte is the green value , and the last byte is the blue value .
2018-06-17 12:13:44 +02:00
*/
2017-10-23 07:05:28 +02:00
ld - > rgb = tal_hexdata ( ld , arg , strlen ( arg ) ) ;
2018-07-28 08:00:16 +02:00
if ( ! ld - > rgb | | tal_count ( ld - > rgb ) ! = 3 )
2017-10-23 07:05:28 +02:00
return tal_fmt ( NULL , " rgb '%s' is not six hex digits " , arg ) ;
return NULL ;
}
static char * opt_set_alias ( const char * arg , struct lightningd * ld )
{
2018-03-01 11:32:38 +01:00
assert ( arg ! = NULL ) ;
2017-10-23 07:05:28 +02:00
ld - > alias = tal_free ( ld - > alias ) ;
/* BOLT #7:
*
2019-07-16 01:20:37 +02:00
* * [ ` 32 * byte ` : ` alias ` ]
2017-10-23 07:05:28 +02:00
* . . .
2018-06-17 12:13:44 +02:00
* - MUST set ` alias ` to a valid UTF - 8 string , with any
* ` alias ` trailing - bytes equal to 0.
2017-10-23 07:05:28 +02:00
*/
if ( strlen ( arg ) > 32 )
return tal_fmt ( NULL , " Alias '%s' is over 32 characters " , arg ) ;
2017-11-24 14:43:31 +01:00
ld - > alias = tal_arrz ( ld , u8 , 33 ) ;
strncpy ( ( char * ) ld - > alias , arg , 32 ) ;
2017-10-23 07:05:28 +02:00
return NULL ;
}
2018-02-22 10:42:58 +01:00
static char * opt_set_offline ( struct lightningd * ld )
{
2018-05-07 05:44:40 +02:00
ld - > reconnect = false ;
ld - > listen = false ;
2018-02-22 10:42:58 +01:00
return NULL ;
}
2018-05-10 01:18:24 +02:00
static char * opt_add_proxy_addr ( const char * arg , struct lightningd * ld )
2018-05-10 01:18:19 +02:00
{
2018-05-15 12:19:59 +02:00
bool needed_dns = false ;
2018-05-10 01:18:24 +02:00
tal_free ( ld - > proxyaddr ) ;
2018-05-10 01:18:19 +02:00
2018-05-10 01:18:23 +02:00
/* We use a tal_arr here, so we can marshal it to gossipd */
2018-05-10 01:18:24 +02:00
ld - > proxyaddr = tal_arr ( ld , struct wireaddr , 1 ) ;
2018-05-10 01:18:23 +02:00
2018-05-10 04:55:15 +02:00
if ( ! parse_wireaddr ( arg , ld - > proxyaddr , 9050 ,
2021-08-18 12:52:21 +02:00
ld - > always_use_proxy ? & needed_dns : NULL ,
2018-05-10 01:18:24 +02:00
NULL ) ) {
2018-05-10 04:55:15 +02:00
return tal_fmt ( NULL , " Unable to parse Tor proxy address '%s' %s " ,
arg , needed_dns ? " (needed dns) " : " " ) ;
2018-05-10 01:18:19 +02:00
}
return NULL ;
}
2018-09-20 13:46:50 +02:00
static char * opt_add_plugin ( const char * arg , struct lightningd * ld )
{
2022-06-15 07:47:57 +02:00
struct plugin * p ;
2020-05-05 03:15:21 +02:00
if ( plugin_blacklisted ( ld - > plugins , arg ) ) {
log_info ( ld - > log , " %s: disabled via disable-plugin " , arg ) ;
return NULL ;
}
2022-06-15 07:47:57 +02:00
p = plugin_register ( ld - > plugins , arg , NULL , false , NULL , NULL ) ;
if ( ! p )
return tal_fmt ( NULL , " Failed to register %s: %s " , arg , strerror ( errno ) ) ;
2018-09-20 13:46:50 +02:00
return NULL ;
}
2018-12-04 04:04:14 +01:00
static char * opt_disable_plugin ( const char * arg , struct lightningd * ld )
{
2020-05-05 03:15:21 +02:00
plugin_blacklist ( ld - > plugins , arg ) ;
return NULL ;
2018-12-04 04:04:14 +01:00
}
2018-12-03 10:26:29 +01:00
static char * opt_add_plugin_dir ( const char * arg , struct lightningd * ld )
{
2018-12-04 04:04:14 +01:00
return add_plugin_dir ( ld - > plugins , arg , false ) ;
}
static char * opt_clear_plugins ( struct lightningd * ld )
{
clear_plugins ( ld - > plugins ) ;
return NULL ;
2018-12-03 10:26:29 +01:00
}
2020-07-29 13:24:07 +02:00
static char * opt_important_plugin ( const char * arg , struct lightningd * ld )
{
2022-06-15 07:47:57 +02:00
struct plugin * p ;
2020-07-29 13:24:07 +02:00
if ( plugin_blacklisted ( ld - > plugins , arg ) ) {
log_info ( ld - > log , " %s: disabled via disable-plugin " , arg ) ;
return NULL ;
}
2022-06-15 07:47:57 +02:00
p = plugin_register ( ld - > plugins , arg , NULL , true , NULL , NULL ) ;
if ( ! p )
return tal_fmt ( NULL , " Failed to register %s: %s " , arg , strerror ( errno ) ) ;
2020-07-29 13:24:07 +02:00
return NULL ;
}
2022-06-26 06:43:01 +02:00
/* Test code looks in logs, so we print prompts to log as well as stdout */
static void prompt ( struct lightningd * ld , const char * str )
{
printf ( " %s \n " , str ) ;
log_debug ( ld - > log , " PROMPT: %s " , str ) ;
/* If we don't flush we might end up being buffered and we might seem
* to hang while we wait for the password . */
fflush ( stdout ) ;
}
2019-10-03 16:32:38 +02:00
/* Prompt the user to enter a password, from which will be derived the key used
* for ` hsm_secret ` encryption .
* The algorithm used to derive the key is Argon2 ( id ) , to which libsodium
* defaults . However argon2id - specific constants are used in case someone runs it
* with a libsodium version which default constants differs ( typically < 1.0 .9 ) .
*/
static char * opt_set_hsm_password ( struct lightningd * ld )
{
2021-12-14 22:57:21 +01:00
char * passwd , * passwd_confirmation , * err_msg ;
2022-03-10 22:26:20 +01:00
int is_encrypted ;
is_encrypted = is_hsm_secret_encrypted ( " hsm_secret " ) ;
if ( is_encrypted = = - 1 )
return tal_fmt ( NULL , " Could not access 'hsm_secret': %s " ,
strerror ( errno ) ) ;
2019-10-03 16:32:38 +02:00
2022-06-26 06:43:01 +02:00
prompt ( ld , " The hsm_secret is encrypted with a password. In order to "
" decrypt it and start the node you must provide the password. " ) ;
prompt ( ld , " Enter hsm_secret password: " ) ;
2021-12-14 22:57:21 +01:00
passwd = read_stdin_pass_with_exit_code ( & err_msg , & opt_exitcode ) ;
2021-01-03 14:54:13 +01:00
if ( ! passwd )
2021-12-14 22:57:21 +01:00
return err_msg ;
2022-03-10 22:26:20 +01:00
if ( ! is_encrypted ) {
2022-06-26 06:43:01 +02:00
prompt ( ld , " Confirm hsm_secret password: " ) ;
2022-03-10 22:26:20 +01:00
fflush ( stdout ) ;
passwd_confirmation = read_stdin_pass_with_exit_code ( & err_msg , & opt_exitcode ) ;
if ( ! passwd_confirmation )
return err_msg ;
if ( ! streq ( passwd , passwd_confirmation ) ) {
2022-07-20 04:29:25 +02:00
opt_exitcode = EXITCODE_HSM_BAD_PASSWORD ;
2022-03-10 22:26:20 +01:00
return " Passwords confirmation mismatch. " ;
}
free ( passwd_confirmation ) ;
2022-03-10 21:30:39 +01:00
}
2022-06-26 06:43:01 +02:00
prompt ( ld , " " ) ;
2019-10-03 16:32:38 +02:00
2021-01-03 12:32:43 +01:00
ld - > config . keypass = tal ( NULL , struct secret ) ;
2021-12-14 22:57:21 +01:00
opt_exitcode = hsm_secret_encryption_key_with_exitcode ( passwd , ld - > config . keypass , & err_msg ) ;
if ( opt_exitcode > 0 )
return err_msg ;
2021-01-03 12:32:43 +01:00
ld - > encrypted_hsm = true ;
2019-10-03 16:32:38 +02:00
free ( passwd ) ;
2021-01-03 12:32:43 +01:00
2019-10-03 16:32:38 +02:00
return NULL ;
}
2017-10-24 04:06:14 +02:00
# if DEVELOPER
2018-12-08 01:30:56 +01:00
static char * opt_subprocess_debug ( const char * optarg , struct lightningd * ld )
{
ld - > dev_debug_subprocess = optarg ;
return NULL ;
}
2019-07-16 23:40:14 +02:00
static char * opt_force_privkey ( const char * optarg , struct lightningd * ld )
{
tal_free ( ld - > dev_force_privkey ) ;
ld - > dev_force_privkey = tal ( ld , struct privkey ) ;
if ( ! hex_decode ( optarg , strlen ( optarg ) ,
ld - > dev_force_privkey , sizeof ( * ld - > dev_force_privkey ) ) )
return tal_fmt ( NULL , " Unable to parse privkey '%s' " , optarg ) ;
return NULL ;
}
2019-07-16 23:41:14 +02:00
static char * opt_force_bip32_seed ( const char * optarg , struct lightningd * ld )
{
tal_free ( ld - > dev_force_bip32_seed ) ;
ld - > dev_force_bip32_seed = tal ( ld , struct secret ) ;
if ( ! hex_decode ( optarg , strlen ( optarg ) ,
ld - > dev_force_bip32_seed ,
sizeof ( * ld - > dev_force_bip32_seed ) ) )
return tal_fmt ( NULL , " Unable to parse secret '%s' " , optarg ) ;
return NULL ;
}
2019-11-01 18:01:54 +01:00
static char * opt_force_tmp_channel_id ( const char * optarg , struct lightningd * ld )
{
tal_free ( ld - > dev_force_tmp_channel_id ) ;
ld - > dev_force_tmp_channel_id = tal ( ld , struct channel_id ) ;
if ( ! hex_decode ( optarg , strlen ( optarg ) ,
ld - > dev_force_tmp_channel_id ,
sizeof ( * ld - > dev_force_tmp_channel_id ) ) )
return tal_fmt ( NULL , " Unable to parse channel id '%s' " , optarg ) ;
return NULL ;
}
2019-07-16 23:45:14 +02:00
static char * opt_force_channel_secrets ( const char * optarg ,
struct lightningd * ld )
{
char * * strs ;
tal_free ( ld - > dev_force_channel_secrets ) ;
tal_free ( ld - > dev_force_channel_secrets_shaseed ) ;
ld - > dev_force_channel_secrets = tal ( ld , struct secrets ) ;
ld - > dev_force_channel_secrets_shaseed = tal ( ld , struct sha256 ) ;
strs = tal_strsplit ( tmpctx , optarg , " / " , STR_EMPTY_OK ) ;
if ( tal_count ( strs ) ! = 7 ) /* Last is NULL */
return " Expected 6 hex secrets separated by / " ;
if ( ! hex_decode ( strs [ 0 ] , strlen ( strs [ 0 ] ) ,
& ld - > dev_force_channel_secrets - > funding_privkey ,
sizeof ( ld - > dev_force_channel_secrets - > funding_privkey ) )
| | ! hex_decode ( strs [ 1 ] , strlen ( strs [ 1 ] ) ,
& ld - > dev_force_channel_secrets - > revocation_basepoint_secret ,
sizeof ( ld - > dev_force_channel_secrets - > revocation_basepoint_secret ) )
| | ! hex_decode ( strs [ 2 ] , strlen ( strs [ 2 ] ) ,
& ld - > dev_force_channel_secrets - > payment_basepoint_secret ,
sizeof ( ld - > dev_force_channel_secrets - > payment_basepoint_secret ) )
| | ! hex_decode ( strs [ 3 ] , strlen ( strs [ 3 ] ) ,
& ld - > dev_force_channel_secrets - > delayed_payment_basepoint_secret ,
sizeof ( ld - > dev_force_channel_secrets - > delayed_payment_basepoint_secret ) )
| | ! hex_decode ( strs [ 4 ] , strlen ( strs [ 4 ] ) ,
& ld - > dev_force_channel_secrets - > htlc_basepoint_secret ,
sizeof ( ld - > dev_force_channel_secrets - > htlc_basepoint_secret ) )
| | ! hex_decode ( strs [ 5 ] , strlen ( strs [ 5 ] ) ,
ld - > dev_force_channel_secrets_shaseed ,
sizeof ( * ld - > dev_force_channel_secrets_shaseed ) ) )
return " Expected 6 hex secrets separated by / " ;
return NULL ;
}
2020-08-25 05:23:28 +02:00
static char * opt_force_featureset ( const char * optarg ,
struct lightningd * ld )
{
char * * parts = tal_strsplit ( tmpctx , optarg , " / " , STR_EMPTY_OK ) ;
2022-02-18 16:41:05 +01:00
if ( tal_count ( parts ) ! = NUM_FEATURE_PLACE + 1 ) {
2020-10-22 20:20:29 +02:00
if ( ! strstarts ( optarg , " - " ) & & ! strstarts ( optarg , " + " ) )
2022-02-18 16:41:05 +01:00
return " Expected 5 feature sets (init/globalinit/ "
" node_announce/channel/bolt11) each terminated by / "
" OR +/-<single_bit_num> " ;
2020-10-22 20:20:29 +02:00
char * endp ;
long int n = strtol ( optarg + 1 , & endp , 10 ) ;
const struct feature_set * f ;
if ( * endp | | endp = = optarg + 1 )
return " Invalid feature number " ;
f = feature_set_for_feature ( NULL , n ) ;
if ( strstarts ( optarg , " - " )
& & ! feature_set_sub ( ld - > our_features , take ( f ) ) )
return " Feature unknown " ;
if ( strstarts ( optarg , " + " )
& & ! feature_set_or ( ld - > our_features , take ( f ) ) )
return " Feature already flagged-on " ;
return NULL ;
}
2020-08-25 05:23:28 +02:00
for ( size_t i = 0 ; parts [ i ] ; i + + ) {
char * * bits = tal_strsplit ( tmpctx , parts [ i ] , " , " , STR_EMPTY_OK ) ;
tal_resize ( & ld - > our_features - > bits [ i ] , 0 ) ;
for ( size_t j = 0 ; bits [ j ] ; j + + ) {
char * endp ;
long int n = strtol ( bits [ j ] , & endp , 10 ) ;
if ( * endp | | endp = = bits [ j ] )
return " Invalid bitnumber " ;
set_feature_bit ( & ld - > our_features - > bits [ i ] , n ) ;
}
}
return NULL ;
}
2017-08-28 18:09:01 +02:00
static void dev_register_opts ( struct lightningd * ld )
2017-01-04 03:52:29 +01:00
{
2019-07-25 08:39:40 +02:00
/* We might want to debug plugins, which are started before normal
* option parsing */
opt_register_early_arg ( " --dev-debugger=<subprocess> " , opt_subprocess_debug , NULL ,
ld , " Invoke gdb at start of <subprocess> " ) ;
2021-11-12 07:44:46 +01:00
opt_register_early_noarg ( " --dev-no-plugin-checksum " , opt_set_bool ,
& ld - > dev_no_plugin_checksum ,
" Don't checksum plugins to detect changes " ) ;
2018-05-07 05:44:40 +02:00
opt_register_noarg ( " --dev-no-reconnect " , opt_set_invbool ,
& ld - > reconnect ,
2019-07-05 16:29:32 +02:00
" Disable automatic reconnect-attempts by this node, but accept incoming " ) ;
2022-07-23 18:21:31 +02:00
opt_register_noarg ( " --dev-fast-reconnect " , opt_set_bool ,
& ld - > dev_fast_reconnect ,
" Make default reconnect delay 3 (not 60) seconds " ) ;
2017-09-12 06:55:54 +02:00
opt_register_noarg ( " --dev-fail-on-subdaemon-fail " , opt_set_bool ,
& ld - > dev_subdaemon_fail , opt_hidden ) ;
2017-10-06 13:57:29 +02:00
opt_register_arg ( " --dev-disconnect=<filename> " , opt_subd_dev_disconnect ,
NULL , ld , " File containing disconnection points " ) ;
2018-05-07 06:29:22 +02:00
opt_register_noarg ( " --dev-allow-localhost " , opt_set_bool ,
& ld - > dev_allow_localhost ,
" Announce and allow announcments for localhost address " ) ;
2018-05-17 06:08:24 +02:00
opt_register_arg ( " --dev-bitcoind-poll " , opt_set_u32 , opt_show_u32 ,
& ld - > topology - > poll_seconds ,
" Time between polling for new transactions " ) ;
2018-05-17 06:46:22 +02:00
2019-09-18 03:05:05 +02:00
opt_register_noarg ( " --dev-fast-gossip " , opt_set_bool ,
& ld - > dev_fast_gossip ,
2019-09-26 04:00:20 +02:00
" Make gossip broadcast 1 second, etc " ) ;
opt_register_noarg ( " --dev-fast-gossip-prune " , opt_set_bool ,
& ld - > dev_fast_gossip_prune ,
" Make gossip pruning 30 seconds " ) ;
2019-04-08 01:51:30 +02:00
opt_register_arg ( " --dev-gossip-time " , opt_set_u32 , opt_show_u32 ,
& ld - > dev_gossip_time ,
" UNIX time to override gossipd to use. " ) ;
2019-07-16 23:40:14 +02:00
opt_register_arg ( " --dev-force-privkey " , opt_force_privkey , NULL , ld ,
" Force HSM to use this as node private key " ) ;
2019-07-16 23:41:14 +02:00
opt_register_arg ( " --dev-force-bip32-seed " , opt_force_bip32_seed , NULL , ld ,
" Force HSM to use this as bip32 seed " ) ;
2019-07-16 23:45:14 +02:00
opt_register_arg ( " --dev-force-channel-secrets " , opt_force_channel_secrets , NULL , ld ,
" Force HSM to use these for all per-channel secrets " ) ;
2019-07-25 08:39:40 +02:00
opt_register_arg ( " --dev-max-funding-unconfirmed-blocks " ,
opt_set_u32 , opt_show_u32 ,
2021-04-05 23:12:11 +02:00
& ld - > dev_max_funding_unconfirmed ,
2019-07-25 08:39:40 +02:00
" Maximum number of blocks we wait for a channel "
" funding transaction to confirm, if we are the "
" fundee. " ) ;
2019-11-01 18:01:54 +01:00
opt_register_arg ( " --dev-force-tmp-channel-id " , opt_force_tmp_channel_id , NULL , ld ,
" Force the temporary channel id, instead of random " ) ;
2019-11-14 01:09:38 +01:00
opt_register_noarg ( " --dev-no-htlc-timeout " , opt_set_bool ,
& ld - > dev_no_htlc_timeout ,
" Don't kill channeld if HTLCs not confirmed within 30 seconds " ) ;
2020-01-23 06:48:42 +01:00
opt_register_noarg ( " --dev-fail-process-onionpacket " , opt_set_bool ,
& dev_fail_process_onionpacket ,
" Force all processing of onion packets to fail " ) ;
2020-07-22 14:07:22 +02:00
opt_register_noarg ( " --dev-no-version-checks " , opt_set_bool ,
& ld - > dev_no_version_checks ,
" Skip calling subdaemons with --version on startup " ) ;
2020-08-04 09:24:42 +02:00
opt_register_early_noarg ( " --dev-builtin-plugins-unimportant " ,
opt_set_bool ,
& ld - > plugins - > dev_builtin_plugins_unimportant ,
" Make builtin plugins unimportant so you can plugin stop them. " ) ;
2020-08-25 05:23:28 +02:00
opt_register_arg ( " --dev-force-features " , opt_force_featureset , NULL , ld ,
2022-02-18 16:41:05 +01:00
" Force the init/globalinit/node_announce/channel/bolt11/ features, each comma-separated bitnumbers OR a single +/-<bitnumber> " ) ;
2020-09-11 08:48:12 +02:00
opt_register_arg ( " --dev-timeout-secs " , opt_set_u32 , opt_show_u32 ,
& ld - > config . connection_timeout_secs ,
" Seconds to timeout if we don't receive INIT from peer " ) ;
2021-09-30 23:19:37 +02:00
opt_register_noarg ( " --dev-no-modern-onion " , opt_set_bool ,
& ld - > dev_ignore_modern_onion ,
" Ignore modern onion messages " ) ;
2022-03-28 01:10:54 +02:00
opt_register_noarg ( " --dev-no-obsolete-onion " , opt_set_bool ,
& ld - > dev_ignore_obsolete_onion ,
" Ignore obsolete onion messages " ) ;
2021-12-29 04:26:40 +01:00
opt_register_arg ( " --dev-disable-commit-after " ,
opt_set_intval , opt_show_intval ,
& ld - > dev_disable_commit ,
" Disable commit timer after this many commits " ) ;
2022-03-25 04:11:55 +01:00
opt_register_noarg ( " --dev-no-ping-timer " , opt_set_bool ,
& ld - > dev_no_ping_timer ,
" Don't hang up if we don't get a ping response " ) ;
2019-07-16 23:41:14 +02:00
}
2019-07-25 08:39:40 +02:00
# endif /* DEVELOPER */
2017-01-04 03:52:29 +01:00
static const struct config testnet_config = {
/* 6 blocks to catch cheating attempts. */
. locktime_blocks = 6 ,
2018-06-11 13:43:30 +02:00
/* They can have up to 14 days, maximumu value that lnd will ask for by default. */
/* FIXME Convince lnd to use more reasonable defaults... */
2018-06-15 15:35:55 +02:00
. locktime_max = 14 * 24 * 6 ,
2017-01-04 03:52:29 +01:00
/* We're fairly trusting, under normal circumstances. */
. anchor_confirms = 1 ,
2019-07-27 19:45:22 +02:00
/* Testnet blockspace is free. */
. max_concurrent_htlcs = 483 ,
2022-03-26 14:31:26 +01:00
/* channel defaults for htlc min/max values */
. htlc_minimum_msat = AMOUNT_MSAT ( 0 ) ,
. htlc_maximum_msat = AMOUNT_MSAT ( - 1ULL ) , /* no limit */
2021-09-28 21:03:08 +02:00
/* Max amount of dust allowed per channel (50ksat) */
. max_dust_htlc_exposure_msat = AMOUNT_MSAT ( 50000000 ) ,
2017-10-23 06:16:57 +02:00
/* Be aggressive on testnet. */
. cltv_expiry_delta = 6 ,
2018-06-08 08:02:52 +02:00
. cltv_final = 10 ,
2017-10-23 06:16:57 +02:00
2017-01-04 03:52:29 +01:00
/* Send commit 10msec after receiving; almost immediately. */
2018-05-17 06:46:22 +02:00
. commit_time_ms = 10 ,
2017-01-04 03:52:29 +01:00
/* Allow dust payments */
. fee_base = 1 ,
/* Take 0.001% */
. fee_per_satoshi = 10 ,
2018-01-16 10:24:46 +01:00
/* Testnet sucks */
. ignore_fee_limits = true ,
2018-04-18 15:23:15 +02:00
/* Rescan 5 hours of blocks on testnet, it's reorg happy */
. rescan = 30 ,
2018-06-11 19:50:37 +02:00
2018-06-20 13:11:25 +02:00
. use_dns = true ,
2019-04-03 10:20:38 +02:00
2022-03-26 14:31:26 +01:00
/* Turn off IP address announcement discovered via peer `remote_addr` */
. disable_ip_discovery = false ,
2019-04-15 22:48:10 +02:00
/* Sets min_effective_htlc_capacity - at 1000$/BTC this is 10ct */
. min_capacity_sat = 10000 ,
2019-09-25 13:05:14 +02:00
2020-09-11 08:48:12 +02:00
/* 1 minute should be enough for anyone! */
. connection_timeout_secs = 60 ,
2021-01-13 09:58:38 +01:00
. exp_offers = IFEXPERIMENTAL ( true , false ) ,
2017-01-04 03:52:29 +01:00
} ;
/* aka. "Dude, where's my coins?" */
static const struct config mainnet_config = {
/* ~one day to catch cheating attempts. */
. locktime_blocks = 6 * 24 ,
2018-06-11 13:43:30 +02:00
/* They can have up to 14 days, maximumu value that lnd will ask for by default. */
/* FIXME Convince lnd to use more reasonable defaults... */
2018-06-15 15:35:55 +02:00
. locktime_max = 14 * 24 * 6 ,
2017-01-04 03:52:29 +01:00
/* We're fairly trusting, under normal circumstances. */
. anchor_confirms = 3 ,
2019-07-27 19:45:22 +02:00
/* While up to 483 htlcs are possible we do 30 by default (as eclair does) to save blockspace */
. max_concurrent_htlcs = 30 ,
2022-03-26 14:31:26 +01:00
/* defaults for htlc min/max values */
. htlc_minimum_msat = AMOUNT_MSAT ( 0 ) ,
. htlc_maximum_msat = AMOUNT_MSAT ( - 1ULL ) , /* no limit */
2021-09-28 21:03:08 +02:00
/* Max amount of dust allowed per channel (50ksat) */
. max_dust_htlc_exposure_msat = AMOUNT_MSAT ( 50000000 ) ,
2017-10-23 06:16:57 +02:00
/* BOLT #2:
*
2018-06-17 12:13:44 +02:00
* 1. the ` cltv_expiry_delta ` for channels , ` 3 R + 2 G + 2 S ` : if in doubt , a
2020-08-20 08:50:47 +02:00
* ` cltv_expiry_delta ` of at least 34 is reasonable ( R = 2 , G = 2 , S = 12 )
2018-06-17 12:13:44 +02:00
*/
2020-08-20 08:50:47 +02:00
/* R = 2, G = 2, S = 12 */
. cltv_expiry_delta = 34 ,
2017-10-23 06:16:57 +02:00
/* BOLT #2:
*
2018-06-17 12:13:44 +02:00
* 4. the minimum ` cltv_expiry ` accepted for terminal payments : the
* worst case for the terminal node C is ` 2 R + G + S ` blocks */
2020-08-20 08:50:47 +02:00
. cltv_final = 18 ,
2017-10-23 06:16:57 +02:00
2017-01-04 03:52:29 +01:00
/* Send commit 10msec after receiving; almost immediately. */
2018-05-17 06:46:22 +02:00
. commit_time_ms = 10 ,
2017-01-04 03:52:29 +01:00
/* Discourage dust payments */
2018-01-19 15:59:20 +01:00
. fee_base = 1000 ,
2017-01-04 03:52:29 +01:00
/* Take 0.001% */
. fee_per_satoshi = 10 ,
2018-01-16 10:24:46 +01:00
/* Mainnet should have more stable fees */
. ignore_fee_limits = false ,
2018-04-18 15:23:15 +02:00
/* Rescan 2.5 hours of blocks on startup, it's not so reorg happy */
. rescan = 15 ,
2018-06-11 19:50:37 +02:00
2018-06-20 13:11:25 +02:00
. use_dns = true ,
2019-04-03 10:20:38 +02:00
2022-03-26 14:31:26 +01:00
/* Turn off IP address announcement discovered via peer `remote_addr` */
. disable_ip_discovery = false ,
2019-04-15 22:48:10 +02:00
/* Sets min_effective_htlc_capacity - at 1000$/BTC this is 10ct */
. min_capacity_sat = 10000 ,
2019-09-25 13:05:14 +02:00
2020-09-11 08:48:12 +02:00
/* 1 minute should be enough for anyone! */
. connection_timeout_secs = 60 ,
2021-01-13 09:58:38 +01:00
. exp_offers = IFEXPERIMENTAL ( true , false ) ,
2017-01-04 03:52:29 +01:00
} ;
2017-08-28 18:09:01 +02:00
static void check_config ( struct lightningd * ld )
2017-01-04 03:52:29 +01:00
{
2019-07-27 19:45:22 +02:00
/* BOLT #2:
*
* The receiving node MUST fail the channel if :
* . . .
* - ` max_accepted_htlcs ` is greater than 483.
*/
if ( ld - > config . max_concurrent_htlcs < 1 | | ld - > config . max_concurrent_htlcs > 483 )
fatal ( " --max-concurrent-htlcs value must be between 1 and 483 it is: %u " ,
ld - > config . max_concurrent_htlcs ) ;
2017-08-28 18:09:01 +02:00
if ( ld - > config . anchor_confirms = = 0 )
2017-01-04 03:52:29 +01:00
fatal ( " anchor-confirms must be greater than zero " ) ;
2018-05-10 01:18:23 +02:00
2021-08-18 12:52:21 +02:00
if ( ld - > always_use_proxy & & ! ld - > proxyaddr )
2018-05-10 01:18:24 +02:00
fatal ( " --always-use-proxy needs --proxy " ) ;
2021-01-25 02:12:23 +01:00
2022-06-26 06:25:01 +02:00
if ( ld - > daemon_parent_fd ! = - 1 & & ! ld - > logfiles )
2021-01-25 02:12:23 +01:00
fatal ( " --daemon needs --log-file " ) ;
2017-01-04 03:52:29 +01:00
}
2018-09-03 02:42:27 +02:00
static char * test_subdaemons_and_exit ( struct lightningd * ld )
2018-01-03 12:05:44 +01:00
{
2018-09-03 02:42:27 +02:00
test_subdaemons ( ld ) ;
2018-01-03 12:05:44 +01:00
exit ( 0 ) ;
return NULL ;
}
2019-08-29 03:01:55 +02:00
static char * list_features_and_exit ( struct lightningd * ld )
{
2020-04-03 02:03:59 +02:00
const char * * features = list_supported_features ( tmpctx , ld - > our_features ) ;
2019-08-29 03:01:55 +02:00
for ( size_t i = 0 ; i < tal_count ( features ) ; i + + )
printf ( " %s \n " , features [ i ] ) ;
2021-09-10 04:14:23 +02:00
# if EXPERIMENTAL_FEATURES
printf ( " supports_open_accept_channel_type \n " ) ;
# endif
2019-08-29 03:01:55 +02:00
exit ( 0 ) ;
}
2018-08-11 10:31:26 +02:00
static char * opt_lightningd_usage ( struct lightningd * ld )
{
char * extra = tal_fmt ( NULL , " \n A bitcoin lightning daemon (default "
2019-10-15 12:58:30 +02:00
" values shown for network: %s). " , chainparams - > network_name ) ;
2018-08-11 10:31:26 +02:00
opt_usage_and_exit ( extra ) ;
tal_free ( extra ) ;
2018-08-01 02:53:20 +02:00
return NULL ;
}
2019-08-01 08:20:43 +02:00
static char * opt_start_daemon ( struct lightningd * ld )
{
int fds [ 2 ] ;
int exitcode , pid ;
/* Already a daemon? OK. */
if ( ld - > daemon_parent_fd ! = - 1 )
return NULL ;
if ( pipe ( fds ) ! = 0 )
err ( 1 , " Creating pipe to talk to --daemon " ) ;
pid = fork ( ) ;
if ( pid = = - 1 )
err ( 1 , " Fork failed for --daemon " ) ;
if ( pid = = 0 ) {
/* Child returns, continues as normal. */
close ( fds [ 0 ] ) ;
ld - > daemon_parent_fd = fds [ 1 ] ;
return NULL ;
}
/* OK, we are the parent. We exit with status told to us by
* child . */
close ( fds [ 1 ] ) ;
if ( read ( fds [ 0 ] , & exitcode , sizeof ( exitcode ) ) = = sizeof ( exitcode ) )
_exit ( exitcode ) ;
/* It died before writing exitcode (presumably 0), so we grab it */
waitpid ( pid , & exitcode , 0 ) ;
if ( WIFEXITED ( exitcode ) )
_exit ( WEXITSTATUS ( exitcode ) ) ;
errx ( 1 , " Died with signal %u " , WTERMSIG ( exitcode ) ) ;
}
2021-09-28 21:03:08 +02:00
static char * opt_set_msat ( const char * arg , struct amount_msat * amt )
{
if ( ! parse_amount_msat ( amt , arg , strlen ( arg ) ) )
return tal_fmt ( NULL , " Unable to parse millisatoshi '%s' " , arg ) ;
return NULL ;
}
2020-04-03 02:03:58 +02:00
static char * opt_set_wumbo ( struct lightningd * ld )
{
2020-04-03 02:03:59 +02:00
feature_set_or ( ld - > our_features ,
2020-04-03 02:03:58 +02:00
take ( feature_set_for_feature ( NULL ,
OPTIONAL_FEATURE ( OPT_LARGE_CHANNELS ) ) ) ) ;
return NULL ;
}
2021-10-18 02:13:33 +02:00
static char * opt_set_websocket_port ( const char * arg , struct lightningd * ld )
{
u32 port COMPILER_WANTS_INIT ( " 9.3.0 -O2 " ) ;
char * err ;
err = opt_set_u32 ( arg , & port ) ;
if ( err )
return err ;
ld - > websocket_port = port ;
if ( ld - > websocket_port ! = port )
return tal_fmt ( NULL , " '%s' is out of range " , arg ) ;
return NULL ;
}
2020-12-10 01:10:17 +01:00
static char * opt_set_dual_fund ( struct lightningd * ld )
{
2021-03-12 01:22:50 +01:00
/* Dual funding implies anchor outputs */
feature_set_or ( ld - > our_features ,
take ( feature_set_for_feature ( NULL ,
OPTIONAL_FEATURE ( OPT_ANCHOR_OUTPUTS ) ) ) ) ;
2020-12-10 01:10:17 +01:00
feature_set_or ( ld - > our_features ,
take ( feature_set_for_feature ( NULL ,
OPTIONAL_FEATURE ( OPT_DUAL_FUND ) ) ) ) ;
return NULL ;
}
2021-01-13 04:00:20 +01:00
static char * opt_set_onion_messages ( struct lightningd * ld )
{
feature_set_or ( ld - > our_features ,
take ( feature_set_for_feature ( NULL ,
OPTIONAL_FEATURE ( OPT_ONION_MESSAGES ) ) ) ) ;
return NULL ;
}
2021-03-15 04:39:44 +01:00
static char * opt_set_shutdown_wrong_funding ( struct lightningd * ld )
{
feature_set_or ( ld - > our_features ,
take ( feature_set_for_feature ( NULL ,
OPTIONAL_FEATURE ( OPT_SHUTDOWN_WRONG_FUNDING ) ) ) ) ;
return NULL ;
}
2021-01-13 09:58:38 +01:00
static char * opt_set_offers ( struct lightningd * ld )
{
ld - > config . exp_offers = true ;
return opt_set_onion_messages ( ld ) ;
}
2019-07-25 08:37:58 +02:00
static void register_opts ( struct lightningd * ld )
{
2019-07-25 08:39:40 +02:00
/* This happens before plugins started */
opt_register_early_noarg ( " --test-daemons-only " ,
test_subdaemons_and_exit ,
ld , opt_hidden ) ;
/* Register plugins as an early args, so we can initialize them and have
* them register more command line options */
opt_register_early_arg ( " --plugin " , opt_add_plugin , NULL , ld ,
" Add a plugin to be run (can be used multiple times) " ) ;
opt_register_early_arg ( " --plugin-dir " , opt_add_plugin_dir ,
NULL , ld ,
" Add a directory to load plugins from (can be used multiple times) " ) ;
opt_register_early_noarg ( " --clear-plugins " , opt_clear_plugins ,
ld ,
" Remove all plugins added before this option " ) ;
opt_register_early_arg ( " --disable-plugin " , opt_disable_plugin ,
NULL , ld ,
" Disable a particular plugin by filename/name " ) ;
2020-07-29 13:24:07 +02:00
opt_register_early_arg ( " --important-plugin " , opt_important_plugin ,
NULL , ld ,
" Add an important plugin to be run (can be used multiple times). Die if the plugin dies. " ) ;
2019-07-25 08:39:40 +02:00
/* Early, as it suppresses DNS lookups from cmdline too. */
opt_register_early_arg ( " --always-use-proxy " ,
opt_set_bool_arg , opt_show_bool ,
2021-08-18 12:52:21 +02:00
& ld - > always_use_proxy , " Use the proxy always " ) ;
2019-07-25 08:39:40 +02:00
2019-08-01 08:20:43 +02:00
/* This immediately makes is a daemon. */
opt_register_early_noarg ( " --daemon " , opt_start_daemon , ld ,
" Run in the background, suppress stdout/stderr " ) ;
2019-11-23 02:45:53 +01:00
opt_register_early_arg ( " --wallet " , opt_set_talstr , NULL ,
& ld - > wallet_dsn ,
" Location of the wallet database. " ) ;
2019-08-01 08:20:43 +02:00
2020-04-03 02:03:58 +02:00
/* This affects our features, so set early. */
opt_register_early_noarg ( " --large-channels|--wumbo " ,
opt_set_wumbo , ld ,
" Allow channels larger than 0.16777215 BTC " ) ;
2020-12-10 01:10:17 +01:00
opt_register_early_noarg ( " --experimental-dual-fund " ,
opt_set_dual_fund , ld ,
" experimental: Advertise dual-funding "
" and allow peers to establish channels "
2021-03-12 01:19:40 +01:00
" via v2 channel open protocol. " ) ;
2020-12-10 01:10:17 +01:00
2021-01-13 04:00:20 +01:00
/* This affects our features, so set early. */
opt_register_early_noarg ( " --experimental-onion-messages " ,
opt_set_onion_messages , ld ,
" EXPERIMENTAL: enable send, receive and relay "
" of onion messages " ) ;
2021-01-13 09:58:38 +01:00
opt_register_early_noarg ( " --experimental-offers " ,
opt_set_offers , ld ,
" EXPERIMENTAL: enable send and receive of offers "
" (also sets experimental-onion-messages) " ) ;
2021-03-15 04:39:44 +01:00
opt_register_early_noarg ( " --experimental-shutdown-wrong-funding " ,
opt_set_shutdown_wrong_funding , ld ,
" EXPERIMENTAL: allow shutdown with alternate txids " ) ;
2020-12-10 01:10:17 +01:00
2018-11-02 01:19:47 +01:00
opt_register_noarg ( " --help|-h " , opt_lightningd_usage , ld ,
2017-01-04 04:34:15 +01:00
" Print this message. " ) ;
2017-10-23 07:05:28 +02:00
opt_register_arg ( " --rgb " , opt_set_rgb , NULL , ld ,
" RRGGBB hex color for node " ) ;
opt_register_arg ( " --alias " , opt_set_alias , NULL , ld ,
" Up to 32-byte alias for node " ) ;
2018-01-09 15:45:07 +01:00
2018-02-20 00:00:09 +01:00
opt_register_arg ( " --pid-file=<file> " , opt_set_talstr , opt_show_charp ,
& ld - > pidfile ,
" Specify pid file " ) ;
2018-01-30 15:17:58 +01:00
2019-07-25 08:39:40 +02:00
opt_register_arg ( " --ignore-fee-limits " , opt_set_bool_arg , opt_show_bool ,
& ld - > config . ignore_fee_limits ,
" (DANGEROUS) allow peer to set any feerate " ) ;
opt_register_arg ( " --watchtime-blocks " , opt_set_u32 , opt_show_u32 ,
& ld - > config . locktime_blocks ,
" Blocks before peer can unilaterally spend funds " ) ;
opt_register_arg ( " --max-locktime-blocks " , opt_set_u32 , opt_show_u32 ,
& ld - > config . locktime_max ,
" Maximum blocks funds may be locked for " ) ;
opt_register_arg ( " --funding-confirms " , opt_set_u32 , opt_show_u32 ,
& ld - > config . anchor_confirms ,
" Confirmations required for funding transaction " ) ;
opt_register_arg ( " --cltv-delta " , opt_set_u32 , opt_show_u32 ,
& ld - > config . cltv_expiry_delta ,
" Number of blocks for cltv_expiry_delta " ) ;
opt_register_arg ( " --cltv-final " , opt_set_u32 , opt_show_u32 ,
& ld - > config . cltv_final ,
" Number of blocks for final cltv_expiry " ) ;
opt_register_arg ( " --commit-time=<millseconds> " ,
opt_set_u32 , opt_show_u32 ,
& ld - > config . commit_time_ms ,
" Time after changes before sending out COMMIT " ) ;
opt_register_arg ( " --fee-base " , opt_set_u32 , opt_show_u32 ,
& ld - > config . fee_base ,
" Millisatoshi minimum to charge for HTLC " ) ;
opt_register_arg ( " --rescan " , opt_set_s32 , opt_show_s32 ,
& ld - > config . rescan ,
" Number of blocks to rescan from the current head, or "
" absolute blockheight if negative " ) ;
opt_register_arg ( " --fee-per-satoshi " , opt_set_u32 , opt_show_u32 ,
& ld - > config . fee_per_satoshi ,
" Microsatoshi fee for every satoshi in HTLC " ) ;
2022-03-26 14:31:26 +01:00
opt_register_arg ( " --htlc-minimum-msat " , opt_set_msat , NULL ,
& ld - > config . htlc_minimum_msat ,
" The default minimal value an HTLC must carry in order to be forwardable for new channels " ) ;
opt_register_arg ( " --htlc-maximum-msat " , opt_set_msat , NULL ,
& ld - > config . htlc_maximum_msat ,
" The default maximal value an HTLC must carry in order to be forwardable for new channel " ) ;
2019-07-27 19:45:22 +02:00
opt_register_arg ( " --max-concurrent-htlcs " , opt_set_u32 , opt_show_u32 ,
& ld - > config . max_concurrent_htlcs ,
" Number of HTLCs one channel can handle concurrently. Should be between 1 and 483 " ) ;
2021-09-28 21:03:08 +02:00
opt_register_arg ( " --max-dust-htlc-exposure-msat " , opt_set_msat ,
NULL , & ld - > config . max_dust_htlc_exposure_msat ,
" Max HTLC amount that can be trimmed " ) ;
2019-07-25 08:39:40 +02:00
opt_register_arg ( " --min-capacity-sat " , opt_set_u64 , opt_show_u64 ,
& ld - > config . min_capacity_sat ,
" Minimum capacity in satoshis for accepting channels " ) ;
opt_register_arg ( " --addr " , opt_add_addr , NULL ,
ld ,
" Set an IP address (v4 or v6) to listen on and announce to the network for incoming connections " ) ;
opt_register_arg ( " --bind-addr " , opt_add_bind_addr , NULL ,
ld ,
" Set an IP address (v4 or v6) to listen on, but not announce " ) ;
opt_register_arg ( " --announce-addr " , opt_add_announce_addr , NULL ,
ld ,
2021-05-20 17:45:27 +02:00
" Set an IP address (v4 or v6) or .onion v3 to announce, but not listen on " ) ;
2022-03-26 14:31:26 +01:00
opt_register_noarg ( " --disable-ip-discovery " , opt_set_bool ,
& ld - > config . disable_ip_discovery ,
" Turn off announcement of discovered public IPs " ) ;
2019-07-25 08:39:40 +02:00
opt_register_noarg ( " --offline " , opt_set_offline , ld ,
" Start in offline-mode (do not automatically reconnect and do not accept incoming connections) " ) ;
opt_register_arg ( " --autolisten " , opt_set_bool_arg , opt_show_bool ,
& ld - > autolisten ,
" If true, listen on default port and announce if it seems to be a public interface " ) ;
opt_register_arg ( " --proxy " , opt_add_proxy_addr , NULL ,
ld , " Set a socks v5 proxy IP address and port " ) ;
opt_register_arg ( " --tor-service-password " , opt_set_talstr , NULL ,
& ld - > tor_service_password ,
" Set a Tor hidden service password " ) ;
2021-06-17 11:52:50 +02:00
# if EXPERIMENTAL_FEATURES
opt_register_arg ( " --experimental-accept-extra-tlv-types " ,
opt_set_accept_extra_tlv_types , NULL , ld ,
" Comma separated list of extra TLV types to accept. " ) ;
# endif
2021-09-21 15:50:57 +02:00
opt_register_early_noarg ( " --disable-dns " , opt_set_invbool , & ld - > config . use_dns ,
" Disable DNS lookups of peers " ) ;
2019-07-25 08:39:40 +02:00
2019-10-03 16:32:38 +02:00
opt_register_noarg ( " --encrypted-hsm " , opt_set_hsm_password , ld ,
2021-12-14 22:57:21 +01:00
" Set the password to encrypt hsm_secret with. If no password is passed through command line, "
" you will be prompted to enter it. " ) ;
2019-10-03 16:32:38 +02:00
2020-01-24 03:20:45 +01:00
opt_register_arg ( " --rpc-file-mode " , & opt_set_mode , & opt_show_mode ,
& ld - > rpc_filemode ,
" Set the file mode (permissions) for the "
" JSON-RPC socket " ) ;
2021-07-08 04:47:03 +02:00
opt_register_arg ( " --force-feerates " ,
opt_force_feerates , NULL , ld ,
" Set testnet/regtest feerates in sats perkw, opening/mutual_close/unlateral_close/delayed_to_us/htlc_resolution/penalty: if fewer specified, last number applies to remainder " ) ;
2020-02-04 01:14:13 +01:00
opt_register_arg ( " --subdaemon " , opt_subdaemon , NULL ,
ld , " Arg specified as SUBDAEMON:PATH. "
" Specifies an alternate subdaemon binary. "
" If the supplied path is relative the subdaemon "
" binary is found in the working directory. "
" This option may be specified multiple times. "
" For example, "
" --subdaemon=hsmd:remote_signer "
" would use a hypothetical remote signing subdaemon. " ) ;
2021-10-18 02:13:33 +02:00
opt_register_arg ( " --experimental-websocket-port " ,
opt_set_websocket_port , NULL ,
ld ,
" experimental: alternate port for peers to connect "
" using WebSockets (RFC6455) " ) ;
2018-01-29 01:30:15 +01:00
opt_register_logging ( ld ) ;
2017-01-04 03:52:29 +01:00
opt_register_version ( ) ;
2017-10-24 04:06:14 +02:00
# if DEVELOPER
2017-08-28 18:09:01 +02:00
dev_register_opts ( ld ) ;
2017-10-24 04:06:14 +02:00
# endif
2017-02-24 06:52:56 +01:00
}
2019-11-23 02:46:57 +01:00
/* We are in ld->config_netdir when this is run! */
static void promote_missing_files ( struct lightningd * ld )
{
# ifdef COMPAT_V073
DIR * d_from ;
struct dirent * d ;
struct stat st ;
/* If hsm_secret already exists, we assume we're ugpraded */
if ( stat ( " hsm_secret " , & st ) = = 0 )
return ;
if ( errno ! = ENOENT )
err ( 1 , " Looking for hsm_secret in lightning dir " ) ;
/* If hsm doesn't exist in basedir, we've nothing to upgrade. */
if ( stat ( path_join ( tmpctx , ld - > config_basedir , " hsm_secret " ) , & st ) ! = 0 )
return ;
d_from = opendir ( ld - > config_basedir ) ;
if ( ! d_from )
err ( 1 , " Opening %s " , ld - > config_basedir ) ;
while ( ( d = readdir ( d_from ) ) ! = NULL ) {
const char * fullname ;
2019-11-23 02:46:58 +01:00
/* Ignore this directory and upper one, and leave
* config and pid files */
2019-11-23 02:46:57 +01:00
if ( streq ( d - > d_name , " . " )
| | streq ( d - > d_name , " .. " )
2019-11-23 02:46:58 +01:00
| | streq ( d - > d_name , " config " )
| | strends ( d - > d_name , " .pid " ) )
2019-11-23 02:46:57 +01:00
continue ;
fullname = path_join ( tmpctx , ld - > config_basedir , d - > d_name ) ;
2020-01-28 04:06:51 +01:00
/* Simply remove rpc file: if they use --rpc-file to place it
* here explicitly it will get recreated , but moving it would
* be confusing as it would be unused . */
if ( streq ( d - > d_name , " lightning-rpc " ) ) {
if ( unlink ( fullname ) ! = 0 )
log_unusual ( ld - > log , " Could not unlink %s: %s " ,
fullname , strerror ( errno ) ) ;
continue ;
}
2019-11-23 02:46:57 +01:00
/* Ignore any directories. */
if ( lstat ( fullname , & st ) ! = 0 )
errx ( 1 , " Could not stat %s " , fullname ) ;
if ( ( st . st_mode & S_IFMT ) = = S_IFDIR )
continue ;
/* Check we don't overwrite something in this dir! */
if ( lstat ( d - > d_name , & st ) ! = - 1 )
errx ( 1 , " Refusing to overwrite %s into %s/ " ,
fullname , ld - > config_netdir ) ;
log_unusual ( ld - > log , " Moving %s into %s/ " ,
d - > d_name , ld - > config_netdir ) ;
if ( rename ( fullname , d - > d_name ) ! = 0 )
err ( 1 , " Could not move %s/%s to %s " ,
ld - > config_basedir , d - > d_name , ld - > config_netdir ) ;
}
closedir ( d_from ) ;
# endif /* COMPAT_V073 */
}
2017-10-23 07:05:28 +02:00
/* Names stolen from https://github.com/ternus/nsaproductgenerator/blob/master/nsa.js */
static const char * codename_adjective [ ]
= { " LOUD " , " RED " , " BLUE " , " GREEN " , " YELLOW " , " IRATE " , " ANGRY " , " PEEVED " ,
" HAPPY " , " SLIMY " , " SLEEPY " , " JUNIOR " , " SLICKER " , " UNITED " , " SOMBER " ,
" BIZARRE " , " ODD " , " WEIRD " , " WRONG " , " LATENT " , " CHILLY " , " STRANGE " , " LOUD " ,
" SILENT " , " HOPPING " , " ORANGE " , " VIOLET " , " VIOLENT " , " LIGHTNING " } ;
static const char * codename_noun [ ]
= { " WHISPER " , " FELONY " , " MOON " , " SUCKER " , " PENGUIN " , " WAFFLE " , " MAESTRO " ,
" NIGHT " , " TRINITY " , " DEITY " , " MONKEY " , " ARK " , " SQUIRREL " , " IRON " , " BOUNCE " ,
" FARM " , " CHEF " , " TROUGH " , " NET " , " TRAWL " , " GLEE " , " WATER " , " SPORK " , " PLOW " ,
" FEED " , " SOUFFLE " , " ROUTE " , " BAGEL " , " MONTANA " , " ANALYST " , " AUTO " , " WATCH " ,
" PHOTO " , " YARD " , " SOURCE " , " MONKEY " , " SEAGULL " , " TOLL " , " SPAWN " , " GOPHER " ,
" CHIPMUNK " , " SET " , " CALENDAR " , " ARTIST " , " CHASER " , " SCAN " , " TOTE " , " BEAM " ,
" ENTOURAGE " , " GENESIS " , " WALK " , " SPATULA " , " RAGE " , " FIRE " , " MASTER " } ;
void setup_color_and_alias ( struct lightningd * ld )
{
if ( ! ld - > rgb )
/* You can't get much red by default */
2019-04-08 11:58:32 +02:00
ld - > rgb = tal_dup_arr ( ld , u8 , ld - > id . k , 3 , 0 ) ;
2017-10-23 07:05:28 +02:00
if ( ! ld - > alias ) {
u64 adjective , noun ;
2018-02-22 11:00:33 +01:00
char * name ;
2017-10-23 07:05:28 +02:00
2019-04-08 11:58:32 +02:00
memcpy ( & adjective , ld - > id . k + 3 , sizeof ( adjective ) ) ;
memcpy ( & noun , ld - > id . k + 3 + sizeof ( adjective ) , sizeof ( noun ) ) ;
2017-10-23 07:05:28 +02:00
noun % = ARRAY_SIZE ( codename_noun ) ;
adjective % = ARRAY_SIZE ( codename_adjective ) ;
2018-02-22 11:00:33 +01:00
/* Only use 32 characters */
2018-09-29 08:34:01 +02:00
name = tal_fmt ( ld , " %s%s " ,
2018-02-22 11:00:33 +01:00
codename_adjective [ adjective ] ,
codename_noun [ noun ] ) ;
# if DEVELOPER
assert ( strlen ( name ) < 32 ) ;
2018-09-29 08:34:01 +02:00
int taillen = 31 - strlen ( name ) ;
2018-02-22 11:00:33 +01:00
if ( taillen > strlen ( version ( ) ) )
taillen = strlen ( version ( ) ) ;
/* Fit as much of end of version() as possible */
2018-09-29 08:34:01 +02:00
tal_append_fmt ( & name , " -%s " ,
2018-02-22 11:00:33 +01:00
version ( ) + strlen ( version ( ) ) - taillen ) ;
# endif
assert ( strlen ( name ) < = 32 ) ;
2017-11-24 14:43:31 +01:00
ld - > alias = tal_arrz ( ld , u8 , 33 ) ;
2018-02-22 11:00:33 +01:00
strcpy ( ( char * ) ld - > alias , name ) ;
tal_free ( name ) ;
2017-10-23 07:05:28 +02:00
}
}
2018-10-31 18:00:44 +01:00
void handle_early_opts ( struct lightningd * ld , int argc , char * argv [ ] )
2017-02-24 06:52:56 +01:00
{
2019-11-23 02:45:53 +01:00
/* Make ccan/opt use tal for allocations */
setup_option_allocators ( ) ;
/*~ List features immediately, before doing anything interesting */
opt_register_early_noarg ( " --list-features-only " ,
list_features_and_exit ,
ld , opt_hidden ) ;
/*~ This does enough parsing to get us the base configuration options */
initial_config_opts ( ld , argc , argv ,
& ld - > config_filename ,
2019-11-23 02:46:40 +01:00
& ld - > config_basedir ,
& ld - > config_netdir ,
2019-11-23 02:45:53 +01:00
& ld - > rpc_filename ) ;
/* Copy in default config, to be modified by further options */
if ( chainparams - > testnet )
ld - > config = testnet_config ;
else
ld - > config = mainnet_config ;
2019-07-25 08:37:58 +02:00
2019-11-23 02:45:53 +01:00
/* Now we can initialize wallet_dsn */
ld - > wallet_dsn = tal_fmt ( ld , " sqlite3://%s/lightningd.sqlite3 " ,
2019-11-23 02:46:40 +01:00
ld - > config_netdir ) ;
2019-11-23 02:45:53 +01:00
2019-11-23 02:46:58 +01:00
/* Set default PID file name to be per-network (in base dir) */
ld - > pidfile = path_join ( ld , ld - > config_basedir ,
tal_fmt ( tmpctx , " lightningd-%s.pid " ,
chainparams - > network_name ) ) ;
2019-07-25 08:37:58 +02:00
2019-08-03 07:10:41 +02:00
/*~ Move into config dir: this eases path manipulation and also
* gives plugins a good place to store their stuff . */
2019-11-23 02:46:40 +01:00
if ( chdir ( ld - > config_netdir ) ! = 0 ) {
2021-10-17 13:27:20 +02:00
log_info ( ld - > log , " Creating configuration directory %s " ,
2019-11-23 02:46:40 +01:00
ld - > config_netdir ) ;
/* We assume home dir exists, so only create two. */
if ( mkdir ( ld - > config_basedir , 0700 ) ! = 0 & & errno ! = EEXIST )
2019-08-03 07:10:41 +02:00
fatal ( " Could not make directory %s: %s " ,
2019-11-23 02:46:40 +01:00
ld - > config_basedir ,
strerror ( errno ) ) ;
if ( mkdir ( ld - > config_netdir , 0700 ) ! = 0 )
fatal ( " Could not make directory %s: %s " ,
ld - > config_netdir , strerror ( errno ) ) ;
if ( chdir ( ld - > config_netdir ) ! = 0 )
2019-08-03 07:10:41 +02:00
fatal ( " Could not change directory %s: %s " ,
2019-11-23 02:46:40 +01:00
ld - > config_netdir , strerror ( errno ) ) ;
2019-08-03 07:10:41 +02:00
}
2019-11-23 02:46:57 +01:00
/*~ We move files from old locations on first upgrade. */
promote_missing_files ( ld ) ;
2019-07-25 08:37:58 +02:00
/*~ The ccan/opt code requires registration then parsing; we
* mimic this API here , even though they ' re on separate lines . */
register_opts ( ld ) ;
2019-11-23 02:45:53 +01:00
/* Now look inside config file(s), but only handle the early
2019-07-25 08:37:58 +02:00
* options ( testnet , plugins etc ) , others may be added on - demand */
2019-11-23 02:46:40 +01:00
parse_config_files ( ld - > config_filename , ld - > config_basedir , true ) ;
2019-07-25 07:35:36 +02:00
2019-07-25 08:37:58 +02:00
/* Early cmdline options now override config file options. */
2018-10-31 18:00:44 +01:00
opt_early_parse_incomplete ( argc , argv , opt_log_stderr_exit ) ;
2019-09-09 09:23:11 +02:00
2019-11-18 01:27:17 +01:00
/* Finalize the logging subsystem now. */
logging_options_parsed ( ld - > log_book ) ;
2018-10-31 18:00:44 +01:00
}
2018-10-13 06:09:49 +02:00
2018-10-31 18:00:44 +01:00
void handle_opts ( struct lightningd * ld , int argc , char * argv [ ] )
{
2018-11-20 04:46:08 +01:00
/* Now look for config file, but only handle non-early
* options , early ones have been parsed in
* handle_early_opts */
2019-11-23 02:46:40 +01:00
parse_config_files ( ld - > config_filename , ld - > config_basedir , false ) ;
2018-11-20 04:46:08 +01:00
2019-07-25 08:37:58 +02:00
/* Now parse cmdline, which overrides config. */
2021-12-14 22:57:21 +01:00
opt_parse ( & argc , argv , opt_log_stderr_exitcode ) ;
2017-01-04 03:52:29 +01:00
if ( argc ! = 1 )
errx ( 1 , " no arguments accepted " ) ;
2021-08-18 12:52:21 +02:00
/* We keep a separate variable rather than overriding always_use_proxy,
2018-05-10 01:18:24 +02:00
* so listconfigs shows the correct thing . */
if ( tal_count ( ld - > proposed_wireaddr ) ! = 0
& & all_tor_addresses ( ld - > proposed_wireaddr ) ) {
ld - > pure_tor_setup = true ;
if ( ! ld - > proxyaddr )
log_info ( ld - > log , " Pure Tor setup with no --proxy: "
" you won't be able to make connections out " ) ;
}
2017-08-28 18:09:01 +02:00
check_config ( ld ) ;
2017-01-04 03:52:29 +01:00
}
2018-01-29 01:30:15 +01:00
/* FIXME: This is a hack! Expose somehow in ccan/opt.*/
/* Returns string after first '-'. */
static const char * first_name ( const char * names , unsigned * len )
{
* len = strcspn ( names + 1 , " |= " ) ;
return names + 1 ;
}
static const char * next_name ( const char * names , unsigned * len )
{
names + = * len ;
if ( names [ 0 ] = = ' ' | | names [ 0 ] = = ' = ' | | names [ 0 ] = = ' \0 ' )
return NULL ;
return first_name ( names + 1 , len ) ;
}
2018-10-19 03:17:49 +02:00
static void json_add_opt_addrs ( struct json_stream * response ,
2018-05-07 06:28:12 +02:00
const char * name0 ,
2018-05-07 06:29:21 +02:00
const struct wireaddr_internal * wireaddrs ,
2018-05-07 06:28:12 +02:00
const enum addr_listen_announce * listen_announce ,
enum addr_listen_announce ala )
{
for ( size_t i = 0 ; i < tal_count ( wireaddrs ) ; i + + ) {
if ( listen_announce [ i ] ! = ala )
continue ;
json_add_string ( response ,
name0 ,
2018-05-07 06:29:21 +02:00
fmt_wireaddr_internal ( name0 , wireaddrs + i ) ) ;
2018-05-07 06:28:12 +02:00
}
}
2022-06-26 06:25:01 +02:00
static void json_add_opt_log_to_files ( struct json_stream * response ,
const char * name0 ,
const char * * logfiles )
{
for ( size_t i = 0 ; i < tal_count ( logfiles ) ; i + + )
json_add_string ( response , name0 , logfiles [ i ] ) ;
}
2020-02-04 01:14:13 +01:00
struct json_add_opt_alt_subdaemon_args {
const char * name0 ;
struct json_stream * response ;
} ;
static bool json_add_opt_alt_subdaemon ( const char * member ,
const char * value ,
struct json_add_opt_alt_subdaemon_args * argp )
{
json_add_string ( argp - > response ,
argp - > name0 ,
tal_fmt ( argp - > name0 , " %s:%s " , member , value ) ) ;
return true ;
}
static void json_add_opt_subdaemons ( struct json_stream * response ,
const char * name0 ,
alt_subdaemon_map * alt_subdaemons )
{
struct json_add_opt_alt_subdaemon_args args ;
args . name0 = name0 ;
args . response = response ;
strmap_iterate ( alt_subdaemons , json_add_opt_alt_subdaemon , & args ) ;
}
2018-01-29 01:30:15 +01:00
static void add_config ( struct lightningd * ld ,
2018-10-19 03:17:49 +02:00
struct json_stream * response ,
2018-01-29 01:30:15 +01:00
const struct opt_table * opt ,
const char * name , size_t len )
{
lightningd: fix memleak false positive.
json_listconfigs() returns in the middle; the name0 is not always freed.
It will be freed later with the response, but our memleak detection doesn't
know that, and Travis caught it:
Global errors:
E - Node /tmp/ltests-5mfrzh5v/test_hsmtool_secret_decryption_1/lightning-1/ has memory leaks: [
E {
E "backtrace": [
E "ccan/ccan/tal/tal.c:437 (tal_alloc_)",
E "ccan/ccan/tal/tal.c:466 (tal_alloc_arr_)",
E "ccan/ccan/tal/tal.c:794 (tal_dup_)",
E "ccan/ccan/tal/str/str.c:32 (tal_strndup_)",
E "lightningd/options.c:1122 (add_config)",
E "lightningd/options.c:1282 (json_listconfigs)",
E "lightningd/jsonrpc.c:588 (command_exec)",
E "lightningd/jsonrpc.c:679 (rpc_command_hook_callback)",
E "lightningd/plugin_hook.c:123 (plugin_hook_call_)",
E "lightningd/jsonrpc.c:729 (plugin_hook_call_rpc_command)",
E "lightningd/jsonrpc.c:736 (call_rpc_command_hook)",
E "common/timeout.c:39 (timer_expired)",
E "lightningd/io_loop_with_timers.c:32 (io_loop_with_timers)",
E "lightningd/lightningd.c:871 (main)"
E ],
E "label": "lightningd/options.c:1122:char[]",
E "parents": [
E "lightningd/json_stream.c:49:struct json_stream",
E "ccan/ccan/io/io.c:91:struct io_conn",
E "lightningd/lightningd.c:104:struct lightningd"
E ],
E "value": "0x5569ada057a8"
E }
E ]
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
2020-01-28 04:53:07 +01:00
char * name0 = tal_strndup ( tmpctx , name , len ) ;
2018-01-29 01:30:15 +01:00
const char * answer = NULL ;
2019-12-02 04:04:23 +01:00
char buf [ OPT_SHOW_LEN + sizeof ( " ... " ) ] ;
2018-01-29 01:30:15 +01:00
2021-06-16 03:11:17 +02:00
# if DEVELOPER
if ( strstarts ( name0 , " dev- " ) ) {
/* Ignore dev settings */
return ;
}
# endif
2018-01-29 01:30:15 +01:00
if ( opt - > type & OPT_NOARG ) {
2019-08-29 03:01:55 +02:00
if ( opt - > desc = = opt_hidden ) {
/* Ignore hidden options (deprecated) */
} else if ( opt - > cb = = ( void * ) opt_usage_and_exit
2018-01-29 01:30:15 +01:00
| | opt - > cb = = ( void * ) version_and_exit
2019-11-23 02:46:58 +01:00
| | is_restricted_ignored ( opt - > cb )
2018-08-01 02:53:20 +02:00
| | opt - > cb = = ( void * ) opt_lightningd_usage
2018-12-04 04:04:14 +01:00
| | opt - > cb = = ( void * ) test_subdaemons_and_exit
/* FIXME: we can't recover this. */
| | opt - > cb = = ( void * ) opt_clear_plugins ) {
2018-01-29 01:30:15 +01:00
/* These are not important */
} else if ( opt - > cb = = ( void * ) opt_set_bool ) {
const bool * b = opt - > u . carg ;
2021-06-16 03:11:17 +02:00
json_add_bool ( response , name0 , * b ) ;
2018-05-07 05:44:40 +02:00
} else if ( opt - > cb = = ( void * ) opt_set_invbool ) {
const bool * b = opt - > u . carg ;
2021-06-16 03:11:17 +02:00
json_add_bool ( response , name0 , ! * b ) ;
2018-05-07 05:44:40 +02:00
} else if ( opt - > cb = = ( void * ) opt_set_offline ) {
2021-06-16 03:11:17 +02:00
json_add_bool ( response , name0 ,
! ld - > reconnect & & ! ld - > listen ) ;
2019-08-01 08:20:43 +02:00
} else if ( opt - > cb = = ( void * ) opt_start_daemon ) {
2021-06-16 03:11:17 +02:00
json_add_bool ( response , name0 ,
ld - > daemon_parent_fd ! = - 1 ) ;
2019-10-03 16:32:38 +02:00
} else if ( opt - > cb = = ( void * ) opt_set_hsm_password ) {
json_add_bool ( response , " encrypted-hsm " , ld - > encrypted_hsm ) ;
2020-04-03 02:03:58 +02:00
} else if ( opt - > cb = = ( void * ) opt_set_wumbo ) {
2020-09-08 07:20:15 +02:00
json_add_bool ( response , name0 ,
2020-04-03 02:03:59 +02:00
feature_offered ( ld - > our_features
- > bits [ INIT_FEATURE ] ,
2020-04-03 02:03:58 +02:00
OPT_LARGE_CHANNELS ) ) ;
2020-12-10 01:10:17 +01:00
} else if ( opt - > cb = = ( void * ) opt_set_dual_fund ) {
json_add_bool ( response , name0 ,
feature_offered ( ld - > our_features
- > bits [ INIT_FEATURE ] ,
OPT_DUAL_FUND ) ) ;
2021-01-13 04:00:20 +01:00
} else if ( opt - > cb = = ( void * ) opt_set_onion_messages ) {
json_add_bool ( response , name0 ,
feature_offered ( ld - > our_features
- > bits [ INIT_FEATURE ] ,
OPT_ONION_MESSAGES ) ) ;
2021-01-13 09:58:38 +01:00
} else if ( opt - > cb = = ( void * ) opt_set_offers ) {
json_add_bool ( response , name0 , ld - > config . exp_offers ) ;
2021-03-15 04:39:44 +01:00
} else if ( opt - > cb = = ( void * ) opt_set_shutdown_wrong_funding ) {
json_add_bool ( response , name0 ,
feature_offered ( ld - > our_features
- > bits [ INIT_FEATURE ] ,
OPT_SHUTDOWN_WRONG_FUNDING ) ) ;
2020-07-10 14:48:00 +02:00
} else if ( opt - > cb = = ( void * ) plugin_opt_flag_set ) {
/* Noop, they will get added below along with the
* OPT_HASARG options . */
2018-01-29 01:30:15 +01:00
} else {
/* Insert more decodes here! */
2018-08-01 02:53:20 +02:00
assert ( ! " A noarg option was added but was not handled " ) ;
2018-01-29 01:30:15 +01:00
}
} else if ( opt - > type & OPT_HASARG ) {
2018-05-17 06:46:22 +02:00
if ( opt - > desc = = opt_hidden ) {
/* Ignore hidden options (deprecated) */
} else if ( opt - > show ) {
2018-01-29 01:30:15 +01:00
opt - > show ( buf , opt - > u . carg ) ;
2022-05-02 17:02:03 +02:00
strcpy ( buf + OPT_SHOW_LEN - 1 , " ... " ) ;
2018-01-29 01:30:15 +01:00
if ( streq ( buf , " true " ) | | streq ( buf , " false " )
2022-07-08 11:56:11 +02:00
| | ( ! streq ( buf , " " ) & & strspn ( buf , " 0123456789. " ) = = strlen ( buf ) ) ) {
2018-01-29 01:30:15 +01:00
/* Let pure numbers and true/false through as
* literals . */
2022-07-04 05:52:35 +02:00
json_add_primitive ( response , name0 , buf ) ;
2018-01-29 01:30:15 +01:00
return ;
}
/* opt_show_charp surrounds with "", strip them */
if ( strstarts ( buf , " \" " ) ) {
2019-11-23 02:46:58 +01:00
char * end = strrchr ( buf , ' " ' ) ;
memmove ( end , end + 1 , strlen ( end ) ) ;
2018-01-29 01:30:15 +01:00
answer = buf + 1 ;
} else
answer = buf ;
} else if ( opt - > cb_arg = = ( void * ) opt_set_talstr
2019-07-25 08:37:58 +02:00
| | opt - > cb_arg = = ( void * ) opt_set_charp
2019-11-23 02:46:58 +01:00
| | is_restricted_print_if_nonnull ( opt - > cb_arg ) ) {
2018-01-29 01:30:15 +01:00
const char * arg = * ( char * * ) opt - > u . carg ;
if ( arg )
answer = tal_fmt ( name0 , " %s " , arg ) ;
} else if ( opt - > cb_arg = = ( void * ) opt_set_rgb ) {
if ( ld - > rgb )
answer = tal_hexstr ( name0 , ld - > rgb , 3 ) ;
} else if ( opt - > cb_arg = = ( void * ) opt_set_alias ) {
answer = ( const char * ) ld - > alias ;
} else if ( opt - > cb_arg = = ( void * ) arg_log_to_file ) {
2022-06-26 06:25:01 +02:00
if ( ld - > logfiles )
json_add_opt_log_to_files ( response , name0 , ld - > logfiles ) ;
2018-05-07 05:53:21 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_add_addr ) {
2018-05-07 06:28:12 +02:00
json_add_opt_addrs ( response , name0 ,
2018-05-07 06:29:22 +02:00
ld - > proposed_wireaddr ,
ld - > proposed_listen_announce ,
2018-05-07 06:28:12 +02:00
ADDR_LISTEN_AND_ANNOUNCE ) ;
return ;
} else if ( opt - > cb_arg = = ( void * ) opt_add_bind_addr ) {
json_add_opt_addrs ( response , name0 ,
2018-05-07 06:29:22 +02:00
ld - > proposed_wireaddr ,
ld - > proposed_listen_announce ,
2018-05-07 06:28:12 +02:00
ADDR_LISTEN ) ;
return ;
} else if ( opt - > cb_arg = = ( void * ) opt_add_announce_addr ) {
json_add_opt_addrs ( response , name0 ,
2018-05-07 06:29:22 +02:00
ld - > proposed_wireaddr ,
ld - > proposed_listen_announce ,
2018-05-07 06:28:12 +02:00
ADDR_ANNOUNCE ) ;
2018-01-29 01:30:15 +01:00
return ;
2020-02-04 01:14:13 +01:00
} else if ( opt - > cb_arg = = ( void * ) opt_subdaemon ) {
json_add_opt_subdaemons ( response , name0 ,
& ld - > alt_subdaemons ) ;
return ;
2018-05-10 01:18:24 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_add_proxy_addr ) {
if ( ld - > proxyaddr )
answer = fmt_wireaddr ( name0 , ld - > proxyaddr ) ;
2018-09-20 13:46:50 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_add_plugin ) {
2018-09-20 20:43:55 +02:00
json_add_opt_plugins ( response , ld - > plugins ) ;
2019-11-18 01:27:17 +01:00
} else if ( opt - > cb_arg = = ( void * ) opt_log_level ) {
json_add_opt_log_levels ( response , ld - > log ) ;
2020-05-05 03:15:34 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_disable_plugin ) {
json_add_opt_disable_plugins ( response , ld - > plugins ) ;
2021-07-08 04:47:03 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_force_feerates ) {
answer = fmt_force_feerates ( name0 , ld - > force_feerates ) ;
2021-10-18 02:13:33 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_set_websocket_port ) {
if ( ld - > websocket_port )
json_add_u32 ( response , name0 ,
ld - > websocket_port ) ;
return ;
2020-07-29 13:24:07 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_important_plugin ) {
/* Do nothing, this is already handled by
* opt_add_plugin . */
2018-12-04 04:04:14 +01:00
} else if ( opt - > cb_arg = = ( void * ) opt_add_plugin_dir
2020-03-17 02:34:35 +01:00
| | opt - > cb_arg = = ( void * ) plugin_opt_set
| | opt - > cb_arg = = ( void * ) plugin_opt_flag_set ) {
2018-12-03 10:26:29 +01:00
/* FIXME: We actually treat it as if they specified
2018-12-04 04:04:14 +01:00
* - - plugin for each one , so ignore these */
2021-09-28 21:03:08 +02:00
} else if ( opt - > cb_arg = = ( void * ) opt_set_msat ) {
2022-06-20 12:22:09 +02:00
/* We allow -msat not _msat here, unlike
* json_add_amount_msat_only */
assert ( strends ( name0 , " -msat " ) ) ;
json_add_string ( response , name0 ,
fmt_amount_msat ( tmpctx ,
* ( struct amount_msat * )
opt - > u . carg ) ) ;
2021-06-17 11:52:50 +02:00
# if EXPERIMENTAL_FEATURES
} else if ( opt - > cb_arg = = ( void * ) opt_set_accept_extra_tlv_types ) {
/* TODO Actually print the option */
2021-06-17 11:52:50 +02:00
# endif
# if DEVELOPER
} else if ( strstarts ( name , " dev- " ) ) {
/* Ignore dev settings */
# endif
2018-01-29 01:30:15 +01:00
} else {
/* Insert more decodes here! */
abort ( ) ;
}
}
2018-03-26 02:08:15 +02:00
if ( answer ) {
2019-06-12 02:38:54 +02:00
struct json_escape * esc = json_escape ( NULL , answer ) ;
2018-03-26 02:08:15 +02:00
json_add_escaped_string ( response , name0 , take ( esc ) ) ;
}
2018-01-29 01:30:15 +01:00
}
2018-12-16 05:52:06 +01:00
static struct command_result * json_listconfigs ( struct command * cmd ,
const char * buffer ,
const jsmntok_t * obj UNNEEDED ,
const jsmntok_t * params )
2018-01-29 01:30:15 +01:00
{
size_t i ;
2018-10-19 03:17:49 +02:00
struct json_stream * response = NULL ;
2022-07-04 03:26:36 +02:00
const char * configname ;
2018-01-29 01:30:15 +01:00
2018-07-20 03:14:02 +02:00
if ( ! param ( cmd , buffer , params ,
2022-07-04 03:26:36 +02:00
p_opt ( " config " , param_string , & configname ) ,
2018-07-20 03:14:02 +02:00
NULL ) )
2018-12-16 05:52:06 +01:00
return command_param_failed ( ) ;
2018-01-29 01:30:15 +01:00
2022-07-04 03:26:36 +02:00
if ( ! configname ) {
2018-10-19 03:17:48 +02:00
response = json_stream_success ( cmd ) ;
2018-01-29 01:30:15 +01:00
json_add_string ( response , " # version " , version ( ) ) ;
2018-10-19 03:17:48 +02:00
}
2018-01-29 01:30:15 +01:00
for ( i = 0 ; i < opt_count ; i + + ) {
unsigned int len ;
const char * name ;
/* FIXME: Print out comment somehow? */
if ( opt_table [ i ] . type = = OPT_SUBTABLE )
continue ;
for ( name = first_name ( opt_table [ i ] . names , & len ) ;
name ;
name = next_name ( name , & len ) ) {
/* Skips over first -, so just need to look for one */
if ( name [ 0 ] ! = ' - ' )
continue ;
2022-07-04 03:26:36 +02:00
if ( configname
& & ! memeq ( configname , strlen ( configname ) ,
2018-01-29 01:30:15 +01:00
name + 1 , len - 1 ) )
continue ;
2019-06-12 02:38:54 +02:00
if ( ! response )
2018-10-19 03:17:48 +02:00
response = json_stream_success ( cmd ) ;
2018-01-29 01:30:15 +01:00
add_config ( cmd - > ld , response , & opt_table [ i ] ,
name + 1 , len - 1 ) ;
2020-09-08 07:20:15 +02:00
/* If we have more than one long name, first
* is preferred */
break ;
2018-01-29 01:30:15 +01:00
}
}
2022-07-04 03:26:36 +02:00
if ( configname & & ! response ) {
2018-12-16 05:52:06 +01:00
return command_fail ( cmd , JSONRPC2_INVALID_PARAMS ,
2022-07-04 03:26:36 +02:00
" Unknown config option %s " ,
configname ) ;
2018-01-29 01:30:15 +01:00
}
2018-12-16 05:52:06 +01:00
return command_success ( cmd , response ) ;
2018-01-29 01:30:15 +01:00
}
static const struct json_command listconfigs_command = {
" listconfigs " ,
2019-05-22 16:08:16 +02:00
" utility " ,
2018-01-29 01:30:15 +01:00
json_listconfigs ,
" List all configuration options, or with [config], just that one. " ,
. verbose = " listconfigs [config] \n "
" Outputs an object, with each field a config options \n "
" (Option names which start with # are comments) \n "
" With [config], object only has that field "
} ;
AUTODATA ( json_command , & listconfigs_command ) ;