From 3c9fd4fbe6aac223afcd838b49d602c04c86b813 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 22 Jan 2016 06:45:05 +1030 Subject: [PATCH] daemon: code to open channel and watch anchor. Signed-off-by: Rusty Russell --- daemon/packets.c | 59 ++++++++++++++++++++++++++++++++-- daemon/peer.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 136 insertions(+), 5 deletions(-) diff --git a/daemon/packets.c b/daemon/packets.c index a681b36e4..839e8d43e 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -1,4 +1,5 @@ #include "bitcoin/script.h" +#include "bitcoin/tx.h" #include "find_p2sh_out.h" #include "lightningd.h" #include "log.h" @@ -9,9 +10,29 @@ #include "state.h" #include #include +#include #define FIXME_STUB(peer) do { log_broken((peer)->dstate->base_log, "%s:%u: Implement %s!", __FILE__, __LINE__, __func__); abort(); } while(0) +static char *hex_of(const tal_t *ctx, const void *p, size_t n) +{ + char *hex = tal_arr(ctx, char, hex_str_size(n)); + hex_encode(p, n, hex, hex_str_size(n)); + return hex; +} + +static void dump_tx(const char *str, const struct bitcoin_tx *tx) +{ + u8 *linear = linearize_tx(NULL, tx); + printf("%s:%s\n", str, hex_of(linear, linear, tal_count(linear))); + tal_free(linear); +} + +static void dump_key(const char *str, const struct pubkey *key) +{ + printf("%s:%s\n", str, hex_of(NULL, key->der, pubkey_derlen(key))); +} + /* Wrap (and own!) member inside Pkt */ static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) { @@ -86,12 +107,26 @@ Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer) Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer) { - FIXME_STUB(peer); + struct signature sig; + OpenCommitSig *s = tal(ctx, OpenCommitSig); + + open_commit_sig__init(s); + + dump_tx("Creating sig for:", peer->them.commit); + dump_key("Using key:", &peer->us.commitkey); + + peer_sign_theircommit(peer, &sig); + s->sig = signature_to_proto(s, &sig); + + return make_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, s); } Pkt *pkt_open_complete(const tal_t *ctx, const struct peer *peer) { - FIXME_STUB(peer); + OpenComplete *o = tal(ctx, OpenComplete); + + open_complete__init(o); + return make_pkt(ctx, PKT__PKT_OPEN_COMPLETE, o); } Pkt *pkt_htlc_update(const tal_t *ctx, const struct peer *peer, @@ -252,7 +287,25 @@ Pkt *accept_pkt_anchor(const tal_t *ctx, Pkt *accept_pkt_open_commit_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt) { - FIXME_STUB(peer); + const OpenCommitSig *s = pkt->open_commit_sig; + + peer->cur_commit_theirsig.stype = SIGHASH_ALL; + if (!proto_to_signature(s->sig, &peer->cur_commit_theirsig.sig)) + return pkt_err(ctx, "Malformed signature"); + + dump_tx("Checking sig for:", peer->us.commit); + dump_key("Using key:", &peer->them.commitkey); + + /* Their sig should sign our commit tx. */ + if (!check_tx_sig(peer->dstate->secpctx, + peer->us.commit, 0, + peer->anchor.redeemscript, + tal_count(peer->anchor.redeemscript), + &peer->them.commitkey, + &peer->cur_commit_theirsig)) + return pkt_err(ctx, "Bad signature"); + + return NULL; } Pkt *accept_pkt_htlc_update(const tal_t *ctx, diff --git a/daemon/peer.c b/daemon/peer.c index 0b8095f6d..ee660f09b 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -439,7 +440,6 @@ const struct json_command connect_command = { }; struct anchor_watch { - struct peer *peer; enum state_input depthok; enum state_input timeout; enum state_input unspent; @@ -447,6 +447,71 @@ struct anchor_watch { enum state_input otherspent; }; +static void anchor_depthchange(struct peer *peer, int depth, + struct anchor_watch *w) +{ + /* Still waiting for it to reach depth? */ + if (w->depthok != INPUT_NONE) { + /* Beware sign! */ + if (depth >= (int)peer->us.mindepth) { + enum state_input in = w->depthok; + w->depthok = INPUT_NONE; + update_state(peer, in, NULL); + } + } else { + if (depth < 0 && w->unspent != INPUT_NONE) { + enum state_input in = w->unspent; + w->unspent = INPUT_NONE; + update_state(peer, in, NULL); + } + } +} + +/* We don't compare scriptSigs: we don't know them anyway! */ +static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb) +{ + size_t i; + + if (txa->version != txb->version + || txa->input_count != txb->input_count + || txa->output_count != txb->output_count + || txa->lock_time != txb->lock_time) + return false; + + for (i = 0; i < txa->input_count; i++) { + if (!structeq(&txa->input[i].txid, &txb->input[i].txid) + || txa->input[i].index != txb->input[i].index + || txa->input[i].sequence_number != txb->input[i].sequence_number) + return false; + } + + for (i = 0; i < txa->output_count; i++) { + if (txa->output[i].amount != txb->output[i].amount + || txa->output[i].script_length != txb->output[i].script_length + || memcmp(txa->output[i].script, txb->output[i].script, + txa->output[i].script_length != 0)) + return false; + } + + return true; +} + +/* We assume the tx is valid! Don't do a blockchain.info and feed this + * invalid transactions! */ +static void anchor_spent(struct peer *peer, + const struct bitcoin_tx *tx, + struct anchor_watch *w) +{ + union input idata; + + /* FIXME: change type in idata? */ + idata.btc = (struct bitcoin_event *)tx; + if (txmatch(tx, peer->them.commit)) + update_state(peer, w->theyspent, &idata); + else + update_state(peer, w->otherspent, &idata); +} + void peer_watch_anchor(struct peer *peer, enum state_input depthok, enum state_input timeout, @@ -454,7 +519,20 @@ void peer_watch_anchor(struct peer *peer, enum state_input theyspent, enum state_input otherspent) { - FIXME_STUB(peer); + struct anchor_watch *w = tal(peer, struct anchor_watch); + + w->depthok = depthok; + w->timeout = timeout; + w->unspent = unspent; + w->theyspent = theyspent; + w->otherspent = otherspent; + + add_anchor_watch(peer, &peer->anchor.txid, peer->anchor.index, + anchor_depthchange, + anchor_spent, + w); + + /* FIXME: add timeout */ } void peer_unwatch_anchor_depth(struct peer *peer,