diff --git a/Makefile b/Makefile index 662da7859..e68f9008b 100644 --- a/Makefile +++ b/Makefile @@ -209,6 +209,7 @@ default: $(PROGRAMS) $(MANPAGES) daemon-all include bitcoin/Makefile include wire/Makefile +include lightningd/Makefile # Git doesn't maintain timestamps, so we only regen if git says we should. CHANGED_FROM_GIT = [ x"`git log $@ | head -n1`" != x"`git log $< | head -n1`" -o x"`git diff $<`" != x"" ] diff --git a/lightningd/.gitignore b/lightningd/.gitignore new file mode 100644 index 000000000..c9af60b4c --- /dev/null +++ b/lightningd/.gitignore @@ -0,0 +1 @@ +lightningd diff --git a/lightningd/Makefile b/lightningd/Makefile new file mode 100644 index 000000000..e85c9160e --- /dev/null +++ b/lightningd/Makefile @@ -0,0 +1,52 @@ +#! /usr/bin/make + +# Designed to be run one level up +lightningd-wrongdir: + $(MAKE) -C .. lightningd-all + +lightningd-all: lightningd/lightningd + +default: lightningd-all + +LIGHTNINGD_LIB_SRC := \ + daemon/configdir.c \ + daemon/json.c \ + daemon/log.c \ + daemon/options.c \ + daemon/opt_time.c \ + daemon/pseudorand.c \ + daemon/routing.c \ + daemon/watch.c + +LIGHTNINGD_LIB_OBJS := $(LIGHTNINGD_LIB_SRC:.c=.o) + +LIGHTNINGD_SRC := \ + lightningd/lightningd.c + +LIGHTNINGD_OBJS := $(LIGHTNINGD_SRC:.c=.o) + +LIGHTNINGD_JSMN_OBJS := daemon/jsmn.o +LIGHTNINGD_JSMN_HEADERS := daemon/jsmn/jsmn.h + +LIGHTNINGD_HEADERS := lightningd/lightningd.h + +$(LIGHTNINGD_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_JSMN_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(GEN_HEADERS) $(CCAN_HEADERS) $(DAEMON_HEADERS) $(LIBBASE58_HEADERS) + +check-source: $(LIGHTNINGD_SRC:%=check-src-include-order/%) +check-source: $(LIGHTNINGD_LIB_SRC:%=check-src-include-order/%) +check-source: $(LIGHTNINGD_CLI_SRC:%=check-src-include-order/%) +check-source: $(LIGHTNINGD_HEADERS:%=check-hdr-include-order/%) +check-source-bolt: $(LIGHTNINGD_SRC:%=bolt-check/%) $(LIGHTNINGD_HEADERS:%=bolt-check/%) + +check-whitespace: $(LIGHTNINGD_SRC:%=check-whitespace/%) $(LIGHTNINGD_HEADERS:%=check-whitespace/%) + +check-lightningd-makefile: + @if [ "`ls lightningd/*.h | grep -v lightningd/gen | tr '\012' ' '`" != "`echo $(LIGHTNINGD_HEADERS) ''`" ]; then echo LIGHTNINGD_HEADERS incorrect; exit 1; fi + +lightningd/lightningd: $(LIGHTNINGD_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) $(CORE_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) $(LIBBASE58_OBJS) libsecp256k1.a + +clean: lightningd-clean + +lightningd-clean: + $(RM) $(LIGHTNINGD_OBJS) $(LIGHTNINGD_LIB_OBJS) $(LIGHTNINGD_JSMN_OBJS) + diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c new file mode 100644 index 000000000..3cf7844ae --- /dev/null +++ b/lightningd/lightningd.c @@ -0,0 +1,196 @@ +#include "lightningd.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +char *bitcoin_datadir; + +#define FIXME_IMPLEMENT() errx(1, "FIXME: Implement %s", __func__) + +/* FIXME: Implement */ +struct invoices *invoices_init(struct lightningd_state *dstate) +{ + return NULL; +} + +struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id); +struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id) +{ + FIXME_IMPLEMENT(); +} + +struct json_result *null_response(const tal_t *ctx) +{ + FIXME_IMPLEMENT(); +} + +void command_success(struct command *cmd, struct json_result *result) +{ + FIXME_IMPLEMENT(); +} + +void command_fail(struct command *cmd, const char *fmt, ...) +{ + FIXME_IMPLEMENT(); +} + +size_t get_tx_depth(struct lightningd_state *dstate, + const struct sha256_double *txid) +{ + FIXME_IMPLEMENT(); +} + + #include +void queue_pkt_nested(struct peer *peer, + int type, + const u8 *nested_pkt) +{ + FIXME_IMPLEMENT(); +} + +static struct lightningd *new_lightningd(const tal_t *ctx) +{ + struct lightningd *ld = tal(ctx, struct lightningd); + + ld->dstate.log_book = new_log_book(&ld->dstate, 20*1024*1024,LOG_INFORM); + ld->log = ld->dstate.base_log = new_log(&ld->dstate, + ld->dstate.log_book, + "lightningd(%u):", + (int)getpid()); + + list_head_init(&ld->dstate.peers); + list_head_init(&ld->dstate.pay_commands); + ld->dstate.portnum = DEFAULT_PORT; + ld->dstate.testnet = true; + timers_init(&ld->dstate.timers, time_mono()); + txwatch_hash_init(&ld->dstate.txwatches); + txowatch_hash_init(&ld->dstate.txowatches); + list_head_init(&ld->dstate.bitcoin_req); + list_head_init(&ld->dstate.wallet); + list_head_init(&ld->dstate.addresses); + ld->dstate.dev_never_routefail = false; + ld->dstate.dev_no_broadcast = false; + ld->dstate.bitcoin_req_running = false; + ld->dstate.nodes = empty_node_map(&ld->dstate); + ld->dstate.reexec = NULL; + ld->dstate.external_ip = NULL; + ld->dstate.announce = NULL; + + ld->dstate.invoices = invoices_init(&ld->dstate); + return ld; +} + +static const char *daemons[] = { + "lightningd" +}; + +/* Check we can run them, and check their versions */ +static void test_daemons(const struct lightningd *ld) +{ + size_t i; + const tal_t *ctx = tal_tmpctx(ld); + + for (i = 0; i < ARRAY_SIZE(daemons); i++) { + int outfd; + const char *dpath = path_join(ctx, ld->daemon_dir, daemons[i]); + const char *verstring; + pid_t pid = pipecmd(&outfd, NULL, &outfd, + dpath, "--version", NULL); + + log_debug(ld->dstate.base_log, "testing %s", dpath); + if (pid == -1) + err(1, "Could not run %s", dpath); + verstring = grab_fd(ctx, outfd); + if (!verstring) + err(1, "Could not get output from %s", dpath); + if (!strstarts(verstring, version()) + || verstring[strlen(version())] != '\n') + errx(1, "%s: bad version '%s'", daemons[i], verstring); + } + tal_free(ctx); +} + +static const char *find_my_path(const tal_t *ctx, const char *argv0) +{ + char *me = path_canon(ctx, argv0); + + if (access(me, X_OK) != 0) + errx(1, "I cannot find myself at %s based on my name %s", + me, argv0); + return path_dirname(ctx, take(me)); +} + +int main(int argc, char *argv[]) +{ + struct lightningd *ld = new_lightningd(NULL); + + err_set_progname(argv[0]); + + secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY + | SECP256K1_CONTEXT_SIGN); + + /* Figure out where we are first. */ + ld->daemon_dir = find_my_path(ld, argv[0]); + + /* Handle options and config; move to .lightningd */ + handle_opts(&ld->dstate, argc, argv); + + /* Activate crash log now we're in the right place. */ + crashlog_activate(ld->log); + + /* Ignore SIGPIPE: we look at our write return values*/ + signal(SIGPIPE, SIG_IGN); + + /* Make sure we can reach other daemons, and versions match. */ + test_daemons(ld); + + /* Mark ourselves live. */ + log_info(ld->log, "Hello world from %s!", version()); + +#if 0 + /* Set up HSM. */ + hsm_init(dstate, &dstate->id); + + /* Initialize block topology. */ + setup_topology(dstate); + + /* Load peers from database. */ + db_load_peers(dstate); + + /* Create RPC socket (if any) */ + setup_jsonrpc(dstate, dstate->rpc_filename); + + /* Ready for connections from peers. */ + setup_listeners(dstate); + + for (;;) { + struct timer *expired; + void *v = io_loop(&dstate->timers, &expired); + + /* We use io_break(dstate) to shut down. */ + if (v == dstate) + break; + + if (expired) + timer_expired(dstate, expired); + } +#endif + + tal_free(ld); + opt_free_table(); + return 0; +} + diff --git a/lightningd/lightningd.h b/lightningd/lightningd.h new file mode 100644 index 000000000..c81fec4fd --- /dev/null +++ b/lightningd/lightningd.h @@ -0,0 +1,24 @@ +#ifndef LIGHTNING_LIGHTNINGD_LIGHTNINGD_H +#define LIGHTNING_LIGHTNINGD_LIGHTNINGD_H +#include "config.h" +#include + +/* BOLT #1: + * + * The default TCP port is 9735. This corresponds to hexadecimal + * `0x2607`, the unicode code point for LIGHTNING. + */ +#define DEFAULT_PORT 0x2607 + +/* FIXME: This is two structures, during the migration from old setup to new */ +struct lightningd { + /* Must be first, since things assume we can tal() off it */ + struct lightningd_state dstate; + + /* The directory to find all the subdaemons. */ + const char *daemon_dir; + + /* Log for general stuff. */ + struct log *log; +}; +#endif /* LIGHTNING_LIGHTNINGD_LIGHTNINGD_H */