mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
Add DEVELOPER flag, set by default.
This is a bit messier than I'd like, but we want to clearly remove all dev code (not just have it uncalled), so we remove fields and functions altogether rather than stub them out. This means we put #ifdefs in callers in some places, but at least it's explicit. We still run tests, but only a subset, and we run with NO_VALGRIND under Travis to avoid increasing test times too much. See-also: #176 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
8d9818ff9c
commit
3c6eec87e3
11
.travis.yml
11
.travis.yml
@ -3,13 +3,14 @@ dist: trusty
|
|||||||
sudo: true
|
sudo: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- NO_VALGRIND=1 ARCH=32
|
- NO_VALGRIND=1 ARCH=32 DEVELOPER=1
|
||||||
- NO_VALGRIND=1 ARCH=64
|
- NO_VALGRIND=1 ARCH=64 DEVELOPER=1
|
||||||
- NO_VALGRIND=0 ARCH=64
|
- NO_VALGRIND=0 ARCH=64 DEVELOPER=1
|
||||||
|
- NO_VALGRIND=0 ARCH=64 DEVELOPER=0
|
||||||
|
|
||||||
# Trusty (aka 14.04) is way way too old, so run in docker...
|
# Trusty (aka 14.04) is way way too old, so run in docker...
|
||||||
script:
|
script:
|
||||||
- docker pull cdecker/lightning-ci:${ARCH}bit > /dev/null
|
- docker pull cdecker/lightning-ci:${ARCH}bit > /dev/null
|
||||||
- docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make -j3
|
- docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make -j3 DEVELOPER=${DEVELOPER}
|
||||||
- docker run --rm=true -e NO_VALGRIND=${NO_VALGRIND:-0} -e TEST_DEBUG=${TEST_DEBUG:-0} -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make check
|
- docker run --rm=true -e NO_VALGRIND=${NO_VALGRIND:-0} -e TEST_DEBUG=${TEST_DEBUG:-0} -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make check DEVELOPER=${DEVELOPER}
|
||||||
- docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make check-source
|
- docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci:${ARCH}bit make check-source
|
||||||
|
11
Makefile
11
Makefile
@ -16,6 +16,15 @@ VALGRIND=valgrind -q --error-exitcode=7
|
|||||||
VALGRIND_TEST_ARGS = --track-origins=yes --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all
|
VALGRIND_TEST_ARGS = --track-origins=yes --leak-check=full --show-reachable=yes --errors-for-leak-kinds=all
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# By default, we are in DEVELOPER mode, use DEVELOPER= on cmdline to override.
|
||||||
|
DEVELOPER := 1
|
||||||
|
|
||||||
|
ifeq ($(DEVELOPER),1)
|
||||||
|
DEV_CFLAGS=-DDEVELOPER=1
|
||||||
|
else
|
||||||
|
DEV_CFLAGS=-DDEVELOPER=0
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(COVERAGE),1)
|
ifeq ($(COVERAGE),1)
|
||||||
COVFLAGS = --coverage
|
COVFLAGS = --coverage
|
||||||
endif
|
endif
|
||||||
@ -132,7 +141,7 @@ ALL_PROGRAMS =
|
|||||||
|
|
||||||
CWARNFLAGS := -Werror -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition
|
CWARNFLAGS := -Werror -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition
|
||||||
CDEBUGFLAGS := -std=gnu11 -g -fstack-protector
|
CDEBUGFLAGS := -std=gnu11 -g -fstack-protector
|
||||||
CFLAGS = $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . $(FEATURES) $(COVFLAGS) -DSHACHAIN_BITS=48 -DCCAN_TAKE_DEBUG=1
|
CFLAGS = $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) $(EXTERNAL_INCLUDE_FLAGS) -I . $(FEATURES) $(COVFLAGS) $(DEV_CFLAGS) -DSHACHAIN_BITS=48 -DCCAN_TAKE_DEBUG=1
|
||||||
|
|
||||||
LDLIBS = -lgmp -lsqlite3 $(COVFLAGS)
|
LDLIBS = -lgmp -lsqlite3 $(COVFLAGS)
|
||||||
|
|
||||||
|
@ -615,12 +615,14 @@ static void send_commit(struct peer *peer)
|
|||||||
u8 *msg;
|
u8 *msg;
|
||||||
const struct htlc **changed_htlcs;
|
const struct htlc **changed_htlcs;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
/* Hack to suppress all commit sends if dev_disconnect says to */
|
/* Hack to suppress all commit sends if dev_disconnect says to */
|
||||||
if (dev_suppress_commit) {
|
if (dev_suppress_commit) {
|
||||||
peer->commit_timer = NULL;
|
peer->commit_timer = NULL;
|
||||||
tal_free(tmpctx);
|
tal_free(tmpctx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FIXME: Document this requirement in BOLT 2! */
|
/* FIXME: Document this requirement in BOLT 2! */
|
||||||
/* We can't send two commits in a row. */
|
/* We can't send two commits in a row. */
|
||||||
@ -1910,6 +1912,7 @@ static void handle_shutdown_cmd(struct peer *peer, const u8 *inmsg)
|
|||||||
start_commit_timer(peer);
|
start_commit_timer(peer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
static void handle_dev_reenable_commit(struct peer *peer)
|
static void handle_dev_reenable_commit(struct peer *peer)
|
||||||
{
|
{
|
||||||
dev_suppress_commit = false;
|
dev_suppress_commit = false;
|
||||||
@ -1918,6 +1921,7 @@ static void handle_dev_reenable_commit(struct peer *peer)
|
|||||||
wire_sync_write(MASTER_FD,
|
wire_sync_write(MASTER_FD,
|
||||||
take(towire_channel_dev_reenable_commit_reply(peer)));
|
take(towire_channel_dev_reenable_commit_reply(peer)));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void req_in(struct peer *peer, const u8 *msg)
|
static void req_in(struct peer *peer, const u8 *msg)
|
||||||
{
|
{
|
||||||
@ -1946,8 +1950,10 @@ static void req_in(struct peer *peer, const u8 *msg)
|
|||||||
handle_shutdown_cmd(peer, msg);
|
handle_shutdown_cmd(peer, msg);
|
||||||
goto out;
|
goto out;
|
||||||
case WIRE_CHANNEL_DEV_REENABLE_COMMIT:
|
case WIRE_CHANNEL_DEV_REENABLE_COMMIT:
|
||||||
|
#if DEVELOPER
|
||||||
handle_dev_reenable_commit(peer);
|
handle_dev_reenable_commit(peer);
|
||||||
goto out;
|
goto out;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
case WIRE_CHANNEL_NORMAL_OPERATION:
|
case WIRE_CHANNEL_NORMAL_OPERATION:
|
||||||
case WIRE_CHANNEL_INIT:
|
case WIRE_CHANNEL_INIT:
|
||||||
case WIRE_CHANNEL_OFFER_HTLC_REPLY:
|
case WIRE_CHANNEL_OFFER_HTLC_REPLY:
|
||||||
|
@ -11,11 +11,14 @@
|
|||||||
|
|
||||||
bool sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES)
|
bool sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES)
|
||||||
{
|
{
|
||||||
|
#if DEVELOPER
|
||||||
|
bool post_sabotage = false;
|
||||||
int type = fromwire_peektype(msg);
|
int type = fromwire_peektype(msg);
|
||||||
|
#endif
|
||||||
u8 *enc = cryptomsg_encrypt_msg(NULL, cs, msg);
|
u8 *enc = cryptomsg_encrypt_msg(NULL, cs, msg);
|
||||||
bool ret;
|
bool ret;
|
||||||
bool post_sabotage = false;
|
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
switch (dev_disconnect(type)) {
|
switch (dev_disconnect(type)) {
|
||||||
case DEV_DISCONNECT_BEFORE:
|
case DEV_DISCONNECT_BEFORE:
|
||||||
dev_sabotage_fd(fd);
|
dev_sabotage_fd(fd);
|
||||||
@ -31,11 +34,14 @@ bool sync_crypto_write(struct crypto_state *cs, int fd, const void *msg TAKES)
|
|||||||
case DEV_DISCONNECT_NORMAL:
|
case DEV_DISCONNECT_NORMAL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
ret = write_all(fd, enc, tal_len(enc));
|
ret = write_all(fd, enc, tal_len(enc));
|
||||||
tal_free(enc);
|
tal_free(enc);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (post_sabotage)
|
if (post_sabotage)
|
||||||
dev_sabotage_fd(fd);
|
dev_sabotage_fd(fd);
|
||||||
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,6 +326,7 @@ u8 *cryptomsg_encrypt_msg(const tal_t *ctx,
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
static struct io_plan *peer_write_postclose(struct io_conn *conn,
|
static struct io_plan *peer_write_postclose(struct io_conn *conn,
|
||||||
struct peer_crypto_state *pcs)
|
struct peer_crypto_state *pcs)
|
||||||
{
|
{
|
||||||
@ -333,6 +334,7 @@ static struct io_plan *peer_write_postclose(struct io_conn *conn,
|
|||||||
dev_sabotage_fd(io_conn_fd(conn));
|
dev_sabotage_fd(io_conn_fd(conn));
|
||||||
return pcs->next_out(conn, pcs->peer);
|
return pcs->next_out(conn, pcs->peer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct io_plan *peer_write_message(struct io_conn *conn,
|
struct io_plan *peer_write_message(struct io_conn *conn,
|
||||||
struct peer_crypto_state *pcs,
|
struct peer_crypto_state *pcs,
|
||||||
@ -341,7 +343,10 @@ struct io_plan *peer_write_message(struct io_conn *conn,
|
|||||||
struct peer *))
|
struct peer *))
|
||||||
{
|
{
|
||||||
struct io_plan *(*post)(struct io_conn *, struct peer_crypto_state *);
|
struct io_plan *(*post)(struct io_conn *, struct peer_crypto_state *);
|
||||||
|
#if DEVELOPER
|
||||||
int type = fromwire_peektype(msg);
|
int type = fromwire_peektype(msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
assert(!pcs->out);
|
assert(!pcs->out);
|
||||||
|
|
||||||
pcs->out = cryptomsg_encrypt_msg(conn, &pcs->cs, msg);
|
pcs->out = cryptomsg_encrypt_msg(conn, &pcs->cs, msg);
|
||||||
@ -349,6 +354,7 @@ struct io_plan *peer_write_message(struct io_conn *conn,
|
|||||||
|
|
||||||
post = peer_write_done;
|
post = peer_write_done;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
switch (dev_disconnect(type)) {
|
switch (dev_disconnect(type)) {
|
||||||
case DEV_DISCONNECT_BEFORE:
|
case DEV_DISCONNECT_BEFORE:
|
||||||
dev_sabotage_fd(io_conn_fd(conn));
|
dev_sabotage_fd(io_conn_fd(conn));
|
||||||
@ -364,6 +370,7 @@ struct io_plan *peer_write_message(struct io_conn *conn,
|
|||||||
case DEV_DISCONNECT_NORMAL:
|
case DEV_DISCONNECT_NORMAL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
/* BOLT #8:
|
/* BOLT #8:
|
||||||
* * Send `lc || c` over the network buffer.
|
* * Send `lc || c` over the network buffer.
|
||||||
|
@ -50,13 +50,16 @@ static void crashlog_activate(void)
|
|||||||
|
|
||||||
void subdaemon_debug(int argc, char *argv[])
|
void subdaemon_debug(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#if DEVELOPER
|
||||||
int i;
|
int i;
|
||||||
bool printed = false;
|
bool printed = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
err_set_progname(argv[0]);
|
err_set_progname(argv[0]);
|
||||||
backtrace_state = backtrace_create_state(argv[0], 0, NULL, NULL);
|
backtrace_state = backtrace_create_state(argv[0], 0, NULL, NULL);
|
||||||
crashlog_activate();
|
crashlog_activate();
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
for (i = 1; i < argc; i++) {
|
for (i = 1; i < argc; i++) {
|
||||||
if (strstarts(argv[i], "--dev-disconnect=")) {
|
if (strstarts(argv[i], "--dev-disconnect=")) {
|
||||||
dev_disconnect_init(atoi(argv[i]
|
dev_disconnect_init(atoi(argv[i]
|
||||||
@ -73,4 +76,5 @@ void subdaemon_debug(int argc, char *argv[])
|
|||||||
printed = true;
|
printed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wire/gen_peer_wire.h>
|
#include <wire/gen_peer_wire.h>
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
/* We move the fd IFF we do a disconnect. */
|
/* We move the fd IFF we do a disconnect. */
|
||||||
static int dev_disconnect_fd = -1;
|
static int dev_disconnect_fd = -1;
|
||||||
static char dev_disconnect_line[200];
|
static char dev_disconnect_line[200];
|
||||||
@ -132,3 +133,4 @@ void dev_blackhole_fd(int fd)
|
|||||||
dup2(fds[1], fd);
|
dup2(fds[1], fd);
|
||||||
close(fds[1]);
|
close(fds[1]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
enum dev_disconnect {
|
enum dev_disconnect {
|
||||||
/* Do nothing. */
|
/* Do nothing. */
|
||||||
DEV_DISCONNECT_NORMAL = '=',
|
DEV_DISCONNECT_NORMAL = '=',
|
||||||
@ -30,5 +31,6 @@ void dev_disconnect_init(int fd);
|
|||||||
|
|
||||||
/* Hack for channeld to do DEV_DISCONNECT_SUPPRESS_COMMIT. */
|
/* Hack for channeld to do DEV_DISCONNECT_SUPPRESS_COMMIT. */
|
||||||
extern bool dev_suppress_commit;
|
extern bool dev_suppress_commit;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
#endif /* LIGHTNING_COMMON_DEV_DISCONNECT_H */
|
#endif /* LIGHTNING_COMMON_DEV_DISCONNECT_H */
|
||||||
|
@ -188,8 +188,10 @@ static void rebroadcast_txs(struct chain_topology *topo, struct command *cmd)
|
|||||||
struct txs_to_broadcast *txs;
|
struct txs_to_broadcast *txs;
|
||||||
struct outgoing_tx *otx;
|
struct outgoing_tx *otx;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (topo->dev_no_broadcast)
|
if (topo->dev_no_broadcast)
|
||||||
return;
|
return;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
txs = tal(topo, struct txs_to_broadcast);
|
txs = tal(topo, struct txs_to_broadcast);
|
||||||
txs->cmd = cmd;
|
txs->cmd = cmd;
|
||||||
@ -263,11 +265,13 @@ void broadcast_tx(struct chain_topology *topo,
|
|||||||
log_add(topo->log, " (tx %s)",
|
log_add(topo->log, " (tx %s)",
|
||||||
type_to_string(ltmp, struct sha256_double, &otx->txid));
|
type_to_string(ltmp, struct sha256_double, &otx->txid));
|
||||||
|
|
||||||
if (topo->dev_no_broadcast)
|
#if DEVELOPER
|
||||||
|
if (topo->dev_no_broadcast) {
|
||||||
broadcast_done(topo->bitcoind, 0, "dev_no_broadcast", otx);
|
broadcast_done(topo->bitcoind, 0, "dev_no_broadcast", otx);
|
||||||
else
|
return;
|
||||||
bitcoind_sendrawtx(topo->bitcoind, otx->hextx,
|
}
|
||||||
broadcast_done, otx);
|
#endif
|
||||||
|
bitcoind_sendrawtx(topo->bitcoind, otx->hextx, broadcast_done, otx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_blocks(struct chain_topology *topo, struct block *b)
|
static void free_blocks(struct chain_topology *topo, struct block *b)
|
||||||
@ -484,6 +488,7 @@ struct txlocator *locate_tx(const void *ctx, const struct chain_topology *topo,
|
|||||||
return tal_free(loc);
|
return tal_free(loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
void json_dev_broadcast(struct command *cmd,
|
void json_dev_broadcast(struct command *cmd,
|
||||||
struct chain_topology *topo,
|
struct chain_topology *topo,
|
||||||
const char *buffer, const jsmntok_t *params)
|
const char *buffer, const jsmntok_t *params)
|
||||||
@ -534,6 +539,7 @@ static const struct json_command dev_blockheight = {
|
|||||||
"Returns { blockheight: u32 } on success"
|
"Returns { blockheight: u32 } on success"
|
||||||
};
|
};
|
||||||
AUTODATA(json_command, &dev_blockheight);
|
AUTODATA(json_command, &dev_blockheight);
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
/* On shutdown, peers get deleted last. That frees from our list, so
|
/* On shutdown, peers get deleted last. That frees from our list, so
|
||||||
* do it now instead. */
|
* do it now instead. */
|
||||||
@ -556,8 +562,10 @@ struct chain_topology *new_topology(const tal_t *ctx, struct log *log)
|
|||||||
topo->log = log;
|
topo->log = log;
|
||||||
topo->default_fee_rate = 40000;
|
topo->default_fee_rate = 40000;
|
||||||
topo->override_fee_rate = 0;
|
topo->override_fee_rate = 0;
|
||||||
topo->dev_no_broadcast = false;
|
|
||||||
topo->bitcoind = new_bitcoind(topo, log);
|
topo->bitcoind = new_bitcoind(topo, log);
|
||||||
|
#if DEVELOPER
|
||||||
|
topo->dev_no_broadcast = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
return topo;
|
return topo;
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,10 @@ struct chain_topology {
|
|||||||
struct txwatch_hash txwatches;
|
struct txwatch_hash txwatches;
|
||||||
struct txowatch_hash txowatches;
|
struct txowatch_hash txowatches;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
/* Suppress broadcast (for testing) */
|
/* Suppress broadcast (for testing) */
|
||||||
bool dev_no_broadcast;
|
bool dev_no_broadcast;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Information relevant to locating a TX in a blockchain. */
|
/* Information relevant to locating a TX in a blockchain. */
|
||||||
@ -156,8 +158,9 @@ struct txlocator *locate_tx(const void *ctx, const struct chain_topology *topo,
|
|||||||
|
|
||||||
void notify_new_block(struct chain_topology *topo, unsigned int height);
|
void notify_new_block(struct chain_topology *topo, unsigned int height);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
void json_dev_broadcast(struct command *cmd,
|
void json_dev_broadcast(struct command *cmd,
|
||||||
struct chain_topology *topo,
|
struct chain_topology *topo,
|
||||||
const char *buffer, const jsmntok_t *params);
|
const char *buffer, const jsmntok_t *params);
|
||||||
|
#endif
|
||||||
#endif /* LIGHTNING_LIGHTNINGD_CHAINTOPOLOGY_H */
|
#endif /* LIGHTNING_LIGHTNINGD_CHAINTOPOLOGY_H */
|
||||||
|
@ -186,6 +186,7 @@ static const struct json_command getlog_command = {
|
|||||||
};
|
};
|
||||||
AUTODATA(json_command, &getlog_command);
|
AUTODATA(json_command, &getlog_command);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
static void json_rhash(struct command *cmd,
|
static void json_rhash(struct command *cmd,
|
||||||
const char *buffer, const jsmntok_t *params)
|
const char *buffer, const jsmntok_t *params)
|
||||||
{
|
{
|
||||||
@ -238,6 +239,7 @@ static const struct json_command dev_crash_command = {
|
|||||||
"Simple crash test for developers"
|
"Simple crash test for developers"
|
||||||
};
|
};
|
||||||
AUTODATA(json_command, &dev_crash_command);
|
AUTODATA(json_command, &dev_crash_command);
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
static void json_getinfo(struct command *cmd,
|
static void json_getinfo(struct command *cmd,
|
||||||
const char *buffer, const jsmntok_t *params)
|
const char *buffer, const jsmntok_t *params)
|
||||||
|
@ -71,11 +71,8 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
|
|||||||
struct lightningd *ld = tal(ctx, struct lightningd);
|
struct lightningd *ld = tal(ctx, struct lightningd);
|
||||||
|
|
||||||
list_head_init(&ld->peers);
|
list_head_init(&ld->peers);
|
||||||
ld->dev_debug_subdaemon = NULL;
|
|
||||||
htlc_in_map_init(&ld->htlcs_in);
|
htlc_in_map_init(&ld->htlcs_in);
|
||||||
htlc_out_map_init(&ld->htlcs_out);
|
htlc_out_map_init(&ld->htlcs_out);
|
||||||
ld->dev_disconnect_fd = -1;
|
|
||||||
ld->dev_hsm_seed = NULL;
|
|
||||||
ld->log_book = log_book;
|
ld->log_book = log_book;
|
||||||
ld->log = new_log(log_book, log_book, "lightningd(%u):", (int)getpid());
|
ld->log = new_log(log_book, log_book, "lightningd(%u):", (int)getpid());
|
||||||
ld->alias = NULL;
|
ld->alias = NULL;
|
||||||
@ -88,6 +85,13 @@ static struct lightningd *new_lightningd(const tal_t *ctx,
|
|||||||
|
|
||||||
/* FIXME: Move into invoice daemon. */
|
/* FIXME: Move into invoice daemon. */
|
||||||
ld->invoices = invoices_init(ld);
|
ld->invoices = invoices_init(ld);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
|
ld->dev_debug_subdaemon = NULL;
|
||||||
|
ld->dev_disconnect_fd = -1;
|
||||||
|
ld->dev_hsm_seed = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
return ld;
|
return ld;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,18 +114,6 @@ struct lightningd {
|
|||||||
/* Our chain topology. */
|
/* Our chain topology. */
|
||||||
struct chain_topology *topology;
|
struct chain_topology *topology;
|
||||||
|
|
||||||
/* If we want to debug a subdaemon. */
|
|
||||||
const char *dev_debug_subdaemon;
|
|
||||||
|
|
||||||
/* If we want to set a specific non-random HSM seed. */
|
|
||||||
const u8 *dev_hsm_seed;
|
|
||||||
|
|
||||||
/* If we have a --dev-disconnect file */
|
|
||||||
int dev_disconnect_fd;
|
|
||||||
|
|
||||||
/* If we have --dev-fail-on-subdaemon-fail */
|
|
||||||
bool dev_subdaemon_fail;
|
|
||||||
|
|
||||||
/* HTLCs in flight. */
|
/* HTLCs in flight. */
|
||||||
struct htlc_in_map htlcs_in;
|
struct htlc_in_map htlcs_in;
|
||||||
struct htlc_out_map htlcs_out;
|
struct htlc_out_map htlcs_out;
|
||||||
@ -139,6 +127,20 @@ struct lightningd {
|
|||||||
|
|
||||||
/* Any outstanding "pay" commands. */
|
/* Any outstanding "pay" commands. */
|
||||||
struct list_head pay_commands;
|
struct list_head pay_commands;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
|
/* If we want to debug a subdaemon. */
|
||||||
|
const char *dev_debug_subdaemon;
|
||||||
|
|
||||||
|
/* If we want to set a specific non-random HSM seed. */
|
||||||
|
const u8 *dev_hsm_seed;
|
||||||
|
|
||||||
|
/* If we have a --dev-disconnect file */
|
||||||
|
int dev_disconnect_fd;
|
||||||
|
|
||||||
|
/* If we have --dev-fail-on-subdaemon-fail */
|
||||||
|
bool dev_subdaemon_fail;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -285,6 +285,7 @@ static void config_register_opts(struct lightningd *ld)
|
|||||||
" regtest, or litecoin)");
|
" regtest, or litecoin)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
static char *opt_set_hsm_seed(const char *arg, struct lightningd *ld)
|
static char *opt_set_hsm_seed(const char *arg, struct lightningd *ld)
|
||||||
{
|
{
|
||||||
ld->dev_hsm_seed = tal_hexdata(ld, arg, strlen(arg));
|
ld->dev_hsm_seed = tal_hexdata(ld, arg, strlen(arg));
|
||||||
@ -310,6 +311,7 @@ static void dev_register_opts(struct lightningd *ld)
|
|||||||
opt_register_arg("--dev-hsm-seed=<seed>", opt_set_hsm_seed,
|
opt_register_arg("--dev-hsm-seed=<seed>", opt_set_hsm_seed,
|
||||||
NULL, ld, "Hex-encoded seed for HSM");
|
NULL, ld, "Hex-encoded seed for HSM");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct config testnet_config = {
|
static const struct config testnet_config = {
|
||||||
/* 6 blocks to catch cheating attempts. */
|
/* 6 blocks to catch cheating attempts. */
|
||||||
@ -560,7 +562,9 @@ void register_opts(struct lightningd *ld)
|
|||||||
|
|
||||||
configdir_register_opts(ld, &ld->config_dir, &ld->rpc_filename);
|
configdir_register_opts(ld, &ld->config_dir, &ld->rpc_filename);
|
||||||
config_register_opts(ld);
|
config_register_opts(ld);
|
||||||
|
#if DEVELOPER
|
||||||
dev_register_opts(ld);
|
dev_register_opts(ld);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Names stolen from https://github.com/ternus/nsaproductgenerator/blob/master/nsa.js */
|
/* Names stolen from https://github.com/ternus/nsaproductgenerator/blob/master/nsa.js */
|
||||||
@ -634,6 +638,7 @@ bool handle_opts(struct lightningd *ld, int argc, char *argv[])
|
|||||||
|
|
||||||
check_config(ld);
|
check_config(ld);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (ld->dev_hsm_seed) {
|
if (ld->dev_hsm_seed) {
|
||||||
int fd;
|
int fd;
|
||||||
unlink("hsm_secret");
|
unlink("hsm_secret");
|
||||||
@ -645,6 +650,7 @@ bool handle_opts(struct lightningd *ld, int argc, char *argv[])
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return newdir;
|
return newdir;
|
||||||
}
|
}
|
||||||
|
@ -204,10 +204,12 @@ void peer_fail_transient(struct peer *peer, const char *fmt, ...)
|
|||||||
logv_add(peer->log, fmt, ap);
|
logv_add(peer->log, fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (dev_disconnect_permanent(peer->ld)) {
|
if (dev_disconnect_permanent(peer->ld)) {
|
||||||
peer_internal_error(peer, "dev_disconnect permfail");
|
peer_internal_error(peer, "dev_disconnect permfail");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
peer_set_owner(peer, NULL);
|
peer_set_owner(peer, NULL);
|
||||||
|
|
||||||
@ -759,88 +761,6 @@ static const struct json_command connect_command = {
|
|||||||
};
|
};
|
||||||
AUTODATA(json_command, &connect_command);
|
AUTODATA(json_command, &connect_command);
|
||||||
|
|
||||||
static void json_dev_fail(struct command *cmd,
|
|
||||||
const char *buffer, const jsmntok_t *params)
|
|
||||||
{
|
|
||||||
jsmntok_t *peertok;
|
|
||||||
struct peer *peer;
|
|
||||||
|
|
||||||
if (!json_get_params(buffer, params,
|
|
||||||
"id", &peertok,
|
|
||||||
NULL)) {
|
|
||||||
command_fail(cmd, "Need id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer = peer_from_json(cmd->ld, buffer, peertok);
|
|
||||||
if (!peer) {
|
|
||||||
command_fail(cmd, "Could not find peer with that id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer_internal_error(peer, "Failing due to dev-fail command");
|
|
||||||
command_success(cmd, null_response(cmd));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct json_command dev_fail_command = {
|
|
||||||
"dev-fail",
|
|
||||||
json_dev_fail,
|
|
||||||
"Fail with peer {id}",
|
|
||||||
"Returns {} on success"
|
|
||||||
};
|
|
||||||
AUTODATA(json_command, &dev_fail_command);
|
|
||||||
|
|
||||||
static void dev_reenable_commit_finished(struct subd *channeld,
|
|
||||||
const u8 *resp,
|
|
||||||
const int *fds,
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!json_get_params(buffer, params,
|
|
||||||
"id", &peertok,
|
|
||||||
NULL)) {
|
|
||||||
command_fail(cmd, "Need id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer = peer_from_json(cmd->ld, buffer, peertok);
|
|
||||||
if (!peer) {
|
|
||||||
command_fail(cmd, "Could not find peer with that id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!peer->owner) {
|
|
||||||
command_fail(cmd, "Peer has no owner");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!streq(peer->owner->name, "lightning_channeld")) {
|
|
||||||
command_fail(cmd, "Peer owned by %s", peer->owner->name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg = towire_channel_dev_reenable_commit(peer);
|
|
||||||
subd_req(peer, peer->owner, take(msg), -1, 0,
|
|
||||||
dev_reenable_commit_finished, cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct json_command dev_reenable_commit = {
|
|
||||||
"dev-reenable-commit",
|
|
||||||
json_dev_reenable_commit,
|
|
||||||
"Reenable the commit timer on peer {id}",
|
|
||||||
"Returns {} on success"
|
|
||||||
};
|
|
||||||
AUTODATA(json_command, &dev_reenable_commit);
|
|
||||||
|
|
||||||
struct log_info {
|
struct log_info {
|
||||||
enum log_level level;
|
enum log_level level;
|
||||||
struct json_result *response;
|
struct json_result *response;
|
||||||
@ -1700,52 +1620,6 @@ void peer_last_tx(struct peer *peer, struct bitcoin_tx *tx,
|
|||||||
peer->last_tx = tal_steal(peer, tx);
|
peer->last_tx = tal_steal(peer, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Guard with heavy dev-only #ifdefs! */
|
|
||||||
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;
|
|
||||||
|
|
||||||
if (!json_get_params(buffer, params,
|
|
||||||
"id", &peertok,
|
|
||||||
NULL)) {
|
|
||||||
command_fail(cmd, "Need id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
peer = peer_from_json(cmd->ld, buffer, peertok);
|
|
||||||
if (!peer) {
|
|
||||||
command_fail(cmd, "Could not find peer with that id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!peer->last_tx) {
|
|
||||||
command_fail(cmd, "Peer has no final transaction");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug(peer->log, "dev-sign-last-tx: signing tx with %zu outputs",
|
|
||||||
tal_count(peer->last_tx->output));
|
|
||||||
sign_last_tx(peer);
|
|
||||||
linear = linearize_tx(cmd, peer->last_tx);
|
|
||||||
|
|
||||||
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,
|
|
||||||
"Sign and return the last commitment transaction",
|
|
||||||
"Sign last transaction with peer @id, return as @tx."
|
|
||||||
" This should never be called outside testing!"
|
|
||||||
};
|
|
||||||
AUTODATA(json_command, &dev_sign_last_tx);
|
|
||||||
|
|
||||||
/* Is this better than the last tx we were holding? */
|
/* Is this better than the last tx we were holding? */
|
||||||
static bool better_closing_fee(struct peer *peer, const struct bitcoin_tx *tx)
|
static bool better_closing_fee(struct peer *peer, const struct bitcoin_tx *tx)
|
||||||
{
|
{
|
||||||
@ -2673,3 +2547,132 @@ const char *peer_state_name(enum peer_state state)
|
|||||||
return enum_peer_state_names[i].name;
|
return enum_peer_state_names[i].name;
|
||||||
return "unknown";
|
return "unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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;
|
||||||
|
|
||||||
|
if (!json_get_params(buffer, params,
|
||||||
|
"id", &peertok,
|
||||||
|
NULL)) {
|
||||||
|
command_fail(cmd, "Need id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer = peer_from_json(cmd->ld, buffer, peertok);
|
||||||
|
if (!peer) {
|
||||||
|
command_fail(cmd, "Could not find peer with that id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!peer->last_tx) {
|
||||||
|
command_fail(cmd, "Peer has no final transaction");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug(peer->log, "dev-sign-last-tx: signing tx with %zu outputs",
|
||||||
|
tal_count(peer->last_tx->output));
|
||||||
|
sign_last_tx(peer);
|
||||||
|
linear = linearize_tx(cmd, peer->last_tx);
|
||||||
|
|
||||||
|
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,
|
||||||
|
"Sign and return the last commitment transaction",
|
||||||
|
"Sign last transaction with peer @id, return as @tx."
|
||||||
|
" This should never be called outside testing!"
|
||||||
|
};
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!json_get_params(buffer, params,
|
||||||
|
"id", &peertok,
|
||||||
|
NULL)) {
|
||||||
|
command_fail(cmd, "Need id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer = peer_from_json(cmd->ld, buffer, peertok);
|
||||||
|
if (!peer) {
|
||||||
|
command_fail(cmd, "Could not find peer with that id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer_internal_error(peer, "Failing due to dev-fail command");
|
||||||
|
command_success(cmd, null_response(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct json_command dev_fail_command = {
|
||||||
|
"dev-fail",
|
||||||
|
json_dev_fail,
|
||||||
|
"Fail with peer {id}",
|
||||||
|
"Returns {} on success"
|
||||||
|
};
|
||||||
|
AUTODATA(json_command, &dev_fail_command);
|
||||||
|
|
||||||
|
static void dev_reenable_commit_finished(struct subd *channeld,
|
||||||
|
const u8 *resp,
|
||||||
|
const int *fds,
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!json_get_params(buffer, params,
|
||||||
|
"id", &peertok,
|
||||||
|
NULL)) {
|
||||||
|
command_fail(cmd, "Need id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
peer = peer_from_json(cmd->ld, buffer, peertok);
|
||||||
|
if (!peer) {
|
||||||
|
command_fail(cmd, "Could not find peer with that id");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!peer->owner) {
|
||||||
|
command_fail(cmd, "Peer has no owner");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!streq(peer->owner->name, "lightning_channeld")) {
|
||||||
|
command_fail(cmd, "Peer owned by %s", peer->owner->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = towire_channel_dev_reenable_commit(peer);
|
||||||
|
subd_req(peer, peer->owner, take(msg), -1, 0,
|
||||||
|
dev_reenable_commit_finished, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct json_command dev_reenable_commit = {
|
||||||
|
"dev-reenable-commit",
|
||||||
|
json_dev_reenable_commit,
|
||||||
|
"Reenable the commit timer on peer {id}",
|
||||||
|
"Returns {} on success"
|
||||||
|
};
|
||||||
|
AUTODATA(json_command, &dev_reenable_commit);
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
@ -134,7 +134,6 @@ static int subd(const char *dir, const char *name, const char *debug_subdaemon,
|
|||||||
int childmsg[2], execfail[2];
|
int childmsg[2], execfail[2];
|
||||||
pid_t childpid;
|
pid_t childpid;
|
||||||
int err, *fd;
|
int err, *fd;
|
||||||
bool debug = debug_subdaemon && strends(name, debug_subdaemon);
|
|
||||||
|
|
||||||
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, childmsg) != 0)
|
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, childmsg) != 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -188,10 +187,12 @@ static int subd(const char *dir, const char *name, const char *debug_subdaemon,
|
|||||||
if (i != dev_disconnect_fd)
|
if (i != dev_disconnect_fd)
|
||||||
close(i);
|
close(i);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (dev_disconnect_fd != -1)
|
if (dev_disconnect_fd != -1)
|
||||||
debug_arg[0] = tal_fmt(NULL, "--dev-disconnect=%i", dev_disconnect_fd);
|
debug_arg[0] = tal_fmt(NULL, "--dev-disconnect=%i", dev_disconnect_fd);
|
||||||
if (debug)
|
if (debug_subdaemon && strends(name, debug_subdaemon))
|
||||||
debug_arg[debug_arg[0] ? 1 : 0] = "--debugger";
|
debug_arg[debug_arg[0] ? 1 : 0] = "--debugger";
|
||||||
|
#endif
|
||||||
execl(path_join(NULL, dir, name), name, debug_arg[0], debug_arg[1], NULL);
|
execl(path_join(NULL, dir, name), name, debug_arg[0], debug_arg[1], NULL);
|
||||||
|
|
||||||
child_errno_fail:
|
child_errno_fail:
|
||||||
@ -236,9 +237,16 @@ int subd_raw(struct lightningd *ld, const char *name)
|
|||||||
{
|
{
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int msg_fd;
|
int msg_fd;
|
||||||
|
const char *debug_subd = NULL;
|
||||||
|
int disconnect_fd = -1;
|
||||||
|
|
||||||
pid = subd(ld->daemon_dir, name, ld->dev_debug_subdaemon,
|
#if DEVELOPER
|
||||||
&msg_fd, ld->dev_disconnect_fd, NULL);
|
debug_subd = ld->dev_debug_subdaemon;
|
||||||
|
disconnect_fd = ld->dev_disconnect_fd;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
|
pid = subd(ld->daemon_dir, name, debug_subd, &msg_fd, disconnect_fd,
|
||||||
|
NULL);
|
||||||
if (pid == (pid_t)-1) {
|
if (pid == (pid_t)-1) {
|
||||||
log_unusual(ld->log, "subd %s failed: %s",
|
log_unusual(ld->log, "subd %s failed: %s",
|
||||||
name, strerror(errno));
|
name, strerror(errno));
|
||||||
@ -342,8 +350,10 @@ static void subdaemon_malformed_msg(struct subd *sd, const u8 *msg)
|
|||||||
msg + sizeof(be16),
|
msg + sizeof(be16),
|
||||||
tal_count(msg) - sizeof(be16)));
|
tal_count(msg) - sizeof(be16)));
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (sd->ld->dev_subdaemon_fail)
|
if (sd->ld->dev_subdaemon_fail)
|
||||||
fatal("Subdaemon %s sent malformed message", sd->name);
|
fatal("Subdaemon %s sent malformed message", sd->name);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if logged, false if malformed. */
|
/* Returns true if logged, false if malformed. */
|
||||||
@ -388,8 +398,10 @@ log_str_peer:
|
|||||||
log_str_broken:
|
log_str_broken:
|
||||||
log_broken(sd->log, "%s: %.*s", name, str_len, str);
|
log_broken(sd->log, "%s: %.*s", name, str_len, str);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
if (sd->ld->dev_subdaemon_fail)
|
if (sd->ld->dev_subdaemon_fail)
|
||||||
fatal("Subdaemon %s hit error", sd->name);
|
fatal("Subdaemon %s hit error", sd->name);
|
||||||
|
#endif
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -491,7 +503,11 @@ next:
|
|||||||
static void destroy_subd(struct subd *sd)
|
static void destroy_subd(struct subd *sd)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
bool fail_if_subd_fails = sd->ld->dev_subdaemon_fail;
|
bool fail_if_subd_fails = false;
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
|
fail_if_subd_fails = sd->ld->dev_subdaemon_fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (waitpid(sd->pid, &status, WNOHANG)) {
|
switch (waitpid(sd->pid, &status, WNOHANG)) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -568,9 +584,16 @@ static struct subd *new_subd(struct lightningd *ld,
|
|||||||
{
|
{
|
||||||
struct subd *sd = tal(ld, struct subd);
|
struct subd *sd = tal(ld, struct subd);
|
||||||
int msg_fd;
|
int msg_fd;
|
||||||
|
const char *debug_subd = NULL;
|
||||||
|
int disconnect_fd = -1;
|
||||||
|
|
||||||
sd->pid = subd(ld->daemon_dir, name, ld->dev_debug_subdaemon,
|
#if DEVELOPER
|
||||||
&msg_fd, ld->dev_disconnect_fd, ap);
|
debug_subd = ld->dev_debug_subdaemon;
|
||||||
|
disconnect_fd = ld->dev_disconnect_fd;
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
|
sd->pid = subd(ld->daemon_dir, name, debug_subd, &msg_fd, disconnect_fd,
|
||||||
|
ap);
|
||||||
if (sd->pid == (pid_t)-1) {
|
if (sd->pid == (pid_t)-1) {
|
||||||
log_unusual(ld->log, "subd %s failed: %s",
|
log_unusual(ld->log, "subd %s failed: %s",
|
||||||
name, strerror(errno));
|
name, strerror(errno));
|
||||||
@ -696,6 +719,7 @@ void subd_release_peer(struct subd *owner, struct peer *peer)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
char *opt_subd_debug(const char *optarg, struct lightningd *ld)
|
char *opt_subd_debug(const char *optarg, struct lightningd *ld)
|
||||||
{
|
{
|
||||||
ld->dev_debug_subdaemon = optarg;
|
ld->dev_debug_subdaemon = optarg;
|
||||||
@ -731,3 +755,4 @@ bool dev_disconnect_permanent(struct lightningd *ld)
|
|||||||
lseek(ld->dev_disconnect_fd, -r, SEEK_CUR);
|
lseek(ld->dev_disconnect_fd, -r, SEEK_CUR);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
@ -163,8 +163,10 @@ void subd_release_peer(struct subd *owner, struct peer *peer);
|
|||||||
*/
|
*/
|
||||||
void subd_shutdown(struct subd *subd, unsigned int seconds);
|
void subd_shutdown(struct subd *subd, unsigned int seconds);
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
char *opt_subd_debug(const char *optarg, struct lightningd *ld);
|
char *opt_subd_debug(const char *optarg, struct lightningd *ld);
|
||||||
char *opt_subd_dev_disconnect(const char *optarg, struct lightningd *ld);
|
char *opt_subd_dev_disconnect(const char *optarg, struct lightningd *ld);
|
||||||
|
|
||||||
bool dev_disconnect_permanent(struct lightningd *ld);
|
bool dev_disconnect_permanent(struct lightningd *ld);
|
||||||
|
#endif /* DEVELOPER */
|
||||||
#endif /* LIGHTNING_LIGHTNINGD_SUBD_H */
|
#endif /* LIGHTNING_LIGHTNINGD_SUBD_H */
|
||||||
|
@ -39,6 +39,7 @@ static void do_write(const void *buf, size_t len)
|
|||||||
#define status_trace(fmt, ...) \
|
#define status_trace(fmt, ...) \
|
||||||
printf(fmt "\n", __VA_ARGS__)
|
printf(fmt "\n", __VA_ARGS__)
|
||||||
|
|
||||||
|
#if DEVELOPER
|
||||||
/* AUTOGENERATED MOCKS START */
|
/* AUTOGENERATED MOCKS START */
|
||||||
/* Generated stub for dev_blackhole_fd */
|
/* Generated stub for dev_blackhole_fd */
|
||||||
void dev_blackhole_fd(int fd UNNEEDED)
|
void dev_blackhole_fd(int fd UNNEEDED)
|
||||||
@ -52,6 +53,7 @@ enum dev_disconnect dev_disconnect(int pkt_type)
|
|||||||
{
|
{
|
||||||
return DEV_DISCONNECT_NORMAL;
|
return DEV_DISCONNECT_NORMAL;
|
||||||
}
|
}
|
||||||
|
#endif /* DEVELOPER */
|
||||||
|
|
||||||
/* We test what look like unknown messages. */
|
/* We test what look like unknown messages. */
|
||||||
#define is_unknown_msg_discardable(x) 0
|
#define is_unknown_msg_discardable(x) 0
|
||||||
|
@ -88,6 +88,16 @@ struct wallet *wallet_new(const tal_t *ctx UNNEEDED, struct log *log UNNEEDED)
|
|||||||
{ fprintf(stderr, "wallet_new called!\n"); abort(); }
|
{ fprintf(stderr, "wallet_new called!\n"); abort(); }
|
||||||
/* AUTOGENERATED MOCKS END */
|
/* AUTOGENERATED MOCKS END */
|
||||||
|
|
||||||
|
/* We only need these in developer mode */
|
||||||
|
#if DEVELOPER
|
||||||
|
/* Generated stub for opt_subd_debug */
|
||||||
|
char *opt_subd_debug(const char *optarg UNNEEDED, struct lightningd *ld UNNEEDED)
|
||||||
|
{ fprintf(stderr, "opt_subd_debug called!\n"); abort(); }
|
||||||
|
/* Generated stub for opt_subd_dev_disconnect */
|
||||||
|
char *opt_subd_dev_disconnect(const char *optarg UNNEEDED, struct lightningd *ld UNNEEDED)
|
||||||
|
{ fprintf(stderr, "opt_subd_dev_disconnect called!\n"); abort(); }
|
||||||
|
#endif
|
||||||
|
|
||||||
#undef main
|
#undef main
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@ -23,6 +23,7 @@ import utils
|
|||||||
bitcoind = None
|
bitcoind = None
|
||||||
TEST_DIR = tempfile.mkdtemp(prefix='lightning-')
|
TEST_DIR = tempfile.mkdtemp(prefix='lightning-')
|
||||||
VALGRIND = os.getenv("NO_VALGRIND", "0") == "0"
|
VALGRIND = os.getenv("NO_VALGRIND", "0") == "0"
|
||||||
|
DEVELOPER = os.getenv("DEVELOPER", "0") == "1"
|
||||||
TEST_DEBUG = os.getenv("TEST_DEBUG", "0") == "1"
|
TEST_DEBUG = os.getenv("TEST_DEBUG", "0") == "1"
|
||||||
|
|
||||||
print("Testing results are in {}".format(TEST_DIR))
|
print("Testing results are in {}".format(TEST_DIR))
|
||||||
@ -104,7 +105,8 @@ class NodeFactory(object):
|
|||||||
with open(os.path.join(lightning_dir, "dev_disconnect"), "w") as f:
|
with open(os.path.join(lightning_dir, "dev_disconnect"), "w") as f:
|
||||||
f.write("\n".join(disconnect))
|
f.write("\n".join(disconnect))
|
||||||
daemon.cmd_line.append("--dev-disconnect=dev_disconnect")
|
daemon.cmd_line.append("--dev-disconnect=dev_disconnect")
|
||||||
daemon.cmd_line.append("--dev-fail-on-subdaemon-fail")
|
if DEVELOPER:
|
||||||
|
daemon.cmd_line.append("--dev-fail-on-subdaemon-fail")
|
||||||
opts = [] if options is None else options
|
opts = [] if options is None else options
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
daemon.cmd_line.append(opt)
|
daemon.cmd_line.append(opt)
|
||||||
@ -441,6 +443,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l2.daemon.wait_for_log('sendrawtx exit 0')
|
l2.daemon.wait_for_log('sendrawtx exit 0')
|
||||||
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
|
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_permfail(self):
|
def test_permfail(self):
|
||||||
l1,l2 = self.connect()
|
l1,l2 = self.connect()
|
||||||
|
|
||||||
@ -485,6 +488,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
bitcoind.rpc.generate(6)
|
bitcoind.rpc.generate(6)
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_onchain_first_commit(self):
|
def test_onchain_first_commit(self):
|
||||||
"""Onchain handling where funder immediately drops to chain"""
|
"""Onchain handling where funder immediately drops to chain"""
|
||||||
|
|
||||||
@ -527,6 +531,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
bitcoind.rpc.generate(6)
|
bitcoind.rpc.generate(6)
|
||||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_onchain_dust_out(self):
|
def test_onchain_dust_out(self):
|
||||||
"""Onchain handling of outgoing dust htlcs (they should fail)"""
|
"""Onchain handling of outgoing dust htlcs (they should fail)"""
|
||||||
# HTLC 1->2, 1 fails after it's irrevocably committed
|
# HTLC 1->2, 1 fails after it's irrevocably committed
|
||||||
@ -579,6 +584,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Payment failed, BTW
|
# Payment failed, BTW
|
||||||
assert l2.rpc.listinvoice('onchain_dust_out')[0]['complete'] == False
|
assert l2.rpc.listinvoice('onchain_dust_out')[0]['complete'] == False
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_onchain_timeout(self):
|
def test_onchain_timeout(self):
|
||||||
"""Onchain handling of outgoing failed htlcs"""
|
"""Onchain handling of outgoing failed htlcs"""
|
||||||
# HTLC 1->2, 1 fails just after it's irrevocably committed
|
# HTLC 1->2, 1 fails just after it's irrevocably committed
|
||||||
@ -634,6 +640,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Payment failed, BTW
|
# Payment failed, BTW
|
||||||
assert l2.rpc.listinvoice('onchain_timeout')[0]['complete'] == False
|
assert l2.rpc.listinvoice('onchain_timeout')[0]['complete'] == False
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_onchain_middleman(self):
|
def test_onchain_middleman(self):
|
||||||
# HTLC 1->2->3, 1->2 goes down after 2 gets preimage from 3.
|
# HTLC 1->2->3, 1->2 goes down after 2 gets preimage from 3.
|
||||||
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
|
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
|
||||||
@ -708,6 +715,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.bitcoin.rpc.generate(100)
|
l1.bitcoin.rpc.generate(100)
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_penalty_inhtlc(self):
|
def test_penalty_inhtlc(self):
|
||||||
"""Test penalty transaction with an incoming HTLC"""
|
"""Test penalty transaction with an incoming HTLC"""
|
||||||
# We suppress each one after first commit; HTLC gets added not fulfilled.
|
# We suppress each one after first commit; HTLC gets added not fulfilled.
|
||||||
@ -829,6 +837,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# FIXME: Test wallet balance...
|
# FIXME: Test wallet balance...
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_permfail_new_commit(self):
|
def test_permfail_new_commit(self):
|
||||||
# Test case where we have two possible commits: it will use new one.
|
# Test case where we have two possible commits: it will use new one.
|
||||||
disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail']
|
disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail']
|
||||||
@ -864,6 +873,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l1.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_permfail_htlc_in(self):
|
def test_permfail_htlc_in(self):
|
||||||
# Test case where we fail with unsettled incoming HTLC.
|
# Test case where we fail with unsettled incoming HTLC.
|
||||||
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
|
disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail']
|
||||||
@ -905,6 +915,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
bitcoind.rpc.generate(6)
|
bitcoind.rpc.generate(6)
|
||||||
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
l2.daemon.wait_for_log('onchaind complete, forgetting peer')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_permfail_htlc_out(self):
|
def test_permfail_htlc_out(self):
|
||||||
# Test case where we fail with unsettled outgoing HTLC.
|
# Test case where we fail with unsettled outgoing HTLC.
|
||||||
disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
|
disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail']
|
||||||
@ -1003,6 +1014,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
ret = l1.rpc.dev_ping(l2.info['id'], 1000, s)
|
ret = l1.rpc.dev_ping(l2.info['id'], 1000, s)
|
||||||
assert ret['totlen'] == 0
|
assert ret['totlen'] == 0
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_ping(self):
|
def test_ping(self):
|
||||||
l1,l2 = self.connect()
|
l1,l2 = self.connect()
|
||||||
|
|
||||||
@ -1014,6 +1026,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# channeld pinging
|
# channeld pinging
|
||||||
self.ping_tests(l1, l2)
|
self.ping_tests(l1, l2)
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_routing_gossip_reconnect(self):
|
def test_routing_gossip_reconnect(self):
|
||||||
# Connect two peers, reconnect and then see if we resume the
|
# Connect two peers, reconnect and then see if we resume the
|
||||||
# gossip.
|
# gossip.
|
||||||
@ -1042,6 +1055,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
self.fund_channel(l1, l3, 10**6)
|
self.fund_channel(l1, l3, 10**6)
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for --dev-broadcast-interval")
|
||||||
def test_routing_gossip(self):
|
def test_routing_gossip(self):
|
||||||
nodes = [self.node_factory.get_node() for _ in range(5)]
|
nodes = [self.node_factory.get_node() for _ in range(5)]
|
||||||
l1 = nodes[0]
|
l1 = nodes[0]
|
||||||
@ -1142,6 +1156,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
route = copy.deepcopy(baseroute)
|
route = copy.deepcopy(baseroute)
|
||||||
l1.rpc.sendpay(to_json(route), rhash)
|
l1.rpc.sendpay(to_json(route), rhash)
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_disconnect(self):
|
def test_disconnect(self):
|
||||||
# These should all make us fail, and retry.
|
# These should all make us fail, and retry.
|
||||||
# FIXME: Configure short timeout for reconnect!
|
# FIXME: Configure short timeout for reconnect!
|
||||||
@ -1157,6 +1172,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log('Failed connected out for {}, will try again'
|
l1.daemon.wait_for_log('Failed connected out for {}, will try again'
|
||||||
.format(l2.info['id']))
|
.format(l2.info['id']))
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_disconnect_funder(self):
|
def test_disconnect_funder(self):
|
||||||
# Now error on funder side duringchannel open.
|
# Now error on funder side duringchannel open.
|
||||||
disconnects = ['-WIRE_OPEN_CHANNEL',
|
disconnects = ['-WIRE_OPEN_CHANNEL',
|
||||||
@ -1177,6 +1193,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) == None
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_disconnect_fundee(self):
|
def test_disconnect_fundee(self):
|
||||||
# Now error on fundee side during channel open.
|
# Now error on fundee side during channel open.
|
||||||
disconnects = ['-WIRE_ACCEPT_CHANNEL',
|
disconnects = ['-WIRE_ACCEPT_CHANNEL',
|
||||||
@ -1195,6 +1212,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
self.assertRaises(ValueError, l1.rpc.fundchannel, l2.info['id'], 20000)
|
||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) == None
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_disconnect_half_signed(self):
|
def test_disconnect_half_signed(self):
|
||||||
# Now, these are the corner cases. Fundee sends funding_signed,
|
# Now, these are the corner cases. Fundee sends funding_signed,
|
||||||
# but funder doesn't receive it.
|
# but funder doesn't receive it.
|
||||||
@ -1214,6 +1232,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert l1.rpc.getpeer(l2.info['id']) == None
|
assert l1.rpc.getpeer(l2.info['id']) == None
|
||||||
assert l2.rpc.getpeer(l1.info['id'])['peerid'] == l1.info['id']
|
assert l2.rpc.getpeer(l1.info['id'])['peerid'] == l1.info['id']
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_signed(self):
|
def test_reconnect_signed(self):
|
||||||
# This will fail *after* both sides consider channel opening.
|
# This will fail *after* both sides consider channel opening.
|
||||||
disconnects = ['+WIRE_FUNDING_SIGNED']
|
disconnects = ['+WIRE_FUNDING_SIGNED']
|
||||||
@ -1243,6 +1262,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log('-> CHANNELD_NORMAL')
|
l1.daemon.wait_for_log('-> CHANNELD_NORMAL')
|
||||||
l2.daemon.wait_for_log('-> CHANNELD_NORMAL')
|
l2.daemon.wait_for_log('-> CHANNELD_NORMAL')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_openingd(self):
|
def test_reconnect_openingd(self):
|
||||||
# Openingd thinks we're still opening; funder reconnects..
|
# Openingd thinks we're still opening; funder reconnects..
|
||||||
disconnects = ['0WIRE_ACCEPT_CHANNEL']
|
disconnects = ['0WIRE_ACCEPT_CHANNEL']
|
||||||
@ -1272,6 +1292,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# Just to be sure, second openingd hand over to channeld.
|
# Just to be sure, second openingd hand over to channeld.
|
||||||
l2.daemon.wait_for_log('lightning_openingd.*REPLY WIRE_OPENING_FUNDEE_REPLY with 2 fds')
|
l2.daemon.wait_for_log('lightning_openingd.*REPLY WIRE_OPENING_FUNDEE_REPLY with 2 fds')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_normal(self):
|
def test_reconnect_normal(self):
|
||||||
# Should reconnect fine even if locked message gets lost.
|
# Should reconnect fine even if locked message gets lost.
|
||||||
disconnects = ['-WIRE_FUNDING_LOCKED',
|
disconnects = ['-WIRE_FUNDING_LOCKED',
|
||||||
@ -1283,6 +1304,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
|
|
||||||
self.fund_channel(l1, l2, 10**6)
|
self.fund_channel(l1, l2, 10**6)
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_sender_add1(self):
|
def test_reconnect_sender_add1(self):
|
||||||
# Fail after add is OK, will cause payment failure though.
|
# Fail after add is OK, will cause payment failure though.
|
||||||
disconnects = ['-WIRE_UPDATE_ADD_HTLC-nocommit',
|
disconnects = ['-WIRE_UPDATE_ADD_HTLC-nocommit',
|
||||||
@ -1309,6 +1331,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
# This will send commit, so will reconnect as required.
|
# This will send commit, so will reconnect as required.
|
||||||
l1.rpc.sendpay(to_json(route), rhash)
|
l1.rpc.sendpay(to_json(route), rhash)
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_sender_add(self):
|
def test_reconnect_sender_add(self):
|
||||||
disconnects = ['-WIRE_COMMITMENT_SIGNED',
|
disconnects = ['-WIRE_COMMITMENT_SIGNED',
|
||||||
'@WIRE_COMMITMENT_SIGNED',
|
'@WIRE_COMMITMENT_SIGNED',
|
||||||
@ -1334,6 +1357,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
for i in range(0,len(disconnects)):
|
for i in range(0,len(disconnects)):
|
||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_receiver_add(self):
|
def test_reconnect_receiver_add(self):
|
||||||
disconnects = ['-WIRE_COMMITMENT_SIGNED',
|
disconnects = ['-WIRE_COMMITMENT_SIGNED',
|
||||||
'@WIRE_COMMITMENT_SIGNED',
|
'@WIRE_COMMITMENT_SIGNED',
|
||||||
@ -1357,6 +1381,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_reconnect_receiver_fulfill(self):
|
def test_reconnect_receiver_fulfill(self):
|
||||||
# Ordering matters: after +WIRE_UPDATE_FULFILL_HTLC, channeld
|
# Ordering matters: after +WIRE_UPDATE_FULFILL_HTLC, channeld
|
||||||
# will continue and try to send WIRE_COMMITMENT_SIGNED: if
|
# will continue and try to send WIRE_COMMITMENT_SIGNED: if
|
||||||
@ -1386,6 +1411,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l1.daemon.wait_for_log('Already have funding locked in')
|
l1.daemon.wait_for_log('Already have funding locked in')
|
||||||
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
assert l2.rpc.listinvoice('testpayment2')[0]['complete'] == True
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_shutdown_reconnect(self):
|
def test_shutdown_reconnect(self):
|
||||||
disconnects = ['-WIRE_SHUTDOWN',
|
disconnects = ['-WIRE_SHUTDOWN',
|
||||||
'@WIRE_SHUTDOWN',
|
'@WIRE_SHUTDOWN',
|
||||||
@ -1413,6 +1439,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
l2.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
|
l2.daemon.wait_for_logs(['sendrawtx exit 0', '-> CLOSINGD_COMPLETE'])
|
||||||
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
|
assert l1.bitcoin.rpc.getmempoolinfo()['size'] == 1
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_closing_negotiation_reconnect(self):
|
def test_closing_negotiation_reconnect(self):
|
||||||
disconnects = ['-WIRE_CLOSING_SIGNED',
|
disconnects = ['-WIRE_CLOSING_SIGNED',
|
||||||
'@WIRE_CLOSING_SIGNED',
|
'@WIRE_CLOSING_SIGNED',
|
||||||
@ -1511,6 +1538,7 @@ class LightningDTests(BaseLightningDTests):
|
|||||||
assert outputs[0] > 8990000
|
assert outputs[0] > 8990000
|
||||||
assert outputs[2] == 10000000
|
assert outputs[2] == 10000000
|
||||||
|
|
||||||
|
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1")
|
||||||
def test_channel_persistence(self):
|
def test_channel_persistence(self):
|
||||||
# Start two nodes and open a channel (to remember). l2 will
|
# Start two nodes and open a channel (to remember). l2 will
|
||||||
# mysteriously die while committing the first HTLC so we can
|
# mysteriously die while committing the first HTLC so we can
|
||||||
|
@ -25,6 +25,7 @@ LIGHTNINGD_CONFIG = {
|
|||||||
"locktime-blocks": 6,
|
"locktime-blocks": 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEVELOPER = os.getenv("DEVELOPER", "0") == "1"
|
||||||
|
|
||||||
def write_config(filename, opts):
|
def write_config(filename, opts):
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
@ -237,11 +238,11 @@ class LightningD(TailableProc):
|
|||||||
'--bitcoin-datadir={}'.format(bitcoin_dir),
|
'--bitcoin-datadir={}'.format(bitcoin_dir),
|
||||||
'--lightning-dir={}'.format(lightning_dir),
|
'--lightning-dir={}'.format(lightning_dir),
|
||||||
'--port={}'.format(port),
|
'--port={}'.format(port),
|
||||||
'--network=regtest',
|
'--network=regtest'
|
||||||
'--dev-broadcast-interval=1000',
|
|
||||||
'--dev-hsm-seed={}'.format(seed.hex())
|
|
||||||
]
|
]
|
||||||
|
if DEVELOPER:
|
||||||
|
self.cmd_line += ['--dev-broadcast-interval=1000',
|
||||||
|
'--dev-hsm-seed={}'.format(seed.hex())]
|
||||||
self.cmd_line += ["--{}={}".format(k, v) for k, v in LIGHTNINGD_CONFIG.items()]
|
self.cmd_line += ["--{}={}".format(k, v) for k, v in LIGHTNINGD_CONFIG.items()]
|
||||||
self.prefix = 'lightningd(%d)' % (port)
|
self.prefix = 'lightningd(%d)' % (port)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user