diff --git a/daemon/lightningd.c b/daemon/lightningd.c index 800214be4..1c92ac87e 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -147,12 +147,21 @@ static void default_config(struct config *config) static void check_config(struct lightningd_state *dstate) { + /* BOLT #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 (dstate->config.closing_fee > dstate->config.commitment_fee) fatal("Closing fee %"PRIu64 " can't exceed commitment fee %"PRIu64, dstate->config.closing_fee, dstate->config.commitment_fee); + if (dstate->config.closing_fee & 1) + fatal("Closing fee %"PRIu64 "must be even.", + dstate->config.closing_fee); + if (dstate->config.commitment_fee_min > dstate->config.commitment_fee) fatal("Minumum fee %"PRIu64 " can't exceed commitment fee %"PRIu64, diff --git a/daemon/packets.c b/daemon/packets.c index 6aa50106f..8dec9cbea 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -243,35 +243,29 @@ Pkt *pkt_err(const tal_t *ctx, const char *msg, ...) return make_pkt(ctx, PKT__PKT_ERROR, e); } -Pkt *pkt_close(const tal_t *ctx, const struct peer *peer) +Pkt *pkt_close_clearing(const tal_t *ctx, const struct peer *peer) { - CloseChannel *c = tal(ctx, CloseChannel); + CloseClearing *c = tal(ctx, CloseClearing); - close_channel__init(c); + close_clearing__init(c); - c->close_fee = peer->close_tx->fee; - c->sig = signature_to_proto(c, &peer->our_close_sig.sig); - - return make_pkt(ctx, PKT__PKT_CLOSE, c); + return make_pkt(ctx, PKT__PKT_CLOSE_CLEARING, c); } -Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer) +Pkt *pkt_close_signature(const tal_t *ctx, const struct peer *peer) { - CloseChannelComplete *c = tal(ctx, CloseChannelComplete); + CloseSignature *c = tal(ctx, CloseSignature); + struct bitcoin_tx *close_tx; + struct signature our_close_sig; - close_channel_complete__init(c); - assert(peer->close_tx); - c->sig = signature_to_proto(c, &peer->our_close_sig.sig); + close_signature__init(c); + close_tx = peer_create_close_tx(ctx, peer, peer->closing.our_fee); - return make_pkt(ctx, PKT__PKT_CLOSE_COMPLETE, c); -} + 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; -Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer) -{ - CloseChannelAck *a = tal(ctx, CloseChannelAck); - - close_channel_ack__init(a); - return make_pkt(ctx, PKT__PKT_CLOSE_ACK, a); + return make_pkt(ctx, PKT__PKT_CLOSE_SIGNATURE, c); } Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt) @@ -721,68 +715,84 @@ Pkt *accept_pkt_update_signature(const tal_t *ctx, return NULL; } -static bool peer_sign_close_tx(struct peer *peer, const Signature *theirs) +Pkt *accept_pkt_close_clearing(const tal_t *ctx, struct peer *peer, const Pkt *pkt) { + /* FIXME: Reject unknown odd fields? */ + return NULL; +} + +Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt, + bool *matches) +{ + const CloseSignature *c = pkt->close_signature; + struct bitcoin_tx *close_tx; struct bitcoin_signature theirsig; - /* We never sign twice! */ - assert(peer->close_tx->input[0].script_length == 0); + /* BOLT #2: - theirsig.stype = SIGHASH_ALL; - if (!proto_to_signature(theirs, &theirsig.sig)) - return false; - - /* Their sig + ours should sign the close tx. */ - if (!check_2of2_sig(peer->dstate->secpctx, - peer->close_tx, 0, - peer->anchor.redeemscript, - tal_count(peer->anchor.redeemscript), - &peer->them.commitkey, &peer->us.commitkey, - &theirsig, &peer->our_close_sig)) - return false; - - /* Complete the close_tx, using signatures. */ - peer->close_tx->input[0].script - = scriptsig_p2sh_2of2(peer->close_tx, - &theirsig, &peer->our_close_sig, - &peer->them.commitkey, - &peer->us.commitkey); - peer->close_tx->input[0].script_length - = tal_count(peer->close_tx->input[0].script); - return true; -} - -Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt) -{ - const CloseChannel *c = pkt->close; - - /* FIXME: Don't accept tiny close fee! */ - if (!peer_create_close_tx(peer, c->close_fee)) + * 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 > peer->them.commit_fee) return pkt_err(ctx, "Invalid close fee"); - if (!peer_sign_close_tx(peer, c->sig)) + /* FIXME: Don't accept tiny fee at all? */ + + /* BOLT #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 pkt_err(ctx, "Didn't increase close fee"); + } else { + if (c->close_fee >= peer->closing.their_fee) + return pkt_err(ctx, "Didn't decrease close fee"); + } + } + + /* BOLT #2: + * + * The receiver MUST check `sig` is valid for the close + * transaction, and MUST fail the connection if it is not. */ + theirsig.stype = SIGHASH_ALL; + if (!proto_to_signature(c->sig, &theirsig.sig)) + return pkt_err(ctx, "Invalid signature format"); + + close_tx = peer_create_close_tx(ctx, peer, c->close_fee); + if (!check_tx_sig(peer->dstate->secpctx, close_tx, 0, + peer->anchor.redeemscript, + tal_count(peer->anchor.redeemscript), + &peer->them.commitkey, &theirsig)) return pkt_err(ctx, "Invalid signature"); - return NULL; -} - -Pkt *accept_pkt_close_complete(const tal_t *ctx, - struct peer *peer, const Pkt *pkt) -{ - const CloseChannelComplete *c = pkt->close_complete; - if (!peer_sign_close_tx(peer, c->sig)) - return pkt_err(ctx, "Invalid signature"); - return NULL; -} - -Pkt *accept_pkt_simultaneous_close(const tal_t *ctx, - struct peer *peer, - const Pkt *pkt) -{ - FIXME_STUB(peer); -} - -/* FIXME: Since this packet is empty, is it worth having? */ -Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt) -{ + + tal_free(peer->closing.their_sig); + peer->closing.their_sig = tal_dup(peer, + struct bitcoin_signature, &theirsig); + peer->closing.their_fee = c->close_fee; + + if (peer->closing.our_fee == peer->closing.their_fee) { + *matches = true; + } else { + /* 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++; + + /* FIXME: Fees may *now* be equal, and they'll + * consider this an ACK! */ + } + *matches = false; + + /* FIXME: Dynamic fee! */ return NULL; } diff --git a/daemon/peer.c b/daemon/peer.c index f07665621..5572006bb 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -222,6 +222,13 @@ static void state_event(struct peer *peer, const union input *idata) { state_single(peer, input, idata); + + if (peer->cleared != INPUT_NONE && !committed_to_htlcs(peer)) { + enum state_input all_done = peer->cleared; + peer->cleared = INPUT_NONE; + state_single(peer, all_done, NULL); + } + try_command(peer); } @@ -353,11 +360,12 @@ static struct peer *new_peer(struct lightningd_state *dstate, list_head_init(&peer->pending_cmd); peer->current_htlc = NULL; peer->commit_tx_counter = 0; - peer->close_tx = NULL; peer->cstate = NULL; peer->close_watch_timeout = NULL; peer->anchor.watches = NULL; peer->cur_commit.watch = NULL; + peer->closing.their_sig = NULL; + peer->cleared = INPUT_NONE; /* If we free peer, conn should be closed, but can't be freed * immediately so don't make peer a parent. */ @@ -621,29 +629,35 @@ static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb) return true; } -static bool is_mutual_close(const struct bitcoin_tx *tx, - const struct bitcoin_tx *close_tx) +/* A mutual close is a simple 2 output p2sh to the final addresses, but + * without knowing fee we can't determine order, so examine each output. */ +static bool is_mutual_close(const struct peer *peer, + const struct bitcoin_tx *tx) { - varint_t i; + const u8 *ctx, *our_p2sh, *their_p2sh; + bool matches; - /* Haven't created mutual close yet? This isn't one then. */ - if (!close_tx) + if (tx->output_count != 2) return false; - /* We know it spends anchor, but do txouts match? */ - if (tx->output_count != close_tx->output_count) + if (!is_p2sh(tx->output[0].script, tx->output[0].script_length) + || !is_p2sh(tx->output[1].script, tx->output[1].script_length)) return false; - for (i = 0; i < tx->output_count; i++) { - if (tx->output[i].amount != close_tx->output[i].amount) - return false; - if (tx->output[i].script_length - != close_tx->output[i].script_length) - return false; - if (memcmp(tx->output[i].script, close_tx->output[i].script, - tx->output[i].script_length) != 0) - return false; - } - return true; + + /* FIXME: Cache these! */ + ctx = tal(NULL, u8); + our_p2sh = scriptpubkey_p2sh(ctx, + bitcoin_redeem_single(tx, &peer->us.finalkey)); + their_p2sh = scriptpubkey_p2sh(ctx, + bitcoin_redeem_single(tx, &peer->them.finalkey)); + + matches = + (memcmp(tx->output[0].script, our_p2sh, tal_count(our_p2sh)) == 0 + && memcmp(tx->output[1].script, their_p2sh, tal_count(their_p2sh)) == 0) + || (memcmp(tx->output[0].script, their_p2sh, tal_count(their_p2sh)) == 0 + && memcmp(tx->output[1].script, our_p2sh, tal_count(our_p2sh)) == 0); + tal_free(ctx); + return matches; } static void close_depth_cb(struct peer *peer, int depth) @@ -665,7 +679,7 @@ static void anchor_spent(struct peer *peer, idata.btc = (struct bitcoin_event *)tx; if (txmatch(tx, peer->them.commit)) state_event(peer, w->theyspent, &idata); - else if (is_mutual_close(tx, peer->close_tx)) + else if (is_mutual_close(peer, tx)) add_close_tx_watch(peer, peer, tx, close_depth_cb); else state_event(peer, w->otherspent, &idata); @@ -836,20 +850,20 @@ void peer_watch_tx(struct peer *peer, add_commit_tx_watch(tx, peer, &txid, spend_tx_done, int2ptr(done)); } -bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis) +struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, + const struct peer *peer, u64 fee) { struct channel_state cstate; - assert(!peer->close_tx); - /* We don't need a deep copy here, just fee levels. */ cstate = *peer->cstate; - if (!adjust_fee(peer->anchor.satoshis, fee_satoshis, + if (!adjust_fee(peer->anchor.satoshis, fee, &cstate.a, &cstate.b)) - return false; + return NULL; log_debug(peer->log, - "creating close-tx: to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u", + "creating close-tx with fee %"PRIu64": to %02x%02x%02x%02x/%02x%02x%02x%02x, amounts %u/%u", + fee, peer->us.finalkey.der[0], peer->us.finalkey.der[1], peer->us.finalkey.der[2], peer->us.finalkey.der[3], peer->them.finalkey.der[0], peer->them.finalkey.der[1], @@ -857,18 +871,31 @@ bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis) cstate.a.pay_msat / 1000, cstate.b.pay_msat / 1000); - peer->close_tx = create_close_tx(peer->dstate->secpctx, peer, - &peer->us.finalkey, - &peer->them.finalkey, - &peer->anchor.txid, - peer->anchor.index, - peer->anchor.satoshis, - cstate.a.pay_msat / 1000, - cstate.b.pay_msat / 1000); + return create_close_tx(peer->dstate->secpctx, ctx, + &peer->us.finalkey, + &peer->them.finalkey, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + cstate.a.pay_msat / 1000, + cstate.b.pay_msat / 1000); +} - peer->our_close_sig.stype = SIGHASH_ALL; - peer_sign_mutual_close(peer, peer->close_tx, &peer->our_close_sig.sig); - return true; +void peer_calculate_close_fee(struct peer *peer) +{ + /* BOLT #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. + */ + + /* FIXME: Dynamic fee! */ + peer->closing.our_fee = peer->dstate->config.closing_fee; +} + +bool peer_has_close_sig(const struct peer *peer) +{ + return peer->closing.their_sig; } static void send_close_timeout(struct peer *peer) @@ -883,10 +910,6 @@ void peer_watch_close(struct peer *peer, /* We save some work by assuming these. */ assert(done == BITCOIN_CLOSE_DONE); - /* FIXME: Dynamic closing fee! */ - if (!peer->close_tx) - peer_create_close_tx(peer, peer->dstate->config.closing_fee); - /* FIXME: We can't send CLOSE, so timeout immediately */ if (!peer->conn) { assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT); @@ -994,12 +1017,36 @@ bool committed_to_htlcs(const struct peer *peer) || tal_count(peer->cstate->b.htlcs) != 0; } -/* Create a bitcoin close tx. */ +void peer_watch_htlcs_cleared(struct peer *peer, + enum state_input all_done) +{ + assert(peer->cleared == INPUT_NONE); + assert(all_done != INPUT_NONE); + peer->cleared = all_done; +} + +/* Create a bitcoin close tx, using last signature they sent. */ const struct bitcoin_tx *bitcoin_close(const tal_t *ctx, struct peer *peer) { - /* Must be signed! */ - assert(peer->close_tx->input[0].script_length != 0); - return peer->close_tx; + struct bitcoin_tx *close_tx; + struct bitcoin_signature our_close_sig; + + close_tx = peer_create_close_tx(ctx, peer, peer->closing.their_fee); + + our_close_sig.stype = SIGHASH_ALL; + peer_sign_mutual_close(peer, close_tx, &our_close_sig.sig); + + /* Complete the close_tx, using signatures. */ + close_tx->input[0].script + = scriptsig_p2sh_2of2(close_tx, + peer->closing.their_sig, + &our_close_sig, + &peer->them.commitkey, + &peer->us.commitkey); + close_tx->input[0].script_length + = tal_count(close_tx->input[0].script); + + return close_tx; } /* Create a bitcoin spend tx (to spend our commit's outputs) */ diff --git a/daemon/peer.h b/daemon/peer.h index 54f787f7f..190570d18 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -141,11 +141,18 @@ struct peer { /* Number of HTLC updates (== number of previous commit txs) */ u64 commit_tx_counter; - /* FIXME: Group closing fields together in anon struct. */ - /* Closing tx and signature once we've generated it */ - struct bitcoin_tx *close_tx; - struct bitcoin_signature our_close_sig; - + struct { + /* Our last suggested closing fee. */ + u64 our_fee; + /* If they've offered a signature, these are set: */ + struct bitcoin_signature *their_sig; + /* If their_sig is non-NULL, this is the fee. */ + u64 their_fee; + } closing; + + /* If not INPUT_NONE, send this when we have no more HTLCs. */ + enum state_input cleared; + /* Current ongoing packetflow */ struct io_data *io_data; @@ -177,6 +184,7 @@ void make_commit_txs(const tal_t *ctx, void peer_add_htlc_expiry(struct peer *peer, const struct abs_locktime *expiry); -bool peer_create_close_tx(struct peer *peer, u64 fee_satoshis); +struct bitcoin_tx *peer_create_close_tx(const tal_t *ctx, + const struct peer *peer, u64 fee); #endif /* LIGHTNING_DAEMON_PEER_H */ diff --git a/lightning.pb-c.c b/lightning.pb-c.c index 96e89abbd..0bb2eb3e2 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -738,133 +738,90 @@ void update_complete__free_unpacked assert(message->base.descriptor == &update_complete__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void close_channel__init - (CloseChannel *message) +void close_clearing__init + (CloseClearing *message) { - static CloseChannel init_value = CLOSE_CHANNEL__INIT; + static CloseClearing init_value = CLOSE_CLEARING__INIT; *message = init_value; } -size_t close_channel__get_packed_size - (const CloseChannel *message) +size_t close_clearing__get_packed_size + (const CloseClearing *message) { - assert(message->base.descriptor == &close_channel__descriptor); + assert(message->base.descriptor == &close_clearing__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t close_channel__pack - (const CloseChannel *message, +size_t close_clearing__pack + (const CloseClearing *message, uint8_t *out) { - assert(message->base.descriptor == &close_channel__descriptor); + assert(message->base.descriptor == &close_clearing__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t close_channel__pack_to_buffer - (const CloseChannel *message, +size_t close_clearing__pack_to_buffer + (const CloseClearing *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &close_channel__descriptor); + assert(message->base.descriptor == &close_clearing__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -CloseChannel * - close_channel__unpack +CloseClearing * + close_clearing__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (CloseChannel *) - protobuf_c_message_unpack (&close_channel__descriptor, + return (CloseClearing *) + protobuf_c_message_unpack (&close_clearing__descriptor, allocator, len, data); } -void close_channel__free_unpacked - (CloseChannel *message, +void close_clearing__free_unpacked + (CloseClearing *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &close_channel__descriptor); + assert(message->base.descriptor == &close_clearing__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void close_channel_complete__init - (CloseChannelComplete *message) +void close_signature__init + (CloseSignature *message) { - static CloseChannelComplete init_value = CLOSE_CHANNEL_COMPLETE__INIT; + static CloseSignature init_value = CLOSE_SIGNATURE__INIT; *message = init_value; } -size_t close_channel_complete__get_packed_size - (const CloseChannelComplete *message) +size_t close_signature__get_packed_size + (const CloseSignature *message) { - assert(message->base.descriptor == &close_channel_complete__descriptor); + assert(message->base.descriptor == &close_signature__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t close_channel_complete__pack - (const CloseChannelComplete *message, +size_t close_signature__pack + (const CloseSignature *message, uint8_t *out) { - assert(message->base.descriptor == &close_channel_complete__descriptor); + assert(message->base.descriptor == &close_signature__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t close_channel_complete__pack_to_buffer - (const CloseChannelComplete *message, +size_t close_signature__pack_to_buffer + (const CloseSignature *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &close_channel_complete__descriptor); + assert(message->base.descriptor == &close_signature__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -CloseChannelComplete * - close_channel_complete__unpack +CloseSignature * + close_signature__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (CloseChannelComplete *) - protobuf_c_message_unpack (&close_channel_complete__descriptor, + return (CloseSignature *) + protobuf_c_message_unpack (&close_signature__descriptor, allocator, len, data); } -void close_channel_complete__free_unpacked - (CloseChannelComplete *message, +void close_signature__free_unpacked + (CloseSignature *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &close_channel_complete__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void close_channel_ack__init - (CloseChannelAck *message) -{ - static CloseChannelAck init_value = CLOSE_CHANNEL_ACK__INIT; - *message = init_value; -} -size_t close_channel_ack__get_packed_size - (const CloseChannelAck *message) -{ - assert(message->base.descriptor == &close_channel_ack__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t close_channel_ack__pack - (const CloseChannelAck *message, - uint8_t *out) -{ - assert(message->base.descriptor == &close_channel_ack__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t close_channel_ack__pack_to_buffer - (const CloseChannelAck *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &close_channel_ack__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -CloseChannelAck * - close_channel_ack__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (CloseChannelAck *) - protobuf_c_message_unpack (&close_channel_ack__descriptor, - allocator, len, data); -} -void close_channel_ack__free_unpacked - (CloseChannelAck *message, - ProtobufCAllocator *allocator) -{ - assert(message->base.descriptor == &close_channel_ack__descriptor); + assert(message->base.descriptor == &close_signature__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void error__init @@ -2033,111 +1990,73 @@ const ProtobufCMessageDescriptor update_complete__descriptor = (ProtobufCMessageInit) update_complete__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor close_channel__field_descriptors[2] = +#define close_clearing__field_descriptors NULL +#define close_clearing__field_indices_by_name NULL +#define close_clearing__number_ranges NULL +const ProtobufCMessageDescriptor close_clearing__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "close_clearing", + "CloseClearing", + "CloseClearing", + "", + sizeof(CloseClearing), + 0, + close_clearing__field_descriptors, + close_clearing__field_indices_by_name, + 0, close_clearing__number_ranges, + (ProtobufCMessageInit) close_clearing__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor close_signature__field_descriptors[2] = { { - "sig", + "close_fee", 1, PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(CloseSignature, close_fee), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "sig", + 2, + PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(CloseChannel, sig), + offsetof(CloseSignature, sig), &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "close_fee", - 2, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(CloseChannel, close_fee), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, }; -static const unsigned close_channel__field_indices_by_name[] = { - 1, /* field[1] = close_fee */ - 0, /* field[0] = sig */ +static const unsigned close_signature__field_indices_by_name[] = { + 0, /* field[0] = close_fee */ + 1, /* field[1] = sig */ }; -static const ProtobufCIntRange close_channel__number_ranges[1 + 1] = +static const ProtobufCIntRange close_signature__number_ranges[1 + 1] = { { 1, 0 }, { 0, 2 } }; -const ProtobufCMessageDescriptor close_channel__descriptor = +const ProtobufCMessageDescriptor close_signature__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "close_channel", - "CloseChannel", - "CloseChannel", + "close_signature", + "CloseSignature", + "CloseSignature", "", - sizeof(CloseChannel), + sizeof(CloseSignature), 2, - close_channel__field_descriptors, - close_channel__field_indices_by_name, - 1, close_channel__number_ranges, - (ProtobufCMessageInit) close_channel__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor close_channel_complete__field_descriptors[1] = -{ - { - "sig", - 1, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(CloseChannelComplete, sig), - &signature__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned close_channel_complete__field_indices_by_name[] = { - 0, /* field[0] = sig */ -}; -static const ProtobufCIntRange close_channel_complete__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor close_channel_complete__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "close_channel_complete", - "CloseChannelComplete", - "CloseChannelComplete", - "", - sizeof(CloseChannelComplete), - 1, - close_channel_complete__field_descriptors, - close_channel_complete__field_indices_by_name, - 1, close_channel_complete__number_ranges, - (ProtobufCMessageInit) close_channel_complete__init, - NULL,NULL,NULL /* reserved[123] */ -}; -#define close_channel_ack__field_descriptors NULL -#define close_channel_ack__field_indices_by_name NULL -#define close_channel_ack__number_ranges NULL -const ProtobufCMessageDescriptor close_channel_ack__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "close_channel_ack", - "CloseChannelAck", - "CloseChannelAck", - "", - sizeof(CloseChannelAck), - 0, - close_channel_ack__field_descriptors, - close_channel_ack__field_indices_by_name, - 0, close_channel_ack__number_ranges, - (ProtobufCMessageInit) close_channel_ack__init, + close_signature__field_descriptors, + close_signature__field_indices_by_name, + 1, close_signature__number_ranges, + (ProtobufCMessageInit) close_signature__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCFieldDescriptor error__field_descriptors[1] = @@ -2178,7 +2097,7 @@ const ProtobufCMessageDescriptor error__descriptor = (ProtobufCMessageInit) error__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor pkt__field_descriptors[16] = +static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = { { "update_add_htlc", @@ -2313,37 +2232,25 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[16] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "close", + "close_clearing", 30, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), - offsetof(Pkt, close), - &close_channel__descriptor, + offsetof(Pkt, close_clearing), + &close_clearing__descriptor, NULL, 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "close_complete", + "close_signature", 31, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), - offsetof(Pkt, close_complete), - &close_channel_complete__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "close_ack", - 32, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Pkt, pkt_case), - offsetof(Pkt, close_ack), - &close_channel_ack__descriptor, + offsetof(Pkt, close_signature), + &close_signature__descriptor, NULL, 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -2374,11 +2281,10 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[16] = }, }; static const unsigned pkt__field_indices_by_name[] = { - 15, /* field[15] = auth */ - 11, /* field[11] = close */ - 13, /* field[13] = close_ack */ - 12, /* field[12] = close_complete */ - 14, /* field[14] = error */ + 14, /* field[14] = auth */ + 11, /* field[11] = close_clearing */ + 12, /* field[12] = close_signature */ + 13, /* field[13] = error */ 7, /* field[7] = open */ 8, /* field[8] = open_anchor */ 9, /* field[9] = open_commit_sig */ @@ -2397,9 +2303,9 @@ static const ProtobufCIntRange pkt__number_ranges[6 + 1] = { 9, 6 }, { 20, 7 }, { 30, 11 }, - { 40, 14 }, - { 50, 15 }, - { 0, 16 } + { 40, 13 }, + { 50, 14 }, + { 0, 15 } }; const ProtobufCMessageDescriptor pkt__descriptor = { @@ -2409,7 +2315,7 @@ const ProtobufCMessageDescriptor pkt__descriptor = "Pkt", "", sizeof(Pkt), - 16, + 15, pkt__field_descriptors, pkt__field_indices_by_name, 6, pkt__number_ranges, diff --git a/lightning.pb-c.h b/lightning.pb-c.h index be8575a00..16f0ab7c9 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -32,9 +32,8 @@ typedef struct _UpdateFailHtlc UpdateFailHtlc; typedef struct _UpdateAccept UpdateAccept; typedef struct _UpdateSignature UpdateSignature; typedef struct _UpdateComplete UpdateComplete; -typedef struct _CloseChannel CloseChannel; -typedef struct _CloseChannelComplete CloseChannelComplete; -typedef struct _CloseChannelAck CloseChannelAck; +typedef struct _CloseClearing CloseClearing; +typedef struct _CloseSignature CloseSignature; typedef struct _Error Error; typedef struct _Pkt Pkt; @@ -419,53 +418,32 @@ struct _UpdateComplete /* - * Begin cooperative close of channel. + * Start clearing out the channel HTLCs so we can close it */ -struct _CloseChannel +struct _CloseClearing +{ + ProtobufCMessage base; +}; +#define CLOSE_CLEARING__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&close_clearing__descriptor) \ + } + + +struct _CloseSignature { ProtobufCMessage base; /* - * This is our signature a new transaction which spends the anchor - * output to my open->final and your open->final, - * as per the last commit tx. - */ - Signature *sig; - /* - * Fee to pay for close transaction. + * Fee in satoshis. */ uint64_t close_fee; -}; -#define CLOSE_CHANNEL__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \ - , NULL, 0 } - - -/* - * OK, here's my sig so you can broadcast it too. We're done. - */ -struct _CloseChannelComplete -{ - ProtobufCMessage base; /* - * This is my signature for that same tx. + * Signature on the close transaction. */ Signature *sig; }; -#define CLOSE_CHANNEL_COMPLETE__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \ - , NULL } - - -/* - * Received close_channel_complete, you can close now. - */ -struct _CloseChannelAck -{ - ProtobufCMessage base; -}; -#define CLOSE_CHANNEL_ACK__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&close_channel_ack__descriptor) \ - } +#define CLOSE_SIGNATURE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&close_signature__descriptor) \ + , 0, NULL } /* @@ -495,9 +473,8 @@ typedef enum { PKT__PKT_UPDATE_DECLINE_HTLC = 6, PKT__PKT_UPDATE_FULFILL_HTLC = 7, PKT__PKT_UPDATE_FAIL_HTLC = 9, - PKT__PKT_CLOSE = 30, - PKT__PKT_CLOSE_COMPLETE = 31, - PKT__PKT_CLOSE_ACK = 32, + PKT__PKT_CLOSE_CLEARING = 30, + PKT__PKT_CLOSE_SIGNATURE = 31, PKT__PKT_ERROR = 40, } Pkt__PktCase; @@ -533,9 +510,8 @@ struct _Pkt /* * Closing */ - CloseChannel *close; - CloseChannelComplete *close_complete; - CloseChannelAck *close_ack; + CloseClearing *close_clearing; + CloseSignature *close_signature; /* * Unexpected issue. */ @@ -870,62 +846,43 @@ UpdateComplete * void update_complete__free_unpacked (UpdateComplete *message, ProtobufCAllocator *allocator); -/* CloseChannel methods */ -void close_channel__init - (CloseChannel *message); -size_t close_channel__get_packed_size - (const CloseChannel *message); -size_t close_channel__pack - (const CloseChannel *message, +/* CloseClearing methods */ +void close_clearing__init + (CloseClearing *message); +size_t close_clearing__get_packed_size + (const CloseClearing *message); +size_t close_clearing__pack + (const CloseClearing *message, uint8_t *out); -size_t close_channel__pack_to_buffer - (const CloseChannel *message, +size_t close_clearing__pack_to_buffer + (const CloseClearing *message, ProtobufCBuffer *buffer); -CloseChannel * - close_channel__unpack +CloseClearing * + close_clearing__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void close_channel__free_unpacked - (CloseChannel *message, +void close_clearing__free_unpacked + (CloseClearing *message, ProtobufCAllocator *allocator); -/* CloseChannelComplete methods */ -void close_channel_complete__init - (CloseChannelComplete *message); -size_t close_channel_complete__get_packed_size - (const CloseChannelComplete *message); -size_t close_channel_complete__pack - (const CloseChannelComplete *message, +/* CloseSignature methods */ +void close_signature__init + (CloseSignature *message); +size_t close_signature__get_packed_size + (const CloseSignature *message); +size_t close_signature__pack + (const CloseSignature *message, uint8_t *out); -size_t close_channel_complete__pack_to_buffer - (const CloseChannelComplete *message, +size_t close_signature__pack_to_buffer + (const CloseSignature *message, ProtobufCBuffer *buffer); -CloseChannelComplete * - close_channel_complete__unpack +CloseSignature * + close_signature__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void close_channel_complete__free_unpacked - (CloseChannelComplete *message, - ProtobufCAllocator *allocator); -/* CloseChannelAck methods */ -void close_channel_ack__init - (CloseChannelAck *message); -size_t close_channel_ack__get_packed_size - (const CloseChannelAck *message); -size_t close_channel_ack__pack - (const CloseChannelAck *message, - uint8_t *out); -size_t close_channel_ack__pack_to_buffer - (const CloseChannelAck *message, - ProtobufCBuffer *buffer); -CloseChannelAck * - close_channel_ack__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void close_channel_ack__free_unpacked - (CloseChannelAck *message, +void close_signature__free_unpacked + (CloseSignature *message, ProtobufCAllocator *allocator); /* Error methods */ void error__init @@ -1018,14 +975,11 @@ typedef void (*UpdateSignature_Closure) typedef void (*UpdateComplete_Closure) (const UpdateComplete *message, void *closure_data); -typedef void (*CloseChannel_Closure) - (const CloseChannel *message, +typedef void (*CloseClearing_Closure) + (const CloseClearing *message, void *closure_data); -typedef void (*CloseChannelComplete_Closure) - (const CloseChannelComplete *message, - void *closure_data); -typedef void (*CloseChannelAck_Closure) - (const CloseChannelAck *message, +typedef void (*CloseSignature_Closure) + (const CloseSignature *message, void *closure_data); typedef void (*Error_Closure) (const Error *message, @@ -1057,9 +1011,8 @@ extern const ProtobufCMessageDescriptor update_fail_htlc__descriptor; extern const ProtobufCMessageDescriptor update_accept__descriptor; extern const ProtobufCMessageDescriptor update_signature__descriptor; extern const ProtobufCMessageDescriptor update_complete__descriptor; -extern const ProtobufCMessageDescriptor close_channel__descriptor; -extern const ProtobufCMessageDescriptor close_channel_complete__descriptor; -extern const ProtobufCMessageDescriptor close_channel_ack__descriptor; +extern const ProtobufCMessageDescriptor close_clearing__descriptor; +extern const ProtobufCMessageDescriptor close_signature__descriptor; extern const ProtobufCMessageDescriptor error__descriptor; extern const ProtobufCMessageDescriptor pkt__descriptor; diff --git a/lightning.proto b/lightning.proto index 45c5b0368..e2d2909da 100644 --- a/lightning.proto +++ b/lightning.proto @@ -171,24 +171,15 @@ message update_complete { required sha256_hash revocation_preimage = 1; } -// Begin cooperative close of channel. -message close_channel { - // This is our signature a new transaction which spends the anchor - // output to my open->final and your open->final, - // as per the last commit tx. - required signature sig = 1; - // Fee to pay for close transaction. - required uint64 close_fee = 2; +// Start clearing out the channel HTLCs so we can close it +message close_clearing { } -// OK, here's my sig so you can broadcast it too. We're done. -message close_channel_complete { - // This is my signature for that same tx. - required signature sig = 1; -} - -// Received close_channel_complete, you can close now. -message close_channel_ack { +message close_signature { + // Fee in satoshis. + required uint64 close_fee = 1; + // Signature on the close transaction. + required signature sig = 2; } // This means we're going to hang up; it's to help diagnose only! @@ -215,9 +206,8 @@ message pkt { update_fulfill_htlc update_fulfill_htlc = 7; update_fail_htlc update_fail_htlc = 9; // Closing - close_channel close = 30; - close_channel_complete close_complete = 31; - close_channel_ack close_ack = 32; + close_clearing close_clearing = 30; + close_signature close_signature = 31; // Unexpected issue. error error = 40; diff --git a/state.c b/state.c index 5f4ac70fa..668b7f442 100644 --- a/state.c +++ b/state.c @@ -276,14 +276,14 @@ enum command_status state(const tal_t *ctx, BITCOIN_ANCHOR_DEPTHOK, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_closing; - } else if (input_is(input, PKT_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, BITCOIN_ANCHOR_DEPTHOK, INPUT_NONE); complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_closing; + goto accept_clearing; } else if (input_is_pkt(input)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -344,14 +344,14 @@ enum command_status state(const tal_t *ctx, BITCOIN_ANCHOR_DEPTHOK, BITCOIN_ANCHOR_TIMEOUT); complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_closing; - } else if (input_is(input, PKT_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, BITCOIN_ANCHOR_DEPTHOK, BITCOIN_ANCHOR_TIMEOUT); complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_closing; + goto accept_clearing; } else if (input_is_pkt(input)) { /* We no longer care about anchor depth. */ peer_unwatch_anchor_depth(peer, @@ -387,10 +387,10 @@ enum command_status state(const tal_t *ctx, goto them_unilateral; } else if (input_is(input, CMD_CLOSE)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_closing; - } else if (input_is(input, PKT_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_closing; + goto accept_clearing; } else if (input_is_pkt(input)) { complete_cmd(peer, &cstatus, CMD_FAIL); goto unexpected_pkt; @@ -427,7 +427,7 @@ enum command_status state(const tal_t *ctx, return next_state(peer, cstatus, prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT)); } else if (input_is(input, CMD_CLOSE)) { - goto start_closing; + goto start_clearing; } else if (input_is(input, PKT_UPDATE_ADD_HTLC)) { change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); goto accept_htlc_add; @@ -443,8 +443,8 @@ enum command_status state(const tal_t *ctx, goto old_commit_spotted; } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { goto anchor_unspent; - } else if (input_is(input, PKT_CLOSE)) { - goto accept_closing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { + goto accept_clearing; } else if (input_is_pkt(input)) { goto unexpected_pkt; } @@ -522,11 +522,11 @@ enum command_status state(const tal_t *ctx, } else if (input_is(input, CMD_CLOSE)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_closing; - } else if (input_is(input, PKT_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_closing; + goto accept_clearing; } else if (input_is_pkt(input)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); @@ -558,14 +558,14 @@ enum command_status state(const tal_t *ctx, peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); goto old_commit_spotted; - } else if (input_is(input, PKT_CLOSE)) { + } else if (input_is(input, PKT_CLOSE_CLEARING)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_closing; + goto accept_clearing; } else if (input_is(input, CMD_CLOSE)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_closing; + goto start_clearing; } else if (input_is_pkt(input)) { peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); @@ -599,81 +599,81 @@ enum command_status state(const tal_t *ctx, goto old_commit_spotted; } else if (input_is(input, CMD_CLOSE)) { peer_htlc_aborted(peer); - goto start_closing; - } else if (input_is(input, PKT_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_CLOSE_CLEARING)) { peer_htlc_aborted(peer); - goto accept_closing; + goto accept_clearing; } else if (input_is_pkt(input)) { peer_htlc_aborted(peer); goto unexpected_pkt; } break; + case STATE_US_CLEARING: + /* This is their reply once they're clearing too. */ + if (input_is(input, PKT_CLOSE_CLEARING)) { + err = accept_pkt_close_clearing(ctx, peer, idata->pkt); + if (err) + goto err_start_unilateral_close; - case STATE_WAIT_FOR_CLOSE_COMPLETE: - if (input_is(input, PKT_CLOSE_COMPLETE)) { - peer_unwatch_close_timeout(peer, - INPUT_CLOSE_COMPLETE_TIMEOUT); - err = accept_pkt_close_complete(ctx, peer, idata->pkt); - if (err) - goto err_start_unilateral_close_already_closing; - queue_pkt(out, - pkt_close_ack(ctx, peer)); - queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer)); - change_peer_cond(peer, PEER_CLOSING, PEER_CLOSED); - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); - } else if (input_is(input, PKT_CLOSE)) { - peer_unwatch_close_timeout(peer, - INPUT_CLOSE_COMPLETE_TIMEOUT); - /* We can use the sig just like CLOSE_COMPLETE */ - err = accept_pkt_simultaneous_close(ctx, peer, - idata->pkt); - if (err) - goto err_start_unilateral_close_already_closing; - queue_pkt(out, - pkt_close_ack(ctx, peer)); - queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer)); - set_peer_cond(peer, PEER_CLOSED); - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); - } else if (input_is(input, PKT_ERROR)) { - peer_unwatch_close_timeout(peer, - INPUT_CLOSE_COMPLETE_TIMEOUT); - peer_unexpected_pkt(peer, idata->pkt); - goto start_unilateral_close_already_closing; + /* Notify us when there are no more htlcs in + * either commit tx */ + peer_watch_htlcs_cleared(peer, INPUT_HTLCS_CLEARED); + + return next_state(peer, cstatus, STATE_BOTH_CLEARING); + /* FIXME: We must continue to allow fulfill & fail! */ + } else if (input_is(input, CMD_SEND_HTLC_FAIL) + || input_is(input, CMD_SEND_HTLC_FULFILL)) { + err = pkt_err(ctx, "FIXME: cmd during clearing."); + goto err_start_unilateral_close; } else if (input_is_pkt(input)) { - /* We ignore all other packets while closing. */ + /* FIXME: We must continue to allow add, fulfill & fail packets */ + goto unexpected_pkt; + } + break; + case STATE_BOTH_CLEARING: + if (input_is(input, INPUT_HTLCS_CLEARED)) { + goto start_closing_cleared; + } else if (input_is(input, CMD_SEND_HTLC_FAIL) + || input_is(input, CMD_SEND_HTLC_FULFILL)) { + err = pkt_err(ctx, "FIXME: cmd during clearing."); + goto err_start_unilateral_close; + } else if (input_is_pkt(input)) { + /* FIXME: We must continue to allow fulfill & fail packets */ + goto unexpected_pkt; + } + break; + case STATE_WAIT_FOR_CLOSE_SIG: + if (input_is(input, PKT_CLOSE_SIGNATURE)) { + bool matches; + err = accept_pkt_close_sig(ctx, peer, idata->pkt, + &matches); + if (err) + goto err_start_unilateral_close; + + /* Did they offer the same fee we did? */ + if (matches) { + peer_unwatch_close_timeout(peer, + INPUT_CLOSE_COMPLETE_TIMEOUT); + + /* Send close TX. */ + queue_tx_broadcast(broadcast, + bitcoin_close(ctx, peer)); + change_peer_cond(peer, + PEER_CLOSING, PEER_CLOSED); + return next_state(peer, cstatus, + STATE_CLOSE_WAIT_CLOSE); + } + + /* Offer the new fee. */ + queue_pkt(out, pkt_close_signature(ctx, peer)); return unchanged_state(cstatus); } else if (input_is(input, INPUT_CLOSE_COMPLETE_TIMEOUT)) { - /* They didn't respond in time. Unilateral close. */ err = pkt_err(ctx, "Close timed out"); - goto err_start_unilateral_close_already_closing; - } - peer_unwatch_close_timeout(peer, INPUT_CLOSE_COMPLETE_TIMEOUT); - goto fail_during_close; - - case STATE_WAIT_FOR_CLOSE_ACK: - if (input_is(input, PKT_CLOSE_ACK)) { - err = accept_pkt_close_ack(ctx, peer, idata->pkt); - if (err) - queue_pkt(out, err); - set_peer_cond(peer, PEER_CLOSED); - /* Just wait for close to happen now. */ - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); + goto err_start_unilateral_close; } else if (input_is_pkt(input)) { - peer_unexpected_pkt(peer, idata->pkt); - /* Don't reply to an error with an error. */ - if (!input_is(input, PKT_ERROR)) { - queue_pkt(out, - pkt_err_unexpected(ctx, idata->pkt)); - } - set_peer_cond(peer, PEER_CLOSED); - /* Just wait for close to happen now. */ - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); - } else if (input_is(input, BITCOIN_CLOSE_DONE)) { - /* They didn't ack, but we're closed, so stop. */ - set_peer_cond(peer, PEER_CLOSED); - return next_state(peer, cstatus, STATE_CLOSED); + goto unexpected_pkt; } - goto fail_during_close; + break; /* Close states are regular: handle as a group. */ case STATE_CLOSE_WAIT_HTLCS: @@ -949,8 +949,20 @@ start_unilateral_close: /* * Close unilaterally. */ + /* No more inputs, no more commands. */ set_peer_cond(peer, PEER_CLOSED); + + /* + * If they sent us a close tx, that's always cheaper than + * broadcasting our last commit tx, and our funds are not + * timelocked. + */ + if (peer_has_close_sig(peer)) { + queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer)); + return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE); + } + tx = bitcoin_commit(ctx, peer); queue_tx_broadcast(broadcast, tx); peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED); @@ -965,28 +977,6 @@ start_unilateral_close: return next_state(peer, cstatus, STATE_CLOSE_WAIT_OURCOMMIT); -err_start_unilateral_close_already_closing: - /* - * They timed out, or were broken; we are going to close unilaterally. - */ - queue_pkt(out, err); - -start_unilateral_close_already_closing: - /* - * Close unilaterally. - */ - /* No more inputs, no more commands. */ - set_peer_cond(peer, PEER_CLOSED); - tx = bitcoin_commit(ctx, peer); - queue_tx_broadcast(broadcast, tx); - peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED); - - /* We agreed to close: shouldn't have any HTLCs */ - if (committed_to_htlcs(peer)) - return next_state(peer, cstatus, STATE_ERR_INTERNAL); - - return next_state(peer, cstatus, STATE_CLOSE_WAIT_CLOSE_OURCOMMIT); - them_unilateral: assert(input == BITCOIN_ANCHOR_THEIRSPEND); @@ -1045,36 +1035,40 @@ accept_htlc_fulfill: return next_state(peer, cstatus, prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG)); -start_closing: +start_clearing: /* - * Start a mutual close. + * Start a mutual close: tell them we want to clear. */ - /* Protocol doesn't (currently?) allow closing with HTLCs. */ - if (committed_to_htlcs(peer)) { - err = pkt_err(ctx, "Close forced due to HTLCs"); - goto err_start_unilateral_close; - } - peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT); + queue_pkt(out, pkt_close_clearing(ctx, peer)); /* No more commands, we're already closing. */ set_peer_cond(peer, PEER_CLOSING); - /* As soon as we send packet, they could close. */ - queue_pkt(out, pkt_close(ctx, peer)); - return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_COMPLETE); + return next_state(peer, cstatus, STATE_US_CLEARING); -accept_closing: - err = accept_pkt_close(ctx, peer, idata->pkt); +start_closing_cleared: + /* As soon as we send packet, they could close. */ + peer_calculate_close_fee(peer); + peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT); + queue_pkt(out, pkt_close_signature(ctx, peer)); + return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_SIG); + +accept_clearing: + err = accept_pkt_close_clearing(ctx, peer, idata->pkt); if (err) goto err_start_unilateral_close; - peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_NONE); - /* Send close TX. */ - queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer)); - queue_pkt(out, pkt_close_complete(ctx, peer)); + + /* Notify us when there are no more htlcs in either commit tx */ + peer_watch_htlcs_cleared(peer, INPUT_HTLCS_CLEARED); + /* No more commands, we're already closing. */ set_peer_cond(peer, PEER_CLOSING); - return next_state(peer, cstatus, STATE_WAIT_FOR_CLOSE_ACK); - + + /* Tell them we're clearing too. */ + queue_pkt(out, pkt_close_clearing(ctx, peer)); + + return next_state(peer, cstatus, STATE_BOTH_CLEARING); + instant_close: /* * Closing, but we haven't sent anything to the blockchain so @@ -1088,48 +1082,6 @@ instant_close: return next_state(peer, cstatus, STATE_ERR_INTERNAL); return next_state(peer, cstatus, STATE_CLOSED); -fail_during_close: - /* - * We've broadcast close tx; if anything goes wrong, we just close - * connection and wait. - */ - set_peer_cond(peer, PEER_CLOSED); - - /* Once close tx is deep enough, we consider it done. */ - if (input_is(input, BITCOIN_CLOSE_DONE)) { - return next_state(peer, cstatus, STATE_CLOSED); - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - /* A reorganization could make this happen. */ - tx = bitcoin_spend_theirs(ctx, peer, idata->btc); - queue_tx_broadcast(broadcast, tx); - peer_watch_tx(peer, tx, BITCOIN_SPEND_THEIRS_DONE); - if (peer_watch_their_htlc_outputs(peer, idata->btc, - BITCOIN_HTLC_TOUS_TIMEOUT, - BITCOIN_HTLC_TOTHEM_SPENT, - BITCOIN_HTLC_TOTHEM_TIMEOUT)) { - /* Expect either close or spendthem to complete */ - /* FIXME: Make sure caller uses INPUT_RVAL - * if they were in the middle of FULFILL! */ - return next_state(peer, cstatus, - STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS); - } - return next_state(peer, cstatus, - STATE_CLOSE_WAIT_SPENDTHEM_CLOSE); - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - tx = bitcoin_steal(ctx, peer, idata->btc); - if (!tx) - return next_state(peer, cstatus, - STATE_ERR_INFORMATION_LEAK); - queue_tx_broadcast(broadcast, tx); - peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE); - /* Expect either close or steal to complete */ - return next_state(peer, cstatus, - STATE_CLOSE_WAIT_STEAL_CLOSE); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - return next_state(peer, cstatus, STATE_ERR_ANCHOR_LOST); - } - return next_state(peer, cstatus, STATE_ERR_INTERNAL); - old_commit_spotted: /* * bitcoind reported a broadcast of the not-latest commit tx. diff --git a/state.h b/state.h index 3547222a0..87f6ec2a6 100644 --- a/state.h +++ b/state.h @@ -111,9 +111,8 @@ Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer); Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer); Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer); Pkt *pkt_err(const tal_t *ctx, const char *fmt, ...); -Pkt *pkt_close(const tal_t *ctx, const struct peer *peer); -Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer); -Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer); +Pkt *pkt_close_clearing(const tal_t *ctx, const struct peer *peer); +Pkt *pkt_close_signature(const tal_t *ctx, const struct peer *peer); Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt); /* Process various packets: return an error packet on failure. */ @@ -151,16 +150,9 @@ Pkt *accept_pkt_update_signature(const tal_t *ctx, struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt); - -Pkt *accept_pkt_close_complete(const tal_t *ctx, - struct peer *peer, const Pkt *pkt); - -Pkt *accept_pkt_simultaneous_close(const tal_t *ctx, - struct peer *peer, - const Pkt *pkt); - -Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_close_clearing(const tal_t *ctx, struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt, + bool *matches); /** * committed_to_htlcs: do we have any locked-in HTLCs? @@ -170,6 +162,14 @@ Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt); */ bool committed_to_htlcs(const struct peer *peer); +/** + * peer_has_close_sig: do we have a valid close_sig from them? + * @peer: the state data for this peer. + * + * We use any acceptable close tx, if we have one, in preference to a commit tx. + */ +bool peer_has_close_sig(const struct peer *peer); + /** * peer_watch_anchor: create a watch for the anchor transaction. * @peer: the state data for this peer. @@ -336,6 +336,20 @@ void peer_unwatch_htlc_spend(struct peer *peer, const struct htlc *htlc, enum state_input all_done); +/** + * peer_watch_htlcs_cleared: tell us when no HTLCs are in commit txs. + * @peer: the state data for this peer. + * @all_done: input to give when all HTLCs are done. + */ +void peer_watch_htlcs_cleared(struct peer *peer, + enum state_input all_done); + +/** + * peer_calculate_close_fee: figure out what the fee for closing is. + * @peer: the state data for this peer. + */ +void peer_calculate_close_fee(struct peer *peer); + /* Start creation of the bitcoin anchor tx. */ void bitcoin_create_anchor(struct peer *peer, enum state_input done); diff --git a/state_types.h b/state_types.h index 5d2ba355e..57c6eeaea 100644 --- a/state_types.h +++ b/state_types.h @@ -52,10 +52,12 @@ enum state { /* * Closing. */ - /* We told them to close, waiting for complete msg. */ - STATE_WAIT_FOR_CLOSE_COMPLETE, - /* They told us to close, waiting for ack msg. */ - STATE_WAIT_FOR_CLOSE_ACK, + /* We told them to clear. */ + STATE_US_CLEARING, + /* They told us to clear, or acked our CLEARING. */ + STATE_BOTH_CLEARING, + /* We're cleared, waiting for close signature / negotiation */ + STATE_WAIT_FOR_CLOSE_SIG, /* All closed. */ STATE_CLOSED, @@ -204,9 +206,8 @@ enum state_input { PKT_UPDATE_COMPLETE = PKT__PKT_UPDATE_COMPLETE, /* Mutual close sequence. */ - PKT_CLOSE = PKT__PKT_CLOSE, - PKT_CLOSE_COMPLETE = PKT__PKT_CLOSE_COMPLETE, - PKT_CLOSE_ACK = PKT__PKT_CLOSE_ACK, + PKT_CLOSE_CLEARING = PKT__PKT_CLOSE_CLEARING, + PKT_CLOSE_SIGNATURE = PKT__PKT_CLOSE_SIGNATURE, /* Something unexpected went wrong. */ PKT_ERROR = PKT__PKT_ERROR, @@ -256,6 +257,9 @@ enum state_input { /* We are not watching any HTLCs any more. */ INPUT_NO_MORE_HTLCS, + /* No more HTLCs in either commitment tx. */ + INPUT_HTLCS_CLEARED, + /* * Timeouts. */