diff --git a/daemon/jsonrpc.c b/daemon/jsonrpc.c index 196c387df..b6184eeaa 100644 --- a/daemon/jsonrpc.c +++ b/daemon/jsonrpc.c @@ -252,6 +252,7 @@ static const struct json_command *cmdlist[] = { &newhtlc_command, &fulfillhtlc_command, &failhtlc_command, + &commit_command, &close_command, /* Developer/debugging options. */ &echo_command, diff --git a/daemon/jsonrpc.h b/daemon/jsonrpc.h index a0edd9e1a..f65e672e0 100644 --- a/daemon/jsonrpc.h +++ b/daemon/jsonrpc.h @@ -61,6 +61,7 @@ extern const struct json_command getpeers_command; extern const struct json_command newhtlc_command; extern const struct json_command fulfillhtlc_command; extern const struct json_command failhtlc_command; +extern const struct json_command commit_command; extern const struct json_command mocktime_command; extern const struct json_command close_command; #endif /* LIGHTNING_DAEMON_JSONRPC_H */ diff --git a/daemon/packets.c b/daemon/packets.c index 66b080df9..0262ca4ef 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -1,6 +1,7 @@ #include "bitcoin/script.h" #include "bitcoin/tx.h" #include "close_tx.h" +#include "commit_tx.h" #include "controlled_time.h" #include "find_p2sh_out.h" #include "lightningd.h" @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -68,13 +70,15 @@ static Pkt *make_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) return pkt; } -static void queue_raw_pkt(struct peer *peer, Pkt *pkt) +static void queue_raw_pkt(struct peer *peer, Pkt *pkt, + void (*ack_cb)(struct peer *peer, void *arg), + void *ack_arg) { size_t n = tal_count(peer->outpkt); tal_resize(&peer->outpkt, n+1); peer->outpkt[n].pkt = pkt; - peer->outpkt[n].ack_cb = NULL; - peer->outpkt[n].ack_arg = NULL; + peer->outpkt[n].ack_cb = ack_cb; + peer->outpkt[n].ack_arg = ack_arg; /* In case it was waiting for output. */ io_wake(peer); @@ -82,15 +86,29 @@ static void queue_raw_pkt(struct peer *peer, Pkt *pkt) static void queue_pkt(struct peer *peer, Pkt__PktCase type, const void *msg) { - queue_raw_pkt(peer, make_pkt(peer, type, msg)); + queue_raw_pkt(peer, make_pkt(peer, type, msg), NULL, NULL); +} + +static void queue_pkt_with_ack(struct peer *peer, Pkt__PktCase type, + const void *msg, + void (*ack_cb)(struct peer *peer, void *arg), + void *ack_arg) +{ + queue_raw_pkt(peer, make_pkt(peer, type, msg), ack_cb, ack_arg); } void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor) { OpenChannel *o = tal(peer, OpenChannel); + /* Set up out commit info now: rest gets done in setup_first_commit + * once anchor is established. */ + peer->us.commit = talz(peer, struct commit_info); + peer->us.commit->revocation_hash = peer->us.next_revocation_hash; + peer_get_revocation_hash(peer, 1, &peer->us.next_revocation_hash); + open_channel__init(o); - o->revocation_hash = sha256_to_proto(o, &peer->us.revocation_hash); + o->revocation_hash = sha256_to_proto(o, &peer->us.commit->revocation_hash); o->next_revocation_hash = sha256_to_proto(o, &peer->us.next_revocation_hash); o->commit_key = pubkey_to_proto(o, &peer->us.commitkey); o->final_key = pubkey_to_proto(o, &peer->us.finalkey); @@ -113,7 +131,6 @@ void queue_pkt_open(struct peer *peer, OpenChannel__AnchorOffer anchor) void queue_pkt_anchor(struct peer *peer) { - struct signature sig; OpenAnchor *a = tal(peer, OpenAnchor); open_anchor__init(a); @@ -121,25 +138,40 @@ void queue_pkt_anchor(struct peer *peer) a->output_index = peer->anchor.index; a->amount = peer->anchor.satoshis; + /* This shouldn't happen! */ + if (!setup_first_commit(peer)) { + queue_pkt_err(peer, + pkt_err(peer, + "Own anchor has insufficient funds")); + return; + } + /* Sign their commit sig */ - peer_sign_theircommit(peer, peer->them.commit, &sig); - a->commit_sig = signature_to_proto(a, &sig); + peer->them.commit->sig = tal(peer->them.commit, + struct bitcoin_signature); + peer->them.commit->sig->stype = SIGHASH_ALL; + peer_sign_theircommit(peer, peer->them.commit->tx, + &peer->them.commit->sig->sig); + a->commit_sig = signature_to_proto(a, &peer->them.commit->sig->sig); queue_pkt(peer, PKT__PKT_OPEN_ANCHOR, a); } void queue_pkt_open_commit_sig(struct peer *peer) { - struct signature sig; OpenCommitSig *s = tal(peer, OpenCommitSig); open_commit_sig__init(s); - dump_tx("Creating sig for:", peer->them.commit); + dump_tx("Creating sig for:", peer->them.commit->tx); dump_key("Using key:", &peer->us.commitkey); - peer_sign_theircommit(peer, peer->them.commit, &sig); - s->sig = signature_to_proto(s, &sig); + peer->them.commit->sig = tal(peer->them.commit, + struct bitcoin_signature); + peer->them.commit->sig->stype = SIGHASH_ALL; + peer_sign_theircommit(peer, peer->them.commit->tx, + &peer->them.commit->sig->sig); + s->sig = signature_to_proto(s, &peer->them.commit->sig->sig); queue_pkt(peer, PKT__PKT_OPEN_COMMIT_SIG, s); } @@ -152,6 +184,20 @@ void queue_pkt_open_complete(struct peer *peer) queue_pkt(peer, PKT__PKT_OPEN_COMPLETE, o); } +/* Once they ack, we can add it on our side. */ +static void add_our_htlc_ourside(struct peer *peer, void *arg) +{ + struct channel_htlc *htlc = arg; + + /* FIXME: must add even if can't pay fee any more! */ + if (!funding_a_add_htlc(peer->us.staging_cstate, + htlc->msatoshis, &htlc->expiry, + &htlc->rhash, htlc->id)) + fatal("FIXME: Failed to add htlc %"PRIu64" to self on ack", + htlc->id); + tal_free(htlc); +} + void queue_pkt_htlc_add(struct peer *peer, const struct htlc_progress *htlc_prog) { @@ -160,91 +206,164 @@ void queue_pkt_htlc_add(struct peer *peer, update_add_htlc__init(u); assert(htlc_prog->stage.type == HTLC_ADD); - u->revocation_hash = sha256_to_proto(u, &htlc_prog->our_revocation_hash); + u->id = htlc_prog->stage.add.htlc.id; u->amount_msat = htlc_prog->stage.add.htlc.msatoshis; u->r_hash = sha256_to_proto(u, &htlc_prog->stage.add.htlc.rhash); u->expiry = abs_locktime_to_proto(u, &htlc_prog->stage.add.htlc.expiry); + /* FIXME: routing! */ + u->route = tal(u, Routing); + routing__init(u->route); - queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u); + /* We're about to send this, so their side will have it from now on. */ + if (!funding_b_add_htlc(peer->them.staging_cstate, + htlc_prog->stage.add.htlc.msatoshis, + &htlc_prog->stage.add.htlc.expiry, + &htlc_prog->stage.add.htlc.rhash, + htlc_prog->stage.add.htlc.id)) + fatal("Could not add HTLC?"); + + peer_add_htlc_expiry(peer, &htlc_prog->stage.add.htlc.expiry); + + queue_pkt_with_ack(peer, PKT__PKT_UPDATE_ADD_HTLC, u, + add_our_htlc_ourside, + tal_dup(peer, struct channel_htlc, + &htlc_prog->stage.add.htlc)); +} + +/* Once they ack, we can fulfill it on our side. */ +static void fulfill_their_htlc_ourside(struct peer *peer, void *arg) +{ + size_t n; + + n = funding_htlc_by_id(&peer->us.staging_cstate->b, ptr2int(arg)); + funding_b_fulfill_htlc(peer->us.staging_cstate, n); } void queue_pkt_htlc_fulfill(struct peer *peer, const struct htlc_progress *htlc_prog) { UpdateFulfillHtlc *f = tal(peer, UpdateFulfillHtlc); + size_t n; update_fulfill_htlc__init(f); assert(htlc_prog->stage.type == HTLC_FULFILL); - f->revocation_hash = sha256_to_proto(f, &htlc_prog->our_revocation_hash); + f->id = htlc_prog->stage.fulfill.id; f->r = sha256_to_proto(f, &htlc_prog->stage.fulfill.r); - queue_pkt(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f); + /* We're about to send this, so their side will have it from now on. */ + n = funding_htlc_by_id(&peer->them.staging_cstate->a, f->id); + funding_a_fulfill_htlc(peer->them.staging_cstate, n); + + queue_pkt_with_ack(peer, PKT__PKT_UPDATE_FULFILL_HTLC, f, + fulfill_their_htlc_ourside, int2ptr(f->id)); +} + +/* Once they ack, we can fail it on our side. */ +static void fail_their_htlc_ourside(struct peer *peer, void *arg) +{ + size_t n; + + n = funding_htlc_by_id(&peer->us.staging_cstate->b, ptr2int(arg)); + funding_b_fail_htlc(peer->us.staging_cstate, n); } void queue_pkt_htlc_fail(struct peer *peer, const struct htlc_progress *htlc_prog) { UpdateFailHtlc *f = tal(peer, UpdateFailHtlc); - const struct channel_htlc *htlc; + size_t n; update_fail_htlc__init(f); assert(htlc_prog->stage.type == HTLC_FAIL); - htlc = &peer->cstate->b.htlcs[htlc_prog->stage.fail.index]; - f->revocation_hash = sha256_to_proto(f, &htlc_prog->our_revocation_hash); - f->r_hash = sha256_to_proto(f, &htlc->rhash); + f->id = htlc_prog->stage.fail.id; + /* FIXME: reason! */ + f->reason = tal(f, FailReason); + fail_reason__init(f->reason); - queue_pkt(peer, PKT__PKT_UPDATE_FAIL_HTLC, f); + /* We're about to send this, so their side will have it from now on. */ + n = funding_htlc_by_id(&peer->them.staging_cstate->a, f->id); + funding_a_fail_htlc(peer->them.staging_cstate, n); + + queue_pkt_with_ack(peer, PKT__PKT_UPDATE_FAIL_HTLC, f, + fail_their_htlc_ourside, int2ptr(f->id)); } -void queue_pkt_update_accept(struct peer *peer) +/* OK, we're sending a signature for their pending changes. */ +void queue_pkt_commit(struct peer *peer) { - UpdateAccept *u = tal(peer, UpdateAccept); - const struct htlc_progress *cur = peer->current_htlc; - struct signature sig; + UpdateCommit *u = tal(peer, UpdateCommit); + struct commit_info *ci = talz(peer, struct commit_info); - update_accept__init(u); + /* Create new commit info for this commit tx. */ + ci->prev = peer->them.commit; + ci->revocation_hash = peer->them.next_revocation_hash; + ci->cstate = copy_funding(ci, peer->them.staging_cstate); + ci->tx = create_commit_tx(ci, + &peer->them.finalkey, + &peer->us.finalkey, + &peer->us.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &ci->revocation_hash, + ci->cstate); - dump_tx("Signing tx", cur->their_commit); - peer_sign_theircommit(peer, cur->their_commit, &sig); - u->sig = signature_to_proto(u, &sig); - u->revocation_hash - = sha256_to_proto(u, &cur->our_revocation_hash); + log_debug(peer->log, "Signing tx for %u/%u msatoshis, %zu/%zu htlcs", + ci->cstate->a.pay_msat, + ci->cstate->b.pay_msat, + tal_count(ci->cstate->a.htlcs), + tal_count(ci->cstate->b.htlcs)); - queue_pkt(peer, PKT__PKT_UPDATE_ACCEPT, u); + /* BOLT #2: + * + * A node MUST NOT send an `update_commit` message which does + * not include any updates. + */ + assert(ci->prev->cstate->changes != ci->cstate->changes); + + ci->sig = tal(ci, struct bitcoin_signature); + ci->sig->stype = SIGHASH_ALL; + peer_sign_theircommit(peer, ci->tx, &ci->sig->sig); + + /* Switch to the new commitment. */ + peer->them.commit = ci; + + /* Now send message */ + update_commit__init(u); + u->sig = signature_to_proto(u, &ci->sig->sig); + + queue_pkt(peer, PKT__PKT_UPDATE_COMMIT, u); } -void queue_pkt_update_signature(struct peer *peer) +/* Send a preimage for the old commit tx. The one we've just committed to is + * in peer->us.commit. */ +void queue_pkt_revocation(struct peer *peer) { - UpdateSignature *u = tal(peer, UpdateSignature); - const struct htlc_progress *cur = peer->current_htlc; - struct signature sig; - struct sha256 preimage; + UpdateRevocation *u = tal(peer, UpdateRevocation); - update_signature__init(u); - - peer_sign_theircommit(peer, cur->their_commit, &sig); - u->sig = signature_to_proto(u, &sig); - assert(peer->commit_tx_counter > 0); - peer_get_revocation_preimage(peer, peer->commit_tx_counter-1, &preimage); - u->revocation_preimage = sha256_to_proto(u, &preimage); - - queue_pkt(peer, PKT__PKT_UPDATE_SIGNATURE, u); -} - -void queue_pkt_update_complete(struct peer *peer) -{ - UpdateComplete *u = tal(peer, UpdateComplete); - struct sha256 preimage; - - update_complete__init(u); + update_revocation__init(u); assert(peer->commit_tx_counter > 0); - peer_get_revocation_preimage(peer, peer->commit_tx_counter-1, &preimage); - u->revocation_preimage = sha256_to_proto(u, &preimage); + assert(peer->us.commit); + assert(peer->us.commit->prev); + assert(!peer->us.commit->prev->revocation_preimage); - queue_pkt(peer, PKT__PKT_UPDATE_COMPLETE, u); + /* We have their signature on the current one, right? */ + assert(peer->us.commit->sig); + + peer->us.commit->prev->revocation_preimage + = tal(peer->us.commit->prev, struct sha256); + peer_get_revocation_preimage(peer, peer->commit_tx_counter-1, + peer->us.commit->prev->revocation_preimage); + u->revocation_preimage + = sha256_to_proto(u, peer->us.commit->prev->revocation_preimage); + + u->next_revocation_hash = sha256_to_proto(u, + &peer->us.next_revocation_hash); + + queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u); } Pkt *pkt_err(struct peer *peer, const char *msg, ...) @@ -262,7 +381,7 @@ Pkt *pkt_err(struct peer *peer, const char *msg, ...) void queue_pkt_err(struct peer *peer, Pkt *err) { - queue_raw_pkt(peer, err); + queue_raw_pkt(peer, err, NULL, NULL); } void queue_pkt_close_clearing(struct peer *peer) @@ -332,8 +451,13 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt) if (!proto_to_pubkey(peer->dstate->secpctx, o->final_key, &peer->them.finalkey)) return pkt_err(peer, "Bad finalkey"); - proto_to_sha256(o->revocation_hash, &peer->them.revocation_hash); - proto_to_sha256(o->next_revocation_hash, &peer->them.next_revocation_hash); + + /* Set up their commit info now: rest gets done in setup_first_commit + * once anchor is established. */ + peer->them.commit = talz(peer, struct commit_info); + proto_to_sha256(o->revocation_hash, &peer->them.commit->revocation_hash); + proto_to_sha256(o->next_revocation_hash, + &peer->them.next_revocation_hash); /* Redeemscript for anchor. */ peer->anchor.redeemscript @@ -342,6 +466,29 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt) return NULL; } +/* Save and check signature. */ +static Pkt *check_and_save_commit_sig(struct peer *peer, + struct commit_info *ci, + const Signature *pb) +{ + assert(!ci->sig); + ci->sig = tal(ci, struct bitcoin_signature); + ci->sig->stype = SIGHASH_ALL; + if (!proto_to_signature(pb, &ci->sig->sig)) + return pkt_err(peer, "Malformed signature"); + + /* Their sig should sign our commit tx. */ + if (!check_tx_sig(peer->dstate->secpctx, + ci->tx, 0, + peer->anchor.redeemscript, + tal_count(peer->anchor.redeemscript), + &peer->them.commitkey, + ci->sig)) + return pkt_err(peer, "Bad signature"); + + return NULL; +} + Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt) { const OpenAnchor *a = pkt->open_anchor; @@ -354,59 +501,17 @@ Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt) peer->anchor.index = a->output_index; peer->anchor.satoshis = a->amount; - /* Create our cstate. */ - peer->cstate = initial_funding(peer, - peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR, - peer->anchor.satoshis, - peer->us.commit_fee_rate); - if (!peer->cstate) + if (!setup_first_commit(peer)) return pkt_err(peer, "Insufficient funds for fee"); - /* Now we can make initial (unsigned!) commit txs. */ - make_commit_txs(peer, peer, - &peer->us.revocation_hash, - &peer->them.revocation_hash, - peer->cstate, - &peer->us.commit, - &peer->them.commit); - - peer->cur_commit.theirsig.stype = SIGHASH_ALL; - if (!proto_to_signature(a->commit_sig, &peer->cur_commit.theirsig.sig)) - return pkt_err(peer, "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(peer, "Bad signature"); - - return NULL; + return check_and_save_commit_sig(peer, peer->us.commit, a->commit_sig); } Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt) { 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(peer, "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(peer, "Bad signature"); - - return NULL; + return check_and_save_commit_sig(peer, peer->us.commit, s->sig); } Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt) @@ -414,249 +519,195 @@ Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt) return NULL; } -static Pkt *decline_htlc(const tal_t *ctx, const char *why) -{ - UpdateDeclineHtlc *d = tal(ctx, UpdateDeclineHtlc); - - update_decline_htlc__init(d); - /* FIXME: Define why in protocol! */ - d->reason_case = UPDATE_DECLINE_HTLC__REASON_CANNOT_ROUTE; - d->cannot_route = true; - - return make_pkt(ctx, PKT__PKT_UPDATE_DECLINE_HTLC, d); -} - -Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt, - Pkt **decline) +/* + * 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) { const UpdateAddHtlc *u = pkt->update_add_htlc; - struct htlc_progress *cur = tal(peer, struct htlc_progress); - Pkt *err; + struct sha256 rhash; + struct abs_locktime expiry; - cur->stage.add.add = HTLC_ADD; - cur->stage.add.htlc.msatoshis = u->amount_msat; - proto_to_sha256(u->r_hash, &cur->stage.add.htlc.rhash); - proto_to_sha256(u->revocation_hash, &cur->their_revocation_hash); - if (!proto_to_abs_locktime(u->expiry, &cur->stage.add.htlc.expiry)) { - err = pkt_err(peer, "Invalid HTLC expiry"); - goto fail; - } + /* BOLT #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"); /* FIXME: Handle block-based expiry! */ - if (!abs_locktime_is_seconds(&cur->stage.add.htlc.expiry)) { - *decline = decline_htlc(peer, - "HTLC expiry in blocks not supported!"); - goto decline; - } + if (!abs_locktime_is_seconds(&expiry)) + return pkt_err(peer, "HTLC expiry in blocks not supported!"); - if (abs_locktime_to_seconds(&cur->stage.add.htlc.expiry) < - controlled_time().ts.tv_sec + peer->dstate->config.min_expiry) { - *decline = decline_htlc(peer, "HTLC expiry too soon!"); - goto decline; - } + /* BOLT #2: + * + * A node MUST NOT add a HTLC if it would result in it + * offering more than 1500 HTLCs in either commitment transaction. + */ + if (tal_count(peer->them.staging_cstate->a.htlcs) == 1500 + || tal_count(peer->us.staging_cstate->b.htlcs) == 1500) + return pkt_err(peer, "Too many HTLCs"); - if (abs_locktime_to_seconds(&cur->stage.add.htlc.expiry) > - controlled_time().ts.tv_sec + peer->dstate->config.max_expiry) { - *decline = decline_htlc(peer, "HTLC expiry too far!"); - goto decline; - } + /* BOLT #2: + * + * A node MUST NOT set `id` equal to another HTLC which is in + * the current staged commitment transaction. + */ + if (funding_htlc_by_id(&peer->them.staging_cstate->a, u->id) + < tal_count(peer->them.staging_cstate->a.htlcs)) + return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); - cur->cstate = copy_funding(cur, peer->cstate); - if (!funding_b_add_htlc(cur->cstate, - cur->stage.add.htlc.msatoshis, - &cur->stage.add.htlc.expiry, - &cur->stage.add.htlc.rhash, 0)) { - err = pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis", - cur->stage.add.htlc.msatoshis); - goto fail; - } - peer_add_htlc_expiry(peer, &cur->stage.add.htlc.expiry); - - peer_get_revocation_hash(peer, peer->commit_tx_counter+1, - &cur->our_revocation_hash); - memcheck(&cur->their_revocation_hash, sizeof(cur->their_revocation_hash)); + /* FIXME: Assert this... */ + /* Note: these should be in sync, so this should be redundant! */ + if (funding_htlc_by_id(&peer->us.staging_cstate->b, u->id) + < tal_count(peer->us.staging_cstate->b.htlcs)) + return pkt_err(peer, "HTLC id %"PRIu64" clashes for us", u->id); - /* Now we create the commit tx pair. */ - make_commit_txs(cur, peer, - memcheck(&cur->our_revocation_hash, - sizeof(cur->our_revocation_hash)), - &cur->their_revocation_hash, - cur->cstate, - &cur->our_commit, &cur->their_commit); + /* BOLT #2: + * + * A node MUST NOT offer `amount_msat` it cannot pay for in + * both commitment transactions at the current `fee_rate` (see + * "Fee Calculation" ). A node SHOULD fail the connection if + * this occurs. + */ + + /* FIXME: This is wrong! We may have already added more txs to + * them.staging_cstate, driving that fee up. + * We should check against the last version they acknowledged. */ + if (!funding_a_add_htlc(peer->them.staging_cstate, + u->amount_msat, &expiry, &rhash, u->id)) + return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" + " in your commitment tx", + u->amount_msat); + + /* If we fail here, we've already changed them.staging_cstate, so + * MUST terminate. */ + if (!funding_b_add_htlc(peer->us.staging_cstate, + u->amount_msat, &expiry, &rhash, u->id)) + return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" + " in our commitment tx", + u->amount_msat); + + peer_add_htlc_expiry(peer, &expiry); /* FIXME: Fees must be sufficient. */ - *decline = NULL; - assert(!peer->current_htlc); - peer->current_htlc = cur; return NULL; +} -fail: - tal_free(cur); - return err; +static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, + size_t *n_us, size_t *n_them) +{ + /* BOLT #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. + */ + *n_us = funding_htlc_by_id(&peer->us.commit->cstate->a, id); + if (*n_us == tal_count(peer->us.commit->cstate->a.htlcs)) + return pkt_err(peer, "Did not find HTLC %"PRIu64, id); + + /* They must not fail/fulfill twice, so it should be in staging, too. */ + *n_us = funding_htlc_by_id(&peer->us.staging_cstate->a, id); + if (*n_us == tal_count(peer->us.staging_cstate->a.htlcs)) + return pkt_err(peer, "Already removed HTLC %"PRIu64, id); + + /* FIXME: Assert this... */ + /* Note: these should match. */ + *n_them = funding_htlc_by_id(&peer->them.staging_cstate->b, id); + if (*n_them == tal_count(peer->them.staging_cstate->b.htlcs)) + return pkt_err(peer, "Did not find your HTLC %"PRIu64, id); -decline: - assert(*decline); - tal_free(cur); return NULL; -}; +} Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) { const UpdateFailHtlc *f = pkt->update_fail_htlc; - struct htlc_progress *cur = tal(peer, struct htlc_progress); + size_t n_us, n_them; Pkt *err; - size_t i; - struct sha256 rhash; - proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash); - proto_to_sha256(f->r_hash, &rhash); + err = find_commited_htlc(peer, f->id, &n_us, &n_them); + if (err) + return err; - i = funding_find_htlc(&peer->cstate->a, &rhash); - if (i == tal_count(peer->cstate->a.htlcs)) { - err = pkt_err(peer, "Unknown HTLC"); - goto fail; - } + /* FIXME: Save reason. */ - cur->stage.fail.fail = HTLC_FAIL; - cur->stage.fail.index = i; - - /* We regain HTLC amount */ - cur->cstate = copy_funding(cur, peer->cstate); - funding_a_fail_htlc(cur->cstate, i); - /* FIXME: Remove timer. */ - - peer_get_revocation_hash(peer, peer->commit_tx_counter+1, - &cur->our_revocation_hash); - - /* Now we create the commit tx pair. */ - make_commit_txs(cur, peer, &cur->our_revocation_hash, - &cur->their_revocation_hash, - cur->cstate, - &cur->our_commit, &cur->their_commit); - - assert(!peer->current_htlc); - peer->current_htlc = cur; + funding_a_fail_htlc(peer->us.staging_cstate, n_us); + funding_b_fail_htlc(peer->them.staging_cstate, n_them); return NULL; - -fail: - tal_free(cur); - return err; } Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) { const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc; - struct htlc_progress *cur = tal(peer, struct htlc_progress); + size_t n_us, n_them; + struct sha256 r, rhash; Pkt *err; - size_t i; - struct sha256 rhash; - cur->stage.fulfill.fulfill = HTLC_FULFILL; - proto_to_sha256(f->r, &cur->stage.fulfill.r); + err = find_commited_htlc(peer, f->id, &n_us, &n_them); + if (err) + return err; - proto_to_sha256(f->revocation_hash, &cur->their_revocation_hash); - sha256(&rhash, &cur->stage.fulfill.r, sizeof(cur->stage.fulfill.r)); - i = funding_find_htlc(&peer->cstate->a, &rhash); - if (i == tal_count(peer->cstate->a.htlcs)) { - err = pkt_err(peer, "Unknown HTLC"); - goto fail; - } - cur->stage.fulfill.index = i; + /* Now, it must solve the HTLC rhash puzzle. */ + proto_to_sha256(f->r, &r); + sha256(&rhash, &r, sizeof(r)); - /* Removing it: they gain HTLC amount */ - cur->cstate = copy_funding(cur, peer->cstate); - funding_a_fulfill_htlc(cur->cstate, i); + if (!structeq(&rhash, &peer->us.staging_cstate->a.htlcs[n_us].rhash)) + return pkt_err(peer, "Invalid r for %"PRIu64, f->id); - peer_get_revocation_hash(peer, peer->commit_tx_counter+1, - &cur->our_revocation_hash); + /* Same ID must have same rhash */ + assert(structeq(&rhash, &peer->them.staging_cstate->b.htlcs[n_them].rhash)); - /* Now we create the commit tx pair. */ - make_commit_txs(cur, peer, &cur->our_revocation_hash, - &cur->their_revocation_hash, - cur->cstate, - &cur->our_commit, &cur->their_commit); - - assert(!peer->current_htlc); - peer->current_htlc = cur; + funding_a_fulfill_htlc(peer->us.staging_cstate, n_us); + funding_b_fulfill_htlc(peer->them.staging_cstate, n_them); return NULL; - -fail: - tal_free(cur); - return err; } -static u64 total_funds(const struct channel_oneside *c) +Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt) { - u64 total = (u64)c->pay_msat + c->fee_msat; - size_t i, n = tal_count(c->htlcs); + const UpdateCommit *c = pkt->update_commit; + Pkt *err; + struct commit_info *ci = talz(peer, struct commit_info); - for (i = 0; i < n; i++) - total += c->htlcs[i].msatoshis; - return total; -} + /* Create new commit info for this commit tx. */ + ci->prev = peer->us.commit; + ci->revocation_hash = peer->us.next_revocation_hash; + ci->cstate = copy_funding(ci, peer->us.staging_cstate); + ci->tx = create_commit_tx(ci, + &peer->us.finalkey, + &peer->them.finalkey, + &peer->them.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &ci->revocation_hash, + ci->cstate); -static void update_to_new_htlcs(struct peer *peer) -{ - struct htlc_progress *cur = peer->current_htlc; - - /* FIXME: Add to shachain too. */ - - /* HTLCs can't change total balance in channel! */ - if (total_funds(&peer->cstate->a) + total_funds(&peer->cstate->b) - != total_funds(&cur->cstate->a) + total_funds(&cur->cstate->b)) - fatal("Illegal funding transition from %u/%u (total %"PRIu64")" - " to %u/%u (total %"PRIu64")", - peer->cstate->a.pay_msat, peer->cstate->a.fee_msat, - total_funds(&peer->cstate->a), - peer->cstate->b.pay_msat, peer->cstate->b.fee_msat, - total_funds(&peer->cstate->b)); - - /* Now, we consider this channel_state current one. */ - tal_free(peer->cstate); - peer->cstate = tal_steal(peer, cur->cstate); - - tal_free(peer->us.commit); - peer->us.commit = tal_steal(peer, cur->our_commit); - /* FIXME: Save their old commit details, to steal funds. */ - tal_free(peer->them.commit); - peer->them.commit = tal_steal(peer, cur->their_commit); - peer->us.revocation_hash = cur->our_revocation_hash; - peer->them.revocation_hash = cur->their_revocation_hash; + /* BOLT #2: + * + * A node MUST NOT send an `update_commit` message which does + * not include any updates. + */ + if (ci->prev->cstate->changes == ci->cstate->changes) + return pkt_err(peer, "Empty commit"); + + err = check_and_save_commit_sig(peer, ci, c->sig); + if (err) + return err; + /* Switch to the new commitment. */ + peer->us.commit = ci; peer->commit_tx_counter++; -} - -Pkt *accept_pkt_update_accept(struct peer *peer, const Pkt *pkt) -{ - const UpdateAccept *a = pkt->update_accept; - struct htlc_progress *cur = peer->current_htlc; - - proto_to_sha256(a->revocation_hash, &cur->their_revocation_hash); - - cur->their_sig.stype = SIGHASH_ALL; - if (!proto_to_signature(a->sig, &cur->their_sig.sig)) - return pkt_err(peer, "Malformed signature"); - - /* Now we can make commit tx pair. */ - make_commit_txs(cur, peer, &cur->our_revocation_hash, - &cur->their_revocation_hash, - cur->cstate, - &cur->our_commit, &cur->their_commit); - - /* Their sig should sign our new commit tx. */ - if (!check_tx_sig(peer->dstate->secpctx, - cur->our_commit, 0, - peer->anchor.redeemscript, - tal_count(peer->anchor.redeemscript), - &peer->them.commitkey, - &cur->their_sig)) - return pkt_err(peer, "Bad signature"); - - /* Our next step will be to send the revocation preimage, so - * update to new HTLC now so we never use the old one. */ - update_to_new_htlcs(peer); + peer_get_revocation_hash(peer, peer->commit_tx_counter + 1, + &peer->us.next_revocation_hash); return NULL; -} +} static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash) { @@ -667,41 +718,30 @@ static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash return structeq(&h, hash); } -Pkt *accept_pkt_update_complete(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) { - /* FIXME: Check preimage against old tx! */ + const UpdateRevocation *r = pkt->update_revocation; + + /* FIXME: Save preimage in shachain too. */ + if (!check_preimage(r->revocation_preimage, + &peer->them.commit->prev->revocation_hash)) + return pkt_err(peer, "complete preimage incorrect"); + + /* They're revoking the previous one. */ + assert(!peer->them.commit->prev->revocation_preimage); + peer->them.commit->prev->revocation_preimage + = tal(peer->them.commit->prev, struct sha256); + + proto_to_sha256(r->revocation_preimage, + peer->them.commit->prev->revocation_preimage); + + /* Save next revocation hash. */ + proto_to_sha256(r->next_revocation_hash, + &peer->them.next_revocation_hash); + return NULL; } - -Pkt *accept_pkt_update_signature(struct peer *peer, - const Pkt *pkt) -{ - const UpdateSignature *s = pkt->update_signature; - struct htlc_progress *cur = peer->current_htlc; - - cur->their_sig.stype = SIGHASH_ALL; - if (!proto_to_signature(s->sig, &cur->their_sig.sig)) - return pkt_err(peer, "Malformed signature"); - - /* Their sig should sign our new commit tx. */ - if (!check_tx_sig(peer->dstate->secpctx, - cur->our_commit, 0, - peer->anchor.redeemscript, - tal_count(peer->anchor.redeemscript), - &peer->them.commitkey, - &cur->their_sig)) - return pkt_err(peer, "Bad signature"); - - /* Check their revocation preimage. */ - if (!check_preimage(s->revocation_preimage, &peer->them.revocation_hash)) - return pkt_err(peer, "Bad revocation preimage"); - - /* Our next step will be to send the revocation preimage, so - * update to new HTLC now so we never use the old one. */ - update_to_new_htlcs(peer); - return NULL; -} - + Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt) { /* FIXME: Reject unknown odd fields? */ @@ -721,7 +761,7 @@ Pkt *accept_pkt_close_sig(struct peer *peer, const Pkt *pkt, bool *matches) * number of satoshis. */ if ((c->close_fee & 1) - || c->close_fee > commit_tx_fee(peer->them.commit, + || c->close_fee > commit_tx_fee(peer->them.commit->tx, peer->anchor.satoshis)) { return pkt_err(peer, "Invalid close fee"); } diff --git a/daemon/peer.c b/daemon/peer.c index 3cae60fca..552a60667 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -10,6 +10,7 @@ #include "log.h" #include "names.h" #include "peer.h" +#include "pseudorand.h" #include "secrets.h" #include "state.h" #include "timeout.h" @@ -207,6 +208,36 @@ static void queue_cmd_(struct peer *peer, try_command(peer); }; +/* All unrevoked commit txs must have no HTLCs in them. */ +bool committed_to_htlcs(const struct peer *peer) +{ + const struct commit_info *i; + + /* Before anchor exchange, we don't even have cstate. */ + if (!peer->us.commit || !peer->us.commit->cstate) + return false; + + i = peer->us.commit; + while (i && !i->revocation_preimage) { + if (tal_count(i->cstate->a.htlcs)) + return true; + if (tal_count(i->cstate->b.htlcs)) + return true; + i = i->prev; + } + + i = peer->them.commit; + while (i && !i->revocation_preimage) { + if (tal_count(i->cstate->a.htlcs)) + return true; + if (tal_count(i->cstate->b.htlcs)) + return true; + i = i->prev; + } + + return false; +} + static void state_event(struct peer *peer, const enum state_input input, const union input *idata) @@ -267,8 +298,8 @@ static void do_anchor_offer(struct peer *peer, void *unused) 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->us.revocation_hash); - peer_get_revocation_hash(peer, 1, &peer->us.next_revocation_hash); + + peer_get_revocation_hash(peer, 0, &peer->us.next_revocation_hash); assert(peer->state == STATE_INIT); @@ -345,14 +376,15 @@ static struct peer *new_peer(struct lightningd_state *dstate, peer->outpkt = tal_arr(peer, struct out_pkt, 0); peer->curr_cmd.cmd = INPUT_NONE; list_head_init(&peer->pending_cmd); - peer->current_htlc = NULL; peer->commit_tx_counter = 0; - 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; + /* Make it different from other node (to catch bugs!), but a + * round number for simple eyeballing. */ + peer->htlc_id_counter = pseudorand(1ULL << 32) * 1000; /* If we free peer, conn should be closed, but can't be freed * immediately so don't make peer a parent. */ @@ -368,7 +400,8 @@ static struct peer *new_peer(struct lightningd_state *dstate, peer->us.commit_fee_rate = dstate->config.commitment_fee_rate; peer->us.commit = peer->them.commit = NULL; - + peer->us.staging_cstate = peer->them.staging_cstate = NULL; + /* FIXME: Attach IO logging for this peer. */ tal_add_destructor(peer, destroy_peer); @@ -615,6 +648,18 @@ static bool txmatch(const struct bitcoin_tx *txa, const struct bitcoin_tx *txb) return true; } +/* We may have two possible "current" commits; this loop will check them both. */ +static bool is_unrevoked_commit(const struct commit_info *ci, + const struct bitcoin_tx *tx) +{ + while (ci && !ci->revocation_preimage) { + if (txmatch(ci->tx, tx)) + return true; + ci = ci->prev; + } + return false; +} + /* 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, @@ -663,7 +708,7 @@ static void anchor_spent(struct peer *peer, /* FIXME: change type in idata? */ idata.btc = (struct bitcoin_event *)tx; - if (txmatch(tx, peer->them.commit)) + if (is_unrevoked_commit(peer->them.commit, tx)) state_event(peer, w->theyspent, &idata); else if (is_mutual_close(peer, tx)) add_close_tx_watch(peer, peer, tx, close_depth_cb); @@ -799,7 +844,8 @@ void peer_watch_delayed(struct peer *peer, { struct sha256_double txid; - assert(tx == peer->us.commit); + /* We only ever spend the last one. */ + assert(tx == peer->us.commit->tx); bitcoin_txid(tx, &txid); memset(&peer->cur_commit.blockid, 0xFF, sizeof(peer->cur_commit.blockid)); @@ -852,7 +898,7 @@ struct bitcoin_tx *peer_create_close_tx(struct peer *peer, u64 fee) struct channel_state cstate; /* We don't need a deep copy here, just fee levels. */ - cstate = *peer->cstate; + cstate = *peer->us.staging_cstate; if (!force_fee(&cstate, fee)) { log_unusual(peer->log, "peer_create_close_tx: can't afford fee %"PRIu64, @@ -896,7 +942,7 @@ void peer_calculate_close_fee(struct peer *peer) * fee of the final commitment transaction and MUST set * `close_fee` to an even number of satoshis. */ - maxfee = commit_tx_fee(peer->us.commit, peer->anchor.satoshis); + maxfee = commit_tx_fee(peer->us.commit->tx, peer->anchor.satoshis); if (peer->closing.our_fee > maxfee) { /* This shouldn't happen: we never accept a commit fee * less than the min_rate, which is greater than the @@ -1001,32 +1047,6 @@ void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt) FIXME_STUB(peer); } -/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */ -void peer_htlc_declined(struct peer *peer, const Pkt *pkt) -{ - log_unusual(peer->log, "Peer declined htlc, reason %i", - pkt->update_decline_htlc->reason_case); - peer->current_htlc = tal_free(peer->current_htlc); -} - -/* Called when their update overrides our update cmd. */ -void peer_htlc_ours_deferred(struct peer *peer) -{ - FIXME_STUB(peer); -} - -/* Successfully added/fulfilled/timedout/routefail an HTLC. */ -void peer_htlc_done(struct peer *peer) -{ - peer->current_htlc = tal_free(peer->current_htlc); -} - -/* Someone aborted an existing HTLC. */ -void peer_htlc_aborted(struct peer *peer) -{ - FIXME_STUB(peer); -} - /* An on-chain transaction revealed an R value. */ const struct htlc *peer_tx_revealed_r_value(struct peer *peer, const struct bitcoin_event *btc) @@ -1034,15 +1054,6 @@ const struct htlc *peer_tx_revealed_r_value(struct peer *peer, FIXME_STUB(peer); } -bool committed_to_htlcs(const struct peer *peer) -{ - /* This is only set after anchor established. */ - if (!peer->cstate) - return false; - return tal_count(peer->cstate->a.htlcs) != 0 - || tal_count(peer->cstate->b.htlcs) != 0; -} - void peer_watch_htlcs_cleared(struct peer *peer, enum state_input all_done) { @@ -1079,7 +1090,7 @@ const struct bitcoin_tx *bitcoin_close(struct peer *peer) const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer) { u8 *redeemscript, *linear; - const struct bitcoin_tx *commit = peer->us.commit; + const struct bitcoin_tx *commit = peer->us.commit->tx; struct bitcoin_signature sig; struct bitcoin_tx *tx; unsigned int p2sh_out; @@ -1089,7 +1100,7 @@ const struct bitcoin_tx *bitcoin_spend_ours(struct peer *peer) &peer->us.finalkey, &peer->them.locktime, &peer->them.finalkey, - &peer->us.revocation_hash); + &peer->us.commit->revocation_hash); /* Now, create transaction to spend it. */ tx = bitcoin_tx(peer, 1, 1); @@ -1161,21 +1172,21 @@ const struct bitcoin_tx *bitcoin_commit(struct peer *peer) struct bitcoin_signature sig; /* Can't be signed already! */ - assert(peer->us.commit->input[0].script_length == 0); + assert(peer->us.commit->tx->input[0].script_length == 0); sig.stype = SIGHASH_ALL; - peer_sign_ourcommit(peer, peer->us.commit, &sig.sig); + peer_sign_ourcommit(peer, peer->us.commit->tx, &sig.sig); - peer->us.commit->input[0].script - = scriptsig_p2sh_2of2(peer->us.commit, - &peer->cur_commit.theirsig, + peer->us.commit->tx->input[0].script + = scriptsig_p2sh_2of2(peer->us.commit->tx, + peer->us.commit->sig, &sig, &peer->them.commitkey, &peer->us.commitkey); - peer->us.commit->input[0].script_length - = tal_count(peer->us.commit->input[0].script); + peer->us.commit->tx->input[0].script_length + = tal_count(peer->us.commit->tx->input[0].script); - return peer->us.commit; + return peer->us.commit->tx; } /* Create a HTLC refund collection */ @@ -1202,22 +1213,6 @@ static void created_anchor(struct lightningd_state *dstate, /* We'll need this later, when we're told to broadcast it. */ peer->anchor.tx = tal_steal(peer, tx); - /* FIXME: Check their cstate too (different fee rate!) */ - peer->cstate = initial_funding(peer, - peer->us.offer_anchor == CMD_OPEN_WITH_ANCHOR, - peer->anchor.satoshis, - peer->us.commit_fee_rate); - if (!peer->cstate) - fatal("Insufficient anchor funds for commitfee"); - - /* Now we can make initial (unsigned!) commit txs. */ - make_commit_txs(peer, peer, - &peer->us.revocation_hash, - &peer->them.revocation_hash, - peer->cstate, - &peer->us.commit, - &peer->them.commit); - state_event(peer, BITCOIN_ANCHOR_CREATED, NULL); } @@ -1259,38 +1254,53 @@ const struct bitcoin_tx *bitcoin_anchor(struct peer *peer) return peer->anchor.tx; } -void make_commit_txs(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *our_revocation_hash, - const struct sha256 *their_revocation_hash, - const struct channel_state *cstate, - struct bitcoin_tx **ours, struct bitcoin_tx **theirs) +/* Sets up the initial cstate and commit tx for both nodes: false if + * insufficient funds. */ +bool setup_first_commit(struct peer *peer) { - struct channel_state their_cstate; + assert(!peer->us.commit->tx); + assert(!peer->them.commit->tx); - *ours = create_commit_tx(ctx, - &peer->us.finalkey, - &peer->them.finalkey, - &peer->them.locktime, - &peer->anchor.txid, - peer->anchor.index, - peer->anchor.satoshis, - our_revocation_hash, - cstate); + /* Revocation hashes already filled in, from pkt_open */ + peer->us.commit->cstate = initial_funding(peer, + peer->us.offer_anchor + == CMD_OPEN_WITH_ANCHOR, + peer->anchor.satoshis, + peer->us.commit_fee_rate); + if (!peer->us.commit->cstate) + return false; - /* Shallow copy: we don't touch HTLCs, just amounts and fees. */ - their_cstate = *cstate; - invert_cstate(&their_cstate); - adjust_fee(&their_cstate, peer->them.commit_fee_rate); - *theirs = create_commit_tx(ctx, - &peer->them.finalkey, - &peer->us.finalkey, - &peer->us.locktime, - &peer->anchor.txid, - peer->anchor.index, - peer->anchor.satoshis, - their_revocation_hash, - &their_cstate); + peer->them.commit->cstate = initial_funding(peer, + peer->them.offer_anchor + == CMD_OPEN_WITH_ANCHOR, + peer->anchor.satoshis, + peer->them.commit_fee_rate); + if (!peer->them.commit->cstate) + return false; + + peer->us.commit->tx = create_commit_tx(peer->us.commit, + &peer->us.finalkey, + &peer->them.finalkey, + &peer->them.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &peer->us.commit->revocation_hash, + peer->us.commit->cstate); + + peer->them.commit->tx = create_commit_tx(peer->them.commit, + &peer->them.finalkey, + &peer->us.finalkey, + &peer->us.locktime, + &peer->anchor.txid, + peer->anchor.index, + peer->anchor.satoshis, + &peer->them.commit->revocation_hash, + peer->them.commit->cstate); + + peer->us.staging_cstate = copy_funding(peer, peer->us.commit->cstate); + peer->them.staging_cstate = copy_funding(peer, peer->them.commit->cstate); + return true; } static void json_add_abstime(struct json_result *response, @@ -1305,16 +1315,13 @@ static void json_add_abstime(struct json_result *response, json_object_end(response); } -static void json_add_cstate(struct json_result *response, - const char *id, - const struct channel_oneside *side) +static void json_add_htlcs(struct json_result *response, + const char *id, + const struct channel_oneside *side) { size_t i; - json_object_start(response, id); - json_add_num(response, "pay", side->pay_msat); - json_add_num(response, "fee", side->fee_msat); - json_array_start(response, "htlcs"); + json_array_start(response, id); for (i = 0; i < tal_count(side->htlcs); i++) { json_object_start(response, NULL); json_add_u64(response, "msatoshis", side->htlcs[i].msatoshis); @@ -1325,9 +1332,21 @@ static void json_add_cstate(struct json_result *response, json_object_end(response); } json_array_end(response); - json_object_end(response); } +/* This is money we can count on. */ +static const struct channel_state *last_signed_state(const struct commit_info *i) +{ + while (i) { + if (i->sig) + return i->cstate; + i = i->prev; + } + return NULL; +} + +/* FIXME: add history command which shows all prior and current commit txs */ + /* FIXME: Somehow we should show running DNS lookups! */ /* FIXME: Show status of peers! */ static void json_getpeers(struct command *cmd, @@ -1339,6 +1358,8 @@ static void json_getpeers(struct command *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)); @@ -1349,12 +1370,26 @@ static void json_getpeers(struct command *cmd, json_add_hex(response, "peerid", p->id.der, sizeof(p->id.der)); - if (p->cstate) { - json_object_start(response, "channel"); - json_add_cstate(response, "us", &p->cstate->a); - json_add_cstate(response, "them", &p->cstate->b); + /* FIXME: Report anchor. */ + + last = last_signed_state(p->us.commit); + if (!last) { json_object_end(response); + continue; } + + json_add_num(response, "our_amount", last->a.pay_msat); + json_add_num(response, "our_fee", last->a.fee_msat); + json_add_num(response, "their_amount", last->b.pay_msat); + json_add_num(response, "their_fee", last->b.fee_msat); + json_add_htlcs(response, "our_htlcs", &last->a); + json_add_htlcs(response, "their_htlcs", &last->b); + + /* Any changes since then? */ + if (p->us.staging_cstate->changes != last->changes) + json_add_num(response, "staged_changes", + p->us.staging_cstate->changes + - last->changes); json_object_end(response); } json_array_end(response); @@ -1370,26 +1405,22 @@ const struct json_command getpeers_command = { }; static void set_htlc_command(struct peer *peer, - struct channel_state *cstate, struct command *jsoncmd, enum state_input cmd, const union htlc_staging *stage) { - assert(!peer->current_htlc); + /* FIXME: memleak! */ + /* FIXME: Get rid of struct htlc_progress */ + struct htlc_progress *progress = tal(peer, struct htlc_progress); - peer->current_htlc = tal(peer, struct htlc_progress); - peer->current_htlc->cstate = tal_steal(peer->current_htlc, cstate); - peer->current_htlc->stage = *stage; - - peer_get_revocation_hash(peer, peer->commit_tx_counter+1, - &peer->current_htlc->our_revocation_hash); - - /* FIXME: Do we need current_htlc as idata arg? */ - set_current_command(peer, cmd, peer->current_htlc, jsoncmd); + progress->stage = *stage; + set_current_command(peer, cmd, progress, jsoncmd); } /* FIXME: Keep a timeout for each peer, in case they're unresponsive. */ - + +/* FIXME: Make sure no HTLCs in any unrevoked commit tx are live. */ + static void check_htlc_expiry(struct peer *peer, void *unused) { size_t i; @@ -1397,10 +1428,10 @@ static void check_htlc_expiry(struct peer *peer, void *unused) stage.fail.fail = HTLC_FAIL; - /* Check their htlcs for expiry. */ - for (i = 0; i < tal_count(peer->cstate->b.htlcs); i++) { - struct channel_htlc *htlc = &peer->cstate->b.htlcs[i]; - struct channel_state *cstate; + /* Check their currently still-existing htlcs for expiry: + * We eliminate them from staging as we go. */ + for (i = 0; i < tal_count(peer->them.staging_cstate->a.htlcs); i++) { + struct channel_htlc *htlc = &peer->them.staging_cstate->a.htlcs[i]; /* Not a seconds-based expiry? */ if (!abs_locktime_is_seconds(&htlc->expiry)) @@ -1411,11 +1442,8 @@ static void check_htlc_expiry(struct peer *peer, void *unused) < abs_locktime_to_seconds(&htlc->expiry)) continue; - cstate = copy_funding(peer, peer->cstate); - funding_b_fail_htlc(cstate, i); - stage.fail.index = i; - set_htlc_command(peer, cstate, NULL, CMD_SEND_HTLC_FAIL, - &stage); + stage.fail.id = htlc->id; + set_htlc_command(peer, NULL, CMD_SEND_HTLC_FAIL, &stage); return; } } @@ -1450,25 +1478,54 @@ static void do_newhtlc(struct peer *peer, struct newhtlc *newhtlc) struct channel_state *cstate; union htlc_staging stage; + /* Now we can assign counter and guarantee uniqueness. */ + newhtlc->htlc.id = peer->htlc_id_counter; stage.add.add = HTLC_ADD; stage.add.htlc = newhtlc->htlc; + + /* BOLT #2: + * + * A node MUST NOT add a HTLC if it would result in it + * offering more than 1500 HTLCs in either commitment transaction. + */ + if (tal_count(peer->us.staging_cstate->a.htlcs) == 1500 + || tal_count(peer->them.staging_cstate->b.htlcs) == 1500) { + command_fail(newhtlc->jsoncmd, "Too many HTLCs"); + } - /* Can we even offer this much? We check now, just before we - * execute. */ - cstate = copy_funding(newhtlc, peer->cstate); - if (!funding_a_add_htlc(cstate, newhtlc->htlc.msatoshis, - &newhtlc->htlc.expiry, &newhtlc->htlc.rhash, 0)) { + + /* BOLT #2: + * + * A node MUST NOT offer `amount_msat` it cannot pay for in + * both commitment transactions at the current `fee_rate` + */ + cstate = copy_funding(newhtlc, peer->them.staging_cstate); + if (!funding_b_add_htlc(cstate, newhtlc->htlc.msatoshis, + &newhtlc->htlc.expiry, &newhtlc->htlc.rhash, + newhtlc->htlc.id)) { command_fail(newhtlc->jsoncmd, - "Cannot afford %"PRIu64" milli-satoshis", + "Cannot afford %"PRIu64 + " milli-satoshis in their commit tx", newhtlc->htlc.msatoshis); return; } - /* FIXME: Never propose duplicate rvalues? */ - peer_add_htlc_expiry(peer, &newhtlc->htlc.expiry); + cstate = copy_funding(newhtlc, peer->us.staging_cstate); + if (!funding_a_add_htlc(cstate, newhtlc->htlc.msatoshis, + &newhtlc->htlc.expiry, &newhtlc->htlc.rhash, + newhtlc->htlc.id)) { + command_fail(newhtlc->jsoncmd, + "Cannot afford %"PRIu64 + " milli-satoshis in our commit tx", + newhtlc->htlc.msatoshis); + return; + } - set_htlc_command(peer, cstate, newhtlc->jsoncmd, - CMD_SEND_HTLC_ADD, &stage); + /* Make sure we never offer the same one twice. */ + peer->htlc_id_counter++; + + /* FIXME: Never propose duplicate rvalues? */ + set_htlc_command(peer, newhtlc->jsoncmd, CMD_SEND_HTLC_ADD, &stage); } static void json_newhtlc(struct command *cmd, @@ -1495,6 +1552,11 @@ static void json_newhtlc(struct command *cmd, return; } + if (!peer->them.commit || !peer->them.commit->cstate) { + command_fail(cmd, "peer not fully established"); + return; + } + /* Attach to cmd until it's complete. */ newhtlc = tal(cmd, struct newhtlc); newhtlc->jsoncmd = cmd; @@ -1544,6 +1606,7 @@ static void json_newhtlc(struct command *cmd, queue_cmd(peer, do_newhtlc, newhtlc); } +/* FIXME: Use HTLC ids, not r values! */ const struct json_command newhtlc_command = { "newhtlc", json_newhtlc, @@ -1559,7 +1622,6 @@ struct fulfillhtlc { static void do_fullfill(struct peer *peer, struct fulfillhtlc *fulfillhtlc) { - struct channel_state *cstate; struct sha256 rhash; size_t i; union htlc_staging stage; @@ -1569,17 +1631,13 @@ static void do_fullfill(struct peer *peer, sha256(&rhash, &fulfillhtlc->r, sizeof(fulfillhtlc->r)); - i = funding_find_htlc(&peer->cstate->b, &rhash); - if (i == tal_count(peer->cstate->b.htlcs)) { - command_fail(fulfillhtlc->jsoncmd, - "preimage htlc not found"); + i = funding_find_htlc(&peer->them.staging_cstate->a, &rhash); + if (i == tal_count(peer->them.staging_cstate->a.htlcs)) { + command_fail(fulfillhtlc->jsoncmd, "preimage htlc not found"); return; } - stage.fulfill.index = i; - cstate = copy_funding(fulfillhtlc, peer->cstate); - funding_b_fulfill_htlc(cstate, i); - - set_htlc_command(peer, cstate, fulfillhtlc->jsoncmd, + stage.fulfill.id = peer->them.staging_cstate->a.htlcs[i].id; + set_htlc_command(peer, fulfillhtlc->jsoncmd, CMD_SEND_HTLC_FULFILL, &stage); } @@ -1604,6 +1662,11 @@ static void json_fulfillhtlc(struct command *cmd, return; } + if (!peer->them.commit || !peer->them.commit->cstate) { + command_fail(cmd, "peer not fully established"); + return; + } + fulfillhtlc = tal(cmd, struct fulfillhtlc); fulfillhtlc->jsoncmd = cmd; @@ -1634,24 +1697,22 @@ struct failhtlc { static void do_failhtlc(struct peer *peer, struct failhtlc *failhtlc) { - struct channel_state *cstate; size_t i; union htlc_staging stage; stage.fail.fail = HTLC_FAIL; - i = funding_find_htlc(&peer->cstate->b, &failhtlc->rhash); - if (i == tal_count(peer->cstate->b.htlcs)) { + /* Look in peer->them.staging_cstate->a, as that's where we'll + * immediately remove it from: avoids double-handling. */ + /* FIXME: Make sure it's also committed in previous commit tx! */ + i = funding_find_htlc(&peer->them.staging_cstate->a, &failhtlc->rhash); + if (i == tal_count(peer->them.staging_cstate->a.htlcs)) { command_fail(failhtlc->jsoncmd, "htlc not found"); return; } - stage.fail.index = i; + stage.fail.id = peer->them.staging_cstate->a.htlcs[i].id; - cstate = copy_funding(failhtlc, peer->cstate); - funding_b_fail_htlc(cstate, i); - - set_htlc_command(peer, cstate, failhtlc->jsoncmd, - CMD_SEND_HTLC_FAIL, &stage); + set_htlc_command(peer, failhtlc->jsoncmd, CMD_SEND_HTLC_FAIL, &stage); } static void json_failhtlc(struct command *cmd, @@ -1675,6 +1736,11 @@ static void json_failhtlc(struct command *cmd, return; } + if (!peer->them.commit || !peer->them.commit->cstate) { + command_fail(cmd, "peer not fully established"); + return; + } + failhtlc = tal(cmd, struct failhtlc); failhtlc->jsoncmd = cmd; @@ -1697,6 +1763,51 @@ const struct json_command failhtlc_command = { "Returns an empty result on success" }; +static void do_commit(struct peer *peer, struct command *jsoncmd) +{ + /* We can have changes we suggested, or changes they suggested. */ + if (peer->them.staging_cstate->changes == peer->them.commit->cstate->changes) { + command_fail(jsoncmd, "no changes to commit"); + return; + } + + set_current_command(peer, CMD_SEND_COMMIT, NULL, jsoncmd); +} + +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(cmd->dstate, buffer, peeridtok); + if (!peer) { + command_fail(cmd, "Could not find peer with that peerid"); + return; + } + + if (!peer->them.commit || !peer->them.commit->cstate) { + command_fail(cmd, "peer not fully established"); + return; + } + + queue_cmd(peer, do_commit, cmd); +} + +const struct json_command commit_command = { + "commit", + json_commit, + "Commit all staged HTLC changes with {peerid}", + "Returns an empty result on success" +}; + static void json_close(struct command *cmd, const char *buffer, const jsmntok_t *params) { diff --git a/daemon/peer.h b/daemon/peer.h index c3d60355a..ba1d64407 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -26,13 +26,13 @@ struct htlc_add { struct htlc_fulfill { enum htlc_stage_type fulfill; - size_t index; + u64 id; struct sha256 r; }; struct htlc_fail { enum htlc_stage_type fail; - size_t index; + u64 id; }; union htlc_staging { @@ -42,6 +42,21 @@ union htlc_staging { struct htlc_fail fail; }; +struct commit_info { + /* Previous one, if any. */ + struct commit_info *prev; + /* Revocation hash. */ + struct sha256 revocation_hash; + /* Commit tx. */ + struct bitcoin_tx *tx; + /* Channel state for this tx. */ + struct channel_state *cstate; + /* Other side's signature for last commit tx (if known) */ + struct bitcoin_signature *sig; + /* Revocation preimage (if known). */ + struct sha256 *revocation_preimage; +}; + struct peer_visible_state { /* CMD_OPEN_WITH_ANCHOR or CMD_OPEN_WITHOUT_ANCHOR */ enum state_input offer_anchor; @@ -53,24 +68,17 @@ struct peer_visible_state { unsigned int mindepth; /* Commitment fee they're offering (satoshi). */ u64 commit_fee_rate; - /* Revocation hash for latest commit tx. */ - struct sha256 revocation_hash; /* Revocation hash for next commit tx. */ struct sha256 next_revocation_hash; - /* Current commit tx. */ - struct bitcoin_tx *commit; + /* Commit txs: last one is current. */ + struct commit_info *commit; + /* cstate to generate next commitment tx. */ + struct channel_state *staging_cstate; }; struct htlc_progress { /* The HTLC we're working on. */ union htlc_staging stage; - - /* Our next state. */ - /* Channel funding state, after we've completed htlc. */ - struct channel_state *cstate; - struct sha256 our_revocation_hash, their_revocation_hash; - struct bitcoin_tx *our_commit, *their_commit; - struct bitcoin_signature their_sig; }; struct out_pkt { @@ -105,9 +113,6 @@ 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; @@ -142,11 +147,12 @@ struct peer { struct txwatch *watch; } cur_commit; - /* Current HTLC, if any. */ - struct htlc_progress *current_htlc; /* Number of HTLC updates (== number of previous commit txs) */ u64 commit_tx_counter; + /* Counter to make unique HTLC ids. */ + u64 htlc_id_counter; + struct { /* Our last suggested closing fee. */ u64 our_fee; @@ -180,12 +186,8 @@ struct peer { void setup_listeners(struct lightningd_state *dstate, unsigned int portnum); -void make_commit_txs(const tal_t *ctx, - const struct peer *peer, - const struct sha256 *our_revocation_hash, - const struct sha256 *their_revocation_hash, - const struct channel_state *cstate, - struct bitcoin_tx **ours, struct bitcoin_tx **theirs); +/* Populates very first peer->{us,them}.commit->{tx,cstate} */ +bool setup_first_commit(struct peer *peer); void peer_add_htlc_expiry(struct peer *peer, const struct abs_locktime *expiry); diff --git a/daemon/test/test.sh b/daemon/test/test.sh index 0c25b7df2..0dd077772 100755 --- a/daemon/test/test.sh +++ b/daemon/test/test.sh @@ -94,8 +94,8 @@ check_status_single() them_fee=$6 them_htlcs="$7" - if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"channel" : { "us" : { "pay" : '$us_pay', "fee" : '$us_fee', "htlcs" : [ '"$us_htlcs"'] }, "them" : { "pay" : '$them_pay', "fee" : '$them_fee', "htlcs" : [ '"$them_htlcs"'] } }'; then :; else - echo Cannot find $lcli output: '"channel" : { "us" : { "pay" : '$us_pay', "fee" : '$us_fee', "htlcs" : [ '"$us_htlcs"'] }, "them" : { "pay" : '$them_pay', "fee" : '$them_fee', "htlcs" : [ '"$them_htlcs"'] } }' >&2 + if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"our_amount" : '$us_pay', "our_fee" : '$us_fee', "their_amount" : '$them_pay', "their_fee" : '$them_fee', "our_htlcs" : [ '"$us_htlcs"'], "their_htlcs" : [ '"$them_htlcs"']'; then :; else + echo Cannot find $lcli output: '"our_amount" : '$us_pay', "our_fee" : '$us_fee', "their_amount" : '$them_pay', "their_fee" : '$them_fee', "our_htlcs" : [ '"$us_htlcs"'], "their_htlcs" : [ '"$them_htlcs"']' >&2 $lcli getpeers | tr -s '\012\011 ' ' ' >&2 return 1 fi @@ -114,6 +114,18 @@ check_status() check_status_single lcli2 "$them_pay" "$them_fee" "$them_htlcs" "$us_pay" "$us_fee" "$us_htlcs" } +check_staged() +{ + lcli="$1" + num_htlcs="$2" + + if $lcli getpeers | tr -s '\012\011 ' ' ' | $FGREP '"staged_changes" : '$num_htlcs; then :; else + echo Cannot find $lcli output: '"staged_changes" : '$num_htlcs >&2 + $lcli getpeers | tr -s '\012\011 ' ' ' >&2 + return 1 + fi +} + check_tx_spend() { $CLI generate 1 @@ -248,8 +260,8 @@ $CLI generate 2 # They poll every second, so give them time to process. sleep 2 -lcli1 getpeers | $FGREP STATE_NORMAL_HIGHPRIO -lcli2 getpeers | $FGREP STATE_NORMAL_LOWPRIO +lcli1 getpeers | $FGREP STATE_NORMAL +lcli2 getpeers | $FGREP STATE_NORMAL A_AMOUNT=$(($AMOUNT - $NO_HTLCS_FEE)) A_FEE=$NO_HTLCS_FEE @@ -262,12 +274,32 @@ SECRET=1de08917a61cb2b62ed5937d38577f6a7bfe59c176781c6d8128018e8b5ccdfd RHASH=`lcli1 dev-rhash $SECRET | sed 's/.*"\([0-9a-f]*\)".*/\1/'` lcli1 newhtlc $ID2 1000000 $EXPIRY $RHASH +# Nothing should have changed! +check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" +# But 2 should register a staged htlc. +check_staged lcli2 1 + +# Now commit it. +lcli1 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 "" $B_AMOUNT $B_FEE "" +check_staged lcli1 1 + # Check channel status A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 1000000)) A_FEE=$(($A_FEE + $EXTRA_FEE)) + +# Node 2 has it committed. +check_status_single lcli2 $B_AMOUNT $B_FEE "" $A_AMOUNT $A_FEE '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' + +# Now node2 gives commitment to node1. +lcli2 commit $ID1 check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 1000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE "" lcli2 fulfillhtlc $ID1 $SECRET +lcli2 commit $ID1 +lcli1 commit $ID2 # We've transferred the HTLC amount to 2, who now has to pay fees, # so no net change for A who saves on fees. @@ -280,6 +312,8 @@ check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" # A new one, at 10x the amount. lcli1 newhtlc $ID2 10000000 $EXPIRY $RHASH +lcli1 commit $ID2 +lcli2 commit $ID1 # Check channel status A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000)) @@ -287,6 +321,8 @@ A_FEE=$(($A_FEE + $EXTRA_FEE)) check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE "" lcli2 failhtlc $ID1 $RHASH +lcli2 commit $ID1 +lcli1 commit $ID2 # Back to how we were before. A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000)) @@ -294,22 +330,26 @@ A_FEE=$(($A_FEE - $EXTRA_FEE)) check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" # Same again, but this time it expires. -lcli1 newhtlc $ID2 10000000 $EXPIRY $RHASH +lcli1 newhtlc $ID2 10000001 $EXPIRY $RHASH +lcli1 commit $ID2 +lcli2 commit $ID1 # Check channel status -A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000000)) +A_AMOUNT=$(($A_AMOUNT - $EXTRA_FEE - 10000001)) A_FEE=$(($A_FEE + $EXTRA_FEE)) -check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000000, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE "" +check_status $A_AMOUNT $A_FEE '{ "msatoshis" : 10000001, "expiry" : { "second" : '$EXPIRY' }, "rhash" : "'$RHASH'" } ' $B_AMOUNT $B_FEE "" # Make sure node1 accepts the expiry packet. lcli1 dev-mocktime $(($EXPIRY)) # This should make node2 send it. lcli2 dev-mocktime $(($EXPIRY + 31)) +lcli2 commit $ID1 +lcli1 commit $ID2 sleep 1 # Back to how we were before. -A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000000)) +A_AMOUNT=$(($A_AMOUNT + $EXTRA_FEE + 10000001)) A_FEE=$(($A_FEE - $EXTRA_FEE)) check_status $A_AMOUNT $A_FEE "" $B_AMOUNT $B_FEE "" diff --git a/lightning.pb-c.c b/lightning.pb-c.c index 84d3e2903..316e63332 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -437,6 +437,49 @@ void open_complete__free_unpacked assert(message->base.descriptor == &open_complete__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void routing__init + (Routing *message) +{ + static Routing init_value = ROUTING__INIT; + *message = init_value; +} +size_t routing__get_packed_size + (const Routing *message) +{ + assert(message->base.descriptor == &routing__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t routing__pack + (const Routing *message, + uint8_t *out) +{ + assert(message->base.descriptor == &routing__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t routing__pack_to_buffer + (const Routing *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &routing__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Routing * + routing__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Routing *) + protobuf_c_message_unpack (&routing__descriptor, + allocator, len, data); +} +void routing__free_unpacked + (Routing *message, + ProtobufCAllocator *allocator) +{ + assert(message->base.descriptor == &routing__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void update_add_htlc__init (UpdateAddHtlc *message) { @@ -480,49 +523,6 @@ void update_add_htlc__free_unpacked assert(message->base.descriptor == &update_add_htlc__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void update_decline_htlc__init - (UpdateDeclineHtlc *message) -{ - static UpdateDeclineHtlc init_value = UPDATE_DECLINE_HTLC__INIT; - *message = init_value; -} -size_t update_decline_htlc__get_packed_size - (const UpdateDeclineHtlc *message) -{ - assert(message->base.descriptor == &update_decline_htlc__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t update_decline_htlc__pack - (const UpdateDeclineHtlc *message, - uint8_t *out) -{ - assert(message->base.descriptor == &update_decline_htlc__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t update_decline_htlc__pack_to_buffer - (const UpdateDeclineHtlc *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &update_decline_htlc__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -UpdateDeclineHtlc * - update_decline_htlc__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (UpdateDeclineHtlc *) - protobuf_c_message_unpack (&update_decline_htlc__descriptor, - allocator, len, data); -} -void update_decline_htlc__free_unpacked - (UpdateDeclineHtlc *message, - ProtobufCAllocator *allocator) -{ - assert(message->base.descriptor == &update_decline_htlc__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} void update_fulfill_htlc__init (UpdateFulfillHtlc *message) { @@ -566,6 +566,49 @@ void update_fulfill_htlc__free_unpacked assert(message->base.descriptor == &update_fulfill_htlc__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void fail_reason__init + (FailReason *message) +{ + static FailReason init_value = FAIL_REASON__INIT; + *message = init_value; +} +size_t fail_reason__get_packed_size + (const FailReason *message) +{ + assert(message->base.descriptor == &fail_reason__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t fail_reason__pack + (const FailReason *message, + uint8_t *out) +{ + assert(message->base.descriptor == &fail_reason__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t fail_reason__pack_to_buffer + (const FailReason *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &fail_reason__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +FailReason * + fail_reason__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (FailReason *) + protobuf_c_message_unpack (&fail_reason__descriptor, + allocator, len, data); +} +void fail_reason__free_unpacked + (FailReason *message, + ProtobufCAllocator *allocator) +{ + assert(message->base.descriptor == &fail_reason__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void update_fail_htlc__init (UpdateFailHtlc *message) { @@ -609,133 +652,90 @@ void update_fail_htlc__free_unpacked assert(message->base.descriptor == &update_fail_htlc__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void update_accept__init - (UpdateAccept *message) +void update_commit__init + (UpdateCommit *message) { - static UpdateAccept init_value = UPDATE_ACCEPT__INIT; + static UpdateCommit init_value = UPDATE_COMMIT__INIT; *message = init_value; } -size_t update_accept__get_packed_size - (const UpdateAccept *message) +size_t update_commit__get_packed_size + (const UpdateCommit *message) { - assert(message->base.descriptor == &update_accept__descriptor); + assert(message->base.descriptor == &update_commit__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t update_accept__pack - (const UpdateAccept *message, +size_t update_commit__pack + (const UpdateCommit *message, uint8_t *out) { - assert(message->base.descriptor == &update_accept__descriptor); + assert(message->base.descriptor == &update_commit__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t update_accept__pack_to_buffer - (const UpdateAccept *message, +size_t update_commit__pack_to_buffer + (const UpdateCommit *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &update_accept__descriptor); + assert(message->base.descriptor == &update_commit__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -UpdateAccept * - update_accept__unpack +UpdateCommit * + update_commit__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (UpdateAccept *) - protobuf_c_message_unpack (&update_accept__descriptor, + return (UpdateCommit *) + protobuf_c_message_unpack (&update_commit__descriptor, allocator, len, data); } -void update_accept__free_unpacked - (UpdateAccept *message, +void update_commit__free_unpacked + (UpdateCommit *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &update_accept__descriptor); + assert(message->base.descriptor == &update_commit__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void update_signature__init - (UpdateSignature *message) +void update_revocation__init + (UpdateRevocation *message) { - static UpdateSignature init_value = UPDATE_SIGNATURE__INIT; + static UpdateRevocation init_value = UPDATE_REVOCATION__INIT; *message = init_value; } -size_t update_signature__get_packed_size - (const UpdateSignature *message) +size_t update_revocation__get_packed_size + (const UpdateRevocation *message) { - assert(message->base.descriptor == &update_signature__descriptor); + assert(message->base.descriptor == &update_revocation__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t update_signature__pack - (const UpdateSignature *message, +size_t update_revocation__pack + (const UpdateRevocation *message, uint8_t *out) { - assert(message->base.descriptor == &update_signature__descriptor); + assert(message->base.descriptor == &update_revocation__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t update_signature__pack_to_buffer - (const UpdateSignature *message, +size_t update_revocation__pack_to_buffer + (const UpdateRevocation *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &update_signature__descriptor); + assert(message->base.descriptor == &update_revocation__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -UpdateSignature * - update_signature__unpack +UpdateRevocation * + update_revocation__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (UpdateSignature *) - protobuf_c_message_unpack (&update_signature__descriptor, + return (UpdateRevocation *) + protobuf_c_message_unpack (&update_revocation__descriptor, allocator, len, data); } -void update_signature__free_unpacked - (UpdateSignature *message, +void update_revocation__free_unpacked + (UpdateRevocation *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &update_signature__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} -void update_complete__init - (UpdateComplete *message) -{ - static UpdateComplete init_value = UPDATE_COMPLETE__INIT; - *message = init_value; -} -size_t update_complete__get_packed_size - (const UpdateComplete *message) -{ - assert(message->base.descriptor == &update_complete__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t update_complete__pack - (const UpdateComplete *message, - uint8_t *out) -{ - assert(message->base.descriptor == &update_complete__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t update_complete__pack_to_buffer - (const UpdateComplete *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &update_complete__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -UpdateComplete * - update_complete__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (UpdateComplete *) - protobuf_c_message_unpack (&update_complete__descriptor, - allocator, len, data); -} -void update_complete__free_unpacked - (UpdateComplete *message, - ProtobufCAllocator *allocator) -{ - assert(message->base.descriptor == &update_complete__descriptor); + assert(message->base.descriptor == &update_revocation__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void close_clearing__init @@ -1620,16 +1620,54 @@ const ProtobufCMessageDescriptor open_complete__descriptor = (ProtobufCMessageInit) open_complete__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[4] = +static const ProtobufCFieldDescriptor routing__field_descriptors[1] = { { - "revocation_hash", + "info", 1, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, + PROTOBUF_C_TYPE_BYTES, 0, /* quantifier_offset */ - offsetof(UpdateAddHtlc, revocation_hash), - &sha256_hash__descriptor, + offsetof(Routing, info), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned routing__field_indices_by_name[] = { + 0, /* field[0] = info */ +}; +static const ProtobufCIntRange routing__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor routing__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "routing", + "Routing", + "Routing", + "", + sizeof(Routing), + 1, + routing__field_descriptors, + routing__field_indices_by_name, + 1, routing__number_ranges, + (ProtobufCMessageInit) routing__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[5] = +{ + { + "id", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(UpdateAddHtlc, id), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1670,17 +1708,30 @@ static const ProtobufCFieldDescriptor update_add_htlc__field_descriptors[4] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "route", + 5, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(UpdateAddHtlc, route), + &routing__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned update_add_htlc__field_indices_by_name[] = { 1, /* field[1] = amount_msat */ 3, /* field[3] = expiry */ + 0, /* field[0] = id */ 2, /* field[2] = r_hash */ - 0, /* field[0] = revocation_hash */ + 4, /* field[4] = route */ }; static const ProtobufCIntRange update_add_htlc__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 4 } + { 0, 5 } }; const ProtobufCMessageDescriptor update_add_htlc__descriptor = { @@ -1690,74 +1741,23 @@ const ProtobufCMessageDescriptor update_add_htlc__descriptor = "UpdateAddHtlc", "", sizeof(UpdateAddHtlc), - 4, + 5, update_add_htlc__field_descriptors, update_add_htlc__field_indices_by_name, 1, update_add_htlc__number_ranges, (ProtobufCMessageInit) update_add_htlc__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor update_decline_htlc__field_descriptors[2] = -{ - { - "insufficient_funds", - 1, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(UpdateDeclineHtlc, reason_case), - offsetof(UpdateDeclineHtlc, insufficient_funds), - &funding__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "cannot_route", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_BOOL, - offsetof(UpdateDeclineHtlc, reason_case), - offsetof(UpdateDeclineHtlc, cannot_route), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned update_decline_htlc__field_indices_by_name[] = { - 1, /* field[1] = cannot_route */ - 0, /* field[0] = insufficient_funds */ -}; -static const ProtobufCIntRange update_decline_htlc__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor update_decline_htlc__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "update_decline_htlc", - "UpdateDeclineHtlc", - "UpdateDeclineHtlc", - "", - sizeof(UpdateDeclineHtlc), - 2, - update_decline_htlc__field_descriptors, - update_decline_htlc__field_indices_by_name, - 1, update_decline_htlc__number_ranges, - (ProtobufCMessageInit) update_decline_htlc__init, - NULL,NULL,NULL /* reserved[123] */ -}; static const ProtobufCFieldDescriptor update_fulfill_htlc__field_descriptors[2] = { { - "revocation_hash", + "id", 1, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(UpdateFulfillHtlc, revocation_hash), - &sha256_hash__descriptor, + offsetof(UpdateFulfillHtlc, id), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1776,8 +1776,8 @@ static const ProtobufCFieldDescriptor update_fulfill_htlc__field_descriptors[2] }, }; static const unsigned update_fulfill_htlc__field_indices_by_name[] = { + 0, /* field[0] = id */ 1, /* field[1] = r */ - 0, /* field[0] = revocation_hash */ }; static const ProtobufCIntRange update_fulfill_htlc__number_ranges[1 + 1] = { @@ -1799,36 +1799,74 @@ const ProtobufCMessageDescriptor update_fulfill_htlc__descriptor = (ProtobufCMessageInit) update_fulfill_htlc__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor fail_reason__field_descriptors[1] = +{ + { + "info", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(FailReason, info), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned fail_reason__field_indices_by_name[] = { + 0, /* field[0] = info */ +}; +static const ProtobufCIntRange fail_reason__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor fail_reason__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "fail_reason", + "FailReason", + "FailReason", + "", + sizeof(FailReason), + 1, + fail_reason__field_descriptors, + fail_reason__field_indices_by_name, + 1, fail_reason__number_ranges, + (ProtobufCMessageInit) fail_reason__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCFieldDescriptor update_fail_htlc__field_descriptors[2] = { { - "revocation_hash", + "id", 1, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, + PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(UpdateFailHtlc, revocation_hash), - &sha256_hash__descriptor, + offsetof(UpdateFailHtlc, id), + NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "r_hash", + "reason", 2, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(UpdateFailHtlc, r_hash), - &sha256_hash__descriptor, + offsetof(UpdateFailHtlc, reason), + &fail_reason__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; static const unsigned update_fail_htlc__field_indices_by_name[] = { - 1, /* field[1] = r_hash */ - 0, /* field[0] = revocation_hash */ + 0, /* field[0] = id */ + 1, /* field[1] = reason */ }; static const ProtobufCIntRange update_fail_htlc__number_ranges[1 + 1] = { @@ -1850,7 +1888,7 @@ const ProtobufCMessageDescriptor update_fail_htlc__descriptor = (ProtobufCMessageInit) update_fail_htlc__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor update_accept__field_descriptors[2] = +static const ProtobufCFieldDescriptor update_commit__field_descriptors[1] = { { "sig", @@ -1858,136 +1896,85 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[2] = PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(UpdateAccept, sig), + offsetof(UpdateCommit, sig), &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "revocation_hash", - 2, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(UpdateAccept, revocation_hash), - &sha256_hash__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, }; -static const unsigned update_accept__field_indices_by_name[] = { - 1, /* field[1] = revocation_hash */ +static const unsigned update_commit__field_indices_by_name[] = { 0, /* field[0] = sig */ }; -static const ProtobufCIntRange update_accept__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor update_accept__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "update_accept", - "UpdateAccept", - "UpdateAccept", - "", - sizeof(UpdateAccept), - 2, - update_accept__field_descriptors, - update_accept__field_indices_by_name, - 1, update_accept__number_ranges, - (ProtobufCMessageInit) update_accept__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor update_signature__field_descriptors[2] = -{ - { - "sig", - 1, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(UpdateSignature, sig), - &signature__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "revocation_preimage", - 2, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(UpdateSignature, revocation_preimage), - &sha256_hash__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned update_signature__field_indices_by_name[] = { - 1, /* field[1] = revocation_preimage */ - 0, /* field[0] = sig */ -}; -static const ProtobufCIntRange update_signature__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor update_signature__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "update_signature", - "UpdateSignature", - "UpdateSignature", - "", - sizeof(UpdateSignature), - 2, - update_signature__field_descriptors, - update_signature__field_indices_by_name, - 1, update_signature__number_ranges, - (ProtobufCMessageInit) update_signature__init, - NULL,NULL,NULL /* reserved[123] */ -}; -static const ProtobufCFieldDescriptor update_complete__field_descriptors[1] = -{ - { - "revocation_preimage", - 1, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(UpdateComplete, revocation_preimage), - &sha256_hash__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned update_complete__field_indices_by_name[] = { - 0, /* field[0] = revocation_preimage */ -}; -static const ProtobufCIntRange update_complete__number_ranges[1 + 1] = +static const ProtobufCIntRange update_commit__number_ranges[1 + 1] = { { 1, 0 }, { 0, 1 } }; -const ProtobufCMessageDescriptor update_complete__descriptor = +const ProtobufCMessageDescriptor update_commit__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "update_complete", - "UpdateComplete", - "UpdateComplete", + "update_commit", + "UpdateCommit", + "UpdateCommit", "", - sizeof(UpdateComplete), + sizeof(UpdateCommit), 1, - update_complete__field_descriptors, - update_complete__field_indices_by_name, - 1, update_complete__number_ranges, - (ProtobufCMessageInit) update_complete__init, + update_commit__field_descriptors, + update_commit__field_indices_by_name, + 1, update_commit__number_ranges, + (ProtobufCMessageInit) update_commit__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor update_revocation__field_descriptors[2] = +{ + { + "revocation_preimage", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(UpdateRevocation, revocation_preimage), + &sha256_hash__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "next_revocation_hash", + 2, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(UpdateRevocation, next_revocation_hash), + &sha256_hash__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned update_revocation__field_indices_by_name[] = { + 1, /* field[1] = next_revocation_hash */ + 0, /* field[0] = revocation_preimage */ +}; +static const ProtobufCIntRange update_revocation__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor update_revocation__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "update_revocation", + "UpdateRevocation", + "UpdateRevocation", + "", + sizeof(UpdateRevocation), + 2, + update_revocation__field_descriptors, + update_revocation__field_indices_by_name, + 1, update_revocation__number_ranges, + (ProtobufCMessageInit) update_revocation__init, NULL,NULL,NULL /* reserved[123] */ }; #define close_clearing__field_descriptors NULL @@ -2097,7 +2084,7 @@ const ProtobufCMessageDescriptor error__descriptor = (ProtobufCMessageInit) error__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = +static const ProtobufCFieldDescriptor pkt__field_descriptors[13] = { { "update_add_htlc", @@ -2111,57 +2098,9 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "update_accept", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Pkt, pkt_case), - offsetof(Pkt, update_accept), - &update_accept__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "update_signature", - 4, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Pkt, pkt_case), - offsetof(Pkt, update_signature), - &update_signature__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "update_complete", - 5, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Pkt, pkt_case), - offsetof(Pkt, update_complete), - &update_complete__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "update_decline_htlc", - 6, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - offsetof(Pkt, pkt_case), - offsetof(Pkt, update_decline_htlc), - &update_decline_htlc__descriptor, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, { "update_fulfill_htlc", - 7, + 3, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), @@ -2173,7 +2112,7 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = }, { "update_fail_htlc", - 9, + 4, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), @@ -2183,6 +2122,30 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "update_commit", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Pkt, pkt_case), + offsetof(Pkt, update_commit), + &update_commit__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "update_revocation", + 6, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Pkt, pkt_case), + offsetof(Pkt, update_revocation), + &update_revocation__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "open", 20, @@ -2281,31 +2244,28 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = }, }; static const unsigned pkt__field_indices_by_name[] = { - 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 */ - 10, /* field[10] = open_complete */ - 1, /* field[1] = update_accept */ + 12, /* field[12] = auth */ + 9, /* field[9] = close_clearing */ + 10, /* field[10] = close_signature */ + 11, /* field[11] = error */ + 5, /* field[5] = open */ + 6, /* field[6] = open_anchor */ + 7, /* field[7] = open_commit_sig */ + 8, /* field[8] = open_complete */ 0, /* field[0] = update_add_htlc */ - 3, /* field[3] = update_complete */ - 4, /* field[4] = update_decline_htlc */ - 6, /* field[6] = update_fail_htlc */ - 5, /* field[5] = update_fulfill_htlc */ - 2, /* field[2] = update_signature */ + 3, /* field[3] = update_commit */ + 2, /* field[2] = update_fail_htlc */ + 1, /* field[1] = update_fulfill_htlc */ + 4, /* field[4] = update_revocation */ }; -static const ProtobufCIntRange pkt__number_ranges[6 + 1] = +static const ProtobufCIntRange pkt__number_ranges[5 + 1] = { { 2, 0 }, - { 9, 6 }, - { 20, 7 }, - { 30, 11 }, - { 40, 13 }, - { 50, 14 }, - { 0, 15 } + { 20, 5 }, + { 30, 9 }, + { 40, 11 }, + { 50, 12 }, + { 0, 13 } }; const ProtobufCMessageDescriptor pkt__descriptor = { @@ -2315,10 +2275,10 @@ const ProtobufCMessageDescriptor pkt__descriptor = "Pkt", "", sizeof(Pkt), - 15, + 13, pkt__field_descriptors, pkt__field_indices_by_name, - 6, pkt__number_ranges, + 5, pkt__number_ranges, (ProtobufCMessageInit) pkt__init, NULL,NULL,NULL /* reserved[123] */ }; diff --git a/lightning.pb-c.h b/lightning.pb-c.h index e8734b0a5..b0b9da2cd 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -25,13 +25,13 @@ typedef struct _OpenChannel OpenChannel; typedef struct _OpenAnchor OpenAnchor; typedef struct _OpenCommitSig OpenCommitSig; typedef struct _OpenComplete OpenComplete; +typedef struct _Routing Routing; typedef struct _UpdateAddHtlc UpdateAddHtlc; -typedef struct _UpdateDeclineHtlc UpdateDeclineHtlc; typedef struct _UpdateFulfillHtlc UpdateFulfillHtlc; +typedef struct _FailReason FailReason; typedef struct _UpdateFailHtlc UpdateFailHtlc; -typedef struct _UpdateAccept UpdateAccept; -typedef struct _UpdateSignature UpdateSignature; -typedef struct _UpdateComplete UpdateComplete; +typedef struct _UpdateCommit UpdateCommit; +typedef struct _UpdateRevocation UpdateRevocation; typedef struct _CloseClearing CloseClearing; typedef struct _CloseSignature CloseSignature; typedef struct _Error Error; @@ -267,6 +267,19 @@ struct _OpenComplete , NULL } +/* + * FIXME: Routing information. + */ +struct _Routing +{ + ProtobufCMessage base; + ProtobufCBinaryData info; +}; +#define ROUTING__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&routing__descriptor) \ + , {0,NULL} } + + /* * Start a new commitment tx to add an HTLC me -> you. */ @@ -274,9 +287,9 @@ struct _UpdateAddHtlc { ProtobufCMessage base; /* - * Hash for which I will supply preimage to revoke this commitment tx. + * Unique identifier for this HTLC. */ - Sha256Hash *revocation_hash; + uint64_t id; /* * Amount for htlc (millisatoshi) */ @@ -288,37 +301,15 @@ struct _UpdateAddHtlc /* * Time at which HTLC expires (absolute) */ - /* - * FIXME: Routing information. - */ Locktime *expiry; + /* + * Onion-wrapped routing information. + */ + Routing *route; }; #define UPDATE_ADD_HTLC__INIT \ { PROTOBUF_C_MESSAGE_INIT (&update_add_htlc__descriptor) \ - , NULL, 0, NULL, NULL } - - -typedef enum { - UPDATE_DECLINE_HTLC__REASON__NOT_SET = 0, - UPDATE_DECLINE_HTLC__REASON_INSUFFICIENT_FUNDS = 1, - UPDATE_DECLINE_HTLC__REASON_CANNOT_ROUTE = 2, -} UpdateDeclineHtlc__ReasonCase; - -/* - * We can't do this HTLC, sorry (instead of update_accept) - */ -struct _UpdateDeclineHtlc -{ - ProtobufCMessage base; - UpdateDeclineHtlc__ReasonCase reason_case; - union { - Funding *insufficient_funds; - protobuf_c_boolean cannot_route; - }; -}; -#define UPDATE_DECLINE_HTLC__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&update_decline_htlc__descriptor) \ - , UPDATE_DECLINE_HTLC__REASON__NOT_SET, {} } + , 0, 0, NULL, NULL, NULL } /* @@ -328,9 +319,9 @@ struct _UpdateFulfillHtlc { ProtobufCMessage base; /* - * Hash for which I will supply preimage to revoke this commitment tx. + * Which HTLC */ - Sha256Hash *revocation_hash; + uint64_t id; /* * HTLC R value. */ @@ -338,83 +329,73 @@ struct _UpdateFulfillHtlc }; #define UPDATE_FULFILL_HTLC__INIT \ { PROTOBUF_C_MESSAGE_INIT (&update_fulfill_htlc__descriptor) \ - , NULL, NULL } + , 0, NULL } /* - * Remove your HTLC: routing has failed upstream, we didn't like it, or timeout. + * FIXME: Failure information. */ +struct _FailReason +{ + ProtobufCMessage base; + ProtobufCBinaryData info; +}; +#define FAIL_REASON__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&fail_reason__descriptor) \ + , {0,NULL} } + + struct _UpdateFailHtlc { ProtobufCMessage base; /* - * Hash for which I will supply preimage to revoke this commitment tx. + * Which HTLC */ - Sha256Hash *revocation_hash; + uint64_t id; /* - * Hash for HTLC R value. + * Reason for failure (for relay to initial node) */ - Sha256Hash *r_hash; + FailReason *reason; }; #define UPDATE_FAIL_HTLC__INIT \ { PROTOBUF_C_MESSAGE_INIT (&update_fail_htlc__descriptor) \ - , NULL, NULL } + , 0, NULL } /* - * OK, I accept that update; here's your signature. + * Commit all the staged HTLCs. */ -struct _UpdateAccept +struct _UpdateCommit { ProtobufCMessage base; /* * Signature for your new commitment tx. */ Signature *sig; - /* - * Hash for which I will supply preimage to revoke this new commit tx. - */ - Sha256Hash *revocation_hash; }; -#define UPDATE_ACCEPT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \ - , NULL, NULL } - - -/* - * Thanks for accepting, here's my last bit. - */ -struct _UpdateSignature -{ - ProtobufCMessage base; - /* - * Signature for your new commitment tx. - */ - Signature *sig; - /* - * Hash preimage which revokes old commitment tx. - */ - Sha256Hash *revocation_preimage; -}; -#define UPDATE_SIGNATURE__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&update_signature__descriptor) \ - , NULL, NULL } +#define UPDATE_COMMIT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&update_commit__descriptor) \ + , NULL } /* * Complete the update. */ -struct _UpdateComplete +struct _UpdateRevocation { ProtobufCMessage base; /* * Hash preimage which revokes old commitment tx. */ Sha256Hash *revocation_preimage; + /* + * Revocation hash for my next commit transaction + */ + Sha256Hash *next_revocation_hash; }; -#define UPDATE_COMPLETE__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&update_complete__descriptor) \ - , NULL } +#define UPDATE_REVOCATION__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&update_revocation__descriptor) \ + , NULL, NULL } /* @@ -467,12 +448,10 @@ typedef enum { PKT__PKT_OPEN_COMMIT_SIG = 22, PKT__PKT_OPEN_COMPLETE = 23, PKT__PKT_UPDATE_ADD_HTLC = 2, - PKT__PKT_UPDATE_ACCEPT = 3, - PKT__PKT_UPDATE_SIGNATURE = 4, - PKT__PKT_UPDATE_COMPLETE = 5, - PKT__PKT_UPDATE_DECLINE_HTLC = 6, - PKT__PKT_UPDATE_FULFILL_HTLC = 7, - PKT__PKT_UPDATE_FAIL_HTLC = 9, + PKT__PKT_UPDATE_FULFILL_HTLC = 3, + PKT__PKT_UPDATE_FAIL_HTLC = 4, + PKT__PKT_UPDATE_COMMIT = 5, + PKT__PKT_UPDATE_REVOCATION = 6, PKT__PKT_CLOSE_CLEARING = 30, PKT__PKT_CLOSE_SIGNATURE = 31, PKT__PKT_ERROR = 40, @@ -501,12 +480,10 @@ struct _Pkt * Updating (most common) */ UpdateAddHtlc *update_add_htlc; - UpdateAccept *update_accept; - UpdateSignature *update_signature; - UpdateComplete *update_complete; - UpdateDeclineHtlc *update_decline_htlc; UpdateFulfillHtlc *update_fulfill_htlc; UpdateFailHtlc *update_fail_htlc; + UpdateCommit *update_commit; + UpdateRevocation *update_revocation; /* * Closing */ @@ -713,6 +690,25 @@ OpenComplete * void open_complete__free_unpacked (OpenComplete *message, ProtobufCAllocator *allocator); +/* Routing methods */ +void routing__init + (Routing *message); +size_t routing__get_packed_size + (const Routing *message); +size_t routing__pack + (const Routing *message, + uint8_t *out); +size_t routing__pack_to_buffer + (const Routing *message, + ProtobufCBuffer *buffer); +Routing * + routing__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void routing__free_unpacked + (Routing *message, + ProtobufCAllocator *allocator); /* UpdateAddHtlc methods */ void update_add_htlc__init (UpdateAddHtlc *message); @@ -732,25 +728,6 @@ UpdateAddHtlc * void update_add_htlc__free_unpacked (UpdateAddHtlc *message, ProtobufCAllocator *allocator); -/* UpdateDeclineHtlc methods */ -void update_decline_htlc__init - (UpdateDeclineHtlc *message); -size_t update_decline_htlc__get_packed_size - (const UpdateDeclineHtlc *message); -size_t update_decline_htlc__pack - (const UpdateDeclineHtlc *message, - uint8_t *out); -size_t update_decline_htlc__pack_to_buffer - (const UpdateDeclineHtlc *message, - ProtobufCBuffer *buffer); -UpdateDeclineHtlc * - update_decline_htlc__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void update_decline_htlc__free_unpacked - (UpdateDeclineHtlc *message, - ProtobufCAllocator *allocator); /* UpdateFulfillHtlc methods */ void update_fulfill_htlc__init (UpdateFulfillHtlc *message); @@ -770,6 +747,25 @@ UpdateFulfillHtlc * void update_fulfill_htlc__free_unpacked (UpdateFulfillHtlc *message, ProtobufCAllocator *allocator); +/* FailReason methods */ +void fail_reason__init + (FailReason *message); +size_t fail_reason__get_packed_size + (const FailReason *message); +size_t fail_reason__pack + (const FailReason *message, + uint8_t *out); +size_t fail_reason__pack_to_buffer + (const FailReason *message, + ProtobufCBuffer *buffer); +FailReason * + fail_reason__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void fail_reason__free_unpacked + (FailReason *message, + ProtobufCAllocator *allocator); /* UpdateFailHtlc methods */ void update_fail_htlc__init (UpdateFailHtlc *message); @@ -789,62 +785,43 @@ UpdateFailHtlc * void update_fail_htlc__free_unpacked (UpdateFailHtlc *message, ProtobufCAllocator *allocator); -/* UpdateAccept methods */ -void update_accept__init - (UpdateAccept *message); -size_t update_accept__get_packed_size - (const UpdateAccept *message); -size_t update_accept__pack - (const UpdateAccept *message, +/* UpdateCommit methods */ +void update_commit__init + (UpdateCommit *message); +size_t update_commit__get_packed_size + (const UpdateCommit *message); +size_t update_commit__pack + (const UpdateCommit *message, uint8_t *out); -size_t update_accept__pack_to_buffer - (const UpdateAccept *message, +size_t update_commit__pack_to_buffer + (const UpdateCommit *message, ProtobufCBuffer *buffer); -UpdateAccept * - update_accept__unpack +UpdateCommit * + update_commit__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void update_accept__free_unpacked - (UpdateAccept *message, +void update_commit__free_unpacked + (UpdateCommit *message, ProtobufCAllocator *allocator); -/* UpdateSignature methods */ -void update_signature__init - (UpdateSignature *message); -size_t update_signature__get_packed_size - (const UpdateSignature *message); -size_t update_signature__pack - (const UpdateSignature *message, +/* UpdateRevocation methods */ +void update_revocation__init + (UpdateRevocation *message); +size_t update_revocation__get_packed_size + (const UpdateRevocation *message); +size_t update_revocation__pack + (const UpdateRevocation *message, uint8_t *out); -size_t update_signature__pack_to_buffer - (const UpdateSignature *message, +size_t update_revocation__pack_to_buffer + (const UpdateRevocation *message, ProtobufCBuffer *buffer); -UpdateSignature * - update_signature__unpack +UpdateRevocation * + update_revocation__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void update_signature__free_unpacked - (UpdateSignature *message, - ProtobufCAllocator *allocator); -/* UpdateComplete methods */ -void update_complete__init - (UpdateComplete *message); -size_t update_complete__get_packed_size - (const UpdateComplete *message); -size_t update_complete__pack - (const UpdateComplete *message, - uint8_t *out); -size_t update_complete__pack_to_buffer - (const UpdateComplete *message, - ProtobufCBuffer *buffer); -UpdateComplete * - update_complete__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void update_complete__free_unpacked - (UpdateComplete *message, +void update_revocation__free_unpacked + (UpdateRevocation *message, ProtobufCAllocator *allocator); /* CloseClearing methods */ void close_clearing__init @@ -954,26 +931,26 @@ typedef void (*OpenCommitSig_Closure) typedef void (*OpenComplete_Closure) (const OpenComplete *message, void *closure_data); +typedef void (*Routing_Closure) + (const Routing *message, + void *closure_data); typedef void (*UpdateAddHtlc_Closure) (const UpdateAddHtlc *message, void *closure_data); -typedef void (*UpdateDeclineHtlc_Closure) - (const UpdateDeclineHtlc *message, - void *closure_data); typedef void (*UpdateFulfillHtlc_Closure) (const UpdateFulfillHtlc *message, void *closure_data); +typedef void (*FailReason_Closure) + (const FailReason *message, + void *closure_data); typedef void (*UpdateFailHtlc_Closure) (const UpdateFailHtlc *message, void *closure_data); -typedef void (*UpdateAccept_Closure) - (const UpdateAccept *message, +typedef void (*UpdateCommit_Closure) + (const UpdateCommit *message, void *closure_data); -typedef void (*UpdateSignature_Closure) - (const UpdateSignature *message, - void *closure_data); -typedef void (*UpdateComplete_Closure) - (const UpdateComplete *message, +typedef void (*UpdateRevocation_Closure) + (const UpdateRevocation *message, void *closure_data); typedef void (*CloseClearing_Closure) (const CloseClearing *message, @@ -1004,13 +981,13 @@ extern const ProtobufCEnumDescriptor open_channel__anchor_offer__descriptor; extern const ProtobufCMessageDescriptor open_anchor__descriptor; extern const ProtobufCMessageDescriptor open_commit_sig__descriptor; extern const ProtobufCMessageDescriptor open_complete__descriptor; +extern const ProtobufCMessageDescriptor routing__descriptor; extern const ProtobufCMessageDescriptor update_add_htlc__descriptor; -extern const ProtobufCMessageDescriptor update_decline_htlc__descriptor; extern const ProtobufCMessageDescriptor update_fulfill_htlc__descriptor; +extern const ProtobufCMessageDescriptor fail_reason__descriptor; 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 update_commit__descriptor; +extern const ProtobufCMessageDescriptor update_revocation__descriptor; extern const ProtobufCMessageDescriptor close_clearing__descriptor; extern const ProtobufCMessageDescriptor close_signature__descriptor; extern const ProtobufCMessageDescriptor error__descriptor; diff --git a/lightning.proto b/lightning.proto index 664cd0e18..a904338b8 100644 --- a/lightning.proto +++ b/lightning.proto @@ -112,63 +112,57 @@ message open_complete { // FIXME: add a merkle proof plus block headers here? } +// FIXME: Routing information. +message routing { + required bytes info = 1; +} + // Start a new commitment tx to add an HTLC me -> you. message update_add_htlc { - // Hash for which I will supply preimage to revoke this commitment tx. - required sha256_hash revocation_hash = 1; + // Unique identifier for this HTLC. + required uint64 id = 1; // Amount for htlc (millisatoshi) required uint32 amount_msat = 2; // Hash for HTLC R value. required sha256_hash r_hash = 3; // Time at which HTLC expires (absolute) required locktime expiry = 4; - // FIXME: Routing information. -} - -// We can't do this HTLC, sorry (instead of update_accept) -message update_decline_htlc { - oneof reason { - funding insufficient_funds = 1; - bool cannot_route = 2; - }; + // Onion-wrapped routing information. + required routing route = 5; } // Complete your HTLC: I have the R value, pay me! message update_fulfill_htlc { - // Hash for which I will supply preimage to revoke this commitment tx. - required sha256_hash revocation_hash = 1; + // Which HTLC + required uint64 id = 1; // HTLC R value. required sha256_hash r = 2; } -// Remove your HTLC: routing has failed upstream, we didn't like it, or timeout. +// FIXME: Failure information. +message fail_reason { + required bytes info = 1; +} + message update_fail_htlc { - // Hash for which I will supply preimage to revoke this commitment tx. - required sha256_hash revocation_hash = 1; - // Hash for HTLC R value. - required sha256_hash r_hash = 2; + // Which HTLC + required uint64 id = 1; + // Reason for failure (for relay to initial node) + required fail_reason reason = 2; } -// OK, I accept that update; here's your signature. -message update_accept { +// Commit all the staged HTLCs. +message update_commit { // Signature for your new commitment tx. required signature sig = 1; - // Hash for which I will supply preimage to revoke this new commit tx. - required sha256_hash revocation_hash = 2; -} - -// Thanks for accepting, here's my last bit. -message update_signature { - // Signature for your new commitment tx. - required signature sig = 1; - // Hash preimage which revokes old commitment tx. - required sha256_hash revocation_preimage = 2; } // Complete the update. -message update_complete { +message update_revocation { // Hash preimage which revokes old commitment tx. required sha256_hash revocation_preimage = 1; + // Revocation hash for my next commit transaction + required sha256_hash next_revocation_hash = 2; } // Start clearing out the channel HTLCs so we can close it @@ -199,12 +193,11 @@ message pkt { open_complete open_complete = 23; // Updating (most common) update_add_htlc update_add_htlc = 2; - update_accept update_accept = 3; - update_signature update_signature = 4; - update_complete update_complete = 5; - update_decline_htlc update_decline_htlc = 6; - update_fulfill_htlc update_fulfill_htlc = 7; - update_fail_htlc update_fail_htlc = 9; + update_fulfill_htlc update_fulfill_htlc = 3; + update_fail_htlc update_fail_htlc = 4; + update_commit update_commit = 5; + update_revocation update_revocation = 6; + // Closing close_clearing close_clearing = 30; close_signature close_signature = 31; diff --git a/state.c b/state.c index 896230c44..41aa5fb34 100644 --- a/state.c +++ b/state.c @@ -4,17 +4,6 @@ #endif #include -static inline bool high_priority(enum state state) -{ - return (state & 1) == (STATE_NORMAL_HIGHPRIO & 1); -} - -#define prio(state, name) \ - (high_priority(state) ? name##_HIGHPRIO : name##_LOWPRIO) - -#define toggle_prio(state, name) \ - (!high_priority(state) ? name##_HIGHPRIO : name##_LOWPRIO) - /* STATE_CLOSE* can be treated as a bitset offset from STATE_CLOSED */ #define BITS_TO_STATE(bits) (STATE_CLOSED + (bits)) #define STATE_TO_BITS(state) ((state) - STATE_CLOSED) @@ -39,10 +28,11 @@ static enum command_status next_state(struct peer *peer, /* * Simple marker to note we don't update state. * - * This happens in two cases: + * This happens in three cases: * - We're ignoring packets while closing. * - We stop watching an on-chain HTLC: we indicate that we want * INPUT_NO_MORE_HTLCS when we get the last one. + * - HTLC add/remove in STATE_NORMAL. */ static enum command_status unchanged_state(enum command_status cstatus) { @@ -78,6 +68,16 @@ static void complete_cmd(struct peer *peer, enum command_status *statusp, *statusp = status; } +/* FIXME: We do this when a command succeeds instantly, and + * state is unchanged. */ +static enum command_status instant_cmd_success(struct peer *peer, + enum command_status cstatus) +{ + assert(peer->cond == PEER_CMD_OK); + assert(cstatus == CMD_NONE); + return CMD_SUCCESS; +} + static void queue_tx_broadcast(const struct bitcoin_tx **broadcast, const struct bitcoin_tx *tx) { @@ -91,7 +91,6 @@ enum command_status state(struct peer *peer, const union input *idata, const struct bitcoin_tx **broadcast) { - Pkt *decline; const struct bitcoin_tx *tx; Pkt *err; enum command_status cstatus = CMD_NONE; @@ -243,8 +242,7 @@ enum command_status state(struct peer *peer, queue_pkt_open_complete(peer); if (peer->state == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED) { complete_cmd(peer, &cstatus, CMD_SUCCESS); - return next_state(peer, cstatus, - STATE_NORMAL_HIGHPRIO); + return next_state(peer, cstatus, STATE_NORMAL); } return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR); @@ -315,8 +313,7 @@ enum command_status state(struct peer *peer, queue_pkt_open_complete(peer); if (peer->state == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED) { complete_cmd(peer, &cstatus, CMD_SUCCESS); - return next_state(peer, cstatus, - STATE_NORMAL_LOWPRIO); + return next_state(peer, cstatus, STATE_NORMAL); } return next_state(peer, cstatus, STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR); @@ -370,12 +367,10 @@ enum command_status state(struct peer *peer, /* Ready for business! Anchorer goes first. */ if (peer->state == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR) { complete_cmd(peer, &cstatus, CMD_SUCCESS); - return next_state(peer, cstatus, - STATE_NORMAL_HIGHPRIO); + return next_state(peer, cstatus, STATE_NORMAL); } else { complete_cmd(peer, &cstatus, CMD_SUCCESS); - return next_state(peer, cstatus, - STATE_NORMAL_LOWPRIO); + return next_state(peer, cstatus, STATE_NORMAL); } } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { complete_cmd(peer, &cstatus, CMD_FAIL); @@ -406,217 +401,78 @@ enum command_status state(struct peer *peer, /* * Channel normal operating states. */ - case STATE_NORMAL_LOWPRIO: - case STATE_NORMAL_HIGHPRIO: - assert(peer->cond == PEER_CMD_OK); - if (input_is(input, CMD_SEND_HTLC_ADD)) { - /* We are to send an HTLC update. */ - queue_pkt_htlc_add(peer, idata->htlc_prog); + case STATE_NORMAL: + /* + * FIXME: For simplicity, we disallow new staging requests + * while a commit is outstanding. + */ + + /* You can only issue this command one at a time. */ + if (input_is(input, CMD_SEND_COMMIT)) { + queue_pkt_commit(peer); change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_HTLC_ACCEPT)); + return next_state(peer, cstatus, STATE_NORMAL_COMMITTING); + } else if (input_is(input, CMD_SEND_HTLC_ADD)) { + /* We are to send an HTLC add. */ + queue_pkt_htlc_add(peer, idata->htlc_prog); + return instant_cmd_success(peer, cstatus); } else if (input_is(input, CMD_SEND_HTLC_FULFILL)) { /* We are to send an HTLC fulfill. */ queue_pkt_htlc_fulfill(peer, idata->htlc_prog); - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT)); + return instant_cmd_success(peer, cstatus); } else if (input_is(input, CMD_SEND_HTLC_FAIL)) { /* We are to send an HTLC fail. */ queue_pkt_htlc_fail(peer, idata->htlc_prog); - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT)); - } else if (input_is(input, CMD_CLOSE)) { - goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - goto start_unilateral_close; - } else if (input_is(input, PKT_UPDATE_ADD_HTLC)) { - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_add; - } else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) { - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_fulfill; - } else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) { - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_fail; - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - goto them_unilateral; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - goto old_commit_spotted; - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - goto anchor_unspent; - } else if (input_is(input, PKT_CLOSE_CLEARING)) { - goto accept_clearing; - } else if (input_is_pkt(input)) { - goto unexpected_pkt; + return instant_cmd_success(peer, cstatus); } - break; - case STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO: - case STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO: - /* HTLCs can also evoke a refusal. */ - if (input_is(input, PKT_UPDATE_DECLINE_HTLC)) { - peer_htlc_declined(peer, idata->pkt); - complete_cmd(peer, &cstatus, CMD_FAIL); - /* No update means no priority change. */ - return next_state(peer, cstatus, - prio(peer->state, STATE_NORMAL)); - } - /* Fall thru */ - case STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO: - case STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO: - if (input_is(input, PKT_UPDATE_ADD_HTLC)) { - /* If we're high priority, ignore their packet */ - if (high_priority(peer->state)) - return cstatus; - - /* Otherwise, process their request first: defer ours */ - peer_htlc_ours_deferred(peer); - complete_cmd(peer, &cstatus, CMD_REQUEUE); - /* Stay busy, since we're processing theirs. */ - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_add; - } else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) { - /* If we're high priority, ignore their packet */ - if (high_priority(peer->state)) - return cstatus; - - /* Otherwise, process their request first: defer ours */ - peer_htlc_ours_deferred(peer); - complete_cmd(peer, &cstatus, CMD_REQUEUE); - /* Stay busy, since we're processing theirs. */ - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_fulfill; - } else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) { - /* If we're high priority, ignore their packet */ - if (high_priority(peer->state)) - return cstatus; - - /* Otherwise, process their request first: defer ours */ - peer_htlc_ours_deferred(peer); - complete_cmd(peer, &cstatus, CMD_REQUEUE); - /* Stay busy, since we're processing theirs. */ - change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY); - goto accept_htlc_fail; - } else if (input_is(input, PKT_UPDATE_ACCEPT)) { - err = accept_pkt_update_accept(peer, idata->pkt); + /* Fall through... */ + case STATE_NORMAL_COMMITTING: + /* Only expect revocation in STATE_NORMAL_COMMITTING */ + if (peer->state == STATE_NORMAL_COMMITTING + && input_is(input, PKT_UPDATE_REVOCATION)) { + err = accept_pkt_revocation(peer, idata->pkt); if (err) { - peer_htlc_aborted(peer); complete_cmd(peer, &cstatus, CMD_FAIL); goto err_start_unilateral_close; } - queue_pkt_update_signature(peer); - /* HTLC is signed (though old tx not revoked yet!) */ - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_COMPLETE)); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto anchor_unspent; - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto them_unilateral; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto old_commit_spotted; - } else if (input_is(input, CMD_CLOSE)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_unilateral_close; - } else if (input_is(input, PKT_CLOSE_CLEARING)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_clearing; - } else if (input_is_pkt(input)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt; - } - break; - case STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO: - case STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO: - if (input_is(input, PKT_UPDATE_COMPLETE)) { - err = accept_pkt_update_complete(peer, idata->pkt); - if (err) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto err_start_unilateral_close; - } - peer_htlc_done(peer); complete_cmd(peer, &cstatus, CMD_SUCCESS); - return next_state(peer, cstatus, - toggle_prio(peer->state, STATE_NORMAL)); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto anchor_unspent; - } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto them_unilateral; - } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto old_commit_spotted; - } else if (input_is(input, PKT_CLOSE_CLEARING)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto accept_clearing; - } else if (input_is(input, CMD_CLOSE)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_clearing; - } else if (input_is(input, INPUT_CONNECTION_LOST)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto start_unilateral_close; - } else if (input_is_pkt(input)) { - peer_htlc_aborted(peer); - complete_cmd(peer, &cstatus, CMD_FAIL); - goto unexpected_pkt; + return next_state(peer, cstatus, STATE_NORMAL); } - break; - case STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO: - case STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO: - if (input_is(input, PKT_UPDATE_SIGNATURE)) { - err = accept_pkt_update_signature(peer, idata->pkt); - if (err) { - peer_htlc_aborted(peer); + + if (input_is(input, CMD_CLOSE)) { + goto start_clearing; + } else if (input_is(input, PKT_UPDATE_ADD_HTLC)) { + err = accept_pkt_htlc_add(peer, idata->pkt); + if (err) goto err_start_unilateral_close; - } - queue_pkt_update_complete(peer); - - peer_htlc_done(peer); - change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK); - /* Toggle between high and low priority states. */ - return next_state(peer, cstatus, - toggle_prio(peer->state, STATE_NORMAL)); - } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { - peer_htlc_aborted(peer); - goto anchor_unspent; + return unchanged_state(cstatus); + } else if (input_is(input, PKT_UPDATE_FULFILL_HTLC)) { + err = accept_pkt_htlc_fulfill(peer, idata->pkt); + if (err) + goto err_start_unilateral_close; + return unchanged_state(cstatus); + } else if (input_is(input, PKT_UPDATE_FAIL_HTLC)) { + err = accept_pkt_htlc_fail(peer, idata->pkt); + if (err) + goto err_start_unilateral_close; + return unchanged_state(cstatus); + } else if (input_is(input, PKT_UPDATE_COMMIT)) { + err = accept_pkt_commit(peer, idata->pkt); + if (err) + goto err_start_unilateral_close; + queue_pkt_revocation(peer); + return unchanged_state(cstatus); } else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) { - peer_htlc_aborted(peer); goto them_unilateral; } else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) { - peer_htlc_aborted(peer); goto old_commit_spotted; - } else if (input_is(input, CMD_CLOSE)) { - peer_htlc_aborted(peer); - goto start_clearing; + } else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) { + goto anchor_unspent; } else if (input_is(input, INPUT_CONNECTION_LOST)) { - peer_htlc_aborted(peer); goto start_unilateral_close; } else if (input_is(input, PKT_CLOSE_CLEARING)) { - peer_htlc_aborted(peer); goto accept_clearing; } else if (input_is_pkt(input)) { - peer_htlc_aborted(peer); goto unexpected_pkt; } break; @@ -1017,39 +873,6 @@ them_unilateral: return next_state(peer, cstatus, STATE_CLOSE_WAIT_SPENDTHEM); -accept_htlc_add: - err = accept_pkt_htlc_add(peer, idata->pkt, &decline); - if (err) - goto err_start_unilateral_close; - if (decline) { - queue_pkt_err(peer, decline); - peer_htlc_declined(peer, decline); - /* No update means no priority change. */ - change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK); - /* We may already be in STATE_NORMAL */ - return next_state_nocheck(peer, cstatus, - prio(peer->state, STATE_NORMAL)); - } - queue_pkt_update_accept(peer); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG)); - -accept_htlc_fail: - err = accept_pkt_htlc_fail(peer, idata->pkt); - if (err) - goto err_start_unilateral_close; - queue_pkt_update_accept(peer); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG)); - -accept_htlc_fulfill: - err = accept_pkt_htlc_fulfill(peer, idata->pkt); - if (err) - goto err_start_unilateral_close; - queue_pkt_update_accept(peer); - return next_state(peer, cstatus, - prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG)); - start_clearing: /* * Start a mutual close: tell them we want to clear. @@ -1095,6 +918,7 @@ instant_close: /* We can't have any HTLCs, since we haven't started. */ if (committed_to_htlcs(peer)) return next_state(peer, cstatus, STATE_ERR_INTERNAL); + return next_state(peer, cstatus, STATE_CLOSED); old_commit_spotted: diff --git a/state.h b/state.h index 3a227074b..ff12d1899 100644 --- a/state.h +++ b/state.h @@ -65,30 +65,6 @@ struct signature; /* Inform peer have an unexpected packet. */ void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt); -/* Current HTLC management. - * The "current" htlc is set before sending CMD_SEND_HTLC_*, or by - * accept_pkt_htlc_*. - * - * After that the state machine manages the current htlc, eventually giving one - * of the following calls (which should reset the current HTLC): - * - * - peer_htlc_declined: sent PKT_UPDATE_DECLINE_HTLC. - * - peer_htlc_ours_deferred: their update was higher priority, retry later. - * - peer_htlc_added: a new HTLC was added successfully. - * - peer_htlc_fulfilled: an existing HTLC was fulfilled successfully. - * - peer_htlc_fail: an existing HTLC failed to route/timedout/etc. - * - peer_htlc_aborted: eg. comms error - */ - -/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */ -void peer_htlc_declined(struct peer *peer, const Pkt *pkt); -/* Called when their update overrides our update cmd. */ -void peer_htlc_ours_deferred(struct peer *peer); -/* Successfully added/fulfilled/timedout/fail an HTLC. */ -void peer_htlc_done(struct peer *peer); -/* Someone aborted an existing HTLC. */ -void peer_htlc_aborted(struct peer *peer); - /* An on-chain transaction revealed an R value. */ const struct htlc *peer_tx_revealed_r_value(struct peer *peer, const struct bitcoin_event *btc); @@ -104,9 +80,8 @@ void queue_pkt_htlc_fulfill(struct peer *peer, const struct htlc_progress *htlc_prog); void queue_pkt_htlc_fail(struct peer *peer, const struct htlc_progress *htlc_prog); -void queue_pkt_update_accept(struct peer *peer); -void queue_pkt_update_signature(struct peer *peer); -void queue_pkt_update_complete(struct peer *peer); +void queue_pkt_commit(struct peer *peer); +void queue_pkt_revocation(struct peer *peer); void queue_pkt_close_clearing(struct peer *peer); void queue_pkt_close_signature(struct peer *peer); @@ -123,8 +98,7 @@ Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt, - Pkt **decline); +Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt); @@ -132,10 +106,9 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_update_accept(struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_update_complete(struct peer *peer, const Pkt *pkt); - -Pkt *accept_pkt_update_signature(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_close_sig(struct peer *peer, const Pkt *pkt, bool *matches); diff --git a/state_types.h b/state_types.h index e97255c9f..8b6b3e073 100644 --- a/state_types.h +++ b/state_types.h @@ -30,25 +30,11 @@ enum state { STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR, /* - * Normal update loop. - * - * NOTE: High and low prios must alternate! + * Normal state. */ - STATE_NORMAL_LOWPRIO, - STATE_NORMAL_HIGHPRIO, - - STATE_WAIT_FOR_HTLC_ACCEPT_LOWPRIO, - STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO, - - STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO, - STATE_WAIT_FOR_UPDATE_ACCEPT_HIGHPRIO, + STATE_NORMAL, + STATE_NORMAL_COMMITTING, - STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO, - STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO, - - STATE_WAIT_FOR_UPDATE_SIG_LOWPRIO, - STATE_WAIT_FOR_UPDATE_SIG_HIGHPRIO, - /* * Closing. */ @@ -195,15 +181,9 @@ enum state_input { /* Updating the commit transaction: your HTLC failed upstream */ PKT_UPDATE_FAIL_HTLC = PKT__PKT_UPDATE_FAIL_HTLC, - /* Update replies: */ - PKT_UPDATE_ACCEPT = PKT__PKT_UPDATE_ACCEPT, - /* Only for PKT_UPDATE_ADD_HTLC. */ - PKT_UPDATE_DECLINE_HTLC = PKT__PKT_UPDATE_DECLINE_HTLC, - - /* Reply to PKT_UPDATE_ACCEPT */ - PKT_UPDATE_SIGNATURE = PKT__PKT_UPDATE_SIGNATURE, - /* Reply to PKT_UPDATE_SIGNATURE */ - PKT_UPDATE_COMPLETE = PKT__PKT_UPDATE_COMPLETE, + /* Committing updates */ + PKT_UPDATE_COMMIT = PKT__PKT_UPDATE_COMMIT, + PKT_UPDATE_REVOCATION = PKT__PKT_UPDATE_REVOCATION, /* Mutual close sequence. */ PKT_CLOSE_CLEARING = PKT__PKT_CLOSE_CLEARING, @@ -279,6 +259,7 @@ enum state_input { CMD_SEND_HTLC_ADD, CMD_SEND_HTLC_FULFILL, CMD_SEND_HTLC_FAIL, + CMD_SEND_COMMIT, CMD_CLOSE, /* Connection lost/timedout with other node. */