From 149fa341bef79a50267a84f2d2d696dc1517d388 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 18 Aug 2016 14:23:45 +0930 Subject: [PATCH] packets.c: accept_pkt_* should do less state-mangling. Move other logic into caller, but it's not complete (it still needs to check some things, and still records some results). Signed-off-by: Rusty Russell --- daemon/packets.c | 252 ++++++++--------------------------------------- daemon/peer.c | 244 +++++++++++++++++++++++++++++++++++++++------ state.c | 46 ++++++++- state.h | 24 +++-- 4 files changed, 316 insertions(+), 250 deletions(-) diff --git a/daemon/packets.c b/daemon/packets.c index a5aceb04b..079a8fb64 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -269,7 +269,9 @@ Pkt *pkt_err_unexpected(struct peer *peer, const Pkt *pkt) } /* Process various packets: return an error packet on failure. */ -Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt, + struct sha256 *revocation_hash, + struct sha256 *next_revocation_hash) { struct rel_locktime locktime; const OpenChannel *o = pkt->open; @@ -305,49 +307,8 @@ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt) o->final_key, &peer->remote.finalkey)) return pkt_err(peer, "Bad finalkey"); - /* Set up their commit info now: rest gets done in setup_first_commit - * once anchor is established. */ - peer->remote.commit = new_commit_info(peer); - proto_to_sha256(o->revocation_hash, &peer->remote.commit->revocation_hash); - proto_to_sha256(o->next_revocation_hash, - &peer->remote.next_revocation_hash); - - /* Witness script for anchor. */ - peer->anchor.witnessscript - = bitcoin_redeem_2of2(peer, peer->dstate->secpctx, - &peer->local.commitkey, - &peer->remote.commitkey); - return NULL; -} - -/* Save and check signature. */ -static Pkt *check_and_save_commit_sig(struct peer *peer, - struct commit_info *ci, - const Signature *pb) -{ - struct bitcoin_signature *sig = tal(ci, struct bitcoin_signature); - - assert(!ci->sig); - sig->stype = SIGHASH_ALL; - if (!proto_to_signature(peer->dstate->secpctx, pb, &sig->sig)) - return pkt_err(peer, "Malformed signature"); - - log_debug(peer->log, "Checking sig for %u/%u msatoshis, %zu/%zu htlcs", - ci->cstate->side[OURS].pay_msat, - ci->cstate->side[THEIRS].pay_msat, - tal_count(ci->cstate->side[OURS].htlcs), - tal_count(ci->cstate->side[THEIRS].htlcs)); - - /* Their sig should sign our commit tx. */ - if (!check_tx_sig(peer->dstate->secpctx, - ci->tx, 0, - NULL, 0, - peer->anchor.witnessscript, - &peer->remote.commitkey, - sig)) - return pkt_err(peer, "Bad signature"); - - ci->sig = sig; + proto_to_sha256(o->revocation_hash, revocation_hash); + proto_to_sha256(o->next_revocation_hash, next_revocation_hash); return NULL; } @@ -362,18 +323,22 @@ Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt) proto_to_sha256(a->txid, &peer->anchor.txid.sha); peer->anchor.index = a->output_index; peer->anchor.satoshis = a->amount; - - if (!setup_first_commit(peer)) - return pkt_err(peer, "Insufficient funds for fee"); - return NULL; } -Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt, + struct bitcoin_signature **sig) { const OpenCommitSig *s = pkt->open_commit_sig; + struct signature signature; - return check_and_save_commit_sig(peer, peer->local.commit, s->sig); + if (!proto_to_signature(peer->dstate->secpctx, s->sig, &signature)) + return pkt_err(peer, "Malformed signature"); + + *sig = tal(peer, struct bitcoin_signature); + (*sig)->stype = SIGHASH_ALL; + (*sig)->sig = signature; + return NULL; } Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt) @@ -385,13 +350,11 @@ Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt) * 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) +Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt, struct htlc **h) { const UpdateAddHtlc *u = pkt->update_add_htlc; struct sha256 rhash; struct abs_locktime expiry; - struct htlc *htlc; - union htlc_staging stage; /* BOLT #2: * @@ -430,29 +393,10 @@ Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt) * * ...and the receiving node MUST add the HTLC addition to the * unacked changeset for its local commitment. */ - htlc = peer_new_htlc(peer, u->id, u->amount_msat, &rhash, - abs_locktime_to_blocks(&expiry), - u->route->info.data, u->route->info.len, - NULL, RCVD_ADD_HTLC); - - /* BOLT #2: - * - * A node MUST NOT offer `amount_msat` it cannot pay for in - * the remote commitment transaction at the current `fee_rate` (see - * "Fee Calculation" ). A node SHOULD fail the connection if - * this occurs. - */ - if (!cstate_add_htlc(peer->local.staging_cstate, htlc, THEIRS)) { - tal_free(htlc); - return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" - " in our commitment tx", - u->amount_msat); - } - - stage.add.add = HTLC_ADD; - stage.add.htlc = htlc; - add_unacked(&peer->local, &stage); - + *h = peer_new_htlc(peer, u->id, u->amount_msat, &rhash, + abs_locktime_to_blocks(&expiry), + u->route->info.data, u->route->info.len, + NULL, RCVD_ADD_HTLC); return NULL; } @@ -476,43 +420,27 @@ static Pkt *find_commited_htlc(struct peer *peer, uint64_t id, return NULL; } -Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt, struct htlc **h) { const UpdateFailHtlc *f = pkt->update_fail_htlc; - struct htlc *htlc; Pkt *err; - union htlc_staging stage; - err = find_commited_htlc(peer, f->id, &htlc); + err = find_commited_htlc(peer, f->id, h); if (err) return err; /* FIXME: Save reason. */ - - cstate_fail_htlc(peer->local.staging_cstate, htlc, OURS); - - /* BOLT #2: - * - * ... and the receiving node MUST add the HTLC fulfill/fail - * to the unacked changeset for its local commitment. - */ - stage.fail.fail = HTLC_FAIL; - stage.fail.htlc = htlc; - add_unacked(&peer->local, &stage); - htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); return NULL; } -Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt, struct htlc **h) { const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc; - struct htlc *htlc; struct sha256 rhash; struct rval r; Pkt *err; - union htlc_staging stage; - err = find_commited_htlc(peer, f->id, &htlc); + err = find_commited_htlc(peer, f->id, h); if (err) return err; @@ -520,102 +448,34 @@ Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) proto_to_rval(f->r, &r); sha256(&rhash, &r, sizeof(r)); - if (!structeq(&rhash, &htlc->rhash)) + if (!structeq(&rhash, &(*h)->rhash)) return pkt_err(peer, "Invalid r for %"PRIu64, f->id); - /* We can relay this upstream immediately. */ - our_htlc_fulfilled(peer, htlc, &r); - - /* BOLT #2: - * - * ... and the receiving node MUST add the HTLC fulfill/fail - * to the unacked changeset for its local commitment. - */ - cstate_fulfill_htlc(peer->local.staging_cstate, htlc, OURS); - htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); - - stage.fulfill.fulfill = HTLC_FULFILL; - stage.fulfill.htlc = htlc; - stage.fulfill.r = r; - add_unacked(&peer->local, &stage); + assert(!(*h)->r); + (*h)->r = tal_dup(*h, struct rval, &r); return NULL; } -Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt) +Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt, + struct bitcoin_signature *sig) { const UpdateCommit *c = pkt->update_commit; - Pkt *err; - struct commit_info *ci = new_commit_info(peer); - static const struct state_table changes[] = { - { RCVD_ADD_REVOCATION, RCVD_ADD_ACK_COMMIT }, - { RCVD_REMOVE_HTLC, RCVD_REMOVE_COMMIT }, - { RCVD_ADD_HTLC, RCVD_ADD_COMMIT }, - { RCVD_REMOVE_REVOCATION, RCVD_REMOVE_ACK_COMMIT } - }; - - /* BOLT #2: - * - * A node MUST NOT send an `update_commit` message which does - * not include any updates. - */ - if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) - return pkt_err(peer, "Empty commit"); - - /* Create new commit info for this commit tx. */ - ci->prev = peer->local.commit; - ci->commit_num = ci->prev->commit_num + 1; - ci->revocation_hash = peer->local.next_revocation_hash; - - /* BOLT #2: - * - * A receiving node MUST apply all local acked and unacked - * changes except unacked fee changes to the local commitment - */ - /* (We already applied them to staging_cstate as we went) */ - ci->cstate = copy_cstate(ci, peer->local.staging_cstate); - ci->tx = create_commit_tx(ci, peer, &ci->revocation_hash, - ci->cstate, LOCAL, &ci->map); - bitcoin_txid(ci->tx, &ci->txid); - - /* 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->local.commit = ci; - peer_get_revocation_hash(peer, ci->commit_num + 1, - &peer->local.next_revocation_hash); + sig->stype = SIGHASH_ALL; + if (!proto_to_signature(peer->dstate->secpctx, c->sig, &sig->sig)) + return pkt_err(peer, "Malformed signature"); return NULL; } -static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash) +Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt, + struct commit_info *ci) { + const UpdateRevocation *r = pkt->update_revocation; struct sha256 h; - proto_to_sha256(preimage, &h); - sha256(&h, &h, sizeof(h)); - return structeq(&h, hash); -} - -Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) -{ - const UpdateRevocation *r = pkt->update_revocation; - struct commit_info *ci = peer->remote.commit->prev; - static const struct state_table changes[] = { - { SENT_ADD_COMMIT, RCVD_ADD_REVOCATION }, - { SENT_REMOVE_ACK_COMMIT, RCVD_REMOVE_ACK_REVOCATION }, - { SENT_ADD_ACK_COMMIT, RCVD_ADD_ACK_REVOCATION }, - { SENT_REMOVE_COMMIT, RCVD_REMOVE_REVOCATION } - }; + assert(!ci->revocation_preimage); + ci->revocation_preimage = tal(ci, struct sha256); + proto_to_sha256(r->revocation_preimage, ci->revocation_preimage); /* BOLT #2: * @@ -623,45 +483,19 @@ Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) * SHA256 hash of `revocation_preimage` matches the previous commitment * transaction, and MUST fail if it does not. */ - if (!check_preimage(r->revocation_preimage, &ci->revocation_hash)) + sha256(&h, ci->revocation_preimage, sizeof(*ci->revocation_preimage)); + if (!structeq(&h, &ci->revocation_hash)) return pkt_err(peer, "complete preimage incorrect"); - /* They're revoking the previous one. */ - assert(!ci->revocation_preimage); - ci->revocation_preimage = tal(ci, struct sha256); - - proto_to_sha256(r->revocation_preimage, ci->revocation_preimage); - // save revocation preimages in shachain - if (!shachain_add_hash(&peer->their_preimages, 0xFFFFFFFFFFFFFFFFL - ci->commit_num, ci->revocation_preimage)) + if (!shachain_add_hash(&peer->their_preimages, + 0xFFFFFFFFFFFFFFFFL - ci->commit_num, + ci->revocation_preimage)) return pkt_err(peer, "preimage not next in shachain"); /* Save next revocation hash. */ proto_to_sha256(r->next_revocation_hash, &peer->remote.next_revocation_hash); - - /* BOLT #2: - * - * The receiver of `update_revocation`... MUST add the remote - * unacked changes to the set of local acked changes. - */ - add_acked_changes(&peer->local.commit->acked_changes, ci->unacked_changes); - apply_changeset(peer, &peer->local, OURS, - ci->unacked_changes, - tal_count(ci->unacked_changes)); - - if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) - fatal("Revocation received but we made empty commitment?"); - - /* Should never examine these again. */ - ci->unacked_changes = tal_free(ci->unacked_changes); - - /* That revocation has committed them to changes in the current commitment. - * Any acked changes come from our commitment, so those are now committed - * by both of us. - */ - peer_both_committed_to(peer, ci->acked_changes, THEIRS); - return NULL; } diff --git a/daemon/peer.c b/daemon/peer.c index 825b2e06c..8f9ff529c 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -368,19 +368,78 @@ static bool closing_pkt_in(struct peer *peer, const Pkt *pkt) static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) { Pkt *err; - struct commit_info *ci; - static const struct state_table changes[] = { + struct commit_info *ci = new_commit_info(peer); + /* FIXME: We can actually merge these two... */ + static const struct state_table commit_changes[] = { + { RCVD_ADD_REVOCATION, RCVD_ADD_ACK_COMMIT }, + { RCVD_REMOVE_HTLC, RCVD_REMOVE_COMMIT }, + { RCVD_ADD_HTLC, RCVD_ADD_COMMIT }, + { RCVD_REMOVE_REVOCATION, RCVD_REMOVE_ACK_COMMIT } + }; + static const struct state_table revocation_changes[] = { { RCVD_ADD_ACK_COMMIT, SENT_ADD_ACK_REVOCATION }, { RCVD_REMOVE_COMMIT, SENT_REMOVE_REVOCATION }, { RCVD_ADD_COMMIT, SENT_ADD_REVOCATION }, { RCVD_REMOVE_ACK_COMMIT, SENT_REMOVE_ACK_REVOCATION } }; - err = accept_pkt_commit(peer, pkt); + ci->sig = tal(ci, struct bitcoin_signature); + err = accept_pkt_commit(peer, pkt, ci->sig); if (err) return err; - assert(peer->local.commit); + /* BOLT #2: + * + * A node MUST NOT send an `update_commit` message which does + * not include any updates. + */ + if (!htlcs_changestate(peer, commit_changes, ARRAY_SIZE(commit_changes))) + return pkt_err(peer, "Empty commit"); + + /* Create new commit info for this commit tx. */ + ci->prev = peer->local.commit; + ci->commit_num = ci->prev->commit_num + 1; + ci->revocation_hash = peer->local.next_revocation_hash; + + /* BOLT #2: + * + * A receiving node MUST apply all local acked and unacked + * changes except unacked fee changes to the local commitment + */ + /* (We already applied them to staging_cstate as we went) */ + ci->cstate = copy_cstate(ci, peer->local.staging_cstate); + ci->tx = create_commit_tx(ci, peer, &ci->revocation_hash, + ci->cstate, LOCAL, &ci->map); + bitcoin_txid(ci->tx, &ci->txid); + + /* 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"); + + /* BOLT #2: + * + * A receiving node MUST apply all local acked and unacked changes + * except unacked fee changes to the local commitment, then it MUST + * check `sig` is valid for that transaction. + */ + if (!check_tx_sig(peer->dstate->secpctx, + ci->tx, 0, + NULL, 0, + peer->anchor.witnessscript, + &peer->remote.commitkey, + ci->sig)) + return pkt_err(peer, "Bad signature"); + + /* Switch to the new commitment. */ + peer->local.commit = ci; + peer_get_revocation_hash(peer, ci->commit_num + 1, + &peer->local.next_revocation_hash); + + /* Now, send the revocation. */ ci = peer->local.commit->prev; assert(ci); assert(!ci->revocation_preimage); @@ -388,7 +447,8 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) /* We have their signature on the current one, right? */ assert(peer->local.commit->sig); - if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) + if (!htlcs_changestate(peer, revocation_changes, + ARRAY_SIZE(revocation_changes))) fatal("sent revoke with no changes"); ci->revocation_preimage = tal(ci, struct sha256); @@ -402,7 +462,8 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) */ /* Note: this means the unacked changes as of the commit we're * revoking */ - add_acked_changes(&peer->remote.commit->acked_changes, ci->unacked_changes); + add_acked_changes(&peer->remote.commit->acked_changes, + ci->unacked_changes); apply_changeset(peer, &peer->remote, THEIRS, ci->unacked_changes, tal_count(ci->unacked_changes)); @@ -412,9 +473,9 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) /* We should never look at this again. */ ci->unacked_changes = tal_free(ci->unacked_changes); - /* That revocation has committed us to changes in the current commitment. - * Any acked changes come from their commitment, so those are now committed - * by both of us. + /* That revocation has committed us to changes in the current + * commitment. Any acked changes come from their commitment, so + * those are now committed by both of us. */ peer_both_committed_to(peer, ci->acked_changes, OURS); @@ -423,6 +484,127 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) return NULL; } +static Pkt *handle_pkt_htlc_add(struct peer *peer, const Pkt *pkt) +{ + union htlc_staging stage; + struct htlc *htlc; + Pkt *err; + + err = accept_pkt_htlc_add(peer, pkt, &htlc); + if (err) + return err; + + /* BOLT #2: + * + * A node MUST NOT offer `amount_msat` it cannot pay for in + * the remote commitment transaction at the current `fee_rate` (see + * "Fee Calculation" ). A node SHOULD fail the connection if + * this occurs. + */ + if (!cstate_add_htlc(peer->local.staging_cstate, htlc, THEIRS)) { + tal_free(htlc); + return pkt_err(peer, "Cannot afford %"PRIu64" milli-satoshis" + " in our commitment tx", + htlc->msatoshis); + } + + stage.add.add = HTLC_ADD; + stage.add.htlc = htlc; + add_unacked(&peer->local, &stage); + return NULL; +} + +static Pkt *handle_pkt_htlc_fail(struct peer *peer, const Pkt *pkt) +{ + union htlc_staging stage; + struct htlc *htlc; + Pkt *err; + + err = accept_pkt_htlc_fail(peer, pkt, &htlc); + if (err) + return err; + + cstate_fail_htlc(peer->local.staging_cstate, htlc, OURS); + + /* BOLT #2: + * + * ... and the receiving node MUST add the HTLC fulfill/fail + * to the unacked changeset for its local commitment. + */ + stage.fail.fail = HTLC_FAIL; + stage.fail.htlc = htlc; + add_unacked(&peer->local, &stage); + htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); + return NULL; +} + +static Pkt *handle_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) +{ + union htlc_staging stage; + struct htlc *htlc; + Pkt *err; + + err = accept_pkt_htlc_fulfill(peer, pkt, &htlc); + if (err) + return err; + + /* We can relay this upstream immediately. */ + our_htlc_fulfilled(peer, htlc, htlc->r); + + /* BOLT #2: + * + * ... and the receiving node MUST add the HTLC fulfill/fail + * to the unacked changeset for its local commitment. + */ + cstate_fulfill_htlc(peer->local.staging_cstate, htlc, OURS); + htlc_changestate(htlc, SENT_ADD_ACK_REVOCATION, RCVD_REMOVE_HTLC); + + stage.fulfill.fulfill = HTLC_FULFILL; + stage.fulfill.htlc = htlc; + stage.fulfill.r = *htlc->r; + add_unacked(&peer->local, &stage); + return NULL; +} + +static Pkt *handle_pkt_revocation(struct peer *peer, const Pkt *pkt) +{ + struct commit_info *ci = peer->remote.commit->prev; + Pkt *err; + static const struct state_table changes[] = { + { SENT_ADD_COMMIT, RCVD_ADD_REVOCATION }, + { SENT_REMOVE_ACK_COMMIT, RCVD_REMOVE_ACK_REVOCATION }, + { SENT_ADD_ACK_COMMIT, RCVD_ADD_ACK_REVOCATION }, + { SENT_REMOVE_COMMIT, RCVD_REMOVE_REVOCATION } + }; + + err = accept_pkt_revocation(peer, pkt, ci); + if (err) + return err; + + /* BOLT #2: + * + * The receiver of `update_revocation`... MUST add the remote + * unacked changes to the set of local acked changes. + */ + add_acked_changes(&peer->local.commit->acked_changes, + ci->unacked_changes); + apply_changeset(peer, &peer->local, OURS, + ci->unacked_changes, + tal_count(ci->unacked_changes)); + + if (!htlcs_changestate(peer, changes, ARRAY_SIZE(changes))) + fatal("Revocation received but we made empty commitment?"); + + /* Should never examine these again. */ + ci->unacked_changes = tal_free(ci->unacked_changes); + + /* That revocation has committed them to changes in the current + * commitment. Any acked changes come from our commitment, so those + * are now committed by both of us. */ + peer_both_committed_to(peer, ci->acked_changes, THEIRS); + return NULL; +} + /* This is the io loop while we're clearing. */ static bool clearing_pkt_in(struct peer *peer, const Pkt *pkt) { @@ -436,7 +618,7 @@ static bool clearing_pkt_in(struct peer *peer, const Pkt *pkt) if (peer->state == STATE_CLEARING) err = pkt_err_unexpected(peer, pkt); else { - err = accept_pkt_revocation(peer, pkt); + err = handle_pkt_revocation(peer, pkt); if (!err) { set_peer_state(peer, STATE_CLEARING, __func__); peer_update_complete(peer); @@ -452,7 +634,7 @@ static bool clearing_pkt_in(struct peer *peer, const Pkt *pkt) if (peer->closing.their_script) err = pkt_err(peer, "Update during clearing"); else - err = accept_pkt_htlc_add(peer, pkt); + err = handle_pkt_htlc_add(peer, pkt); break; case PKT__PKT_CLOSE_CLEARING: @@ -466,10 +648,10 @@ static bool clearing_pkt_in(struct peer *peer, const Pkt *pkt) break; case PKT__PKT_UPDATE_FULFILL_HTLC: - err = accept_pkt_htlc_fulfill(peer, pkt); + err = handle_pkt_htlc_fulfill(peer, pkt); break; case PKT__PKT_UPDATE_FAIL_HTLC: - err = accept_pkt_htlc_fail(peer, pkt); + err = handle_pkt_htlc_fail(peer, pkt); break; case PKT__PKT_UPDATE_COMMIT: err = handle_pkt_commit(peer, pkt); @@ -542,15 +724,15 @@ static bool normal_pkt_in(struct peer *peer, const Pkt *pkt) switch (pkt->pkt_case) { case PKT_UPDATE_ADD_HTLC: - err = accept_pkt_htlc_add(peer, pkt); + err = handle_pkt_htlc_add(peer, pkt); break; case PKT_UPDATE_FULFILL_HTLC: - err = accept_pkt_htlc_fulfill(peer, pkt); + err = handle_pkt_htlc_fulfill(peer, pkt); break; case PKT_UPDATE_FAIL_HTLC: - err = accept_pkt_htlc_fail(peer, pkt); + err = handle_pkt_htlc_fail(peer, pkt); break; case PKT_UPDATE_COMMIT: @@ -574,7 +756,7 @@ static bool normal_pkt_in(struct peer *peer, const Pkt *pkt) case PKT_UPDATE_REVOCATION: if (peer->state == STATE_NORMAL_COMMITTING) { - err = accept_pkt_revocation(peer, pkt); + err = handle_pkt_revocation(peer, pkt); if (!err) { peer_update_complete(peer); set_peer_state(peer, STATE_NORMAL, __func__); @@ -785,14 +967,10 @@ static bool fulfill_onchain(struct peer *peer, struct htlc *htlc) } static bool command_htlc_fulfill(struct peer *peer, - struct htlc *htlc, - const struct rval *r) + struct htlc *htlc) { union htlc_staging stage; - assert(!htlc->r); - htlc->r = tal_dup(htlc, struct rval, r); - if (peer->state == STATE_CLOSE_ONCHAIN_THEIR_UNILATERAL || peer->state == STATE_CLOSE_ONCHAIN_OUR_UNILATERAL) { return fulfill_onchain(peer, htlc); @@ -812,7 +990,7 @@ static bool command_htlc_fulfill(struct peer *peer, stage.fulfill.fulfill = HTLC_FULFILL; stage.fulfill.htlc = htlc; - stage.fulfill.r = *r; + stage.fulfill.r = *htlc->r; add_unacked(&peer->remote, &stage); htlc_changestate(htlc, RCVD_ADD_ACK_REVOCATION, SENT_REMOVE_HTLC); @@ -2051,11 +2229,11 @@ static void resolve_our_htlcs(struct peer *peer, void our_htlc_fulfilled(struct peer *peer, struct htlc *htlc, const struct rval *preimage) { - if (htlc->src) - command_htlc_fulfill(htlc->src->peer, htlc->src, preimage); - else { - assert(!htlc->r); - htlc->r = tal_dup(htlc, struct rval, preimage); + if (htlc->src) { + assert(!htlc->src->r); + htlc->src->r = tal_dup(htlc->src, struct rval, htlc->r); + command_htlc_fulfill(htlc->src->peer, htlc->src); + } else { complete_pay_command(peer, htlc); } } @@ -2921,7 +3099,10 @@ static void their_htlc_added(struct peer *peer, struct htlc *htlc) log_info(peer->log, "Immediately resolving HTLC %"PRIu64, htlc->id); - command_htlc_fulfill(peer, htlc, &payment->r); + + assert(!htlc->r); + htlc->r = tal_dup(htlc, struct rval, &payment->r); + command_htlc_fulfill(peer, htlc); goto free_rest; case ROUTE_STEP__NEXT_BITCOIN: @@ -3336,7 +3517,10 @@ static void json_fulfillhtlc(struct command *cmd, return; } - if (command_htlc_fulfill(peer, htlc, &r)) + assert(!htlc->r); + htlc->r = tal_dup(htlc, struct rval, &r); + + if (command_htlc_fulfill(peer, htlc)) command_success(cmd, null_response(cmd)); else command_fail(cmd, diff --git a/state.c b/state.c index e404aeab0..20eec2bd8 100644 --- a/state.c +++ b/state.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -33,6 +34,28 @@ static void send_open_pkt(struct peer *peer, queue_pkt_open(peer, anchor); } +static Pkt *init_from_pkt_open(struct peer *peer, const Pkt *pkt) +{ + struct commit_info *ci = new_commit_info(peer); + Pkt *err; + + err = accept_pkt_open(peer, pkt, &ci->revocation_hash, + &peer->remote.next_revocation_hash); + if (err) + return err; + + /* Set up their commit info now: rest gets done in setup_first_commit + * once anchor is established. */ + peer->remote.commit = ci; + + /* Witness script for anchor. */ + peer->anchor.witnessscript + = bitcoin_redeem_2of2(peer, peer->dstate->secpctx, + &peer->local.commitkey, + &peer->remote.commitkey); + return NULL; +} + enum state state(struct peer *peer, const enum state_input input, const Pkt *pkt, @@ -61,7 +84,7 @@ enum state state(struct peer *peer, break; case STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR: if (input_is(input, PKT_OPEN)) { - err = accept_pkt_open(peer, pkt); + err = init_from_pkt_open(peer, pkt); if (err) { peer_open_complete(peer, err->error->problem); goto err_breakdown; @@ -74,7 +97,7 @@ enum state state(struct peer *peer, break; case STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR: if (input_is(input, PKT_OPEN)) { - err = accept_pkt_open(peer, pkt); + err = init_from_pkt_open(peer, pkt); if (err) { peer_open_complete(peer, err->error->problem); goto err_breakdown; @@ -112,6 +135,13 @@ enum state state(struct peer *peer, peer_open_complete(peer, err->error->problem); goto err_breakdown; } + + if (!setup_first_commit(peer)) { + err = pkt_err(peer, "Insufficient funds for fee"); + peer_open_complete(peer, err->error->problem); + goto err_breakdown; + } + log_debug_struct(peer->log, "Creating sig for %s", struct bitcoin_tx, peer->remote.commit->tx); @@ -138,7 +168,17 @@ enum state state(struct peer *peer, break; case STATE_OPEN_WAIT_FOR_COMMIT_SIG: if (input_is(input, PKT_OPEN_COMMIT_SIG)) { - err = accept_pkt_open_commit_sig(peer, pkt); + err = accept_pkt_open_commit_sig(peer, pkt, + &peer->local.commit->sig); + if (!err && + !check_tx_sig(peer->dstate->secpctx, + peer->local.commit->tx, 0, + NULL, 0, + peer->anchor.witnessscript, + &peer->remote.commitkey, + peer->local.commit->sig)) + err = pkt_err(peer, "Bad signature"); + if (err) { bitcoin_release_anchor(peer, INPUT_NONE); peer_open_complete(peer, err->error->problem); diff --git a/state.h b/state.h index 2810d7fd8..0fd82217d 100644 --- a/state.h +++ b/state.h @@ -73,6 +73,7 @@ static inline bool state_can_remove_htlc(enum state s) struct peer; struct bitcoin_tx; +struct commit_info; static inline bool input_is_pkt(enum state_input input) { @@ -115,25 +116,32 @@ void queue_pkt_err(struct peer *peer, Pkt *err); Pkt *pkt_err_unexpected(struct peer *peer, const Pkt *pkt); /* Process various packets: return an error packet on failure. */ -Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt, + struct sha256 *revocation_hash, + struct sha256 *next_revocation_hash); + Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt); - +Pkt *accept_pkt_open_commit_sig(struct peer *peer, const Pkt *pkt, + struct bitcoin_signature **sig); + Pkt *accept_pkt_open_complete(struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_htlc_add(struct peer *peer, const Pkt *pkt, struct htlc **h); -Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_htlc_fail(struct peer *peer, const Pkt *pkt, struct htlc **h); -Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt, struct htlc **h); Pkt *accept_pkt_update_accept(struct peer *peer, const Pkt *pkt); -Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt); +Pkt *accept_pkt_commit(struct peer *peer, const Pkt *pkt, + struct bitcoin_signature *sig); + +Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt, + struct commit_info *ci); -Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt); Pkt *accept_pkt_close_clearing(struct peer *peer, const Pkt *pkt); /**