From 88bb38f63b46eeac6ea3f3a29b71dd9aca6cacd0 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 29 Aug 2017 01:23:01 +0930 Subject: [PATCH] daemon/lightningd: remove building, and main files Signed-off-by: Rusty Russell --- .travis.yml | 6 +- INSTALL.md | 4 +- Makefile | 6 +- contrib/pylightning/lightning/__init__.py | 2 +- contrib/pylightning/lightning/lightning.py | 95 - daemon/Makefile | 62 +- daemon/chaintopology.c | 1 - daemon/channel.c | 359 -- daemon/channel.h | 140 - daemon/commit_tx.c | 225 - daemon/commit_tx.h | 40 - daemon/cryptopkt.c | 656 --- daemon/cryptopkt.h | 48 - daemon/db.c | 1980 -------- daemon/db.h | 76 - daemon/dns.c | 2 +- daemon/failure.c | 40 - daemon/failure.h | 36 - daemon/feechange.c | 144 - daemon/feechange.h | 52 - daemon/feechange_state.h | 23 - daemon/htlc.c | 81 - daemon/invoice.c | 9 + daemon/irc_announce.c | 280 -- daemon/irc_announce.h | 9 - daemon/jsonrpc.c | 4 +- daemon/lightningd.c | 174 - daemon/names.c | 36 - daemon/names.h | 10 - daemon/output_to_htlc.c | 80 - daemon/output_to_htlc.h | 20 - daemon/p2p_announce.c | 231 - daemon/p2p_announce.h | 15 - daemon/packets.c | 599 --- daemon/pay.c | 478 -- daemon/pay.h | 19 - daemon/peer.c | 5294 -------------------- daemon/peer.h | 91 - daemon/peer_internal.h | 210 - daemon/routingrpc.c | 169 - daemon/secrets.c | 251 - daemon/secrets.h | 68 - daemon/sphinx.c | 479 -- daemon/sphinx.h | 136 - daemon/state.h | 77 - daemon/state_types.h | 99 - daemon/test/Makefile | 73 - daemon/test/run-maxfee.c | 52 - daemon/test/scripts/generate-block.sh | 21 - daemon/test/scripts/getinput.sh | 29 - daemon/test/scripts/helpers.sh | 467 -- daemon/test/scripts/setup.sh | 47 - daemon/test/scripts/shutdown.sh | 11 - daemon/test/scripts/vars.sh | 40 - daemon/test/test-basic | 359 -- daemon/test/test-different-fees | 86 - daemon/test/test-funding-timeout | 82 - daemon/test/test-invoice | 87 - daemon/test/test-mutual-close-with-htlcs | 96 - daemon/test/test-routing | 146 - daemon/test/test-steal | 91 - daemon/test/test-unilateral | 87 - daemon/wallet.c | 144 - daemon/wallet.h | 21 - daemon/watch.c | 4 +- tests/test_lightningd.py | 151 +- tests/utils.py | 13 - type_to_string.c | 3 - 68 files changed, 75 insertions(+), 14951 deletions(-) delete mode 100644 daemon/channel.c delete mode 100644 daemon/channel.h delete mode 100644 daemon/commit_tx.c delete mode 100644 daemon/commit_tx.h delete mode 100644 daemon/cryptopkt.c delete mode 100644 daemon/cryptopkt.h delete mode 100644 daemon/db.c delete mode 100644 daemon/db.h delete mode 100644 daemon/failure.c delete mode 100644 daemon/failure.h delete mode 100644 daemon/feechange.c delete mode 100644 daemon/feechange.h delete mode 100644 daemon/feechange_state.h delete mode 100644 daemon/htlc.c delete mode 100644 daemon/irc_announce.c delete mode 100644 daemon/irc_announce.h delete mode 100644 daemon/lightningd.c delete mode 100644 daemon/names.c delete mode 100644 daemon/names.h delete mode 100644 daemon/output_to_htlc.c delete mode 100644 daemon/output_to_htlc.h delete mode 100644 daemon/p2p_announce.c delete mode 100644 daemon/p2p_announce.h delete mode 100644 daemon/packets.c delete mode 100644 daemon/pay.c delete mode 100644 daemon/pay.h delete mode 100644 daemon/peer.c delete mode 100644 daemon/peer.h delete mode 100644 daemon/peer_internal.h delete mode 100644 daemon/routingrpc.c delete mode 100644 daemon/secrets.c delete mode 100644 daemon/secrets.h delete mode 100644 daemon/sphinx.c delete mode 100644 daemon/sphinx.h delete mode 100644 daemon/state.h delete mode 100644 daemon/state_types.h delete mode 100644 daemon/test/Makefile delete mode 100644 daemon/test/run-maxfee.c delete mode 100755 daemon/test/scripts/generate-block.sh delete mode 100755 daemon/test/scripts/getinput.sh delete mode 100644 daemon/test/scripts/helpers.sh delete mode 100755 daemon/test/scripts/setup.sh delete mode 100755 daemon/test/scripts/shutdown.sh delete mode 100644 daemon/test/scripts/vars.sh delete mode 100755 daemon/test/test-basic delete mode 100755 daemon/test/test-different-fees delete mode 100755 daemon/test/test-funding-timeout delete mode 100755 daemon/test/test-invoice delete mode 100755 daemon/test/test-mutual-close-with-htlcs delete mode 100755 daemon/test/test-routing delete mode 100755 daemon/test/test-steal delete mode 100755 daemon/test/test-unilateral delete mode 100644 daemon/wallet.c delete mode 100644 daemon/wallet.h diff --git a/.travis.yml b/.travis.yml index a7dd5fde3..c86579fe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,12 +3,12 @@ dist: trusty sudo: true env: - - NOVALGRIND=1 NO_VALGRIND=0 - - NOVALGRIND=0 NO_VALGRIND=1 + - NOVALGRIND=1 + - NOVALGRIND=0 # Trusty (aka 14.04) is way way too old, so run in docker... script: - docker pull cdecker/lightning-ci > /dev/null - docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci make -j3 - - docker run --rm=true -e NOVALGRIND=${NOVALGRIND:-0} -e TEST_DEBUG=${TEST_DEBUG:-0} -e NO_VALGRIND=${NOVALGRIND:-0} -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci make check + - docker run --rm=true -e NOVALGRIND=${NOVALGRIND:-0} -e TEST_DEBUG=${TEST_DEBUG:-0} -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci make check - docker run --rm=true -v "${TRAVIS_BUILD_DIR}":/build -t cdecker/lightning-ci make check-source diff --git a/INSTALL.md b/INSTALL.md index 6a2e156d1..0ab85b23c 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -51,7 +51,7 @@ make Running lightning: ``` bitcoind & -./daemon/lightningd & +./lightningd/lightningd & ./daemon/lightning-cli help ``` **Note**: You may need to include `testnet=1` in `bitcoin.conf` @@ -85,6 +85,6 @@ Running lightning: ``` bitcoind export LD_LIBRARY_PATH=/usr/local/lib -./daemon/lightningd +./lightningd/lightningd ./daemon/lightning-cli help ``` diff --git a/Makefile b/Makefile index d6ffd7908..7fcafafe2 100644 --- a/Makefile +++ b/Makefile @@ -219,7 +219,7 @@ CFLAGS := $(CWARNFLAGS) $(CDEBUGFLAGS) -I $(CCANDIR) -I libwally-core/src/secp25 LDLIBS := -lprotobuf-c -lgmp -lsqlite3 $(COVFLAGS) $(PROGRAMS): CFLAGS+=-I. -default: $(PROGRAMS) doc-all daemon-all +default: $(PROGRAMS) doc-all include doc/Makefile include bitcoin/Makefile @@ -242,7 +242,7 @@ test-protocol: test/test_protocol check: test-protocol $(MAKE) pytest -pytest: daemon/lightningd daemon/lightning-cli lightningd-all +pytest: daemon/lightning-cli lightningd-all PYTHONPATH=contrib/pylightning python3 tests/test_lightningd.py -f # Keep includes in alpha order. @@ -255,7 +255,7 @@ check-hdr-include-order/%: % @if [ "$$(grep '^#include' < $< | tail -n +2)" != "$$(grep '^#include' < $< | tail -n +2 | LC_ALL=C sort)" ]; then echo "$<:1: includes out of order"; exit 1; fi # Make sure Makefile includes all headers. -check-makefile: check-daemon-makefile +check-makefile: @if [ "`echo bitcoin/*.h`" != "$(BITCOIN_HEADERS)" ]; then echo BITCOIN_HEADERS incorrect; exit 1; fi @if [ x"`ls *.h | grep -v ^gen_ | fgrep -v lightning.pb-c.h`" != x"`echo $(CORE_HEADERS) $(CORE_TX_HEADERS) | tr ' ' '\n' | LC_ALL=C sort`" ]; then echo CORE_HEADERS incorrect; exit 1; fi @if [ x"$(CCANDIR)/config.h `find $(CCANDIR)/ccan -name '*.h' | grep -v /test/ | LC_ALL=C sort | tr '\n' ' '`" != x"$(CCAN_HEADERS) " ]; then echo CCAN_HEADERS incorrect; exit 1; fi diff --git a/contrib/pylightning/lightning/__init__.py b/contrib/pylightning/lightning/__init__.py index ef4a36347..8192d42c8 100644 --- a/contrib/pylightning/lightning/__init__.py +++ b/contrib/pylightning/lightning/__init__.py @@ -1 +1 @@ -from .lightning import LightningRpc, LegacyLightningRpc +from .lightning import LightningRpc diff --git a/contrib/pylightning/lightning/lightning.py b/contrib/pylightning/lightning/lightning.py index d50016fb0..4f245dd37 100644 --- a/contrib/pylightning/lightning/lightning.py +++ b/contrib/pylightning/lightning/lightning.py @@ -105,101 +105,6 @@ class LightningRpc(UnixDomainSocketRpc): return self._call("dev-add-route", [src, dst, base, var, delay, minblocks]) -class LegacyLightningRpc(UnixDomainSocketRpc): - def getchannels(self): - """List all known channels. - """ - return self._call("getchannels", [])['channels'] - - def getnodes(self): - """List all known nodes in the network. - """ - return self._call("getnodes", []) - - def getlog(self, level=None): - """Get logs, with optional level: [io|debug|info|unusual] - """ - return self._call("getlog", [level]) - - def getpeers(self): - """Return a list of peers. - """ - return self._call("getpeers", []) - - def getroute(self, destination, amount, riskfactor=1): - """Return route to `destination` for `amount` milli satoshis, using `riskfactor` - """ - return self._call("getroute", [destination, amount, riskfactor])['route'] - - def getinfo(self): - """Get general information about this node""" - return self._call("getinfo", []) - - def invoice(self, amount, label, paymentKey=None): - """Create a new invoice. - - Create invoice for `amount` millisatoshi with - `label`. Optionally you can specify the `paymentKey`, - otherwise a random one will be generated. The `label` has to - be unique. - """ - args = [amount, label] - if paymentKey is not None: - args.append(paymentKey) - return self._call("invoice", args) - - def waitinvoice(self, label=None, async=False): - """Wait for the next invoice to be paid, after `label` (if supplied) - """ - args = [] - if label is not None: - args.append(label) - def call(): - return self._call("waitinvoice", args) - if async: - return self.executor.submit(call) - else: - return call() - - def sendpay(self, route, paymenthash): - """Send along `route` in return for preimage of `paymenthash` - """ - return self._call("sendpay", [route, paymenthash]) - - def pay(self, destination, amount, paymenthash): - """Shorthand for `getroute` and `sendpay` - - Sends `amount` millisatoshi to `destination` for invoice matching `paymenthash` - """ - route = self.getroute(destination, amount, 1) - return self.sendpay(route, paymenthash) - - def dev_rhash(self, secret): - res = self._call("dev-rhash", [secret]) - print(res) - return self._call("dev-rhash", [secret])['rhash'] - - def dev_newhtlc(self, peerid, amount, expiry, rhash): - return self._call("dev-newhtlc", [peerid, amount, expiry, rhash]) - - def dev_add_route(self, src, dst, base_fee, fee_rate, delay, minblocks): - return self._call("dev-add-route", [src, dst, base_fee, fee_rate, delay, minblocks]) - - def connect(self, hostname, port, fundingtxhex, async=False): - """Connect to a `host` at `port` using `fundingtxhex` to fund - """ - def call_connect(): - return self._call("connect", [hostname, port, fundingtxhex]) - - if not async: - return call_connect() - else: - return self.executor.submit(call_connect) - - def newaddr(self): - """Get a new address to fund a channel - """ - return self._call("newaddr", []) if __name__ == "__main__": l1 = LightningRpc("/tmp/lightning1/lightning-rpc") diff --git a/daemon/Makefile b/daemon/Makefile index b74ce23c0..9c270edbb 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -8,7 +8,7 @@ LC_CTYPE=C daemon-wrongdir: $(MAKE) -C .. daemon-all -daemon-all: daemon/lightningd daemon/lightning-cli +daemon-all: daemon/lightning-cli DAEMON_LIB_SRC := \ daemon/configdir.c \ @@ -21,35 +21,16 @@ DAEMON_SRC := \ daemon/bitcoind.c \ daemon/broadcast.c \ daemon/chaintopology.c \ - daemon/channel.c \ - daemon/commit_tx.c \ - daemon/cryptopkt.c \ - daemon/db.c \ daemon/dns.c \ - daemon/failure.c \ - daemon/feechange.c \ - daemon/htlc.c \ daemon/htlc_state.c \ daemon/invoice.c \ - daemon/irc_announce.c \ daemon/jsonrpc.c \ - daemon/lightningd.c \ daemon/netaddr.c \ daemon/options.c \ daemon/opt_time.c \ - daemon/output_to_htlc.c \ - daemon/p2p_announce.c \ - daemon/packets.c \ - daemon/pay.c \ - daemon/peer.c \ daemon/routing.c \ - daemon/routingrpc.c \ - daemon/secrets.c \ - daemon/sphinx.c \ daemon/timeout.c \ - daemon/wallet.c \ daemon/watch.c \ - daemon/names.c \ irc.c DAEMON_OBJS := $(DAEMON_SRC:.c=.o) @@ -61,50 +42,28 @@ DAEMON_JSMN_OBJS := daemon/jsmn.o DAEMON_JSMN_HEADERS := daemon/jsmn/jsmn.h DAEMON_GEN_HEADERS := \ - daemon/gen_feechange_state_names.h \ - daemon/gen_htlc_state_names.h \ - daemon/gen_pkt_names.h \ - daemon/gen_state_names.h + daemon/gen_htlc_state_names.h DAEMON_HEADERS := \ daemon/bitcoind.h \ daemon/broadcast.h \ daemon/chaintopology.h \ - daemon/channel.h \ - daemon/commit_tx.h \ daemon/configdir.h \ - daemon/cryptopkt.h \ - daemon/db.h \ daemon/dns.h \ - daemon/failure.h \ - daemon/feechange.h \ - daemon/feechange_state.h \ daemon/htlc.h \ daemon/htlc_state.h \ daemon/invoice.h \ - daemon/irc_announce.h \ daemon/json.h \ daemon/jsonrpc.h \ daemon/lightningd.h \ daemon/log.h \ - daemon/names.h \ daemon/netaddr.h \ daemon/opt_time.h \ daemon/options.h \ - daemon/output_to_htlc.h \ - daemon/p2p_announce.h \ daemon/packets.h \ - daemon/pay.h \ - daemon/peer.h \ - daemon/peer_internal.h \ daemon/pseudorand.h \ daemon/routing.h \ - daemon/secrets.h \ - daemon/sphinx.h \ - daemon/state.h \ - daemon/state_types.h \ daemon/timeout.h \ - daemon/wallet.h \ daemon/watch.h daemon/gen_htlc_state_names.h: daemon/htlc_state.h ccan/ccan/cdump/tools/cdump-enumstr @@ -120,7 +79,7 @@ daemon/gen_state_names.h: daemon/state_types.h ccan/ccan/cdump/tools/cdump-enums daemon/gen_pkt_names.h: lightning.pb-c.h ccan/ccan/cdump/tools/cdump-enumstr (echo 'enum PktCase {'; grep '^ PKT__' lightning.pb-c.h; echo '};') | ccan/ccan/cdump/tools/cdump-enumstr - | sed 's/enum PktCase/Pkt__PktCase/' > $@ -$(DAEMON_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS): $(DAEMON_HEADERS) $(DAEMON_JSMN_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(CORE_TX_HEADERS) $(GEN_HEADERS) $(DAEMON_GEN_HEADERS) $(CCAN_HEADERS) $(WIRE_HEADERS) $(WIRE_GEN_HEADERS) $(LIBSODIUM_HEADERS) $(LIBBASE58_HEADERS) +$(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS): $(DAEMON_JSMN_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(CORE_TX_HEADERS) $(GEN_HEADERS) $(DAEMON_GEN_HEADERS) $(CCAN_HEADERS) $(WIRE_HEADERS) $(WIRE_GEN_HEADERS) $(LIBSODIUM_HEADERS) $(LIBBASE58_HEADERS) $(DAEMON_JSMN_OBJS): $(DAEMON_JSMN_HEADERS) $(DAEMON_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS): CFLAGS += -USHACHAIN_BITS @@ -129,11 +88,6 @@ check-source: $(DAEMON_SRC:%=check-src-include-order/%) check-source: $(DAEMON_LIB_SRC:%=check-src-include-order/%) check-source: $(DAEMON_CLI_SRC:%=check-src-include-order/%) check-source: $(DAEMON_HEADERS:%=check-hdr-include-order/%) -check-daemon-makefile: - @echo $(DAEMON_HEADERS) | tr ' ' '\012' > /tmp/daemon-headers-makefile - @ls daemon/*.h | grep -v daemon/gen > /tmp/daemon-headers-file - @if [ "`diff -w /tmp/daemon-headers-makefile /tmp/daemon-headers-file`" != "" ]; then echo DAEMON_HEADERS incorrect; diff -w --context=2 /tmp/daemon-headers-makefile /tmp/daemon-headers-file; exit 1; fi - @rm /tmp/daemon-headers-makefile /tmp/daemon-headers-file check-source-bolt: $(DAEMON_SRC:%=bolt-check/%) $(DAEMON_HEADERS:%=bolt-check/%) @@ -152,17 +106,9 @@ daemon/jsmn/jsmn.c: daemon/jsmn/jsmn.h daemon/jsmn.o: daemon/jsmn/jsmn.c $(COMPILE.c) -DJSMN_STRICT=1 $(OUTPUT_OPTION) $< -# We need a 64-bit shachain (default) -daemon/shachain-64.o: $(CCANDIR)/ccan/crypto/shachain/shachain.c $(CCAN_HEADERS) - $(CC) $(CFLAGS) -USHACHAIN_BITS -c -o $@ $< - -daemon/lightningd: $(DAEMON_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_JSMN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(CORE_PROTOBUF_OBJS) $(BITCOIN_OBJS) $(LIBBASE58_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) daemon/shachain-64.o libsecp256k1.a libsodium.a - daemon/lightning-cli: $(DAEMON_CLI_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_JSMN_OBJS) $(CORE_OBJS) $(BITCOIN_OBJS) $(LIBBASE58_OBJS) $(WIRE_OBJS) $(CCAN_OBJS) libsecp256k1.a libsodium.a daemon-clean: - $(RM) $(DAEMON_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS) $(DAEMON_JSMN_OBJS) $(DAEMON_GEN_HEADERS) + $(RM) $(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS) $(DAEMON_JSMN_OBJS) $(DAEMON_GEN_HEADERS) daemon-maintainer-clean: - -include daemon/test/Makefile diff --git a/daemon/chaintopology.c b/daemon/chaintopology.c index 8c33ee8b3..c36082d30 100644 --- a/daemon/chaintopology.c +++ b/daemon/chaintopology.c @@ -5,7 +5,6 @@ #include "jsonrpc.h" #include "lightningd.h" #include "log.h" -#include "peer.h" #include "timeout.h" #include "utils.h" #include "watch.h" diff --git a/daemon/channel.c b/daemon/channel.c deleted file mode 100644 index 7170678c7..000000000 --- a/daemon/channel.c +++ /dev/null @@ -1,359 +0,0 @@ -#include "channel.h" -#include "htlc.h" -#include "remove_dust.h" -#include "type_to_string.h" -#include -#include -#include -#include -#include -#include -#include - -uint64_t fee_by_feerate(size_t txsize, uint64_t fee_rate) -{ - /* FIXME-OLD #2: - * - * The fee for a transaction MUST be calculated by multiplying this - * bytecount by the fee rate, dividing by 1000 and truncating - * (rounding down) the result to an even number of satoshis. - */ - return txsize * fee_rate / 2000 * 2; -} - -/* FIXME-OLD #2: - * - * A node MUST use the formula 338 + 32 bytes for every non-dust HTLC - * as the bytecount for calculating commitment transaction fees. Note - * that the fee requirement is unchanged, even if the elimination of - * dust HTLC outputs has caused a non-zero fee already. - */ -static size_t tx_bytes(size_t num_nondust_htlcs) -{ - return 338 + 32 * num_nondust_htlcs; -} - -static uint64_t calculate_fee_msat(size_t num_nondust_htlcs, - uint64_t fee_rate) -{ - /* milli-satoshis */ - return fee_by_feerate(tx_bytes(num_nondust_htlcs), fee_rate) * 1000; -} - -/* Pay this much fee, if possible. Return amount unpaid. */ -static uint64_t pay_fee(struct channel_oneside *side, uint64_t fee_msat) -{ - if (side->pay_msat >= fee_msat) { - side->pay_msat -= fee_msat; - side->fee_msat += fee_msat; - return 0; - } else { - uint64_t remainder = fee_msat - side->pay_msat; - side->fee_msat += side->pay_msat; - side->pay_msat = 0; - return remainder; - } -} - -/* Charge the fee as per FIXME-OLD #2 */ -static void recalculate_fees(struct channel_oneside *a, - struct channel_oneside *b, - uint64_t fee_msat) -{ - uint64_t remainder; - - /* Fold in fees, to recalcuate again below. */ - a->pay_msat += a->fee_msat; - b->pay_msat += b->fee_msat; - a->fee_msat = b->fee_msat = 0; - - /* FIXME-OLD #2: - * - * 1. If each nodes can afford half the fee from their - * to-`final_key` output, reduce the two to-`final_key` - * outputs accordingly. - * - * 2. Otherwise, reduce the to-`final_key` output of one node - * which cannot afford the fee to zero (resulting in that - * entire output paying fees). If the remaining - * to-`final_key` output is greater than the fee remaining, - * reduce it accordingly, otherwise reduce it to zero to - * pay as much fee as possible. - */ - remainder = pay_fee(a, fee_msat / 2) + pay_fee(b, fee_msat / 2); - - /* If there's anything left, the other side tries to pay for it. */ - remainder = pay_fee(a, remainder); - pay_fee(b, remainder); -} - -/* a transfers htlc_msat to a HTLC (gains it, if -ve) */ -static bool change_funding(uint64_t anchor_satoshis, - uint64_t fee_rate, - int64_t htlc_msat, - struct channel_oneside *a, - struct channel_oneside *b, - size_t num_nondust_htlcs, - bool must_afford_fee) -{ - uint64_t fee_msat; - uint64_t htlcs_total; - - htlcs_total = anchor_satoshis * 1000 - - (a->pay_msat + a->fee_msat + b->pay_msat + b->fee_msat); - - fee_msat = calculate_fee_msat(num_nondust_htlcs, fee_rate); - - /* If A is paying, can it afford it? */ - if (htlc_msat >= 0) { - uint64_t cost = htlc_msat; - if (must_afford_fee) - cost += fee_msat / 2; - if (cost > a->pay_msat + a->fee_msat) - return false; - } - - /* OK, now adjust funds for A, then recalculate fees. */ - a->pay_msat -= htlc_msat; - recalculate_fees(a, b, fee_msat); - - htlcs_total += htlc_msat; - assert(htlcs_total == anchor_satoshis * 1000 - - (a->pay_msat + a->fee_msat + b->pay_msat + b->fee_msat)); - return true; -} - -bool anchor_too_large(uint64_t anchor_satoshis) -{ - /* Anchor must fit in 32 bit. */ - return anchor_satoshis >= (1ULL << 32) / 1000; -} - -struct channel_state *initial_cstate(const tal_t *ctx, - uint64_t anchor_satoshis, - uint64_t fee_rate, - enum side funding) -{ - uint64_t fee_msat; - struct channel_state *cstate = talz(ctx, struct channel_state); - struct channel_oneside *funder, *fundee; - - cstate->fee_rate = fee_rate; - cstate->anchor = anchor_satoshis; - cstate->num_nondust = 0; - - /* Anchor must fit in 32 bit. */ - assert(!anchor_too_large(anchor_satoshis)); - - fee_msat = calculate_fee_msat(0, fee_rate); - if (fee_msat > anchor_satoshis * 1000) - return tal_free(cstate); - - funder = &cstate->side[funding]; - fundee = &cstate->side[!funding]; - - /* Neither side has HTLCs. */ - funder->num_htlcs = fundee->num_htlcs = 0; - - /* Initially, all goes back to funder. */ - funder->pay_msat = anchor_satoshis * 1000 - fee_msat; - funder->fee_msat = fee_msat; - - /* Make sure it checks out. */ - assert(change_funding(anchor_satoshis, fee_rate, 0, funder, fundee, 0, false)); - assert(funder->fee_msat == fee_msat); - assert(fundee->fee_msat == 0); - - return cstate; -} - -/* FIXME: Write exact variant! */ -uint64_t approx_max_feerate(const struct channel_state *cstate, - enum side side) -{ - uint64_t max_funds; - - max_funds = cstate->side[side].pay_msat + cstate->side[side].fee_msat; - - return max_funds / tx_bytes(cstate->num_nondust); -} - -bool can_afford_feerate(const struct channel_state *cstate, uint64_t fee_rate, - enum side side) -{ - u64 fee_msat = calculate_fee_msat(cstate->num_nondust, fee_rate); - - return cstate->side[side].pay_msat + cstate->side[side].fee_msat - >= fee_msat; -} - -void adjust_fee(struct channel_state *cstate, uint64_t fee_rate) -{ - uint64_t fee_msat; - - fee_msat = calculate_fee_msat(cstate->num_nondust, fee_rate); - - recalculate_fees(&cstate->side[LOCAL], &cstate->side[REMOTE], fee_msat); -} - -bool force_fee(struct channel_state *cstate, uint64_t fee) -{ - /* Beware overflow! */ - if (fee > 0xFFFFFFFFFFFFFFFFULL / 1000) - return false; - recalculate_fees(&cstate->side[LOCAL], &cstate->side[REMOTE], fee * 1000); - return cstate->side[LOCAL].fee_msat + cstate->side[REMOTE].fee_msat == fee * 1000; -} - -/* Add a HTLC to @creator if it can afford it. */ -bool cstate_add_htlc(struct channel_state *cstate, const struct htlc *htlc, - bool must_afford_fee) -{ - size_t nondust; - struct channel_oneside *creator, *recipient; - - creator = &cstate->side[htlc_owner(htlc)]; - recipient = &cstate->side[!htlc_owner(htlc)]; - - /* Remember to count the new one in total txsize if not dust! */ - nondust = cstate->num_nondust; - if (!is_dust(htlc->msatoshi / 1000)) - nondust++; - - if (!change_funding(cstate->anchor, cstate->fee_rate, - htlc->msatoshi, creator, recipient, nondust, - must_afford_fee)) - return false; - - cstate->num_nondust = nondust; - creator->num_htlcs++; - return true; -} - -/* Remove htlc from creator, credit it to beneficiary. */ -static void remove_htlc(struct channel_state *cstate, - enum side creator, - enum side beneficiary, - const struct htlc *htlc) -{ - size_t nondust; - - /* Remember to remove this one in total txsize if not dust! */ - nondust = cstate->num_nondust; - if (!is_dust(htlc->msatoshi / 1000)) { - assert(nondust > 0); - nondust--; - } - - /* Can't fail since msatoshi is positive. */ - if (!change_funding(cstate->anchor, cstate->fee_rate, - -(int64_t)htlc->msatoshi, - &cstate->side[beneficiary], - &cstate->side[!beneficiary], nondust, false)) - abort(); - - /* Actually remove the HTLC. */ - assert(cstate->side[creator].num_htlcs > 0); - cstate->side[creator].num_htlcs--; - cstate->num_nondust = nondust; -} - -void cstate_fail_htlc(struct channel_state *cstate, const struct htlc *htlc) -{ - remove_htlc(cstate, htlc_owner(htlc), htlc_owner(htlc), htlc); -} - -void cstate_fulfill_htlc(struct channel_state *cstate, const struct htlc *htlc) -{ - remove_htlc(cstate, htlc_owner(htlc), !htlc_owner(htlc), htlc); -} - -struct channel_state *copy_cstate(const tal_t *ctx, - const struct channel_state *cstate) -{ - return tal_dup(ctx, struct channel_state, cstate); -} - -void force_add_htlc(struct channel_state *cstate, const struct htlc *htlc) -{ - struct channel_oneside *creator; - - creator = &cstate->side[htlc_owner(htlc)]; - creator->num_htlcs++; - creator->pay_msat -= htlc->msatoshi; - - /* Remember to count the new one in total txsize if not dust! */ - if (!is_dust(htlc->msatoshi / 1000)) - cstate->num_nondust++; -} - -static void force_remove_htlc(struct channel_state *cstate, - enum side beneficiary, - const struct htlc *htlc) -{ - cstate->side[beneficiary].pay_msat += htlc->msatoshi; - cstate->side[htlc_owner(htlc)].num_htlcs--; - if (!is_dust(htlc->msatoshi / 1000)) - cstate->num_nondust--; -} - -void force_fail_htlc(struct channel_state *cstate, const struct htlc *htlc) -{ - force_remove_htlc(cstate, htlc_owner(htlc), htlc); -} - -void force_fulfill_htlc(struct channel_state *cstate, const struct htlc *htlc) -{ - force_remove_htlc(cstate, !htlc_owner(htlc), htlc); -} - -bool balance_after_force(struct channel_state *cstate) -{ - /* We should not spend more than anchor */ - if (cstate->side[LOCAL].pay_msat + cstate->side[REMOTE].pay_msat - > cstate->anchor * 1000) - return false; - - /* Check for wrap. */ - if (cstate->side[LOCAL].pay_msat > cstate->anchor * 1000) - return false; - if (cstate->side[REMOTE].pay_msat > cstate->anchor * 1000) - return false; - - if (cstate->num_nondust - > cstate->side[LOCAL].num_htlcs + cstate->side[REMOTE].num_htlcs) - return false; - - /* Recalc fees. */ - adjust_fee(cstate, cstate->fee_rate); - return true; -} - -static char *fmt_channel_oneside(const tal_t *ctx, - const struct channel_oneside *co) -{ - return tal_fmt(ctx, "{ pay_msat=%u" - " fee_msat=%u" - " num_htlcs=%u }", - co->pay_msat, - co->fee_msat, - co->num_htlcs); -} - -static char *fmt_channel_state(const tal_t *ctx, - const struct channel_state *cs) -{ - return tal_fmt(ctx, "{ anchor=%"PRIu64 - " fee_rate=%"PRIu64 - " num_nondust=%u" - " ours=%s" - " theirs=%s }", - cs->anchor, - cs->fee_rate, - cs->num_nondust, - fmt_channel_oneside(ctx, &cs->side[LOCAL]), - fmt_channel_oneside(ctx, &cs->side[REMOTE])); -} - -REGISTER_TYPE_TO_STRING(channel_oneside, fmt_channel_oneside); -REGISTER_TYPE_TO_STRING(channel_state, fmt_channel_state); diff --git a/daemon/channel.h b/daemon/channel.h deleted file mode 100644 index ca199389d..000000000 --- a/daemon/channel.h +++ /dev/null @@ -1,140 +0,0 @@ -#ifndef LIGHTNING_DAEMON_CHANNEL_H -#define LIGHTNING_DAEMON_CHANNEL_H -#include "config.h" -#include "bitcoin/locktime.h" -#include "daemon/htlc.h" -#include -#include -#include -#include - -struct channel_oneside { - /* Payment and fee is in millisatoshi. */ - uint32_t pay_msat, fee_msat; - /* Number of HTLCs (required for limiting total number) */ - unsigned int num_htlcs; -}; - -struct channel_state { - /* Satoshis paid by anchor. */ - uint64_t anchor; - /* Satoshis per 1000 bytes. */ - uint64_t fee_rate; - /* Number of non-dust htlcs (to calculate txsize) */ - unsigned int num_nondust; - struct channel_oneside side[2]; -}; - -/** - * initial_cstate: Given initial fees and funding anchor, what is initial state? - * @ctx: tal context to allocate return value from. - * @anchor_satoshis: The anchor amount. - * @fee_rate: amount to pay in fees per kb (in satoshi). - * @dir: which side paid for the anchor. - * - * Returns state, or NULL if malformed. - */ -struct channel_state *initial_cstate(const tal_t *ctx, - uint64_t anchor_satoshis, - uint64_t fee_rate, - enum side side); - -/** - * copy_cstate: Make a deep copy of channel_state - * @ctx: tal context to allocate return value from. - * @cstate: state to copy. - */ -struct channel_state *copy_cstate(const tal_t *ctx, - const struct channel_state *cstate); - -/** - * cstate_add_htlc: append an HTLC to cstate if it can afford it - * @cstate: The channel state - * @htlc: the htlc pointer. - * @must_afford_fee: true if payer must meet fee. - * - * If that direction can't afford the HTLC this will return false and - * leave @cstate unchanged. If @must_afford_fee is true, and the - * direction can't afford its half of the fees, it will also return - * false and leave @cstate unchanged. Otherwise, pay_msat and fee_msat - * are adjusted accordingly; true is returned. - */ -bool cstate_add_htlc(struct channel_state *cstate, const struct htlc *htlc, - bool must_afford_fee); - -/** - * cstate_fail_htlc: remove an HTLC, funds to the side which offered it. - * @cstate: The channel state - * @htlc: the htlc to remove. - * - * This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit - * the value of the HTLC (back) to cstate->side[dir]. - */ -void cstate_fail_htlc(struct channel_state *cstate, const struct htlc *htlc); - -/** - * cstate_fulfill_htlc: remove an HTLC, funds to side which accepted it. - * @cstate: The channel state - * @htlc: the htlc to remove - * - * This will remove the @index'th entry in cstate->side[dir].htlcs[], and credit - * the value of the HTLC to cstate->side[!dir]. - */ -void cstate_fulfill_htlc(struct channel_state *cstate, const struct htlc *htlc); - -/** - * approx_max_feerate: what's the most side could raise fee rate to? - * @cstate: The channel state - * @side: LOCAL or REMOTE - * - * This is not exact! To check if their offer is valid, use can_afford_feerate. - */ -uint64_t approx_max_feerate(const struct channel_state *cstate, - enum side side); - -/** - * can_afford_feerate: could this side pay for the fee if changed to fee_rate? - * @cstate: The channel state - * @fee_rate: the new fee rate proposed - * @side: LOCAL or REMOTE - */ -bool can_afford_feerate(const struct channel_state *cstate, uint64_t fee_rate, - enum side side); - -/** - * adjust_fee: Change fee rate. - * @cstate: The channel state - * @fee_rate: fee in satoshi per 1000 bytes. - */ -void adjust_fee(struct channel_state *cstate, uint64_t fee_rate); - -/** - * force_fee: Change fee to a specific value. - * @cstate: The channel state - * @fee: fee in satoshi. - * - * This is used for the close transaction, which specifies an exact fee. - * If the fee cannot be paid in full, this return false (but cstate will - * still be altered). - */ -bool force_fee(struct channel_state *cstate, uint64_t fee); - -/** - * fee_for_feerate: calculate the fee (in satoshi) for a given fee_rate. - * @txsize: transaction size in bytes. - * @fee_rate: satoshi per 1000 bytes. - */ -uint64_t fee_by_feerate(size_t txsize, uint64_t fee_rate); - -/** - * anchor_too_large: does anchor amount fit in 32-bits of millisatoshi. - * @anchor_satoshis: amount in satoshis - */ -bool anchor_too_large(uint64_t anchor_satoshis); - -/* Routines to db to force HTLC changes out-of-order which may wrap. */ -void force_add_htlc(struct channel_state *cstate, const struct htlc *htlc); -void force_fail_htlc(struct channel_state *cstate, const struct htlc *htlc); -void force_fulfill_htlc(struct channel_state *cstate, const struct htlc *htlc); -bool balance_after_force(struct channel_state *cstate); -#endif /* LIGHTNING_DAEMON_CHANNEL_H */ diff --git a/daemon/commit_tx.c b/daemon/commit_tx.c deleted file mode 100644 index bdb3e0a51..000000000 --- a/daemon/commit_tx.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "bitcoin/locktime.h" -#include "bitcoin/pubkey.h" -#include "bitcoin/script.h" -#include "bitcoin/shadouble.h" -#include "bitcoin/tx.h" -#include "channel.h" -#include "commit_tx.h" -#include "htlc.h" -#include "lightningd.h" -#include "log.h" -#include "overflows.h" -#include "peer.h" -#include "peer_internal.h" -#include "permute_tx.h" -#include "remove_dust.h" -#include "utils.h" -#include -#include - -u8 *wscript_for_htlc(const tal_t *ctx, - const struct peer *peer, - const struct htlc *h, - const struct sha256 *rhash, - enum side side) -{ - const struct peer_visible_state *this_side, *other_side; - u8 *(*fn)(const tal_t *, - const struct pubkey *, const struct pubkey *, - const struct abs_locktime *, const struct rel_locktime *, - const struct sha256 *, const struct sha256 *); - - /* scripts are different for htlcs offered vs accepted */ - if (side == htlc_owner(h)) - fn = bitcoin_redeem_htlc_send; - else - fn = bitcoin_redeem_htlc_recv; - - if (side == LOCAL) { - this_side = &peer->local; - other_side = &peer->remote; - } else { - this_side = &peer->remote; - other_side = &peer->local; - } - - return fn(ctx, - &this_side->finalkey, &other_side->finalkey, - &h->expiry, &this_side->locktime, rhash, &h->rhash); -} - -static size_t count_htlcs(const struct htlc_map *htlcs, int flag) -{ - struct htlc_map_iter it; - struct htlc *h; - size_t n = 0; - - for (h = htlc_map_first(htlcs, &it); h; h = htlc_map_next(htlcs, &it)) { - if (htlc_has(h, flag)) - n++; - } - return n; -} - -u8 *commit_output_to_us(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - u8 **wscript) -{ - u8 *tmp; - if (!wscript) - wscript = &tmp; - - /* Our output to ourself is encumbered by delay. */ - if (side == LOCAL) { - *wscript = bitcoin_redeem_secret_or_delay(ctx, - &peer->local.finalkey, - &peer->remote.locktime, - &peer->remote.finalkey, - rhash); - return scriptpubkey_p2wsh(ctx, *wscript); - } else { - /* Their output to us is a simple p2wpkh */ - *wscript = NULL; - return scriptpubkey_p2wpkh(ctx, &peer->local.finalkey); - } -} - -u8 *commit_output_to_them(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - u8 **wscript) -{ - u8 *tmp; - if (!wscript) - wscript = &tmp; - - /* Their output to themselves is encumbered by delay. */ - if (side == REMOTE) { - *wscript = bitcoin_redeem_secret_or_delay(ctx, - &peer->remote.finalkey, - &peer->local.locktime, - &peer->local.finalkey, - rhash); - return scriptpubkey_p2wsh(ctx, *wscript); - } else { - /* Our output to them is a simple p2wpkh */ - *wscript = NULL; - return scriptpubkey_p2wpkh(ctx, &peer->remote.finalkey); - } -} - -/* Takes ownership of script. */ -static bool add_output(struct bitcoin_tx *tx, u8 *script, u64 amount, - size_t *output_count, - u64 *total) -{ - assert(*output_count < tal_count(tx->output)); - if (is_dust(amount)) - return false; - tx->output[*output_count].script = tal_steal(tx, script); - tx->output[*output_count].amount = amount; - (*output_count)++; - (*total) += amount; - return true; -} - -struct bitcoin_tx *create_commit_tx(const tal_t *ctx, - struct peer *peer, - const struct sha256 *rhash, - const struct channel_state *cstate, - enum side side, - bool *otherside_only) -{ - const tal_t *tmpctx = tal_tmpctx(ctx); - struct bitcoin_tx *tx; - uint64_t total = 0; - struct htlc_map_iter it; - struct htlc *h; - size_t output_count; - bool pays_to[2]; - int committed_flag = HTLC_FLAG(side,HTLC_F_COMMITTED); - - /* Now create commitment tx: one input, two outputs (plus htlcs) */ - tx = bitcoin_tx(ctx, 1, 2 + count_htlcs(&peer->htlcs, committed_flag)); - - log_debug(peer->log, "Creating commitment tx:"); - log_add_struct(peer->log, " rhash = %s", struct sha256, rhash); - log_add_struct(peer->log, " My finalkey = %s", struct pubkey, - &peer->local.finalkey); - log_add_struct(peer->log, " Their finalkey = %s", struct pubkey, - &peer->remote.finalkey); - log_add_struct(peer->log, " My locktime = %s", struct rel_locktime, - &peer->local.locktime); - log_add_struct(peer->log, " Their locktime = %s", struct rel_locktime, - &peer->remote.locktime); - - /* Our input spends the anchor tx output. */ - tx->input[0].txid = peer->anchor.txid; - tx->input[0].index = peer->anchor.index; - tx->input[0].amount = tal_dup(tx->input, u64, &peer->anchor.satoshis); - - output_count = 0; - pays_to[LOCAL] = add_output(tx, commit_output_to_us(tmpctx, peer, rhash, - side, NULL), - cstate->side[LOCAL].pay_msat / 1000, - &output_count, - &total); - if (pays_to[LOCAL]) - log_debug(peer->log, "Pays %u to local: %s", - cstate->side[LOCAL].pay_msat / 1000, - tal_hex(tmpctx, tx->output[output_count-1].script)); - else - log_debug(peer->log, "DOES NOT pay %u to local", - cstate->side[LOCAL].pay_msat / 1000); - pays_to[REMOTE] = add_output(tx, commit_output_to_them(tmpctx, peer, - rhash, side, - NULL), - cstate->side[REMOTE].pay_msat / 1000, - &output_count, - &total); - if (pays_to[REMOTE]) - log_debug(peer->log, "Pays %u to remote: %s", - cstate->side[REMOTE].pay_msat / 1000, - tal_hex(tmpctx, tx->output[output_count-1].script)); - else - log_debug(peer->log, "DOES NOT pay %u to remote", - cstate->side[REMOTE].pay_msat / 1000); - - /* If their tx doesn't pay to them, or our tx doesn't pay to us... */ - *otherside_only = !pays_to[side]; - - /* First two outputs done, now for the HTLCs. */ - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - const u8 *wscript; - - if (!htlc_has(h, committed_flag)) - continue; - wscript = wscript_for_htlc(tmpctx, peer, h, rhash, side); - /* If we pay any HTLC, it's txout is not just to other side. */ - if (add_output(tx, scriptpubkey_p2wsh(tmpctx, wscript), - h->msatoshi / 1000, &output_count, &total)) { - *otherside_only = false; - log_debug(peer->log, "Pays %"PRIu64" to htlc %"PRIu64, - h->msatoshi / 1000, h->id); - log_add_struct(peer->log, " expiry %s", - struct abs_locktime, &h->expiry); - log_add_struct(peer->log, " rhash %s", struct sha256, - &h->rhash); - log_debug(peer->log, "Script: %s", - tal_hex(tmpctx, wscript)); - } else - log_debug(peer->log, "DOES NOT pay %"PRIu64" to htlc %"PRIu64, - h->msatoshi / 1000, h->id); - } - assert(total <= peer->anchor.satoshis); - - tal_resize(&tx->output, output_count); - permute_outputs(tx->output, tal_count(tx->output), NULL); - tal_free(tmpctx); - return tx; -} diff --git a/daemon/commit_tx.h b/daemon/commit_tx.h deleted file mode 100644 index c1ab61db1..000000000 --- a/daemon/commit_tx.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef LIGHTNING_COMMIT_TX_H -#define LIGHTNING_COMMIT_TX_H -#include "config.h" -#include "htlc.h" -#include - -struct channel_state; -struct sha256; -struct pubkey; -struct peer; - -u8 *wscript_for_htlc(const tal_t *ctx, - const struct peer *peer, - const struct htlc *h, - const struct sha256 *rhash, - enum side side); - -/* Returns scriptpubkey: *wscript is NULL if it's a direct p2wpkh. */ -u8 *commit_output_to_us(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - u8 **wscript); - -/* Returns scriptpubkey: *wscript is NULL if it's a direct p2wpkh. */ -u8 *commit_output_to_them(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - u8 **wscript); - -/* Create commitment tx to spend the anchor tx output; doesn't fill in - * input scriptsig. */ -struct bitcoin_tx *create_commit_tx(const tal_t *ctx, - struct peer *peer, - const struct sha256 *rhash, - const struct channel_state *cstate, - enum side side, - bool *otherside_only); -#endif diff --git a/daemon/cryptopkt.c b/daemon/cryptopkt.c deleted file mode 100644 index 651007821..000000000 --- a/daemon/cryptopkt.c +++ /dev/null @@ -1,656 +0,0 @@ -#include "bitcoin/shadouble.h" -#include "bitcoin/signature.h" -#include "cryptopkt.h" -#include "lightning.pb-c.h" -#include "lightningd.h" -#include "log.h" -#include "names.h" -#include "peer.h" -#include "peer_internal.h" -#include "protobuf_convert.h" -#include "secrets.h" -#include "utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX_PKT_LEN (1024 * 1024) - -/* FIXME-OLD#1: - `length` is a 4-byte little-endian field indicating the size of the unencrypted body. - */ - -struct crypto_pkt { - le32 length; - u8 auth_tag[crypto_aead_chacha20poly1305_ABYTES]; - - /* ... contents... */ - u8 data[]; -}; - -/* Temporary structure for negotiation */ -struct key_negotiate { - struct lightningd_state *dstate; - - /* Our session secret key. */ - u8 seckey[32]; - - /* Our pubkey, their pubkey. */ - le32 keylen; - u8 our_sessionpubkey[33], their_sessionpubkey[33]; - - /* After DH key exchange, we create io_data to check auth. */ - struct io_data *iod; - - /* Logging structure we're using. */ - struct log *log; - - /* Did we expect a particular ID? */ - const struct pubkey *expected_id; - - /* Callback once it's all done. */ - struct io_plan *(*cb)(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - void *arg); - void *arg; -}; - -struct enckey { - struct sha256 k; -}; - - -/* FIXME-OLD #1: - * * sending-key: SHA256(shared-secret || sending-node-session-pubkey) - * * receiving-key: SHA256(shared-secret || receiving-node-session-pubkey) - */ -static struct enckey enckey_from_secret(const unsigned char secret[32], - const unsigned char serial_pubkey[33]) -{ - struct sha256_ctx ctx; - struct enckey enckey; - - sha256_init(&ctx); - sha256_update(&ctx, memcheck(secret, 32), 32); - sha256_update(&ctx, memcheck(serial_pubkey, 33), 33); - sha256_done(&ctx, &enckey.k); - - return enckey; -} - -struct dir_state { - u64 nonce; - struct enckey enckey; - - /* Current packet (encrypted). */ - struct crypto_pkt *cpkt; - size_t pkt_len; -}; - -static void setup_crypto(struct dir_state *dir, - u8 shared_secret[32], u8 serial_pubkey[33]) -{ - /* FIXME-OLD #1: Nonces...MUST begin at 0 */ - dir->nonce = 0; - - dir->enckey = enckey_from_secret(shared_secret, serial_pubkey); - - dir->cpkt = NULL; -} - -struct io_data { - /* Stuff we need to keep around to talk to peer. */ - struct dir_state in, out; - - /* Callback once packet decrypted. */ - struct io_plan *(*cb)(struct io_conn *, struct peer *); - - /* Once peer is assigned, this is set. */ - struct peer *peer; - - /* Length we're currently reading. */ - struct crypto_pkt hdr_in; -}; - -static void *proto_tal_alloc(void *allocator_data, size_t size) -{ - return tal_arr(allocator_data, char, size); -} - -static void proto_tal_free(void *allocator_data, void *pointer) -{ - tal_free(pointer); -} - -static void le64_nonce(unsigned char *npub, u64 nonce) -{ - /* FIXME-OLD #1: Nonces are 64-bit little-endian numbers */ - le64 le_nonce = cpu_to_le64(nonce); - memcpy(npub, &le_nonce, sizeof(le_nonce)); - BUILD_ASSERT(crypto_aead_chacha20poly1305_NPUBBYTES == sizeof(le_nonce)); -} - -/* Encrypts data..data + len - 1 inclusive into data..data + len - 1 and - * then writes the authentication tag at data+len. - * - * This increments nonce every time. - */ -static void encrypt_in_place(void *data, size_t len, - u64 *nonce, const struct enckey *enckey) -{ - int ret; - unsigned long long clen; - unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES]; - - le64_nonce(npub, *nonce); - ret = crypto_aead_chacha20poly1305_encrypt(data, &clen, - memcheck(data, len), len, - NULL, 0, NULL, - npub, enckey->k.u.u8); - assert(ret == 0); - assert(clen == len + crypto_aead_chacha20poly1305_ABYTES); - (*nonce)++; -} - -/* Checks authentication tag at data+len, then - * decrypts data..data + len - 1 inclusive into data..data + len - 1. - * - * This increments nonce every time. - */ -static bool decrypt_in_place(void *data, size_t len, - u64 *nonce, const struct enckey *enckey) -{ - int ret; - unsigned long long mlen; - unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES]; - - le64_nonce(npub, *nonce); - mlen = len + crypto_aead_chacha20poly1305_ABYTES; - - ret = crypto_aead_chacha20poly1305_decrypt(data, &mlen, NULL, - memcheck(data, mlen), mlen, - NULL, 0, - npub, enckey->k.u.u8); - if (ret == 0) { - assert(mlen == len); - (*nonce)++; - return true; - } - return false; -} - -static Pkt *decrypt_body(const tal_t *ctx, struct io_data *iod, struct log *log) -{ - struct ProtobufCAllocator prototal; - Pkt *ret; - size_t data_len = le32_to_cpu(iod->hdr_in.length); - - if (!decrypt_in_place(iod->in.cpkt->data, data_len, - &iod->in.nonce, &iod->in.enckey)) { - /* Free encrypted packet. */ - iod->in.cpkt = tal_free(iod->in.cpkt); - log_unusual(log, "Body decryption failed"); - return NULL; - } - - /* De-protobuf it. */ - prototal.alloc = proto_tal_alloc; - prototal.free = proto_tal_free; - prototal.allocator_data = tal(ctx, char); - - ret = pkt__unpack(&prototal, data_len, iod->in.cpkt->data); - if (!ret) { - log_unusual(log, "Packet failed to unpack!"); - tal_free(prototal.allocator_data); - } else { - /* Make sure packet owns contents */ - tal_steal(ctx, ret); - tal_steal(ret, prototal.allocator_data); - - log_debug(log, "Received packet LEN=%zu, type=%s", - data_len, - ret->pkt_case == PKT__PKT_AUTH ? "PKT_AUTH" - : pkt_name(ret->pkt_case)); - } - - /* Free encrypted packet. */ - iod->in.cpkt = tal_free(iod->in.cpkt); - - return ret; -} - -static struct crypto_pkt *encrypt_pkt(struct io_data *iod, const Pkt *pkt, - size_t *totlen) -{ - struct crypto_pkt *cpkt; - size_t len; - - len = pkt__get_packed_size(pkt); - *totlen = sizeof(*cpkt) + len + crypto_aead_chacha20poly1305_ABYTES; - - cpkt = (struct crypto_pkt *)tal_arr(iod, char, *totlen); - cpkt->length = cpu_to_le32(len); - - /* Encrypt header. */ - encrypt_in_place(cpkt, sizeof(cpkt->length), - &iod->out.nonce, &iod->out.enckey); - - /* Encrypt body. */ - pkt__pack(pkt, cpkt->data); - encrypt_in_place(cpkt->data, len, &iod->out.nonce, &iod->out.enckey); - - return cpkt; -} - -static struct io_plan *recv_body(struct io_conn *conn, struct peer *peer) -{ - struct io_data *iod = peer->io_data; - - assert(!peer->inpkt); - - /* We have full packet. */ - peer->inpkt = decrypt_body(iod, iod, peer->log); - if (!peer->inpkt) - return io_close(conn); - - return iod->cb(conn, peer); -} - -static bool decrypt_header(struct log *log, struct io_data *iod, - size_t *body_len) -{ - /* We have length: Check it. */ - if (!decrypt_in_place(&iod->hdr_in.length, sizeof(iod->hdr_in.length), - &iod->in.nonce, &iod->in.enckey)) { - log_unusual(log, "Header decryption failed"); - return false; - } - log_debug(log, "Decrypted header len %u", - le32_to_cpu(iod->hdr_in.length)); - - /* FIXME-OLD #1: `length` MUST NOT exceed 1MB (1048576 bytes). */ - if (le32_to_cpu(iod->hdr_in.length) > MAX_PKT_LEN) { - log_unusual(log, - "Packet overlength: %"PRIu64, - le64_to_cpu(iod->hdr_in.length)); - return false; - } - - /* Allocate room for body, copy header. */ - *body_len = le32_to_cpu(iod->hdr_in.length) - + crypto_aead_chacha20poly1305_ABYTES; - - iod->in.cpkt = (struct crypto_pkt *) - tal_arr(iod, char, sizeof(iod->hdr_in) + *body_len); - *iod->in.cpkt = iod->hdr_in; - return true; -} - -static struct io_plan *recv_header(struct io_conn *conn, struct peer *peer) -{ - struct io_data *iod = peer->io_data; - size_t body_len; - - if (!decrypt_header(peer->log, iod, &body_len)) - return io_close(conn); - - return io_read(conn, iod->in.cpkt->data, body_len, recv_body, peer); -} - -struct io_plan *peer_read_packet(struct io_conn *conn, - struct peer *peer, - struct io_plan *(*cb)(struct io_conn *, - struct peer *)) -{ - struct io_data *iod = peer->io_data; - - iod->cb = cb; - return io_read(conn, &iod->hdr_in, sizeof(iod->hdr_in), - recv_header, peer); -} - -/* Caller must free data! */ -struct io_plan *peer_write_packet(struct io_conn *conn, - struct peer *peer, - const Pkt *pkt, - struct io_plan *(*next)(struct io_conn *, - struct peer *)) -{ - struct io_data *iod = peer->io_data; - size_t totlen; - - /* We free previous packet here, rather than doing indirection - * via io_write */ - tal_free(iod->out.cpkt); - - iod->out.cpkt = encrypt_pkt(iod, pkt, &totlen); - /* Free unencrypted packet. */ - tal_free(pkt); - - return io_write(conn, iod->out.cpkt, totlen, next, peer); -} - -static void *pkt_unwrap(Pkt *inpkt, struct log *log, Pkt__PktCase which) -{ - size_t i; - const ProtobufCMessage *base; - - if (inpkt->pkt_case != which) { - log_unusual(log, "Expected %u, got %u", - which, inpkt->pkt_case); - return NULL; - } - - /* It's a union, and each member starts with base. Pick one */ - base = &inpkt->error->base; - - /* Look for unknown fields. Remember, "It's OK to be odd!" */ - for (i = 0; i < base->n_unknown_fields; i++) { - log_debug(log, "Unknown field in %u: %u", - which, base->unknown_fields[i].tag); - /* Odd is OK */ - if (base->unknown_fields[i].tag & 1) - continue; - log_unusual(log, "Unknown field %u in %u", - base->unknown_fields[i].tag, which); - return NULL; - } - return inpkt->error; -} - -static bool check_proof(struct key_negotiate *neg, struct log *log, - Pkt *inpkt, - const struct pubkey *expected_id, - struct pubkey *id) -{ - struct sha256_double sha; - secp256k1_ecdsa_signature sig; - Authenticate *auth; - - auth = pkt_unwrap(inpkt, log, PKT__PKT_AUTH); - if (!auth) - return false; - - /* FIXME-OLD #1: - * - * The receiving node MUST check that: - * - * 1. `node_id` is the expected value for the sending node. - */ - if (!proto_to_pubkey(auth->node_id, id)) { - log_unusual(log, "Invalid auth id"); - return false; - } - - if (expected_id && !structeq(id, expected_id)) { - log_unusual(log, "Incorrect auth id"); - return false; - } - - /* FIXME-OLD #1: - * - * 2. `session_sig` is a valid secp256k1 ECDSA signature encoded as - * a 32-byte big endian R value, followed by a 32-byte big - * endian S value. - */ - if (!proto_to_signature(auth->session_sig, &sig)) { - log_unusual(log, "Invalid auth signature"); - return false; - } - - - /* FIXME-OLD #1: - * - * 3. `session_sig` is the signature of the SHA256 of SHA256 of the - * its own sessionpubkey, using the secret key corresponding to - * the sender's `node_id`. - */ - sha256_double(&sha, neg->our_sessionpubkey, - sizeof(neg->our_sessionpubkey)); - - if (!check_signed_hash(&sha, &sig, id)) { - log_unusual(log, "Bad auth signature"); - return false; - } - - return true; -} - -static struct io_plan *recv_body_negotiate(struct io_conn *conn, - struct key_negotiate *neg) -{ - struct io_data *iod = neg->iod; - struct io_plan *plan; - Pkt *pkt; - struct pubkey id; - - /* We have full packet. */ - pkt = decrypt_body(neg, iod, neg->log); - if (!pkt) - return io_close(conn); - - if (!check_proof(neg, neg->log, pkt, neg->expected_id, &id)) - return io_close(conn); - - /* Steal so that the callback may not accidentally free it for us */ - tal_steal(NULL, neg); - - plan = neg->cb(conn, neg->dstate, neg->iod, neg->log, &id, neg->arg); - tal_free(neg); - return plan; -} - -static struct io_plan *recv_header_negotiate(struct io_conn *conn, - struct key_negotiate *neg) -{ - size_t body_len; - struct io_data *iod = neg->iod; - - if (!decrypt_header(neg->log, iod, &body_len)) - return io_close(conn); - - return io_read(conn, iod->in.cpkt->data, body_len, recv_body_negotiate, - neg); -} - -static struct io_plan *receive_proof(struct io_conn *conn, - struct key_negotiate *neg) -{ - return io_read(conn, &neg->iod->hdr_in, sizeof(neg->iod->hdr_in), - recv_header_negotiate, neg); -} - -/* Steals w onto the returned Pkt */ -static Pkt *pkt_wrap(const tal_t *ctx, void *w, Pkt__PktCase pkt_case) -{ - Pkt *pkt = tal(ctx, Pkt); - pkt__init(pkt); - pkt->pkt_case = pkt_case; - /* Union, so any will do */ - pkt->error = tal_steal(pkt, w); - return pkt; -} - -static Pkt *authenticate_pkt(const tal_t *ctx, - const struct pubkey *node_id, - const secp256k1_ecdsa_signature *sig) -{ - Authenticate *auth = tal(ctx, Authenticate); - authenticate__init(auth); - auth->node_id = pubkey_to_proto(auth, node_id); - auth->session_sig = signature_to_proto(auth, sig); - return pkt_wrap(ctx, auth, PKT__PKT_AUTH); -} - -static struct io_plan *keys_exchanged(struct io_conn *conn, - struct key_negotiate *neg) -{ - u8 shared_secret[32]; - struct pubkey sessionkey; - secp256k1_ecdsa_signature sig; - Pkt *auth; - size_t totlen; - - if (!pubkey_from_der(neg->their_sessionpubkey, - sizeof(neg->their_sessionpubkey), - &sessionkey)) { - log_unusual_blob(neg->log, "Bad sessionkey %s", - neg->their_sessionpubkey, - sizeof(neg->their_sessionpubkey)); - return io_close(conn); - } - - /* Derive shared secret. */ - if (!secp256k1_ecdh(secp256k1_ctx, shared_secret, - &sessionkey.pubkey, neg->seckey)) { - log_unusual(neg->log, "Bad ECDH"); - return io_close(conn); - } - - /* Each side combines with their OWN session key to SENDING crypto. */ - neg->iod = tal(neg, struct io_data); - setup_crypto(&neg->iod->in, shared_secret, neg->their_sessionpubkey); - setup_crypto(&neg->iod->out, shared_secret, neg->our_sessionpubkey); - - /* FIXME-OLD #1: - * - * `session_sig` is the signature of the SHA256 of SHA256 of the its - * own sessionpubkey, using the secret key corresponding to the - * sender's `node_id`. - */ - privkey_sign(neg->dstate, neg->their_sessionpubkey, - sizeof(neg->their_sessionpubkey), &sig); - - auth = authenticate_pkt(neg, &neg->dstate->id, &sig); - - neg->iod->out.cpkt = encrypt_pkt(neg->iod, auth, &totlen); - return io_write(conn, neg->iod->out.cpkt, totlen, receive_proof, neg); -} - -/* Read and ignore any extra bytes... */ -static struct io_plan *discard_extra(struct io_conn *conn, - struct key_negotiate *neg) -{ - size_t len = le32_to_cpu(neg->keylen); - - /* FIXME-OLD#1: Additional fields MAY be added, and MUST be - * included in the `length` field. These MUST be ignored by - * implementations which do not understand them. */ - if (len > sizeof(neg->their_sessionpubkey)) { - char *discard; - - len -= sizeof(neg->their_sessionpubkey); - discard = tal_arr(neg, char, len); - log_unusual(neg->log, - "Ignoring %zu extra handshake bytes", - len); - return io_read(conn, discard, len, keys_exchanged, neg); - } - - return keys_exchanged(conn, neg); -} - -static struct io_plan *session_key_receive(struct io_conn *conn, - struct key_negotiate *neg) -{ - /* FIXME-OLD#1: The `length` field is the length after the field - itself, and MUST be 33 or greater. */ - if (le32_to_cpu(neg->keylen) < sizeof(neg->their_sessionpubkey)) { - log_unusual(neg->log, "short session key length %u", - le32_to_cpu(neg->keylen)); - return io_close(conn); - } - - /* FIXME-OLD#1: `length` MUST NOT exceed 1MB (1048576 bytes). */ - if (le32_to_cpu(neg->keylen) > 1048576) { - log_unusual(neg->log, - "Oversize session key length %u", - le32_to_cpu(neg->keylen)); - return io_close(conn); - } - - log_debug(neg->log, "Session key length %u", le32_to_cpu(neg->keylen)); - - /* Now read their key. */ - return io_read(conn, neg->their_sessionpubkey, - sizeof(neg->their_sessionpubkey), discard_extra, neg); -} - -static struct io_plan *session_key_len_receive(struct io_conn *conn, - struct key_negotiate *neg) -{ - /* Read the amount of data they will send.. */ - return io_read(conn, &neg->keylen, sizeof(neg->keylen), - session_key_receive, neg); -} - -static void gen_sessionkey(u8 seckey[32], - secp256k1_pubkey *pubkey) -{ - do { - randombytes_buf(seckey, 32); - } while (!secp256k1_ec_pubkey_create(secp256k1_ctx, pubkey, seckey)); -} - -static struct io_plan *write_sessionkey(struct io_conn *conn, - struct key_negotiate *neg) -{ - return io_write(conn, neg->our_sessionpubkey, - sizeof(neg->our_sessionpubkey), - session_key_len_receive, neg); -} - -struct io_plan *peer_crypto_setup_(struct io_conn *conn, - struct lightningd_state *dstate, - const struct pubkey *id, - struct log *log, - struct io_plan *(*cb)(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - void *arg), - void *arg) -{ - size_t outputlen; - secp256k1_pubkey sessionkey; - struct key_negotiate *neg; - - /* FIXME-OLD #1: - * - * The 4-byte length for each message is encrypted separately - * (resulting in a 20 byte header when the authentication tag - * is appended) */ - BUILD_ASSERT(sizeof(struct crypto_pkt) == 20); - - /* We store negotiation state here. */ - neg = tal(conn, struct key_negotiate); - neg->cb = cb; - neg->arg = arg; - neg->dstate = dstate; - neg->expected_id = id; - neg->log = log; - - gen_sessionkey(neg->seckey, &sessionkey); - - outputlen = sizeof(neg->our_sessionpubkey); - secp256k1_ec_pubkey_serialize(secp256k1_ctx, - neg->our_sessionpubkey, &outputlen, - &sessionkey, - SECP256K1_EC_COMPRESSED); - assert(outputlen == sizeof(neg->our_sessionpubkey)); - neg->keylen = cpu_to_le32(sizeof(neg->our_sessionpubkey)); - return io_write(conn, &neg->keylen, sizeof(neg->keylen), - write_sessionkey, neg); -} diff --git a/daemon/cryptopkt.h b/daemon/cryptopkt.h deleted file mode 100644 index ac75759b1..000000000 --- a/daemon/cryptopkt.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef LIGHTNING_DAEMON_CRYPTOPKT_H -#define LIGHTNING_DAEMON_CRYPTOPKT_H -#include "config.h" -#include "lightning.pb-c.h" -#include -#include - -struct io_data; -struct json_connecting; -struct lightningd_state; -struct log; -struct peer; - -struct io_plan *peer_crypto_setup_(struct io_conn *conn, - struct lightningd_state *dstate, - const struct pubkey *id, - struct log *log, - struct io_plan *(*cb)(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - void *arg), - void *arg); - -#define peer_crypto_setup(conn, dstate, id, log_, cb, arg) \ - peer_crypto_setup_((conn), (dstate), (id), (log_), \ - typesafe_cb_preargs(struct io_plan *, void *, \ - (cb), (arg), \ - struct io_conn *, \ - struct lightningd_state *, \ - struct io_data *, \ - struct log *, \ - const struct pubkey *), \ - (arg)) - -/* Reads packet into peer->inpkt/peer->inpkt_len */ -struct io_plan *peer_read_packet(struct io_conn *conn, - struct peer *peer, - struct io_plan *(*cb)(struct io_conn *, - struct peer *)); - -struct io_plan *peer_write_packet(struct io_conn *conn, - struct peer *peer, - const Pkt *pkt, - struct io_plan *(*next)(struct io_conn *, - struct peer *)); -#endif /* LIGHTNING_DAEMON_CRYPTOPKT_H */ diff --git a/daemon/db.c b/daemon/db.c deleted file mode 100644 index 45b4ae514..000000000 --- a/daemon/db.c +++ /dev/null @@ -1,1980 +0,0 @@ -#include "bitcoin/pullpush.h" -#include "commit_tx.h" -#include "db.h" -#include "feechange.h" -#include "gen_version.h" -#include "htlc.h" -#include "invoice.h" -#include "lightningd.h" -#include "log.h" -#include "names.h" -#include "netaddr.h" -#include "pay.h" -#include "peer_internal.h" -#include "routing.h" -#include "secrets.h" -#include "utils.h" -#include "wallet.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DB_FILE "lightning.sqlite3" - -/* They don't use stdint types. */ -#define PRIuSQLITE64 "llu" - -struct db { - bool in_transaction; - const char *err; - sqlite3 *sql; -}; - -static void close_db(struct db *db) -{ - sqlite3_close(db->sql); -} - -/* We want a string, not an 'unsigned char *' thanks! */ -static const char *sqlite3_column_str(sqlite3_stmt *stmt, int iCol) -{ - return cast_signed(const char *, sqlite3_column_text(stmt, iCol)); -} - -#define SQL_U64(var) stringify(var)" BIGINT" /* Actually, an s64 */ -#define SQL_U32(var) stringify(var)" INT" -#define SQL_BOOL(var) stringify(var)" BOOLEAN" -#define SQL_BLOB(var) stringify(var)" BLOB" - -#define SQL_PUBKEY(var) stringify(var)" CHAR(33)" -#define SQL_PRIVKEY(var) stringify(var)" CHAR(32)" -#define SQL_SIGNATURE(var) stringify(var)" CHAR(64)" -#define SQL_TXID(var) stringify(var)" CHAR(32)" -#define SQL_RHASH(var) stringify(var)" CHAR(32)" -#define SQL_SHA256(var) stringify(var)" CHAR(32)" -#define SQL_R(var) stringify(var)" CHAR(32)" -/* STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE == 45*/ -#define SQL_STATENAME(var) stringify(var)" VARCHAR(45)" -#define SQL_INVLABEL(var) stringify(var)" VARCHAR("stringify(INVOICE_MAX_LABEL_LEN)")" - -/* 8 + 4 + (8 + 32) * (64 + 1) */ -#define SHACHAIN_SIZE 2612 -#define SQL_SHACHAIN(var) stringify(var)" CHAR("stringify(SHACHAIN_SIZE)")" - -/* FIXME: Should be fixed size. */ -#define SQL_ROUTING(var) stringify(var)" BLOB" -#define SQL_FAIL(var) stringify(var)" BLOB" - -#define TABLE(tablename, ...) \ - "CREATE TABLE " #tablename " (" CPPMAGIC_JOIN(", ", __VA_ARGS__) ");" - -static const char *sql_bool(bool b) -{ - /* SQL2003 says TRUE and FALSE are binary literal keywords. - * sqlite3 barfs. */ - return (b) ? "1" : "0"; -} - -static bool PRINTF_FMT(3,4) - db_exec(const char *caller, - struct lightningd_state *dstate, const char *fmt, ...) -{ - va_list ap; - char *cmd, *errmsg; - int err; - - if (dstate->db->in_transaction && dstate->db->err) - return false; - - va_start(ap, fmt); - cmd = tal_vfmt(dstate->db, fmt, ap); - va_end(ap); - - err = sqlite3_exec(dstate->db->sql, cmd, NULL, NULL, &errmsg); - if (err != SQLITE_OK) { - tal_free(dstate->db->err); - dstate->db->err = tal_fmt(dstate->db, "%s:%s:%s:%s", - caller, sqlite3_errstr(err), - cmd, errmsg); - sqlite3_free(errmsg); - tal_free(cmd); - log_broken(dstate->base_log, "%s", dstate->db->err); - return false; - } - tal_free(cmd); - return true; -} - -static char *sql_hex_or_null(const tal_t *ctx, const void *buf, size_t len) -{ - char *r; - - if (!buf) - return "NULL"; - r = tal_arr(ctx, char, 3 + hex_str_size(len)); - r[0] = 'x'; - r[1] = '\''; - hex_encode(buf, len, r+2, hex_str_size(len)); - r[2+hex_str_size(len)-1] = '\''; - r[2+hex_str_size(len)] = '\0'; - return r; -} - -static void from_sql_blob(sqlite3_stmt *stmt, int idx, void *p, size_t n) -{ - if (sqlite3_column_bytes(stmt, idx) != n) - fatal("db:wrong bytes %i not %zu", - sqlite3_column_bytes(stmt, idx), n); - memcpy(p, sqlite3_column_blob(stmt, idx), n); -} - -static u8 *tal_sql_blob(const tal_t *ctx, sqlite3_stmt *stmt, int idx) -{ - u8 *p; - - if (sqlite3_column_type(stmt, idx) == SQLITE_NULL) - return NULL; - - p = tal_arr(ctx, u8, sqlite3_column_bytes(stmt, idx)); - from_sql_blob(stmt, idx, p, tal_count(p)); - return p; -} - -static void pubkey_from_sql(sqlite3_stmt *stmt, int idx, struct pubkey *pk) -{ - if (!pubkey_from_der(sqlite3_column_blob(stmt, idx), - sqlite3_column_bytes(stmt, idx), pk)) - fatal("db:bad pubkey length %i", - sqlite3_column_bytes(stmt, idx)); -} - -static void sha256_from_sql(sqlite3_stmt *stmt, int idx, struct sha256 *sha) -{ - from_sql_blob(stmt, idx, sha, sizeof(*sha)); -} - -static void sig_from_sql(sqlite3_stmt *stmt, int idx, - secp256k1_ecdsa_signature *sig) -{ - u8 compact[64]; - - from_sql_blob(stmt, idx, compact, sizeof(compact)); - if (secp256k1_ecdsa_signature_parse_compact(secp256k1_ctx, sig, - compact) != 1) - fatal("db:bad signature blob"); -} - -static char *sig_to_sql(const tal_t *ctx, - const secp256k1_ecdsa_signature *sig) -{ - u8 compact[64]; - - if (!sig) - return sql_hex_or_null(ctx, NULL, 0); - - secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx, compact, - sig); - return sql_hex_or_null(ctx, compact, sizeof(compact)); -} - -static void db_load_wallet(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - - err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM wallet;", -1, - &stmt, NULL); - - if (err != SQLITE_OK) - fatal("db_load_wallet:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct privkey privkey; - if (err != SQLITE_ROW) - fatal("db_load_wallet:step gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - if (sqlite3_column_count(stmt) != 1) - fatal("db_load_wallet:step gave %i cols, not 1", - sqlite3_column_count(stmt)); - from_sql_blob(stmt, 0, &privkey, sizeof(privkey)); - if (!restore_wallet_address(dstate, &privkey)) - fatal("db_load_wallet:bad privkey"); - } - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("db_load_wallet:finalize gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); -} - -void db_add_wallet_privkey(struct lightningd_state *dstate, - const struct privkey *privkey) -{ - char *ctx = tal_tmpctx(dstate); - - log_debug(dstate->base_log, "%s", __func__); - if (!db_exec(__func__, dstate, - "INSERT INTO wallet VALUES (x'%s');", - tal_hexstr(ctx, privkey, sizeof(*privkey)))) - fatal("db_add_wallet_privkey failed"); - tal_free(ctx); -} - -static void load_peer_secrets(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - bool secrets_set = false; - - select = tal_fmt(ctx, - "SELECT * FROM peer_secrets WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_secrets:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - if (err != SQLITE_ROW) - fatal("load_peer_secrets:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - if (secrets_set) - fatal("load_peer_secrets: two secrets for '%s'", - select); - peer_set_secrets_from_db(peer, - sqlite3_column_blob(stmt, 1), - sqlite3_column_bytes(stmt, 1), - sqlite3_column_blob(stmt, 2), - sqlite3_column_bytes(stmt, 2), - sqlite3_column_blob(stmt, 3), - sqlite3_column_bytes(stmt, 3)); - secrets_set = true; - } - - if (!secrets_set) - fatal("load_peer_secrets: no secrets for '%s'", select); - tal_free(ctx); -} - -static void load_peer_anchor(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - bool anchor_set = false; - - select = tal_fmt(ctx, - "SELECT * FROM anchors WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_anchor:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - if (err != SQLITE_ROW) - fatal("load_peer_anchor:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - if (anchor_set) - fatal("load_peer_anchor: two anchors for '%s'", - select); - from_sql_blob(stmt, 1, - &peer->anchor.txid, sizeof(peer->anchor.txid)); - peer->anchor.index = sqlite3_column_int64(stmt, 2); - peer->anchor.satoshis = sqlite3_column_int64(stmt, 3); - peer->anchor.ours = sqlite3_column_int(stmt, 6); - peer_watch_anchor(peer, sqlite3_column_int(stmt, 4)); - peer->anchor.min_depth = sqlite3_column_int(stmt, 5); - anchor_set = true; - } - - if (!anchor_set) - fatal("load_peer_anchor: no anchor for '%s'", select); - tal_free(ctx); -} - -static void load_peer_anchor_input(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - bool anchor_input_set = false; - - select = tal_fmt(ctx, - "SELECT * FROM anchor_inputs WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_anchor_input:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - if (err != SQLITE_ROW) - fatal("load_peer_anchor_input:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - if (anchor_input_set) - fatal("load_peer_anchor_input: two inputs for '%s'", - select); - peer->anchor.input = tal(peer, struct anchor_input); - from_sql_blob(stmt, 1, - &peer->anchor.input->txid, - sizeof(peer->anchor.input->txid)); - peer->anchor.input->index = sqlite3_column_int(stmt, 2); - peer->anchor.input->in_amount = sqlite3_column_int64(stmt, 3); - peer->anchor.input->out_amount = sqlite3_column_int64(stmt, 4); - pubkey_from_sql(stmt, 5, &peer->anchor.input->walletkey); - anchor_input_set = true; - } - - if (!anchor_input_set) - fatal("load_peer_anchor_input: no inputs for '%s'", select); - tal_free(ctx); -} - -static void load_peer_visible_state(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - bool visible_set = false; - - select = tal_fmt(ctx, - "SELECT * FROM their_visible_state WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_visible_state:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - if (err != SQLITE_ROW) - fatal("load_peer_visible_state:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - if (sqlite3_column_count(stmt) != 8) - fatal("load_peer_visible_state:step gave %i cols, not 8", - sqlite3_column_count(stmt)); - - if (visible_set) - fatal("load_peer_visible_state: two states for %s", select); - visible_set = true; - - peer->remote.offer_anchor = sqlite3_column_int(stmt, 1); - pubkey_from_sql(stmt, 2, &peer->remote.commitkey); - pubkey_from_sql(stmt, 3, &peer->remote.finalkey); - peer->remote.locktime.locktime = sqlite3_column_int(stmt, 4); - peer->remote.mindepth = sqlite3_column_int(stmt, 5); - peer->remote.commit_fee_rate = sqlite3_column_int64(stmt, 6); - sha256_from_sql(stmt, 7, &peer->remote.next_revocation_hash); - log_debug(peer->log, "%s:next_revocation_hash=%s", - __func__, - tal_hexstr(ctx, &peer->remote.next_revocation_hash, - sizeof(peer->remote.next_revocation_hash))); - - /* Now we can fill in anchor witnessscript. */ - peer->anchor.witnessscript - = bitcoin_redeem_2of2(peer, - &peer->local.commitkey, - &peer->remote.commitkey); - } - - if (!visible_set) - fatal("load_peer_visible_state: no result '%s'", select); - - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("load_peer_visible_state:finalize gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - tal_free(ctx); -} - -static void load_peer_commit_info(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - - select = tal_fmt(ctx, - "SELECT * FROM commit_info WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_commit_info:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct commit_info **cip, *ci; - - if (err != SQLITE_ROW) - fatal("load_peer_commit_info:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - /* peer "SQL_PUBKEY", side TEXT, commit_num INT, revocation_hash "SQL_SHA256", sig "SQL_SIGNATURE", xmit_order INT, prev_revocation_hash "SQL_SHA256", */ - if (sqlite3_column_count(stmt) != 7) - fatal("load_peer_commit_info:step gave %i cols, not 7", - sqlite3_column_count(stmt)); - - if (streq(sqlite3_column_str(stmt, 1), "LOCAL")) - cip = &peer->local.commit; - else { - if (!streq(sqlite3_column_str(stmt, 1), "REMOTE")) - fatal("load_peer_commit_info:bad side %s", - sqlite3_column_str(stmt, 1)); - cip = &peer->remote.commit; - /* This is a hack where we temporarily store their - * previous revocation hash before we get their - * revocation. */ - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { - peer->their_prev_revocation_hash - = tal(peer, struct sha256); - sha256_from_sql(stmt, 6, - peer->their_prev_revocation_hash); - } - } - - /* Do we already have this one? */ - if (*cip) - fatal("load_peer_commit_info:duplicate side %s", - sqlite3_column_str(stmt, 1)); - - *cip = ci = new_commit_info(peer, sqlite3_column_int64(stmt, 2)); - sha256_from_sql(stmt, 3, &ci->revocation_hash); - ci->order = sqlite3_column_int64(stmt, 4); - - if (sqlite3_column_type(stmt, 5) == SQLITE_NULL) - ci->sig = NULL; - else { - ci->sig = tal(ci, secp256k1_ecdsa_signature); - sig_from_sql(stmt, 5, ci->sig); - } - - /* Set once we have updated HTLCs. */ - ci->cstate = NULL; - ci->tx = NULL; - } - - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("load_peer_commit_info:finalize gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - tal_free(ctx); - - if (!peer->local.commit) - fatal("load_peer_commit_info:no local commit info found"); - if (!peer->remote.commit) - fatal("load_peer_commit_info:no remote commit info found"); -} - -/* Because their HTLCs are not ordered wrt to ours, we can go negative - * and do normally-impossible things in intermediate states. So we - * mangle cstate balances manually. */ -static void apply_htlc(struct channel_state *cstate, const struct htlc *htlc, - enum side side) -{ - const char *sidestr = side_to_str(side); - - if (!htlc_has(htlc, HTLC_FLAG(side,HTLC_F_WAS_COMMITTED))) - return; - - log_debug(htlc->peer->log, " %s committed", sidestr); - force_add_htlc(cstate, htlc); - - if (!htlc_has(htlc, HTLC_FLAG(side, HTLC_F_COMMITTED))) { - log_debug(htlc->peer->log, " %s %s", - sidestr, htlc->r ? "resolved" : "failed"); - if (htlc->r) - force_fulfill_htlc(cstate, htlc); - else - force_fail_htlc(cstate, htlc); - } -} - -/* As we load the HTLCs, we apply them to get the final channel_state. - * We also get the last used htlc id. - * This is slow, but sure. */ -static void load_peer_htlcs(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - const char *select; - bool to_them_only, to_us_only; - - select = tal_fmt(ctx, - "SELECT * FROM htlcs WHERE peer = x'%s' ORDER BY id;", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_htlcs:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - peer->local.commit->cstate = initial_cstate(peer->local.commit, - peer->anchor.satoshis, - peer->local.commit_fee_rate, - peer->local.offer_anchor ? - LOCAL : REMOTE); - peer->remote.commit->cstate = initial_cstate(peer->remote.commit, - peer->anchor.satoshis, - peer->remote.commit_fee_rate, - peer->local.offer_anchor ? - LOCAL : REMOTE); - - /* We rebuild cstate by running *every* HTLC through. */ - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct htlc *htlc; - struct sha256 rhash; - enum htlc_state hstate; - - if (err != SQLITE_ROW) - fatal("load_peer_htlcs:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - if (sqlite3_column_count(stmt) != 11) - fatal("load_peer_htlcs:step gave %i cols, not 11", - sqlite3_column_count(stmt)); - sha256_from_sql(stmt, 5, &rhash); - - hstate = htlc_state_from_name(sqlite3_column_str(stmt, 2)); - if (hstate == HTLC_STATE_INVALID) - fatal("load_peer_htlcs:invalid state %s", - sqlite3_column_str(stmt, 2)); - htlc = peer_new_htlc(peer, - sqlite3_column_int64(stmt, 1), - sqlite3_column_int64(stmt, 3), - &rhash, - sqlite3_column_int64(stmt, 4), - sqlite3_column_blob(stmt, 7), - sqlite3_column_bytes(stmt, 7), - NULL, - hstate); - - if (sqlite3_column_type(stmt, 6) != SQLITE_NULL) { - htlc->r = tal(htlc, struct preimage); - from_sql_blob(stmt, 6, htlc->r, sizeof(*htlc->r)); - } - if (sqlite3_column_type(stmt, 10) != SQLITE_NULL) { - htlc->fail = tal_sql_blob(htlc, stmt, 10); - } - - if (htlc->r && htlc->fail) - fatal("%s HTLC %"PRIu64" has failed and fulfilled?", - htlc_owner(htlc) == LOCAL ? "local" : "remote", - htlc->id); - - log_debug(peer->log, "Loaded %s HTLC %"PRIu64" (%s)", - htlc_owner(htlc) == LOCAL ? "local" : "remote", - htlc->id, htlc_state_name(htlc->state)); - - if (htlc_owner(htlc) == LOCAL - && htlc->id >= peer->htlc_id_counter) - peer->htlc_id_counter = htlc->id + 1; - - /* Update cstate with this HTLC. */ - apply_htlc(peer->local.commit->cstate, htlc, LOCAL); - apply_htlc(peer->remote.commit->cstate, htlc, REMOTE); - } - - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("load_peer_htlcs:finalize gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - /* Now set any in-progress fee changes. */ - select = tal_fmt(ctx, - "SELECT * FROM feechanges WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_htlcs:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - enum feechange_state feechange_state; - - if (err != SQLITE_ROW) - fatal("load_peer_htlcs:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - if (sqlite3_column_count(stmt) != 3) - fatal("load_peer_htlcs:step gave %i cols, not 3", - sqlite3_column_count(stmt)); - - feechange_state - = feechange_state_from_name(sqlite3_column_str(stmt, 1)); - if (feechange_state == FEECHANGE_STATE_INVALID) - fatal("load_peer_htlcs:invalid feechange state %s", - sqlite3_column_str(stmt, 1)); - if (peer->feechanges[feechange_state]) - fatal("load_peer_htlcs: second feechange in state %s", - sqlite3_column_str(stmt, 1)); - peer->feechanges[feechange_state] - = new_feechange(peer, sqlite3_column_int64(stmt, 2), - feechange_state); - } - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("load_peer_htlcs:finalize gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - if (!balance_after_force(peer->local.commit->cstate) - || !balance_after_force(peer->remote.commit->cstate)) - fatal("load_peer_htlcs:channel didn't balance"); - - /* Update commit->tx and commit->map */ - peer->local.commit->tx = create_commit_tx(peer->local.commit, - peer, - &peer->local.commit->revocation_hash, - peer->local.commit->cstate, - LOCAL, &to_them_only); - bitcoin_txid(peer->local.commit->tx, &peer->local.commit->txid); - - peer->remote.commit->tx = create_commit_tx(peer->remote.commit, - peer, - &peer->remote.commit->revocation_hash, - peer->remote.commit->cstate, - REMOTE, &to_us_only); - bitcoin_txid(peer->remote.commit->tx, &peer->remote.commit->txid); - - peer->remote.staging_cstate = copy_cstate(peer, peer->remote.commit->cstate); - peer->local.staging_cstate = copy_cstate(peer, peer->local.commit->cstate); - log_debug(peer->log, "Local staging: pay %u/%u fee %u/%u htlcs %u/%u", - peer->local.staging_cstate->side[LOCAL].pay_msat, - peer->local.staging_cstate->side[REMOTE].pay_msat, - peer->local.staging_cstate->side[LOCAL].fee_msat, - peer->local.staging_cstate->side[REMOTE].fee_msat, - peer->local.staging_cstate->side[LOCAL].num_htlcs, - peer->local.staging_cstate->side[REMOTE].num_htlcs); - log_debug(peer->log, "Remote staging: pay %u/%u fee %u/%u htlcs %u/%u", - peer->remote.staging_cstate->side[LOCAL].pay_msat, - peer->remote.staging_cstate->side[REMOTE].pay_msat, - peer->remote.staging_cstate->side[LOCAL].fee_msat, - peer->remote.staging_cstate->side[REMOTE].fee_msat, - peer->remote.staging_cstate->side[LOCAL].num_htlcs, - peer->remote.staging_cstate->side[REMOTE].num_htlcs); - - tal_free(ctx); -} - -/* FIXME: A real database person would do this in a single clause along - * with loading the htlcs in the first place! */ -static void connect_htlc_src(struct lightningd_state *dstate) -{ - sqlite3 *sql = dstate->db->sql; - int err; - sqlite3_stmt *stmt; - char *ctx = tal_tmpctx(dstate); - const char *select; - - select = tal_fmt(ctx, - "SELECT peer,id,state,src_peer,src_id FROM htlcs WHERE src_peer IS NOT NULL AND state <> 'RCVD_REMOVE_ACK_REVOCATION' AND state <> 'SENT_REMOVE_ACK_REVOCATION';"); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("connect_htlc_src:%s gave %s:%s", - select, sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct pubkey id; - struct peer *peer; - struct htlc *htlc; - enum htlc_state s; - - if (err != SQLITE_ROW) - fatal("connect_htlc_src:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - pubkey_from_sql(stmt, 0, &id); - peer = find_peer(dstate, &id); - if (!peer) - continue; - - s = htlc_state_from_name(sqlite3_column_str(stmt, 2)); - if (s == HTLC_STATE_INVALID) - fatal("connect_htlc_src:unknown state %s", - sqlite3_column_str(stmt, 2)); - - htlc = htlc_get(&peer->htlcs, sqlite3_column_int64(stmt, 1), - htlc_state_owner(s)); - if (!htlc) - fatal("connect_htlc_src:unknown htlc %"PRIuSQLITE64" state %s", - sqlite3_column_int64(stmt, 1), - sqlite3_column_str(stmt, 2)); - - pubkey_from_sql(stmt, 4, &id); - peer = find_peer(dstate, &id); - if (!peer) - fatal("connect_htlc_src:unknown src peer %s", - tal_hexstr(dstate, &id, sizeof(id))); - - /* Source must be a HTLC they offered. */ - htlc->src = htlc_get(&peer->htlcs, - sqlite3_column_int64(stmt, 4), - REMOTE); - if (!htlc->src) - fatal("connect_htlc_src:unknown src htlc"); - } - - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("load_peer_htlcs:finalize gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - tal_free(ctx); -} - -static const char *linearize_shachain(const tal_t *ctx, - const struct shachain *shachain) -{ - size_t i; - u8 *p = tal_arr(ctx, u8, 0); - const char *str; - - push_le64(shachain->min_index, push, &p); - push_le32(shachain->num_valid, push, &p); - for (i = 0; i < shachain->num_valid; i++) { - push_le64(shachain->known[i].index, push, &p); - push(&shachain->known[i].hash, sizeof(shachain->known[i].hash), - &p); - } - for (i = shachain->num_valid; i < ARRAY_SIZE(shachain->known); i++) { - static u8 zeroes[sizeof(shachain->known[0].hash)]; - push_le64(0, push, &p); - push(zeroes, sizeof(zeroes), &p); - } - - assert(tal_count(p) == SHACHAIN_SIZE); - str = tal_hex(ctx, p); - tal_free(p); - return str; -} - -static bool delinearize_shachain(struct shachain *shachain, - const void *data, size_t len) -{ - size_t i; - const u8 *p = data; - - shachain->min_index = pull_le64(&p, &len); - shachain->num_valid = pull_le32(&p, &len); - for (i = 0; i < ARRAY_SIZE(shachain->known); i++) { - shachain->known[i].index = pull_le64(&p, &len); - pull(&p, &len, &shachain->known[i].hash, - sizeof(shachain->known[i].hash)); - } - return p && len == 0; -} - -static void load_peer_shachain(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - bool shachain_found = false; - const char *select; - - select = tal_fmt(ctx, - "SELECT * FROM shachain WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_shachain:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - const char *hexstr; - - if (err != SQLITE_ROW) - fatal("load_peer_shachain:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - /* shachain (peer "SQL_PUBKEY", shachain BINARY(%zu) */ - if (sqlite3_column_count(stmt) != 2) - fatal("load_peer_shachain:step gave %i cols, not 2", - sqlite3_column_count(stmt)); - - if (shachain_found) - fatal("load_peer_shachain:multiple shachains?"); - - hexstr = tal_hexstr(ctx, sqlite3_column_blob(stmt, 1), - sqlite3_column_bytes(stmt, 1)); - if (!delinearize_shachain(&peer->their_preimages, - sqlite3_column_blob(stmt, 1), - sqlite3_column_bytes(stmt, 1))) - fatal("load_peer_shachain:invalid shachain %s", - hexstr); - shachain_found = true; - } - - if (!shachain_found) - fatal("load_peer_shachain:no shachain"); - tal_free(ctx); -} - -/* We may not have one, and that's OK. */ -static void load_peer_closing(struct peer *peer) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = peer->dstate->db->sql; - char *ctx = tal_tmpctx(peer); - bool closing_found = false; - const char *select; - - select = tal_fmt(ctx, - "SELECT * FROM closing WHERE peer = x'%s';", - pubkey_to_hexstr(ctx, peer->id)); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_closing:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - if (err != SQLITE_ROW) - fatal("load_peer_closing:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - if (sqlite3_column_count(stmt) != 9) - fatal("load_peer_closing:step gave %i cols, not 9", - sqlite3_column_count(stmt)); - - if (closing_found) - fatal("load_peer_closing:multiple closing?"); - - peer->closing.our_fee = sqlite3_column_int64(stmt, 1); - peer->closing.their_fee = sqlite3_column_int64(stmt, 2); - if (sqlite3_column_type(stmt, 3) == SQLITE_NULL) - peer->closing.their_sig = NULL; - else { - peer->closing.their_sig = tal(peer, - secp256k1_ecdsa_signature); - sig_from_sql(stmt, 3, peer->closing.their_sig); - } - peer->closing.our_script = tal_sql_blob(peer, stmt, 4); - peer->closing.their_script = tal_sql_blob(peer, stmt, 5); - peer->closing.shutdown_order = sqlite3_column_int64(stmt, 6); - peer->closing.closing_order = sqlite3_column_int64(stmt, 7); - peer->closing.sigs_in = sqlite3_column_int64(stmt, 8); - closing_found = true; - } - tal_free(ctx); -} - -/* FIXME: much of this is redundant. */ -static void restore_peer_local_visible_state(struct peer *peer) -{ - assert(peer->local.offer_anchor == !peer->remote.offer_anchor); - - /* peer->local.commitkey and peer->local.finalkey set by - * peer_set_secrets_from_db(). */ - memcheck(&peer->local.commitkey, sizeof(peer->local.commitkey)); - memcheck(&peer->local.finalkey, sizeof(peer->local.finalkey)); - /* These set in new_peer */ - memcheck(&peer->local.locktime, sizeof(peer->local.locktime)); - memcheck(&peer->local.mindepth, sizeof(peer->local.mindepth)); - /* This set in db_load_peers */ - memcheck(&peer->local.commit_fee_rate, - sizeof(peer->local.commit_fee_rate)); - - peer_get_revocation_hash(peer, - peer->local.commit->commit_num + 1, - &peer->local.next_revocation_hash); - - if (state_is_normal(peer->state)) - peer->nc = add_connection(peer->dstate->rstate, - &peer->dstate->id, peer->id, - peer->dstate->config.fee_base, - peer->dstate->config.fee_per_satoshi, - peer->dstate->config.min_htlc_expiry, - peer->dstate->config.min_htlc_expiry); - - peer->their_commitsigs = peer->local.commit->commit_num + 1; - /* If they created anchor, they didn't send a sig for first commit */ - if (!peer->anchor.ours) - peer->their_commitsigs--; - - if (peer->local.commit->order + 1 > peer->order_counter) - peer->order_counter = peer->local.commit->order + 1; - if (peer->remote.commit->order + 1 > peer->order_counter) - peer->order_counter = peer->remote.commit->order + 1; - if (peer->closing.closing_order + 1 > peer->order_counter) - peer->order_counter = peer->closing.closing_order + 1; - if (peer->closing.shutdown_order + 1 > peer->order_counter) - peer->order_counter = peer->closing.shutdown_order + 1; -} - -static void db_load_peers(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - struct peer *peer; - - err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM peers;", -1, - &stmt, NULL); - - if (err != SQLITE_OK) - fatal("db_load_peers:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - enum state state; - struct log *l; - struct pubkey id; - const char *idstr; - - if (err != SQLITE_ROW) - fatal("db_load_peers:step gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - if (sqlite3_column_count(stmt) != 4) - fatal("db_load_peers:step gave %i cols, not 4", - sqlite3_column_count(stmt)); - state = name_to_state(sqlite3_column_str(stmt, 1)); - if (state == STATE_MAX) - fatal("db_load_peers:unknown state %s", - sqlite3_column_str(stmt, 1)); - pubkey_from_sql(stmt, 0, &id); - idstr = pubkey_to_hexstr(dstate, &id); - l = new_log(dstate, dstate->log_book, "%s:", idstr); - tal_free(idstr); - peer = new_peer(dstate, l, state, sqlite3_column_int(stmt, 2)); - peer->htlc_id_counter = 0; - peer->id = tal_dup(peer, struct pubkey, &id); - peer->local.commit_fee_rate = sqlite3_column_int64(stmt, 3); - peer->order_counter = 1; - log_debug(peer->log, "%s:%s", - __func__, state_name(peer->state)); - } - err = sqlite3_finalize(stmt); - if (err != SQLITE_OK) - fatal("db_load_peers:finalize gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - - list_for_each(&dstate->peers, peer, list) { - load_peer_secrets(peer); - load_peer_closing(peer); - peer->anchor.min_depth = 0; - if (peer->state >= STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - && !state_is_error(peer->state)) { - load_peer_anchor(peer); - load_peer_visible_state(peer); - load_peer_shachain(peer); - load_peer_commit_info(peer); - load_peer_htlcs(peer); - restore_peer_local_visible_state(peer); - } - if (peer->local.offer_anchor) - load_peer_anchor_input(peer); - } - - connect_htlc_src(dstate); -} - - -static const char *pubkeys_to_hex(const tal_t *ctx, const struct pubkey *ids) -{ - u8 *ders = tal_arr(ctx, u8, PUBKEY_DER_LEN * tal_count(ids)); - size_t i; - - for (i = 0; i < tal_count(ids); i++) - pubkey_to_der(ders + i * PUBKEY_DER_LEN, &ids[i]); - - return tal_hex(ctx, ders); -} -static struct pubkey *pubkeys_from_arr(const tal_t *ctx, - const void *blob, size_t len) -{ - struct pubkey *ids; - size_t i; - - if (len % PUBKEY_DER_LEN) - fatal("ids array bad length %zu", len); - - ids = tal_arr(ctx, struct pubkey, len / PUBKEY_DER_LEN); - for (i = 0; i < tal_count(ids); i++) { - if (!pubkey_from_der(blob, PUBKEY_DER_LEN, &ids[i])) - fatal("ids array invalid %zu", i); - blob = (const u8 *)blob + PUBKEY_DER_LEN; - } - return ids; -} - -static void db_load_pay(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - char *ctx = tal_tmpctx(dstate); - - err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM pay;", -1, - &stmt, NULL); - - if (err != SQLITE_OK) - fatal("db_load_pay:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct sha256 rhash; - struct htlc *htlc; - struct pubkey *peer_id; - u64 htlc_id, msatoshi; - struct pubkey *ids; - struct preimage *r; - void *fail; - - if (err != SQLITE_ROW) - fatal("db_load_pay:step gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - if (sqlite3_column_count(stmt) != 7) - fatal("db_load_pay:step gave %i cols, not 7", - sqlite3_column_count(stmt)); - - sha256_from_sql(stmt, 0, &rhash); - msatoshi = sqlite3_column_int64(stmt, 1); - ids = pubkeys_from_arr(ctx, - sqlite3_column_blob(stmt, 2), - sqlite3_column_bytes(stmt, 2)); - if (sqlite3_column_type(stmt, 3) == SQLITE_NULL) - peer_id = NULL; - else { - peer_id = tal(ctx, struct pubkey); - pubkey_from_sql(stmt, 3, peer_id); - } - htlc_id = sqlite3_column_int64(stmt, 4); - if (sqlite3_column_type(stmt, 5) == SQLITE_NULL) - r = NULL; - else { - r = tal(ctx, struct preimage); - from_sql_blob(stmt, 5, r, sizeof(*r)); - } - fail = tal_sql_blob(ctx, stmt, 6); - /* Exactly one of these must be set. */ - if (!fail + !peer_id + !r != 2) - fatal("db_load_pay: not exactly one set:" - " fail=%p peer_id=%p r=%p", - fail, peer_id, r); - if (peer_id) { - struct peer *peer = find_peer(dstate, peer_id); - if (!peer) - fatal("db_load_pay: unknown peer"); - htlc = htlc_get(&peer->htlcs, htlc_id, LOCAL); - if (!htlc) - fatal("db_load_pay: unknown htlc"); - } else - htlc = NULL; - - if (!pay_add(dstate, &rhash, msatoshi, ids, htlc, fail, r)) - fatal("db_load_pay: could not add pay"); - } - tal_free(ctx); -} - -static void db_load_invoice(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - char *ctx = tal_tmpctx(dstate); - - err = sqlite3_prepare_v2(dstate->db->sql, "SELECT * FROM invoice;", -1, - &stmt, NULL); - - if (err != SQLITE_OK) - fatal("db_load_invoice:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(dstate->db->sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct preimage r; - u64 msatoshi, paid_num; - const char *label; - - if (err != SQLITE_ROW) - fatal("db_load_invoice:step gave %s:%s", - sqlite3_errstr(err), - sqlite3_errmsg(dstate->db->sql)); - if (sqlite3_column_count(stmt) != 4) - fatal("db_load_invoice:step gave %i cols, not 4", - sqlite3_column_count(stmt)); - - from_sql_blob(stmt, 0, &r, sizeof(r)); - msatoshi = sqlite3_column_int64(stmt, 1); - label = (const char *)sqlite3_column_text(stmt, 2); - paid_num = sqlite3_column_int64(stmt, 3); - invoice_add(dstate->invoices, &r, msatoshi, label, paid_num); - } - tal_free(ctx); -} - -static void db_load_addresses(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = dstate->db->sql; - char *ctx = tal_tmpctx(dstate); - const char *select; - - select = tal_fmt(ctx, "SELECT * FROM peer_address;"); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("load_peer_addresses:prepare gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - struct peer_address *addr; - - if (err != SQLITE_ROW) - fatal("load_peer_addresses:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - addr = tal(dstate, struct peer_address); - pubkey_from_sql(stmt, 0, &addr->id); - if (!netaddr_from_blob(sqlite3_column_blob(stmt, 1), - sqlite3_column_bytes(stmt, 1), - &addr->addr)) - fatal("load_peer_addresses: unparsable addresses for '%s'", - select); - list_add_tail(&dstate->addresses, &addr->list); - log_debug(dstate->base_log, "load_peer_addresses:%s", - pubkey_to_hexstr(ctx, &addr->id)); - } - tal_free(ctx); -} - -static void db_check_version(struct lightningd_state *dstate) -{ - int err; - sqlite3_stmt *stmt; - sqlite3 *sql = dstate->db->sql; - char *ctx = tal_tmpctx(dstate); - const char *select; - - select = tal_fmt(ctx, "SELECT * FROM version;"); - - err = sqlite3_prepare_v2(sql, select, -1, &stmt, NULL); - if (err != SQLITE_OK) - fatal("DATABASE NEEDS UPDATE. Can't access VERSION: %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - - while ((err = sqlite3_step(stmt)) != SQLITE_DONE) { - const char *ver; - - if (err != SQLITE_ROW) - fatal("db_check_version:step gave %s:%s", - sqlite3_errstr(err), sqlite3_errmsg(sql)); - ver = sqlite3_column_str(stmt, 0); - if (!streq(ver, VERSION)) { - if (dstate->config.db_version_ignore) - log_unusual(dstate->base_log, - "DATABASE NEEDS UPDATE." - " Version %s does not match %s", - ver, VERSION); - else - fatal("DATABASE NEEDS UPDATE." - " Version %s does not match %s", - ver, VERSION); - } - } - tal_free(ctx); -} - -static void db_load(struct lightningd_state *dstate) -{ - db_check_version(dstate); - db_load_wallet(dstate); - db_load_addresses(dstate); - db_load_peers(dstate); - db_load_pay(dstate); - db_load_invoice(dstate); -} - -void db_init(struct lightningd_state *dstate) -{ - int err; - bool created = false; - - if (SQLITE_VERSION_NUMBER != sqlite3_libversion_number()) - fatal("SQLITE version mistmatch: compiled %u, now %u", - SQLITE_VERSION_NUMBER, sqlite3_libversion_number()); - - dstate->db = tal(dstate, struct db); - - err = sqlite3_open_v2(DB_FILE, &dstate->db->sql, - SQLITE_OPEN_READWRITE, NULL); - if (err != SQLITE_OK) { - log_unusual(dstate->base_log, - "Error opening %s (%s), trying to create", - DB_FILE, sqlite3_errstr(err)); - err = sqlite3_open_v2(DB_FILE, &dstate->db->sql, - SQLITE_OPEN_READWRITE - | SQLITE_OPEN_CREATE, NULL); - if (err != SQLITE_OK) - fatal("failed creating %s: %s", - DB_FILE, sqlite3_errstr(err)); - created = true; - } - - tal_add_destructor(dstate->db, close_db); - dstate->db->in_transaction = false; - dstate->db->err = NULL; - - if (!created) { - db_load(dstate); - return; - } - - /* Set up tables. */ - dstate->db->in_transaction = true; - db_exec(__func__, dstate, "BEGIN IMMEDIATE;"); - db_exec(__func__, dstate, - TABLE(wallet, - SQL_PRIVKEY(privkey)) - TABLE(pay, - SQL_RHASH(rhash), SQL_U64(msatoshi), - SQL_BLOB(ids), SQL_PUBKEY(htlc_peer), - SQL_U64(htlc_id), SQL_R(r), SQL_FAIL(fail), - "PRIMARY KEY(rhash)") - TABLE(invoice, - SQL_R(r), SQL_U64(msatoshi), SQL_INVLABEL(label), - SQL_U64(paid_num), - "PRIMARY KEY(label)") - TABLE(anchor_inputs, - SQL_PUBKEY(peer), - SQL_TXID(txid), SQL_U32(idx), - SQL_U64(in_amount), SQL_U64(out_amount), - SQL_PUBKEY(walletkey)) - TABLE(anchors, - SQL_PUBKEY(peer), - SQL_TXID(txid), SQL_U32(idx), SQL_U64(amount), - SQL_U32(ok_depth), SQL_U32(min_depth), - SQL_BOOL(ours)) - /* FIXME: state in key is overkill: just need side */ - TABLE(htlcs, - SQL_PUBKEY(peer), SQL_U64(id), - SQL_STATENAME(state), SQL_U64(msatoshi), - SQL_U32(expiry), SQL_RHASH(rhash), SQL_R(r), - SQL_ROUTING(routing), SQL_PUBKEY(src_peer), - SQL_U64(src_id), SQL_BLOB(fail), - "PRIMARY KEY(peer, id, state)") - TABLE(feechanges, - SQL_PUBKEY(peer), SQL_STATENAME(state), - SQL_U32(fee_rate), - "PRIMARY KEY(peer,state)") - TABLE(commit_info, - SQL_PUBKEY(peer), SQL_U32(side), - SQL_U64(commit_num), SQL_SHA256(revocation_hash), - SQL_U64(xmit_order), SQL_SIGNATURE(sig), - SQL_SHA256(prev_revocation_hash), - "PRIMARY KEY(peer, side)") - TABLE(shachain, - SQL_PUBKEY(peer), SQL_SHACHAIN(shachain), - "PRIMARY KEY(peer)") - TABLE(their_visible_state, - SQL_PUBKEY(peer), SQL_BOOL(offered_anchor), - SQL_PUBKEY(commitkey), SQL_PUBKEY(finalkey), - SQL_U32(locktime), SQL_U32(mindepth), - SQL_U32(commit_fee_rate), - SQL_SHA256(next_revocation_hash), - "PRIMARY KEY(peer)") - TABLE(their_commitments, - SQL_PUBKEY(peer), SQL_SHA256(txid), - SQL_U64(commit_num), - "PRIMARY KEY(peer, txid)") - TABLE(peer_secrets, - SQL_PUBKEY(peer), SQL_PRIVKEY(commitkey), - SQL_PRIVKEY(finalkey), - SQL_SHA256(revocation_seed), - "PRIMARY KEY(peer)") - TABLE(peer_address, - SQL_PUBKEY(peer), SQL_BLOB(addr), - "PRIMARY KEY(peer)") - TABLE(closing, - SQL_PUBKEY(peer), SQL_U64(our_fee), - SQL_U64(their_fee), SQL_SIGNATURE(their_sig), - SQL_BLOB(our_script), SQL_BLOB(their_script), - SQL_U64(shutdown_order), SQL_U64(closing_order), - SQL_U64(sigs_in), - "PRIMARY KEY(peer)") - TABLE(peers, - SQL_PUBKEY(peer), SQL_STATENAME(state), - SQL_BOOL(offered_anchor), SQL_U32(our_feerate), - "PRIMARY KEY(peer)") - TABLE(version, "version VARCHAR(100)")); - db_exec(__func__, dstate, "INSERT INTO version VALUES ('"VERSION"');"); - db_exec(__func__, dstate, "COMMIT;"); - dstate->db->in_transaction = false; - - if (dstate->db->err) { - unlink(DB_FILE); - fatal("%s", dstate->db->err); - } -} - -void db_set_anchor(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid; - - assert(peer->dstate->db->in_transaction); - peerid = pubkey_to_hexstr(ctx, peer->id); - log_debug(peer->log, "%s(%s)", __func__, peerid); - - db_exec(__func__, peer->dstate, - "INSERT INTO anchors VALUES (x'%s', x'%s', %u, %"PRIu64", %i, %u, %s);", - peerid, - tal_hexstr(ctx, &peer->anchor.txid, sizeof(peer->anchor.txid)), - peer->anchor.index, - peer->anchor.satoshis, - peer->anchor.ok_depth, - peer->anchor.min_depth, - sql_bool(peer->anchor.ours)); - - db_exec(__func__, peer->dstate, - "INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', %"PRIi64", %s, NULL);", - peerid, - side_to_str(LOCAL), - tal_hexstr(ctx, &peer->local.commit->revocation_hash, - sizeof(peer->local.commit->revocation_hash)), - peer->local.commit->order, - sig_to_sql(ctx, peer->local.commit->sig)); - - db_exec(__func__, peer->dstate, - "INSERT INTO commit_info VALUES(x'%s', '%s', 0, x'%s', %"PRIi64", %s, NULL);", - peerid, - side_to_str(REMOTE), - tal_hexstr(ctx, &peer->remote.commit->revocation_hash, - sizeof(peer->remote.commit->revocation_hash)), - peer->remote.commit->order, - sig_to_sql(ctx, peer->remote.commit->sig)); - - db_exec(__func__, peer->dstate, - "INSERT INTO shachain VALUES (x'%s', x'%s');", - peerid, - linearize_shachain(ctx, &peer->their_preimages)); - - tal_free(ctx); -} - -void db_set_visible_state(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - - db_exec(__func__, peer->dstate, - "INSERT INTO their_visible_state VALUES (x'%s', %s, x'%s', x'%s', %u, %u, %"PRIu64", x'%s');", - peerid, - sql_bool(peer->remote.offer_anchor), - pubkey_to_hexstr(ctx, &peer->remote.commitkey), - pubkey_to_hexstr(ctx, &peer->remote.finalkey), - peer->remote.locktime.locktime, - peer->remote.mindepth, - peer->remote.commit_fee_rate, - tal_hexstr(ctx, &peer->remote.next_revocation_hash, - sizeof(peer->remote.next_revocation_hash))); - - tal_free(ctx); -} - -void db_update_next_revocation_hash(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s):%s", __func__, peerid, - tal_hexstr(ctx, &peer->remote.next_revocation_hash, - sizeof(peer->remote.next_revocation_hash))); - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE their_visible_state SET next_revocation_hash=x'%s' WHERE peer=x'%s';", - tal_hexstr(ctx, &peer->remote.next_revocation_hash, - sizeof(peer->remote.next_revocation_hash)), - peerid); - tal_free(ctx); -} - -void db_create_peer(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "INSERT INTO peers VALUES (x'%s', '%s', %s, %"PRIi64");", - peerid, - state_name(peer->state), - sql_bool(peer->local.offer_anchor), - peer->local.commit_fee_rate); - - db_exec(__func__, peer->dstate, - "INSERT INTO peer_secrets VALUES (x'%s', %s);", - peerid, peer_secrets_for_db(ctx, peer)); - - if (peer->local.offer_anchor) - db_exec(__func__, peer->dstate, - "INSERT INTO anchor_inputs VALUES" - " (x'%s', x'%s', %u, %"PRIi64", %"PRIi64", x'%s');", - peerid, - tal_hexstr(ctx, &peer->anchor.input->txid, - sizeof(peer->anchor.input->txid)), - peer->anchor.input->index, - peer->anchor.input->in_amount, - peer->anchor.input->out_amount, - pubkey_to_hexstr(ctx, &peer->anchor.input->walletkey)); - - tal_free(ctx); -} - -void db_start_transaction(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(!peer->dstate->db->in_transaction); - peer->dstate->db->in_transaction = true; - peer->dstate->db->err = tal_free(peer->dstate->db->err); - - db_exec(__func__, peer->dstate, "BEGIN IMMEDIATE;"); - tal_free(ctx); -} - -void db_abort_transaction(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - peer->dstate->db->in_transaction = false; - db_exec(__func__, peer->dstate, "ROLLBACK;"); - tal_free(ctx); -} - -const char *db_commit_transaction(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - if (!db_exec(__func__, peer->dstate, "COMMIT;")) - db_abort_transaction(peer); - else - peer->dstate->db->in_transaction = false; - tal_free(ctx); - - return peer->dstate->db->err; -} - -void db_new_htlc(struct peer *peer, const struct htlc *htlc) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - - if (htlc->src) { - db_exec(__func__, peer->dstate, - "INSERT INTO htlcs VALUES" - " (x'%s', %"PRIu64", '%s', %"PRIu64", %u, x'%s', NULL, x'%s', x'%s', %"PRIu64", NULL);", - pubkey_to_hexstr(ctx, peer->id), - htlc->id, - htlc_state_name(htlc->state), - htlc->msatoshi, - abs_locktime_to_blocks(&htlc->expiry), - tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash)), - tal_hex(ctx, htlc->routing), - peerid, - htlc->src->id); - } else { - db_exec(__func__, peer->dstate, - "INSERT INTO htlcs VALUES" - " (x'%s', %"PRIu64", '%s', %"PRIu64", %u, x'%s', NULL, x'%s', NULL, NULL, NULL);", - peerid, - htlc->id, - htlc_state_name(htlc->state), - htlc->msatoshi, - abs_locktime_to_blocks(&htlc->expiry), - tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash)), - tal_hex(ctx, htlc->routing)); - } - - tal_free(ctx); -} - -void db_new_feechange(struct peer *peer, const struct feechange *feechange) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - - db_exec(__func__, peer->dstate, - "INSERT INTO feechanges VALUES" - " (x'%s', '%s', %"PRIu64");", - peerid, - feechange_state_name(feechange->state), - feechange->fee_rate); - - tal_free(ctx); -} - -void db_update_htlc_state(struct peer *peer, const struct htlc *htlc, - enum htlc_state oldstate) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s): %"PRIu64" %s->%s", __func__, peerid, - htlc->id, htlc_state_name(oldstate), - htlc_state_name(htlc->state)); - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE htlcs SET state='%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", - htlc_state_name(htlc->state), peerid, - htlc->id, htlc_state_name(oldstate)); - - tal_free(ctx); -} - -void db_update_feechange_state(struct peer *peer, - const struct feechange *f, - enum feechange_state oldstate) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s): %s->%s", __func__, peerid, - feechange_state_name(oldstate), - feechange_state_name(f->state)); - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE feechanges SET state='%s' WHERE peer=x'%s' AND state='%s';", - feechange_state_name(f->state), peerid, - feechange_state_name(oldstate)); - - tal_free(ctx); -} - -void db_remove_feechange(struct peer *peer, const struct feechange *feechange, - enum feechange_state oldstate) -{ - const char *ctx = tal(peer, char); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - assert(peer->dstate->db->in_transaction); - - db_exec(__func__, peer->dstate, - "DELETE FROM feechanges WHERE peer=x'%s' AND state='%s';", - peerid, feechange_state_name(oldstate)); - - tal_free(ctx); -} - -void db_update_state(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE peers SET state='%s' WHERE peer=x'%s';", - state_name(peer->state), peerid); - tal_free(ctx); -} - -void db_htlc_fulfilled(struct peer *peer, const struct htlc *htlc) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE htlcs SET r=x'%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", - tal_hexstr(ctx, htlc->r, sizeof(*htlc->r)), - peerid, - htlc->id, - htlc_state_name(htlc->state)); - - tal_free(ctx); -} - -void db_htlc_failed(struct peer *peer, const struct htlc *htlc) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE htlcs SET fail=x'%s' WHERE peer=x'%s' AND id=%"PRIu64" AND state='%s';", - tal_hexstr(ctx, htlc->fail, sizeof(*htlc->fail)), - peerid, - htlc->id, - htlc_state_name(htlc->state)); - - tal_free(ctx); -} - -void db_new_commit_info(struct peer *peer, enum side side, - const struct sha256 *prev_rhash) -{ - struct commit_info *ci; - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - if (side == LOCAL) { - ci = peer->local.commit; - } else { - ci = peer->remote.commit; - } - - db_exec(__func__, peer->dstate, "UPDATE commit_info SET commit_num=%"PRIu64", revocation_hash=x'%s', sig=%s, xmit_order=%"PRIi64", prev_revocation_hash=%s WHERE peer=x'%s' AND side='%s';", - ci->commit_num, - tal_hexstr(ctx, &ci->revocation_hash, - sizeof(ci->revocation_hash)), - sig_to_sql(ctx, ci->sig), - ci->order, - sql_hex_or_null(ctx, prev_rhash, sizeof(*prev_rhash)), - peerid, side_to_str(side)); - tal_free(ctx); -} - -/* FIXME: Is this strictly necessary? */ -void db_remove_their_prev_revocation_hash(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - - db_exec(__func__, peer->dstate, "UPDATE commit_info SET prev_revocation_hash=NULL WHERE peer=x'%s' AND side='REMOTE' and prev_revocation_hash IS NOT NULL;", - peerid); - tal_free(ctx); -} - - -void db_save_shachain(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, "UPDATE shachain SET shachain=x'%s' WHERE peer=x'%s';", - linearize_shachain(ctx, &peer->their_preimages), - peerid); - tal_free(ctx); -} - -void db_add_commit_map(struct peer *peer, - const struct sha256_double *txid, u64 commit_num) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s),commit_num=%"PRIu64, __func__, peerid, - commit_num); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "INSERT INTO their_commitments VALUES (x'%s', x'%s', %"PRIu64");", - peerid, - tal_hexstr(ctx, txid, sizeof(*txid)), - commit_num); - tal_free(ctx); -} - -/* FIXME: Clean out old ones! */ -bool db_add_peer_address(struct lightningd_state *dstate, - const struct peer_address *addr) -{ - const tal_t *ctx = tal_tmpctx(dstate); - bool ok; - - log_debug(dstate->base_log, "%s", __func__); - - assert(!dstate->db->in_transaction); - ok = db_exec(__func__, dstate, - "INSERT OR REPLACE INTO peer_address VALUES (x'%s', x'%s');", - pubkey_to_hexstr(ctx, &addr->id), - netaddr_to_hex(ctx, &addr->addr)); - - tal_free(ctx); - return ok; -} - -void db_forget_peer(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - size_t i; - const char *const tables[] = { "anchors", "htlcs", "commit_info", "shachain", "their_visible_state", "their_commitments", "peer_secrets", "closing", "peers" }; - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->state == STATE_CLOSED); - - db_start_transaction(peer); - - for (i = 0; i < ARRAY_SIZE(tables); i++) { - db_exec(__func__, peer->dstate, - "DELETE from %s WHERE peer=x'%s';", - tables[i], peerid); - } - if (db_commit_transaction(peer) != NULL) - fatal("%s:db_commi_transaction failed", __func__); - - tal_free(ctx); -} - -void db_begin_shutdown(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "INSERT INTO closing VALUES (x'%s', 0, 0, NULL, NULL, NULL, 0, 0, 0);", - peerid); - tal_free(ctx); -} - -void db_set_our_closing_script(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, "UPDATE closing SET our_script=x'%s',shutdown_order=%"PRIu64" WHERE peer=x'%s';", - tal_hex(ctx, peer->closing.our_script), - peer->closing.shutdown_order, - peerid); - tal_free(ctx); -} - -void db_set_their_closing_script(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(peer->dstate->db->in_transaction); - db_exec(__func__, peer->dstate, - "UPDATE closing SET their_script=x'%s' WHERE peer=x'%s';", - tal_hex(ctx, peer->closing.their_script), - peerid); - tal_free(ctx); -} - -/* For first time, we are in transaction to make it atomic with peer->state - * update. Later calls are not. */ -/* FIXME: make caller wrap in transaction. */ -void db_update_our_closing(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - db_exec(__func__, peer->dstate, - "UPDATE closing SET our_fee=%"PRIu64", closing_order=%"PRIi64" WHERE peer=x'%s';", - peer->closing.our_fee, - peer->closing.closing_order, - peerid); - tal_free(ctx); -} - -bool db_update_their_closing(struct peer *peer) -{ - const char *ctx = tal_tmpctx(peer); - bool ok; - const char *peerid = pubkey_to_hexstr(ctx, peer->id); - - log_debug(peer->log, "%s(%s)", __func__, peerid); - - assert(!peer->dstate->db->in_transaction); - ok = db_exec(__func__, peer->dstate, - "UPDATE closing SET their_fee=%"PRIu64", their_sig=%s, sigs_in=%u WHERE peer=x'%s';", - peer->closing.their_fee, - sig_to_sql(ctx, peer->closing.their_sig), - peer->closing.sigs_in, - peerid); - tal_free(ctx); - return ok; -} - -bool db_new_pay_command(struct lightningd_state *dstate, - const struct sha256 *rhash, - const struct pubkey *ids, - u64 msatoshi, - const struct htlc *htlc) -{ - const tal_t *ctx = tal_tmpctx(dstate); - bool ok; - - log_debug(dstate->base_log, "%s", __func__); - log_add_struct(dstate->base_log, "(%s)", struct sha256, rhash); - - assert(!dstate->db->in_transaction); - ok = db_exec(__func__, dstate, - "INSERT INTO pay VALUES (x'%s', %"PRIu64", x'%s', x'%s', %"PRIu64", NULL, NULL);", - tal_hexstr(ctx, rhash, sizeof(*rhash)), - msatoshi, - pubkeys_to_hex(ctx, ids), - pubkey_to_hexstr(ctx, htlc->peer->id), - htlc->id); - tal_free(ctx); - return ok; -} - -bool db_replace_pay_command(struct lightningd_state *dstate, - const struct sha256 *rhash, - const struct pubkey *ids, - u64 msatoshi, - const struct htlc *htlc) -{ - const tal_t *ctx = tal_tmpctx(dstate); - bool ok; - - log_debug(dstate->base_log, "%s", __func__); - log_add_struct(dstate->base_log, "(%s)", struct sha256, rhash); - - assert(!dstate->db->in_transaction); - ok = db_exec(__func__, dstate, - "UPDATE pay SET msatoshi=%"PRIu64", ids=x'%s', htlc_peer=x'%s', htlc_id=%"PRIu64", r=NULL, fail=NULL WHERE rhash=x'%s';", - msatoshi, - pubkeys_to_hex(ctx, ids), - pubkey_to_hexstr(ctx, htlc->peer->id), - htlc->id, - tal_hexstr(ctx, rhash, sizeof(*rhash))); - tal_free(ctx); - return ok; -} - -void db_complete_pay_command(struct lightningd_state *dstate, - const struct htlc *htlc) -{ - const tal_t *ctx = tal_tmpctx(dstate); - - log_debug(dstate->base_log, "%s", __func__); - log_add_struct(dstate->base_log, "(%s)", struct sha256, &htlc->rhash); - - assert(dstate->db->in_transaction); - if (htlc->r) - db_exec(__func__, dstate, - "UPDATE pay SET r=x'%s', htlc_peer=NULL WHERE rhash=x'%s';", - tal_hexstr(ctx, htlc->r, sizeof(*htlc->r)), - tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash))); - else - db_exec(__func__, dstate, - "UPDATE pay SET fail=x'%s', htlc_peer=NULL WHERE rhash=x'%s';", - tal_hex(ctx, htlc->fail), - tal_hexstr(ctx, &htlc->rhash, sizeof(htlc->rhash))); - - tal_free(ctx); -} - -bool db_new_invoice(struct lightningd_state *dstate, - u64 msatoshi, - const char *label, - const struct preimage *r) -{ - const tal_t *ctx = tal_tmpctx(dstate); - bool ok; - - log_debug(dstate->base_log, "%s", __func__); - - assert(!dstate->db->in_transaction); - - /* Insert label as hex; suspect injection attacks. */ - ok = db_exec(__func__, dstate, - "INSERT INTO invoice VALUES (x'%s', %"PRIu64", x'%s', %s);", - tal_hexstr(ctx, r, sizeof(*r)), - msatoshi, - tal_hexstr(ctx, label, strlen(label)), - sql_bool(false)); - tal_free(ctx); - return ok; -} - -void db_resolve_invoice(struct lightningd_state *dstate, - const char *label, u64 paid_num) -{ - const tal_t *ctx = tal_tmpctx(dstate); - - log_debug(dstate->base_log, "%s", __func__); - - assert(dstate->db->in_transaction); - - db_exec(__func__, dstate, "UPDATE invoice SET paid_num=%"PRIu64" WHERE label=x'%s';", - paid_num, tal_hexstr(ctx, label, strlen(label))); - tal_free(ctx); -} - -bool db_remove_invoice(struct lightningd_state *dstate, - const char *label) -{ - const tal_t *ctx = tal_tmpctx(dstate); - bool ok; - - log_debug(dstate->base_log, "%s", __func__); - - assert(!dstate->db->in_transaction); - - ok = db_exec(__func__, dstate, "DELETE FROM invoice WHERE label=x'%s';", - tal_hexstr(ctx, label, strlen(label))); - tal_free(ctx); - return ok; -} diff --git a/daemon/db.h b/daemon/db.h deleted file mode 100644 index c0a08a0b2..000000000 --- a/daemon/db.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef LIGHTNING_DAEMON_DB_H -#define LIGHTNING_DAEMON_DB_H -#include "config.h" -#include "peer.h" -#include - -void db_init(struct lightningd_state *dstate); - -void db_start_transaction(struct peer *peer); -void db_abort_transaction(struct peer *peer); -const char *db_commit_transaction(struct peer *peer); - -void db_add_wallet_privkey(struct lightningd_state *dstate, - const struct privkey *privkey); - -bool db_add_peer_address(struct lightningd_state *dstate, - const struct peer_address *addr); - -/* Must NOT be inside transaction. */ -bool db_update_their_closing(struct peer *peer); -bool db_new_pay_command(struct lightningd_state *dstate, - const struct sha256 *rhash, - const struct pubkey *ids, - u64 msatoshi, - const struct htlc *htlc); -bool db_replace_pay_command(struct lightningd_state *dstate, - const struct sha256 *rhash, - const struct pubkey *ids, - u64 msatoshi, - const struct htlc *htlc); -bool db_new_invoice(struct lightningd_state *dstate, - u64 msatoshi, - const char *label, - const struct preimage *r); - -bool db_remove_invoice(struct lightningd_state *dstate, - const char *label); - -/* FIXME: save error handling until db_commit_transaction for calls - * which have to be inside transaction anyway. */ - -/* Must be inside transaction. */ -void db_create_peer(struct peer *peer); -void db_set_visible_state(struct peer *peer); -void db_set_anchor(struct peer *peer); -void db_new_htlc(struct peer *peer, const struct htlc *htlc); -void db_new_feechange(struct peer *peer, const struct feechange *feechange); -void db_htlc_fulfilled(struct peer *peer, const struct htlc *htlc); -void db_htlc_failed(struct peer *peer, const struct htlc *htlc); -void db_update_htlc_state(struct peer *peer, const struct htlc *htlc, - enum htlc_state oldstate); -void db_complete_pay_command(struct lightningd_state *dstate, - const struct htlc *htlc); -void db_resolve_invoice(struct lightningd_state *dstate, - const char *label, u64 paid_num); -void db_update_feechange_state(struct peer *peer, - const struct feechange *f, - enum feechange_state oldstate); -void db_remove_feechange(struct peer *peer, const struct feechange *feechange, - enum feechange_state oldstate); -void db_new_commit_info(struct peer *peer, enum side side, - const struct sha256 *prev_rhash); -void db_remove_their_prev_revocation_hash(struct peer *peer); -void db_update_next_revocation_hash(struct peer *peer); -void db_save_shachain(struct peer *peer); -void db_update_state(struct peer *peer); -void db_begin_shutdown(struct peer *peer); -void db_set_our_closing_script(struct peer *peer); -void db_update_our_closing(struct peer *peer); -void db_set_their_closing_script(struct peer *peer); - -void db_add_commit_map(struct peer *peer, - const struct sha256_double *txid, u64 commit_num); - -void db_forget_peer(struct peer *peer); -#endif /* LIGHTNING_DAEMON_DB_H */ diff --git a/daemon/dns.c b/daemon/dns.c index 92a7af4fd..b5b8002fc 100644 --- a/daemon/dns.c +++ b/daemon/dns.c @@ -2,7 +2,7 @@ #include "dns.h" #include "lightningd.h" #include "log.h" -#include "peer.h" +#include "netaddr.h" #include #include #include diff --git a/daemon/failure.c b/daemon/failure.c deleted file mode 100644 index 1c8deabf1..000000000 --- a/daemon/failure.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "failure.h" -#include "protobuf_convert.h" -#include - -/* FIXME: Crypto! */ -const u8 *failinfo_create(const tal_t *ctx, - const struct pubkey *id, - u32 error_code, - const char *reason) -{ - FailInfo *f = tal(ctx, FailInfo); - u8 *arr; - - fail_info__init(f); - f->id = pubkey_to_proto(f, id); - f->error_code = error_code; - if (reason) - f->reason = tal_strdup(f, reason); - else - f->reason = NULL; - - arr = tal_arr(ctx, u8, fail_info__get_packed_size(f)); - fail_info__pack(f, arr); - tal_free(f); - return arr; -} - -FailInfo *failinfo_unwrap(const tal_t *ctx, const void *data, size_t len) -{ - struct ProtobufCAllocator *prototal = make_prototal(ctx); - FailInfo *f; - - f = fail_info__unpack(prototal, len, data); - if (f) - steal_from_prototal(ctx, prototal, f); - else - tal_free(prototal); - - return f; -} diff --git a/daemon/failure.h b/daemon/failure.h deleted file mode 100644 index 8ccb1d39b..000000000 --- a/daemon/failure.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef LIGHTNING_DAEMON_FAILURE_H -#define LIGHTNING_DAEMON_FAILURE_H -#include "config.h" -#include "lightning.pb-c.h" -#include -#include -#include - -struct pubkey; - -enum fail_error { - BAD_REQUEST_400 = 400, - UNAUTHORIZED_401 = 401, - PAYMENT_REQUIRED_402 = 402, - FORBIDDEN_403 = 403, - NOT_FOUND_404 = 404, - METHOD_NOT_ALLOWED_405 = 405, - REQUEST_TIMEOUT_408 = 408, - GONE_410 = 410, - IM_A_TEAPOT_418 = 418, - INTERNAL_SERVER_ERROR_500 = 500, - NOT_IMPLEMENTED_501 = 501, - BAD_GATEWAY_502 = 502, - SERVICE_UNAVAILABLE_503 = 503, - GATEWAY_TIMEOUT_504 = 504, - VERSION_NOT_SUPPORTED_505 = 505 -}; - -const u8 *failinfo_create(const tal_t *ctx, - const struct pubkey *id, - enum fail_error error_code, - const char *reason); - -FailInfo *failinfo_unwrap(const tal_t *ctx, const void *data, size_t len); - -#endif /* LIGHTNING_DAEMON_FAILURE_H */ diff --git a/daemon/feechange.c b/daemon/feechange.c deleted file mode 100644 index 3024a3267..000000000 --- a/daemon/feechange.c +++ /dev/null @@ -1,144 +0,0 @@ -#include "db.h" -#include "feechange.h" -#include "log.h" -#include "peer.h" -#include "peer_internal.h" -#include -#include - #include "gen_feechange_state_names.h" - -/* This is the HTLC-like flags for each state. */ -static const int per_state_bits[] = { - [SENT_FEECHANGE] = HTLC_ADDING + HTLC_LOCAL_F_OWNER - + HTLC_REMOTE_F_PENDING, - - [SENT_FEECHANGE_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER - + HTLC_REMOTE_F_COMMITTED - + HTLC_REMOTE_F_WAS_COMMITTED, - - [RCVD_FEECHANGE_REVOCATION] = HTLC_ADDING + HTLC_LOCAL_F_OWNER - + HTLC_REMOTE_F_COMMITTED - + HTLC_REMOTE_F_REVOKED - + HTLC_LOCAL_F_PENDING - + HTLC_REMOTE_F_WAS_COMMITTED, - - [RCVD_FEECHANGE_ACK_COMMIT] = HTLC_ADDING + HTLC_LOCAL_F_OWNER - + HTLC_REMOTE_F_COMMITTED - + HTLC_REMOTE_F_REVOKED - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_WAS_COMMITTED - + HTLC_REMOTE_F_WAS_COMMITTED, - - [SENT_FEECHANGE_ACK_REVOCATION] = HTLC_LOCAL_F_OWNER - + HTLC_REMOTE_F_COMMITTED - + HTLC_REMOTE_F_REVOKED - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_REVOKED - + HTLC_LOCAL_F_WAS_COMMITTED - + HTLC_REMOTE_F_WAS_COMMITTED, - - [RCVD_FEECHANGE] = HTLC_ADDING + HTLC_REMOTE_F_OWNER - + HTLC_LOCAL_F_PENDING, - - [RCVD_FEECHANGE_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_WAS_COMMITTED, - - [SENT_FEECHANGE_REVOCATION] = HTLC_ADDING + HTLC_REMOTE_F_OWNER - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_REVOKED - + HTLC_REMOTE_F_PENDING - + HTLC_LOCAL_F_WAS_COMMITTED, - - [SENT_FEECHANGE_ACK_COMMIT] = HTLC_ADDING + HTLC_REMOTE_F_OWNER - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_REVOKED - + HTLC_REMOTE_F_COMMITTED - + HTLC_LOCAL_F_WAS_COMMITTED - + HTLC_REMOTE_F_WAS_COMMITTED, - - [RCVD_FEECHANGE_ACK_REVOCATION] = HTLC_REMOTE_F_OWNER - + HTLC_LOCAL_F_COMMITTED - + HTLC_LOCAL_F_REVOKED - + HTLC_REMOTE_F_COMMITTED - + HTLC_REMOTE_F_REVOKED - + HTLC_LOCAL_F_WAS_COMMITTED - + HTLC_REMOTE_F_WAS_COMMITTED, -}; - -int feechange_state_flags(enum feechange_state state) -{ - assert(state < ARRAY_SIZE(per_state_bits)); - assert(per_state_bits[state]); - return per_state_bits[state]; -} - -const char *feechange_state_name(enum feechange_state s) -{ - size_t i; - - for (i = 0; enum_feechange_state_names[i].name; i++) - if (enum_feechange_state_names[i].v == s) - return enum_feechange_state_names[i].name; - return "unknown"; -} - -enum feechange_state feechange_state_from_name(const char *name) -{ - size_t i; - - for (i = 0; enum_feechange_state_names[i].name; i++) - if (streq(enum_feechange_state_names[i].name, name)) - return enum_feechange_state_names[i].v; - return FEECHANGE_STATE_INVALID; -} - -struct feechange *new_feechange(struct peer *peer, - u64 fee_rate, - enum feechange_state state) -{ - struct feechange *f = tal(peer, struct feechange); - f->state = state; - f->fee_rate = fee_rate; - - return f; -} - -void feechange_changestate(struct peer *peer, - struct feechange *f, - enum feechange_state oldstate, - enum feechange_state newstate, - bool db_commit) -{ - peer_debug(peer, "feechange: %s->%s", - feechange_state_name(f->state), - feechange_state_name(newstate)); - assert(f->state == oldstate); - assert(peer->feechanges[f->state] == f); - - /* You can only go to consecutive states. */ - assert(newstate == f->state + 1); - - /* You can't change sides. */ - assert(feechange_side(f->state) == feechange_side(newstate)); - - f->state = newstate; - - /* We can have multiple dead feestates, but only one in any other */ - if (!feechange_is_dead(f)) - assert(!peer->feechanges[f->state]); - - peer->feechanges[oldstate] = NULL; - peer->feechanges[newstate] = f; - - if (db_commit) { - if (newstate == RCVD_FEECHANGE_COMMIT - || newstate == SENT_FEECHANGE_COMMIT) - db_new_feechange(peer, f); - else if (newstate == RCVD_FEECHANGE_ACK_REVOCATION - || newstate == SENT_FEECHANGE_ACK_REVOCATION) - db_remove_feechange(peer, f, oldstate); - else - db_update_feechange_state(peer, f, oldstate); - } -} diff --git a/daemon/feechange.h b/daemon/feechange.h deleted file mode 100644 index 77dc02f09..000000000 --- a/daemon/feechange.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef LIGHTNING_DAEMON_FEECHANGE_H -#define LIGHTNING_DAEMON_FEECHANGE_H -#include "config.h" -#include "channel.h" -#include "feechange_state.h" - -struct peer; - -struct feechange { - /* What's the status */ - enum feechange_state state; - /* The rate. */ - u64 fee_rate; -}; - -static inline enum side feechange_side(enum feechange_state state) -{ - if (state <= SENT_FEECHANGE_ACK_REVOCATION) { - return LOCAL; - } else { - assert(state < FEECHANGE_STATE_INVALID); - return REMOTE; - } -} - -void feechange_changestate(struct peer *peer, - struct feechange *feechange, - enum feechange_state oldstate, - enum feechange_state newstate, - bool db_commit); - -struct feechange *new_feechange(struct peer *peer, - u64 fee_rate, - enum feechange_state state); - -const char *feechange_state_name(enum feechange_state s); -enum feechange_state feechange_state_from_name(const char *name); - -/* HTLC-add-style bitflags for each feechange state */ -int feechange_state_flags(enum feechange_state state); - -static inline bool feechange_has(const struct feechange *f, int flag) -{ - return feechange_state_flags(f->state) & flag; -} - -static inline bool feechange_is_dead(const struct feechange *feechange) -{ - return feechange->state == SENT_FEECHANGE_ACK_REVOCATION - || feechange->state == RCVD_FEECHANGE_ACK_REVOCATION; -} -#endif /* LIGHTNING_DAEMON_FEECHANGE_H */ diff --git a/daemon/feechange_state.h b/daemon/feechange_state.h deleted file mode 100644 index 6841d15a9..000000000 --- a/daemon/feechange_state.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LIGHTNING_DAEMON_FEECHANGE_STATE_H -#define LIGHTNING_DAEMON_FEECHANGE_STATE_H -#include "config.h" - -/* Like HTLCs, but only adding; we never "remove" a feechange. */ -enum feechange_state { - /* When we add a new feechange, it goes in this order. */ - SENT_FEECHANGE, - SENT_FEECHANGE_COMMIT, - RCVD_FEECHANGE_REVOCATION, - RCVD_FEECHANGE_ACK_COMMIT, - SENT_FEECHANGE_ACK_REVOCATION, - - /* When they add a new feechange, it goes in this order. */ - RCVD_FEECHANGE, - RCVD_FEECHANGE_COMMIT, - SENT_FEECHANGE_REVOCATION, - SENT_FEECHANGE_ACK_COMMIT, - RCVD_FEECHANGE_ACK_REVOCATION, - - FEECHANGE_STATE_INVALID -}; -#endif /* LIGHTNING_DAEMON_FEECHANGE_STATE_H */ diff --git a/daemon/htlc.c b/daemon/htlc.c deleted file mode 100644 index db51dc42c..000000000 --- a/daemon/htlc.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "db.h" -#include "htlc.h" -#include "log.h" -#include "peer.h" -#include "peer_internal.h" -#include "type_to_string.h" -#include -#include -#include - -void htlc_changestate(struct htlc *h, - enum htlc_state oldstate, - enum htlc_state newstate, - bool db_commit) -{ - peer_debug(h->peer, "htlc %"PRIu64": %s->%s", h->id, - htlc_state_name(h->state), htlc_state_name(newstate)); - assert(h->state == oldstate); - - /* You can only go to consecutive states. */ - assert(newstate == h->state + 1); - - /* You can't change sides. */ - assert((htlc_state_flags(h->state)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) - == (htlc_state_flags(newstate)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - - h->state = newstate; - - if (db_commit) { - if (newstate == RCVD_ADD_COMMIT || newstate == SENT_ADD_COMMIT) { - db_new_htlc(h->peer, h); - return; - } - /* These never hit the database. */ - if (oldstate == RCVD_REMOVE_HTLC) - oldstate = SENT_ADD_ACK_REVOCATION; - else if (oldstate == SENT_REMOVE_HTLC) - oldstate = RCVD_ADD_ACK_REVOCATION; - db_update_htlc_state(h->peer, h, oldstate); - } -} - -void htlc_undostate(struct htlc *h, - enum htlc_state oldstate, - enum htlc_state newstate) -{ - log_debug(h->peer->log, "htlc %"PRIu64": %s->%s", h->id, - htlc_state_name(h->state), htlc_state_name(newstate)); - assert(h->state == oldstate); - - /* You can only return to previous state. */ - assert(newstate == h->state - 1); - - /* And must only be proposal, not commit. */ - assert(h->state == SENT_REMOVE_HTLC || h->state == RCVD_REMOVE_HTLC); - - /* You can't change sides. */ - assert((htlc_state_flags(h->state)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER)) - == (htlc_state_flags(newstate)&(HTLC_LOCAL_F_OWNER|HTLC_REMOTE_F_OWNER))); - - h->state = newstate; -} - -static char *fmt_htlc(const tal_t *ctx, const struct htlc *h) -{ - return tal_fmt(ctx, "{ id=%"PRIu64 - " msatoshi=%"PRIu64 - " expiry=%s" - " rhash=%s" - " rval=%s" - " src=%s }", - h->id, h->msatoshi, - type_to_string(ctx, struct abs_locktime, &h->expiry), - type_to_string(ctx, struct sha256, &h->rhash), - h->r ? tal_hexstr(ctx, h->r, sizeof(*h->r)) - : "UNKNOWN", - h->src ? type_to_string(ctx, struct pubkey, - h->src->peer->id) - : "local"); -} -REGISTER_TYPE_TO_STRING(htlc, fmt_htlc); diff --git a/daemon/invoice.c b/daemon/invoice.c index 7699ff8f0..db66257ae 100644 --- a/daemon/invoice.c +++ b/daemon/invoice.c @@ -102,6 +102,15 @@ static void tell_waiter(struct command *cmd, const struct invoice *paid) command_success(cmd, response); } +/* UNIFICATION FIXME */ +void db_resolve_invoice(struct lightningd_state *dstate, + const char *label, u64 paid_num); +bool db_new_invoice(struct lightningd_state *dstate, + u64 msatoshi, + const char *label, + const struct preimage *r); +bool db_remove_invoice(struct lightningd_state *dstate, const char *label); + void resolve_invoice(struct lightningd_state *dstate, struct invoice *invoice) { struct invoice_waiter *w; diff --git a/daemon/irc_announce.c b/daemon/irc_announce.c deleted file mode 100644 index f45dac401..000000000 --- a/daemon/irc_announce.c +++ /dev/null @@ -1,280 +0,0 @@ -#include "bitcoin/privkey.h" -#include "bitcoin/signature.h" -#include "daemon/chaintopology.h" -#include "daemon/irc_announce.h" -#include "daemon/lightningd.h" -#include "daemon/log.h" -#include "daemon/peer.h" -#include "daemon/peer_internal.h" -#include "daemon/routing.h" -#include "daemon/secrets.h" -#include "daemon/timeout.h" -#include "utils.h" - -#include -#include - -/* Sign a privmsg by prepending the signature to the message */ -static void sign_privmsg(struct ircstate *state, struct privmsg *msg) -{ - int siglen; - u8 der[72]; - secp256k1_ecdsa_signature sig; - privkey_sign(state->dstate, msg->msg, strlen(msg->msg), &sig); - siglen = signature_to_der(der, &sig); - msg->msg = tal_fmt(msg, "%s %s", tal_hexstr(msg, der, siglen), msg->msg); -} - -static bool announce_channel(const tal_t *ctx, struct ircstate *state, struct peer *p) -{ - char txid[65]; - struct privmsg *msg = talz(ctx, struct privmsg); - struct txlocator *loc = locate_tx(ctx, state->dstate->topology, &p->anchor.txid); - - if (loc == NULL) - return false; - - bitcoin_txid_to_hex(&p->anchor.txid, txid, sizeof(txid)); - msg->channel = "#lightning-nodes"; - msg->msg = tal_fmt( - msg, "CHAN %s %s %s %d %d %d %d %d", - pubkey_to_hexstr(msg, &state->dstate->id), - pubkey_to_hexstr(msg, p->id), - txid, - loc->blkheight, - loc->index, - state->dstate->config.fee_base, - state->dstate->config.fee_per_satoshi, - state->dstate->config.min_htlc_expiry - ); - sign_privmsg(state, msg); - irc_send_msg(state, msg); - return true; -} - -/* Send an announcement for this node to the channel, including its - * hostname, port and ID */ -static void announce_node(const tal_t *ctx, struct ircstate *state) -{ - char *hostname = state->dstate->external_ip; - int port = state->dstate->portnum; - struct privmsg *msg = talz(ctx, struct privmsg); - - if (hostname == NULL) { - //FIXME: log that we don't know our IP yet. - return; - } - - msg->channel = "#lightning-nodes"; - msg->msg = tal_fmt( - msg, "NODE %s %s %d", - pubkey_to_hexstr(msg, &state->dstate->id), - hostname, - port - ); - - sign_privmsg(state, msg); - irc_send_msg(state, msg); -} - -/* Announce the node's contact information and all of its channels */ -static void announce(struct ircstate *state) -{ - - tal_t *ctx = tal(state, tal_t); - struct peer *p; - - announce_node(ctx, state); - - list_for_each(&state->dstate->peers, p, list) { - - if (!state_is_normal(p->state)) - continue; - announce_channel(ctx, state, p); - } - tal_free(ctx); - - /* By default we announce every 6 hours, otherwise when someone joins */ - log_debug(state->log, "Setting long announce time: 6 hours"); - state->dstate->announce = new_reltimer(&state->dstate->timers, state, - time_from_sec(3600 * 6), - announce, state); -} - -/* Reconnect to IRC server upon disconnection. */ -static void handle_irc_disconnect(struct ircstate *state) -{ - /* Stop announcing. */ - state->dstate->announce = tal_free(state->dstate->announce); - new_reltimer(&state->dstate->timers, state, state->reconnect_timeout, - irc_connect, state); -} - -/* Verify a signed privmsg */ -static bool verify_signed_privmsg( - struct ircstate *istate, - const struct pubkey *pk, - const struct privmsg *msg) -{ - secp256k1_ecdsa_signature sig; - struct sha256_double hash; - const char *m = msg->msg + 1; - int siglen = strchr(m, ' ') - m; - const char *content = m + siglen + 1; - u8 *der = tal_hexdata(msg, m, siglen); - - siglen = hex_data_size(siglen); - if (der == NULL) - return false; - - if (!signature_from_der(der, siglen, &sig)) - return false; - sha256_double(&hash, content, strlen(content)); - return check_signed_hash(&hash, &sig, pk); -} - -static void handle_irc_channel_announcement( - struct ircstate *istate, - const struct privmsg *msg, - char **splits) -{ - struct pubkey *pk1 = talz(msg, struct pubkey); - struct pubkey *pk2 = talz(msg, struct pubkey); - struct sha256_double *txid = talz(msg, struct sha256_double); - int index; - bool ok = true; - int blkheight; - - ok &= pubkey_from_hexstr(splits[1], strlen(splits[1]), pk1); - ok &= pubkey_from_hexstr(splits[2], strlen(splits[2]), pk2); - ok &= bitcoin_txid_from_hex(splits[3], strlen(splits[3]), txid); - blkheight = atoi(splits[4]); - index = atoi(splits[5]); - if (!ok || index < 0 || blkheight < 0) { - log_debug(istate->dstate->base_log, "Unable to parse channel announcent."); - return; - } - - if (!verify_signed_privmsg(istate, pk1, msg)) { - log_debug(istate->log, - "Ignoring announcement from %s, signature check failed.", - splits[1]); - return; - } - - /* - * FIXME Check in topology that the tx is in the block and - * that the endpoints match. - */ - - add_connection(istate->dstate->rstate, pk1, pk2, atoi(splits[6]), - atoi(splits[7]), atoi(splits[8]), 6); -} - -static void handle_irc_node_announcement( - struct ircstate *istate, - const struct privmsg *msg, - char **splits) -{ - struct pubkey *pk = talz(msg, struct pubkey); - if (!pubkey_from_hexstr(splits[1], strlen(splits[1]), pk)) - return; - - if (!verify_signed_privmsg(istate, pk, msg)) { - log_debug(istate->log, "Ignoring node announcement from %s, signature check failed.", - splits[1]); - return; - } else if(splits[4] != NULL && strlen(splits[4]) > 64) { - log_debug(istate->log, "Ignoring node announcement from %s, alias too long", - splits[1]); - } - - struct node *node = add_node(istate->dstate->rstate, pk); - if (splits[4] != NULL){ - tal_free(node->alias); - node->alias = tal_hexdata(node, splits[4], strlen(splits[4])); - } -} - -/* - * Handle an incoming message by checking if it is a channel - * announcement, parse it and add the channel to the topology if yes. - * - * The format for a valid announcement is: - * CHAN - * - */ -static void handle_irc_privmsg(struct ircstate *istate, const struct privmsg *msg) -{ - char **splits = tal_strsplit(msg, msg->msg + 1, " ", STR_NO_EMPTY); - int splitcount = tal_count(splits) - 1; - - if (splitcount < 2) - return; - - char *type = splits[1]; - - if (splitcount == 10 && streq(type, "CHAN")) - handle_irc_channel_announcement(istate, msg, splits + 1); - else if (splitcount >= 5 && streq(type, "NODE")) - handle_irc_node_announcement(istate, msg, splits + 1); -} - -static void handle_irc_command(struct ircstate *istate, const struct irccommand *cmd) -{ - struct lightningd_state *dstate = istate->dstate; - char **params = tal_strsplit(cmd, cmd->params, " ", STR_NO_EMPTY); - - if (streq(cmd->command, "338") && tal_count(params) >= 4) { - dstate->external_ip = tal_strdup( - istate->dstate, params[3]); - log_debug(dstate->base_log, "Detected my own IP as %s", dstate->external_ip); - - // Add our node to the node_map for completeness - add_node(istate->dstate->rstate, &dstate->id); - } else if (streq(cmd->command, "JOIN")) { - unsigned int delay; - - /* Throw away any existing announce timer, and announce within - * 60 seconds. */ - dstate->announce = tal_free(dstate->announce); - - delay = pseudorand(60000000); - log_debug(istate->log, "Setting new announce time %u sec", - delay / 1000000); - dstate->announce = new_reltimer(&dstate->timers, istate, - time_from_usec(delay), - announce, istate); - } -} - -static void handle_irc_connected(struct ircstate *istate) -{ - irc_send(istate, "JOIN", "#lightning-nodes"); - irc_send(istate, "WHOIS", "%s", istate->nick); -} - -void setup_irc_connection(struct lightningd_state *dstate) -{ - // Register callback - irc_privmsg_cb = *handle_irc_privmsg; - irc_connect_cb = *handle_irc_connected; - irc_disconnect_cb = *handle_irc_disconnect; - irc_command_cb = *handle_irc_command; - - struct ircstate *state = talz(dstate, struct ircstate); - state->dstate = dstate; - state->server = "irc.lfnet.org"; - state->reconnect_timeout = time_from_sec(15); - state->log = new_log(state, state->dstate->log_book, "%s:irc", - log_prefix(state->dstate->base_log)); - - /* Truncate nick at 13 bytes, would be imposed by freenode anyway */ - state->nick = tal_fmt( - state, - "N%.12s", - pubkey_to_hexstr(state, &dstate->id) + 1); - - /* We will see our own JOIN message, which will trigger announce */ - irc_connect(state); -} diff --git a/daemon/irc_announce.h b/daemon/irc_announce.h deleted file mode 100644 index bce649771..000000000 --- a/daemon/irc_announce.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef LIGHTNING_DAEMON_IRC_ANNOUNCE_H -#define LIGHTNING_DAEMON_IRC_ANNOUNCE_H -#include "config.h" -#include "irc.h" - -// Main entrypoint for the lightning daemon -void setup_irc_connection(struct lightningd_state *dstate); - -#endif /* LIGHTNING_DAEMON_IRC_ANNOUNCE_H */ diff --git a/daemon/jsonrpc.c b/daemon/jsonrpc.c index 42659cb48..a32f644e3 100644 --- a/daemon/jsonrpc.c +++ b/daemon/jsonrpc.c @@ -5,7 +5,6 @@ #include "jsonrpc.h" #include "lightningd.h" #include "log.h" -#include "peer.h" #include "version.h" #include #include @@ -231,6 +230,9 @@ static const struct json_command dev_crash_command = { }; AUTODATA(json_command, &dev_crash_command); +/* UNIFICATION FIXME */ +void debug_dump_peers(struct lightningd_state *dstate); + static void json_restart(struct command *cmd, const char *buffer, const jsmntok_t *params) { diff --git a/daemon/lightningd.c b/daemon/lightningd.c deleted file mode 100644 index e4b198036..000000000 --- a/daemon/lightningd.c +++ /dev/null @@ -1,174 +0,0 @@ -#include "bitcoind.h" -#include "chaintopology.h" -#include "db.h" -#include "invoice.h" -#include "irc_announce.h" -#include "jsonrpc.h" -#include "lightningd.h" -#include "log.h" -#include "options.h" -#include "p2p_announce.h" -#include "peer.h" -#include "routing.h" -#include "secrets.h" -#include "timeout.h" -#include "utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct lightningd_state *lightningd_state(void) -{ - struct lightningd_state *dstate = tal(NULL, struct lightningd_state); - struct sha256_double unused; - - dstate->log_book = new_log_book(dstate, 20*1024*1024, LOG_INFORM); - dstate->base_log = new_log(dstate, dstate->log_book, - "lightningd(%u):", (int)getpid()); - - list_head_init(&dstate->peers); - list_head_init(&dstate->pay_commands); - dstate->portnum = 0; - dstate->testnet = true; - timers_init(&dstate->timers, time_mono()); - list_head_init(&dstate->wallet); - list_head_init(&dstate->addresses); - dstate->dev_never_routefail = false; - dstate->rstate = new_routing_state(dstate, dstate->base_log, &unused); - dstate->reexec = NULL; - dstate->external_ip = NULL; - dstate->announce = NULL; - dstate->invoices = invoices_init(dstate); - return dstate; -} - -static void json_lightningd_dev_broadcast(struct command *cmd, - const char *buffer, - const jsmntok_t *params) -{ - json_dev_broadcast(cmd, cmd->dstate->topology, buffer, params); -} - -static const struct json_command dev_broadcast_command = { - "dev-broadcast", - json_lightningd_dev_broadcast, - "Pretend we broadcast txs, but don't send to bitcoind", - "Returns an empty result on success (waits for flush if enabled)" -}; -AUTODATA(json_command, &dev_broadcast_command); - -int main(int argc, char *argv[]) -{ - struct lightningd_state *dstate = lightningd_state(); - - err_set_progname(argv[0]); - - if (!streq(protobuf_c_version(), PROTOBUF_C_VERSION)) - errx(1, "Compiled against protobuf %s, but have %s", - PROTOBUF_C_VERSION, protobuf_c_version()); - - secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY - | SECP256K1_CONTEXT_SIGN); - - dstate->topology = new_topology(dstate, dstate->base_log); - dstate->bitcoind = new_bitcoind(dstate, dstate->base_log); - dstate->bitcoind->chainparams = chainparams_for_network("regtest"); - - /* Handle options and config; move to .lightningd */ - register_opts(dstate); - handle_opts(dstate, argc, argv); - - /* Now we can set chain_hash properly. */ - dstate->rstate->chain_hash - = dstate->bitcoind->chainparams->genesis_blockhash; - - /* Activate crash log now we're in the right place. */ - crashlog_activate(dstate->base_log); - - /* Ignore SIGPIPE: we look at our write return values*/ - signal(SIGPIPE, SIG_IGN); - - /* Set up node ID and private key. */ - secrets_init(dstate); - new_node(dstate->rstate, &dstate->id); - - /* Read or create database. */ - db_init(dstate); - - /* Initialize block topology. */ - setup_topology(dstate->topology, dstate->bitcoind, &dstate->timers, - dstate->config.poll_time, - get_peer_min_block(dstate)); - - /* Create RPC socket (if any) */ - setup_jsonrpc(dstate, dstate->rpc_filename); - - /* Set up connections from peers (if dstate->portnum is set) */ - setup_listeners(dstate); - - /* set up IRC peer discovery */ - if (dstate->config.use_irc) - setup_irc_connection(dstate); - - /* set up P2P gossip protocol */ - setup_p2p_announce(dstate); - - log_info(dstate->base_log, "Hello world!"); - - /* If we loaded peers from database, reconnect now. */ - reconnect_peers(dstate); - - /* And send out anchors again if we're waiting. */ - rebroadcast_anchors(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); - else - cleanup_peers(dstate); - } - - if (dstate->reexec) { - int fd; - - log_unusual(dstate->base_log, "Restart at user request"); - fflush(stdout); - fflush(stderr); - - /* Manually close all fds (or near enough!) */ - for (fd = 3; fd < 1024; fd++) - close(fd); - - if (dstate->dev_never_routefail) { - size_t n = tal_count(dstate->reexec); - tal_resizez(&dstate->reexec, n+1); - dstate->reexec[n-1] = "--dev-no-routefail"; - } - execvp(dstate->reexec[0], dstate->reexec); - fatal("Exec '%s' failed: %s", - dstate->reexec[0], strerror(errno)); - } - - tal_free(dstate); - opt_free_table(); - return 0; -} diff --git a/daemon/names.c b/daemon/names.c deleted file mode 100644 index 246a98daa..000000000 --- a/daemon/names.c +++ /dev/null @@ -1,36 +0,0 @@ -#include "names.h" -#include -/* Indented for 'check-source' because it has to be included after names.h */ - #include "daemon/gen_state_names.h" - #include "daemon/gen_pkt_names.h" - -const char *state_name(enum state s) -{ - size_t i; - - for (i = 0; enum_state_names[i].name; i++) - if (enum_state_names[i].v == s) - return enum_state_names[i].name; - return "unknown"; -} - -enum state name_to_state(const char *name) -{ - size_t i; - - for (i = 0; enum_state_names[i].name; i++) - if (streq(name, enum_state_names[i].name)) - return enum_state_names[i].v; - - return STATE_MAX; -} - -const char *pkt_name(Pkt__PktCase pkt) -{ - size_t i; - - for (i = 0; enum_PktCase_names[i].name; i++) - if (enum_PktCase_names[i].v == pkt) - return enum_PktCase_names[i].name; - return "unknown"; -} diff --git a/daemon/names.h b/daemon/names.h deleted file mode 100644 index 04072773e..000000000 --- a/daemon/names.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef LIGHTNING_NAMES_H -#define LIGHTNING_NAMES_H -#include "config.h" -#include "lightning.pb-c.h" -#include "state_types.h" - -const char *state_name(enum state s); -enum state name_to_state(const char *name); -const char *pkt_name(Pkt__PktCase pkt); -#endif /* LIGHTNING_NAMES_H */ diff --git a/daemon/output_to_htlc.c b/daemon/output_to_htlc.c deleted file mode 100644 index c91d7fbe1..000000000 --- a/daemon/output_to_htlc.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "commit_tx.h" -#include "output_to_htlc.h" -#include "peer.h" -#include "peer_internal.h" - -/* FIXME: Array makes this O(n^2). Use a hash table. */ -struct wscript_by_wpkh { - struct htlc *h; - const u8 *wscript; - struct sha256 hash; -}; - -struct htlc_output_map { - struct wscript_by_wpkh *wpkh; -}; - -struct htlc_output_map *get_htlc_output_map(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - unsigned int commit_num) -{ - struct htlc_map_iter it; - struct htlc *h; - size_t i; - struct htlc_output_map *omap = tal(ctx, struct htlc_output_map); - - /* FIXME: use commit_num to filter htlcs. */ - if (side == LOCAL) - assert(commit_num <= peer->local.commit->commit_num); - else - assert(commit_num <= peer->remote.commit->commit_num); - - omap->wpkh = tal_arr(omap, struct wscript_by_wpkh, - htlc_map_count(&peer->htlcs)); - - for (i = 0, h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - omap->wpkh[i].h = h; - omap->wpkh[i].wscript = wscript_for_htlc(omap, peer, h, rhash, - side); - sha256(&omap->wpkh[i].hash, - omap->wpkh[i].wscript, - tal_count(omap->wpkh[i].wscript)); - i++; - } - tal_resize(&omap->wpkh, i); - return omap; -} - -static struct wscript_by_wpkh *get_wpkh(struct htlc_output_map *omap, - const u8 *script) -{ - size_t i; - - if (!is_p2wsh(script)) - return NULL; - - for (i = 0; i < tal_count(omap->wpkh); i++) { - if (!memcmp(script + 2, omap->wpkh[i].hash.u.u8, - sizeof(omap->wpkh[i].hash))) - return &omap->wpkh[i]; - } - return NULL; -} - -/* Which wscript does this pay to? */ -struct htlc *txout_get_htlc(struct htlc_output_map *omap, - const u8 *script, - const u8 **wscript) -{ - struct wscript_by_wpkh *wpkh = get_wpkh(omap, script); - - if (wpkh) { - *wscript = wpkh->wscript; - return wpkh->h; - } - return NULL; -} diff --git a/daemon/output_to_htlc.h b/daemon/output_to_htlc.h deleted file mode 100644 index 2963b473b..000000000 --- a/daemon/output_to_htlc.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H -#define LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H -#include "config.h" -#include "htlc.h" - -struct peer; -struct sha256; - -/* Get a map of HTLCs (including at least those at the given commit_num). */ -struct htlc_output_map *get_htlc_output_map(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *rhash, - enum side side, - unsigned int commit_num); - -/* If this scriptPubkey pays to a HTLC, get the full wscript */ -struct htlc *txout_get_htlc(struct htlc_output_map *omap, - const u8 *script, const u8 **wscript); - -#endif /* LIGHTNING_DAEMON_OUTPUT_TO_HTLC_H */ diff --git a/daemon/p2p_announce.c b/daemon/p2p_announce.c deleted file mode 100644 index 874a036e6..000000000 --- a/daemon/p2p_announce.c +++ /dev/null @@ -1,231 +0,0 @@ -#include "daemon/broadcast.h" -#include "daemon/chaintopology.h" -#include "daemon/log.h" -#include "daemon/p2p_announce.h" -#include "daemon/packets.h" -#include "daemon/peer.h" -#include "daemon/peer_internal.h" -#include "daemon/routing.h" -#include "daemon/secrets.h" -#include "daemon/timeout.h" -#include "utils.h" - -#include -#include -#include - -static void broadcast_channel_update(struct lightningd_state *dstate, struct peer *peer) -{ - struct txlocator *loc; - u8 *serialized; - secp256k1_ecdsa_signature signature; - struct short_channel_id short_channel_id; - u32 timestamp = time_now().ts.tv_sec; - const tal_t *tmpctx = tal_tmpctx(dstate); - - loc = locate_tx(tmpctx, dstate->topology, &peer->anchor.txid); - short_channel_id.blocknum = loc->blkheight; - short_channel_id.txnum = loc->index; - short_channel_id.outnum = peer->anchor.index; - - /* Avoid triggering memcheck */ - memset(&signature, 0, sizeof(signature)); - - serialized = towire_channel_update(tmpctx, &signature, - &dstate->rstate->chain_hash, - &short_channel_id, - timestamp, - pubkey_cmp(&dstate->id, peer->id) > 0, - dstate->config.min_htlc_expiry, - //FIXME(cdecker) Make the minimum HTLC configurable - 1, - dstate->config.fee_base, - dstate->config.fee_per_satoshi); - privkey_sign(dstate, serialized + 66, tal_count(serialized) - 66, - &signature); - serialized = towire_channel_update(tmpctx, &signature, - &dstate->rstate->chain_hash, - &short_channel_id, - timestamp, - pubkey_cmp(&dstate->id, peer->id) > 0, - dstate->config.min_htlc_expiry, - 1, - dstate->config.fee_base, - dstate->config.fee_per_satoshi); - u8 *tag = tal_arr(tmpctx, u8, 0); - towire_short_channel_id(&tag, &short_channel_id); - queue_broadcast(dstate->rstate->broadcasts, WIRE_CHANNEL_UPDATE, tag, serialized); - tal_free(tmpctx); -} - -static void broadcast_node_announcement(struct lightningd_state *dstate) -{ - u8 *serialized; - secp256k1_ecdsa_signature signature; - static const u8 rgb_color[3]; - static const u8 alias[32]; - u32 timestamp = time_now().ts.tv_sec; - const tal_t *tmpctx = tal_tmpctx(dstate); - u8 *address; - - /* Are we listening for incoming connections at all? */ - if (!dstate->external_ip || !dstate->portnum) { - tal_free(tmpctx); - return; - } - - /* Avoid triggering memcheck */ - memset(&signature, 0, sizeof(signature)); - - address = write_ip(tmpctx, dstate->external_ip, dstate->portnum); - serialized = towire_node_announcement(tmpctx, &signature, - NULL, - timestamp, - &dstate->id, rgb_color, alias, - address); - privkey_sign(dstate, serialized + 66, tal_count(serialized) - 66, - &signature); - serialized = towire_node_announcement(tmpctx, &signature, - NULL, - timestamp, - &dstate->id, rgb_color, alias, - address); - u8 *tag = tal_arr(tmpctx, u8, 0); - towire_pubkey(&tag, &dstate->id); - queue_broadcast(dstate->rstate->broadcasts, WIRE_NODE_ANNOUNCEMENT, tag, - serialized); - tal_free(tmpctx); -} - -static void broadcast_channel_announcement(struct lightningd_state *dstate, struct peer *peer) -{ - struct txlocator *loc; - struct short_channel_id short_channel_id; - secp256k1_ecdsa_signature node_signature[2]; - secp256k1_ecdsa_signature bitcoin_signature[2]; - const struct pubkey *node_id[2]; - const struct pubkey *bitcoin_key[2]; - secp256k1_ecdsa_signature *my_node_signature; - secp256k1_ecdsa_signature *my_bitcoin_signature; - u8 *serialized; - const tal_t *tmpctx = tal_tmpctx(dstate); - - loc = locate_tx(tmpctx, dstate->topology, &peer->anchor.txid); - - short_channel_id.blocknum = loc->blkheight; - short_channel_id.txnum = loc->index; - short_channel_id.outnum = peer->anchor.index; - - /* Set all sigs to zero */ - memset(node_signature, 0, sizeof(node_signature)); - memset(bitcoin_signature, 0, sizeof(bitcoin_signature)); - - //FIXME(cdecker) Copy remote stored signatures into place - if (pubkey_cmp(&dstate->id, peer->id) > 0) { - node_id[0] = peer->id; - node_id[1] = &dstate->id; - bitcoin_key[0] = peer->id; - bitcoin_key[1] = &dstate->id; - my_node_signature = &node_signature[1]; - my_bitcoin_signature = &bitcoin_signature[1]; - } else { - node_id[1] = peer->id; - node_id[0] = &dstate->id; - bitcoin_key[1] = peer->id; - bitcoin_key[0] = &dstate->id; - my_node_signature = &node_signature[0]; - my_bitcoin_signature = &bitcoin_signature[0]; - } - - /* Sign the node_id with the bitcoin_key, proves delegation */ - serialized = tal_arr(tmpctx, u8, 0); - towire_pubkey(&serialized, &dstate->id); - privkey_sign(dstate, serialized, tal_count(serialized), my_bitcoin_signature); - - /* BOLT #7: - * - * The creating node MUST compute the double-SHA256 hash `h` of the - * message, starting at offset 256, up to the end of the message. - */ - serialized = towire_channel_announcement(tmpctx, &node_signature[0], - &node_signature[1], - &bitcoin_signature[0], - &bitcoin_signature[1], - NULL, - &dstate->rstate->chain_hash, - &short_channel_id, - node_id[0], - node_id[1], - bitcoin_key[0], - bitcoin_key[1]); - privkey_sign(dstate, serialized + 256, tal_count(serialized) - 256, my_node_signature); - - serialized = towire_channel_announcement(tmpctx, &node_signature[0], - &node_signature[1], - &bitcoin_signature[0], - &bitcoin_signature[1], - NULL, - &dstate->rstate->chain_hash, - &short_channel_id, - node_id[0], - node_id[1], - bitcoin_key[0], - bitcoin_key[1]); - u8 *tag = tal_arr(tmpctx, u8, 0); - towire_short_channel_id(&tag, &short_channel_id); - queue_broadcast(dstate->rstate->broadcasts, WIRE_CHANNEL_ANNOUNCEMENT, - tag, serialized); - tal_free(tmpctx); -} - -static void announce(struct lightningd_state *dstate) -{ - struct peer *p; - int nchan = 0; - - new_reltimer(&dstate->timers, dstate, time_from_sec(5*60*60), announce, dstate); - - list_for_each(&dstate->peers, p, list) { - if (state_is_normal(p->state)) { - broadcast_channel_announcement(dstate, p); - broadcast_channel_update(dstate, p); - nchan += 1; - } - } - - /* No point in broadcasting our node if we don't have a channel */ - if (nchan > 0) - broadcast_node_announcement(dstate); -} - -void announce_channel(struct lightningd_state *dstate, struct peer *peer) -{ - broadcast_channel_announcement(dstate, peer); - broadcast_channel_update(dstate, peer); - broadcast_node_announcement(dstate); - -} - -static void process_broadcast_queue(struct lightningd_state *dstate) -{ - struct peer *p; - struct queued_message *msg; - new_reltimer(&dstate->timers, dstate, time_from_sec(30), process_broadcast_queue, dstate); - list_for_each(&dstate->peers, p, list) { - if (!state_is_normal(p->state)) - continue; - msg = next_broadcast_message(dstate->rstate->broadcasts, - &p->broadcast_index); - while (msg != NULL) { - queue_pkt_nested(p, msg->type, msg->payload); - msg = next_broadcast_message(dstate->rstate->broadcasts, - &p->broadcast_index); - } - } -} - -void setup_p2p_announce(struct lightningd_state *dstate) -{ - new_reltimer(&dstate->timers, dstate, time_from_sec(5*60*60), announce, dstate); - new_reltimer(&dstate->timers, dstate, time_from_sec(30), process_broadcast_queue, dstate); -} diff --git a/daemon/p2p_announce.h b/daemon/p2p_announce.h deleted file mode 100644 index 32ba88103..000000000 --- a/daemon/p2p_announce.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LIGHTNING_DAEMON_P2P_ANNOUNCE_H -#define LIGHTNING_DAEMON_P2P_ANNOUNCE_H -#include "config.h" -#include "daemon/broadcast.h" -#include "daemon/lightningd.h" -#include "daemon/routing.h" -#include "lightningd.h" -#include "wire/gen_peer_wire.h" - -void setup_p2p_announce(struct lightningd_state *dstate); - -/* Used to announce the existence of a channel and the endpoints */ -void announce_channel(struct lightningd_state *dstate, struct peer *peer); - -#endif /* LIGHTNING_DAEMON_P2P_ANNOUNCE_H */ diff --git a/daemon/packets.c b/daemon/packets.c deleted file mode 100644 index 5b8833713..000000000 --- a/daemon/packets.c +++ /dev/null @@ -1,599 +0,0 @@ -#include "bitcoin/preimage.h" -#include "bitcoin/script.h" -#include "bitcoin/tx.h" -#include "chaintopology.h" -#include "close_tx.h" -#include "commit_tx.h" -#include "cryptopkt.h" -#include "htlc.h" -#include "lightningd.h" -#include "log.h" -#include "names.h" -#include "packets.h" -#include "peer.h" -#include "peer_internal.h" -#include "protobuf_convert.h" -#include "secrets.h" -#include "state.h" -#include "utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Wrap (and own!) member inside Pkt */ -static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) -{ - Pkt *pkt = tal(ctx, Pkt); - - pkt__init(pkt); - pkt->pkt_case = type; - /* This is a union, so doesn't matter which we assign. */ - pkt->error = (Error *)tal_steal(pkt, msg); - - /* This makes sure all packets are valid. */ -#ifndef NDEBUG - { - size_t len; - u8 *packed; - Pkt *cpy; - - len = pkt__get_packed_size(pkt); - packed = tal_arr(pkt, u8, len); - pkt__pack(pkt, packed); - cpy = pkt__unpack(NULL, len, memcheck(packed, len)); - assert(cpy); - pkt__free_unpacked(cpy, NULL); - tal_free(packed); - } -#endif - return pkt; -} - -static void queue_raw_pkt(struct peer *peer, Pkt *pkt) -{ - size_t n = tal_count(peer->outpkt); - tal_resize(&peer->outpkt, n+1); - peer->outpkt[n] = pkt; - - log_debug(peer->log, "Queued pkt %s (order=%"PRIu64")", - pkt_name(pkt->pkt_case), peer->order_counter); - - /* In case it was waiting for output. */ - io_wake(peer); -} - -static void queue_pkt(struct peer *peer, Pkt__PktCase type, const void *msg) -{ - queue_raw_pkt(peer, make_pkt(peer, type, msg)); -} - -void queue_pkt_open(struct peer *peer, bool offer_anchor) -{ - OpenChannel *o = tal(peer, OpenChannel); - - open_channel__init(o); - o->revocation_hash = sha256_to_proto(o, &peer->local.commit->revocation_hash); - o->next_revocation_hash = sha256_to_proto(o, &peer->local.next_revocation_hash); - o->commit_key = pubkey_to_proto(o, &peer->local.commitkey); - o->final_key = pubkey_to_proto(o, &peer->local.finalkey); - o->delay = tal(o, Locktime); - locktime__init(o->delay); - o->delay->locktime_case = LOCKTIME__LOCKTIME_BLOCKS; - o->delay->blocks = rel_locktime_to_blocks(&peer->local.locktime); - o->initial_fee_rate = peer->local.commit_fee_rate; - if (offer_anchor) - o->anch = OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR; - else - o->anch = OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR; - o->min_depth = peer->local.mindepth; - queue_pkt(peer, PKT__PKT_OPEN, o); -} - -void queue_pkt_anchor(struct peer *peer) -{ - OpenAnchor *a = tal(peer, OpenAnchor); - - open_anchor__init(a); - a->txid = sha256_to_proto(a, &peer->anchor.txid.sha); - a->output_index = peer->anchor.index; - a->amount = peer->anchor.satoshis; - - queue_pkt(peer, PKT__PKT_OPEN_ANCHOR, a); -} - -void queue_pkt_open_commit_sig(struct peer *peer) -{ - OpenCommitSig *s = tal(peer, OpenCommitSig); - - open_commit_sig__init(s); - - s->sig = signature_to_proto(s, peer->remote.commit->sig); - - queue_pkt(peer, PKT__PKT_OPEN_COMMIT_SIG, s); -} - -void queue_pkt_open_complete(struct peer *peer) -{ - OpenComplete *o = tal(peer, OpenComplete); - - open_complete__init(o); - queue_pkt(peer, PKT__PKT_OPEN_COMPLETE, o); -} - -void queue_pkt_htlc_add(struct peer *peer, struct htlc *htlc) -{ - UpdateAddHtlc *u = tal(peer, UpdateAddHtlc); - - update_add_htlc__init(u); - - u->id = htlc->id; - u->amount_msat = htlc->msatoshi; - u->r_hash = sha256_to_proto(u, &htlc->rhash); - u->expiry = abs_locktime_to_proto(u, &htlc->expiry); - u->route = tal(u, Routing); - routing__init(u->route); - u->route->info.data = tal_dup_arr(u, u8, - htlc->routing, - tal_count(htlc->routing), - 0); - u->route->info.len = tal_count(u->route->info.data); - - queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u); -} - -void queue_pkt_htlc_fulfill(struct peer *peer, struct htlc *htlc) -{ - UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc); - - update_fulfill_htlc__init(f); - f->id = htlc->id; - f->r = preimage_to_proto(f, htlc->r); - - queue_pkt(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f); -} - -void queue_pkt_htlc_fail(struct peer *peer, struct htlc *htlc) -{ - UpdateFailHtlc *f = tal(peer, UpdateFailHtlc); - - update_fail_htlc__init(f); - f->id = htlc->id; - - f->reason = tal(f, FailReason); - fail_reason__init(f->reason); - f->reason->info.len = tal_count(htlc->fail); - f->reason->info.data = tal_dup_arr(f->reason, u8, - htlc->fail, f->reason->info.len, 0); - - queue_pkt(peer, PKT__PKT_UPDATE_FAIL_HTLC, f); -} - -void queue_pkt_feechange(struct peer *peer, u64 feerate) -{ - UpdateFee *f = tal(peer, UpdateFee); - - update_fee__init(f); - f->fee_rate = feerate; - - queue_pkt(peer, PKT__PKT_UPDATE_FEE, f); -} - -/* OK, we're sending a signature for their pending changes. */ -void queue_pkt_commit(struct peer *peer, const secp256k1_ecdsa_signature *sig) -{ - UpdateCommit *u = tal(peer, UpdateCommit); - - /* Now send message */ - update_commit__init(u); - if (sig) - u->sig = signature_to_proto(u, sig); - else - u->sig = NULL; - - queue_pkt(peer, PKT__PKT_UPDATE_COMMIT, u); -} - - -/* Send a preimage for the old commit tx. The one we've just committed to is - * in peer->local.commit. */ -void queue_pkt_revocation(struct peer *peer, - const struct sha256 *preimage, - const struct sha256 *next_hash) -{ - UpdateRevocation *u = tal(peer, UpdateRevocation); - - update_revocation__init(u); - - u->revocation_preimage = sha256_to_proto(u, preimage); - u->next_revocation_hash = sha256_to_proto(u, next_hash); - queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u); -} - -/* Send a serialized nested packet. */ -void queue_pkt_nested(struct peer *peer, - int type, - const u8 *nested_pkt) -{ - NestedPkt *pb = tal(peer, NestedPkt); - nested_pkt__init(pb); - pb->type = type; - pb->inner_pkt.len = tal_count(nested_pkt); - pb->inner_pkt.data = tal_dup_arr(pb, u8, nested_pkt, pb->inner_pkt.len, 0); - queue_pkt(peer, PKT__PKT_NESTED, pb); -} - -Pkt *pkt_err(struct peer *peer, const char *msg, ...) -{ - Error *e = tal(peer, Error); - va_list ap; - - error__init(e); - va_start(ap, msg); - e->problem = tal_vfmt(e, msg, ap); - va_end(ap); - - log_unusual(peer->log, "Sending PKT_ERROR: %s", e->problem); - return make_pkt(peer, PKT__PKT_ERROR, e); -} - -Pkt *pkt_init(struct peer *peer, u64 ack) -{ - Init *i = tal(peer, Init); - init__init(i); - i->ack = ack; - /* FIXME-OLD #2: - * - * A node SHOULD set the `features` field of the `init` - * message to a bitset representing features it supports. - */ - /* No features yet! */ - return make_pkt(peer, PKT__PKT_INIT, i); -} - -void queue_pkt_err(struct peer *peer, Pkt *err) -{ - queue_raw_pkt(peer, err); -} - -void queue_pkt_close_shutdown(struct peer *peer) -{ - CloseShutdown *c = tal(peer, CloseShutdown); - - close_shutdown__init(c); - c->scriptpubkey.data = tal_dup_arr(c, u8, - peer->closing.our_script, - tal_count(peer->closing.our_script), - 0); - c->scriptpubkey.len = tal_count(c->scriptpubkey.data); - - queue_pkt(peer, PKT__PKT_CLOSE_SHUTDOWN, c); -} - -void queue_pkt_close_signature(struct peer *peer) -{ - CloseSignature *c = tal(peer, CloseSignature); - struct bitcoin_tx *close_tx; - secp256k1_ecdsa_signature our_close_sig; - - close_signature__init(c); - close_tx = peer_create_close_tx(c, peer, peer->closing.our_fee); - - peer_sign_mutual_close(peer, close_tx, &our_close_sig); - c->sig = signature_to_proto(c, &our_close_sig); - c->close_fee = peer->closing.our_fee; - log_info(peer->log, "queue_pkt_close_signature: offered close fee %" - PRIu64, c->close_fee); - - queue_pkt(peer, PKT__PKT_CLOSE_SIGNATURE, c); -} - -Pkt *pkt_err_unexpected(struct peer *peer, const Pkt *pkt) -{ - return pkt_err(peer, "Unexpected packet %s", pkt_name(pkt->pkt_case)); -} - -/* Process various packets: return an error packet on failure. */ -Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt, - struct sha256 *revocation_hash, - struct sha256 *next_revocation_hash) -{ - struct rel_locktime locktime; - const OpenChannel *o = pkt->open; - u64 feerate = get_feerate(peer->dstate->topology); - - if (!proto_to_rel_locktime(o->delay, &locktime)) - return pkt_err(peer, "Invalid delay"); - if (o->delay->locktime_case != LOCKTIME__LOCKTIME_BLOCKS) - return pkt_err(peer, "Delay in seconds not accepted"); - if (o->delay->blocks > peer->dstate->config.locktime_max) - return pkt_err(peer, "Delay %u too great", o->delay->blocks); - if (o->min_depth > peer->dstate->config.anchor_confirms_max) - return pkt_err(peer, "min_depth %u too great", o->min_depth); - if (o->initial_fee_rate - < feerate * peer->dstate->config.commitment_fee_min_percent / 100) - return pkt_err(peer, "Commitment fee %u below %"PRIu64" x %u%%", - o->initial_fee_rate, feerate, - peer->dstate->config.commitment_fee_min_percent); - if (peer->dstate->config.commitment_fee_max_percent != 0 - && (o->initial_fee_rate - > feerate * peer->dstate->config.commitment_fee_max_percent/100)) - return pkt_err(peer, "Commitment fee %u above %"PRIu64" x %u%%", - o->initial_fee_rate, feerate, - peer->dstate->config.commitment_fee_max_percent); - if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) - peer->remote.offer_anchor = true; - else if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR) - peer->remote.offer_anchor = false; - else - return pkt_err(peer, "Unknown offer anchor value %u", - o->anch); - - if (peer->remote.offer_anchor == peer->local.offer_anchor) - return pkt_err(peer, "Exactly one side can offer anchor (we %s)", - peer->local.offer_anchor ? "do" : "don't"); - - if (!proto_to_rel_locktime(o->delay, &peer->remote.locktime)) - return pkt_err(peer, "Malformed locktime"); - peer->remote.mindepth = o->min_depth; - peer->remote.commit_fee_rate = o->initial_fee_rate; - if (!proto_to_pubkey(o->commit_key, &peer->remote.commitkey)) - return pkt_err(peer, "Bad commitkey"); - if (!proto_to_pubkey(o->final_key, &peer->remote.finalkey)) - return pkt_err(peer, "Bad finalkey"); - - proto_to_sha256(o->revocation_hash, revocation_hash); - proto_to_sha256(o->next_revocation_hash, next_revocation_hash); - return NULL; -} - -Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt) -{ - const OpenAnchor *a = pkt->open_anchor; - - /* They must be offering anchor for us to try accepting */ - assert(!peer->local.offer_anchor); - assert(peer->remote.offer_anchor); - - if (anchor_too_large(a->amount)) - return pkt_err(peer, "Anchor millisatoshis exceeds 32 bits"); - - proto_to_sha256(a->txid, &peer->anchor.txid.sha); - peer->anchor.index = a->output_index; - peer->anchor.satoshis = a->amount; - return NULL; -} - -Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt, - secp256k1_ecdsa_signature *sig) -{ - const OpenCommitSig *s = pkt->open_commit_sig; - - if (!proto_to_signature(s->sig, sig)) - return pkt_err(peer, "Malformed signature"); - return NULL; -} - -Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt) -{ - return NULL; -} - -/* - * We add changes to both our staging cstate (as they did when they sent - * it) and theirs (as they will when we ack it). - */ -Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt, struct htlc **h) -{ - const UpdateAddHtlc *u = pkt->update_add_htlc; - struct sha256 rhash; - struct abs_locktime expiry; - - /* FIXME-OLD #2: - * - * `amount_msat` MUST BE greater than 0. - */ - if (u->amount_msat == 0) - return pkt_err(peer, "Invalid amount_msat"); - - proto_to_sha256(u->r_hash, &rhash); - if (!proto_to_abs_locktime(u->expiry, &expiry)) - return pkt_err(peer, "Invalid HTLC expiry"); - - if (abs_locktime_is_seconds(&expiry)) - return pkt_err(peer, "HTLC expiry in seconds not supported!"); - - /* FIXME-OLD #2: - * - * A node MUST NOT add a HTLC if it would result in it - * offering more than 300 HTLCs in the remote commitment transaction. - */ - if (peer->remote.staging_cstate->side[REMOTE].num_htlcs == 300) - return pkt_err(peer, "Too many HTLCs"); - - /* FIXME-OLD #2: - * - * A node MUST set `id` to a unique identifier for this HTLC - * amongst all past or future `update_add_htlc` messages. - */ - /* Note that it's not *our* problem if they do this, it's - * theirs (future confusion). Nonetheless, we detect and - * error for them. */ - if (htlc_get(&peer->htlcs, u->id, REMOTE)) - return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); - - /* FIXME-OLD #2: - * - * ...and the receiving node MUST add the HTLC addition to the - * unacked changeset for its local commitment. */ - *h = peer_new_htlc(peer, u->id, u->amount_msat, &rhash, - abs_locktime_to_blocks(&expiry), - u->route->info.data, u->route->info.len, - NULL, RCVD_ADD_HTLC); - return NULL; -} - -static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, - struct htlc **local_htlc) -{ - *local_htlc = htlc_get(&peer->htlcs, id, LOCAL); - - /* FIXME-OLD #2: - * - * A node MUST check that `id` corresponds to an HTLC in its - * current commitment transaction, and MUST fail the - * connection if it does not. - */ - if (!(*local_htlc)) - return pkt_err(peer, "Did not find HTLC %"PRIu64, id); - - if ((*local_htlc)->state != SENT_ADD_ACK_REVOCATION) - return pkt_err(peer, "HTLC %"PRIu64" state %s", id, - htlc_state_name((*local_htlc)->state)); - - return NULL; -} - -Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt, struct htlc **h, - u8 **fail) -{ - const UpdateFailHtlc *f = pkt->update_fail_htlc; - Pkt *err; - - err = find_commited_htlc(peer, f->id, h); - if (err) - return err; - - if ((*h)->r) - return pkt_err(peer, "HTLC %"PRIu64" already fulfilled", - (*h)->id); - - *fail = tal_dup_arr(*h, u8, f->reason->info.data, f->reason->info.len,0); - return NULL; -} - -Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt, struct htlc **h, - struct preimage *r) -{ - const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc; - struct sha256 rhash; - Pkt *err; - - err = find_commited_htlc(peer, f->id, h); - if (err) - return err; - - /* Now, it must solve the HTLC rhash puzzle. */ - proto_to_preimage(f->r, r); - sha256(&rhash, r, sizeof(*r)); - - if (!structeq(&rhash, &(*h)->rhash)) - return pkt_err(peer, "Invalid r for %"PRIu64, f->id); - - return NULL; -} - -Pkt *accept_pkt_update_fee(struct peer *peer, const Pkt *pkt, u64 *feerate) -{ - const UpdateFee *f = pkt->update_fee; - - *feerate = f->fee_rate; - return NULL; -} - -Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt, - secp256k1_ecdsa_signature *sig) -{ - const UpdateCommit *c = pkt->update_commit; - - if (!c->sig && sig) - return pkt_err(peer, "Expected signature"); - - if (!sig && c->sig) - return pkt_err(peer, "Unexpected signature"); - - if (!sig && !c->sig) - return NULL; - - if (!proto_to_signature(c->sig, sig)) - return pkt_err(peer, "Malformed signature"); - return NULL; -} - -Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) -{ - const UpdateRevocation *r = pkt->update_revocation; - struct sha256 h, preimage; - - assert(peer->their_prev_revocation_hash); - proto_to_sha256(r->revocation_preimage, &preimage); - - /* FIXME-OLD #2: - * - * The receiver of `update_revocation` MUST check that the - * SHA256 hash of `revocation_preimage` matches the previous commitment - * transaction, and MUST fail if it does not. - */ - sha256(&h, &preimage, sizeof(preimage)); - if (!structeq(&h, peer->their_prev_revocation_hash)) { - log_unusual(peer->log, "Incorrect preimage for %"PRIu64, - peer->remote.commit->commit_num - 1); - return pkt_err(peer, "complete preimage incorrect"); - } - - // save revocation preimages in shachain - if (!shachain_add_hash(&peer->their_preimages, - 0xFFFFFFFFFFFFFFFFL - - (peer->remote.commit->commit_num - 1), - &preimage)) - return pkt_err(peer, "preimage not next in shachain"); - - log_debug(peer->log, "Got revocation preimage %"PRIu64, - peer->remote.commit->commit_num - 1); - - /* Clear the previous revocation hash. */ - peer->their_prev_revocation_hash - = tal_free(peer->their_prev_revocation_hash); - - /* Save next revocation hash. */ - proto_to_sha256(r->next_revocation_hash, - &peer->remote.next_revocation_hash); - return NULL; -} - -Pkt *accept_pkt_close_shutdown(struct peer *peer, const Pkt *pkt) -{ - const CloseShutdown *c = pkt->close_shutdown; - - peer->closing.their_script = tal_dup_arr(peer, u8, - c->scriptpubkey.data, - c->scriptpubkey.len, 0); - - /* FIXME-OLD #2: - * - * 1. `OP_DUP` `OP_HASH160` `20` 20-bytes `OP_EQUALVERIFY` `OP_CHECKSIG` - * (pay to pubkey hash), OR - * 2. `OP_HASH160` `20` 20-bytes `OP_EQUAL` (pay to script hash), OR - * 3. `OP_0` `20` 20-bytes (version 0 pay to witness pubkey), OR - * 4. `OP_0` `32` 32-bytes (version 0 pay to witness script hash) - * - * A node receiving `close_shutdown` SHOULD fail the connection - * `script_pubkey` is not one of those forms. - */ - if (!is_p2pkh(peer->closing.their_script) - && !is_p2sh(peer->closing.their_script) - && !is_p2wpkh(peer->closing.their_script) - && !is_p2wsh(peer->closing.their_script)) { - log_broken_blob(peer->log, "Bad script_pubkey %s", - peer->closing.their_script, - tal_count(peer->closing.their_script)); - return pkt_err(peer, "Bad script_pubkey"); - } - - return NULL; -} diff --git a/daemon/pay.c b/daemon/pay.c deleted file mode 100644 index 9792be65c..000000000 --- a/daemon/pay.c +++ /dev/null @@ -1,478 +0,0 @@ -#include "chaintopology.h" -#include "db.h" -#include "failure.h" -#include "jsonrpc.h" -#include "lightningd.h" -#include "log.h" -#include "pay.h" -#include "peer.h" -#include "peer_internal.h" -#include "routing.h" -#include "sphinx.h" -#include -#include -#include -#include -#include - -/* Outstanding "pay" commands. */ -struct pay_command { - struct list_node list; - struct sha256 rhash; - u64 msatoshi; - const struct pubkey *ids; - /* Set if this is in progress. */ - struct htlc *htlc; - /* Preimage if this succeeded. */ - const struct preimage *rval; - struct command *cmd; -}; -static void json_pay_success(struct command *cmd, const struct preimage *rval) -{ - struct json_result *response; - - response = new_json_result(cmd); - json_object_start(response, NULL); - json_add_hex(response, "preimage", rval, sizeof(*rval)); - json_object_end(response); - command_success(cmd, response); -} - -static void handle_json(struct command *cmd, const struct htlc *htlc, - const FailInfo *f) -{ - struct pubkey id; - const char *idstr = "INVALID"; - - if (htlc->r) { - json_pay_success(cmd, htlc->r); - return; - } - - if (!f) { - command_fail(cmd, "failed (bad message)"); - return; - } - - if (proto_to_pubkey(f->id, &id)) - idstr = pubkey_to_hexstr(cmd, &id); - - command_fail(cmd, - "failed: error code %u node %s reason %s", - f->error_code, idstr, f->reason ? f->reason : "unknown"); -} - -static void check_routing_failure(struct lightningd_state *dstate, - const struct pay_command *pc, - const FailInfo *f) -{ - size_t i; - struct pubkey id; - - if (!f) - return; - - /* FIXME: We remove route on *any* failure. */ - log_debug(dstate->base_log, "Seeking route for fail code %u", - f->error_code); - if (!proto_to_pubkey(f->id, &id)) { - log_add(dstate->base_log, " - bad node"); - return; - } - - log_add_struct(dstate->base_log, " node %s", struct pubkey, &id); - - /* Don't remove route if it's last node (obviously) */ - for (i = 0; i+1 < tal_count(pc->ids); i++) { - if (structeq(&pc->ids[i], &id)) { - remove_connection(dstate->rstate, &pc->ids[i], &pc->ids[i+1]); - return; - } - } - - if (structeq(&pc->ids[i], &id)) - log_debug(dstate->base_log, "Final node: ignoring"); - else - log_debug(dstate->base_log, "Node not on route: ignoring"); -} - -void complete_pay_command(struct lightningd_state *dstate, - const struct htlc *htlc) -{ - struct pay_command *i; - - list_for_each(&dstate->pay_commands, i, list) { - if (i->htlc == htlc) { - FailInfo *f = NULL; - - db_complete_pay_command(dstate, htlc); - - if (htlc->r) - i->rval = tal_dup(i, struct preimage, htlc->r); - else { - f = failinfo_unwrap(i->cmd, htlc->fail, - tal_count(htlc->fail)); - check_routing_failure(dstate, i, f); - } - - /* No longer connected to live HTLC. */ - i->htlc = NULL; - - /* Can be NULL if JSON RPC goes away. */ - if (i->cmd) - handle_json(i->cmd, htlc, f); - return; - } - } - - /* Can happen with testing low-level commands. */ - log_unusual(dstate->base_log, "No command for HTLC %"PRIu64" %s", - htlc->id, htlc->r ? "fulfill" : "fail"); -} - -/* When JSON RPC goes away, cmd is freed: detach from any running paycommand */ -static void remove_cmd_from_pc(struct command *cmd) -{ - struct pay_command *pc; - - list_for_each(&cmd->dstate->pay_commands, pc, list) { - if (pc->cmd == cmd) { - pc->cmd = NULL; - return; - } - } - /* We can reach here, in the case where another pay command - * re-uses the pc->cmd before we get around to cleaning up. */ -} - -static struct pay_command *find_pay_command(struct lightningd_state *dstate, - const struct sha256 *rhash) -{ - struct pay_command *pc; - - list_for_each(&dstate->pay_commands, pc, list) { - if (structeq(rhash, &pc->rhash)) - return pc; - } - return NULL; -} - -/* For database restore. */ -bool pay_add(struct lightningd_state *dstate, - const struct sha256 *rhash, - u64 msatoshi, - const struct pubkey *ids, - struct htlc *htlc, - const u8 *fail UNNEEDED, - const struct preimage *r) -{ - struct pay_command *pc; - - if (find_pay_command(dstate, rhash)) - return false; - - pc = tal(dstate, struct pay_command); - pc->rhash = *rhash; - pc->msatoshi = msatoshi; - pc->ids = tal_dup_arr(pc, struct pubkey, ids, tal_count(ids), 0); - pc->htlc = htlc; - if (r) - pc->rval = tal_dup(pc, struct preimage, r); - else - pc->rval = NULL; - pc->cmd = NULL; - - list_add_tail(&dstate->pay_commands, &pc->list); - return true; -} - -static void json_add_route(struct json_result *response, - const struct pubkey *id, - u64 amount, unsigned int delay) -{ - json_object_start(response, NULL); - json_add_pubkey(response, "id", id); - json_add_u64(response, "msatoshi", amount); - json_add_num(response, "delay", delay); - json_object_end(response); -} - -static void json_getroute(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct pubkey id; - jsmntok_t *idtok, *msatoshitok, *riskfactortok; - struct json_result *response; - size_t i; - u64 msatoshi; - double riskfactor; - - if (!json_get_params(buffer, params, - "id", &idtok, - "msatoshi", &msatoshitok, - "riskfactor", &riskfactortok, - NULL)) { - command_fail(cmd, "Need id, msatoshi and riskfactor"); - return; - } - - if (!pubkey_from_hexstr(buffer + idtok->start, - idtok->end - idtok->start, &id)) { - command_fail(cmd, "Invalid id"); - return; - } - - if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) { - command_fail(cmd, "'%.*s' is not a valid number", - (int)(msatoshitok->end - msatoshitok->start), - buffer + msatoshitok->start); - return; - } - - if (!json_tok_double(buffer, riskfactortok, &riskfactor)) { - command_fail(cmd, "'%.*s' is not a valid double", - (int)(riskfactortok->end - riskfactortok->start), - buffer + riskfactortok->start); - return; - } - - struct route_hop *hops = get_route(cmd, cmd->dstate->rstate, &cmd->dstate->id, &id, msatoshi, riskfactor); - - if (!hops) { - command_fail(cmd, "no route found"); - return; - } - - response = new_json_result(cmd); - json_object_start(response, NULL); - json_array_start(response, "route"); - for (i = 0; i < tal_count(hops); i++) - json_add_route(response, - &hops[i].nodeid, hops[i].amount, hops[i].delay); - json_array_end(response); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command getroute_command = { - "getroute", - json_getroute, - "Return route to {id} for {msatoshi}, using {riskfactor}", - "Returns a {route} array of {id} {msatoshi} {delay}: msatoshi and delay (in blocks) is cumulative." -}; -AUTODATA(json_command, &getroute_command); - -static void json_sendpay(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct pubkey *ids; - jsmntok_t *routetok, *rhashtok; - const jsmntok_t *t, *end; - unsigned int delay; - size_t n_hops; - struct sha256 rhash; - struct peer *peer; - struct pay_command *pc; - bool replacing = false; - const u8 *onion; - u8 sessionkey[32]; - enum fail_error error_code; - const char *err; - struct hoppayload *hoppayloads; - u64 amount, lastamount; - struct onionpacket *packet; - - if (!json_get_params(buffer, params, - "route", &routetok, - "rhash", &rhashtok, - NULL)) { - command_fail(cmd, "Need route and rhash"); - return; - } - - if (!hex_decode(buffer + rhashtok->start, - rhashtok->end - rhashtok->start, - &rhash, sizeof(rhash))) { - command_fail(cmd, "'%.*s' is not a valid sha256 hash", - (int)(rhashtok->end - rhashtok->start), - buffer + rhashtok->start); - return; - } - - if (routetok->type != JSMN_ARRAY) { - command_fail(cmd, "'%.*s' is not an array", - (int)(routetok->end - routetok->start), - buffer + routetok->start); - return; - } - - end = json_next(routetok); - n_hops = 0; - ids = tal_arr(cmd, struct pubkey, n_hops); - hoppayloads = tal_arr(cmd, struct hoppayload, 0); - for (t = routetok + 1; t < end; t = json_next(t)) { - const jsmntok_t *amttok, *idtok, *delaytok; - - if (t->type != JSMN_OBJECT) { - command_fail(cmd, "route %zu '%.*s' is not an object", - n_hops, - (int)(t->end - t->start), - buffer + t->start); - return; - } - amttok = json_get_member(buffer, t, "msatoshi"); - idtok = json_get_member(buffer, t, "id"); - delaytok = json_get_member(buffer, t, "delay"); - if (!amttok || !idtok || !delaytok) { - command_fail(cmd, "route %zu needs msatoshi/id/delay", - n_hops); - return; - } - - if (n_hops == 0) { - /* What we will send */ - if (!json_tok_u64(buffer, amttok, &amount)) { - command_fail(cmd, "route %zu invalid msatoshi", n_hops); - return; - } - lastamount = amount; - } else{ - /* What that hop will forward */ - tal_resize(&hoppayloads, n_hops); - memset(&hoppayloads[n_hops-1], 0, sizeof(struct hoppayload)); - if (!json_tok_u64(buffer, amttok, &hoppayloads[n_hops-1].amt_to_forward)) { - command_fail(cmd, "route %zu invalid msatoshi", n_hops); - return; - } - /* FIXME: Populate outgoing_cltv_value */ - lastamount = hoppayloads[n_hops-1].amt_to_forward; - } - - tal_resize(&ids, n_hops+1); - memset(&ids[n_hops], 0, sizeof(ids[n_hops])); - if (!pubkey_from_hexstr(buffer + idtok->start, - idtok->end - idtok->start, - &ids[n_hops])) { - command_fail(cmd, "route %zu invalid id", n_hops); - return; - } - /* Only need first delay. */ - if (n_hops == 0 && !json_tok_number(buffer, delaytok, &delay)) { - command_fail(cmd, "route %zu invalid delay", n_hops); - return; - } - n_hops++; - } - - /* Add payload for final hop */ - tal_resize(&hoppayloads, n_hops); - memset(&hoppayloads[n_hops-1], 0, sizeof(struct hoppayload)); - - if (n_hops == 0) { - command_fail(cmd, "Empty route"); - return; - } - - pc = find_pay_command(cmd->dstate, &rhash); - if (pc) { - replacing = true; - log_debug(cmd->dstate->base_log, "json_sendpay: found previous"); - if (pc->htlc) { - log_add(cmd->dstate->base_log, "... still in progress"); - command_fail(cmd, "still in progress"); - return; - } - if (pc->rval) { - size_t old_nhops = tal_count(pc->ids); - log_add(cmd->dstate->base_log, "... succeeded"); - /* Must match successful payment parameters. */ - if (pc->msatoshi != lastamount) { - command_fail(cmd, - "already succeeded with amount %" - PRIu64, pc->msatoshi); - return; - } - if (!structeq(&pc->ids[old_nhops-1], &ids[n_hops-1])) { - char *previd; - previd = pubkey_to_hexstr(cmd, - &pc->ids[old_nhops-1]); - command_fail(cmd, - "already succeeded to %s", - previd); - return; - } - json_pay_success(cmd, pc->rval); - return; - } - log_add(cmd->dstate->base_log, "... retrying"); - } - - peer = find_peer(cmd->dstate, &ids[0]); - if (!peer) { - command_fail(cmd, "no connection to first peer found"); - return; - } - - randombytes_buf(&sessionkey, sizeof(sessionkey)); - - /* Onion will carry us from first peer onwards. */ - packet = create_onionpacket(cmd, ids, hoppayloads, sessionkey, - rhash.u.u8, sizeof(struct sha256)); - onion = serialize_onionpacket(cmd, packet); - - if (pc) - pc->ids = tal_free(pc->ids); - else - pc = tal(cmd->dstate, struct pay_command); - pc->cmd = cmd; - pc->rhash = rhash; - pc->rval = NULL; - pc->ids = tal_steal(pc, ids); - pc->msatoshi = lastamount; - - /* Expiry for HTLCs is absolute. And add one to give some margin. */ - err = command_htlc_add(peer, amount, - delay + get_block_height(cmd->dstate->topology) - + 1, - &rhash, NULL, - onion, &error_code, &pc->htlc); - if (err) { - command_fail(cmd, "could not add htlc: %u: %s", error_code, err); - tal_free(pc); - return; - } - - if (replacing) { - if (!db_replace_pay_command(cmd->dstate, &pc->rhash, - pc->ids, pc->msatoshi, - pc->htlc)) { - command_fail(cmd, "database error"); - /* We could reconnect, but db error is *bad*. */ - peer_fail(peer, __func__); - tal_free(pc); - return; - } - } else { - if (!db_new_pay_command(cmd->dstate, &pc->rhash, - pc->ids, pc->msatoshi, - pc->htlc)) { - command_fail(cmd, "database error"); - /* We could reconnect, but db error is *bad*. */ - peer_fail(peer, __func__); - tal_free(pc); - return; - } - } - - /* Wait until we get response. */ - list_add_tail(&cmd->dstate->pay_commands, &pc->list); - tal_add_destructor(cmd, remove_cmd_from_pc); -} - -static const struct json_command sendpay_command = { - "sendpay", - json_sendpay, - "Send along {route} in return for preimage of {rhash}", - "Returns the {preimage} on success" -}; -AUTODATA(json_command, &sendpay_command); diff --git a/daemon/pay.h b/daemon/pay.h deleted file mode 100644 index ab36b0819..000000000 --- a/daemon/pay.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LIGHTNING_DAEMON_PAY_H -#define LIGHTNING_DAEMON_PAY_H -#include "config.h" - -struct htlc; -struct lightningd_state; -struct preimage; - -void complete_pay_command(struct lightningd_state *dstate, - const struct htlc *htlc); - -bool pay_add(struct lightningd_state *dstate, - const struct sha256 *rhash, - u64 msatoshi, - const struct pubkey *ids, - struct htlc *htlc, - const u8 *fail, - const struct preimage *r); -#endif /* LIGHTNING_DAEMON_PAY_H */ diff --git a/daemon/peer.c b/daemon/peer.c deleted file mode 100644 index c08bfd688..000000000 --- a/daemon/peer.c +++ /dev/null @@ -1,5294 +0,0 @@ -#include "bitcoind.h" -#include "chaintopology.h" -#include "close_tx.h" -#include "commit_tx.h" -#include "cryptopkt.h" -#include "db.h" -#include "dns.h" -#include "find_p2sh_out.h" -#include "invoice.h" -#include "jsonrpc.h" -#include "lightningd.h" -#include "log.h" -#include "names.h" -#include "netaddr.h" -#include "output_to_htlc.h" -#include "p2p_announce.h" -#include "packets.h" -#include "pay.h" -#include "peer.h" -#include "peer_internal.h" -#include "permute_tx.h" -#include "protobuf_convert.h" -#include "pseudorand.h" -#include "remove_dust.h" -#include "routing.h" -#include "secrets.h" -#include "sphinx.h" -#include "state.h" -#include "timeout.h" -#include "utils.h" -#include "wallet.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct json_connecting { - /* This owns us, so we're freed after command_fail or command_success */ - struct command *cmd; - const char *name, *port; - struct anchor_input *input; -}; - -static bool command_htlc_set_fail(struct peer *peer, struct htlc *htlc, - enum fail_error error_code, const char *why); -static bool command_htlc_fail(struct peer *peer, struct htlc *htlc); -static bool command_htlc_fulfill(struct peer *peer, struct htlc *htlc); -static void try_commit(struct peer *peer); - -void peer_debug(struct peer *peer, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - logv(peer->log, LOG_DBG, fmt, ap); - va_end(ap); -} - -void peer_add_their_commit(struct peer *peer, - const struct sha256_double *txid, u64 commit_num) -{ - struct their_commit *tc = tal(peer, struct their_commit); - tc->txid = *txid; - tc->commit_num = commit_num; - list_add_tail(&peer->their_commits, &tc->list); - - db_add_commit_map(peer, txid, commit_num); -} - -/* Create a bitcoin close tx, using last signature they sent. */ -static const struct bitcoin_tx *mk_bitcoin_close(const tal_t *ctx, - struct peer *peer) -{ - struct bitcoin_tx *close_tx; - secp256k1_ecdsa_signature our_close_sig; - - close_tx = peer_create_close_tx(ctx, peer, peer->closing.their_fee); - - peer_sign_mutual_close(peer, close_tx, &our_close_sig); - - close_tx->input[0].witness - = bitcoin_witness_2of2(close_tx->input, - peer->closing.their_sig, - &our_close_sig, - &peer->remote.commitkey, - &peer->local.commitkey); - - return close_tx; -} - -/* Create a bitcoin spend tx (to spend our commit's outputs) */ -static const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer) -{ - u8 *witnessscript; - const struct bitcoin_tx *commit = peer->local.commit->tx; - secp256k1_ecdsa_signature sig; - struct bitcoin_tx *tx; - unsigned int p2wsh_out; - uint64_t fee; - - /* The redeemscript for a commit tx is fairly complex. */ - witnessscript = bitcoin_redeem_secret_or_delay(peer, - &peer->local.finalkey, - &peer->remote.locktime, - &peer->remote.finalkey, - &peer->local.commit->revocation_hash); - - /* Now, create transaction to spend it. */ - tx = bitcoin_tx(peer, 1, 1); - tx->input[0].txid = peer->local.commit->txid; - p2wsh_out = find_p2wsh_out(commit, witnessscript); - tx->input[0].index = p2wsh_out; - tx->input[0].sequence_number = bitcoin_nsequence(&peer->remote.locktime); - tx->input[0].amount = tal_dup(tx->input, u64, - &commit->output[p2wsh_out].amount); - - tx->output[0].script = scriptpubkey_p2sh(tx, - bitcoin_redeem_single(tx, - &peer->local.finalkey)); - - /* Witness length can vary, due to DER encoding of sigs, but we - * use 176 from an example run. */ - assert(measure_tx_cost(tx) == 83 * 4); - - fee = fee_by_feerate(83 + 176 / 4, get_feerate(peer->dstate->topology)); - - /* FIXME: Fail gracefully in these cases (not worth collecting) */ - if (fee > commit->output[p2wsh_out].amount - || is_dust(commit->output[p2wsh_out].amount - fee)) - fatal("Amount of %"PRIu64" won't cover fee %"PRIu64, - commit->output[p2wsh_out].amount, fee); - - tx->output[0].amount = commit->output[p2wsh_out].amount - fee; - - peer_sign_spend(peer, tx, witnessscript, &sig); - - tx->input[0].witness = bitcoin_witness_secret(tx, - NULL, 0, &sig, - witnessscript); - - return tx; -} - -/* Sign and local commit tx */ -static void sign_commit_tx(struct peer *peer) -{ - secp256k1_ecdsa_signature sig; - - /* Can't be signed already, and can't have scriptsig! */ - assert(!peer->local.commit->tx->input[0].script); - assert(!peer->local.commit->tx->input[0].witness); - - peer_sign_ourcommit(peer, peer->local.commit->tx, &sig); - - peer->local.commit->tx->input[0].witness - = bitcoin_witness_2of2(peer->local.commit->tx->input, - peer->local.commit->sig, - &sig, - &peer->remote.commitkey, - &peer->local.commitkey); -} - -static u64 commit_tx_fee(const struct bitcoin_tx *commit, u64 anchor_satoshis) -{ - uint64_t i, total = 0; - - for (i = 0; i < tal_count(commit->output); i++) - total += commit->output[i].amount; - - assert(anchor_satoshis >= total); - return anchor_satoshis - total; -} - -struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id) -{ - struct peer *peer; - - list_for_each(&dstate->peers, peer, list) { - if (peer->id && pubkey_eq(peer->id, id)) - return peer; - } - return NULL; -} - -struct peer *find_peer_by_pkhash(struct lightningd_state *dstate, const u8 *pkhash) -{ - struct peer *peer; - struct ripemd160 addr; - - list_for_each(&dstate->peers, peer, list) { - pubkey_to_hash160(peer->id, &addr); - if (memcmp(&addr, pkhash, sizeof(addr)) == 0) - return peer; - } - return NULL; -} - -void debug_dump_peers(struct lightningd_state *dstate) -{ - struct peer *peer; - - list_for_each(&dstate->peers, peer, list) { - if (!peer->local.commit - || !peer->remote.commit) - continue; - log_debug_struct(peer->log, "our cstate: %s", - struct channel_state, - peer->local.commit->cstate); - log_debug_struct(peer->log, "their cstate: %s", - struct channel_state, - peer->remote.commit->cstate); - } -} - -static struct peer *find_peer_json(struct lightningd_state *dstate, - const char *buffer, - jsmntok_t *peeridtok) -{ - struct pubkey peerid; - - if (!pubkey_from_hexstr(buffer + peeridtok->start, - peeridtok->end - peeridtok->start, &peerid)) - return NULL; - - return find_peer(dstate, &peerid); -} - -static bool peer_uncommitted_changes(const struct peer *peer) -{ - struct htlc_map_iter it; - struct htlc *h; - enum feechange_state i; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (htlc_has(h, HTLC_REMOTE_F_PENDING)) - return true; - } - /* Pending feechange we sent, or pending ack of theirs. */ - for (i = 0; i < ARRAY_SIZE(peer->feechanges); i++) { - if (!peer->feechanges[i]) - continue; - if (feechange_state_flags(i) & HTLC_REMOTE_F_PENDING) - return true; - } - return false; -} - -static void remote_changes_pending(struct peer *peer) -{ - if (!peer->commit_timer) { - log_debug(peer->log, "remote_changes_pending: adding timer"); - peer->commit_timer = new_reltimer(&peer->dstate->timers, peer, - peer->dstate->config.commit_time, - try_commit, peer); - } else - log_debug(peer->log, "remote_changes_pending: timer already exists"); -} - -static void peer_update_complete(struct peer *peer) -{ - log_debug(peer->log, "peer_update_complete"); - if (peer->commit_jsoncmd) { - command_success(peer->commit_jsoncmd, - null_response(peer->commit_jsoncmd)); - peer->commit_jsoncmd = NULL; - } - - /* Have we got more changes in the meantime? */ - if (peer_uncommitted_changes(peer)) { - log_debug(peer->log, "peer_update_complete: more changes!"); - remote_changes_pending(peer); - } -} - -/* FIXME: Split success and fail functions, roll state changes etc into - * success case. */ -static void peer_open_complete(struct peer *peer, const char *problem) -{ - if (problem) { - log_unusual(peer->log, "peer open failed: %s", problem); - if (peer->open_jsoncmd) { - command_fail(peer->open_jsoncmd, "%s", problem); - peer->open_jsoncmd = NULL; - } - } else { - log_debug(peer->log, "peer open complete"); - assert(!peer->nc); - /* We're connected, so record it. */ - peer->nc = add_connection(peer->dstate->rstate, - &peer->dstate->id, peer->id, - peer->dstate->config.fee_base, - peer->dstate->config.fee_per_satoshi, - peer->dstate->config.min_htlc_expiry, - peer->dstate->config.min_htlc_expiry); - if (peer->open_jsoncmd) { - struct json_result *response; - response = new_json_result(peer->open_jsoncmd); - - json_object_start(response, NULL); - json_add_pubkey(response, "id", peer->id); - json_object_end(response); - command_success(peer->open_jsoncmd, response); - peer->open_jsoncmd = NULL; - } - } -} - -static void set_peer_state(struct peer *peer, enum state newstate, - const char *caller, bool db_commit) -{ - log_debug(peer->log, "%s: %s => %s", caller, - state_name(peer->state), state_name(newstate)); - peer->state = newstate; - - /* We can only route in normal state. */ - if (!state_is_normal(peer->state)) - peer->nc = tal_free(peer->nc); - - if (db_commit) - db_update_state(peer); -} - -static void peer_breakdown(struct peer *peer) -{ - if (peer->commit_jsoncmd) { - command_fail(peer->commit_jsoncmd, "peer breakdown"); - peer->commit_jsoncmd = NULL; - } - - /* FIXME: Reason. */ - if (peer->open_jsoncmd) { - command_fail(peer->open_jsoncmd, "peer breakdown"); - peer->open_jsoncmd = NULL; - } - - /* If we have a closing tx, use it. */ - if (peer->closing.their_sig) { - const struct bitcoin_tx *close = mk_bitcoin_close(peer, peer); - log_unusual(peer->log, "Peer breakdown: sending close tx"); - broadcast_tx(peer->dstate->topology, peer, close, NULL); - tal_free(close); - /* If we have a signed commit tx (maybe not if we just offered - * anchor, or they supplied anchor, or no outputs to us). */ - } else if (peer->local.commit && peer->local.commit->sig) { - log_unusual(peer->log, "Peer breakdown: sending commit tx"); - sign_commit_tx(peer); - broadcast_tx(peer->dstate->topology, peer, - peer->local.commit->tx, NULL); - } else { - log_info(peer->log, "Peer breakdown: nothing to do"); - /* We close immediately. */ - set_peer_state(peer, STATE_CLOSED, __func__, false); - db_forget_peer(peer); - } - - /* Always wake peer to close or flush packets. */ - io_wake(peer); -} - -/* All unrevoked commit txs must have no HTLCs in them. */ -static bool committed_to_htlcs(const struct peer *peer) -{ - struct htlc_map_iter it; - struct htlc *h; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (htlc_is_dead(h)) - continue; - return true; - } - return false; -} - -static void peer_calculate_close_fee(struct peer *peer) -{ - /* Use actual worst-case length of close tx: based on FIXME-OLD#02's - * commitment tx numbers, but only 1 byte for output count */ - const uint64_t txsize = 41 + 221 + 10 + 32 + 32; - uint64_t maxfee; - - peer->closing.our_fee - = fee_by_feerate(txsize, get_feerate(peer->dstate->topology)); - - /* FIXME-OLD #2: - * The sender MUST set `close_fee` lower than or equal to the - * fee of the final commitment transaction, and MUST set - * `close_fee` to an even number of satoshis. - */ - maxfee = commit_tx_fee(peer->local.commit->tx, peer->anchor.satoshis); - if (peer->closing.our_fee > maxfee) { - /* This could only happen if the fee rate dramatically */ - log_unusual(peer->log, - "Closing fee %"PRIu64" exceeded commit fee %"PRIu64", reducing.", - peer->closing.our_fee, maxfee); - peer->closing.our_fee = maxfee; - - /* This can happen if actual commit txfee is odd. */ - if (peer->closing.our_fee & 1) - peer->closing.our_fee--; - } - assert(!(peer->closing.our_fee & 1)); -} - -static void start_closing_in_transaction(struct peer *peer) -{ - assert(!committed_to_htlcs(peer)); - - set_peer_state(peer, STATE_MUTUAL_CLOSING, __func__, true); - - peer_calculate_close_fee(peer); - peer->closing.closing_order = peer->order_counter++; - db_update_our_closing(peer); - queue_pkt_close_signature(peer); -} - -static struct io_plan *peer_close(struct io_conn *conn, struct peer *peer) -{ - /* Tell writer to wrap it up (may have to xmit first) */ - io_wake(peer); - /* We do nothing more. */ - return io_wait(conn, NULL, io_never, NULL); -} - -void peer_fail(struct peer *peer, const char *caller) -{ - /* Don't fail twice. */ - if (state_is_error(peer->state) || state_is_onchain(peer->state)) - return; - - /* FIXME: Save state here? */ - set_peer_state(peer, STATE_ERR_BREAKDOWN, caller, false); - peer_breakdown(peer); -} - -/* Communication failed: send err (if non-NULL), then dump to chain and close. */ -static bool peer_comms_err(struct peer *peer, Pkt *err) -{ - if (err) - queue_pkt_err(peer, err); - - peer_fail(peer, __func__); - return false; -} - -static bool peer_database_err(struct peer *peer) -{ - return peer_comms_err(peer, pkt_err(peer, "database error")); -} - -/* Unexpected packet received: stop listening, send error, start - * breakdown procedure, return false. */ -static bool peer_received_unexpected_pkt(struct peer *peer, const Pkt *pkt, - const char *where) -{ - const char *p; - Pkt *err; - - log_unusual(peer->log, "%s: received unexpected pkt %u (%s) in %s", - where, pkt->pkt_case, pkt_name(pkt->pkt_case), - state_name(peer->state)); - - if (pkt->pkt_case != PKT__PKT_ERROR) { - err = pkt_err_unexpected(peer, pkt); - goto out; - } - - /* FIXME-OLD #2: - * - * A node MUST fail the connection if it receives an `err` - * message, and MUST NOT send an `err` message in this case. - * For other connection failures, a node SHOULD send an - * informative `err` message. - */ - err = NULL; - - /* Check packet for weird chars. */ - for (p = pkt->error->problem; *p; p++) { - if (cisprint(*p)) - continue; - - p = tal_hexstr(peer, pkt->error->problem, - strlen(pkt->error->problem)); - log_unusual(peer->log, "Error pkt (hex) %s", p); - tal_free(p); - goto out; - } - log_unusual(peer->log, "Error pkt '%s'", pkt->error->problem); - -out: - return peer_comms_err(peer, err); -} - -/* Creation the bitcoin anchor tx, spending output user provided. */ -static bool bitcoin_create_anchor(struct peer *peer) -{ - struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); - size_t i; - - /* We must be offering anchor for us to try creating it */ - assert(peer->local.offer_anchor); - - tx->output[0].script = scriptpubkey_p2wsh(tx, peer->anchor.witnessscript); - tx->output[0].amount = peer->anchor.input->out_amount; - - tx->input[0].txid = peer->anchor.input->txid; - tx->input[0].index = peer->anchor.input->index; - tx->input[0].amount = tal_dup(tx->input, u64, - &peer->anchor.input->in_amount); - - if (!wallet_add_signed_input(peer->dstate, - &peer->anchor.input->walletkey, - tx, 0)) - return false; - - bitcoin_txid(tx, &peer->anchor.txid); - peer->anchor.tx = tx; - peer->anchor.index = 0; - /* We'll need this later, when we're told to broadcast it. */ - peer->anchor.satoshis = tx->output[0].amount; - - /* To avoid malleation, all inputs must be segwit! */ - for (i = 0; i < tal_count(tx->input); i++) - assert(tx->input[i].witness); - return true; -} - -static bool open_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err; - struct commit_info *ci; - - assert(peer->state == STATE_OPEN_WAIT_FOR_OPENPKT); - - if (pkt->pkt_case != PKT__PKT_OPEN) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - db_start_transaction(peer); - ci = new_commit_info(peer, 0); - - err = accept_pkt_open(peer, pkt, &ci->revocation_hash, - &peer->remote.next_revocation_hash); - if (err) { - db_abort_transaction(peer); - return peer_comms_err(peer, err); - } - - db_set_visible_state(peer); - - /* Set up their commit info now: rest gets done in setup_first_commit - * once anchor is established. */ - peer->remote.commit = ci; - - /* Witness script for anchor. */ - peer->anchor.witnessscript - = bitcoin_redeem_2of2(peer, - &peer->local.commitkey, - &peer->remote.commitkey); - - if (peer->local.offer_anchor) { - if (!bitcoin_create_anchor(peer)) { - db_abort_transaction(peer); - err = pkt_err(peer, "Own anchor unavailable"); - return peer_comms_err(peer, err); - } - /* FIXME: Redundant with peer->local.offer_anchor? */ - peer->anchor.ours = true; - - /* This shouldn't happen! */ - if (!setup_first_commit(peer)) { - db_abort_transaction(peer); - err = pkt_err(peer, "Own anchor has insufficient funds"); - return peer_comms_err(peer, err); - } - set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT, - __func__, true); - if (db_commit_transaction(peer) != NULL) - return peer_database_err(peer); - queue_pkt_anchor(peer); - return true; - } else { - set_peer_state(peer, STATE_OPEN_WAIT_FOR_ANCHORPKT, - __func__, true); - if (db_commit_transaction(peer) != NULL) - return peer_database_err(peer); - return true; - } -} - -static void funding_tx_failed(struct peer *peer, - int exitstatus, - const char *err) -{ - const char *str = tal_fmt(peer, "Broadcasting funding gave %i: %s", - exitstatus, err); - - peer_open_complete(peer, str); - peer_breakdown(peer); - queue_pkt_err(peer, pkt_err(peer, "Funding failed")); -} - -static bool open_ouranchor_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err; - - if (pkt->pkt_case != PKT__PKT_OPEN_COMMIT_SIG) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - peer->local.commit->sig = tal(peer->local.commit, - secp256k1_ecdsa_signature); - err = accept_pkt_open_commit_sig(peer, pkt, - peer->local.commit->sig); - if (!err && - !check_tx_sig(peer->local.commit->tx, 0, - NULL, - peer->anchor.witnessscript, - &peer->remote.commitkey, - peer->local.commit->sig)) - err = pkt_err(peer, "Bad signature"); - - if (err) { - peer->local.commit->sig = tal_free(peer->local.commit->sig); - return peer_comms_err(peer, err); - } - - peer->their_commitsigs++; - - db_start_transaction(peer); - db_set_anchor(peer); - db_new_commit_info(peer, LOCAL, NULL); - set_peer_state(peer, - STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, - __func__, true); - if (db_commit_transaction(peer) != NULL) - return peer_database_err(peer); - - broadcast_tx(peer->dstate->topology, - peer, peer->anchor.tx, funding_tx_failed); - peer_watch_anchor(peer, peer->local.mindepth); - return true; -} - - -static bool open_theiranchor_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err; - const char *db_err; - - if (pkt->pkt_case != PKT__PKT_OPEN_ANCHOR) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - err = accept_pkt_anchor(peer, pkt); - if (err) { - peer_open_complete(peer, err->error->problem); - return peer_comms_err(peer, err); - } - - peer->anchor.ours = false; - if (!setup_first_commit(peer)) { - err = pkt_err(peer, "Insufficient funds for fee"); - peer_open_complete(peer, err->error->problem); - return peer_comms_err(peer, err); - } - - log_debug_struct(peer->log, "Creating sig for %s", - struct bitcoin_tx, - peer->remote.commit->tx); - log_add_struct(peer->log, " using key %s", - struct pubkey, &peer->local.commitkey); - - peer->remote.commit->sig = tal(peer->remote.commit, - secp256k1_ecdsa_signature); - peer_sign_theircommit(peer, peer->remote.commit->tx, - peer->remote.commit->sig); - - peer->remote.commit->order = peer->order_counter++; - db_start_transaction(peer); - db_set_anchor(peer); - db_new_commit_info(peer, REMOTE, NULL); - peer_add_their_commit(peer, - &peer->remote.commit->txid, - peer->remote.commit->commit_num); - set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, - __func__, true); - db_err = db_commit_transaction(peer); - if (db_err) { - peer_open_complete(peer, db_err); - return peer_database_err(peer); - } - - queue_pkt_open_commit_sig(peer); - peer_watch_anchor(peer, peer->local.mindepth); - return true; -} - -/* Dump all known channels and nodes to the peer. Used when a new - * connection was established. */ -static void sync_routing_table(struct lightningd_state *dstate, struct peer *peer) -{ - struct node *n; - struct node_map_iter it; - int i; - struct node_connection *nc; - for (n = node_map_first(dstate->rstate->nodes, &it); n; n = node_map_next(dstate->rstate->nodes, &it)) { - size_t num_edges = tal_count(n->out); - for (i = 0; i < num_edges; i++) { - nc = n->out[i]; - if (nc->channel_announcement) - queue_pkt_nested(peer, WIRE_CHANNEL_ANNOUNCEMENT, nc->channel_announcement); - if (nc->channel_update) - queue_pkt_nested(peer, WIRE_CHANNEL_UPDATE, nc->channel_update); - } - if (n->node_announcement && num_edges > 0) - queue_pkt_nested(peer, WIRE_NODE_ANNOUNCEMENT, n->node_announcement); - } -} - -static bool open_wait_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err; - const char *db_err; - - /* If they want to shutdown during this, we do mutual close dance. */ - if (pkt->pkt_case == PKT__PKT_CLOSE_SHUTDOWN) { - err = accept_pkt_close_shutdown(peer, pkt); - if (err) - return peer_comms_err(peer, err); - - peer_open_complete(peer, "Shutdown request received"); - db_start_transaction(peer); - db_set_their_closing_script(peer); - start_closing_in_transaction(peer); - if (db_commit_transaction(peer) != NULL) - return peer_database_err(peer); - - return false; - } - - switch (peer->state) { - case STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE: - case STATE_OPEN_WAIT_THEIRCOMPLETE: - if (pkt->pkt_case != PKT__PKT_OPEN_COMPLETE) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - err = accept_pkt_open_complete(peer, pkt); - if (err) { - peer_open_complete(peer, err->error->problem); - return peer_comms_err(peer, err); - } - - db_start_transaction(peer); - if (peer->state == STATE_OPEN_WAIT_THEIRCOMPLETE) { - peer_open_complete(peer, NULL); - set_peer_state(peer, STATE_NORMAL, __func__, true); - announce_channel(peer->dstate, peer); - sync_routing_table(peer->dstate, peer); - } else { - set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH, - __func__, true); - } - - db_err = db_commit_transaction(peer); - if (db_err) { - peer_open_complete(peer, db_err); - return peer_database_err(peer); - } - return true; - - case STATE_OPEN_WAIT_ANCHORDEPTH: - return peer_received_unexpected_pkt(peer, pkt, __func__); - - default: - log_unusual(peer->log, - "%s: unexpected state %s", - __func__, state_name(peer->state)); - peer_fail(peer, __func__); - return false; - } -} - -static void set_htlc_rval(struct peer *peer, - struct htlc *htlc, const struct preimage *rval) -{ - assert(!htlc->r); - assert(!htlc->fail); - htlc->r = tal_dup(htlc, struct preimage, rval); - db_htlc_fulfilled(peer, htlc); -} - -static void set_htlc_fail(struct peer *peer, - struct htlc *htlc, const void *fail, size_t len) -{ - assert(!htlc->r); - assert(!htlc->fail); - htlc->fail = tal_dup_arr(htlc, u8, fail, len, 0); - db_htlc_failed(peer, htlc); -} - -static void route_htlc_onwards(struct peer *peer, - struct htlc *htlc, - u64 msatoshi, - const u8 *pb_id, - const u8 *rest_of_route, - const struct peer *only_dest) -{ - struct peer *next; - struct htlc *newhtlc; - enum fail_error error_code; - const char *err; - - if (!only_dest) { - log_debug_struct(peer->log, "Forwarding HTLC %s", - struct sha256, &htlc->rhash); - log_add(peer->log, " (id %"PRIu64")", htlc->id); - } - - next = find_peer_by_pkhash(peer->dstate, pb_id); - if (!next || !next->nc) { - log_unusual(peer->log, "Can't route HTLC %"PRIu64": no %speer ", - htlc->id, next ? "ready " : ""); - if (!peer->dstate->dev_never_routefail) - command_htlc_set_fail(peer, htlc, NOT_FOUND_404, - "Unknown peer"); - return; - } - - if (only_dest && next != only_dest) - return; - - /* Offered fee must be sufficient. */ - if ((s64)(htlc->msatoshi - msatoshi) - < connection_fee(next->nc, msatoshi)) { - log_unusual(peer->log, - "Insufficient fee for HTLC %"PRIu64 - ": %"PRIi64" on %"PRIu64, - htlc->id, htlc->msatoshi - msatoshi, - msatoshi); - command_htlc_set_fail(peer, htlc, PAYMENT_REQUIRED_402, - "Insufficent fee"); - return; - } - - log_debug_struct(peer->log, "HTLC forward to %s", - struct pubkey, next->id); - - /* This checks the HTLC itself is possible. */ - err = command_htlc_add(next, msatoshi, - abs_locktime_to_blocks(&htlc->expiry) - - next->nc->delay, - &htlc->rhash, htlc, rest_of_route, - &error_code, &newhtlc); - if (err) - command_htlc_set_fail(peer, htlc, error_code, err); -} - -static void their_htlc_added(struct peer *peer, struct htlc *htlc, - struct peer *only_dest) -{ - struct invoice *invoice; - struct onionpacket *packet; - struct route_step *step = NULL; - - if (abs_locktime_is_seconds(&htlc->expiry)) { - log_unusual(peer->log, "HTLC %"PRIu64" is in seconds", htlc->id); - command_htlc_set_fail(peer, htlc, BAD_REQUEST_400, - "bad locktime"); - return; - } - - if (abs_locktime_to_blocks(&htlc->expiry) <= - get_block_height(peer->dstate->topology) + peer->dstate->config.min_htlc_expiry) { - log_unusual(peer->log, "HTLC %"PRIu64" expires too soon:" - " block %u", - htlc->id, abs_locktime_to_blocks(&htlc->expiry)); - command_htlc_set_fail(peer, htlc, BAD_REQUEST_400, - "expiry too soon"); - return; - } - - if (abs_locktime_to_blocks(&htlc->expiry) > - get_block_height(peer->dstate->topology) + peer->dstate->config.max_htlc_expiry) { - log_unusual(peer->log, "HTLC %"PRIu64" expires too far:" - " block %u", - htlc->id, abs_locktime_to_blocks(&htlc->expiry)); - command_htlc_set_fail(peer, htlc, BAD_REQUEST_400, - "expiry too far"); - return; - } - - packet = parse_onionpacket(peer, - htlc->routing, tal_count(htlc->routing)); - if (packet) { - u8 shared_secret[32]; - - if (onion_shared_secret(shared_secret, packet, - peer->dstate->privkey)) - step = process_onionpacket(packet, packet, - shared_secret, - htlc->rhash.u.u8, - sizeof(htlc->rhash)); - } - - if (!step) { - log_unusual(peer->log, "Bad onion, failing HTLC %"PRIu64, - htlc->id); - command_htlc_set_fail(peer, htlc, BAD_REQUEST_400, - "invalid onion"); - goto free_packet; - } - - switch (step->nextcase) { - case ONION_END: - if (only_dest) - goto free_packet; - invoice = find_unpaid(peer->dstate->invoices, &htlc->rhash); - if (!invoice) { - log_unusual(peer->log, "No invoice for HTLC %"PRIu64, - htlc->id); - log_add_struct(peer->log, " rhash=%s", - struct sha256, &htlc->rhash); - if (unlikely(!peer->dstate->dev_never_routefail)) - command_htlc_set_fail(peer, htlc, - UNAUTHORIZED_401, - "unknown rhash"); - goto free_packet; - } - - if (htlc->msatoshi != invoice->msatoshi) { - log_unusual(peer->log, "Short payment for '%s' HTLC %"PRIu64 - ": %"PRIu64" not %"PRIu64 " satoshi!", - invoice->label, - htlc->id, - htlc->msatoshi, - invoice->msatoshi); - command_htlc_set_fail(peer, htlc, - UNAUTHORIZED_401, - "incorrect amount"); - goto free_packet; - } - - log_info(peer->log, "Immediately resolving '%s' HTLC %"PRIu64, - invoice->label, htlc->id); - - resolve_invoice(peer->dstate, invoice); - set_htlc_rval(peer, htlc, &invoice->r); - command_htlc_fulfill(peer, htlc); - goto free_packet; - - case ONION_FORWARD: - route_htlc_onwards(peer, htlc, step->hoppayload->amt_to_forward, step->next->nexthop, - serialize_onionpacket(step, step->next), only_dest); - goto free_packet; - default: - log_info(peer->log, "Unknown step type %u", step->nextcase); - command_htlc_set_fail(peer, htlc, VERSION_NOT_SUPPORTED_505, - "unknown step type"); - goto free_packet; - } - -free_packet: - tal_free(packet); -} - -static void our_htlc_failed(struct peer *peer, struct htlc *htlc) -{ - assert(htlc_owner(htlc) == LOCAL); - if (htlc->src) { - set_htlc_fail(htlc->src->peer, htlc->src, - htlc->fail, tal_count(htlc->fail)); - command_htlc_fail(htlc->src->peer, htlc->src); - } else - complete_pay_command(peer->dstate, htlc); -} - -static void our_htlc_fulfilled(struct peer *peer, struct htlc *htlc) -{ - if (htlc->src) { - set_htlc_rval(htlc->src->peer, htlc->src, htlc->r); - command_htlc_fulfill(htlc->src->peer, htlc->src); - } else { - complete_pay_command(peer->dstate, htlc); - } -} - -/* FIXME: Slow! */ -static struct htlc *htlc_with_source(struct peer *peer, struct htlc *src) -{ - struct htlc_map_iter it; - struct htlc *h; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (h->src == src) - return h; - } - return NULL; -} - -/* peer has come back online: re-send any we have to send to them. */ -static void retry_all_routing(struct peer *restarted_peer) -{ - struct peer *peer; - struct htlc_map_iter it; - struct htlc *h; - - /* Look for added htlcs from other peers which need to go here. */ - list_for_each(&restarted_peer->dstate->peers, peer, list) { - if (peer == restarted_peer) - continue; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (h->state != RCVD_ADD_ACK_REVOCATION) - continue; - if (htlc_with_source(peer, h)) - continue; - their_htlc_added(peer, h, restarted_peer); - } - } - - /* Catch any HTLCs which are fulfilled, but the message got reset - * by reconnect. */ - for (h = htlc_map_first(&restarted_peer->htlcs, &it); - h; - h = htlc_map_next(&restarted_peer->htlcs, &it)) { - if (h->state != RCVD_ADD_ACK_REVOCATION) - continue; - if (h->r) - command_htlc_fulfill(restarted_peer, h); - else if (h->fail) - command_htlc_fail(restarted_peer, h); - } -} - -static bool adjust_cstate_side(struct channel_state *cstate, - struct htlc *h, - enum htlc_state old, enum htlc_state new, - enum side side) -{ - int oldf = htlc_state_flags(old), newf = htlc_state_flags(new); - bool old_committed, new_committed; - - /* We applied changes to staging_cstate when we first received - * add/remove packet, so we could make sure it was valid. Don't - * do that again. */ - if (old == SENT_ADD_HTLC || old == RCVD_REMOVE_HTLC - || old == RCVD_ADD_HTLC || old == SENT_REMOVE_HTLC) - return true; - - old_committed = (oldf & HTLC_FLAG(side, HTLC_F_COMMITTED)); - new_committed = (newf & HTLC_FLAG(side, HTLC_F_COMMITTED)); - - if (old_committed && !new_committed) { - if (h->r) - cstate_fulfill_htlc(cstate, h); - else - cstate_fail_htlc(cstate, h); - } else if (!old_committed && new_committed) { - if (!cstate_add_htlc(cstate, h, false)) { - log_broken_struct(h->peer->log, - "Cannot afford htlc %s", - struct htlc, h); - log_add_struct(h->peer->log, " channel state %s", - struct channel_state, cstate); - return false; - } - } - return true; -} - -/* We apply changes to staging_cstate when we first PENDING, so we can - * make sure they're valid. So here we change the staging_cstate on - * the revocation receive (ie. when acked). */ -static bool adjust_cstates(struct peer *peer, struct htlc *h, - enum htlc_state old, enum htlc_state new) -{ - return adjust_cstate_side(peer->remote.staging_cstate, h, old, new, - REMOTE) - && adjust_cstate_side(peer->local.staging_cstate, h, old, new, - LOCAL); -} - -static void adjust_cstate_fee_side(struct channel_state *cstate, - const struct feechange *f, - enum feechange_state old, - enum feechange_state new, - enum side side) -{ - /* We applied changes to staging_cstate when we first received - * feechange packet, so we could make sure it was valid. Don't - * do that again. */ - if (old == SENT_FEECHANGE || old == RCVD_FEECHANGE) - return; - - /* Feechanges only ever get applied to the side which created them: - * ours gets applied when they ack, theirs gets applied when we ack. */ - if (side == LOCAL && new == RCVD_FEECHANGE_REVOCATION) - adjust_fee(cstate, f->fee_rate); - else if (side == REMOTE && new == SENT_FEECHANGE_REVOCATION) - adjust_fee(cstate, f->fee_rate); -} - -static void adjust_cstates_fee(struct peer *peer, const struct feechange *f, - enum feechange_state old, - enum feechange_state new) -{ - adjust_cstate_fee_side(peer->remote.staging_cstate, f, old, new, REMOTE); - adjust_cstate_fee_side(peer->local.staging_cstate, f, old, new, LOCAL); -} - -static void check_both_committed(struct peer *peer, struct htlc *h) -{ - if (!htlc_has(h, HTLC_ADDING) && !htlc_has(h, HTLC_REMOVING)) - log_debug(peer->log, - "Both committed to %s of %s HTLC %"PRIu64 "(%s)", - h->state == SENT_ADD_ACK_REVOCATION - || h->state == RCVD_ADD_ACK_REVOCATION ? "ADD" - : h->r ? "FULFILL" : "FAIL", - htlc_owner(h) == LOCAL ? "our" : "their", - h->id, htlc_state_name(h->state)); - - switch (h->state) { - case RCVD_REMOVE_ACK_REVOCATION: - /* If it was fulfilled, we handled it immediately. */ - if (h->fail) - our_htlc_failed(peer, h); - break; - case RCVD_ADD_ACK_REVOCATION: - their_htlc_added(peer, h, NULL); - break; - default: - break; - } -} - -struct htlcs_table { - enum htlc_state from, to; -}; - -struct feechanges_table { - enum feechange_state from, to; -}; - -static const char *changestates(struct peer *peer, - const struct htlcs_table *table, - size_t n, - const struct feechanges_table *ftable, - size_t n_ftable, - bool db_commit) -{ - struct htlc_map_iter it; - struct htlc *h; - bool changed = false; - size_t i; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - for (i = 0; i < n; i++) { - if (h->state == table[i].from) { - if (!adjust_cstates(peer, h, - table[i].from, table[i].to)) - return "accounting error"; - htlc_changestate(h, table[i].from, - table[i].to, db_commit); - check_both_committed(peer, h); - changed = true; - } - } - } - - for (i = 0; i < n_ftable; i++) { - struct feechange *f = peer->feechanges[ftable[i].from]; - if (!f) - continue; - adjust_cstates_fee(peer, f, ftable[i].from, ftable[i].to); - feechange_changestate(peer, f, - ftable[i].from, ftable[i].to, - db_commit); - changed = true; - } - - /* FIXME-OLD #2: - * - * A node MUST NOT send an `update_commit` message which does - * not include any updates. - */ - if (!changed) - return "no changes made"; - return NULL; -} - -/* This is the io loop while we're negotiating closing tx. */ -static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) -{ - const CloseSignature *c = pkt->close_signature; - struct bitcoin_tx *close_tx; - secp256k1_ecdsa_signature theirsig; - - assert(peer->state == STATE_MUTUAL_CLOSING); - - if (pkt->pkt_case != PKT__PKT_CLOSE_SIGNATURE) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - log_info(peer->log, "closing_pkt_in: they offered close fee %"PRIu64, - c->close_fee); - - /* FIXME-OLD #2: - * - * The sender MUST set `close_fee` lower than or equal to the fee of the - * final commitment transaction, and MUST set `close_fee` to an even - * number of satoshis. - */ - if ((c->close_fee & 1) - || c->close_fee > commit_tx_fee(peer->remote.commit->tx, - peer->anchor.satoshis)) { - return peer_comms_err(peer, pkt_err(peer, "Invalid close fee")); - } - - /* FIXME: Don't accept tiny fee at all? */ - - /* FIXME-OLD #2: - ... otherwise it SHOULD propose a - value strictly between the received `close_fee` and its - previously-sent `close_fee`. - */ - if (peer->closing.their_sig) { - /* We want more, they should give more. */ - if (peer->closing.our_fee > peer->closing.their_fee) { - if (c->close_fee <= peer->closing.their_fee) - return peer_comms_err(peer, - pkt_err(peer, "Didn't increase close fee")); - } else { - if (c->close_fee >= peer->closing.their_fee) - return peer_comms_err(peer, - pkt_err(peer, "Didn't decrease close fee")); - } - } - - /* FIXME-OLD #2: - * - * The receiver MUST check `sig` is valid for the close - * transaction with the given `close_fee`, and MUST fail the - * connection if it is not. */ - if (!proto_to_signature(c->sig, &theirsig)) - return peer_comms_err(peer, - pkt_err(peer, "Invalid signature format")); - - close_tx = peer_create_close_tx(c, peer, c->close_fee); - if (!check_tx_sig(close_tx, 0, - NULL, - peer->anchor.witnessscript, - &peer->remote.commitkey, &theirsig)) - return peer_comms_err(peer, - pkt_err(peer, "Invalid signature")); - - tal_free(peer->closing.their_sig); - peer->closing.their_sig = tal_dup(peer, - secp256k1_ecdsa_signature, &theirsig); - peer->closing.their_fee = c->close_fee; - peer->closing.sigs_in++; - - if (!db_update_their_closing(peer)) - return peer_database_err(peer); - - if (peer->closing.our_fee != peer->closing.their_fee) { - /* FIXME-OLD #2: - * - * If the receiver agrees with the fee, it SHOULD reply with a - * `close_signature` with the same `close_fee` value, - * otherwise it SHOULD propose a value strictly between the - * received `close_fee` and its previously-sent `close_fee`. - */ - - /* Adjust our fee to close on their fee. */ - u64 sum; - - /* Beware overflow! */ - sum = (u64)peer->closing.our_fee + peer->closing.their_fee; - - peer->closing.our_fee = sum / 2; - if (peer->closing.our_fee & 1) - peer->closing.our_fee++; - - log_info(peer->log, "accept_pkt_close_sig: we change to %"PRIu64, - peer->closing.our_fee); - - peer->closing.closing_order = peer->order_counter++; - - db_start_transaction(peer); - db_update_our_closing(peer); - if (db_commit_transaction(peer) != NULL) - return peer_database_err(peer); - - queue_pkt_close_signature(peer); - } - - /* Note corner case: we may *now* agree with them! */ - if (peer->closing.our_fee == peer->closing.their_fee) { - const struct bitcoin_tx *close; - log_info(peer->log, "accept_pkt_close_sig: we agree"); - /* FIXME-OLD #2: - * - * Once a node has sent or received a `close_signature` with - * matching `close_fee` it SHOULD close the connection and - * SHOULD sign and broadcast the final closing transaction. - */ - close = mk_bitcoin_close(peer, peer); - broadcast_tx(peer->dstate->topology, peer, close, NULL); - tal_free(close); - return false; - } - - return true; -} - -/* We can get update_commit in both normal and shutdown states. */ -static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) -{ - Pkt *err; - const char *errmsg; - struct sha256 preimage; - struct commit_info *ci; - bool to_them_only; - /* FIXME: We can actually merge these two... */ - static const struct htlcs_table commit_changes[] = { - { RCVD_ADD_REVOCATION, RCVD_ADD_ACK_COMMIT }, - { RCVD_REMOVE_HTLC, RCVD_REMOVE_COMMIT }, - { RCVD_ADD_HTLC, RCVD_ADD_COMMIT }, - { RCVD_REMOVE_REVOCATION, RCVD_REMOVE_ACK_COMMIT } - }; - static const struct feechanges_table commit_feechanges[] = { - { RCVD_FEECHANGE_REVOCATION, RCVD_FEECHANGE_ACK_COMMIT }, - { RCVD_FEECHANGE, RCVD_FEECHANGE_COMMIT } - }; - static const struct htlcs_table revocation_changes[] = { - { RCVD_ADD_ACK_COMMIT, SENT_ADD_ACK_REVOCATION }, - { RCVD_REMOVE_COMMIT, SENT_REMOVE_REVOCATION }, - { RCVD_ADD_COMMIT, SENT_ADD_REVOCATION }, - { RCVD_REMOVE_ACK_COMMIT, SENT_REMOVE_ACK_REVOCATION } - }; - static const struct feechanges_table revocation_feechanges[] = { - { RCVD_FEECHANGE_ACK_COMMIT, SENT_FEECHANGE_ACK_REVOCATION }, - { RCVD_FEECHANGE_COMMIT, SENT_FEECHANGE_REVOCATION } - }; - - ci = new_commit_info(peer, peer->local.commit->commit_num + 1); - - db_start_transaction(peer); - - /* FIXME-OLD #2: - * - * A node MUST NOT send an `update_commit` message which does - * not include any updates. - */ - errmsg = changestates(peer, - commit_changes, ARRAY_SIZE(commit_changes), - commit_feechanges, ARRAY_SIZE(commit_feechanges), - true); - if (errmsg) { - db_abort_transaction(peer); - return pkt_err(peer, "%s", errmsg); - } - - /* Create new commit info for this commit tx. */ - ci->revocation_hash = peer->local.next_revocation_hash; - - /* FIXME-OLD #2: - * - * A receiving node MUST apply all local acked and unacked - * changes except unacked fee changes to the local commitment - */ - /* (We already applied them to staging_cstate as we went) */ - ci->cstate = copy_cstate(ci, peer->local.staging_cstate); - ci->tx = create_commit_tx(ci, peer, &ci->revocation_hash, - ci->cstate, LOCAL, &to_them_only); - bitcoin_txid(ci->tx, &ci->txid); - - log_debug(peer->log, "Check tx %"PRIu64" sig", ci->commit_num); - log_add_struct(peer->log, " for %s", struct channel_state, ci->cstate); - log_add_struct(peer->log, " (txid %s)", struct sha256_double, &ci->txid); - - /* FIXME-OLD #2: - * - * If the commitment transaction has only a single output which pays - * to the other node, `sig` MUST be unset. Otherwise, a sending node - * MUST apply all remote acked and unacked changes except unacked fee - * changes to the remote commitment before generating `sig`. - */ - if (!to_them_only) - ci->sig = tal(ci, secp256k1_ecdsa_signature); - - err = accept_pkt_commit(peer, pkt, ci->sig); - if (err) - return err; - - /* FIXME-OLD #2: - * - * A receiving node MUST apply all local acked and unacked changes - * except unacked fee changes to the local commitment, then it MUST - * check `sig` is valid for that transaction. - */ - if (ci->sig && !check_tx_sig(ci->tx, 0, - NULL, - peer->anchor.witnessscript, - &peer->remote.commitkey, - ci->sig)) { - db_abort_transaction(peer); - return pkt_err(peer, "Bad signature"); - } - - /* Switch to the new commitment. */ - tal_free(peer->local.commit); - peer->local.commit = ci; - peer->local.commit->order = peer->order_counter++; - - db_new_commit_info(peer, LOCAL, NULL); - peer_get_revocation_hash(peer, ci->commit_num + 1, - &peer->local.next_revocation_hash); - peer->their_commitsigs++; - - /* Now, send the revocation. */ - - /* We have their signature on the current one, right? */ - assert(to_them_only || peer->local.commit->sig); - assert(peer->local.commit->commit_num > 0); - - errmsg = changestates(peer, - revocation_changes, ARRAY_SIZE(revocation_changes), - revocation_feechanges, - ARRAY_SIZE(revocation_feechanges), - true); - if (errmsg) { - log_broken(peer->log, "queue_pkt_revocation: %s", errmsg); - db_abort_transaction(peer); - return pkt_err(peer, "Database error"); - } - - peer_get_revocation_preimage(peer, peer->local.commit->commit_num - 1, - &preimage); - - /* Fire off timer if this ack caused new changes */ - if (peer_uncommitted_changes(peer)) - remote_changes_pending(peer); - - queue_pkt_revocation(peer, &preimage, &peer->local.next_revocation_hash); - - /* If we're shutting down and no more HTLCs, begin closing */ - if (peer->closing.their_script && !committed_to_htlcs(peer)) - start_closing_in_transaction(peer); - - if (db_commit_transaction(peer) != NULL) - return pkt_err(peer, "Database error"); - - return NULL; -} - -static Pkt *handle_pkt_htlc_add(struct peer *peer, const Pkt *pkt) -{ - struct htlc *htlc; - Pkt *err; - - err = accept_pkt_htlc_add(peer, pkt, &htlc); - if (err) - return err; - assert(htlc->state == RCVD_ADD_HTLC); - - /* FIXME-OLD #2: - * - * A node MUST NOT offer `amount_msat` it cannot pay for in - * the remote commitment transaction at the current `fee_rate` (see - * "Fee Calculation" ). A node SHOULD fail the connection if - * this occurs. - */ - if (!cstate_add_htlc(peer->local.staging_cstate, htlc, true)) { - u64 id = htlc->id; - log_broken_struct(peer->log, "They cannot afford htlc %s", - struct htlc, htlc); - log_add_struct(peer->log, " cstate %s", - struct channel_state, - peer->local.staging_cstate); - tal_free(htlc); - return pkt_err(peer, "Cannot afford htlc %"PRIu64, id); - } - return NULL; -} - -static Pkt *handle_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) -{ - struct htlc *htlc; - u8 *fail; - Pkt *err; - - err = accept_pkt_htlc_fail(peer, pkt, &htlc, &fail); - if (err) - return err; - - /* This can happen with re-transmissions; simply note it. */ - if (htlc->fail) { - log_debug(peer->log, "HTLC %"PRIu64" failed twice", htlc->id); - htlc->fail = tal_free(htlc->fail); - } - - db_start_transaction(peer); - - set_htlc_fail(peer, htlc, fail, tal_count(fail)); - tal_free(fail); - - if (db_commit_transaction(peer) != NULL) - return pkt_err(peer, "database error"); - - cstate_fail_htlc(peer->local.staging_cstate, htlc); - - /* FIXME-OLD #2: - * - * ... and the receiving node MUST add the HTLC fulfill/fail - * to the unacked changeset for its local commitment. - */ - htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC, false); - return NULL; -} - -static Pkt *handle_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) -{ - struct htlc *htlc; - Pkt *err; - struct preimage r; - - err = accept_pkt_htlc_fulfill(peer, pkt, &htlc, &r); - if (err) - return err; - - /* Reconnect may mean HTLC was already fulfilled. That's OK. */ - if (!htlc->r) { - db_start_transaction(peer); - set_htlc_rval(peer, htlc, &r); - - /* We can relay this upstream immediately. */ - our_htlc_fulfilled(peer, htlc); - if (db_commit_transaction(peer) != NULL) - return pkt_err(peer, "database error"); - } - - /* FIXME-OLD #2: - * - * ... and the receiving node MUST add the HTLC fulfill/fail - * to the unacked changeset for its local commitment. - */ - cstate_fulfill_htlc(peer->local.staging_cstate, htlc); - htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC, false); - return NULL; -} - -static void set_feechange(struct peer *peer, u64 fee_rate, - enum feechange_state state) -{ - /* If we already have a feechange for this commit, simply update it. */ - if (peer->feechanges[state]) { - log_debug(peer->log, "Feechange: fee %"PRIu64" to %"PRIu64, - peer->feechanges[state]->fee_rate, - fee_rate); - peer->feechanges[state]->fee_rate = fee_rate; - } else { - log_debug(peer->log, "Feechange: New fee %"PRIu64, fee_rate); - peer->feechanges[state] = new_feechange(peer, fee_rate, state); - } -} - -static Pkt *handle_pkt_feechange(struct peer *peer, const Pkt *pkt) -{ - u64 feerate; - Pkt *err; - - err = accept_pkt_update_fee(peer, pkt, &feerate); - if (err) - return err; - - /* FIXME-OLD #2: - * - * The sending node MUST NOT send a `fee_rate` which it could not - * afford (see "Fee Calculation), were it applied to the receiving - * node's commitment transaction. The receiving node SHOULD fail the - * connection if this occurs. - */ - if (!can_afford_feerate(peer->local.staging_cstate, feerate, REMOTE)) - return pkt_err(peer, "Cannot afford feerate %"PRIu64, - feerate); - - set_feechange(peer, feerate, RCVD_FEECHANGE); - return NULL; -} - -static Pkt *handle_pkt_revocation(struct peer *peer, const Pkt *pkt, - enum state next_state) -{ - Pkt *err; - const char *errmsg; - static const struct htlcs_table changes[] = { - { SENT_ADD_COMMIT, RCVD_ADD_REVOCATION }, - { SENT_REMOVE_ACK_COMMIT, RCVD_REMOVE_ACK_REVOCATION }, - { SENT_ADD_ACK_COMMIT, RCVD_ADD_ACK_REVOCATION }, - { SENT_REMOVE_COMMIT, RCVD_REMOVE_REVOCATION } - }; - static const struct feechanges_table feechanges[] = { - { SENT_FEECHANGE_COMMIT, RCVD_FEECHANGE_REVOCATION }, - { SENT_FEECHANGE_ACK_COMMIT, RCVD_FEECHANGE_ACK_REVOCATION } - }; - - err = accept_pkt_revocation(peer, pkt); - if (err) - return err; - - /* FIXME-OLD #2: - * - * The receiver of `update_revocation`... MUST add the remote - * unacked changes to the set of local acked changes. - */ - db_start_transaction(peer); - errmsg = changestates(peer, changes, ARRAY_SIZE(changes), - feechanges, ARRAY_SIZE(feechanges), true); - if (errmsg) { - log_broken(peer->log, "accept_pkt_revocation: %s", errmsg); - db_abort_transaction(peer); - return pkt_err(peer, "failure accepting update_revocation: %s", - errmsg); - } - db_save_shachain(peer); - db_update_next_revocation_hash(peer); - set_peer_state(peer, next_state, __func__, true); - db_remove_their_prev_revocation_hash(peer); - - /* If we're shutting down and no more HTLCs, begin closing */ - if (peer->closing.their_script && !committed_to_htlcs(peer)) - start_closing_in_transaction(peer); - - if (db_commit_transaction(peer) != NULL) - return pkt_err(peer, "database error"); - - return NULL; -} - -/* This is the io loop while we're doing shutdown. */ -static bool shutdown_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err = NULL; - - assert(peer->state == STATE_SHUTDOWN - || peer->state == STATE_SHUTDOWN_COMMITTING); - - switch (pkt->pkt_case) { - case PKT__PKT_UPDATE_REVOCATION: - if (peer->state == STATE_SHUTDOWN) - return peer_received_unexpected_pkt(peer, pkt, __func__); - else { - err = handle_pkt_revocation(peer, pkt, STATE_SHUTDOWN); - if (!err) - peer_update_complete(peer); - } - break; - - case PKT__PKT_UPDATE_ADD_HTLC: - /* FIXME-OLD #2: - * - * A node MUST NOT send a `update_add_htlc` after a - * `close_shutdown` */ - if (peer->closing.their_script) - err = pkt_err(peer, "Update during shutdown"); - else - err = handle_pkt_htlc_add(peer, pkt); - break; - - case PKT__PKT_CLOSE_SHUTDOWN: - /* FIXME-OLD #2: - * - * A node... MUST NOT send more than one `close_shutdown`. */ - if (peer->closing.their_script) - return peer_received_unexpected_pkt(peer, pkt, __func__); - else { - err = accept_pkt_close_shutdown(peer, pkt); - if (!err) { - db_start_transaction(peer); - db_set_their_closing_script(peer); - /* If no more HTLCs, we're closing. */ - if (!committed_to_htlcs(peer)) - start_closing_in_transaction(peer); - if (db_commit_transaction(peer) != NULL) - err = pkt_err(peer, "database error"); - } - } - break; - - case PKT__PKT_UPDATE_FULFILL_HTLC: - err = handle_pkt_htlc_fulfill(peer, pkt); - break; - case PKT__PKT_UPDATE_FAIL_HTLC: - err = handle_pkt_htlc_fail(peer, pkt); - break; - case PKT__PKT_UPDATE_FEE: - err = handle_pkt_feechange(peer, pkt); - break; - case PKT__PKT_UPDATE_COMMIT: - err = handle_pkt_commit(peer, pkt); - break; - case PKT__PKT_ERROR: - return peer_received_unexpected_pkt(peer, pkt, __func__); - - case PKT__PKT_AUTH: - case PKT__PKT_OPEN: - case PKT__PKT_OPEN_ANCHOR: - case PKT__PKT_OPEN_COMMIT_SIG: - case PKT__PKT_OPEN_COMPLETE: - case PKT__PKT_CLOSE_SIGNATURE: - default: - return peer_received_unexpected_pkt(peer, pkt, __func__); - } - - if (err) - return peer_comms_err(peer, err); - - return true; -} - -static bool do_commit(struct peer *peer, struct command *jsoncmd) -{ - struct commit_info *ci; - const char *errmsg; - static const struct htlcs_table changes[] = { - { SENT_ADD_HTLC, SENT_ADD_COMMIT }, - { SENT_REMOVE_REVOCATION, SENT_REMOVE_ACK_COMMIT }, - { SENT_ADD_REVOCATION, SENT_ADD_ACK_COMMIT}, - { SENT_REMOVE_HTLC, SENT_REMOVE_COMMIT} - }; - static const struct feechanges_table feechanges[] = { - { SENT_FEECHANGE, SENT_FEECHANGE_COMMIT }, - { SENT_FEECHANGE_REVOCATION, SENT_FEECHANGE_ACK_COMMIT} - }; - bool to_us_only; - - /* We can have changes we suggested, or changes they suggested. */ - if (!peer_uncommitted_changes(peer)) { - log_debug(peer->log, "do_commit: no changes to commit"); - if (jsoncmd) - command_fail(jsoncmd, "no changes to commit"); - return true; - } - - log_debug(peer->log, "do_commit: sending commit command %"PRIu64, - peer->remote.commit->commit_num + 1); - - assert(state_can_commit(peer->state)); - assert(!peer->commit_jsoncmd); - - peer->commit_jsoncmd = jsoncmd; - ci = new_commit_info(peer, peer->remote.commit->commit_num + 1); - - assert(!peer->their_prev_revocation_hash); - peer->their_prev_revocation_hash - = tal_dup(peer, struct sha256, - &peer->remote.commit->revocation_hash); - - db_start_transaction(peer); - - errmsg = changestates(peer, changes, ARRAY_SIZE(changes), - feechanges, ARRAY_SIZE(feechanges), true); - if (errmsg) { - log_broken(peer->log, "queue_pkt_commit: %s", errmsg); - goto database_error; - } - - /* Create new commit info for this commit tx. */ - ci->revocation_hash = peer->remote.next_revocation_hash; - /* FIXME-OLD #2: - * - * ...a sending node MUST apply all remote acked and unacked - * changes except unacked fee changes to the remote commitment - * before generating `sig`. */ - ci->cstate = copy_cstate(ci, peer->remote.staging_cstate); - ci->tx = create_commit_tx(ci, peer, &ci->revocation_hash, - ci->cstate, REMOTE, &to_us_only); - bitcoin_txid(ci->tx, &ci->txid); - - if (!to_us_only) { - log_debug(peer->log, "Signing tx %"PRIu64, ci->commit_num); - log_add_struct(peer->log, " for %s", - struct channel_state, ci->cstate); - log_add_struct(peer->log, " (txid %s)", - struct sha256_double, &ci->txid); - - ci->sig = tal(ci, secp256k1_ecdsa_signature); - peer_sign_theircommit(peer, ci->tx, ci->sig); - } - - /* Switch to the new commitment. */ - tal_free(peer->remote.commit); - peer->remote.commit = ci; - peer->remote.commit->order = peer->order_counter++; - db_new_commit_info(peer, REMOTE, peer->their_prev_revocation_hash); - - /* We don't need to remember their commit if we don't give sig. */ - if (ci->sig) - peer_add_their_commit(peer, &ci->txid, ci->commit_num); - - if (peer->state == STATE_SHUTDOWN) { - set_peer_state(peer, STATE_SHUTDOWN_COMMITTING, __func__, true); - } else { - assert(peer->state == STATE_NORMAL); - set_peer_state(peer, STATE_NORMAL_COMMITTING, __func__, true); - } - if (db_commit_transaction(peer) != NULL) - goto database_error; - - queue_pkt_commit(peer, ci->sig); - return true; - -database_error: - db_abort_transaction(peer); - peer_fail(peer, __func__); - return false; -} - -static bool peer_start_shutdown(struct peer *peer) -{ - enum state newstate; - u8 *redeemscript; - - /* We might have uncommited changes; if so, commit them now. */ - if (!do_commit(peer, NULL)) - return false; - - db_start_transaction(peer); - - db_begin_shutdown(peer); - - /* If they started close, we might not have sent ours. */ - assert(!peer->closing.our_script); - - redeemscript = bitcoin_redeem_single(peer, &peer->local.finalkey); - - peer->closing.our_script = scriptpubkey_p2sh(peer, redeemscript); - tal_free(redeemscript); - - /* FIXME-OLD #2: - * - * A node SHOULD send a `close_shutdown` (if it has - * not already) after receiving `close_shutdown`. - */ - peer->closing.shutdown_order = peer->order_counter++; - db_set_our_closing_script(peer); - - queue_pkt_close_shutdown(peer); - - if (peer->state == STATE_NORMAL_COMMITTING) { - newstate = STATE_SHUTDOWN_COMMITTING; - } else { - newstate = STATE_SHUTDOWN; - } - set_peer_state(peer, newstate, __func__, true); - - /* Catch case where we've exchanged and had no HTLCs anyway. */ - if (peer->closing.their_script && !committed_to_htlcs(peer)) - start_closing_in_transaction(peer); - - return db_commit_transaction(peer) == NULL; -} - -/* Shim to handle the new packet format until we complete the - * switch. Handing the protobuf in anyway to fall back on protobuf - * based error handling. */ -static bool nested_pkt_in(struct peer *peer, const u32 type, - const u8 *innerpkt, size_t innerpktlen, - const Pkt *pkt) -{ - switch (type) { - case WIRE_CHANNEL_ANNOUNCEMENT: - handle_channel_announcement(peer->dstate->rstate, innerpkt, innerpktlen); - break; - case WIRE_CHANNEL_UPDATE: - handle_channel_update(peer->dstate->rstate, innerpkt, innerpktlen); - break; - case WIRE_NODE_ANNOUNCEMENT: - handle_node_announcement(peer->dstate->rstate, innerpkt, innerpktlen); - break; - default: - /* BOLT01: Unknown even typed packets MUST kill the - connection, unknown odd-typed packets MAY be ignored. */ - if (type % 2 == 0){ - return peer_received_unexpected_pkt(peer, pkt, __func__); - } else { - log_debug(peer->log, "Ignoring odd typed (%d) unknown packet.", type); - return true; - } - } - return true; -} - -/* This is the io loop while we're in normal mode. */ -static bool normal_pkt_in(struct peer *peer, const Pkt *pkt) -{ - Pkt *err = NULL; - - assert(peer->state == STATE_NORMAL - || peer->state == STATE_NORMAL_COMMITTING); - - switch (pkt->pkt_case) { - case PKT__PKT_UPDATE_ADD_HTLC: - err = handle_pkt_htlc_add(peer, pkt); - break; - - case PKT__PKT_UPDATE_FULFILL_HTLC: - err = handle_pkt_htlc_fulfill(peer, pkt); - break; - - case PKT__PKT_UPDATE_FAIL_HTLC: - err = handle_pkt_htlc_fail(peer, pkt); - break; - - case PKT__PKT_UPDATE_FEE: - err = handle_pkt_feechange(peer, pkt); - break; - - case PKT__PKT_UPDATE_COMMIT: - err = handle_pkt_commit(peer, pkt); - break; - - case PKT__PKT_CLOSE_SHUTDOWN: - err = accept_pkt_close_shutdown(peer, pkt); - if (err) - break; - if (!peer_start_shutdown(peer)) { - err = pkt_err(peer, "database error"); - break; - } - return true; - - case PKT__PKT_UPDATE_REVOCATION: - if (peer->state == STATE_NORMAL_COMMITTING) { - err = handle_pkt_revocation(peer, pkt, STATE_NORMAL); - if (!err) - peer_update_complete(peer); - break; - } - /* Fall thru. */ - default: - return peer_received_unexpected_pkt(peer, pkt, __func__); - } - - if (err) { - return peer_comms_err(peer, err); - } - - return true; -} - -/* Create a HTLC fulfill transaction for onchain.tx[out_num]. */ -static const struct bitcoin_tx *htlc_fulfill_tx(const struct peer *peer, - unsigned int out_num) -{ - struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); - const struct htlc *htlc = peer->onchain.htlcs[out_num]; - const u8 *wscript = peer->onchain.wscripts[out_num]; - secp256k1_ecdsa_signature sig; - u64 fee, satoshis; - - assert(htlc->r); - - tx->input[0].index = out_num; - tx->input[0].txid = peer->onchain.txid; - satoshis = htlc->msatoshi / 1000; - tx->input[0].amount = tal_dup(tx->input, u64, &satoshis); - tx->input[0].sequence_number = bitcoin_nsequence(&peer->remote.locktime); - - /* Using a new output address here would be useless: they can tell - * it's their HTLC, and that we collected it via rval. */ - tx->output[0].script = scriptpubkey_p2sh(tx, - bitcoin_redeem_single(tx, - &peer->local.finalkey)); - - log_debug(peer->log, "Pre-witness txlen = %zu\n", - measure_tx_cost(tx) / 4); - - assert(measure_tx_cost(tx) == 83 * 4); - - /* Witness length can vary, due to DER encoding of sigs, but we - * use 539 from an example run. */ - fee = fee_by_feerate(83 + 539 / 4, get_feerate(peer->dstate->topology)); - - /* FIXME: Fail gracefully in these cases (not worth collecting) */ - if (fee > satoshis || is_dust(satoshis - fee)) - fatal("HTLC fulfill amount of %"PRIu64" won't cover fee %"PRIu64, - satoshis, fee); - - tx->output[0].amount = satoshis - fee; - - peer_sign_htlc_fulfill(peer, tx, wscript, &sig); - - tx->input[0].witness = bitcoin_witness_htlc(tx, - htlc->r, &sig, wscript); - - log_debug(peer->log, "tx cost for htlc fulfill tx: %zu", - measure_tx_cost(tx)); - - return tx; -} - -static bool command_htlc_set_fail(struct peer *peer, struct htlc *htlc, - enum fail_error error_code, const char *why) -{ - const u8 *fail = failinfo_create(htlc, - &peer->dstate->id, error_code, why); - - set_htlc_fail(peer, htlc, fail, tal_count(fail)); - tal_free(fail); - return command_htlc_fail(peer, htlc); -} - -static bool command_htlc_fail(struct peer *peer, struct htlc *htlc) -{ - /* If onchain, nothing we can do. */ - if (!state_can_remove_htlc(peer->state)) - return false; - - /* FIXME-OLD #2: - * - * The sending node MUST add the HTLC fulfill/fail to the - * unacked changeset for its remote commitment - */ - cstate_fail_htlc(peer->remote.staging_cstate, htlc); - - htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC, false); - - remote_changes_pending(peer); - - queue_pkt_htlc_fail(peer, htlc); - return true; -} - -/* FIXME-OLD #onchain: - * - * If the node receives... a redemption preimage for an unresolved *commitment - * tx* output it was offered, it MUST *resolve* the output by spending it using - * the preimage. - */ -static bool fulfill_onchain(struct peer *peer, struct htlc *htlc) -{ - size_t i; - - for (i = 0; i < tal_count(peer->onchain.htlcs); i++) { - if (peer->onchain.htlcs[i] == htlc) { - /* Already irrevocably resolved? */ - if (peer->onchain.resolved[i]) - return false; - peer->onchain.resolved[i] - = htlc_fulfill_tx(peer, i); - broadcast_tx(peer->dstate->topology, - peer, peer->onchain.resolved[i], NULL); - return true; - } - } - fatal("Unknown HTLC to fulfill onchain"); -} - -static bool command_htlc_fulfill(struct peer *peer, struct htlc *htlc) -{ - if (peer->state == STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL - || peer->state == STATE_CLOSE_ONCHAIN_OUR_UNILATERAL) { - return fulfill_onchain(peer, htlc); - } - - if (!state_can_remove_htlc(peer->state)) - return false; - - /* FIXME-OLD #2: - * - * The sending node MUST add the HTLC fulfill/fail to the - * unacked changeset for its remote commitment - */ - cstate_fulfill_htlc(peer->remote.staging_cstate, htlc); - - htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC, false); - - remote_changes_pending(peer); - - queue_pkt_htlc_fulfill(peer, htlc); - return true; -} - -const char *command_htlc_add(struct peer *peer, u64 msatoshi, - unsigned int expiry, - const struct sha256 *rhash, - struct htlc *src, - const u8 *route, - u32 *error_code, - struct htlc **htlc) -{ - struct abs_locktime locktime; - - if (!blocks_to_abs_locktime(expiry, &locktime)) { - log_unusual(peer->log, "add_htlc: fail: bad expiry %u", expiry); - *error_code = BAD_REQUEST_400; - return "bad expiry"; - } - - if (expiry < get_block_height(peer->dstate->topology) + peer->dstate->config.min_htlc_expiry) { - log_unusual(peer->log, "add_htlc: fail: expiry %u is too soon", - expiry); - *error_code = BAD_REQUEST_400; - return "expiry too soon"; - } - - if (expiry > get_block_height(peer->dstate->topology) + peer->dstate->config.max_htlc_expiry) { - log_unusual(peer->log, "add_htlc: fail: expiry %u is too far", - expiry); - *error_code = BAD_REQUEST_400; - return "expiry too far"; - } - - /* FIXME-OLD #2: - * - * A node MUST NOT add a HTLC if it would result in it - * offering more than 300 HTLCs in the remote commitment transaction. - */ - if (peer->remote.staging_cstate->side[LOCAL].num_htlcs == 300) { - log_unusual(peer->log, "add_htlc: fail: already at limit"); - *error_code = SERVICE_UNAVAILABLE_503; - return "channel full"; - } - - if (!state_can_add_htlc(peer->state)) { - log_unusual(peer->log, "add_htlc: fail: peer state %s", - state_name(peer->state)); - *error_code = NOT_FOUND_404; - return "peer not available"; - } - - *htlc = peer_new_htlc(peer, peer->htlc_id_counter, - msatoshi, rhash, expiry, route, tal_count(route), - src, SENT_ADD_HTLC); - - /* FIXME-OLD #2: - * - * The sending node MUST add the HTLC addition to the unacked - * changeset for its remote commitment - */ - if (!cstate_add_htlc(peer->remote.staging_cstate, *htlc, true)) { - /* FIXME-OLD #2: - * - * A node MUST NOT offer `amount_msat` it cannot pay for in - * the remote commitment transaction at the current `fee_rate` - */ - log_unusual(peer->log, "add_htlc: fail: Cannot afford %"PRIu64 - " milli-satoshis in their commit tx", - msatoshi); - log_add_struct(peer->log, " channel state %s", - struct channel_state, - peer->remote.staging_cstate); - *htlc = tal_free(*htlc); - *error_code = SERVICE_UNAVAILABLE_503; - return "cannot afford htlc"; - } - - remote_changes_pending(peer); - - queue_pkt_htlc_add(peer, *htlc); - - /* Make sure we never offer the same one twice. */ - peer->htlc_id_counter++; - - return NULL; -} - -static struct io_plan *pkt_out(struct io_conn *conn, struct peer *peer) -{ - Pkt *out; - size_t n = tal_count(peer->outpkt); - - if (n == 0) { - /* We close the connection once we've sent everything. */ - if (!state_can_io(peer->state)) { - log_debug(peer->log, "pkt_out: no IO possible, closing"); - return io_close(conn); - } - return io_out_wait(conn, peer, pkt_out, peer); - } - - if (peer->fake_close || !peer->output_enabled) - return io_out_wait(conn, peer, pkt_out, peer); - - out = peer->outpkt[0]; - memmove(peer->outpkt, peer->outpkt + 1, (sizeof(*peer->outpkt)*(n-1))); - tal_resize(&peer->outpkt, n-1); - log_debug(peer->log, "pkt_out: writing %s", pkt_name(out->pkt_case)); - return peer_write_packet(conn, peer, out, pkt_out); -} - -static void clear_output_queue(struct peer *peer) -{ - size_t i, n = tal_count(peer->outpkt); - for (i = 0; i < n; i++) - tal_free(peer->outpkt[i]); - tal_resize(&peer->outpkt, 0); -} - -static struct io_plan *pkt_in(struct io_conn *conn, struct peer *peer) -{ - bool keep_going = true; - - /* We ignore packets if they tell us to, or we're closing already */ - if (peer->fake_close || !state_can_io(peer->state)) - keep_going = true; - - /* Sidestep the state machine for nested packets */ - else if (peer->inpkt->pkt_case == PKT__PKT_NESTED) - keep_going = nested_pkt_in(peer, peer->inpkt->nested->type, - peer->inpkt->nested->inner_pkt.data, - peer->inpkt->nested->inner_pkt.len, - peer->inpkt); - else if (state_is_normal(peer->state)) - keep_going = normal_pkt_in(peer, peer->inpkt); - else if (state_is_shutdown(peer->state)) - keep_going = shutdown_pkt_in(peer, peer->inpkt); - else if (peer->state == STATE_MUTUAL_CLOSING) - keep_going = closing_pkt_in(peer, peer->inpkt); - else if (peer->state == STATE_OPEN_WAIT_FOR_OPENPKT) - keep_going = open_pkt_in(peer, peer->inpkt); - else if (peer->state == STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT) - keep_going = open_ouranchor_pkt_in(peer, peer->inpkt); - else if (peer->state == STATE_OPEN_WAIT_FOR_ANCHORPKT) - keep_going = open_theiranchor_pkt_in(peer, peer->inpkt); - else if (state_is_openwait(peer->state)) - keep_going = open_wait_pkt_in(peer, peer->inpkt); - else { - log_unusual(peer->log, - "Unexpected state %s", state_name(peer->state)); - keep_going = false; - } - - peer->inpkt = tal_free(peer->inpkt); - if (keep_going) - return peer_read_packet(conn, peer, pkt_in); - else - return peer_close(conn, peer); -} - -/* - * This only works because we send one update at a time, and they can't - * ask for it again if they've already sent the `update_revocation` acking it. - */ -static void retransmit_updates(struct peer *peer) -{ - struct htlc_map_iter it; - struct htlc *h; - - /* FIXME-OLD #2: - * - * A node MAY simply retransmit messages which are identical to the - * previous transmission. */ - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - switch (h->state) { - case SENT_ADD_COMMIT: - log_debug(peer->log, "Retransmitting add HTLC %"PRIu64, - h->id); - queue_pkt_htlc_add(peer, h); - break; - case SENT_REMOVE_COMMIT: - log_debug(peer->log, "Retransmitting %s HTLC %"PRIu64, - h->r ? "fulfill" : "fail", h->id); - if (h->r) - queue_pkt_htlc_fulfill(peer, h); - else - queue_pkt_htlc_fail(peer, h); - break; - default: - break; - } - } - - assert(!peer->feechanges[SENT_FEECHANGE]); -} - -/* FIXME-OLD #2: - * - * On disconnection, a node MUST reverse any uncommitted changes sent by the - * other side (ie. `update_add_htlc`, `update_fee`, `update_fail_htlc` and - * `update_fulfill_htlc` for which no `update_commit` has been received). A - * node SHOULD retain the `r` value from the `update_fulfill_htlc`, however. -*/ -static void forget_uncommitted_changes(struct peer *peer) -{ - struct htlc *h; - struct htlc_map_iter it; - bool retry; - - if (!peer->remote.commit || !peer->remote.commit->cstate) - return; - - log_debug(peer->log, "Forgetting uncommitted"); - log_debug_struct(peer->log, "LOCAL: changing from %s", - struct channel_state, peer->local.staging_cstate); - log_add_struct(peer->log, " to %s", - struct channel_state, peer->local.commit->cstate); - log_debug_struct(peer->log, "REMOTE: changing from %s", - struct channel_state, peer->remote.staging_cstate); - log_add_struct(peer->log, " to %s", - struct channel_state, peer->remote.commit->cstate); - - tal_free(peer->local.staging_cstate); - tal_free(peer->remote.staging_cstate); - peer->local.staging_cstate - = copy_cstate(peer, peer->local.commit->cstate); - peer->remote.staging_cstate - = copy_cstate(peer, peer->remote.commit->cstate); - - /* We forget everything we're routing, and re-send. This - * works for the reload-from-database case as well as the - * normal reconnect. */ -again: - retry = false; - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - switch (h->state) { - case SENT_ADD_HTLC: - /* Adjust counter to lowest HTLC removed */ - if (peer->htlc_id_counter > h->id) { - log_debug(peer->log, - "Lowering htlc_id_counter to %"PRIu64, - h->id); - peer->htlc_id_counter = h->id; - } - /* Fall thru */ - case RCVD_ADD_HTLC: - log_debug(peer->log, "Forgetting %s %"PRIu64, - htlc_state_name(h->state), h->id); - /* May miss some due to delete reorg. */ - tal_free(h); - retry = true; - break; - case RCVD_REMOVE_HTLC: - log_debug(peer->log, "Undoing %s %"PRIu64, - htlc_state_name(h->state), h->id); - htlc_undostate(h, RCVD_REMOVE_HTLC, - SENT_ADD_ACK_REVOCATION); - break; - case SENT_REMOVE_HTLC: - log_debug(peer->log, "Undoing %s %"PRIu64, - htlc_state_name(h->state), h->id); - htlc_undostate(h, SENT_REMOVE_HTLC, - RCVD_ADD_ACK_REVOCATION); - break; - default: - break; - } - } - if (retry) - goto again; - - /* Forget uncommitted feechanges */ - peer->feechanges[SENT_FEECHANGE] - = tal_free(peer->feechanges[SENT_FEECHANGE]); - peer->feechanges[RCVD_FEECHANGE] - = tal_free(peer->feechanges[RCVD_FEECHANGE]); - - /* Make sure our HTLC counter is correct. */ - if (peer->htlc_id_counter != 0) - assert(htlc_get(&peer->htlcs, peer->htlc_id_counter-1, LOCAL)); - assert(!htlc_get(&peer->htlcs, peer->htlc_id_counter, LOCAL)); -} - -static void retransmit_pkts(struct peer *peer, s64 ack) -{ - log_debug(peer->log, "Our order counter is %"PRIi64", their ack %"PRIi64, - peer->order_counter, ack); - - if (ack > peer->order_counter) { - log_unusual(peer->log, "reconnect ack %"PRIi64" > %"PRIi64, - ack, peer->order_counter); - peer_comms_err(peer, pkt_err(peer, "invalid ack")); - return; - } - - log_debug(peer->log, "They acked %"PRIi64", remote=%"PRIi64" local=%"PRIi64, - ack, peer->remote.commit ? peer->remote.commit->order : -2, - peer->local.commit ? peer->local.commit->order : -2); - - /* FIXME-OLD #2: - * - * A node MAY assume that only one of each type of message need be - * retransmitted. A node SHOULD retransmit the last of each message - * type which was not counted by the `ack` field. - */ - while (ack < peer->order_counter) { - if (ack == 0) { - queue_pkt_open(peer, peer->local.offer_anchor); - } else if (ack == 1) { - queue_pkt_open_commit_sig(peer); - } else if (peer->remote.commit - && ack == peer->remote.commit->order) { - /* FIXME-OLD #2: - * - * Before retransmitting `update_commit`, the node - * MUST send appropriate `update_add_htlc`, - * `update_fee`, `update_fail_htlc` or - * `update_fulfill_htlc` messages (the other node will - * have forgotten them, as required above). - */ - retransmit_updates(peer); - queue_pkt_commit(peer, peer->remote.commit->sig); - } else if (peer->local.commit - && ack == peer->local.commit->order) { - /* Re-transmit revocation. */ - struct sha256 preimage, next; - u64 commit_num = peer->local.commit->commit_num - 1; - - /* Make sure we don't revoke current commit! */ - assert(commit_num < peer->local.commit->commit_num); - peer_get_revocation_preimage(peer, commit_num,&preimage); - peer_get_revocation_hash(peer, commit_num + 2, &next); - log_debug(peer->log, "Re-sending revocation hash %"PRIu64, - commit_num + 2); - log_add_struct(peer->log, "value %s", struct sha256, - &next); - log_add_struct(peer->log, "local.next=%s", struct sha256, - &peer->local.next_revocation_hash); - log_debug(peer->log, "Re-sending revocation %"PRIu64, - commit_num); - queue_pkt_revocation(peer, &preimage, &next); - } else if (ack == peer->closing.shutdown_order) { - log_debug(peer->log, "Re-sending shutdown"); - queue_pkt_close_shutdown(peer); - } else if (ack == peer->closing.closing_order) { - log_debug(peer->log, "Re-sending closing order"); - queue_pkt_close_signature(peer); - } else { - log_broken(peer->log, "Can't rexmit %"PRIu64 - " when local commit %"PRIi64" and remote %"PRIi64, - ack, - peer->local.commit ? peer->local.commit->order : -2, - peer->remote.commit ? peer->remote.commit->order : -2); - peer_comms_err(peer, pkt_err(peer, "invalid ack")); - return; - } - ack++; - } - - /* We might need to update HTLCs which were from other peers. */ - retry_all_routing(peer); -} - -static u64 desired_commit_feerate(struct lightningd_state *dstate) -{ - return get_feerate(dstate->topology) * dstate->config.commitment_fee_percent / 100; -} - -static bool want_feechange(const struct peer *peer) -{ - if (!state_is_normal(peer->state) && !state_is_shutdown(peer->state)) - return false; - log_debug(peer->log, "Current fee_rate: %"PRIu64" want %"PRIu64, - peer->local.staging_cstate->fee_rate, - desired_commit_feerate(peer->dstate)); - /* FIXME: Send fee changes when we want it */ - return false; -} - -static void peer_has_connected(struct peer *peer) -{ - assert(!peer->connected); - peer->connected = true; - - /* Do we want to send something? */ - if (peer_uncommitted_changes(peer) || want_feechange(peer)) { - log_debug(peer->log, "connected: changes pending"); - remote_changes_pending(peer); - } -} - -static struct io_plan *init_pkt_in(struct io_conn *conn, struct peer *peer) -{ - if (peer->inpkt->pkt_case != PKT__PKT_INIT) { - peer_received_unexpected_pkt(peer, peer->inpkt, __func__); - goto fail; - } - - /* They might have missed the error, tell them before hanging up */ - if (state_is_error(peer->state)) { - queue_pkt_err(peer, pkt_err(peer, "In error state %s", - state_name(peer->state))); - goto fail; - } - - /* We might have had an onchain event while handshaking! */ - if (!state_can_io(peer->state)) - goto fail; - - if (peer->inpkt->init->has_features) { - size_t i; - - /* FIXME-OLD #2: - * - * The receiving node SHOULD ignore any odd feature bits it - * does not support, and MUST fail the connection if any - * unsupported even `features` bit is set. */ - for (i = 0; i < peer->inpkt->init->features.len*CHAR_BIT; i++) { - size_t byte = i / CHAR_BIT, bit = i % CHAR_BIT; - if (peer->inpkt->init->features.data[byte] & (1<log, - "They offered feature %zu", i); - continue; - } - queue_pkt_err(peer, - pkt_err(peer, - "Unsupported feature %zu", - i)); - goto fail; - } - } - } - - /* Send any packets they missed. */ - retransmit_pkts(peer, peer->inpkt->init->ack); - - /* We let the conversation go this far in case they missed the - * close packets. But now we can close if we're done. */ - if (!state_can_io(peer->state)) { - log_debug(peer->log, "State %s, closing immediately", - state_name(peer->state)); - goto fail; - } - - /* Back into normal mode. */ - peer->inpkt = tal_free(peer->inpkt); - - peer_has_connected(peer); - - if (state_is_normal(peer->state)){ - announce_channel(peer->dstate, peer); - sync_routing_table(peer->dstate, peer); - } - - return io_duplex(conn, - peer_read_packet(conn, peer, pkt_in), - pkt_out(conn, peer)); - -fail: - /* We always free inpkt; they may yet reconnect. */ - peer->inpkt = tal_free(peer->inpkt); - return pkt_out(conn, peer); -} - -static struct io_plan *read_init_pkt(struct io_conn *conn, - struct peer *peer) -{ - return peer_read_packet(conn, peer, init_pkt_in); -} - -static u64 peer_commitsigs_received(struct peer *peer) -{ - return peer->their_commitsigs; -} - -static u64 peer_revocations_received(struct peer *peer) -{ - /* How many preimages we've received. */ - return -peer->their_preimages.min_index; -} - -static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer) -{ - u64 open, sigs, revokes, shutdown, closing; - - open = (peer->state == STATE_OPEN_WAIT_FOR_OPENPKT ? 0 : 1); - sigs = peer_commitsigs_received(peer); - revokes = peer_revocations_received(peer); - shutdown = peer->closing.their_script ? 1 : 0; - closing = peer->closing.sigs_in; - log_debug(peer->log, - "Init with ack %"PRIu64" opens + %"PRIu64" sigs + %" - PRIu64" revokes + %"PRIu64" shutdown + %"PRIu64" closing", - open, sigs, revokes, shutdown, closing); - - /* FIXME-OLD #2: - * - * A node MUST send an `init` message immediately immediately after - * it has validated the `authenticate` message. A node MUST set - * the `ack` field in the `init` message to the the sum of - * previously-processed messages of types `open`, `open_commit_sig`, - * `update_commit`, `update_revocation`, `close_shutdown` and - * `close_signature`. */ - return peer_write_packet(conn, peer, - pkt_init(peer, open + sigs + revokes - + shutdown + closing), - read_init_pkt); -} - -/* Crypto is on, we are live. */ -static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer) -{ - peer_secrets_init(peer); - - peer_get_revocation_hash(peer, 0, &peer->local.next_revocation_hash); - - assert(peer->state == STATE_INIT); - - /* Counter is 1 for sending pkt_open: we'll do it in retransmit_pkts */ - peer->order_counter++; - - db_start_transaction(peer); - set_peer_state(peer, STATE_OPEN_WAIT_FOR_OPENPKT, __func__, true); - - /* FIXME: Start timeout, and close peer if they don't progress! */ - db_create_peer(peer); - if (db_commit_transaction(peer) != NULL) { - peer_database_err(peer); - return peer_close(conn, peer); - } - - /* Set up out commit info now: rest gets done in setup_first_commit - * once anchor is established. */ - peer->local.commit = new_commit_info(peer, 0); - peer->local.commit->revocation_hash = peer->local.next_revocation_hash; - peer_get_revocation_hash(peer, 1, &peer->local.next_revocation_hash); - - return peer_send_init(conn,peer); -} - -static void destroy_peer(struct peer *peer) -{ - if (peer->conn) - io_close(peer->conn); - list_del_from(&peer->dstate->peers, &peer->list); -} - -static void try_reconnect(struct peer *peer); - -static void peer_disconnect(struct io_conn *conn, struct peer *peer) -{ - log_info(peer->log, "Disconnected"); - - /* No longer connected. */ - peer->conn = NULL; - peer->connected = false; - - /* Not even set up yet? Simply free.*/ - if (peer->state == STATE_INIT) { - /* This means we didn't get past crypto handshake or hit db */ - tal_free(peer); - return; - } - - /* Completely dead? Free it now. */ - if (peer->state == STATE_CLOSED) { - io_break(peer); - return; - } - - /* This is an unexpected close. */ - if (state_can_io(peer->state)) { - forget_uncommitted_changes(peer); - try_reconnect(peer); - } -} - -static void try_commit(struct peer *peer) -{ - peer->commit_timer = NULL; - - if (!peer->connected) { - log_debug(peer->log, "try_commit: state=%s, not connected", - state_name(peer->state)); - return; - } - - if (state_can_commit(peer->state)) - do_commit(peer, NULL); - else { - /* FIXME: try again when we receive revocation / - * reconnect, rather than using timer! */ - log_debug(peer->log, "try_commit: state=%s, re-queueing timer", - state_name(peer->state)); - - remote_changes_pending(peer); - } -} - -struct commit_info *new_commit_info(const tal_t *ctx, u64 commit_num) -{ - struct commit_info *ci = tal(ctx, struct commit_info); - ci->commit_num = commit_num; - ci->tx = NULL; - ci->cstate = NULL; - ci->sig = NULL; - ci->order = (s64)-1LL; - return ci; -} - -static bool peer_reconnected(struct peer *peer, - struct io_conn *conn, - int addr_type, int addr_protocol, - struct io_data *iod, - const struct pubkey *id, - bool we_connected) -{ - char *name; - struct netaddr addr; - - assert(structeq(peer->id, id)); - - peer->io_data = tal_steal(peer, iod); - - /* FIXME: Attach IO logging for this peer. */ - if (!netaddr_from_fd(io_conn_fd(conn), addr_type, addr_protocol, &addr)) - return false; - - /* If we free peer, conn should be closed, but can't be freed - * immediately so don't make peer a parent. */ - peer->conn = conn; - io_set_finish(conn, peer_disconnect, peer); - - name = netaddr_name(peer, &addr); - log_info(peer->log, "Reconnected %s %s", - we_connected ? "out to" : "in from", name); - tal_free(name); - - return true; -} - -struct peer *new_peer(struct lightningd_state *dstate, - struct log *log, - enum state state, - bool offer_anchor) -{ - struct peer *peer = tal(dstate, struct peer); - - peer->state = state; - peer->connected = false; - peer->id = NULL; - peer->dstate = dstate; - peer->io_data = NULL; - peer->secrets = NULL; - list_head_init(&peer->watches); - peer->inpkt = NULL; - peer->outpkt = tal_arr(peer, Pkt *, 0); - peer->open_jsoncmd = NULL; - peer->commit_jsoncmd = NULL; - list_head_init(&peer->their_commits); - peer->anchor.ok_depth = -1; - peer->order_counter = 0; - peer->their_commitsigs = 0; - peer->cur_commit.watch = NULL; - peer->closing.their_sig = NULL; - peer->closing.our_script = NULL; - peer->closing.their_script = NULL; - peer->closing.shutdown_order = (s64)-1LL; - peer->closing.closing_order = (s64)-1LL; - peer->closing.sigs_in = 0; - peer->onchain.tx = NULL; - peer->onchain.resolved = NULL; - peer->onchain.htlcs = NULL; - peer->onchain.wscripts = NULL; - peer->commit_timer = NULL; - peer->nc = NULL; - peer->their_prev_revocation_hash = NULL; - peer->conn = NULL; - peer->fake_close = false; - peer->output_enabled = true; - peer->local.offer_anchor = offer_anchor; - peer->broadcast_index = 0; - if (!blocks_to_rel_locktime(dstate->config.locktime_blocks, - &peer->local.locktime)) - fatal("Could not convert locktime_blocks"); - peer->local.mindepth = dstate->config.anchor_confirms; - peer->local.commit = peer->remote.commit = NULL; - peer->local.staging_cstate = peer->remote.staging_cstate = NULL; - peer->log = tal_steal(peer, log); - log_debug(peer->log, "New peer %p", peer); - - htlc_map_init(&peer->htlcs); - memset(peer->feechanges, 0, sizeof(peer->feechanges)); - shachain_init(&peer->their_preimages); - - list_add(&dstate->peers, &peer->list); - tal_add_destructor(peer, destroy_peer); - return peer; -} - -static struct peer_address *find_address(struct lightningd_state *dstate, - const struct pubkey *id) -{ - struct peer_address *i; - - list_for_each(&dstate->addresses, i, list) { - if (structeq(&id->pubkey, &i->id.pubkey)) - return i; - } - return NULL; -} - -static bool add_peer_address(struct lightningd_state *dstate, - const struct pubkey *id, - const struct netaddr *addr) -{ - struct peer_address *a = find_address(dstate, id); - if (a) { - a->addr = *addr; - } else { - a = tal(dstate, struct peer_address); - a->addr = *addr; - a->id = *id; - list_add_tail(&dstate->addresses, &a->list); - } - return db_add_peer_address(dstate, a); -} - -static bool peer_first_connected(struct peer *peer, - struct io_conn *conn, - int addr_type, int addr_protocol, - struct io_data *iod, - const struct pubkey *id, - bool we_connected) -{ - char *name, *idstr; - struct netaddr addr; - - peer->io_data = tal_steal(peer, iod); - peer->id = tal_dup(peer, struct pubkey, id); - peer->local.commit_fee_rate = desired_commit_feerate(peer->dstate); - - peer->htlc_id_counter = 0; - - /* If we free peer, conn should be closed, but can't be freed - * immediately so don't make peer a parent. */ - peer->conn = conn; - io_set_finish(conn, peer_disconnect, peer); - - peer->anchor.min_depth = get_block_height(peer->dstate->topology); - - /* FIXME: Attach IO logging for this peer. */ - if (!netaddr_from_fd(io_conn_fd(conn), addr_type, addr_protocol, &addr)) - return false; - - /* Save/update address if we connected to them. */ - if (we_connected && !add_peer_address(peer->dstate, peer->id, &addr)) - return false; - - name = netaddr_name(peer, &addr); - idstr = pubkey_to_hexstr(name, peer->id); - log_info(peer->log, "Connected %s %s id %s, changing prefix", - we_connected ? "out to" : "in from", name, idstr); - set_log_prefix(peer->log, tal_fmt(name, "%s:", idstr)); - tal_free(name); - - log_debug(peer->log, "Using fee rate %"PRIu64, - peer->local.commit_fee_rate); - return true; -} - -static void htlc_destroy(struct htlc *htlc) -{ - if (!htlc_map_del(&htlc->peer->htlcs, htlc)) - fatal("Could not find htlc to destroy"); -} - -struct htlc *peer_new_htlc(struct peer *peer, - u64 id, - u64 msatoshi, - const struct sha256 *rhash, - u32 expiry, - const u8 *route, - size_t routelen, - struct htlc *src, - enum htlc_state state) -{ - struct htlc *h = tal(peer, struct htlc); - h->peer = peer; - h->state = state; - h->id = id; - h->msatoshi = msatoshi; - h->rhash = *rhash; - h->r = NULL; - h->fail = NULL; - if (!blocks_to_abs_locktime(expiry, &h->expiry)) - fatal("Invalid HTLC expiry %u", expiry); - h->routing = tal_dup_arr(h, u8, route, routelen, 0); - h->src = src; - if (htlc_owner(h) == LOCAL) { - if (src) { - h->deadline = abs_locktime_to_blocks(&src->expiry) - - peer->dstate->config.deadline_blocks; - } else - /* If we're paying, give it a little longer. */ - h->deadline = expiry - + peer->dstate->config.min_htlc_expiry; - } else { - assert(htlc_owner(h) == REMOTE); - } - htlc_map_add(&peer->htlcs, h); - tal_add_destructor(h, htlc_destroy); - - return h; -} - -static struct io_plan *crypto_on_reconnect(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - const struct pubkey *id, - struct peer *peer, - bool we_connected) -{ - /* Setup peer->conn and peer->io_data */ - if (!peer_reconnected(peer, conn, SOCK_STREAM, IPPROTO_TCP, - iod, id, we_connected)) - return io_close(conn); - - /* We need to eliminate queue now. */ - clear_output_queue(peer); - - return peer_send_init(conn, peer); -} - -static struct io_plan *crypto_on_reconnect_in(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - struct peer *peer) -{ - assert(log == peer->log); - return crypto_on_reconnect(conn, dstate, iod, id, peer, false); -} - -static struct io_plan *crypto_on_reconnect_out(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - struct peer *peer) -{ - assert(log == peer->log); - return crypto_on_reconnect(conn, dstate, iod, id, peer, true); -} - -static struct io_plan *crypto_on_out(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - struct json_connecting *connect) -{ - struct peer *peer; - - if (find_peer(dstate, id)) { - command_fail(connect->cmd, "Already connected to peer %s", - pubkey_to_hexstr(connect->cmd, id)); - return io_close(conn); - } - - /* Initiator currently funds channel */ - peer = new_peer(dstate, log, STATE_INIT, true); - if (!peer_first_connected(peer, conn, SOCK_STREAM, IPPROTO_TCP, - iod, id, true)) { - command_fail(connect->cmd, "Failed to make peer for %s:%s", - connect->name, connect->port); - return io_close(conn); - } - peer->anchor.input = tal_steal(peer, connect->input); - peer->open_jsoncmd = connect->cmd; - return peer_crypto_on(conn, peer); -} - -static struct io_plan *peer_connected_out(struct io_conn *conn, - struct lightningd_state *dstate, - const struct netaddr *netaddr, - struct json_connecting *connect) -{ - struct log *l; - - l = new_log(conn, dstate->log_book, "OUT-%s:%s:", - connect->name, connect->port); - - log_debug_struct(l, "Connected out to %s", struct netaddr, netaddr); - return peer_crypto_setup(conn, dstate, NULL, l, crypto_on_out, connect); -} - -static struct io_plan *crypto_on_in(struct io_conn *conn, - struct lightningd_state *dstate, - struct io_data *iod, - struct log *log, - const struct pubkey *id, - void *unused) -{ - struct peer *peer; - - /* FIXME-OLD #2: - * - * A node MUST handle continuing a previous channel on a new encrypted - * transport. */ - peer = find_peer(dstate, id); - if (peer) { - /* Close any existing connection, without side effects. */ - if (peer->conn) { - log_debug(log, "This is reconnect for peer %p", peer); - log_debug(peer->log, "Reconnect: closing old conn %p for new conn %p", - peer->conn, conn); - io_set_finish(peer->conn, NULL, NULL); - io_close(peer->conn); - peer->conn = NULL; - peer->connected = false; - } - return crypto_on_reconnect_in(conn, dstate, iod, peer->log, id, - peer); - } - - /* Initiator currently funds channel */ - peer = new_peer(dstate, log, STATE_INIT, false); - if (!peer_first_connected(peer, conn, SOCK_STREAM, IPPROTO_TCP, - iod, id, false)) - return io_close(conn); - - return peer_crypto_on(conn, peer); -} - -static struct io_plan *peer_connected_in(struct io_conn *conn, - struct lightningd_state *dstate) -{ - struct netaddr addr; - struct log *l; - const char *name; - - if (!netaddr_from_fd(io_conn_fd(conn), SOCK_STREAM, IPPROTO_TCP, &addr)) - return false; - name = netaddr_name(conn, &addr); - l = new_log(conn, dstate->log_book, "IN-%s:", name); - - log_debug(l, "Connected in"); - - return peer_crypto_setup(conn, dstate, NULL, l, crypto_on_in, NULL); -} - -static int make_listen_fd(struct lightningd_state *dstate, - int domain, void *addr, socklen_t len) -{ - int fd = socket(domain, SOCK_STREAM, 0); - if (fd < 0) { - log_debug(dstate->base_log, "Failed to create %u socket: %s", - domain, strerror(errno)); - return -1; - } - - if (addr) { - int on = 1; - - /* Re-use, please.. */ - if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) - log_unusual(dstate->base_log, - "Failed setting socket reuse: %s", - strerror(errno)); - - if (bind(fd, addr, len) != 0) { - log_unusual(dstate->base_log, - "Failed to bind on %u socket: %s", - domain, strerror(errno)); - goto fail; - } - } - - if (listen(fd, 5) != 0) { - log_unusual(dstate->base_log, - "Failed to listen on %u socket: %s", - domain, strerror(errno)); - goto fail; - } - return fd; - -fail: - close_noerr(fd); - return -1; -} - -void setup_listeners(struct lightningd_state *dstate) -{ - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - socklen_t len; - int fd1, fd2; - - if (!dstate->portnum) - return; - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = INADDR_ANY; - addr.sin_port = htons(dstate->portnum); - - memset(&addr6, 0, sizeof(addr6)); - addr6.sin6_family = AF_INET6; - addr6.sin6_addr = in6addr_any; - addr6.sin6_port = htons(dstate->portnum); - - /* IPv6, since on Linux that (usually) binds to IPv4 too. */ - fd1 = make_listen_fd(dstate, AF_INET6, &addr6, sizeof(addr6)); - if (fd1 >= 0) { - struct sockaddr_in6 in6; - - len = sizeof(in6); - if (getsockname(fd1, (void *)&in6, &len) != 0) { - log_unusual(dstate->base_log, - "Failed get IPv6 sockname: %s", - strerror(errno)); - close_noerr(fd1); - } else { - addr.sin_port = in6.sin6_port; - assert(dstate->portnum == ntohs(addr.sin_port)); - log_debug(dstate->base_log, - "Creating IPv6 listener on port %u", - dstate->portnum); - io_new_listener(dstate, fd1, peer_connected_in, dstate); - } - } - - /* Just in case, aim for the same port... */ - fd2 = make_listen_fd(dstate, AF_INET, &addr, sizeof(addr)); - if (fd2 >= 0) { - len = sizeof(addr); - if (getsockname(fd2, (void *)&addr, &len) != 0) { - log_unusual(dstate->base_log, - "Failed get IPv4 sockname: %s", - strerror(errno)); - close_noerr(fd2); - } else { - assert(dstate->portnum == ntohs(addr.sin_port)); - log_debug(dstate->base_log, - "Creating IPv4 listener on port %u", - dstate->portnum); - io_new_listener(dstate, fd2, peer_connected_in, dstate); - } - } - - if (fd1 < 0 && fd2 < 0) - fatal("Could not bind to a network address"); -} - -static void peer_failed(struct lightningd_state *dstate, - struct json_connecting *connect) -{ - /* FIXME: Better diagnostics! */ - command_fail(connect->cmd, "Failed to connect to peer %s:%s", - connect->name, connect->port); -} - -static void json_connect(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct json_connecting *connect; - jsmntok_t *host, *port, *txtok; - struct bitcoin_tx *tx; - int output; - size_t txhexlen; - u64 fee; - const tal_t *tmpctx = tal_tmpctx(cmd); - - if (!json_get_params(buffer, params, - "host", &host, - "port", &port, - "tx", &txtok, - NULL)) { - command_fail(cmd, "Need host, port and tx to a wallet address"); - return; - } - - connect = tal(cmd, struct json_connecting); - connect->cmd = cmd; - connect->name = tal_strndup(connect, buffer + host->start, - host->end - host->start); - connect->port = tal_strndup(connect, buffer + port->start, - port->end - port->start); - connect->input = tal(connect, struct anchor_input); - - txhexlen = txtok->end - txtok->start; - tx = bitcoin_tx_from_hex(tmpctx, buffer + txtok->start, txhexlen); - if (!tx) { - command_fail(cmd, "'%.*s' is not a valid transaction", - txtok->end - txtok->start, - buffer + txtok->start); - return; - } - - bitcoin_txid(tx, &connect->input->txid); - - /* Find an output we know how to spend. */ - for (output = 0; output < tal_count(tx->output); output++) { - if (wallet_can_spend(cmd->dstate, &tx->output[output], - &connect->input->walletkey)) - break; - } - if (output == tal_count(tx->output)) { - command_fail(cmd, "Tx doesn't send to wallet address"); - return; - } - - connect->input->index = output; - connect->input->in_amount = tx->output[output].amount; - - /* FIXME: This is normal case, not exact. */ - fee = fee_by_feerate(94 + 1+73 + 1+33 + 1, get_feerate(cmd->dstate->topology)); - if (fee >= connect->input->in_amount) { - command_fail(cmd, "Amount %"PRIu64" below fee %"PRIu64, - connect->input->in_amount, fee); - return; - } - - connect->input->out_amount = connect->input->in_amount - fee; - if (anchor_too_large(connect->input->out_amount)) { - command_fail(cmd, "Amount %"PRIu64" is too large", - connect->input->out_amount); - return; - } - if (!dns_resolve_and_connect(cmd->dstate, connect->name, connect->port, - peer_connected_out, peer_failed, connect)) { - command_fail(cmd, "DNS failed"); - return; - } - - tal_free(tmpctx); -} - -static const struct json_command connect_command = { - "connect", - json_connect, - "Connect to a {host} at {port} using hex-encoded {tx} to fund", - "Returns the {id} on success (once channel established)" -}; -AUTODATA(json_command, &connect_command); - -/* Have any of our HTLCs passed their deadline? */ -static bool any_deadline_past(struct peer *peer) -{ - u32 height = get_block_height(peer->dstate->topology); - struct htlc_map_iter it; - struct htlc *h; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (htlc_is_dead(h)) - continue; - if (htlc_owner(h) != LOCAL) - continue; - if (height >= h->deadline) { - log_unusual_struct(peer->log, - "HTLC %s deadline has passed", - struct htlc, h); - return true; - } - } - return false; -} - -static void check_htlc_expiry(struct peer *peer) -{ - u32 height = get_block_height(peer->dstate->topology); - struct htlc_map_iter it; - struct htlc *h; - - /* Check their currently still-existing htlcs for expiry */ - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - assert(!abs_locktime_is_seconds(&h->expiry)); - - /* Only their consider HTLCs which are completely locked in. */ - if (h->state != RCVD_ADD_ACK_REVOCATION) - continue; - - /* We give it an extra block, to avoid the worst of the - * inter-node timing issues. */ - if (height <= abs_locktime_to_blocks(&h->expiry)) - continue; - - db_start_transaction(peer); - /* This can fail only if we're in an error state. */ - command_htlc_set_fail(peer, h, - REQUEST_TIMEOUT_408, "timed out"); - if (db_commit_transaction(peer) != NULL) { - peer_fail(peer, __func__); - return; - } - } - - /* FIXME-OLD #2: - * - * A node MUST NOT offer a HTLC after this deadline, and MUST - * fail the connection if an HTLC which it offered is in - * either node's current commitment transaction past this - * deadline. - */ - - /* To save logic elsewhere (ie. to avoid signing a new commit with a - * past-deadline HTLC) we also check staged HTLCs. - */ - if (!state_is_normal(peer->state)) - return; - - if (any_deadline_past(peer)) - peer_fail(peer, __func__); -} - -static void peer_depth_ok(struct peer *peer) -{ - queue_pkt_open_complete(peer); - - db_start_transaction(peer); - - switch (peer->state) { - case STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE: - set_peer_state(peer, STATE_OPEN_WAIT_THEIRCOMPLETE, - __func__, true); - break; - case STATE_OPEN_WAIT_ANCHORDEPTH: - peer_open_complete(peer, NULL); - set_peer_state(peer, STATE_NORMAL, __func__, true); - announce_channel(peer->dstate, peer); - sync_routing_table(peer->dstate, peer); - break; - default: - log_broken(peer->log, "%s: state %s", - __func__, state_name(peer->state)); - peer_fail(peer, __func__); - break; - } - - if (db_commit_transaction(peer)) - peer_database_err(peer); -} - -static enum watch_result anchor_depthchange(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - void *unused) -{ - log_debug(peer->log, "Anchor at depth %u", depth); - - /* Still waiting for it to reach depth? */ - if (state_is_waiting_for_anchor(peer->state)) { - log_debug(peer->log, "Waiting for depth %i", - peer->anchor.ok_depth); - /* We can see a run of blocks all at once, so may be > depth */ - if ((int)depth >= peer->anchor.ok_depth) { - peer_depth_ok(peer); - peer->anchor.ok_depth = -1; - } - } else if (depth == 0) - /* FIXME: Report losses! */ - fatal("Funding transaction was unspent!"); - - /* Since this gets called on every new block, check HTLCs here. */ - check_htlc_expiry(peer); - - /* If fee rate has changed, fire off update to change it. */ - if (want_feechange(peer) && state_can_commit(peer->state)) { - log_debug(peer->log, "fee rate changed to %"PRIu64, - desired_commit_feerate(peer->dstate)); - /* FIXME: If fee changes back before update, we screw - * up and send an empty commit. We need to generate a - * real packet here! */ - remote_changes_pending(peer); - } - - /* FIXME-OLD #2: - * - * A node MUST update bitcoin fees if it estimates that the - * current commitment transaction will not be processed in a - * timely manner (see "Risks With HTLC Timeouts"). - */ - /* Note: we don't do this when we're told to ignore fees. */ - /* FIXME: BOLT should say what to do if it can't! We drop conn. */ - if (!state_is_onchain(peer->state) && !state_is_error(peer->state) - && peer->dstate->config.commitment_fee_min_percent != 0 - && peer->local.commit->cstate->fee_rate < get_feerate(peer->dstate->topology)) { - log_broken(peer->log, "fee rate %"PRIu64" lower than %"PRIu64, - peer->local.commit->cstate->fee_rate, - get_feerate(peer->dstate->topology)); - peer_fail(peer, __func__); - } - - return KEEP_WATCHING; -} - -void notify_new_block(struct chain_topology *topo, unsigned int height) -{ - struct lightningd_state *dstate = tal_parent(topo); - /* This is where we check for anchor timeouts. */ - struct peer *peer; - - list_for_each(&dstate->peers, peer, list) { - if (!state_is_waiting_for_anchor(peer->state)) - continue; - - /* If we haven't seen anchor yet, we can timeout. */ - if (height >= peer->anchor.min_depth - + dstate->config.anchor_onchain_wait - + dstate->config.anchor_confirms) { - queue_pkt_err(peer, pkt_err(peer, "Funding timeout")); - set_peer_state(peer, STATE_ERR_ANCHOR_TIMEOUT, __func__, - false); - peer_breakdown(peer); - } - } -} - -static bool outputscript_eq(const struct bitcoin_tx_output *out, - size_t i, const u8 *script) -{ - if (tal_count(out[i].script) != tal_count(script)) - return false; - return memcmp(out[i].script, script, tal_count(script)) == 0; -} - -/* This tx is their commitment; - * fill in onchain.htlcs[], wscripts[], to_us_idx and to_them_idx */ -static bool map_onchain_outputs(struct peer *peer, - const struct sha256 *rhash, - const struct bitcoin_tx *tx, - enum side side, - unsigned int commit_num) -{ - u8 *to_us, *to_them, *to_them_wscript, *to_us_wscript; - struct htlc_output_map *hmap; - size_t i; - - peer->onchain.to_us_idx = peer->onchain.to_them_idx = -1; - peer->onchain.htlcs = tal_arr(tx, struct htlc *, tal_count(tx->output)); - peer->onchain.wscripts = tal_arr(tx, const u8 *, tal_count(tx->output)); - - to_us = commit_output_to_us(tx, peer, rhash, side, &to_us_wscript); - to_them = commit_output_to_them(tx, peer, rhash, side, - &to_them_wscript); - - /* Now generate the wscript hashes for every possible HTLC. */ - hmap = get_htlc_output_map(tx, peer, rhash, side, commit_num); - - for (i = 0; i < tal_count(tx->output); i++) { - log_debug(peer->log, "%s: output %zi", __func__, i); - if (peer->onchain.to_us_idx == -1 - && outputscript_eq(tx->output, i, to_us)) { - log_add(peer->log, " -> to us"); - peer->onchain.htlcs[i] = NULL; - peer->onchain.wscripts[i] = to_us_wscript; - peer->onchain.to_us_idx = i; - continue; - } - if (peer->onchain.to_them_idx == -1 - && outputscript_eq(tx->output, i, to_them)) { - log_add(peer->log, " -> to them"); - peer->onchain.htlcs[i] = NULL; - peer->onchain.wscripts[i] = to_them_wscript; - peer->onchain.to_them_idx = i; - continue; - } - /* Must be an HTLC output */ - peer->onchain.htlcs[i] = txout_get_htlc(hmap, - tx->output[i].script, - peer->onchain.wscripts+i); - if (!peer->onchain.htlcs[i]) { - log_add(peer->log, "no HTLC found"); - goto fail; - } - tal_steal(peer->onchain.htlcs, peer->onchain.htlcs[i]); - tal_steal(peer->onchain.wscripts, peer->onchain.wscripts[i]); - log_add(peer->log, "HTLC %"PRIu64, peer->onchain.htlcs[i]->id); - } - tal_free(hmap); - return true; - -fail: - tal_free(hmap); - return false; -} - -static bool is_mutual_close(const struct peer *peer, - const struct bitcoin_tx *tx) -{ - const u8 *ours, *theirs; - - ours = peer->closing.our_script; - theirs = peer->closing.their_script; - /* If we don't know the closing scripts, can't have signed them. */ - if (!ours || !theirs) - return false; - - if (tal_count(tx->output) != 2) - return false; - - /* Without knowing fee amounts, can't determine order. Check both. */ - if (scripteq(tx->output[0].script, ours) - && scripteq(tx->output[1].script, theirs)) - return true; - - if (scripteq(tx->output[0].script, theirs) - && scripteq(tx->output[1].script, ours)) - return true; - - return false; -} - -/* Create a HTLC refund collection for onchain.tx output out_num. */ -static const struct bitcoin_tx *htlc_timeout_tx(const struct peer *peer, - unsigned int out_num) -{ - const struct htlc *htlc = peer->onchain.htlcs[out_num]; - const u8 *wscript = peer->onchain.wscripts[out_num]; - struct bitcoin_tx *tx = bitcoin_tx(peer, 1, 1); - secp256k1_ecdsa_signature sig; - u64 fee, satoshis; - - /* We must set locktime so HTLC expiry can OP_CHECKLOCKTIMEVERIFY */ - tx->lock_time = htlc->expiry.locktime; - tx->input[0].index = out_num; - tx->input[0].txid = peer->onchain.txid; - satoshis = htlc->msatoshi / 1000; - tx->input[0].amount = tal_dup(tx->input, u64, &satoshis); - tx->input[0].sequence_number = bitcoin_nsequence(&peer->remote.locktime); - - /* Using a new output address here would be useless: they can tell - * it's our HTLC, and that we collected it via timeout. */ - tx->output[0].script = scriptpubkey_p2sh(tx, - bitcoin_redeem_single(tx, - &peer->local.finalkey)); - - log_unusual(peer->log, "Pre-witness txlen = %zu\n", - measure_tx_cost(tx) / 4); - - assert(measure_tx_cost(tx) == 83 * 4); - - /* Witness length can vary, due to DER encoding of sigs, but we - * use 539 from an example run. */ - fee = fee_by_feerate(83 + 539 / 4, get_feerate(peer->dstate->topology)); - - /* FIXME: Fail gracefully in these cases (not worth collecting) */ - if (fee > satoshis || is_dust(satoshis - fee)) - fatal("HTLC refund amount of %"PRIu64" won't cover fee %"PRIu64, - satoshis, fee); - - tx->output[0].amount = satoshis - fee; - - peer_sign_htlc_refund(peer, tx, wscript, &sig); - - tx->input[0].witness = bitcoin_witness_htlc(tx, - NULL, &sig, wscript); - - log_unusual(peer->log, "tx cost for htlc timeout tx: %zu", - measure_tx_cost(tx)); - - return tx; -} - -static void reset_onchain_closing(struct peer *peer) -{ - if (peer->onchain.tx) { - log_unusual_struct(peer->log, - "New anchor spend, forgetting old tx %s", - struct sha256_double, &peer->onchain.txid); - peer->onchain.tx = tal_free(peer->onchain.tx); - peer->onchain.resolved = NULL; - peer->onchain.htlcs = NULL; - peer->onchain.wscripts = NULL; - } -} - -static const struct bitcoin_tx *irrevocably_resolved(struct peer *peer) -{ - /* We can't all be irrevocably resolved until the commit tx is, - * so just mark that as resolving us. */ - return peer->onchain.tx; -} - -/* We usually don't fail HTLCs we offered, but if the peer breaks down - * before we've confirmed it, this is exactly what happens. */ -static void fail_own_htlc(struct peer *peer, struct htlc *htlc) -{ - /* We can't do anything about db failures; peer already closed. */ - db_start_transaction(peer); - set_htlc_fail(peer, htlc, "peer closed", strlen("peer closed")); - our_htlc_failed(peer, htlc); - db_commit_transaction(peer); -} - -/* We've spent an HTLC output to get our funds back. There's still a - * chance that they could also spend the HTLC output (using the preimage), - * so we need to wait for some confirms. - * - * However, we don't want to wait too long: our upstream will get upset if - * their HTLC has timed out and we don't close it. So we wait one less - * than the HTLC timeout difference. - */ -static enum watch_result our_htlc_timeout_depth(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - struct htlc *htlc) -{ - if (depth == 0) - return KEEP_WATCHING; - if (depth + 1 < peer->dstate->config.min_htlc_expiry) - return KEEP_WATCHING; - fail_own_htlc(peer, htlc); - return DELETE_WATCH; -} - -static enum watch_result our_htlc_depth(struct peer *peer, - unsigned int depth, - const struct sha256_double *txid, - enum side whose_commit, - unsigned int out_num) -{ - struct htlc *h = peer->onchain.htlcs[out_num]; - u32 height; - - /* Must be in a block. */ - if (depth == 0) - return KEEP_WATCHING; - - height = get_block_height(peer->dstate->topology); - - /* FIXME-OLD #onchain: - * - * If the *commitment tx* is the other node's, the output is - * considered *timed out* once the HTLC is expired. If the - * *commitment tx* is this node's, the output is considered *timed - * out* once the HTLC is expired, AND the output's - * `OP_CHECKSEQUENCEVERIFY` delay has passed. - */ - if (height < abs_locktime_to_blocks(&h->expiry)) - return KEEP_WATCHING; - - if (whose_commit == LOCAL) { - if (depth < rel_locktime_to_blocks(&peer->remote.locktime)) - return KEEP_WATCHING; - } - - /* FIXME-OLD #onchain: - * - * If the output has *timed out* and not been *resolved*, the node - * MUST *resolve* the output by spending it. - */ - /* FIXME: we should simply delete this watch if HTLC is fulfilled. */ - if (!peer->onchain.resolved[out_num]) { - peer->onchain.resolved[out_num] = htlc_timeout_tx(peer, out_num); - watch_tx(peer->onchain.resolved[out_num], - peer->dstate->topology, - peer, - peer->onchain.resolved[out_num], - our_htlc_timeout_depth, h); - broadcast_tx(peer->dstate->topology, - peer, peer->onchain.resolved[out_num], NULL); - } - return DELETE_WATCH; -} - -static enum watch_result our_htlc_depth_theircommit(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - ptrint_t *out_num) -{ - struct sha256_double txid; - bitcoin_txid(tx, &txid); - return our_htlc_depth(peer, depth, &txid, REMOTE, ptr2int(out_num)); -} - -static enum watch_result our_htlc_depth_ourcommit(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - ptrint_t *out_num) -{ - struct sha256_double txid; - bitcoin_txid(tx, &txid); - return our_htlc_depth(peer, depth, &txid, LOCAL, ptr2int(out_num)); -} - -static enum watch_result their_htlc_depth(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - ptrint_t *out_num) -{ - u32 height; - const struct htlc *htlc = peer->onchain.htlcs[ptr2int(out_num)]; - - /* Must be in a block. */ - if (depth == 0) - return KEEP_WATCHING; - - height = get_block_height(peer->dstate->topology); - - /* FIXME-OLD #onchain: - * - * Otherwise, if the output HTLC has expired, it is considered - * *irrevocably resolved*. - */ - if (height < abs_locktime_to_blocks(&htlc->expiry)) - return KEEP_WATCHING; - - peer->onchain.resolved[ptr2int(out_num)] = irrevocably_resolved(peer); - return DELETE_WATCH; -} - -static enum watch_result our_main_output_depth(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - void *unused) -{ - /* Not past CSV timeout? */ - if (depth < rel_locktime_to_blocks(&peer->remote.locktime)) - return KEEP_WATCHING; - - assert(peer->onchain.to_us_idx != -1); - - /* FIXME-OLD #onchain: - * - * 1. _A's main output_: A node SHOULD spend this output to a - * convenient address. This avoids having to remember the - * complicated witness script associated with that particular - * channel for later spending. ... If the output is spent (as - * recommended), the output is *resolved* by the spending - * transaction - */ - peer->onchain.resolved[peer->onchain.to_us_idx] - = bitcoin_spend_ours(peer); - broadcast_tx(peer->dstate->topology, - peer, peer->onchain.resolved[peer->onchain.to_us_idx], - NULL); - return DELETE_WATCH; -} - -/* Any of our HTLCs we didn't have in our commitment tx, but they did, - * we can't fail until we're sure our commitment tx will win. */ -static enum watch_result our_unilateral_depth(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - void *unused) -{ - struct htlc_map_iter it; - struct htlc *h; - - if (depth < peer->dstate->config.min_htlc_expiry) - return KEEP_WATCHING; - - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (htlc_owner(h) == LOCAL - && !htlc_has(h, HTLC_LOCAL_F_COMMITTED) - && htlc_has(h, HTLC_REMOTE_F_COMMITTED)) { - log_debug(peer->log, - "%s:failing uncommitted htlc %"PRIu64, - __func__, h->id); - fail_own_htlc(peer, h); - } - } - return DELETE_WATCH; -} - -static enum watch_result our_htlc_spent(struct peer *peer, - const struct bitcoin_tx *tx, - size_t input_num, - const struct block *block, - struct htlc *h) -{ - struct sha256 sha; - struct preimage preimage; - - /* FIXME-OLD #onchain: - * - * If a node sees a redemption transaction...the node MUST extract the - * preimage from the transaction input witness. This is either to - * prove payment (if this node originated the payment), or to redeem - * the corresponding incoming HTLC from another peer. - */ - - /* This is the form of all HTLC spends. */ - if (!tx->input[input_num].witness - || tal_count(tx->input[input_num].witness) != 3 - || tal_count(tx->input[input_num].witness[1]) != sizeof(preimage)) - fatal("Impossible HTLC spend for %"PRIu64, h->id); - - /* Our timeout tx has all-zeroes, so we can distinguish it. */ - if (memeqzero(tx->input[input_num].witness[1], sizeof(preimage))) - /* They might try to race us. */ - return KEEP_WATCHING; - - memcpy(&preimage, tx->input[input_num].witness[1], sizeof(preimage)); - sha256(&sha, &preimage, sizeof(preimage)); - - /* FIXME: This could happen with a ripemd collision, since - * script.c only checks that ripemd matches... */ - if (!structeq(&sha, &h->rhash)) - fatal("HTLC redeemed with incorrect r value?"); - - log_unusual(peer->log, "Peer redeemed HTLC %"PRIu64" on-chain", - h->id); - log_add_struct(peer->log, " using rvalue %s", struct preimage, &preimage); - - set_htlc_rval(peer, h, &preimage); - our_htlc_fulfilled(peer, h); - - /* FIXME-OLD #onchain: - * - * If a node sees a redemption transaction, the output is considered - * *irrevocably resolved*... Note that we don't care about the fate of - * the redemption transaction itself once we've extracted the - * preimage; the knowledge is not revocable. - */ - peer->onchain.resolved[tx->input[input_num].index] - = irrevocably_resolved(peer); - return DELETE_WATCH; -} - -static void resolve_our_htlc(struct peer *peer, - unsigned int out_num, - enum watch_result (*cb)(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - ptrint_t *out_num)) -{ - /* FIXME-OLD #onchain: - * - * A node MUST watch for spends of *commitment tx* outputs for HTLCs - * it offered; each one must be *resolved* by a timeout transaction - * (the node pays back to itself) or redemption transaction (the other - * node provides the redemption preimage). - */ - watch_txo(peer->onchain.tx, - peer->dstate->topology, - peer, &peer->onchain.txid, out_num, - our_htlc_spent, peer->onchain.htlcs[out_num]); - watch_txid(peer->onchain.tx, - peer->dstate->topology, - peer, &peer->onchain.txid, cb, int2ptr(out_num)); -} - -static void resolve_their_htlc(struct peer *peer, unsigned int out_num) -{ - /* FIXME-OLD #onchain: - * - * If the node ... already knows... a redemption preimage for an - * unresolved *commitment tx* output it was offered, it MUST *resolve* - * the output by spending it using the preimage. - */ - if (peer->onchain.htlcs[out_num]->r) { - peer->onchain.resolved[out_num] = htlc_fulfill_tx(peer, out_num); - broadcast_tx(peer->dstate->topology, - peer, peer->onchain.resolved[out_num], NULL); - } else { - /* FIXME-OLD #onchain: - * - * Otherwise, if the output HTLC has expired, it is considered - * *irrevocably resolved*. - */ - watch_tx(peer->onchain.tx, - peer->dstate->topology, - peer, peer->onchain.tx, - their_htlc_depth, int2ptr(out_num)); - } -} - -/* FIXME-OLD #onchain: - * - * When node A sees its own *commitment tx*: - */ -static void resolve_our_unilateral(struct peer *peer) -{ - unsigned int i; - struct chain_topology *topo = peer->dstate->topology; - const struct bitcoin_tx *tx = peer->onchain.tx; - - /* This only works because we always watch for a long time before - * freeing peer, by which time this has resolved. We could create - * resolved[] entries for these uncommitted HTLCs, too. */ - watch_tx(tx, topo, peer, tx, our_unilateral_depth, NULL); - - for (i = 0; i < tal_count(tx->output); i++) { - /* FIXME-OLD #onchain: - * - * 1. _A's main output_: A node SHOULD spend this output to a - * convenient address. ... A node MUST wait until the - * `OP_CHECKSEQUENCEVERIFY` delay has passed (as specified - * by the other node's `open_channel` `delay` field) before - * spending the output. - */ - if (i == peer->onchain.to_us_idx) - watch_tx(tx, topo, - peer, tx, our_main_output_depth, NULL); - - /* FIXME-OLD #onchain: - * - * 2. _B's main output_: No action required, this output is - * considered *resolved* by the *commitment tx*. - */ - else if (i == peer->onchain.to_them_idx) - peer->onchain.resolved[i] = tx; - - /* FIXME-OLD #onchain: - * - * 3. _A's offered HTLCs_: See On-chain HTLC Handling: Our - * Offers below. - */ - else if (htlc_owner(peer->onchain.htlcs[i]) == LOCAL) - resolve_our_htlc(peer, i, our_htlc_depth_ourcommit); - - /* FIXME-OLD #onchain: - * - * 4. _B's offered HTLCs_: See On-chain HTLC Handling: Their - * Offers below. - */ - else - resolve_their_htlc(peer, i); - } -} - -/* FIXME-OLD #onchain: - * - * Similarly, when node A sees a *commitment tx* from B: - */ -static void resolve_their_unilateral(struct peer *peer) -{ - unsigned int i; - const struct bitcoin_tx *tx = peer->onchain.tx; - - for (i = 0; i < tal_count(tx->output); i++) { - /* FIXME-OLD #onchain: - * - * 1. _A's main output_: No action is required; this is a - * simple P2WPKH output. This output is considered - * *resolved* by the *commitment tx*. - */ - if (i == peer->onchain.to_us_idx) - peer->onchain.resolved[i] = tx; - /* FIXME-OLD #onchain: - * - * 2. _B's main output_: No action required, this output is - * considered *resolved* by the *commitment tx*. - */ - else if (i == peer->onchain.to_them_idx) - peer->onchain.resolved[i] = tx; - /* FIXME-OLD #onchain: - * - * 3. _A's offered HTLCs_: See On-chain HTLC Handling: Our - * Offers below. - */ - else if (htlc_owner(peer->onchain.htlcs[i]) == LOCAL) - resolve_our_htlc(peer, i, our_htlc_depth_theircommit); - /* - * 4. _B's offered HTLCs_: See On-chain HTLC Handling: Their - * Offers below. - */ - else - resolve_their_htlc(peer, i); - } -} - -static void resolve_mutual_close(struct peer *peer) -{ - unsigned int i; - - /* FIXME-OLD #onchain: - * - * A node doesn't need to do anything else as it has already agreed to - * the output, which is sent to its specified scriptpubkey (see FIXME-OLD - * #2 "4.1: Closing initiation: close_shutdown"). - */ - for (i = 0; i < tal_count(peer->onchain.tx->output); i++) - peer->onchain.resolved[i] = irrevocably_resolved(peer); - - /* No HTLCs. */ - peer->onchain.htlcs = tal_arrz(peer->onchain.tx, - struct htlc *, - tal_count(peer->onchain.tx->output)); -} - -/* Called every time the tx spending the funding tx changes depth. */ -static enum watch_result check_for_resolution(struct peer *peer, - const struct bitcoin_tx *tx, - unsigned int depth, - void *unused) -{ - size_t i, n = tal_count(peer->onchain.resolved); - size_t forever = peer->dstate->config.forever_confirms; - - /* FIXME-OLD #onchain: - * - * A node MUST *resolve* all outputs as specified below, and MUST be - * prepared to resolve them multiple times in case of blockchain - * reorganizations. - */ - for (i = 0; i < n; i++) - if (!peer->onchain.resolved[i]) - return KEEP_WATCHING; - - /* FIXME-OLD #onchain: - * - * Outputs which are *resolved* by a transaction are considered - * *irrevocably resolved* once they are included in a block at least - * 100 deep on the most-work blockchain. - */ - if (depth < forever) - return KEEP_WATCHING; - - for (i = 0; i < n; i++) { - struct sha256_double txid; - - bitcoin_txid(peer->onchain.resolved[i], &txid); - if (get_tx_depth(peer->dstate->topology, &txid, NULL) < forever) - return KEEP_WATCHING; - } - - /* FIXME-OLD #onchain: - * - * A node MUST monitor the blockchain for transactions which spend any - * output which is not *irrevocably resolved* until all outputs are - * *irrevocably resolved*. - */ - set_peer_state(peer, STATE_CLOSED, "check_for_resolution", false); - db_forget_peer(peer); - - /* It's theoretically possible that peer is still writing output */ - if (!peer->conn) - io_break(peer); - else - io_wake(peer); - - return DELETE_WATCH; -} - -static bool find_their_old_tx(struct peer *peer, - const struct sha256_double *txid, - u64 *idx) -{ - /* FIXME: Don't keep these in memory, search db here. */ - struct their_commit *tc; - - log_debug_struct(peer->log, "Finding txid %s", struct sha256_double, - txid); - list_for_each(&peer->their_commits, tc, list) { - if (structeq(&tc->txid, txid)) { - *idx = tc->commit_num; - return true; - } - } - return false; -} - -static void resolve_their_steal(struct peer *peer, - const struct sha256 *revocation_preimage) -{ - int i, n; - const struct bitcoin_tx *tx = peer->onchain.tx; - struct bitcoin_tx *steal_tx; - size_t wsize = 0; - u64 input_total = 0, fee; - - /* Create steal_tx: don't need to steal to_us output */ - if (peer->onchain.to_us_idx == -1) - steal_tx = bitcoin_tx(tx, tal_count(tx->output), 1); - else - steal_tx = bitcoin_tx(tx, tal_count(tx->output) - 1, 1); - n = 0; - - log_debug(peer->log, "Analyzing tx to steal:"); - for (i = 0; i < tal_count(tx->output); i++) { - /* FIXME-OLD #onchain: - * 1. _A's main output_: No action is required; this is a - * simple P2WPKH output. This output is considered - * *resolved* by the *commitment tx*. - */ - if (i == peer->onchain.to_us_idx) { - log_debug(peer->log, "%i is to-us, ignoring", i); - peer->onchain.resolved[i] = tx; - continue; - } - - /* FIXME-OLD #onchain: - * - * 2. _B's main output_: The node MUST *resolve* this by - * spending using the revocation preimage. - * - * 3. _A's offered HTLCs_: The node MUST *resolve* this by - * spending using the revocation preimage. - * - * 4. _B's offered HTLCs_: The node MUST *resolve* this by - * spending using the revocation preimage. - */ - peer->onchain.resolved[i] = steal_tx; - - /* Connect it up. */ - steal_tx->input[n].txid = peer->onchain.txid; - steal_tx->input[n].index = i; - steal_tx->input[n].amount = tal_dup(steal_tx, u64, - &tx->output[i].amount); - /* Track witness size, for fee. */ - wsize += tal_count(peer->onchain.wscripts[i]); - input_total += tx->output[i].amount; - n++; - } - assert(n == tal_count(steal_tx->input)); - - fee = get_feerate(peer->dstate->topology) - * (measure_tx_cost(steal_tx) + wsize) / 1000; - - if (fee > input_total || is_dust(input_total - fee)) { - log_unusual(peer->log, "Not worth stealing tiny amount %"PRIu64, - input_total); - /* Consider them all resolved by steal tx. */ - for (i = 0; i < tal_count(peer->onchain.resolved); i++) - peer->onchain.resolved[i] = tx; - tal_free(steal_tx); - return; - } - steal_tx->output[0].amount = input_total - fee; - steal_tx->output[0].script = scriptpubkey_p2sh(steal_tx, - bitcoin_redeem_single(steal_tx, - &peer->local.finalkey)); - - /* Now, we can sign them all (they're all of same form). */ - n = 0; - for (i = 0; i < tal_count(tx->output); i++) { - secp256k1_ecdsa_signature sig; - - /* Don't bother stealing the output already to us. */ - if (i == peer->onchain.to_us_idx) - continue; - - peer_sign_steal_input(peer, steal_tx, n, - peer->onchain.wscripts[i], - &sig); - - steal_tx->input[n].witness - = bitcoin_witness_secret(steal_tx, - revocation_preimage, - sizeof(*revocation_preimage), - &sig, - peer->onchain.wscripts[i]); - n++; - } - assert(n == tal_count(steal_tx->input)); - - broadcast_tx(peer->dstate->topology, peer, steal_tx, NULL); -} - -static struct sha256 *get_rhash(struct peer *peer, u64 commit_num, - struct sha256 *rhash) -{ - struct sha256 preimage; - - /* Previous revoked tx? */ - if (shachain_get_hash(&peer->their_preimages, - 0xFFFFFFFFFFFFFFFFL - commit_num, - &preimage)) { - sha256(rhash, &preimage, sizeof(preimage)); - return tal_dup(peer, struct sha256, &preimage); - } - - /* Current tx? */ - if (commit_num == peer->remote.commit->commit_num) { - *rhash = peer->remote.commit->revocation_hash; - return NULL; - } - - /* Last tx, but we haven't got revoke for it yet? */ - assert(commit_num == peer->remote.commit->commit_num-1); - *rhash = *peer->their_prev_revocation_hash; - return NULL; -} - -/* We assume the tx is valid! Don't do a blockchain.info and feed this - * invalid transactions! */ -static enum watch_result anchor_spent(struct peer *peer, - const struct bitcoin_tx *tx, - size_t input_num, - const struct block *block, - void *unused) -{ - Pkt *err; - enum state newstate; - struct htlc_map_iter it; - struct htlc *h; - u64 commit_num; - - assert(input_num < tal_count(tx->input)); - - /* We only ever sign single-input txs. */ - if (input_num != 0) { - log_broken(peer->log, "Anchor spend by non-single input tx"); - goto unknown_spend; - } - - /* We may have been following a different spend. Forget it. */ - reset_onchain_closing(peer); - - peer->onchain.tx = tal_steal(peer, tx); - bitcoin_txid(tx, &peer->onchain.txid); - - /* If we have any HTLCs we're not committed to yet, fail them now. */ - for (h = htlc_map_first(&peer->htlcs, &it); - h; - h = htlc_map_next(&peer->htlcs, &it)) { - if (h->state == SENT_ADD_HTLC) { - fail_own_htlc(peer, h); - } - } - - /* We need to resolve every output. */ - peer->onchain.resolved - = tal_arrz(tx, const struct bitcoin_tx *, - tal_count(tx->output)); - - /* A mutual close tx. */ - if (is_mutual_close(peer, tx)) { - newstate = STATE_CLOSE_ONCHAIN_MUTUAL; - err = NULL; - resolve_mutual_close(peer); - /* Our unilateral */ - } else if (structeq(&peer->local.commit->txid, - &peer->onchain.txid)) { - newstate = STATE_CLOSE_ONCHAIN_OUR_UNILATERAL; - /* We're almost certainly closed to them by now. */ - err = pkt_err(peer, "Our own unilateral close tx seen"); - if (!map_onchain_outputs(peer, - &peer->local.commit->revocation_hash, - tx, LOCAL, - peer->local.commit->commit_num)) { - log_broken(peer->log, - "Can't resolve own anchor spend %"PRIu64"!", - peer->local.commit->commit_num); - goto unknown_spend; - } - resolve_our_unilateral(peer); - /* Must be their unilateral */ - } else if (find_their_old_tx(peer, &peer->onchain.txid, - &commit_num)) { - struct sha256 *preimage, rhash; - - preimage = get_rhash(peer, commit_num, &rhash); - if (!map_onchain_outputs(peer, &rhash, tx, REMOTE, commit_num)) { - /* Should not happen */ - log_broken(peer->log, - "Can't resolve known anchor spend %"PRIu64"!", - commit_num); - goto unknown_spend; - } - if (preimage) { - newstate = STATE_CLOSE_ONCHAIN_CHEATED; - err = pkt_err(peer, "Revoked transaction seen"); - resolve_their_steal(peer, preimage); - } else { - newstate = STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL; - err = pkt_err(peer, "Unilateral close tx seen"); - resolve_their_unilateral(peer); - } - } else { - /* FIXME: Log harder! */ - log_broken(peer->log, - "Unknown anchor spend! Funds may be lost!"); - goto unknown_spend; - } - - /* FIXME-OLD #onchain: - * - * A node MAY send a descriptive error packet in this case. - */ - if (err && state_can_io(peer->state)) - queue_pkt_err(peer, err); - - /* Don't need to save to DB: it will be replayed if we crash. */ - set_peer_state(peer, newstate, "anchor_spent", false); - - /* If we've just closed connection, make output close it. */ - io_wake(peer); - - /* FIXME-OLD #onchain: - * - * A node SHOULD fail the connection if it is not already - * closed when it sees the funding transaction spent. - */ - assert(!state_can_io(peer->state)); - - assert(peer->onchain.resolved != NULL); - watch_tx(tx, peer->dstate->topology, - peer, tx, check_for_resolution, NULL); - - return KEEP_WATCHING; - -unknown_spend: - /* FIXME-OLD #onchain: - * - * A node SHOULD report an error to the operator if it - * sees a transaction spend the funding transaction - * output which does not fall into one of these - * categories (mutual close, unilateral close, or - * cheating attempt). Such a transaction implies its - * private key has leaked, and funds may be lost. - */ - /* FIXME: Save to db. */ - set_peer_state(peer, STATE_ERR_INFORMATION_LEAK, "anchor_spent", false); - return DELETE_WATCH; -} - -void peer_watch_anchor(struct peer *peer, int depth) -{ - struct chain_topology *topo = peer->dstate->topology; - - log_debug_struct(peer->log, "watching for anchor %s", - struct sha256_double, &peer->anchor.txid); - log_add(peer->log, " to hit depth %i", depth); - - peer->anchor.ok_depth = depth; - watch_txid(peer, topo, peer, - &peer->anchor.txid, anchor_depthchange, NULL); - watch_txo(peer, topo, peer, &peer->anchor.txid, 0, anchor_spent, NULL); -} - -struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, - struct peer *peer, u64 fee) -{ - struct channel_state cstate; - - /* We don't need a deep copy here, just fee levels. */ - cstate = *peer->local.staging_cstate; - if (!force_fee(&cstate, fee)) { - log_unusual(peer->log, - "peer_create_close_tx: can't afford fee %"PRIu64, - fee); - return NULL; - } - - log_debug(peer->log, - "creating close-tx with fee %"PRIu64" amounts %u/%u to ", - fee, - cstate.side[LOCAL].pay_msat / 1000, - cstate.side[REMOTE].pay_msat / 1000); - log_add_struct(peer->log, "%s", struct pubkey, &peer->local.finalkey); - log_add_struct(peer->log, "/%s", struct pubkey, &peer->remote.finalkey); - - return create_close_tx(ctx, - peer->closing.our_script, - peer->closing.their_script, - &peer->anchor.txid, - peer->anchor.index, - peer->anchor.satoshis, - cstate.side[LOCAL].pay_msat / 1000, - cstate.side[REMOTE].pay_msat / 1000, - /* FIXME: Real dust limit! */ - 0); -} - -/* Sets up the initial cstate and commit tx for both nodes: false if - * insufficient funds. */ -bool setup_first_commit(struct peer *peer) -{ - bool to_them_only, to_us_only; - - assert(!peer->local.commit->tx); - assert(!peer->remote.commit->tx); - - /* Revocation hashes already filled in, from pkt_open */ - peer->local.commit->cstate = initial_cstate(peer->local.commit, - peer->anchor.satoshis, - peer->local.commit_fee_rate, - peer->local.offer_anchor ? - LOCAL : REMOTE); - if (!peer->local.commit->cstate) - return false; - - peer->remote.commit->cstate = initial_cstate(peer->remote.commit, - peer->anchor.satoshis, - peer->remote.commit_fee_rate, - peer->local.offer_anchor ? - LOCAL : REMOTE); - if (!peer->remote.commit->cstate) - return false; - - peer->local.commit->tx = create_commit_tx(peer->local.commit, - peer, - &peer->local.commit->revocation_hash, - peer->local.commit->cstate, - LOCAL, &to_them_only); - bitcoin_txid(peer->local.commit->tx, &peer->local.commit->txid); - - peer->remote.commit->tx = create_commit_tx(peer->remote.commit, - peer, - &peer->remote.commit->revocation_hash, - peer->remote.commit->cstate, - REMOTE, &to_us_only); - assert(to_them_only != to_us_only); - - /* If we offer anchor, their commit is to-us only. */ - assert(to_us_only == peer->local.offer_anchor); - bitcoin_txid(peer->remote.commit->tx, &peer->remote.commit->txid); - - peer->local.staging_cstate = copy_cstate(peer, peer->local.commit->cstate); - peer->remote.staging_cstate = copy_cstate(peer, peer->remote.commit->cstate); - - return true; -} - -static struct io_plan *peer_reconnect(struct io_conn *conn, struct peer *peer) -{ - /* In case they reconnected to us already. */ - if (peer->conn) - return io_close(conn); - - log_debug(peer->log, "Reconnected, doing crypto..."); - peer->conn = conn; - assert(!peer->connected); - - assert(peer->id); - return peer_crypto_setup(conn, peer->dstate, - peer->id, peer->log, - crypto_on_reconnect_out, peer); -} - -/* We can't only retry when we want to send: they may want to send us - * something but not be able to connect (NAT). So keep retrying.. */ -static void reconnect_failed(struct io_conn *conn, struct peer *peer) -{ - /* Already otherwise connected (ie. they connected in)? */ - if (peer->conn) { - log_debug(peer->log, "reconnect_failed: already connected"); - return; - } - - log_debug(peer->log, "Setting timer to re-connect"); - new_reltimer(&peer->dstate->timers, peer, peer->dstate->config.poll_time, - try_reconnect, peer); -} - -static struct io_plan *init_conn(struct io_conn *conn, struct peer *peer) -{ - struct addrinfo a; - struct peer_address *addr = find_address(peer->dstate, peer->id); - - netaddr_to_addrinfo(&a, &addr->addr); - return io_connect(conn, &a, peer_reconnect, peer); -} - -static void try_reconnect(struct peer *peer) -{ - struct io_conn *conn; - struct peer_address *addr; - char *name; - int fd; - - /* Already reconnected? */ - if (peer->conn) { - log_debug(peer->log, "try_reconnect: already connected"); - return; - } - - addr = find_address(peer->dstate, peer->id); - if (!addr) { - log_debug(peer->log, "try_reconnect: no known address"); - return; - } - - fd = socket(addr->addr.saddr.s.sa_family, addr->addr.type, - addr->addr.protocol); - if (fd < 0) { - log_broken(peer->log, "do_reconnect: failed to create socket: %s", - strerror(errno)); - peer_fail(peer, __func__); - return; - } - - assert(!peer->conn); - conn = io_new_conn(peer->dstate, fd, init_conn, peer); - name = netaddr_name(peer, &addr->addr); - log_debug(peer->log, "Trying to reconnect to %s", name); - tal_free(name); - io_set_finish(conn, reconnect_failed, peer); -} - -void reconnect_peers(struct lightningd_state *dstate) -{ - struct peer *peer; - - list_for_each(&dstate->peers, peer, list) - try_reconnect(peer); -} - -/* Return earliest block we're interested in, or 0 for none. */ -u32 get_peer_min_block(struct lightningd_state *dstate) -{ - u32 min_block = 0; - struct peer *peer; - - /* If loaded from database, go back to earliest possible peer anchor. */ - list_for_each(&dstate->peers, peer, list) { - if (!peer->anchor.min_depth) - continue; - if (min_block == 0 || peer->anchor.min_depth < min_block) - min_block = peer->anchor.min_depth; - } - return min_block; -} - -/* We may have gone down before broadcasting the anchor. Try again. */ -void rebroadcast_anchors(struct lightningd_state *dstate) -{ - struct peer *peer; - - list_for_each(&dstate->peers, peer, list) { - if (!state_is_waiting_for_anchor(peer->state)) - continue; - if (!peer->anchor.ours) - continue; - if (!bitcoin_create_anchor(peer)) - peer_fail(peer, __func__); - else - broadcast_tx(peer->dstate->topology, - peer, peer->anchor.tx, NULL); - } -} - -static void json_add_abstime(struct json_result *response, - const char *id, - const struct abs_locktime *t) -{ - json_object_start(response, id); - if (abs_locktime_is_seconds(t)) - json_add_num(response, "second", abs_locktime_to_seconds(t)); - else - json_add_num(response, "block", abs_locktime_to_blocks(t)); - json_object_end(response); -} - -static void json_add_htlcs(struct json_result *response, - const char *id, - struct peer *peer, - enum side owner) -{ - struct htlc_map_iter it; - struct htlc *h; - const struct htlc_map *htlcs = &peer->htlcs; - - json_array_start(response, id); - for (h = htlc_map_first(htlcs, &it); h; h = htlc_map_next(htlcs, &it)) { - if (htlc_owner(h) != owner) - continue; - - /* Ignore completed HTLCs. */ - if (htlc_is_dead(h)) - continue; - - json_object_start(response, NULL); - json_add_u64(response, "msatoshi", h->msatoshi); - json_add_abstime(response, "expiry", &h->expiry); - json_add_hex(response, "rhash", &h->rhash, sizeof(h->rhash)); - json_add_string(response, "state", htlc_state_name(h->state)); - json_object_end(response); - } - json_array_end(response); -} - -/* FIXME: add history command which shows all prior and current commit txs */ - -/* FIXME: Somehow we should show running DNS lookups! */ -static void json_getpeers(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *p; - struct json_result *response = new_json_result(cmd); - - json_object_start(response, NULL); - json_array_start(response, "peers"); - list_for_each(&cmd->dstate->peers, p, list) { - const struct channel_state *last; - - json_object_start(response, NULL); - json_add_string(response, "name", log_prefix(p->log)); - json_add_string(response, "state", state_name(p->state)); - - if (p->id) - json_add_pubkey(response, "peerid", p->id); - - json_add_bool(response, "connected", p->connected); - - /* FIXME: Report anchor. */ - - if (!p->local.commit || !p->local.commit->cstate) { - json_object_end(response); - continue; - } - last = p->local.commit->cstate; - - json_add_num(response, "our_amount", last->side[LOCAL].pay_msat); - json_add_num(response, "our_fee", last->side[LOCAL].fee_msat); - json_add_num(response, "their_amount", last->side[REMOTE].pay_msat); - json_add_num(response, "their_fee", last->side[REMOTE].fee_msat); - json_add_htlcs(response, "our_htlcs", p, LOCAL); - json_add_htlcs(response, "their_htlcs", p, REMOTE); - json_object_end(response); - } - json_array_end(response); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command getpeers_command = { - "getpeers", - json_getpeers, - "List the current peers", - "Returns a 'peers' array" -}; -AUTODATA(json_command, &getpeers_command); - -static void json_gethtlcs(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok, *resolvedtok; - bool resolved = false; - struct json_result *response = new_json_result(cmd); - struct htlc *h; - struct htlc_map_iter it; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - "?resolved", &resolvedtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (resolvedtok && !json_tok_bool(buffer, resolvedtok, &resolved)) { - command_fail(cmd, "resolved must be true or false"); - return; - } - - json_object_start(response, NULL); - json_array_start(response, "htlcs"); - for (h = htlc_map_first(&peer->htlcs, &it); - h; h = htlc_map_next(&peer->htlcs, &it)) { - if (htlc_is_dead(h) && !resolved) - continue; - - json_object_start(response, NULL); - json_add_u64(response, "id", h->id); - json_add_string(response, "state", htlc_state_name(h->state)); - json_add_u64(response, "msatoshi", h->msatoshi); - json_add_abstime(response, "expiry", &h->expiry); - json_add_hex(response, "rhash", &h->rhash, sizeof(h->rhash)); - if (h->r) - json_add_hex(response, "r", h->r, sizeof(*h->r)); - if (htlc_owner(h) == LOCAL) { - json_add_num(response, "deadline", h->deadline); - if (h->src) { - json_object_start(response, "src"); - json_add_pubkey(response, - "peerid", h->src->peer->id); - json_add_u64(response, "id", h->src->id); - json_object_end(response); - } - } else { - if (h->routing) - json_add_hex(response, "routing", - h->routing, tal_count(h->routing)); - } - json_object_end(response); - } - json_array_end(response); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command gethtlcs_command = { - "gethtlcs", - json_gethtlcs, - "List HTLCs for {peer}; all if {resolved} is true.", - "Returns a 'htlcs' array" -}; -AUTODATA(json_command, &gethtlcs_command); - -/* To avoid freeing underneath ourselves, we free outside event loop. */ -void cleanup_peers(struct lightningd_state *dstate) -{ - struct peer *peer, *next; - - list_for_each_safe(&dstate->peers, peer, next, list) { - /* Deletes itself from list. */ - if (!peer->conn && peer->state == STATE_CLOSED) - tal_free(peer); - } -} - -static void json_newhtlc(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok, *msatoshitok, *expirytok, *rhashtok; - unsigned int expiry; - u64 msatoshi; - struct sha256 rhash; - struct json_result *response = new_json_result(cmd); - struct htlc *htlc; - const char *err; - enum fail_error error_code; - struct hoppayload *hoppayloads; - u8 sessionkey[32]; - struct onionpacket *packet; - u8 *onion; - struct pubkey *path = tal_arrz(cmd, struct pubkey, 1); - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - "msatoshi", &msatoshitok, - "expiry", &expirytok, - "rhash", &rhashtok, - NULL)) { - command_fail(cmd, "Need peerid, msatoshi, expiry and rhash"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->remote.commit || !peer->remote.commit->cstate) { - command_fail(cmd, "peer not fully established"); - return; - } - - if (!peer->connected) { - command_fail(cmd, "peer not connected"); - return; - } - - if (!json_tok_u64(buffer, msatoshitok, &msatoshi)) { - command_fail(cmd, "'%.*s' is not a valid number", - (int)(msatoshitok->end - msatoshitok->start), - buffer + msatoshitok->start); - return; - } - if (!json_tok_number(buffer, expirytok, &expiry)) { - command_fail(cmd, "'%.*s' is not a valid number", - (int)(expirytok->end - expirytok->start), - buffer + expirytok->start); - return; - } - - if (!hex_decode(buffer + rhashtok->start, - rhashtok->end - rhashtok->start, - &rhash, sizeof(rhash))) { - command_fail(cmd, "'%.*s' is not a valid sha256 hash", - (int)(rhashtok->end - rhashtok->start), - buffer + rhashtok->start); - return; - } - - tal_arr(cmd, struct pubkey, 1); - hoppayloads = tal_arrz(cmd, struct hoppayload, 1); - memcpy(&path[0], peer->id, sizeof(struct pubkey)); - randombytes_buf(&sessionkey, sizeof(sessionkey)); - packet = create_onionpacket(cmd, path, hoppayloads, sessionkey, - rhash.u.u8, sizeof(rhash)); - onion = serialize_onionpacket(cmd, packet); - - log_debug(peer->log, "JSON command to add new HTLC"); - err = command_htlc_add(peer, msatoshi, expiry, &rhash, NULL, - onion, - &error_code, &htlc); - if (err) { - command_fail(cmd, "could not add htlc: %u:%s", error_code, err); - return; - } - log_debug(peer->log, "JSON new HTLC is %"PRIu64, htlc->id); - - json_object_start(response, NULL); - json_add_u64(response, "id", htlc->id); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command dev_newhtlc_command = { - "dev-newhtlc", - json_newhtlc, - "Offer {peerid} an HTLC worth {msatoshi} in {expiry} (block number) with {rhash}", - "Returns { id: u64 } result on success" -}; -AUTODATA(json_command, &dev_newhtlc_command); - -static void json_fulfillhtlc(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok, *idtok, *rtok; - u64 id; - struct htlc *htlc; - struct sha256 rhash; - struct preimage r; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - "id", &idtok, - "r", &rtok, - NULL)) { - command_fail(cmd, "Need peerid, id and r"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->remote.commit || !peer->remote.commit->cstate) { - command_fail(cmd, "peer not fully established"); - return; - } - - if (!peer->connected) { - command_fail(cmd, "peer not connected"); - return; - } - - if (!json_tok_u64(buffer, idtok, &id)) { - command_fail(cmd, "'%.*s' is not a valid id", - (int)(idtok->end - idtok->start), - buffer + idtok->start); - return; - } - - if (!hex_decode(buffer + rtok->start, - rtok->end - rtok->start, - &r, sizeof(r))) { - command_fail(cmd, "'%.*s' is not a valid sha256 preimage", - (int)(rtok->end - rtok->start), - buffer + rtok->start); - return; - } - - htlc = htlc_get(&peer->htlcs, id, REMOTE); - if (!htlc) { - command_fail(cmd, "preimage htlc not found"); - return; - } - - if (htlc->state != RCVD_ADD_ACK_REVOCATION) { - command_fail(cmd, "htlc in state %s", - htlc_state_name(htlc->state)); - return; - } - - sha256(&rhash, &r, sizeof(r)); - if (!structeq(&htlc->rhash, &rhash)) { - command_fail(cmd, "preimage incorrect"); - return; - } - - /* This can happen if we're disconnected, and thus haven't sent - * fulfill yet; we stored r in database immediately. */ - if (!htlc->r) { - const char *db_err; - - db_start_transaction(peer); - set_htlc_rval(peer, htlc, &r); - - /* We can relay this upstream immediately. */ - our_htlc_fulfilled(peer, htlc); - db_err = db_commit_transaction(peer); - if (db_err) { - command_fail(cmd, "%s", db_err); - return; - } - } - - if (command_htlc_fulfill(peer, htlc)) - command_success(cmd, null_response(cmd)); - else - command_fail(cmd, - "htlc_fulfill not possible in state %s", - state_name(peer->state)); -} - -static const struct json_command dev_fulfillhtlc_command = { - "dev-fulfillhtlc", - json_fulfillhtlc, - "Redeem htlc proposed by {peerid} of {id} using {r}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_fulfillhtlc_command); - -static void json_failhtlc(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok, *idtok, *reasontok; - u64 id; - struct htlc *htlc; - const char *db_err; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - "id", &idtok, - "reason", &reasontok, - NULL)) { - command_fail(cmd, "Need peerid, id and reason"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->remote.commit || !peer->remote.commit->cstate) { - command_fail(cmd, "peer not fully established"); - return; - } - - if (!peer->connected) { - command_fail(cmd, "peer not connected"); - return; - } - - if (!json_tok_u64(buffer, idtok, &id)) { - command_fail(cmd, "'%.*s' is not a valid id", - (int)(idtok->end - idtok->start), - buffer + idtok->start); - return; - } - - htlc = htlc_get(&peer->htlcs, id, REMOTE); - if (!htlc) { - command_fail(cmd, "preimage htlc not found"); - return; - } - - if (htlc->state != RCVD_ADD_ACK_REVOCATION) { - command_fail(cmd, "htlc in state %s", - htlc_state_name(htlc->state)); - return; - } - - db_start_transaction(peer); - - set_htlc_fail(peer, htlc, buffer + reasontok->start, - reasontok->end - reasontok->start); - - db_err = db_commit_transaction(peer); - if (db_err) { - command_fail(cmd, "%s", db_err); - return; - } - - if (command_htlc_fail(peer, htlc)) - command_success(cmd, null_response(cmd)); - else - command_fail(cmd, - "htlc_fail not possible in state %s", - state_name(peer->state)); -} - -static const struct json_command dev_failhtlc_command = { - "dev-failhtlc", - json_failhtlc, - "Fail htlc proposed by {peerid} which has {id}, using {reason}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_failhtlc_command); - -static void json_commit(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->remote.commit || !peer->remote.commit->cstate) { - command_fail(cmd, "peer not fully established"); - return; - } - - if (!peer->connected) { - command_fail(cmd, "peer not connected"); - return; - } - - if (!state_can_commit(peer->state)) { - command_fail(cmd, "peer in state %s", state_name(peer->state)); - return; - } - - do_commit(peer, cmd); -} - -static const struct json_command dev_commit_command = { - "dev-commit", - json_commit, - "Commit all staged HTLC changes with {peerid}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_commit_command); - -static void json_close(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!state_is_normal(peer->state) && !state_is_opening(peer->state)) { - command_fail(cmd, "Peer is already closing: state %s", - state_name(peer->state)); - return; - } - - if (!peer_start_shutdown(peer)) { - command_fail(cmd, "Database error"); - return; - } - /* FIXME: Block until closed! */ - command_success(cmd, null_response(cmd)); -} - -static const struct json_command close_command = { - "close", - json_close, - "Close the channel with peer {peerid}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &close_command); - -static void json_feerate(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - jsmntok_t *feeratetok; - u64 feerate; - - if (!json_get_params(buffer, params, - "feerate", &feeratetok, - NULL)) { - command_fail(cmd, "Need feerate"); - return; - } - - if (!json_tok_u64(buffer, feeratetok, &feerate)) { - command_fail(cmd, "Invalid feerate"); - return; - } - log_debug(cmd->jcon->log, "Fee rate changed to %"PRIu64, feerate); - cmd->dstate->topology->default_fee_rate = feerate; - - command_success(cmd, null_response(cmd)); -} - -static const struct json_command dev_feerate_command = { - "dev-feerate", - json_feerate, - "Change the (default) fee rate to {feerate}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_feerate_command); - -static void json_disconnect(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->conn) { - command_fail(cmd, "Peer is already disconnected"); - return; - } - - /* We don't actually close it, since for testing we want only - * one side to freak out. We just ensure we ignore it. */ - log_debug(peer->log, "Pretending connection is closed"); - peer->fake_close = true; - peer->connected = false; - peer_fail(peer, __func__); - - command_success(cmd, null_response(cmd)); -} - -static void json_reconnect(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->conn) { - command_fail(cmd, "Peer is already disconnected"); - return; - } - - /* Should reconnect on its own. */ - io_close(peer->conn); - command_success(cmd, null_response(cmd)); -} - -static void json_signcommit(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok; - u8 *linear; - struct json_result *response = new_json_result(cmd); - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - NULL)) { - command_fail(cmd, "Need peerid"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->local.commit->sig) { - command_fail(cmd, "Peer has not given us a signature"); - return; - } - - sign_commit_tx(peer); - linear = linearize_tx(cmd, peer->local.commit->tx); - - /* Clear witness for potential future uses. */ - peer->local.commit->tx->input[0].witness - = tal_free(peer->local.commit->tx->input[0].witness); - - json_object_start(response, NULL); - json_add_string(response, "tx", tal_hex(cmd, linear)); - json_object_end(response); - command_success(cmd, response); -} - -static void json_output(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct peer *peer; - jsmntok_t *peeridtok, *enabletok; - bool enable; - - if (!json_get_params(buffer, params, - "peerid", &peeridtok, - "enable", &enabletok, - NULL)) { - command_fail(cmd, "Need peerid and enable"); - return; - } - - peer = find_peer_json(cmd->dstate, buffer, peeridtok); - if (!peer) { - command_fail(cmd, "Could not find peer with that peerid"); - return; - } - - if (!peer->conn) { - command_fail(cmd, "Peer is already disconnected"); - return; - } - - if (!json_tok_bool(buffer, enabletok, &enable)) { - command_fail(cmd, "enable must be true or false"); - return; - } - - log_debug(peer->log, "dev-output: output %s", - enable ? "enabled" : "disabled"); - peer->output_enabled = enable; - - /* Flush any outstanding output */ - if (peer->output_enabled) - io_wake(peer); - - command_success(cmd, null_response(cmd)); -} -static const struct json_command dev_output_command = { - "dev-output", - json_output, - "Enable/disable any messages to peer {peerid} depending on {enable}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_output_command); - -static const struct json_command dev_disconnect_command = { - "dev-disconnect", - json_disconnect, - "Force a disconnect with peer {peerid}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_disconnect_command); - -static const struct json_command dev_reconnect_command = { - "dev-reconnect", - json_reconnect, - "Force a reconnect with peer {peerid}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_reconnect_command); - -static const struct json_command dev_signcommit_command = { - "dev-signcommit", - json_signcommit, - "Sign and return the current commit with peer {peerid}", - "Returns a hex string on success" -}; -AUTODATA(json_command, &dev_signcommit_command); diff --git a/daemon/peer.h b/daemon/peer.h deleted file mode 100644 index 9f12702a1..000000000 --- a/daemon/peer.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef LIGHTNING_DAEMON_PEER_H -#define LIGHTNING_DAEMON_PEER_H -#include "config.h" -#include "bitcoin/locktime.h" -#include "bitcoin/privkey.h" -#include "bitcoin/pubkey.h" -#include "bitcoin/script.h" -#include "bitcoin/shadouble.h" -#include "channel.h" -#include "failure.h" -#include "feechange.h" -#include "htlc.h" -#include "lightning.pb-c.h" -#include "netaddr.h" -#include "protobuf_convert.h" -#include "state.h" -#include "wire/gen_peer_wire.h" -#include -#include -#include -#include - -struct log; -struct lightningd_state; -struct peer; - -/* Mapping for id -> network address. */ -struct peer_address { - struct list_node list; - struct pubkey id; - struct netaddr addr; -}; - -void setup_listeners(struct lightningd_state *dstate); - -void peer_debug(struct peer *peer, const char *fmt, ...) - PRINTF_FMT(2,3); - -struct peer *find_peer(struct lightningd_state *dstate, const struct pubkey *id); -struct peer *find_peer_by_pkhash(struct lightningd_state *dstate, const u8 *pkhash); - -struct peer *new_peer(struct lightningd_state *dstate, - struct log *log, - enum state state, - bool offer_anchor); - -/* Populates very first peer->{local,remote}.commit->{tx,cstate} */ -bool setup_first_commit(struct peer *peer); - -/* Whenever we send a signature, remember the txid -> commit_num mapping */ -void peer_add_their_commit(struct peer *peer, - const struct sha256_double *txid, u64 commit_num); - -/* Allocate a new commit_info struct. */ -struct commit_info *new_commit_info(const tal_t *ctx, u64 commit_num); - -/* Freeing removes from map, too */ -struct htlc *peer_new_htlc(struct peer *peer, - u64 id, - u64 msatoshi, - const struct sha256 *rhash, - u32 expiry, - const u8 *route, - size_t route_len, - struct htlc *src, - enum htlc_state state); - -const char *command_htlc_add(struct peer *peer, u64 msatoshi, - unsigned int expiry, - const struct sha256 *rhash, - struct htlc *src, - const u8 *route, - enum fail_error *error_code, - struct htlc **htlc); - -/* Peer has an issue, breakdown and fail. */ -void peer_fail(struct peer *peer, const char *caller); - -void peer_watch_anchor(struct peer *peer, int depth); - -struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, - struct peer *peer, u64 fee); - -u32 get_peer_min_block(struct lightningd_state *dstate); - -void debug_dump_peers(struct lightningd_state *dstate); - -void reconnect_peers(struct lightningd_state *dstate); -void rebroadcast_anchors(struct lightningd_state *dstate); -void cleanup_peers(struct lightningd_state *dstate); -#endif /* LIGHTNING_DAEMON_PEER_H */ diff --git a/daemon/peer_internal.h b/daemon/peer_internal.h deleted file mode 100644 index 8ba7934dc..000000000 --- a/daemon/peer_internal.h +++ /dev/null @@ -1,210 +0,0 @@ -/* This header holds structure definitions for struct peer, which must - * not be exposed to ../lightningd/ */ -#ifndef LIGHTNING_DAEMON_PEER_INTERNAL_H -#define LIGHTNING_DAEMON_PEER_INTERNAL_H -#include "config.h" - -struct anchor_input { - struct sha256_double txid; - unsigned int index; - /* Amount of input (satoshis), and output (satoshis) */ - u64 in_amount, out_amount; - /* Wallet entry to use to spend. */ - struct pubkey walletkey; -}; - -/* Information we remember for their commitment txs which we signed. - * - * Given the commit_num, we can use shachain to derive the revocation preimage - * (if we've received it yet: we might have not, for the last). - */ -struct their_commit { - struct list_node list; - - struct sha256_double txid; - u64 commit_num; -}; - -struct commit_info { - /* Commit number (0 == from open) */ - u64 commit_num; - /* Revocation hash. */ - struct sha256 revocation_hash; - /* Commit tx & txid */ - struct bitcoin_tx *tx; - struct sha256_double txid; - /* Channel state for this tx. */ - struct channel_state *cstate; - /* Other side's signature for last commit tx (if known) */ - secp256k1_ecdsa_signature *sig; - /* Order which commit was sent (theirs) / revocation was sent (ours) */ - s64 order; -}; - -struct peer_visible_state { - /* Is this side funding the channel? */ - bool offer_anchor; - /* Key for commitment tx inputs, then key for commitment tx outputs */ - struct pubkey commitkey, finalkey; - /* How long to they want the other's outputs locked (blocks) */ - struct rel_locktime locktime; - /* Minimum depth of anchor before channel usable. */ - unsigned int mindepth; - /* Commitment fee they're offering (satoshi). */ - u64 commit_fee_rate; - /* Revocation hash for next commit tx. */ - struct sha256 next_revocation_hash; - /* Commit txs: last one is current. */ - struct commit_info *commit; - - /* cstate to generate next commitment tx. */ - struct channel_state *staging_cstate; -}; - -struct peer { - /* dstate->peers list */ - struct list_node list; - - /* State in state machine. */ - enum state state; - - /* Network connection. */ - struct io_conn *conn; - - /* Are we connected now? (Crypto handshake completed). */ - bool connected; - - /* If we're doing an open, this is the command which triggered it */ - struct command *open_jsoncmd; - - /* If we're doing a commit, this is the command which triggered it */ - struct command *commit_jsoncmd; - - /* Global state. */ - struct lightningd_state *dstate; - - /* Their ID. */ - struct pubkey *id; - - /* Order counter for transmission of revocations/commitments. */ - s64 order_counter; - - /* Current received packet. */ - Pkt *inpkt; - - /* Queue of output packets. */ - Pkt **outpkt; - - /* Their commitments we have signed (which could appear on chain). */ - struct list_head their_commits; - - /* Number of commitment signatures we've received. */ - u64 their_commitsigs; - - /* Anchor tx output */ - struct { - struct sha256_double txid; - unsigned int index; - u64 satoshis; - u8 *witnessscript; - - /* Minimum possible depth for anchor */ - unsigned int min_depth; - - /* If we're creating anchor, this tells us where to source it */ - struct anchor_input *input; - - /* If we created it, we keep entire tx. */ - const struct bitcoin_tx *tx; - - /* Depth to trigger anchor if still opening, or -1. */ - int ok_depth; - - /* Did we create anchor? */ - bool ours; - } anchor; - - struct { - /* Their signature for our current commit sig. */ - secp256k1_ecdsa_signature theirsig; - /* The watch we have on a live commit tx. */ - struct txwatch *watch; - } cur_commit; - - /* Counter to make unique HTLC ids. */ - u64 htlc_id_counter; - - /* Mutual close info. */ - struct { - /* Our last suggested closing fee. */ - u64 our_fee; - /* If they've offered a signature, these are set: */ - secp256k1_ecdsa_signature *their_sig; - /* If their_sig is non-NULL, this is the fee. */ - u64 their_fee; - /* scriptPubKey we/they want for closing. */ - u8 *our_script, *their_script; - /* Last sent (in case we need to retransmit) */ - s64 shutdown_order, closing_order; - /* How many closing sigs have we receieved? */ - u32 sigs_in; - } closing; - - /* If we're closing on-chain */ - struct { - /* Everything (watches, resolved[], etc) tal'ed off this: - * The commit which spends the anchor tx. */ - const struct bitcoin_tx *tx; - struct sha256_double txid; - - /* If >= 0, indicates which txout is to us and to them. */ - int to_us_idx, to_them_idx; - /* Maps what txouts are HTLCs (NULL implies to_us/them_idx). */ - struct htlc **htlcs; - /* Witness scripts for each output (where appropriate) */ - const u8 **wscripts; - /* The tx which resolves each txout. */ - const struct bitcoin_tx **resolved; - } onchain; - - /* All HTLCs. */ - struct htlc_map htlcs; - - /* We only track one feechange per state: last one counts. */ - struct feechange *feechanges[FEECHANGE_STATE_INVALID]; - - /* Current ongoing packetflow */ - struct io_data *io_data; - - /* What happened. */ - struct log *log; - - /* Things we're watching for (see watches.c) */ - struct list_head watches; - - /* Timeout for collecting changes before sending commit. */ - struct oneshot *commit_timer; - - /* Private keys for dealing with this peer. */ - struct peer_secrets *secrets; - - /* Our route connection to peer: NULL until we are in normal mode. */ - struct node_connection *nc; - - /* For testing. */ - bool fake_close; - bool output_enabled; - - /* Stuff we have in common. */ - struct peer_visible_state local, remote; - - /* If we have sent a new commit tx, but not received their revocation */ - struct sha256 *their_prev_revocation_hash; - - /* this is where we will store their revocation preimages*/ - struct shachain their_preimages; - - /* High water mark for the staggered broadcast */ - u64 broadcast_index; -}; -#endif /* LIGHTNING_DAEMON_PEER_INTERNAL_H */ diff --git a/daemon/routingrpc.c b/daemon/routingrpc.c deleted file mode 100644 index 182cf3dbb..000000000 --- a/daemon/routingrpc.c +++ /dev/null @@ -1,169 +0,0 @@ -#include "jsonrpc.h" -#include "lightningd.h" -#include "log.h" -#include "routing.h" - -static void json_add_route(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - jsmntok_t *srctok, *dsttok, *basetok, *vartok, *delaytok, *minblockstok; - struct pubkey src, dst; - u32 base, var, delay, minblocks; - - if (!json_get_params(buffer, params, - "src", &srctok, - "dst", &dsttok, - "base", &basetok, - "var", &vartok, - "delay", &delaytok, - "minblocks", &minblockstok, - NULL)) { - command_fail(cmd, "Need src, dst, base, var, delay & minblocks"); - return; - } - - if (!pubkey_from_hexstr(buffer + srctok->start, - srctok->end - srctok->start, &src)) { - command_fail(cmd, "src %.*s not valid", - srctok->end - srctok->start, - buffer + srctok->start); - return; - } - - if (!pubkey_from_hexstr(buffer + dsttok->start, - dsttok->end - dsttok->start, &dst)) { - command_fail(cmd, "dst %.*s not valid", - dsttok->end - dsttok->start, - buffer + dsttok->start); - return; - } - - if (!json_tok_number(buffer, basetok, &base) - || !json_tok_number(buffer, vartok, &var) - || !json_tok_number(buffer, delaytok, &delay) - || !json_tok_number(buffer, minblockstok, &minblocks)) { - command_fail(cmd, - "base, var, delay and minblocks must be numbers"); - return; - } - - add_connection(cmd->dstate->rstate, &src, &dst, base, var, delay, minblocks); - command_success(cmd, null_response(cmd)); -} - -static const struct json_command dev_add_route_command = { - "dev-add-route", - json_add_route, - "Add route from {src} to {dst}, {base} rate in msatoshi, {var} rate in msatoshi, {delay} blocks delay and {minblocks} minimum timeout", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_add_route_command); - -static void json_getchannels(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct json_result *response = new_json_result(cmd); - struct node_map_iter it; - struct node *n; - struct node_map *nodes = cmd->dstate->rstate->nodes; - struct node_connection *c; - int num_conn, i; - - json_object_start(response, NULL); - json_array_start(response, "channels"); - for (n = node_map_first(nodes, &it); n; n = node_map_next(nodes, &it)) { - num_conn = tal_count(n->out); - for (i = 0; i < num_conn; i++){ - c = n->out[i]; - json_object_start(response, NULL); - json_add_pubkey(response, "from", &n->id); - json_add_pubkey(response, "to", &c->dst->id); - json_add_num(response, "base_fee", c->base_fee); - json_add_num(response, "proportional_fee", c->proportional_fee); - json_add_num(response, "expiry", c->delay); - json_add_bool(response, "active", c->active); - json_object_end(response); - } - } - json_array_end(response); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command getchannels_command = { - "getchannels", - json_getchannels, - "List all known channels.", - "Returns a 'channels' array with all known channels including their fees." -}; -AUTODATA(json_command, &getchannels_command); - -static void json_routefail(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - jsmntok_t *enabletok; - bool enable; - - if (!json_get_params(buffer, params, - "enable", &enabletok, - NULL)) { - command_fail(cmd, "Need enable"); - return; - } - - if (!json_tok_bool(buffer, enabletok, &enable)) { - command_fail(cmd, "enable must be true or false"); - return; - } - - log_debug(cmd->dstate->base_log, "dev-routefail: routefail %s", - enable ? "enabled" : "disabled"); - cmd->dstate->dev_never_routefail = !enable; - - command_success(cmd, null_response(cmd)); -} -static const struct json_command dev_routefail_command = { - "dev-routefail", - json_routefail, - "FAIL htlcs that we can't route if {enable}", - "Returns an empty result on success" -}; -AUTODATA(json_command, &dev_routefail_command); - -static void json_getnodes(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct json_result *response = new_json_result(cmd); - struct node *n; - struct node_map_iter i; - size_t j; - - n = node_map_first(cmd->dstate->rstate->nodes, &i); - - json_object_start(response, NULL); - json_array_start(response, "nodes"); - - while (n != NULL) { - json_object_start(response, NULL); - json_add_pubkey(response, "nodeid", &n->id); - json_array_start(response, "addresses"); - for (j=0; jaddresses); j++) { - json_add_address(response, NULL, &n->addresses[j]); - } - json_array_end(response); - json_object_end(response); - n = node_map_next(cmd->dstate->rstate->nodes, &i); - } - - json_array_end(response); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command getnodes_command = { - "getnodes", - json_getnodes, - "List all known nodes in the network.", - "Returns a 'nodes' array" -}; -AUTODATA(json_command, &getnodes_command); diff --git a/daemon/secrets.c b/daemon/secrets.c deleted file mode 100644 index 0ce9ca78c..000000000 --- a/daemon/secrets.c +++ /dev/null @@ -1,251 +0,0 @@ -#include "bitcoin/privkey.h" -#include "bitcoin/shadouble.h" -#include "bitcoin/signature.h" -#include "lightningd.h" -#include "log.h" -#include "peer.h" -#include "peer_internal.h" -#include "secrets.h" -#include "utils.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len, - secp256k1_ecdsa_signature *sig) -{ - struct sha256_double h; - - sha256_double(&h, memcheck(src, len), len); - sign_hash(dstate->privkey, &h, sig); -} - -struct peer_secrets { - /* Two private keys, one for commit txs, one for final output. */ - struct privkey commit, final; - /* Seed from which we generate revocation hashes. */ - struct sha256 revocation_seed; -}; - -void peer_sign_theircommit(const struct peer *peer, - struct bitcoin_tx *commit, - secp256k1_ecdsa_signature *sig) -{ - /* Commit tx only has one input: that of the anchor. */ - sign_tx_input(commit, 0, - NULL, - peer->anchor.witnessscript, - &peer->secrets->commit, - &peer->local.commitkey, - sig); -} - -void peer_sign_ourcommit(const struct peer *peer, - struct bitcoin_tx *commit, - secp256k1_ecdsa_signature *sig) -{ - /* Commit tx only has one input: that of the anchor. */ - sign_tx_input(commit, 0, - NULL, - peer->anchor.witnessscript, - &peer->secrets->commit, - &peer->local.commitkey, - sig); -} - -void peer_sign_spend(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *commit_witnessscript, - secp256k1_ecdsa_signature *sig) -{ - /* Spend tx only has one input: that of the commit tx. */ - sign_tx_input(spend, 0, - NULL, - commit_witnessscript, - &peer->secrets->final, - &peer->local.finalkey, - sig); -} - -void peer_sign_htlc_refund(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *htlc_witnessscript, - secp256k1_ecdsa_signature *sig) -{ - /* Spend tx only has one input: that of the commit tx. */ - sign_tx_input(spend, 0, - NULL, - htlc_witnessscript, - &peer->secrets->final, - &peer->local.finalkey, - sig); -} - -void peer_sign_htlc_fulfill(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *htlc_witnessscript, - secp256k1_ecdsa_signature *sig) -{ - /* Spend tx only has one input: that of the commit tx. */ - sign_tx_input(spend, 0, - NULL, - htlc_witnessscript, - &peer->secrets->final, - &peer->local.finalkey, - sig); -} - -void peer_sign_mutual_close(const struct peer *peer, - struct bitcoin_tx *close, - secp256k1_ecdsa_signature *sig) -{ - sign_tx_input(close, 0, - NULL, - peer->anchor.witnessscript, - &peer->secrets->commit, - &peer->local.commitkey, - sig); -} - -void peer_sign_steal_input(const struct peer *peer, - struct bitcoin_tx *spend, - size_t i, - const u8 *witnessscript, - secp256k1_ecdsa_signature *sig) -{ - /* Spend tx only has one input: that of the commit tx. */ - sign_tx_input(spend, i, - NULL, - witnessscript, - &peer->secrets->final, - &peer->local.finalkey, - sig); -} - -static void new_keypair(struct lightningd_state *dstate, - struct privkey *privkey, struct pubkey *pubkey) -{ - do { - randombytes_buf(privkey->secret.data, - sizeof(privkey->secret.data)); - } while (!pubkey_from_privkey(privkey, pubkey)); -} - -void peer_secrets_init(struct peer *peer) -{ - peer->secrets = tal(peer, struct peer_secrets); - - new_keypair(peer->dstate, &peer->secrets->commit, &peer->local.commitkey); - new_keypair(peer->dstate, &peer->secrets->final, &peer->local.finalkey); - randombytes_buf(peer->secrets->revocation_seed.u.u8, sizeof(peer->secrets->revocation_seed.u.u8)); -} - -void peer_get_revocation_preimage(const struct peer *peer, u64 index, - struct sha256 *preimage) -{ - // generate hashes in reverse order, otherwise the first hash gives away everything - shachain_from_seed(&peer->secrets->revocation_seed, 0xFFFFFFFFFFFFFFFFL - index, preimage); -} - -void peer_get_revocation_hash(const struct peer *peer, u64 index, - struct sha256 *rhash) -{ - struct sha256 preimage; - - peer_get_revocation_preimage(peer, index, &preimage); - sha256(rhash, preimage.u.u8, sizeof(preimage.u.u8)); -} - -const char *peer_secrets_for_db(const tal_t *ctx, struct peer *peer) -{ - const struct peer_secrets *ps = peer->secrets; - return tal_fmt(ctx, "x'%s', x'%s', x'%s'", - tal_hexstr(ctx, &ps->commit, sizeof(ps->commit)), - tal_hexstr(ctx, &ps->final, sizeof(ps->final)), - tal_hexstr(ctx, &ps->revocation_seed, - sizeof(ps->revocation_seed))); -} - -void peer_set_secrets_from_db(struct peer *peer, - const void *commit_privkey, - size_t commit_privkey_len, - const void *final_privkey, - size_t final_privkey_len, - const void *revocation_seed, - size_t revocation_seed_len) -{ - struct peer_secrets *ps = tal(peer, struct peer_secrets); - - assert(!peer->secrets); - peer->secrets = ps; - - if (commit_privkey_len != sizeof(ps->commit) - || final_privkey_len != sizeof(ps->final) - || revocation_seed_len != sizeof(ps->revocation_seed)) - fatal("peer_set_secrets_from_db: bad lengths %zu/%zu/%zu", - commit_privkey_len, final_privkey_len, - revocation_seed_len); - - memcpy(&ps->commit, commit_privkey, commit_privkey_len); - memcpy(&ps->final, final_privkey, final_privkey_len); - memcpy(&ps->revocation_seed, revocation_seed, revocation_seed_len); - - if (!pubkey_from_privkey(&ps->commit, &peer->local.commitkey)) - fatal("peer_set_secrets_from_db:bad commit privkey"); - if (!pubkey_from_privkey(&ps->final, &peer->local.finalkey)) - fatal("peer_set_secrets_from_db:bad final privkey"); -} - -void secrets_init(struct lightningd_state *dstate) -{ - int fd; - - dstate->privkey = tal(dstate, struct privkey); - - fd = open("privkey", O_RDONLY); - if (fd < 0) { - if (errno != ENOENT) - fatal("Failed to open privkey: %s", strerror(errno)); - - log_unusual(dstate->base_log, "Creating privkey file"); - new_keypair(dstate, dstate->privkey, &dstate->id); - - fd = open("privkey", O_CREAT|O_EXCL|O_WRONLY, 0400); - if (fd < 0) - fatal("Failed to create privkey file: %s", - strerror(errno)); - if (!write_all(fd, &dstate->privkey->secret, - sizeof(dstate->privkey->secret))) { - unlink_noerr("privkey"); - fatal("Failed to write to privkey file: %s", - strerror(errno)); - } - if (fsync(fd) != 0) - fatal("Failed to sync to privkey file: %s", - strerror(errno)); - close(fd); - - fd = open("privkey", O_RDONLY); - if (fd < 0) - fatal("Failed to reopen privkey: %s", strerror(errno)); - } - if (!read_all(fd, &dstate->privkey->secret, - sizeof(dstate->privkey->secret))) - fatal("Failed to read privkey: %s", strerror(errno)); - close(fd); - if (!pubkey_from_privkey(dstate->privkey, &dstate->id)) - fatal("Invalid privkey"); - - log_info_struct(dstate->base_log, "ID: %s", struct pubkey, &dstate->id); -} diff --git a/daemon/secrets.h b/daemon/secrets.h deleted file mode 100644 index 10abaf50b..000000000 --- a/daemon/secrets.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef LIGHTNING_DAEMON_SECRETS_H -#define LIGHTNING_DAEMON_SECRETS_H -/* Routines to handle private keys. */ -#include "config.h" -#include -#include -#include - -struct peer; -struct lightningd_state; -struct sha256; - -void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len, - secp256k1_ecdsa_signature *sig); - -void peer_sign_theircommit(const struct peer *peer, - struct bitcoin_tx *commit, - secp256k1_ecdsa_signature *sig); - -void peer_sign_ourcommit(const struct peer *peer, - struct bitcoin_tx *commit, - secp256k1_ecdsa_signature *sig); - -void peer_sign_spend(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *commit_witnessscript, - secp256k1_ecdsa_signature *sig); - -void peer_sign_htlc_refund(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *htlc_witnessscript, - secp256k1_ecdsa_signature *sig); - -void peer_sign_htlc_fulfill(const struct peer *peer, - struct bitcoin_tx *spend, - const u8 *htlc_witnessscript, - secp256k1_ecdsa_signature *sig); - -void peer_sign_mutual_close(const struct peer *peer, - struct bitcoin_tx *close, - secp256k1_ecdsa_signature *sig); - -void peer_sign_steal_input(const struct peer *peer, - struct bitcoin_tx *spend, - size_t i, - const u8 *witnessscript, - secp256k1_ecdsa_signature *sig); - -const char *peer_secrets_for_db(const tal_t *ctx, struct peer *peer); - -void peer_set_secrets_from_db(struct peer *peer, - const void *commit_privkey, - size_t commit_privkey_len, - const void *final_privkey, - size_t final_privkey_len, - const void *revocation_seed, - size_t revocation_seed_len); - -void peer_secrets_init(struct peer *peer); - -void peer_get_revocation_hash(const struct peer *peer, u64 index, - struct sha256 *rhash); -void peer_get_revocation_preimage(const struct peer *peer, u64 index, - struct sha256 *preimage); - -void secrets_init(struct lightningd_state *dstate); - -#endif /* LIGHTNING_DAEMON_SECRETS_H */ diff --git a/daemon/sphinx.c b/daemon/sphinx.c deleted file mode 100644 index e25aaf37c..000000000 --- a/daemon/sphinx.c +++ /dev/null @@ -1,479 +0,0 @@ -#include "sphinx.h" -#include "utils.h" -#include - -#include - -#include -#include -#include - -#include - -#include - -#include -#include - -#define BLINDING_FACTOR_SIZE 32 -#define SHARED_SECRET_SIZE 32 -#define NUM_STREAM_BYTES ((2 * NUM_MAX_HOPS + 2) * SECURITY_PARAMETER) -#define KEY_LEN 32 - -struct hop_params { - u8 secret[SHARED_SECRET_SIZE]; - u8 blind[BLINDING_FACTOR_SIZE]; - secp256k1_pubkey ephemeralkey; -}; - -struct keyset { - u8 pi[KEY_LEN]; - u8 mu[KEY_LEN]; - u8 rho[KEY_LEN]; - u8 gamma[KEY_LEN]; -}; - -/* Small helper to append data to a buffer and update the position - * into the buffer - */ -static void write_buffer(u8 *dst, const void *src, const size_t len, int *pos) -{ - memcpy(dst + *pos, src, len); - *pos += len; -} - -/* Read len bytes from the source at position pos into dst and update - * the position pos accordingly. - */ -static void read_buffer(void *dst, const u8 *src, const size_t len, int *pos) -{ - memcpy(dst, src + *pos, len); - *pos += len; -} - -u8 *serialize_onionpacket( - const tal_t *ctx, - const struct onionpacket *m) -{ - u8 *dst = tal_arr(ctx, u8, TOTAL_PACKET_SIZE); - - u8 der[33]; - size_t outputlen = 33; - int p = 0; - - secp256k1_ec_pubkey_serialize(secp256k1_ctx, - der, - &outputlen, - &m->ephemeralkey, - SECP256K1_EC_COMPRESSED); - - write_buffer(dst, &m->version, 1, &p); - write_buffer(dst, der, outputlen, &p); - write_buffer(dst, m->mac, sizeof(m->mac), &p); - write_buffer(dst, m->routinginfo, ROUTING_INFO_SIZE, &p); - write_buffer(dst, m->hoppayloads, TOTAL_HOP_PAYLOAD_SIZE, &p); - return dst; -} - -struct onionpacket *parse_onionpacket( - const tal_t *ctx, - const void *src, - const size_t srclen - ) -{ - struct onionpacket *m; - int p = 0; - u8 rawEphemeralkey[33]; - - if (srclen != TOTAL_PACKET_SIZE) - return NULL; - - m = talz(ctx, struct onionpacket); - - read_buffer(&m->version, src, 1, &p); - if (m->version != 0x01) { - // FIXME add logging - return tal_free(m); - } - read_buffer(rawEphemeralkey, src, 33, &p); - - if (secp256k1_ec_pubkey_parse(secp256k1_ctx, &m->ephemeralkey, rawEphemeralkey, 33) != 1) - return tal_free(m); - - read_buffer(&m->mac, src, 20, &p); - read_buffer(&m->routinginfo, src, ROUTING_INFO_SIZE, &p); - read_buffer(&m->hoppayloads, src, TOTAL_HOP_PAYLOAD_SIZE, &p); - return m; -} - -static struct hoppayload *parse_hoppayload(const tal_t *ctx, u8 *src) -{ - int p = 0; - struct hoppayload *result = talz(ctx, struct hoppayload); - - read_buffer(&result->realm, src, sizeof(result->realm), &p); - read_buffer(&result->amt_to_forward, - src, sizeof(result->amt_to_forward), &p); - read_buffer(&result->outgoing_cltv_value, - src, sizeof(result->outgoing_cltv_value), &p); - read_buffer(&result->unused_with_v0_version_on_header, - src, sizeof(result->unused_with_v0_version_on_header), &p); - return result; -} - -static void serialize_hoppayload(u8 *dst, struct hoppayload *hp) -{ - int p = 0; - - write_buffer(dst, &hp->realm, sizeof(hp->realm), &p); - write_buffer(dst, &hp->amt_to_forward, sizeof(hp->amt_to_forward), &p); - write_buffer(dst, &hp->outgoing_cltv_value, - sizeof(hp->outgoing_cltv_value), &p); - write_buffer(dst, &hp->unused_with_v0_version_on_header, - sizeof(hp->unused_with_v0_version_on_header), &p); -} - - -static void xorbytes(uint8_t *d, const uint8_t *a, const uint8_t *b, size_t len) -{ - size_t i; - - for (i = 0; i < len; i++) - d[i] = a[i] ^ b[i]; -} - -/* - * Generate a pseudo-random byte stream of length `dstlen` from key `k` and - * store it in `dst`. `dst must be at least `dstlen` bytes long. - */ -static void generate_cipher_stream(void *dst, const u8 *k, size_t dstlen) -{ - u8 nonce[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - crypto_stream_chacha20(dst, dstlen, nonce, k); -} - -static bool compute_hmac( - void *dst, - const void *src, - size_t len, - const void *key, - size_t keylen) -{ - crypto_auth_hmacsha256_state state; - - crypto_auth_hmacsha256_init(&state, key, keylen); - crypto_auth_hmacsha256_update(&state, memcheck(src, len), len); - crypto_auth_hmacsha256_final(&state, dst); - return true; -} - -static void compute_packet_hmac(const struct onionpacket *packet, - const u8 *assocdata, const size_t assocdatalen, - u8 *mukey, u8 *hmac) -{ - u8 mactemp[ROUTING_INFO_SIZE + TOTAL_HOP_PAYLOAD_SIZE + assocdatalen]; - u8 mac[32]; - int pos = 0; - - write_buffer(mactemp, packet->routinginfo, ROUTING_INFO_SIZE, &pos); - write_buffer(mactemp, packet->hoppayloads, TOTAL_HOP_PAYLOAD_SIZE, &pos); - write_buffer(mactemp, assocdata, assocdatalen, &pos); - - compute_hmac(mac, mactemp, sizeof(mactemp), mukey, KEY_LEN); - memcpy(hmac, mac, 20); -} - -static bool generate_key(void *k, const char *t, u8 tlen, const u8 *s) -{ - return compute_hmac(k, s, KEY_LEN, t, tlen); -} - -static bool generate_header_padding( - void *dst, size_t dstlen, - const size_t hopsize, - const char *keytype, - size_t keytypelen, - const u8 numhops, - struct hop_params *params - ) -{ - int i; - u8 cipher_stream[(NUM_MAX_HOPS + 1) * hopsize]; - u8 key[KEY_LEN]; - - memset(dst, 0, dstlen); - for (i = 1; i < numhops; i++) { - if (!generate_key(&key, keytype, keytypelen, params[i - 1].secret)) - return false; - - generate_cipher_stream(cipher_stream, key, sizeof(cipher_stream)); - int pos = ((NUM_MAX_HOPS - i) + 1) * hopsize; - xorbytes(dst, dst, cipher_stream + pos, sizeof(cipher_stream) - pos); - } - return true; -} - -static void compute_blinding_factor(const secp256k1_pubkey *key, - const u8 sharedsecret[SHARED_SECRET_SIZE], - u8 res[BLINDING_FACTOR_SIZE]) -{ - struct sha256_ctx ctx; - u8 der[33]; - size_t outputlen = 33; - struct sha256 temp; - - secp256k1_ec_pubkey_serialize(secp256k1_ctx, der, &outputlen, key, - SECP256K1_EC_COMPRESSED); - sha256_init(&ctx); - sha256_update(&ctx, der, sizeof(der)); - sha256_update(&ctx, sharedsecret, SHARED_SECRET_SIZE); - sha256_done(&ctx, &temp); - memcpy(res, &temp, 32); -} - -static bool blind_group_element( - secp256k1_pubkey *blindedelement, - const secp256k1_pubkey *pubkey, - const u8 blind[BLINDING_FACTOR_SIZE]) -{ - /* tweak_mul is inplace so copy first. */ - if (pubkey != blindedelement) - *blindedelement = *pubkey; - if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, blindedelement, blind) != 1) - return false; - return true; -} - -static bool create_shared_secret( - u8 *secret, - const secp256k1_pubkey *pubkey, - const u8 *sessionkey) -{ - - if (secp256k1_ecdh(secp256k1_ctx, secret, pubkey, sessionkey) != 1) - return false; - return true; -} - -bool onion_shared_secret( - u8 *secret, - const struct onionpacket *packet, - const struct privkey *privkey) -{ - return create_shared_secret(secret, &packet->ephemeralkey, - privkey->secret.data); -} - -static void generate_key_set(const u8 secret[SHARED_SECRET_SIZE], - struct keyset *keys) -{ - generate_key(keys->rho, "rho", 3, secret); - generate_key(keys->pi, "pi", 2, secret); - generate_key(keys->mu, "mu", 2, secret); - generate_key(keys->gamma, "gamma", 5, secret); -} - -static struct hop_params *generate_hop_params( - const tal_t *ctx, - const u8 *sessionkey, - struct pubkey path[]) -{ - int i, j, num_hops = tal_count(path); - secp256k1_pubkey temp; - u8 blind[BLINDING_FACTOR_SIZE]; - struct hop_params *params = tal_arr(ctx, struct hop_params, num_hops); - - /* Initialize the first hop with the raw information */ - if (secp256k1_ec_pubkey_create( - secp256k1_ctx, ¶ms[0].ephemeralkey, sessionkey) != 1) - return NULL; - - if (!create_shared_secret( - params[0].secret, &path[0].pubkey, sessionkey)) - return NULL; - - compute_blinding_factor( - ¶ms[0].ephemeralkey, params[0].secret, - params[0].blind); - - /* Recursively compute all following ephemeral public keys, - * secrets and blinding factors - */ - for (i = 1; i < num_hops; i++) { - if (!blind_group_element( - ¶ms[i].ephemeralkey, - ¶ms[i - 1].ephemeralkey, - params[i - 1].blind)) - return NULL; - - /* Blind this hop's point with all previous blinding factors - * Order is indifferent, multiplication is commutative. - */ - memcpy(&blind, sessionkey, 32); - temp = path[i].pubkey; - if (!blind_group_element(&temp, &temp, blind)) - return NULL; - for (j = 0; j < i; j++) - if (!blind_group_element( - &temp, - &temp, - params[j].blind)) - return NULL; - - /* Now hash temp and store it. This requires us to - * DER-serialize first and then skip the sign byte. - */ - u8 der[33]; - size_t outputlen = 33; - secp256k1_ec_pubkey_serialize( - secp256k1_ctx, der, &outputlen, &temp, - SECP256K1_EC_COMPRESSED); - struct sha256 h; - sha256(&h, der, sizeof(der)); - memcpy(¶ms[i].secret, &h, sizeof(h)); - - compute_blinding_factor( - ¶ms[i].ephemeralkey, - params[i].secret, params[i].blind); - } - return params; -} - -struct onionpacket *create_onionpacket( - const tal_t *ctx, - struct pubkey *path, - struct hoppayload hoppayloads[], - const u8 *sessionkey, - const u8 *assocdata, - const size_t assocdatalen - ) -{ - struct onionpacket *packet = talz(ctx, struct onionpacket); - int i, num_hops = tal_count(path); - u8 filler[2 * (num_hops - 1) * SECURITY_PARAMETER]; - u8 hopfiller[(num_hops - 1) * HOP_PAYLOAD_SIZE]; - struct keyset keys; - struct bitcoin_address nextaddr; - u8 nexthmac[SECURITY_PARAMETER]; - u8 stream[ROUTING_INFO_SIZE], hopstream[TOTAL_HOP_PAYLOAD_SIZE]; - struct hop_params *params = generate_hop_params(ctx, sessionkey, path); - u8 binhoppayloads[tal_count(path)][HOP_PAYLOAD_SIZE]; - - for (i = 0; i < num_hops; i++) - serialize_hoppayload(binhoppayloads[i], &hoppayloads[i]); - - if (!params) - return NULL; - packet->version = 1; - memset(&nextaddr, 0, 20); - memset(nexthmac, 0, 20); - memset(packet->routinginfo, 0, ROUTING_INFO_SIZE); - - generate_header_padding(filler, sizeof(filler), 2 * SECURITY_PARAMETER, - "rho", 3, num_hops, params); - generate_header_padding(hopfiller, sizeof(hopfiller), HOP_PAYLOAD_SIZE, - "gamma", 5, num_hops, params); - - for (i = num_hops - 1; i >= 0; i--) { - generate_key_set(params[i].secret, &keys); - generate_cipher_stream(stream, keys.rho, ROUTING_INFO_SIZE); - - /* Rightshift mix-header by 2*SECURITY_PARAMETER */ - memmove(packet->routinginfo + 2 * SECURITY_PARAMETER, packet->routinginfo, - ROUTING_INFO_SIZE - 2 * SECURITY_PARAMETER); - memcpy(packet->routinginfo, &nextaddr, SECURITY_PARAMETER); - memcpy(packet->routinginfo + SECURITY_PARAMETER, nexthmac, SECURITY_PARAMETER); - xorbytes(packet->routinginfo, packet->routinginfo, stream, ROUTING_INFO_SIZE); - - /* Rightshift hop-payloads and obfuscate */ - memmove(packet->hoppayloads + HOP_PAYLOAD_SIZE, packet->hoppayloads, - TOTAL_HOP_PAYLOAD_SIZE - HOP_PAYLOAD_SIZE); - memcpy(packet->hoppayloads, binhoppayloads[i], HOP_PAYLOAD_SIZE); - generate_cipher_stream(hopstream, keys.gamma, TOTAL_HOP_PAYLOAD_SIZE); - xorbytes(packet->hoppayloads, packet->hoppayloads, hopstream, - TOTAL_HOP_PAYLOAD_SIZE); - - if (i == num_hops - 1) { - size_t len = (NUM_MAX_HOPS - num_hops + 1) * 2 * SECURITY_PARAMETER; - memcpy(packet->routinginfo + len, filler, sizeof(filler)); - len = (NUM_MAX_HOPS - num_hops + 1) * HOP_PAYLOAD_SIZE; - memcpy(packet->hoppayloads + len, hopfiller, sizeof(hopfiller)); - } - - compute_packet_hmac(packet, assocdata, assocdatalen, keys.mu, - nexthmac); - pubkey_to_hash160(&path[i], &nextaddr.addr); - } - memcpy(packet->mac, nexthmac, sizeof(nexthmac)); - memcpy(&packet->ephemeralkey, ¶ms[0].ephemeralkey, sizeof(secp256k1_pubkey)); - return packet; -} - -/* - * Given a onionpacket msg extract the information for the current - * node and unwrap the remainder so that the node can forward it. - */ -struct route_step *process_onionpacket( - const tal_t *ctx, - const struct onionpacket *msg, - const u8 *shared_secret, - const u8 *assocdata, - const size_t assocdatalen - ) -{ - struct route_step *step = talz(ctx, struct route_step); - u8 hmac[20]; - struct keyset keys; - u8 paddedhoppayloads[TOTAL_HOP_PAYLOAD_SIZE + HOP_PAYLOAD_SIZE]; - u8 hopstream[TOTAL_HOP_PAYLOAD_SIZE + HOP_PAYLOAD_SIZE]; - u8 blind[BLINDING_FACTOR_SIZE]; - u8 stream[NUM_STREAM_BYTES]; - u8 paddedheader[ROUTING_INFO_SIZE + 2 * SECURITY_PARAMETER]; - - step->next = talz(step, struct onionpacket); - step->next->version = msg->version; - generate_key_set(shared_secret, &keys); - - compute_packet_hmac(msg, assocdata, assocdatalen, keys.mu, hmac); - - if (memcmp(msg->mac, hmac, sizeof(hmac)) != 0) { - warnx("Computed MAC does not match expected MAC, the message was modified."); - return tal_free(step); - } - - //FIXME:store seen secrets to avoid replay attacks - generate_cipher_stream(stream, keys.rho, sizeof(stream)); - - memset(paddedheader, 0, sizeof(paddedheader)); - memcpy(paddedheader, msg->routinginfo, ROUTING_INFO_SIZE); - xorbytes(paddedheader, paddedheader, stream, sizeof(stream)); - - /* Extract the per-hop payload */ - generate_cipher_stream(hopstream, keys.gamma, sizeof(hopstream)); - - memset(paddedhoppayloads, 0, sizeof(paddedhoppayloads)); - memcpy(paddedhoppayloads, msg->hoppayloads, TOTAL_HOP_PAYLOAD_SIZE); - xorbytes(paddedhoppayloads, paddedhoppayloads, hopstream, sizeof(hopstream)); - step->hoppayload = parse_hoppayload(step, paddedhoppayloads); - memcpy(&step->next->hoppayloads, paddedhoppayloads + HOP_PAYLOAD_SIZE, - TOTAL_HOP_PAYLOAD_SIZE); - - compute_blinding_factor(&msg->ephemeralkey, shared_secret, blind); - if (!blind_group_element(&step->next->ephemeralkey, &msg->ephemeralkey, blind)) - return tal_free(step); - memcpy(&step->next->nexthop, paddedheader, SECURITY_PARAMETER); - memcpy(&step->next->mac, - paddedheader + SECURITY_PARAMETER, - SECURITY_PARAMETER); - - memcpy(&step->next->routinginfo, paddedheader + 2 * SECURITY_PARAMETER, ROUTING_INFO_SIZE); - - if (memeqzero(step->next->mac, sizeof(step->next->mac))) { - step->nextcase = ONION_END; - } else { - step->nextcase = ONION_FORWARD; - } - - return step; -} diff --git a/daemon/sphinx.h b/daemon/sphinx.h deleted file mode 100644 index 61c9c6479..000000000 --- a/daemon/sphinx.h +++ /dev/null @@ -1,136 +0,0 @@ -#ifndef LIGHTNING_DAEMON_SPHINX_H -#define LIGHTNING_DAEMON_SPHINX_H - -#include "config.h" -#include "bitcoin/privkey.h" -#include "bitcoin/pubkey.h" - -#include -#include -#include -#include - -#define SECURITY_PARAMETER 20 -#define NUM_MAX_HOPS 20 -#define HOP_PAYLOAD_SIZE 20 -#define TOTAL_HOP_PAYLOAD_SIZE (NUM_MAX_HOPS * HOP_PAYLOAD_SIZE) -#define ROUTING_INFO_SIZE (2 * NUM_MAX_HOPS * SECURITY_PARAMETER) -#define TOTAL_PACKET_SIZE (1 + 33 + SECURITY_PARAMETER + ROUTING_INFO_SIZE + \ - TOTAL_HOP_PAYLOAD_SIZE) - -struct onionpacket { - /* Cleartext information */ - u8 version; - u8 nexthop[20]; - u8 mac[20]; - secp256k1_pubkey ephemeralkey; - - /* Encrypted information */ - u8 routinginfo[ROUTING_INFO_SIZE]; - u8 hoppayloads[TOTAL_HOP_PAYLOAD_SIZE]; -}; - -enum route_next_case { - ONION_END = 0, - ONION_FORWARD = 1, -}; - -/* FIXME-OLD #4: - * - * The format of the per-hop-payload for a version 0 packet is as follows: -``` -+----------------+--------------------------+-------------------------------+--------------------------------------------+ -| realm (1 byte) | amt_to_forward (8 bytes) | outgoing_cltv_value (4 bytes) | unused_with_v0_version_on_header (7 bytes) | -+----------------+--------------------------+-------------------------------+--------------------------------------------+ -``` -*/ -struct hoppayload { - u8 realm; - u64 amt_to_forward; - u32 outgoing_cltv_value; - u8 unused_with_v0_version_on_header[7]; -}; - -struct route_step { - enum route_next_case nextcase; - struct onionpacket *next; - struct hoppayload *hoppayload; -}; - -/** - * create_onionpacket - Create a new onionpacket that can be routed - * over a path of intermediate nodes. - * - * @ctx: tal context to allocate from - * @path: public keys of nodes along the path. - * @hoppayloads: payloads destined for individual hosts (limited to - * HOP_PAYLOAD_SIZE bytes) - * @num_hops: path length in nodes - * @sessionkey: 20 byte random session key to derive secrets from - * @assocdata: associated data to commit to in HMACs - * @assocdatalen: length of the assocdata - */ -struct onionpacket *create_onionpacket( - const tal_t * ctx, - struct pubkey path[], - struct hoppayload hoppayloads[], - const u8 * sessionkey, - const u8 *assocdata, - const size_t assocdatalen - ); - -/** - * onion_shared_secret - calculate ECDH shared secret between nodes. - * - * @secret: the shared secret (32 bytes long) - * @pubkey: the public key of the other node - * @privkey: the private key of this node (32 bytes long) - */ -bool onion_shared_secret( - u8 *secret, - const struct onionpacket *packet, - const struct privkey *privkey); - -/** - * process_onionpacket - process an incoming packet by stripping one - * onion layer and return the packet for the next hop. - * - * @ctx: tal context to allocate from - * @packet: incoming packet being processed - * @shared_secret: the result of onion_shared_secret. - * @hoppayload: the per-hop payload destined for the processing node. - * @assocdata: associated data to commit to in HMACs - * @assocdatalen: length of the assocdata - */ -struct route_step *process_onionpacket( - const tal_t * ctx, - const struct onionpacket *packet, - const u8 *shared_secret, - const u8 *assocdata, - const size_t assocdatalen - ); - -/** - * serialize_onionpacket - Serialize an onionpacket to a buffer. - * - * @ctx: tal context to allocate from - * @packet: the packet to serialize - */ -u8 *serialize_onionpacket( - const tal_t *ctx, - const struct onionpacket *packet); - -/** - * parese_onionpacket - Parse an onionpacket from a buffer. - * - * @ctx: tal context to allocate from - * @src: buffer to read the packet from - * @srclen: length of the @src - */ -struct onionpacket *parse_onionpacket( - const tal_t *ctx, - const void *src, - const size_t srclen - ); - -#endif /* LIGHTNING_DAEMON_SPHINX_H */ diff --git a/daemon/state.h b/daemon/state.h deleted file mode 100644 index f709ebb01..000000000 --- a/daemon/state.h +++ /dev/null @@ -1,77 +0,0 @@ -#ifndef LIGHTNING_DAEMON_STATE_H -#define LIGHTNING_DAEMON_STATE_H -#include "config.h" - -#include "daemon/state_types.h" -#include - -static inline bool state_is_error(enum state s) -{ - return s >= STATE_ERR_BREAKDOWN && s <= STATE_ERR_INTERNAL; -} - -static inline bool state_is_shutdown(enum state s) -{ - return s == STATE_SHUTDOWN || s == STATE_SHUTDOWN_COMMITTING; -} - -static inline bool state_is_onchain(enum state s) -{ - return s >= STATE_CLOSE_ONCHAIN_CHEATED - && s <= STATE_CLOSE_ONCHAIN_MUTUAL; -} - -static inline bool state_is_normal(enum state s) -{ - return s == STATE_NORMAL || s == STATE_NORMAL_COMMITTING; -} - -static inline bool state_is_waiting_for_anchor(enum state s) -{ - return s == STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - || s == STATE_OPEN_WAIT_ANCHORDEPTH; -} - -static inline bool state_is_openwait(enum state s) -{ - return s == STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - || s == STATE_OPEN_WAIT_ANCHORDEPTH - || s == STATE_OPEN_WAIT_THEIRCOMPLETE; -} - -static inline bool state_is_opening(enum state s) -{ - return s <= STATE_OPEN_WAIT_THEIRCOMPLETE; -} - -static inline bool state_can_io(enum state s) -{ - if (state_is_error(s)) - return false; - if (s == STATE_CLOSED) - return false; - if (state_is_onchain(s)) - return false; - return true; -} - -static inline bool state_can_commit(enum state s) -{ - return s == STATE_NORMAL || s == STATE_SHUTDOWN; -} - -/* FIXME-OLD #2: - * - * A node MUST NOT send a `update_add_htlc` after a `close_shutdown` - */ -static inline bool state_can_add_htlc(enum state s) -{ - return state_is_normal(s); -} - -static inline bool state_can_remove_htlc(enum state s) -{ - return state_is_normal(s) || state_is_shutdown(s); -} - -#endif /* LIGHTNING_STATE_H */ diff --git a/daemon/state_types.h b/daemon/state_types.h deleted file mode 100644 index b6b1120ec..000000000 --- a/daemon/state_types.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef LIGHTNING_STATE_TYPES_H -#define LIGHTNING_STATE_TYPES_H -#include "config.h" -/* FIXME: cdump is really dumb, so we put these in their own header. */ -#include "lightning.pb-c.h" - -enum state { - STATE_INIT, - - /* - * Opening. - */ - STATE_OPEN_WAIT_FOR_OPENPKT, - STATE_OPEN_WAIT_FOR_ANCHORPKT, - STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT, - - /* We're waiting for depth+their complete. */ - STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, - /* Got their pkt_complete. */ - STATE_OPEN_WAIT_ANCHORDEPTH, - /* Got anchor depth. */ - STATE_OPEN_WAIT_THEIRCOMPLETE, - - /* - * Normal state. - */ - STATE_NORMAL, - STATE_NORMAL_COMMITTING, - - /* - * Closing (handled outside state machine). - */ - STATE_SHUTDOWN, - STATE_SHUTDOWN_COMMITTING, - STATE_MUTUAL_CLOSING, - - /* Four states to represent closing onchain (for getpeers) */ - STATE_CLOSE_ONCHAIN_CHEATED, - STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL, - STATE_CLOSE_ONCHAIN_OUR_UNILATERAL, - STATE_CLOSE_ONCHAIN_MUTUAL, - - /* All closed. */ - STATE_CLOSED, - - /* - * Where angels fear to tread. - */ - /* Bad packet from them / protocol breakdown. */ - STATE_ERR_BREAKDOWN, - /* The anchor didn't reach blockchain in reasonable time. */ - STATE_ERR_ANCHOR_TIMEOUT, - /* We saw a tx we didn't sign. */ - STATE_ERR_INFORMATION_LEAK, - /* We ended up in an unexpected state. */ - STATE_ERR_INTERNAL, - - STATE_MAX -}; - -enum state_input { - /* - * Packet inputs. - */ - PKT_OPEN = PKT__PKT_OPEN, - PKT_OPEN_ANCHOR = PKT__PKT_OPEN_ANCHOR, - PKT_OPEN_COMMIT_SIG = PKT__PKT_OPEN_COMMIT_SIG, - PKT_OPEN_COMPLETE = PKT__PKT_OPEN_COMPLETE, - - /* Updating the commit transaction: new HTLC */ - PKT_UPDATE_ADD_HTLC = PKT__PKT_UPDATE_ADD_HTLC, - /* Updating the commit transaction: I have your R value! */ - PKT_UPDATE_FULFILL_HTLC = PKT__PKT_UPDATE_FULFILL_HTLC, - /* Updating the commit transaction: your HTLC failed upstream */ - PKT_UPDATE_FAIL_HTLC = PKT__PKT_UPDATE_FAIL_HTLC, - - /* Committing updates */ - PKT_UPDATE_COMMIT = PKT__PKT_UPDATE_COMMIT, - PKT_UPDATE_REVOCATION = PKT__PKT_UPDATE_REVOCATION, - - /* If they want to close. */ - PKT_CLOSE_SHUTDOWN = PKT__PKT_CLOSE_SHUTDOWN, - - /* Something unexpected went wrong. */ - PKT_ERROR = PKT__PKT_ERROR, - - /* - * Non-packet inputs. - */ - INPUT_NONE, - - /* - * Timeouts. - */ - INPUT_CLOSE_COMPLETE_TIMEOUT, - - INPUT_MAX -}; -#endif /* LIGHTNING_STATE_TYPES_H */ diff --git a/daemon/test/Makefile b/daemon/test/Makefile deleted file mode 100644 index f22fe7025..000000000 --- a/daemon/test/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -check: daemon-tests - -# We run three different bitcoinds, for different types of tests. -# Provides limited paralellism. -daemon-test-0-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=0 daemon/test/test-$* -daemon-test-1-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=1 daemon/test/test-$* -daemon-test-2-%: - NO_VALGRIND=$(NO_VALGRIND) VARIANT=2 daemon/test/test-$* - -# These don't work in parallel, so chain the deps -daemon-test-0-steal: daemon-test-0-unilateral -daemon-test-0-unilateral: daemon-test-0-funding-timeout -daemon-test-0-funding-timeout: daemon-test-0-mutual-close-with-htlcs -daemon-test-0-mutual-close-with-htlcs: daemon-test-0-different-fees -daemon-test-0-different-fees: daemon-test-0-routing -daemon-test-0-routing: daemon-test-0-invoice -daemon-test-0-invoice: daemon-test-0-basic\ manual-commit -daemon-test-0-basic\ manual-commit: daemon-test-0-basic -daemon-test-0-basic: daemon-test-setup-0 - -daemon-test-2-steal\ --reconnect: daemon-test-2-unilateral\ --reconnect -daemon-test-2-unilateral\ --reconnect: daemon-test-2-funding-timeout\ --reconnect -daemon-test-2-funding-timeout\ --reconnect: daemon-test-2-mutual-close-with-htlcs\ --reconnect -daemon-test-2-mutual-close-with-htlcs\ --reconnect: daemon-test-2-different-fees\ --reconnect -daemon-test-2-different-fees\ --reconnect: daemon-test-2-routing\ --reconnect -daemon-test-2-routing\ --reconnect: daemon-test-2-invoice\ --reconnect -daemon-test-2-invoice\ --reconnect: daemon-test-2-basic\ manual-commit\ --reconnect -daemon-test-2-basic\ manual-commit\ --reconnect: daemon-test-2-basic\ --reconnect -daemon-test-2-basic\ --reconnect: daemon-test-setup-2 - -daemon-test-1-steal\ --restart: daemon-test-1-unilateral\ --restart -daemon-test-1-unilateral\ --restart: daemon-test-1-funding-timeout\ --restart -daemon-test-1-funding-timeout\ --restart: daemon-test-1-mutual-close-with-htlcs\ --restart -daemon-test-1-mutual-close-with-htlcs\ --restart: daemon-test-1-different-fees\ --restart -daemon-test-1-different-fees\ --restart: daemon-test-1-routing\ --restart -daemon-test-1-routing\ --restart: daemon-test-1-invoice\ --restart -daemon-test-1-invoice\ --restart: daemon-test-1-basic\ manual-commit\ --restart -daemon-test-1-basic\ manual-commit\ --restart: daemon-test-1-basic\ --restart -daemon-test-1-basic\ --restart: daemon-test-setup-1 - -# We shutdown first in case something is left over. -daemon-test-setup-%: daemon-all - VARIANT=$* daemon/test/scripts/shutdown.sh 2>/dev/null || true - VARIANT=$* daemon/test/scripts/setup.sh - -daemon-test-shutdown-0: daemon-test-0-steal - VARIANT=0 daemon/test/scripts/shutdown.sh -daemon-test-shutdown-1: daemon-test-1-steal\ --restart - VARIANT=1 daemon/test/scripts/shutdown.sh -daemon-test-shutdown-2: daemon-test-2-steal\ --reconnect - VARIANT=2 daemon/test/scripts/shutdown.sh - -# Forms long dependency chains. -daemon-all-test: daemon-test-shutdown-0 daemon-test-shutdown-1 daemon-test-shutdown-2 - -# Note that these actually #include everything they need, except ccan/ and bitcoin/. -# That allows for unit testing of statics, and special effects. -DAEMON_TEST_SRC := $(wildcard daemon/test/run-*.c) -DAEMON_TEST_OBJS := $(DAEMON_TEST_SRC:.c=.o) -DAEMON_TEST_PROGRAMS := $(DAEMON_TEST_OBJS:.o=) - -update-mocks: $(DAEMON_TEST_SRC:%=update-mocks/%) - -$(DAEMON_TEST_PROGRAMS): $(CCAN_OBJS) $(BITCOIN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(CORE_PROTOBUF_OBJS) $(LIBBASE58_OBJS) $(WIRE_OBJS) libsecp256k1.a libsodium.a utils.o - -$(DAEMON_TEST_OBJS): $(DAEMON_HEADERS) $(DAEMON_JSMN_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(CORE_TX_HEADERS) $(GEN_HEADERS) $(DAEMON_GEN_HEADERS) $(CCAN_HEADERS) $(WIRE_HEADERS) - -daemon-unit-tests: $(DAEMON_TEST_PROGRAMS:%=unittest/%) - -daemon-tests: daemon-unit-tests daemon-all-test - diff --git a/daemon/test/run-maxfee.c b/daemon/test/run-maxfee.c deleted file mode 100644 index 89eb519f8..000000000 --- a/daemon/test/run-maxfee.c +++ /dev/null @@ -1,52 +0,0 @@ -#include "daemon/channel.c" -#include "daemon/htlc.c" -#include "daemon/htlc_state.c" -#include -#include - -/* AUTOGENERATED MOCKS START */ -/* Generated stub for db_new_htlc */ -void db_new_htlc(struct peer *peer UNNEEDED, const struct htlc *htlc UNNEEDED) -{ fprintf(stderr, "db_new_htlc called!\n"); abort(); } -/* Generated stub for db_update_htlc_state */ -void db_update_htlc_state(struct peer *peer UNNEEDED, const struct htlc *htlc UNNEEDED, - enum htlc_state oldstate UNNEEDED) -{ fprintf(stderr, "db_update_htlc_state called!\n"); abort(); } -/* Generated stub for log_ */ -void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...) - -{ fprintf(stderr, "log_ called!\n"); abort(); } -/* Generated stub for peer_debug */ -void peer_debug(struct peer *peer UNNEEDED, const char *fmt UNNEEDED, ...) - -{ fprintf(stderr, "peer_debug called!\n"); abort(); } -/* Could not find declaration for tal_hexstr */ -/* Could not find declaration for type_to_string_ */ -/* AUTOGENERATED MOCKS END */ - -static void test_maxfee(size_t htlcs, u64 funds) -{ - struct channel_state cstate; - uint64_t maxrate; - - cstate.side[LOCAL].pay_msat = funds; - cstate.side[LOCAL].fee_msat = 0; - cstate.num_nondust = htlcs; - - maxrate = approx_max_feerate(&cstate, LOCAL); - assert(fee_by_feerate(tx_bytes(htlcs), maxrate) <= funds); -} - -int main(void) -{ - size_t htlcs, i; - for (htlcs = 0; htlcs < 600; htlcs++) { - for (i = 0; i < 32; i++) { - test_maxfee(htlcs, i); - test_maxfee(htlcs, 1ULL << i); - test_maxfee(htlcs, (1ULL << i) - 1); - test_maxfee(htlcs, (1ULL << i) + 1); - } - } - return 0; -} diff --git a/daemon/test/scripts/generate-block.sh b/daemon/test/scripts/generate-block.sh deleted file mode 100755 index 2b5f3820e..000000000 --- a/daemon/test/scripts/generate-block.sh +++ /dev/null @@ -1,21 +0,0 @@ -#! /bin/sh -# Generate a block. - -set -e - -. `dirname $0`/vars.sh -INIT=$1 - -# Initially we need 100 blocks so coinbase matures, giving us funds. -if [ -n "$INIT" ]; then - # To activate segwit via BIP9, we need at least 432 blocks! - $CLI generate 432 > /dev/null - if $CLI getblockchaininfo | tr -s '\012\011 ' ' ' | grep -q '"segwit": { "status": "active",'; then : - else - echo "Segwit not activated after 432 blocks?" >&2 - $CLI getblockchaininfo >&2 - exit 1 - fi -else - $CLI generate 1 > /dev/null -fi diff --git a/daemon/test/scripts/getinput.sh b/daemon/test/scripts/getinput.sh deleted file mode 100755 index c2f046f87..000000000 --- a/daemon/test/scripts/getinput.sh +++ /dev/null @@ -1,29 +0,0 @@ -#! /bin/sh -# Query bitcoind to get (first) unspent output to spend. - -### -# Nobody should *EVER* write code like this. EVER!! -### -set -e - -. `dirname $0`/vars.sh - -NUM=1 -if [ $# = 1 ]; then - NUM=$1 - shift -fi - -if [ $# -gt 0 ]; then - echo "Usage: getinput.sh [INPUT-INDEX]" - exit 1 -fi - -TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` -OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1` -AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'` -SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` -ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1` -PRIVKEY=`$CLI dumpprivkey $ADDR` - -echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT/$PRIVKEY diff --git a/daemon/test/scripts/helpers.sh b/daemon/test/scripts/helpers.sh deleted file mode 100644 index f4a6699a4..000000000 --- a/daemon/test/scripts/helpers.sh +++ /dev/null @@ -1,467 +0,0 @@ -#! /bin/sh -# Sourced by test script. - -# Takes the number of lightningd's we're going to start (2 or 3), then args -parse_cmdline() -{ - NUM_LIGHTNINGD=$1 - shift - - DIR1=/tmp/lightning.$$.1 - DIR2=/tmp/lightning.$$.2 - REDIR1="$DIR1/output" - REDIR2="$DIR2/output" - REDIRERR1="$DIR1/errors" - REDIRERR2="$DIR2/errors" - - if [ $NUM_LIGHTNINGD = 3 ]; then - DIR3=/tmp/lightning.$$.3 - REDIR3="$DIR3/output" - REDIRERR3="$DIR3/errors" - fi - - while [ $# != 0 ]; do - case x"$1" in - x"--valgrind-vgdb") - [ -n "$NO_VALGRIND" ] || PREFIX="$PREFIX --vgdb-error=1" - REDIR1="/dev/tty" - REDIRERR1="/dev/tty" - REDIR2="/dev/tty" - REDIRERR2="/dev/tty" - if [ $NUM_LIGHTNINGD = 3 ]; then - REDIR3="/dev/tty" - REDIRERR3="/dev/tty" - fi - ;; - x"--gdb1") - GDB1=1 - ;; - x"--gdb2") - GDB2=1 - ;; - x"--gdb3") - GDB3=1 - if [ $NUM_LIGHTNINGD -lt 3 ]; then - echo "$1" invalid with only 2 lightning daemons >&2 - exit 1 - fi - ;; - x"--gdb1="*) - DAEMON1_EXTRA=--dev-debugger=${1#--gdb1=} - ;; - x"--gdb2="*) - DAEMON2_EXTRA=--dev-debugger=${1#--gdb2=} - ;; - x"--reconnect") - RECONNECT=reconnect - ;; - x"--restart") - RECONNECT=restart - ;; - x"--crash") - CRASH_ON_FAIL=1 - ;; - x"--verbose") - VERBOSE=1 - ;; - *) - echo Unknown arg "$1" >&2 - exit 1 - esac - shift - done - - if [ -n "$VERBOSE" ]; then - FGREP="fgrep" - else - FGREP="fgrep -q" - # Suppress command output. - exec >/dev/null - fi -} - -failed() -{ - if [ -n "$CRASH_ON_FAIL" ]; then - $LCLI1 dev-crash 2>/dev/null || true - $LCLI2 dev-crash 2>/dev/null || true - echo -n Crash results in $DIR1 and $DIR2 >&2 - if [ -n "$LCLI3" ]; then - $LCLI3 dev-crash 2>/dev/null || true - echo and $DIR3 >&2 - else - echo >&2 - fi - fi - cat $DIR1/errors $DIR2/errors $DIR3/errors 2>/dev/null || true - exit 1 -} - -setup_lightning() -{ - NUM_LIGHTNINGD=$1 - - LCLI1="../lightning-cli --lightning-dir=$DIR1" - LCLI2="../lightning-cli --lightning-dir=$DIR2" - [ $NUM_LIGHTNINGD = 2 ] || LCLI3="../lightning-cli --lightning-dir=$DIR3" - - trap failed EXIT - mkdir $DIR1 $DIR2 - [ $NUM_LIGHTNINGD = 2 ] || mkdir $DIR3 - - cat > $DIR1/config <> $DIR2/config - [ $NUM_LIGHTNINGD = 2 ] || echo port=`findport 4010 $VARIANT` >> $DIR3/config -} - -# Use DIR REDIR REDIRERR GDBFLAG BINARY EXTRAARGS -start_one_lightningd() -{ - # Need absolute path for re-exec testing. - local CMD - CMD="$(readlink -f `pwd`/../../$5) --lightning-dir=$1" - if [ -n "$4" ]; then - echo Press return once you run: gdb --args $CMD $6 >&2 - - read REPLY - else - CMD="$PREFIX $CMD" - $CMD $6 > $2 2> $3 & - fi - echo $CMD $6 -} - -start_lightningd() -{ - NUM_LIGHTNINGD=$1 - BINARY=${2:-daemon/lightningd} - - # If bitcoind not already running, start it. - if ! $CLI getinfo >/dev/null 2>&1; then - echo Starting bitcoind... - scripts/setup.sh - SHUTDOWN_BITCOIN=scripts/shutdown.sh - else - SHUTDOWN_BITCOIN=/bin/true - fi - - LIGHTNINGD1=`start_one_lightningd $DIR1 $REDIR1 $REDIRERR1 "$GDB1" $BINARY $DAEMON1_EXTRA` - LIGHTNINGD2=`start_one_lightningd $DIR2 $REDIR2 $REDIRERR2 "$GDB2" $BINARY $DAEMON2_EXTRA` - [ $NUM_LIGHTNINGD = 2 ] || LIGHTNINGD3=`start_one_lightningd $DIR3 $REDIR3 $REDIRERR3 "$GDB3" $BINARY` - - if ! check "$LCLI1 getlog 2>/dev/null | $FGREP Hello"; then - echo Failed to start daemon 1 >&2 - exit 1 - fi - - if ! check "$LCLI2 getlog 2>/dev/null | $FGREP Hello"; then - echo Failed to start daemon 2 >&2 - exit 1 - fi - - if [ $NUM_LIGHTNINGD = 3 ] && ! check "$LCLI3 getlog 2>/dev/null | $FGREP Hello"; then - echo Failed to start daemon 3 >&2 - exit 1 - fi - - # Version should match binary version - GETINFO_VERSION=`$LCLI1 getinfo | sed -n 's/.*"version" : "\([^"]*\)".*/\1/p'` - LCLI_VERSION=$($LCLI1 --version | head -n1) - LDAEMON_VERSION=$($LIGHTNINGD1 --version | head -n1) - if [ $GETINFO_VERSION != $LCLI_VERSION -o $GETINFO_VERSION != $LDAEMON_VERSION ]; then - echo Wrong versions: getinfo gave $GETINFO_VERSION, cli gave $LCLI_VERSION, daemon gave $LDAEMON_VERSION >&2 - exit 1 - fi - - ID1=`get_info_field "$LCLI1" id` - ID2=`get_info_field "$LCLI2" id` - [ $NUM_LIGHTNINGD = 2 ] || ID3=`get_info_field "$LCLI3" id` - - PORT2=`get_info_field "$LCLI2" port` - [ $NUM_LIGHTNINGD = 2 ] || PORT3=`get_info_field "$LCLI3" port` -} - -fund_lightningd() -{ - # Make a payment into a P2SH for anchor. - P2SHADDR=`$LCLI1 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'` - FUND_INPUT_TXID=`$CLI sendtoaddress $P2SHADDR 0.01` - FUND_INPUT_TX=`$CLI getrawtransaction $FUND_INPUT_TXID` - - # Mine it so check_tx_spend doesn't see it (breaks some tests). - $CLI generate 1 -} - -lcli1() -{ - if [ -n "$VERBOSE" ]; then - echo $LCLI1 "$@" >&2 - fi - # Make sure we output if it fails; we need to capture it otherwise. - if ! OUT=`$LCLI1 "$@"`; then - echo "$OUT" - return 1 - fi - echo "$OUT" - if [ -n "$DO_RECONNECT" ]; then - case "$1" in - # Don't restart on every get* command. - get*) - ;; - dev-disconnect) - ;; - stop) - ;; - *) - case "$RECONNECT" in - reconnect) - [ -z "$VERBOSE" ] || echo RECONNECTING >&2 - $LCLI1 dev-reconnect $ID2 >/dev/null - ;; - restart) - [ -z "$VERBOSE" ] || echo RESTARTING >&2 - $LCLI1 -- dev-restart $LIGHTNINGD1 >/dev/null 2>&1 || true - if ! check "$LCLI1 getlog 2>/dev/null | fgrep -q Hello"; then - echo "dev-restart failed!">&2 - exit 1 - fi - ;; - esac - # Wait for reconnect (if peer2 still there) - if [ -z "$NO_PEER2" ] && ! check "$LCLI1 getpeers | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 - fi - - if [ "$1" = "dev-newhtlc" ]; then - # It might have gotten committed, or might be forgotten. - ID=`echo "$OUT" | extract_id` - if ! htlc_exists "$LCLI1" $2 $ID; then - if [ -z "$VERBOSE" ]; then - $LCLI1 "$@" >/dev/null 2>&1 || true - else - echo "Rerunning $LCLI1 $@" >&2 - $LCLI1 "$@" >&2 || true - fi - fi - # Make sure it's confirmed before we run next command, - # in case *that* restarts (unless manual commit) - [ -n "$MANUALCOMMIT" ] || check ! htlc_is_state \'"$LCLI1"\' $2 $ID SENT_ADD_HTLC - # Removals may also be forgotten. - elif [ "$1" = "fulfillhtlc" -o "$1" = "failhtlc" ]; then - ID="$3" - if htlc_is_state "$LCLI1" $2 $ID RCVD_ADD_ACK_REVOCATION; then - if [ -z "$VERBOSE" ]; then - $LCLI1 "$@" >/dev/null 2>&1 || true - else - echo "Rerunning $LCLI1 $@" >&2 - $LCLI1 "$@" >&2 || true - fi - # Make sure it's confirmed before we run next command, - # in case *that* restarts. - [ -n "$MANUALCOMMIT" ] || check ! htlc_is_state \'"$LCLI1"\' $2 $ID SENT_REMOVE_HTLC - fi - fi - ;; - esac - fi -} - -lcli2() -{ - if [ -n "$VERBOSE" ]; then - echo $LCLI2 "$@" >&2 - fi - $LCLI2 "$@" -} - -lcli3() -{ - if [ -n "$VERBOSE" ]; then - echo $LCLI3 "$@" >&2 - fi - $LCLI3 "$@" -} - -all_ok() -{ - # Look for valgrind errors. - if grep ^== $DIR1/errors; then exit 1; fi - if grep ^== $DIR2/errors; then exit 1; fi - [ $NUM_LIGHTNINGD = 2 ] || if grep ^== $DIR3/errors; then exit 1; fi - - # Look for unknown logging types. - if grep "UNKNOWN TYPE" $DIR1/output >&2; then exit 1; fi - if grep "UNKNOWN TYPE" $DIR2/output >&2; then exit 1; fi - [ $NUM_LIGHTNINGD = 2 ] || if grep "UNKNOWN TYPE" $DIR3/output >&2; then exit 1; fi - $SHUTDOWN_BITCOIN - - trap "rm -rf $DIR1 $DIR2 $DIR3" EXIT - exit 0 -} - -# If result is in quotes, those are stripped. Spaces in quotes not handled -get_field() -{ - tr -s '\012\011" ' ' ' | sed 's/.* '$1' : \([^, }]*\).*/\1/' -} - -# If result is in quotes, those are stripped. Spaces in quotes not handled -get_info_field() -{ - $1 getinfo | tr -s '\012\011" ' ' ' | sed 's/.* '$2' : \([^, }]*\).*/\1/' -} - -# Peer $1 -> $2's htlc $3 is in state $4 -htlc_is_state() -{ - if [ $# != 4 ]; then echo "htlc_is_state got $# ARGS: $@" >&2; exit 1; fi - $1 gethtlcs $2 true | tr -s '\012\011\" ' ' ' | $FGREP "id : $3, state : $4 ," >&2 -} - -# Peer $1 -> $2's htlc $3 exists -htlc_exists() -{ - $1 gethtlcs $2 true | tr -s '\012\011\" ' ' ' | $FGREP "id : $3," >&2 -} - -blockheight() -{ - $CLI getblockcount -} - -# Usage: ... -check() -{ - local i=0 - while ! eval "$@"; do - sleep 1 - i=$(($i + 1)) - if [ $i = 60 ]; then - return 1 - fi - done -} - -check_balance_single() -{ - lcli="$1" - us_pay=$2 - us_fee=$3 - them_pay=$4 - them_fee=$5 - - if check "$lcli getpeers | tr -s '\012\011\" ' ' ' | $FGREP \"our_amount : $us_pay, our_fee : $us_fee, their_amount : $them_pay, their_fee : $them_fee,\""; then :; else - echo Cannot find $lcli output: "our_amount : $us_pay, our_fee : $us_fee, their_amount : $them_pay, their_fee : $them_fee," >&2 - $lcli getpeers | tr -s '\012\011" ' ' ' >&2 - return 1 - fi -} - -check_status_single() -{ - lcli="$1" - us_pay=$2 - us_fee=$3 - us_htlcs="$4" - them_pay=$5 - them_fee=$6 - them_htlcs="$7" - - check_balance_single "$lcli" $us_pay $us_fee $them_pay $them_fee - - if check "$lcli getpeers | tr -s '\012\011\" ' ' ' | $FGREP \"our_htlcs : [ $us_htlcs], their_htlcs : [ $them_htlcs]\""; then :; else - echo Cannot find $lcli output: "our_htlcs : [ $us_htlcs], their_htlcs : [ $them_htlcs]" >&2 - $lcli getpeers | tr -s '\012\011" ' ' ' >&2 - return 1 - fi -} - -# SEND_ -> RCVD_ and RCVD_ -> SEND_ -swap_status() -{ - echo "$@" | sed -e 's/state : RCVD_/@@/g' -e 's/state : SENT_/state : RCVD_/g' -e 's/@@/state : SENT_/g' -} - -check_status() -{ - us_pay=$1 - us_fee=$2 - us_htlcs="$3" - them_pay=$4 - them_fee=$5 - them_htlcs="$6" - - check_status_single lcli1 "$us_pay" "$us_fee" "$us_htlcs" "$them_pay" "$them_fee" "$them_htlcs" - check_status_single lcli2 "$them_pay" "$them_fee" "`swap_status \"$them_htlcs\"`" "$us_pay" "$us_fee" "`swap_status \"$us_htlcs\"`" -} - -check_tx_spend() -{ - local FAIL - FAIL=0 - if [ $# = 1 ]; then - check "$CLI getrawmempool | $FGREP $1" || FAIL=1 - else - check "$CLI getrawmempool | $FGREP '\"'" || FAIL=1 - fi - if [ $FAIL = 1 ]; then - echo "No tx $1 in mempool:" >&2 - $CLI getrawmempool >&2 - exit 1 - fi -} - -check_peerstate() -{ - if check "$1 getpeers | $FGREP -w $2"; then : - else - echo "$1" not in state "$2": >&2 - $1 getpeers >&2 - exit 1 - fi -} - -check_peerconnected() -{ - if check "$1 getpeers | tr -s '\012\011\" ' ' ' | $FGREP -w 'connected : '$2"; then : - else - echo "$1" not connected "$2": >&2 - $1 getpeers >&2 - exit 1 - fi -} - -check_no_peers() -{ - if check "$1 getpeers | tr -s '\012\011\" ' ' ' | $FGREP 'peers : [ ]'"; then : - else - echo "$1" still has peers: >&2 - $1 getpeers >&2 - exit 1 - fi -} - -extract_id() -{ - XID=`tr -s '\012\011\" ' ' ' | sed -n 's/{ id : \([0-9]*\) }/\1/p'` - case "$XID" in - [0-9]*) - echo $XID;; - *) - return 1;; - esac -} diff --git a/daemon/test/scripts/setup.sh b/daemon/test/scripts/setup.sh deleted file mode 100755 index e89d5e752..000000000 --- a/daemon/test/scripts/setup.sh +++ /dev/null @@ -1,47 +0,0 @@ -#! /bin/sh -e - -. `dirname $0`/vars.sh - -VERSION=$(`dirname $0`/../../lightning-cli --version | head -n1) -[ $VERSION = `git describe --always --dirty` ] || (echo Wrong version $VERSION >&2; exit 1) - -# Start clean -rm -rf $DATADIR -mkdir $DATADIR - -# Find a free port (racy, but hey) -PORT=`findport 18332 $VARIANT` -RPCPORT=`findport $(($PORT + 1))` - -# Create appropriate config file so cmdline matches. -cat > $DATADIR/bitcoin.conf </dev/null 2>&1; do - if [ $i -gt 60 ]; then - echo $DAEMON start failed? >&1 - exit 1 - fi - sleep 1 - i=$(($i + 1)) -done - -# Make sure they have segwit support! -if $CLI getblockchaininfo | grep -q '"segwit"'; then : -else - echo This bitcoind does not have segwit support. >&2 - echo Please install a recent one >&2 - exit 1 -fi - -`dirname $0`/generate-block.sh init - -A1=$($CLI getnewaddress) -TX=`$CLI sendmany "" "{ \"$A1\":0.01 }"` -`dirname $0`/generate-block.sh diff --git a/daemon/test/scripts/shutdown.sh b/daemon/test/scripts/shutdown.sh deleted file mode 100755 index c39fba9a4..000000000 --- a/daemon/test/scripts/shutdown.sh +++ /dev/null @@ -1,11 +0,0 @@ -#! /bin/sh -e - -. `dirname $0`/vars.sh - -[ ! -f $DATADIR/regtest/bitcoind.pid ] || BITCOIN_PID=`cat $DATADIR/regtest/bitcoind.pid` - -$CLI stop -sleep 1 # Make sure socket is closed. - -# Now make sure it's dead. -if [ -n "$BITCOIN_PID" ]; then kill -9 $BITCOIN_PID 2>/dev/null || true; fi diff --git a/daemon/test/scripts/vars.sh b/daemon/test/scripts/vars.sh deleted file mode 100644 index 0fe3147b7..000000000 --- a/daemon/test/scripts/vars.sh +++ /dev/null @@ -1,40 +0,0 @@ -# Sourced by other scripts - -# Bash variables for in-depth debugging. -#set -vx -#export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' - -# Suppress sync if we can, for speedup. -if which eatmydata >/dev/null; then EATMYDATA=eatmydata; fi - -DATADIR=/tmp/bitcoin-lightning$VARIANT -CLI="bitcoin-cli -datadir=$DATADIR" -REGTESTDIR=regtest -DAEMON="$EATMYDATA bitcoind -datadir=$DATADIR" - -PREFIX=$EATMYDATA - -# Always use valgrind if available (unless NO_VALGRIND=1 set) -if which valgrind >/dev/null; then :; else NO_VALGRIND=1; fi -[ -n "$NO_VALGRIND" ] || PREFIX="$EATMYDATA valgrind -q $VG_TRACE_CHILDREN --trace-children-skip=*bitcoin-cli* --error-exitcode=7" - -# We inject 0.01 bitcoin, but then fees (estimatefee fails and we use a -# fee rate as per the default). -AMOUNT=991880000 - -# Default fee rate per kb. -FEE_RATE=200000 - -# Fee in millisatoshi if we have no htlcs (note rounding to make it even) -NO_HTLCS_FEE=$((338 * $FEE_RATE / 2000 * 2000)) -ONE_HTLCS_FEE=$(( (338 + 32) * $FEE_RATE / 2000 * 2000)) -EXTRA_FEE=$(($ONE_HTLCS_FEE - $NO_HTLCS_FEE)) - -findport() -{ - PORT=$1 - # Give two ports per variant. - if [ x"$2" != x ]; then PORT=$(($PORT + $2 * 2)); fi - while netstat -ntl | grep -q ":$PORT "; do PORT=$(($PORT + 1)); done - echo $PORT -} diff --git a/daemon/test/test-basic b/daemon/test/test-basic deleted file mode 100755 index ba005f57c..000000000 --- a/daemon/test/test-basic +++ /dev/null @@ -1,359 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -if [ x"$1" = x"manual-commit" ]; then - MANUALCOMMIT=1 - shift -fi - -parse_cmdline 2 "$@" -setup_lightning 2 - -if [ -n "$MANUALCOMMIT" ]; then - # Aka. never. - echo 'commit-time=1h' >> $DIR1/config - echo 'commit-time=1h' >> $DIR2/config -fi - -start_lightningd 2 -fund_lightningd - -# Check IDs match logs -[ `$LCLI1 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID1 ] -[ `$LCLI2 getlog | sed -n 's/.*"ID: \([0-9a-f]*\)".*/\1/p'` = $ID2 ] - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Expect them to be waiting for anchor, and ack from other side. -check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE -check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - -# Enable reconnect from here. -DO_RECONNECT=$RECONNECT - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -# We turn off routing failure for the moment. -lcli1 dev-routefail false -lcli2 dev-routefail false - -A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE=$NO_HTLCS_FEE -B_AMOUNT=0 -B_FEE=0 -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# This is 10,000 satoshi, so not dust! -HTLC_AMOUNT=10000000 - -EXPIRY=$(( $(blockheight) + 10)) -SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd -RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -if [ -n "$MANUALCOMMIT" ]; then - # They should register a staged htlc. - check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_HTLC } " $B_AMOUNT $B_FEE "" - - # Now commit it. - lcli1 dev-commit $ID2 - - # Node 1 hasn't got it committed, but node2 should have told it to stage. - check_status_single lcli1 $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_REVOCATION } " $B_AMOUNT $B_FEE "" - - # Check channel status - A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) - A_FEE=$(($A_FEE + $EXTRA_FEE)) - - # Node 2 has it committed. - check_status_single lcli2 $B_AMOUNT $B_FEE "" $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_REVOCATION } " - - # There should be no "both committed" here yet - if lcli1 getlog debug | $FGREP "Both committed"; then - echo "Node1 thinks they are both committed"; - exit 1 - fi - if lcli2 getlog debug | $FGREP "Both committed"; then - echo "Node2 thinks they are both committed"; - exit 1 - fi - - # Now node2 gives commitment to node1. - lcli2 dev-commit $ID1 - - # After revocation, they should know they're both committed. - check lcli1 "getlog debug | $FGREP 'Both committed to ADD of our HTLC'" - check lcli2 "getlog debug | $FGREP 'Both committed to ADD of their HTLC'" -else - A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) - A_FEE=$(($A_FEE + $EXTRA_FEE)) -fi - -# Both should have committed tx. -check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# Without manual commit, this check is racy. -if [ -n "$MANUALCOMMIT" ]; then - if lcli1 getlog debug | $FGREP 'Both committed to FULFILL'; then - echo "Node1 thinks they are both committed"; - exit 1 - fi - if lcli2 getlog debug | $FGREP 'Both committed to FULFILL'; then - echo "Node2 thinks they are both committed"; - exit 1 - fi -fi -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -# If we're very slow, manually committed above, and we're restarting, -# we may restart *after* this and thus not see it in the log. -[ "$RECONNECT$MANUALCOMMIT" = restart1 ] || check lcli1 "getlog debug | $FGREP 'Both committed to FULFILL of our HTLC'" -check lcli2 "getlog debug | $FGREP 'Both committed to FULFILL of their HTLC'" - -# We've transferred the HTLC amount to 2, who now has to pay fees, -# so no net change for A who saves on fees. -B_FEE=$HTLC_AMOUNT -# With no HTLCs, extra fee no longer required. -A_FEE=$(($A_FEE - $EXTRA_FEE - $B_FEE)) -A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT)) - -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# A new one, at 10x the amount. -HTLC_AMOUNT=100000000 - -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# Check channel status -A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) -A_FEE=$(($A_FEE + $EXTRA_FEE)) -check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -lcli2 dev-failhtlc $ID1 $HTLCID 695 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -# Back to how we were before. -A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT)) -A_FEE=$(($A_FEE - $EXTRA_FEE)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# Same again, but this time it expires. -HTLC_AMOUNT=10000001 -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# Check channel status -A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) -A_FEE=$(($A_FEE + $EXTRA_FEE)) -check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -# Make sure node1 accepts the expiry packet. -while [ $(blockheight) != $EXPIRY ]; do - $CLI generate 1 -done - -# This should make node2 send it. -$CLI generate 1 - -if [ -n "$MANUALCOMMIT" ]; then - check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_REMOVE_HTLC } " $B_AMOUNT $B_FEE "" - - lcli2 dev-commit $ID1 - lcli1 dev-commit $ID2 -fi - -# Back to how we were before. -A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + $HTLC_AMOUNT)) -A_FEE=$(($A_FEE - $EXTRA_FEE)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# First, give more money to node2, so it can offer HTLCs. -EXPIRY=$(( $(blockheight) + 10)) -HTLC_AMOUNT=100000000 -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -# Both now pay equal fees. -A_FEE=$(($NO_HTLCS_FEE / 2)) -B_FEE=$(($NO_HTLCS_FEE / 2)) -# We transferred 10000000 before, and $HTLC_AMOUNT now. -A_AMOUNT=$(($AMOUNT - 10000000 - $HTLC_AMOUNT - $A_FEE)) -B_AMOUNT=$((10000000 + $HTLC_AMOUNT - $B_FEE)) - -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# Two failures crossover -SECRET2=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfe -RHASH2=`lcli1 dev-rhash $SECRET2 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -# This means B will *just* afford it (but can't cover increased fees) -HTLC_AMOUNT=$(($B_AMOUNT - $EXTRA_FEE / 2)) -HTLCID=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -# Make sure that's committed, in case lcli1 restarts. -lcli2 dev-commit $ID1 >/dev/null || true - -HTLCID2=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# A covers the extra part of the fee. -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE - $EXTRA_FEE / 2)) $(($A_FEE + $EXTRA_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } " 0 $(($B_FEE + $EXTRA_FEE / 2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " - -# Fail both, to reset. -lcli1 dev-failhtlc $ID2 $HTLCID 830 -lcli2 dev-failhtlc $ID1 $HTLCID2 829 - -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# Now, two HTLCs at once, one from each direction. -# Both sides can afford this. -HTLC_AMOUNT=1000000 -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` -HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } " - -lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET2 -lcli2 dev-failhtlc $ID1 $HTLCID 849 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -# We transferred amount from B to A. -A_AMOUNT=$(($A_AMOUNT + $HTLC_AMOUNT)) -B_AMOUNT=$(($B_AMOUNT - $HTLC_AMOUNT)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# Now, test making more changes before receiving commit reply. -DO_RECONNECT="" -lcli2 dev-output $ID1 false -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -# Make sure node1 sends commit (in the background, since it will block!) -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 & - -if [ -n "$MANUALCOMMIT" ]; then - # node2 will consider this committed. - check_status_single lcli2 $(($B_AMOUNT - $EXTRA_FEE/2)) $(($B_FEE + $EXTRA_FEE/2)) "" $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE/2)) $(($A_FEE + $EXTRA_FEE/2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_REVOCATION } " -else - # It will start committing by itself - check_status_single lcli2 $(($B_AMOUNT - $EXTRA_FEE/2)) $(($B_FEE + $EXTRA_FEE/2)) "" $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE/2)) $(($A_FEE + $EXTRA_FEE/2)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_COMMIT } " -fi - -# node1 will still be awaiting node2's revocation reply. -check_status_single lcli1 $(($A_AMOUNT)) $(($A_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_COMMIT } " $B_AMOUNT $B_FEE "" - -# Now send another offer, and enable node2 output. -HTLCID2=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH2 | extract_id` -lcli2 dev-output $ID1 true - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - -DO_RECONNECT=$RECONNECT - -# Both sides should be committed to htlcs -# We open-code check_status here: HTLCs could be in either order. -check_balance_single lcli1 $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) -check_balance_single lcli2 $(($B_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) $(($A_AMOUNT - $HTLC_AMOUNT*2 - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) - -# Once both balances are correct, this should be right. -lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]" || lcli1 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : SENT_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } ], their_htlcs : [ ]" - -lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION } ]" || lcli2 getpeers | tr -s '\012\011" ' ' ' | $FGREP "our_htlcs : [ ], their_htlcs : [ { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH2 , state : RCVD_ADD_ACK_REVOCATION }, { msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } ]" - -# Just for once, reconnect/restart node 2. -case "$RECONNECT" in - reconnect) - echo RECONNECTING NODE2 - $LCLI2 dev-reconnect $ID1 >/dev/null - sleep 1 - ;; - restart) - echo RESTARTING NODE2 - $LCLI2 -- dev-restart $LIGHTNINGD2 >/dev/null 2>&1 || true - if ! check "$LCLI2 getlog 2>/dev/null | fgrep -q Hello"; then - echo "Node2 dev-restart failed!">&2 - exit 1 - fi - ;; -esac - -if ! check "$LCLI2 getpeers | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 -fi - -# Node2 collects the HTLCs. -lcli2 dev-fulfillhtlc $ID1 $HTLCID $SECRET -lcli2 dev-fulfillhtlc $ID1 $HTLCID2 $SECRET2 - -[ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 -[ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - -# We transferred 2 * amount from A to B. -A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT * 2)) -B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT * 2)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -lcli1 close $ID2 - -# They should be negotiating the close. -check_peerstate lcli1 STATE_MUTUAL_CLOSING -check_peerstate lcli2 STATE_MUTUAL_CLOSING - -$CLI generate 1 - -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL -check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL - -# Give it forever-1 blocks. -$CLI generate 8 - -# Make sure they saw it! -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL -check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL - -# Now the final one. -$CLI generate 1 - -check_no_peers lcli1 -check_no_peers lcli2 - -lcli1 stop -lcli2 stop - -all_ok diff --git a/daemon/test/test-different-fees b/daemon/test/test-different-fees deleted file mode 100755 index dde82e73a..000000000 --- a/daemon/test/test-different-fees +++ /dev/null @@ -1,86 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 - -# Simply override default fee (estimatefee fails on regtest anyway) -DEFAULT_FEE_RATE2=50000 -# We use 5x fee rate for commits, by defailt. -FEE_RATE2=$(($DEFAULT_FEE_RATE2 * 5)) -echo "default-fee-rate=$DEFAULT_FEE_RATE2" >> $DIR2/config - -start_lightningd 2 -fund_lightningd - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -# Asymmetry, since fee rates different. -NO_HTLCS_FEE2=$((338 * $FEE_RATE2 / 2000 * 2000)) -ONE_HTLCS_FEE2=$(( (338 + 32) * $FEE_RATE2 / 2000 * 2000)) - -A_AMOUNT1=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE1=$NO_HTLCS_FEE -A_AMOUNT2=$(($AMOUNT - $NO_HTLCS_FEE2)) -A_FEE2=$NO_HTLCS_FEE2 -B_AMOUNT=0 -B_FEE=0 - -check_status_single lcli1 $A_AMOUNT1 $A_FEE1 "" $B_AMOUNT $B_FEE "" -check_status_single lcli2 $B_AMOUNT $B_FEE "" $(($A_AMOUNT2)) $(($A_FEE2)) "" - -# This is 100,000 satoshi, so covers fees. -HTLC_AMOUNT=100000000 -RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` -ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` -ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` -lcli1 sendpay "$ROUTE" $RHASH - -# They should not split fees. -check_status_single lcli1 $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" -check_status_single lcli2 $(($HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) "" $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) "" - - # FIXME: reactivate feechanges! - # # Change fee rate on node2 to same as node1. - # lcli2 dev-feerate 40000 - # $CLI generate 1 - # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - - # check_status $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" - - # # Change back. - # lcli2 dev-feerate 50000 - # $CLI generate 1 - # [ ! -n "$MANUALCOMMIT" ] || lcli2 dev-commit $ID1 - # [ ! -n "$MANUALCOMMIT" ] || lcli1 dev-commit $ID2 - - # check_status_single lcli1 $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) $(($NO_HTLCS_FEE / 2)) "" - # check_status_single lcli2 $(($HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) "" $(($AMOUNT - $HTLC_AMOUNT - $NO_HTLCS_FEE2 / 2)) $(($NO_HTLCS_FEE2 / 2)) "" - -lcli1 close $ID2 -check_tx_spend - -# Give it 10 blocks ie "forever" -$CLI generate 10 -check_no_peers lcli1 -check_no_peers lcli2 - -lcli1 stop -lcli2 stop - -all_ok diff --git a/daemon/test/test-funding-timeout b/daemon/test/test-funding-timeout deleted file mode 100755 index c1635d635..000000000 --- a/daemon/test/test-funding-timeout +++ /dev/null @@ -1,82 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 -start_lightningd 2 -fund_lightningd - -# Prevent anchor broadcast -lcli1 dev-broadcast false -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Expect them to be waiting for anchor, and ack from other side. -check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE -check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - -# Enable reconnect from here. -DO_RECONNECT=$RECONNECT - -$CLI generate 99 - -# Still waiting. -check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE -check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE - -# Make sure whichever times out first doesn't tell the other. -lcli1 dev-output $ID2 false -lcli2 dev-output $ID1 false -$CLI generate 1 - -# Node1 should have gone into STATE_ERR_ANCHOR_TIMEOUT. -check "lcli1 getlog debug | $FGREP STATE_ERR_ANCHOR_TIMEOUT" - -# Don't try to reconnect any more if we are. -if [ x"$RECONNECT" = xreconnect ]; then DO_RECONNECT=""; fi - -# If we're restarting, don't expect peer. -NO_PEER2=1 - -# Now let them send errors if they're still trying. -lcli2 dev-output $ID1 true || true -lcli1 dev-output $ID2 true || true - -# Peer 2 should give up, and have forgotten all about it. -check "lcli2 getlog debug | $FGREP STATE_CLOSED" -check_no_peers lcli2 - -# Node1 should be disconnected. -check_peerconnected lcli1 false - -# Now let node1 broadcast anchor and unilateral close belatedly! -lcli1 dev-broadcast true - -# Now mine that transaction so they see it. -$CLI generate 1 -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL - -# Now move bitcoind 1 day, which is what node2 asked for on commit. -# Get current time from last block (works if we run this twice). -CURTIME=$($CLI getblock $($CLI getblockhash $(($BLOCKHEIGHT + 100))) | sed -n 's/ "time": \([0-9]*\),/\1/p') -$CLI setmocktime $(($CURTIME + 24 * 60 * 60)) - -# Move average so CSV moves. -$CLI generate 6 - -# Now it should have spent the commit tx. -check_tx_spend - -# 100 blocks pass -$CLI generate 100 - -# Considers it all done now. -check_no_peers lcli1 - -lcli1 stop -lcli2 stop -all_ok diff --git a/daemon/test/test-invoice b/daemon/test/test-invoice deleted file mode 100755 index 59bec2d3a..000000000 --- a/daemon/test/test-invoice +++ /dev/null @@ -1,87 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 -start_lightningd 2 -fund_lightningd - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE=$NO_HTLCS_FEE -B_AMOUNT=0 -B_FEE=0 -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# 100k satoshi should cover fees. -HTLC_AMOUNT=100000000 -EXPIRY=$(( $(blockheight) + 10)) -RHASH3=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -lcli2 listinvoice -[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] - -HTLCID3=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH3 | extract_id` - -# We transferred amount from A to B, but fee now split evenly. -A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) -B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) -A_FEE=$(($NO_HTLCS_FEE / 2)) -B_FEE=$(($NO_HTLCS_FEE / 2)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -[ "`lcli2 listinvoice | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] - -# Now, failed payment (didn't pay enough) -RHASH4=`lcli2 invoice $HTLC_AMOUNT RHASH4 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -# Shouldn't have this already. -if lcli2 getlog | $FGREP 'Short payment for'; then exit 1; fi - -# Test listinvoice with both, or subset (either order possible!) -INVOICES=`lcli2 listinvoice | tr -s '\012\011\" ' ' '` -[ "$INVOICES" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true }, { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] || [ "$INVOICES" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false }, { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] -[ "`lcli2 listinvoice RHASH3 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH3 , rhash : $RHASH3 , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] -[ "`lcli2 listinvoice RHASH4 | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH4 , rhash : $RHASH4 , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] - -HTLCID4=`lcli1 dev-newhtlc $ID2 $(($HTLC_AMOUNT - 1)) $EXPIRY $RHASH4 | extract_id` - -check lcli2 "getlog | $FGREP 'Short payment for'" -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -lcli2 delinvoice RHASH4 -if lcli2 delinvoice RHASH3 >/dev/null; then - echo "Should not be able to delete completed invoice!" >&2 - exit 1 -fi - -lcli1 close $ID2 - -# They should be negotiate the close. -check_tx_spend - -# Bury it in "forever" blocks. -$CLI generate 10 - -check_no_peers lcli1 -check_no_peers lcli2 - -lcli1 stop -lcli2 stop - -all_ok diff --git a/daemon/test/test-mutual-close-with-htlcs b/daemon/test/test-mutual-close-with-htlcs deleted file mode 100755 index 497ea9397..000000000 --- a/daemon/test/test-mutual-close-with-htlcs +++ /dev/null @@ -1,96 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 -start_lightningd 2 -fund_lightningd - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE=$NO_HTLCS_FEE -B_AMOUNT=0 -B_FEE=0 - -# Send funds to 2 so it can offer HTLCS -HTLC_AMOUNT=100000000 -RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` -ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` -ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` -lcli1 sendpay "$ROUTE" $RHASH - -# They pay half fees each. -A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) -A_FEE=$(($NO_HTLCS_FEE / 2)) -B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) -B_FEE=$(($NO_HTLCS_FEE / 2)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# For next step, make sure neither node fails HTLCs we're about to set up. -lcli1 dev-routefail false -lcli2 dev-routefail false - -# Set up HTLCs both ways. - -# This is 10,000 satoshi, so not dust! -HTLC_AMOUNT=10000000 - -EXPIRY=$(( $(blockheight) + 10)) -SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd -RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -HTLCID1=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -# FIXME: Test with dust htlc, too. -HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " - -# Now begin close -lcli1 close $ID2 - -# They should be waiting for it to clear up. -check_peerstate lcli1 STATE_SHUTDOWN -check_peerstate lcli2 STATE_SHUTDOWN - -# Fail one, still waiting. -lcli2 dev-failhtlc $ID1 $HTLCID1 800 -check_peerstate lcli1 STATE_SHUTDOWN -check_peerstate lcli2 STATE_SHUTDOWN - -# Fulfill the other causes them to actually complete the close. -lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET -check_peerstate lcli1 STATE_MUTUAL_CLOSING -check_peerstate lcli2 STATE_MUTUAL_CLOSING - -check_tx_spend -$CLI generate 1 - -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_MUTUAL -check_peerstate lcli2 STATE_CLOSE_ONCHAIN_MUTUAL - -# Give it "forever" blocks. -$CLI generate 9 - -check_no_peers lcli1 -check_no_peers lcli2 - -lcli1 stop -lcli2 stop - -all_ok diff --git a/daemon/test/test-routing b/daemon/test/test-routing deleted file mode 100755 index 4b6b590e4..000000000 --- a/daemon/test/test-routing +++ /dev/null @@ -1,146 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 3 "$@" -setup_lightning 3 -start_lightningd 3 -fund_lightningd - -# We connect 1->2->3 -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & -check_tx_spend -$CLI generate 1 - -P2SHADDR2=`$LCLI2 newaddr | sed -n 's/{ "address" : "\(.*\)" }/\1/p'` -TXID2=`$CLI sendtoaddress $P2SHADDR2 0.01` -FUND_INPUT_TX2=`$CLI getrawtransaction $TXID2` -$CLI generate 1 - -lcli2 connect localhost $PORT3 $FUND_INPUT_TX2 & -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -# Make sure all in STATE_NORMAL. -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli3 STATE_NORMAL - -# More than enough to cover commit fees. -HTLC_AMOUNT=100000000 - -# Tell node 1 about the 2->3 route. -# Add to config in case we are restaring. -echo "add-route=$ID2/$ID3/546000/10/36/36" >> $DIR1/config -lcli1 dev-add-route $ID2 $ID3 546000 10 36 36 -RHASH=`lcli3 invoice $HTLC_AMOUNT RHASH | sed 's/.*"\([0-9a-f]*\)".*/\1/'` -BAD_RHASH=`echo $RHASH | tr '0-9a-f' 'a-f0-9'` - -# Get route. -ROUTE=`lcli1 getroute $ID3 $HTLC_AMOUNT 1` -ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` - -# Try wrong hash. -if lcli1 sendpay "$ROUTE" $BAD_RHASH; then - echo Paid with wrong hash? >&2 - exit 1 -fi - -# Try underpaying. -PAID=`echo "$ROUTE" | sed -n 's/.*"msatoshi" : \([0-9]*\),.*/\1/p'` -UNDERPAY=`echo "$ROUTE" | sed "s/: $PAID,/: $(($PAID - 1)),/"` -if lcli1 sendpay "$UNDERPAY" $RHASH; then - echo Paid with too little? >&2 - exit 1 -fi - -# If restarting, make sure node3 remembers incoming payment. -if [ "$RECONNECT" = restart ]; then - $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true - if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 - fi -fi - -[ "`lcli3 listinvoice RHASH | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT, complete : false } ] " ] -# Pay correctly. -lcli1 sendpay "$ROUTE" $RHASH - -# Node 3 should end up with that amount (minus 1/2 tx fee) -# Note that it is delayed a little, since node2 fulfils as soon as fulfill -# starts. -check lcli3 "getpeers | $FGREP \"\\\"our_amount\\\" : $(($HTLC_AMOUNT - $NO_HTLCS_FEE / 2))\"" - -# If restarting, make sure node3 remembers completed payment. -if [ "$RECONNECT" = restart ]; then - echo RESTARTING NODE3 - $LCLI3 -- dev-restart $LIGHTNINGD3 >/dev/null 2>&1 || true - sleep 5 - $LCLI2 -- dev-restart $LIGHTNINGD2 >/dev/null 2>&1 || true - if ! check "$LCLI3 getpeers 2>/dev/null | tr -s '\012\011\" ' ' ' | fgrep -q 'connected : true'"; then - echo "Failed to reconnect!">&2 - exit 1 - fi -fi - -[ "`lcli3 listinvoice RHASH | tr -s '\012\011\" ' ' '`" = "[ { label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT, complete : true } ] " ] - -[ "`lcli3 waitanyinvoice | tr -s '\012\011\" ' ' '`" = "{ label : RHASH , rhash : $RHASH , msatoshi : $HTLC_AMOUNT } " ] - -# Can't pay twice (try from node2) -ROUTE2=`lcli2 getroute $ID3 $HTLC_AMOUNT 1` -ROUTE2=`echo $ROUTE2 | sed 's/^{ "route" : \(.*\) }$/\1/'` -if lcli2 sendpay "$ROUTE2" $RHASH; then - echo "Paying twice worked?" >&2 - exit 1 -fi - -lcli3 close $ID2 -check_peerstate lcli3 STATE_MUTUAL_CLOSING - -# Re-send should be a noop (doesn't matter that node3 is down!) -lcli1 sendpay "$ROUTE" $RHASH - -# Re-send to different id or amount should complain. -SHORTROUTE=`echo "$ROUTE" | sed 's/, { "id" : .* }//' | sed 's/"msatoshi" : [0-9]*,/"msatoshi" : '$HTLC_AMOUNT,/` -lcli1 sendpay "$SHORTROUTE" $RHASH | $FGREP "already succeeded to $ID3" -lcli1 sendpay "$UNDERPAY" $RHASH | $FGREP "already succeeded with amount $HTLC_AMOUNT" - -# Now node2 should fail to route. -if lcli1 sendpay "$ROUTE" $BAD_RHASH | $FGREP "failed: error code 404 node $ID2 reason Unknown peer"; then : ; -else - echo "Pay to node3 didn't give 404" >&2 - exit 1 -fi - -# Now node1 should fail to route (route deleted) -if lcli1 getroute $ID3 $HTLC_AMOUNT 1 | $FGREP "no route found"; then : ; -else - echo "Pay to node3 didn't fail instantly second time" >&2 - exit 1 -fi - -lcli1 close $ID2 -check_peerstate lcli1 STATE_MUTUAL_CLOSING - -# Make sure both txs broadcast. -check '[ `$CLI getrawmempool | egrep -c "[a-f0-9]{32}"` = 2 ]' - -# Bury them in "forever" blocks. -$CLI generate 10 - -check_no_peers lcli1 -check_no_peers lcli2 -check_no_peers lcli3 - -lcli1 stop -lcli2 stop -lcli3 stop - -all_ok diff --git a/daemon/test/test-steal b/daemon/test/test-steal deleted file mode 100755 index 2bc1da2c2..000000000 --- a/daemon/test/test-steal +++ /dev/null @@ -1,91 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 -start_lightningd 2 -fund_lightningd - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE=$NO_HTLCS_FEE -B_AMOUNT=0 -B_FEE=0 - -# Send funds to 2 so it can offer HTLCS -HTLC_AMOUNT=100000000 -RHASH=`lcli2 invoice $HTLC_AMOUNT RHASH3 | sed 's/.*"\([0-9a-f]*\)".*/\1/'` -ROUTE=`lcli1 getroute $ID2 $HTLC_AMOUNT 1` -ROUTE=`echo $ROUTE | sed 's/^{ "route" : \(.*\) }$/\1/'` -lcli1 sendpay "$ROUTE" $RHASH - -# They pay half fees each noe. -A_AMOUNT=$(($A_AMOUNT - $HTLC_AMOUNT + $NO_HTLCS_FEE / 2)) -A_FEE=$(($NO_HTLCS_FEE / 2)) -B_AMOUNT=$(($B_AMOUNT + $HTLC_AMOUNT - $NO_HTLCS_FEE / 2)) -B_FEE=$(($NO_HTLCS_FEE / 2)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# For next step, make sure neither node fails HTLCs we're about to set up. -lcli1 dev-routefail false -lcli2 dev-routefail false - -# Set up HTLCs both ways. - -# This is 10,000 satoshi, so not dust! -HTLC_AMOUNT=10000000 - -EXPIRY=$(( $(blockheight) + 10)) -SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd -RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -HTLCID1=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -# FIXME: Test with dust htlc, too. -HTLCID2=`lcli2 dev-newhtlc $ID1 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -check_status $(($A_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($A_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $(($B_AMOUNT - $HTLC_AMOUNT - $EXTRA_FEE)) $(($B_FEE + $EXTRA_FEE)) "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : RCVD_ADD_ACK_REVOCATION } " - -# This is the tx we're going to try to spend. -STEAL_TX=`$LCLI1 dev-signcommit $ID2 | cut -d\" -f4` - -# Fail one, succeed 2->1 payment -lcli2 dev-failhtlc $ID1 $HTLCID1 800 -lcli1 dev-fulfillhtlc $ID2 $HTLCID2 $SECRET - -A_AMOUNT=$(($A_AMOUNT + $HTLC_AMOUNT)) -B_AMOUNT=$(($B_AMOUNT - $HTLC_AMOUNT)) -check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" - -# Send out old commit tx from peer 1. -$CLI sendrawtransaction $STEAL_TX -$CLI generate 1 - -# Node1 should get really upset; node2 should steal the transaction. -check_peerstate lcli1 STATE_ERR_INFORMATION_LEAK -check_peerstate lcli2 STATE_CLOSE_ONCHAIN_CHEATED -check_tx_spend - -# Give it "forever" blocks. -$CLI generate 10 - -check_no_peers lcli2 - -lcli1 stop -lcli2 stop -all_ok diff --git a/daemon/test/test-unilateral b/daemon/test/test-unilateral deleted file mode 100755 index c6d4bea31..000000000 --- a/daemon/test/test-unilateral +++ /dev/null @@ -1,87 +0,0 @@ -#! /bin/sh -e - -# Wherever we are, we want to be in daemon/test dir. -cd `git rev-parse --show-toplevel`/daemon/test - -. scripts/vars.sh -. scripts/helpers.sh - -parse_cmdline 2 "$@" -setup_lightning 2 -start_lightningd 2 -fund_lightningd - -lcli1 connect localhost $PORT2 $FUND_INPUT_TX & - -# Now make it pass anchor (should be in mempool: one block to bury it) -check_tx_spend -$CLI generate 1 - -DO_RECONNECT=$RECONNECT - -check_peerstate lcli1 STATE_NORMAL -check_peerstate lcli2 STATE_NORMAL - -# Make sure node2 doesn't fail -lcli2 dev-routefail false - -A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) -A_FEE=$NO_HTLCS_FEE -B_AMOUNT=0 -B_FEE=0 - -# This is 10,000 satoshi, so not dust! -HTLC_AMOUNT=10000000 - -EXPIRY=$(( $(blockheight) + 10)) -SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd -RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'` - -HTLCID=`lcli1 dev-newhtlc $ID2 $HTLC_AMOUNT $EXPIRY $RHASH | extract_id` - -A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - $HTLC_AMOUNT)) -A_FEE=$(($A_FEE + $EXTRA_FEE)) -B_AMOUNT=0 -B_FEE=0 - -# Wait for both to committed. -check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -# make node1 disconnect with node2. -lcli1 dev-disconnect $ID2 -check_peerconnected lcli1 false - -# lcli1 should have sent out commitment tx -check_peerstate lcli1 STATE_ERR_BREAKDOWN -check_tx_spend - -# Mine it. -$CLI generate 1 -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL -check_peerstate lcli2 STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL - -# both still know about htlc -check_status $A_AMOUNT $A_FEE "{ msatoshi : $HTLC_AMOUNT, expiry : { block : $EXPIRY }, rhash : $RHASH , state : SENT_ADD_ACK_REVOCATION } " $B_AMOUNT $B_FEE "" - -# Generate 6 blocks so CSV timeout has expired. -$CLI generate 6 - -# Now, lcli1 should spend its own output. -check_tx_spend -check_peerstate lcli1 STATE_CLOSE_ONCHAIN_OUR_UNILATERAL - -while [ $(blockheight) != $EXPIRY ]; do - $CLI generate 1 -done - -# lcli1 should have gotten HTLC back. -check_tx_spend - -# Now, after "forever" blocks, should all be concluded. -$CLI generate 10 - -# Both consider it all done now. -check_no_peers lcli1 - -lcli1 stop -all_ok diff --git a/daemon/wallet.c b/daemon/wallet.c deleted file mode 100644 index 9e39c54ad..000000000 --- a/daemon/wallet.c +++ /dev/null @@ -1,144 +0,0 @@ -/* Poor man's wallet. - * Needed because bitcoind doesn't (yet) produce segwit outputs, and we need - * such outputs for our anchor tx to make it immalleable. - */ -#include "bitcoin/base58.h" -#include "bitcoin/privkey.h" -#include "bitcoin/script.h" -#include "bitcoin/signature.h" -#include "bitcoin/tx.h" -#include "db.h" -#include "jsonrpc.h" -#include "lightningd.h" -#include "log.h" -#include "wallet.h" -#include -#include - -struct wallet { - struct list_node list; - struct privkey privkey; - struct pubkey pubkey; - struct ripemd160 p2sh; -}; - -bool restore_wallet_address(struct lightningd_state *dstate, - const struct privkey *privkey) -{ - struct wallet *w = tal(dstate, struct wallet); - u8 *redeemscript; - struct sha256 h; - - w->privkey = *privkey; - if (!pubkey_from_privkey(&w->privkey, &w->pubkey)) - return false; - - redeemscript = bitcoin_redeem_p2sh_p2wpkh(w, &w->pubkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&w->p2sh, h.u.u8, sizeof(h)); - - list_add_tail(&dstate->wallet, &w->list); - tal_free(redeemscript); - return true; -} - -static void new_keypair(struct privkey *privkey, struct pubkey *pubkey) -{ - do { - randombytes_buf(privkey->secret.data, - sizeof(privkey->secret.data)); - } while (!pubkey_from_privkey(privkey, pubkey)); -} - -static struct wallet *find_by_pubkey(struct lightningd_state *dstate, - const struct pubkey *walletkey) -{ - struct wallet *w; - - list_for_each(&dstate->wallet, w, list) { - if (pubkey_eq(walletkey, &w->pubkey)) - return w; - } - return NULL; -} - -bool wallet_add_signed_input(struct lightningd_state *dstate, - const struct pubkey *walletkey, - struct bitcoin_tx *tx, - unsigned int input_num) -{ - u8 *redeemscript; - secp256k1_ecdsa_signature sig; - struct wallet *w = find_by_pubkey(dstate, walletkey); - - assert(input_num < tal_count(tx->input)); - if (!w) - return false; - - redeemscript = bitcoin_redeem_p2sh_p2wpkh(tx, &w->pubkey); - - sign_tx_input(tx, input_num, - redeemscript, - p2wpkh_scriptcode(redeemscript, &w->pubkey), - &w->privkey, - &w->pubkey, - &sig); - - bitcoin_witness_p2sh_p2wpkh(tx->input, - &tx->input[input_num], - &sig, - &w->pubkey); - tal_free(redeemscript); - return true; -} - -bool wallet_can_spend(struct lightningd_state *dstate, - const struct bitcoin_tx_output *output, - struct pubkey *walletkey) -{ - struct ripemd160 h; - struct wallet *w; - - if (!is_p2sh(output->script)) - return NULL; - - memcpy(&h, output->script + 2, 20); - list_for_each(&dstate->wallet, w, list) { - if (structeq(&h, &w->p2sh)) { - *walletkey = w->pubkey; - return true; - } - } - return false; -} - -static void json_newaddr(struct command *cmd, - const char *buffer, const jsmntok_t *params) -{ - struct json_result *response = new_json_result(cmd); - struct wallet *w = tal(cmd->dstate, struct wallet); - u8 *redeemscript; - struct sha256 h; - - new_keypair(&w->privkey, &w->pubkey); - redeemscript = bitcoin_redeem_p2sh_p2wpkh(cmd, &w->pubkey); - sha256(&h, redeemscript, tal_count(redeemscript)); - ripemd160(&w->p2sh, h.u.u8, sizeof(h)); - - list_add_tail(&cmd->dstate->wallet, &w->list); - db_add_wallet_privkey(cmd->dstate, &w->privkey); - - json_object_start(response, NULL); - json_add_string(response, "address", - p2sh_to_base58(cmd, cmd->dstate->testnet, &w->p2sh)); - json_object_end(response); - command_success(cmd, response); -} - -static const struct json_command newaddr_command = { - "newaddr", - json_newaddr, - "Get a new address to fund a channel", - "Returns {address} a p2sh address" -}; -AUTODATA(json_command, &newaddr_command); diff --git a/daemon/wallet.h b/daemon/wallet.h deleted file mode 100644 index 753542d1c..000000000 --- a/daemon/wallet.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef LIGHTNING_DAEMON_WALLET_H -#define LIGHTNING_DAEMON_WALLET_H -#include "config.h" - -struct lightningd_state; -struct bitcoin_tx; -struct bitcoin_tx_output; - -bool restore_wallet_address(struct lightningd_state *dstate, - const struct privkey *privkey); - -bool wallet_add_signed_input(struct lightningd_state *dstate, - const struct pubkey *walletkey, - struct bitcoin_tx *tx, - unsigned int input_num); - -bool wallet_can_spend(struct lightningd_state *dstate, - const struct bitcoin_tx_output *output, - struct pubkey *walletkey); - -#endif /* LIGHTNING_DAEMON_WALLET_H */ diff --git a/daemon/watch.c b/daemon/watch.c index 1b8467dde..2aaf348d2 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -32,7 +32,6 @@ #include "chaintopology.h" #include "lightningd.h" #include "log.h" -#include "peer.h" #include "pseudorand.h" #include "timeout.h" #include "watch.h" @@ -160,6 +159,9 @@ struct txowatch *watch_txo_(const tal_t *ctx, return w; } +/* UNIFICATION FIXME */ +void peer_debug(struct peer *peer, const char *fmt, ...); + /* Returns true if we fired a callback */ static bool txw_fire(struct chain_topology *topo, struct txwatch *txw, diff --git a/tests/test_lightningd.py b/tests/test_lightningd.py index c9d82432a..9262eb55d 100644 --- a/tests/test_lightningd.py +++ b/tests/test_lightningd.py @@ -2,7 +2,7 @@ from binascii import hexlify, unhexlify from concurrent import futures from decimal import Decimal from hashlib import sha256 -from lightning import LightningRpc, LegacyLightningRpc +from lightning import LightningRpc import copy import json @@ -86,7 +86,7 @@ class NodeFactory(object): self.nodes = [] self.executor = executor - def get_node(self, legacy=True, disconnect=None): + def get_node(self, disconnect=None): node_id = self.next_id self.next_id += 1 @@ -95,17 +95,13 @@ class NodeFactory(object): socket_path = os.path.join(lightning_dir, "lightning-rpc").format(node_id) port = 16330+node_id - if legacy: - daemon = utils.LegacyLightningD(lightning_dir, bitcoind.bitcoin_dir, port=port) - rpc = LegacyLightningRpc(socket_path, self.executor) - else: - daemon = utils.LightningD(lightning_dir, bitcoind.bitcoin_dir, port=port) - # If we have a disconnect string, dump it to a file for daemon. - if disconnect: - with open(os.path.join(lightning_dir, "dev_disconnect"), "w") as f: - f.write("\n".join(disconnect)) - daemon.cmd_line.append("--dev-disconnect=dev_disconnect") - rpc = LightningRpc(socket_path, self.executor) + daemon = utils.LightningD(lightning_dir, bitcoind.bitcoin_dir, port=port) + # If we have a disconnect string, dump it to a file for daemon. + if disconnect: + with open(os.path.join(lightning_dir, "dev_disconnect"), "w") as f: + f.write("\n".join(disconnect)) + daemon.cmd_line.append("--dev-disconnect=dev_disconnect") + rpc = LightningRpc(socket_path, self.executor) node = utils.LightningNode(daemon, rpc, bitcoind, self.executor) self.nodes.append(node) @@ -170,8 +166,8 @@ class BaseLightningDTests(unittest.TestCase): class LightningDTests(BaseLightningDTests): def connect(self): - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node() ret = l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) assert ret['id'] == l2.info['id'] @@ -401,8 +397,8 @@ class LightningDTests(BaseLightningDTests): def test_permfail_new_commit(self): # Test case where we have two possible commits: it will use new one. disconnects = ['-WIRE_REVOKE_AND_ACK', 'permfail'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -440,8 +436,8 @@ class LightningDTests(BaseLightningDTests): def test_permfail_htlc_in(self): # Test case where we fail with unsettled incoming HTLC. disconnects = ['-WIRE_UPDATE_FULFILL_HTLC', 'permfail'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -479,8 +475,8 @@ class LightningDTests(BaseLightningDTests): def test_permfail_htlc_out(self): # Test case where we fail with unsettled outgoing HTLC. disconnects = ['+WIRE_REVOKE_AND_ACK', 'permfail'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l2, l1, 10**6) @@ -579,9 +575,9 @@ class LightningDTests(BaseLightningDTests): # Connect two peers, reconnect and then see if we resume the # gossip. disconnects = ['-WIRE_CHANNEL_ANNOUNCEMENT'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) - l3 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() + l3 = self.node_factory.get_node() l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) l1.openchannel(l2, 20000) @@ -594,7 +590,7 @@ class LightningDTests(BaseLightningDTests): wait_for(lambda: len(n.rpc.getchannels()['channels']) == 4) def test_routing_gossip(self): - nodes = [self.node_factory.get_node(legacy=False) for _ in range(5)] + nodes = [self.node_factory.get_node() for _ in range(5)] l1 = nodes[0] l5 = nodes[4] @@ -638,7 +634,7 @@ class LightningDTests(BaseLightningDTests): def test_forward(self): # Connect 1 -> 2 -> 3. l1,l2 = self.connect() - l3 = self.node_factory.get_node(legacy=False) + l3 = self.node_factory.get_node() ret = l2.rpc.connect('localhost', l3.info['port'], l3.info['id']) assert ret['id'] == l3.info['id'] @@ -698,8 +694,8 @@ class LightningDTests(BaseLightningDTests): disconnects = ['-WIRE_INIT', '@WIRE_INIT', '+WIRE_INIT'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() for d in disconnects: self.assertRaises(ValueError, l1.rpc.connect, 'localhost', l2.info['port'], l2.info['id']) @@ -715,8 +711,8 @@ class LightningDTests(BaseLightningDTests): '+WIRE_OPEN_CHANNEL', '-WIRE_FUNDING_CREATED', '@WIRE_FUNDING_CREATED'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 20000 / 10**6) @@ -733,8 +729,8 @@ class LightningDTests(BaseLightningDTests): disconnects = ['-WIRE_ACCEPT_CHANNEL', '@WIRE_ACCEPT_CHANNEL', '+WIRE_ACCEPT_CHANNEL'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 20000 / 10**6) @@ -750,8 +746,8 @@ class LightningDTests(BaseLightningDTests): # Now, these are the corner cases. Fundee sends funding_signed, # but funder doesn't receive it. disconnects = ['@WIRE_FUNDING_SIGNED'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 20000 / 10**6) @@ -768,8 +764,8 @@ class LightningDTests(BaseLightningDTests): def test_reconnect_signed(self): # This will fail *after* both sides consider channel opening. disconnects = ['+WIRE_FUNDING_SIGNED'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 20000 / 10**6) @@ -799,8 +795,8 @@ class LightningDTests(BaseLightningDTests): disconnects = ['-WIRE_FUNDING_LOCKED', '@WIRE_FUNDING_LOCKED', '+WIRE_FUNDING_LOCKED'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() ret = l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -816,8 +812,8 @@ class LightningDTests(BaseLightningDTests): '-WIRE_REVOKE_AND_ACK', '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() ret = l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -857,8 +853,8 @@ class LightningDTests(BaseLightningDTests): '-WIRE_REVOKE_AND_ACK', '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) ret = l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -883,8 +879,8 @@ class LightningDTests(BaseLightningDTests): '-WIRE_REVOKE_AND_ACK', '@WIRE_REVOKE_AND_ACK', '+WIRE_REVOKE_AND_ACK'] - l1 = self.node_factory.get_node(legacy=False) - l2 = self.node_factory.get_node(legacy=False, disconnect=disconnects) + l1 = self.node_factory.get_node() + l2 = self.node_factory.get_node(disconnect=disconnects) ret = l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -903,8 +899,8 @@ class LightningDTests(BaseLightningDTests): disconnects = ['-WIRE_SHUTDOWN', '@WIRE_SHUTDOWN', '+WIRE_SHUTDOWN'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -930,8 +926,8 @@ class LightningDTests(BaseLightningDTests): disconnects = ['-WIRE_CLOSING_SIGNED', '@WIRE_CLOSING_SIGNED', '+WIRE_CLOSING_SIGNED'] - l1 = self.node_factory.get_node(legacy=False, disconnect=disconnects) - l2 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node(disconnect=disconnects) + l2 = self.node_factory.get_node() l1.rpc.connect('localhost', l2.info['port'], l2.info['id']) self.fund_channel(l1, l2, 10**6) @@ -955,7 +951,7 @@ class LightningDTests(BaseLightningDTests): def test_json_addfunds(self): sat = 10**6 - l1 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node() addr = l1.rpc.newaddr()['address'] txid = l1.bitcoin.rpc.sendtoaddress(addr, 0.01) tx = l1.bitcoin.rpc.getrawtransaction(txid) @@ -968,7 +964,7 @@ class LightningDTests(BaseLightningDTests): def test_withdraw(self): amount = 1000000 - l1 = self.node_factory.get_node(legacy=False) + l1 = self.node_factory.get_node() addr = l1.rpc.newaddr()['address'] @@ -1052,60 +1048,5 @@ class LightningDTests(BaseLightningDTests): l1.daemon.start() assert l1.rpc.getpeers()['peers'][0]['msatoshi_to_us'] == 99980000 -class LegacyLightningDTests(BaseLightningDTests): - - def test_connect(self): - l1 = self.node_factory.get_node() - l2 = self.node_factory.get_node() - l1.connect(l2, 0.01, async=False) - - def test_successful_payment(self): - l1 = self.node_factory.get_node() - l2 = self.node_factory.get_node() - bitcoind = l1.bitcoin - - capacity = 0.01 * 10**8 * 10**3 - htlc_amount = 10000 - l1.connect(l2, 0.01) - - invoice = l2.rpc.invoice(htlc_amount, "successful_payment") - - # TODO(cdecker) Assert that we have an invoice - rhash = invoice['rhash'] - assert len(rhash) == 64 - - route = l1.rpc.getroute(l2.info['id'], htlc_amount, 1) - assert len(route) == 1 - assert route[0] == {'msatoshi': htlc_amount, 'id': l2.info['id'], 'delay': 6} - - receipt = l1.rpc.sendpay(route, invoice['rhash']) - assert sha256(unhexlify(receipt['preimage'])).hexdigest() == rhash - - # Now go for the combined RPC call - invoice = l2.rpc.invoice(100, "one_shot_payment") - l1.rpc.pay(l2.info['id'], 100, invoice['rhash']) - - def test_multihop_payment(self): - nodes = [self.node_factory.get_node() for _ in range(5)] - for i in range(len(nodes)-1): - nodes[i].connect(nodes[i+1], 0.01) - - htlc_amount = 10000 - - # Manually add channel l2 -> l3 to l1 so that it can compute the route - for i in range(len(nodes)-1): - nodes[0].rpc.dev_add_route(nodes[i].info['id'], nodes[i+1].info['id'], 1, 1, 6, 6) - #l1.rpc.dev_add_route(l2.info['id'], l3.info['id'], 1, 1, 6, 6) - - sync_blockheight(nodes) - - invoice = nodes[-1].rpc.invoice(htlc_amount, "multihop_payment") - route = nodes[0].rpc.getroute(nodes[-1].info['id'], htlc_amount, 1) - receipt = nodes[0].rpc.sendpay(route, invoice['rhash']) - - nodes[-1].daemon.wait_for_log("STATE_NORMAL_COMMITTING => STATE_NORMAL") - nodes[0].daemon.wait_for_log("STATE_NORMAL_COMMITTING => STATE_NORMAL") - - if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/tests/utils.py b/tests/utils.py index 2e36b63f1..8807fe098 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -235,19 +235,6 @@ class LightningD(TailableProc): TailableProc.stop(self) logging.info("LightningD stopped") -class LegacyLightningD(LightningD): - def __init__(self, *args, **kwargs): - LightningD.__init__(self, *args, **kwargs) - self.cmd_line[0] = 'daemon/lightningd' - # Filter out non-legacy options - self.cmd_line = [c for c in self.cmd_line if '--network' not in c and '--dev-broadcast-interval' not in c] - - def start(self): - TailableProc.start(self) - self.wait_for_log("Hello world!") - logging.info("LightningD started") - - class LightningNode(object): def __init__(self, daemon, rpc, btc, executor): self.rpc = rpc diff --git a/type_to_string.c b/type_to_string.c index 50652c586..7e52bb0a5 100644 --- a/type_to_string.c +++ b/type_to_string.c @@ -1,10 +1,7 @@ #include "bitcoin/locktime.h" #include "bitcoin/pubkey.h" #include "bitcoin/tx.h" -#include "daemon/channel.h" #include "daemon/htlc.h" -#include "daemon/lightningd.h" -#include "daemon/peer.h" #include "protobuf_convert.h" #include "type_to_string.h" #include "utils.h"