Skip to content

Commit b423b33

Browse files
committed
protocol: implement close as per BOLT #2.
We don't actually implement closing when we have HTLCs (we should allow it, as that's what the clearing phase is for), since soon we'll rewrite HTLC to match the async HTLC protocol of BOLT #2. Note that this folds the close paths, using a simple check if we have a close transaction. That's a slight state layer violation, but reduces code duplication. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent afedf0e commit b423b33

File tree

10 files changed

+502
-609
lines changed

10 files changed

+502
-609
lines changed

daemon/lightningd.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,21 @@ static void default_config(struct config *config)
147147

148148
static void check_config(struct lightningd_state *dstate)
149149
{
150+
/* BOLT #2:
151+
* The sender MUST set `close_fee` lower than or equal to the
152+
* fee of the final commitment transaction, and MUST set
153+
* `close_fee` to an even number of satoshis.
154+
*/
150155
if (dstate->config.closing_fee > dstate->config.commitment_fee)
151156
fatal("Closing fee %"PRIu64
152157
" can't exceed commitment fee %"PRIu64,
153158
dstate->config.closing_fee,
154159
dstate->config.commitment_fee);
155160

161+
if (dstate->config.closing_fee & 1)
162+
fatal("Closing fee %"PRIu64 "must be even.",
163+
dstate->config.closing_fee);
164+
156165
if (dstate->config.commitment_fee_min > dstate->config.commitment_fee)
157166
fatal("Minumum fee %"PRIu64
158167
" can't exceed commitment fee %"PRIu64,

daemon/packets.c

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -243,35 +243,29 @@ Pkt *pkt_err(const tal_t *ctx, const char *msg, ...)
243243
return make_pkt(ctx, PKT__PKT_ERROR, e);
244244
}
245245

246-
Pkt *pkt_close(const tal_t *ctx, const struct peer *peer)
246+
Pkt *pkt_close_clearing(const tal_t *ctx, const struct peer *peer)
247247
{
248-
CloseChannel *c = tal(ctx, CloseChannel);
248+
CloseClearing *c = tal(ctx, CloseClearing);
249249

250-
close_channel__init(c);
250+
close_clearing__init(c);
251251

252-
c->close_fee = peer->close_tx->fee;
253-
c->sig = signature_to_proto(c, &peer->our_close_sig.sig);
254-
255-
return make_pkt(ctx, PKT__PKT_CLOSE, c);
252+
return make_pkt(ctx, PKT__PKT_CLOSE_CLEARING, c);
256253
}
257254

258-
Pkt *pkt_close_complete(const tal_t *ctx, const struct peer *peer)
255+
Pkt *pkt_close_signature(const tal_t *ctx, const struct peer *peer)
259256
{
260-
CloseChannelComplete *c = tal(ctx, CloseChannelComplete);
261-
262-
close_channel_complete__init(c);
263-
assert(peer->close_tx);
264-
c->sig = signature_to_proto(c, &peer->our_close_sig.sig);
257+
CloseSignature *c = tal(ctx, CloseSignature);
258+
struct bitcoin_tx *close_tx;
259+
struct signature our_close_sig;
265260

266-
return make_pkt(ctx, PKT__PKT_CLOSE_COMPLETE, c);
267-
}
261+
close_signature__init(c);
262+
close_tx = peer_create_close_tx(ctx, peer, peer->closing.our_fee);
268263

269-
Pkt *pkt_close_ack(const tal_t *ctx, const struct peer *peer)
270-
{
271-
CloseChannelAck *a = tal(ctx, CloseChannelAck);
264+
peer_sign_mutual_close(peer, close_tx, &our_close_sig);
265+
c->sig = signature_to_proto(c, &our_close_sig);
266+
c->close_fee = peer->closing.our_fee;
272267

273-
close_channel_ack__init(a);
274-
return make_pkt(ctx, PKT__PKT_CLOSE_ACK, a);
268+
return make_pkt(ctx, PKT__PKT_CLOSE_SIGNATURE, c);
275269
}
276270

277271
Pkt *pkt_err_unexpected(const tal_t *ctx, const Pkt *pkt)
@@ -721,68 +715,84 @@ Pkt *accept_pkt_update_signature(const tal_t *ctx,
721715
return NULL;
722716
}
723717

724-
static bool peer_sign_close_tx(struct peer *peer, const Signature *theirs)
718+
Pkt *accept_pkt_close_clearing(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
719+
{
720+
/* FIXME: Reject unknown odd fields? */
721+
return NULL;
722+
}
723+
724+
Pkt *accept_pkt_close_sig(const tal_t *ctx, struct peer *peer, const Pkt *pkt,
725+
bool *matches)
725726
{
727+
const CloseSignature *c = pkt->close_signature;
728+
struct bitcoin_tx *close_tx;
726729
struct bitcoin_signature theirsig;
727730

728-
/* We never sign twice! */
729-
assert(peer->close_tx->input[0].script_length == 0);
731+
/* BOLT #2:
730732
731-
theirsig.stype = SIGHASH_ALL;
732-
if (!proto_to_signature(theirs, &theirsig.sig))
733-
return false;
734-
735-
/* Their sig + ours should sign the close tx. */
736-
if (!check_2of2_sig(peer->dstate->secpctx,
737-
peer->close_tx, 0,
738-
peer->anchor.redeemscript,
739-
tal_count(peer->anchor.redeemscript),
740-
&peer->them.commitkey, &peer->us.commitkey,
741-
&theirsig, &peer->our_close_sig))
742-
return false;
743-
744-
/* Complete the close_tx, using signatures. */
745-
peer->close_tx->input[0].script
746-
= scriptsig_p2sh_2of2(peer->close_tx,
747-
&theirsig, &peer->our_close_sig,
748-
&peer->them.commitkey,
749-
&peer->us.commitkey);
750-
peer->close_tx->input[0].script_length
751-
= tal_count(peer->close_tx->input[0].script);
752-
return true;
753-
}
754-
755-
Pkt *accept_pkt_close(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
756-
{
757-
const CloseChannel *c = pkt->close;
758-
759-
/* FIXME: Don't accept tiny close fee! */
760-
if (!peer_create_close_tx(peer, c->close_fee))
733+
* The sender MUST set `close_fee` lower than or equal to the fee of the
734+
* final commitment transaction, and MUST set `close_fee` to an even
735+
* number of satoshis.
736+
*/
737+
if (c->close_fee & 1 || c->close_fee > peer->them.commit_fee)
761738
return pkt_err(ctx, "Invalid close fee");
762739

763-
if (!peer_sign_close_tx(peer, c->sig))
764-
return pkt_err(ctx, "Invalid signature");
765-
return NULL;
766-
}
740+
/* FIXME: Don't accept tiny fee at all? */
741+
742+
/* BOLT #2:
743+
... otherwise it SHOULD propose a
744+
value strictly between the received `close_fee` and its
745+
previously-sent `close_fee`.
746+
*/
747+
if (peer->closing.their_sig) {
748+
/* We want more, they should give more. */
749+
if (peer->closing.our_fee > peer->closing.their_fee) {
750+
if (c->close_fee <= peer->closing.their_fee)
751+
return pkt_err(ctx, "Didn't increase close fee");
752+
} else {
753+
if (c->close_fee >= peer->closing.their_fee)
754+
return pkt_err(ctx, "Didn't decrease close fee");
755+
}
756+
}
767757

768-
Pkt *accept_pkt_close_complete(const tal_t *ctx,
769-
struct peer *peer, const Pkt *pkt)
770-
{
771-
const CloseChannelComplete *c = pkt->close_complete;
772-
if (!peer_sign_close_tx(peer, c->sig))
758+
/* BOLT #2:
759+
*
760+
* The receiver MUST check `sig` is valid for the close
761+
* transaction, and MUST fail the connection if it is not. */
762+
theirsig.stype = SIGHASH_ALL;
763+
if (!proto_to_signature(c->sig, &theirsig.sig))
764+
return pkt_err(ctx, "Invalid signature format");
765+
766+
close_tx = peer_create_close_tx(ctx, peer, c->close_fee);
767+
if (!check_tx_sig(peer->dstate->secpctx, close_tx, 0,
768+
peer->anchor.redeemscript,
769+
tal_count(peer->anchor.redeemscript),
770+
&peer->them.commitkey, &theirsig))
773771
return pkt_err(ctx, "Invalid signature");
774-
return NULL;
775-
}
776772

777-
Pkt *accept_pkt_simultaneous_close(const tal_t *ctx,
778-
struct peer *peer,
779-
const Pkt *pkt)
780-
{
781-
FIXME_STUB(peer);
782-
}
773+
tal_free(peer->closing.their_sig);
774+
peer->closing.their_sig = tal_dup(peer,
775+
struct bitcoin_signature, &theirsig);
776+
peer->closing.their_fee = c->close_fee;
783777

784-
/* FIXME: Since this packet is empty, is it worth having? */
785-
Pkt *accept_pkt_close_ack(const tal_t *ctx, struct peer *peer, const Pkt *pkt)
786-
{
778+
if (peer->closing.our_fee == peer->closing.their_fee) {
779+
*matches = true;
780+
} else {
781+
/* Adjust our fee to close on their fee. */
782+
u64 sum;
783+
784+
/* Beware overflow! */
785+
sum = (u64)peer->closing.our_fee + peer->closing.their_fee;
786+
787+
peer->closing.our_fee = sum / 2;
788+
if (peer->closing.our_fee & 1)
789+
peer->closing.our_fee++;
790+
791+
/* FIXME: Fees may *now* be equal, and they'll
792+
* consider this an ACK! */
793+
}
794+
*matches = false;
795+
796+
/* FIXME: Dynamic fee! */
787797
return NULL;
788798
}

0 commit comments

Comments
 (0)