diff --git a/commit_tx.h b/commit_tx.h index b35b563a0..fabd8889b 100644 --- a/commit_tx.h +++ b/commit_tx.h @@ -6,6 +6,7 @@ struct channel_state; struct sha256_double; +struct sha256; struct pubkey; struct rel_locktime; diff --git a/daemon/packets.c b/daemon/packets.c index 69a544e0c..a681b36e4 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -1,3 +1,5 @@ +#include "bitcoin/script.h" +#include "find_p2sh_out.h" #include "lightningd.h" #include "log.h" #include "names.h" @@ -67,7 +69,19 @@ Pkt *pkt_open(const tal_t *ctx, const struct peer *peer, Pkt *pkt_anchor(const tal_t *ctx, const struct peer *peer) { - FIXME_STUB(peer); + struct signature sig; + OpenAnchor *a = tal(ctx, 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; + + /* Sign their commit sig */ + peer_sign_theircommit(peer, &sig); + a->commit_sig = signature_to_proto(a, &sig); + + return make_pkt(ctx, PKT__PKT_OPEN_ANCHOR, a); } Pkt *pkt_open_commit_sig(const tal_t *ctx, const struct peer *peer) @@ -149,7 +163,7 @@ Pkt *accept_pkt_open(const tal_t *ctx, struct peer *peer, const Pkt *pkt) { struct rel_locktime locktime; - OpenChannel *o = pkt->open; + const OpenChannel *o = pkt->open; if (!proto_to_rel_locktime(o->delay, &locktime)) return pkt_err(ctx, "Invalid delay"); @@ -184,6 +198,10 @@ Pkt *accept_pkt_open(const tal_t *ctx, return pkt_err(ctx, "Bad finalkey"); proto_to_sha256(o->revocation_hash, &peer->them.revocation_hash); + /* Redeemscript for anchor. */ + peer->anchor.redeemscript + = bitcoin_redeem_2of2(peer, &peer->us.commitkey, + &peer->them.commitkey); return NULL; } @@ -191,7 +209,44 @@ Pkt *accept_pkt_anchor(const tal_t *ctx, struct peer *peer, const Pkt *pkt) { - FIXME_STUB(peer); + const OpenAnchor *a = pkt->open_anchor; + u64 commitfee; + + /* They must be offering anchor for us to try accepting */ + assert(peer->us.offer_anchor == CMD_OPEN_WITHOUT_ANCHOR); + assert(peer->them.offer_anchor == CMD_OPEN_WITH_ANCHOR); + + proto_to_sha256(a->txid, &peer->anchor.txid.sha); + peer->anchor.index = a->output_index; + peer->anchor.satoshis = a->amount; + + /* Create funder's cstate, invert to get ours. */ + commitfee = commit_fee(peer->them.commit_fee, peer->us.commit_fee); + peer->cstate = initial_funding(peer, + peer->us.offer_anchor, + peer->anchor.satoshis, + commitfee); + if (!peer->cstate) + return pkt_err(ctx, "Insufficient funds for fee"); + invert_cstate(peer->cstate); + + /* Now we can make initial (unsigned!) commit txs. */ + peer_make_commit_txs(peer); + + peer->cur_commit_theirsig.stype = SIGHASH_ALL; + if (!proto_to_signature(a->commit_sig, &peer->cur_commit_theirsig.sig)) + return pkt_err(ctx, "Malformed signature"); + + /* 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_open_commit_sig(const tal_t *ctx, diff --git a/daemon/peer.c b/daemon/peer.c index 799eca45f..0b8095f6d 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -1,6 +1,8 @@ #include "bitcoind.h" +#include "commit_tx.h" #include "cryptopkt.h" #include "dns.h" +#include "find_p2sh_out.h" #include "jsonrpc.h" #include "lightningd.h" #include "log.h" @@ -8,6 +10,8 @@ #include "peer.h" #include "secrets.h" #include "state.h" +#include +#include #include #include #include @@ -246,6 +250,8 @@ static struct peer *new_peer(struct lightningd_state *dstate, /* FIXME: Make this dynamic. */ peer->us.commit_fee = dstate->config.commitment_fee; + peer->us.commit = peer->them.commit = NULL; + /* FIXME: Attach IO logging for this peer. */ tal_add_destructor(peer, destroy_peer); @@ -278,6 +284,7 @@ static struct io_plan *peer_connected_out(struct io_conn *conn, } log_info(peer->log, "Connected out to %s:%s", connect->name, connect->port); + peer->anchor.satoshis = connect->satoshis; peer->jsoncmd = NULL; command_success(connect->cmd, null_response(connect)); @@ -678,25 +685,101 @@ const struct bitcoin_tx *bitcoin_htlc_spend(const tal_t *ctx, FIXME_STUB(peer); } +static void created_anchor(struct lightningd_state *dstate, + const struct bitcoin_tx *tx, + struct peer *peer) +{ + size_t commitfee; + + bitcoin_txid(tx, &peer->anchor.txid); + peer->anchor.index = find_p2sh_out(tx, peer->anchor.redeemscript); + assert(peer->anchor.satoshis == tx->output[peer->anchor.index].amount); + /* We'll need this later, when we're told to broadcast it. */ + peer->anchor.tx = tal_steal(peer, tx); + + commitfee = commit_fee(peer->them.commit_fee, peer->us.commit_fee); + peer->cstate = initial_funding(peer, + peer->us.offer_anchor, + peer->anchor.satoshis, + commitfee); + if (!peer->cstate) + fatal("Insufficient anchor funds for commitfee"); + + /* Now we can make initial (unsigned!) commit txs. */ + peer_make_commit_txs(peer); + + update_state(peer, BITCOIN_ANCHOR_CREATED, NULL); +} + /* Start creation of the bitcoin anchor tx. */ void bitcoin_create_anchor(struct peer *peer, enum state_input done) { - /* FIXME */ + struct sha256 h; + struct ripemd160 redeemhash; + char *p2shaddr; + + /* We must be offering anchor for us to try creating it */ + assert(peer->us.offer_anchor); + + sha256(&h, peer->anchor.redeemscript, + tal_count(peer->anchor.redeemscript)); + ripemd160(&redeemhash, h.u.u8, sizeof(h)); + + p2shaddr = p2sh_to_base58(peer, peer->dstate->config.testnet, + &redeemhash); + + assert(done == BITCOIN_ANCHOR_CREATED); + + bitcoind_create_payment(peer->dstate, p2shaddr, peer->anchor.satoshis, + created_anchor, peer); } /* We didn't end up broadcasting the anchor: release the utxos. * If done != INPUT_NONE, remove existing create_anchor too. */ void bitcoin_release_anchor(struct peer *peer, enum state_input done) { - FIXME_STUB(peer); + + /* FIXME: stop bitcoind command */ + log_unusual(peer->log, "Anchor not spent, please -zapwallettxs"); } /* Get the bitcoin anchor tx. */ const struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer) { - FIXME_STUB(peer); + return peer->anchor.tx; } +void peer_make_commit_txs(struct peer *peer) +{ + struct channel_state their_cstate; + + tal_free(peer->us.commit); + tal_free(peer->them.commit); + + /* FIXME: Where do we update revocation_hash fields? */ + peer->us.commit = create_commit_tx(peer, + &peer->us.finalkey, + &peer->them.finalkey, + &peer->them.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &peer->us.revocation_hash, + peer->cstate); + + their_cstate = *peer->cstate; + invert_cstate(&their_cstate); + peer->them.commit = create_commit_tx(peer, + &peer->them.finalkey, + &peer->us.finalkey, + &peer->us.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &peer->them.revocation_hash, + &their_cstate); +} + /* FIXME: Somehow we should show running DNS lookups! */ /* FIXME: Show status of peers! */ static void json_getpeers(struct command *cmd, diff --git a/daemon/peer.h b/daemon/peer.h index 2a94c0143..f1b186d6f 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -3,6 +3,9 @@ #include "config.h" #include "bitcoin/locktime.h" #include "bitcoin/pubkey.h" +#include "bitcoin/script.h" +#include "bitcoin/shadouble.h" +#include "funding.h" #include "lightning.pb-c.h" #include "netaddr.h" #include "state.h" @@ -22,6 +25,8 @@ struct peer_visible_state { u64 commit_fee; /* Revocation hash for latest commit tx. */ struct sha256 revocation_hash; + /* Current commit tx. */ + struct bitcoin_tx *commit; }; struct peer { @@ -45,6 +50,9 @@ struct peer { /* Global state. */ struct lightningd_state *dstate; + /* Funding status for current commit tx (from our PoV). */ + struct channel_state *cstate; + /* The other end's address. */ struct netaddr addr; @@ -57,7 +65,20 @@ struct peer { /* Queue of output packets. */ Pkt *outpkt[5]; size_t num_outpkt; - + + /* Anchor tx output */ + struct { + struct sha256_double txid; + unsigned int index; + u64 satoshis; + u8 *redeemscript; + /* If we created it, we keep entire tx. */ + const struct bitcoin_tx *tx; + } anchor; + + /* Their signature for our current commit sig. */ + struct bitcoin_signature cur_commit_theirsig; + /* Current ongoing packetflow */ struct io_data *io_data; @@ -76,4 +97,6 @@ struct peer { void setup_listeners(struct lightningd_state *dstate, unsigned int portnum); +void peer_make_commit_txs(struct peer *peer); + #endif /* LIGHTNING_DAEMON_PEER_H */