/* 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) { UpdateRevocation *u = tal(peer, UpdateRevocation); update_revocation__init(u); assert(peer->commit_tx_counter > 0); assert(peer->us.commit); assert(peer->us.commit->prev); assert(!peer->us.commit->prev->revocation_preimage); /* 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); u->ack = peer_outgoing_ack(peer); queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u); }
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->local.commit = new_commit_info(peer); peer->local.commit->revocation_hash = peer->local.next_revocation_hash; peer_get_revocation_hash(peer, 1, &peer->local.next_revocation_hash); open_channel__init(o); o->revocation_hash = sha256_to_proto(o, &peer->local.commit->revocation_hash); o->next_revocation_hash = sha256_to_proto(o, &peer->local.next_revocation_hash); o->commit_key = pubkey_to_proto(o, peer->dstate->secpctx, &peer->local.commitkey); o->final_key = pubkey_to_proto(o, peer->dstate->secpctx, &peer->local.finalkey); o->delay = tal(o, Locktime); locktime__init(o->delay); o->delay->locktime_case = LOCKTIME__LOCKTIME_BLOCKS; o->delay->blocks = rel_locktime_to_blocks(&peer->local.locktime); o->initial_fee_rate = peer->local.commit_fee_rate; if (anchor == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) assert(peer->local.offer_anchor == CMD_OPEN_WITH_ANCHOR); else { assert(anchor == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR); assert(peer->local.offer_anchor == CMD_OPEN_WITHOUT_ANCHOR); } o->anch = anchor; o->min_depth = peer->local.mindepth; queue_pkt(peer, PKT__PKT_OPEN, o); }
/* Send a preimage for the old commit tx. The one we've just committed to is * in peer->local.commit. */ void queue_pkt_revocation(struct peer *peer) { UpdateRevocation *u = tal(peer, UpdateRevocation); struct commit_info *ci; update_revocation__init(u); assert(peer->local.commit); ci = peer->local.commit->prev; assert(ci); assert(!ci->revocation_preimage); /* We have their signature on the current one, right? */ assert(peer->local.commit->sig); ci->revocation_preimage = tal(ci, struct sha256); peer_get_revocation_preimage(peer, ci->commit_num, ci->revocation_preimage); u->revocation_preimage = sha256_to_proto(u, ci->revocation_preimage); u->next_revocation_hash = sha256_to_proto(u, &peer->local.next_revocation_hash); queue_pkt(peer, PKT__PKT_UPDATE_REVOCATION, u); /* BOLT #2: * * The node sending `update_revocation` MUST add the local unacked * changes to the set of remote acked changes. */ /* Note: this means the unacked changes as of the commit we're * revoking */ 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)); if (tal_count(ci->unacked_changes)) remote_changes_pending(peer); /* 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. */ peer_both_committed_to(peer, ci->acked_changes, OURS); }
void queue_pkt_htlc_add(struct peer *peer, struct htlc *htlc) { UpdateAddHtlc *u = tal(peer, UpdateAddHtlc); union htlc_staging stage; update_add_htlc__init(u); u->id = htlc->id; u->amount_msat = htlc->msatoshis; u->r_hash = sha256_to_proto(u, &htlc->rhash); u->expiry = abs_locktime_to_proto(u, &htlc->expiry); u->route = tal(u, Routing); routing__init(u->route); u->route->info.data = tal_dup_arr(u, u8, htlc->routing, tal_count(htlc->routing), 0); u->route->info.len = tal_count(u->route->info.data); /* BOLT #2: * * The sending node MUST add the HTLC addition to the unacked * changeset for its remote commitment */ if (!cstate_add_htlc(peer->remote.staging_cstate, htlc, OURS)) fatal("Could not add HTLC?"); stage.add.add = HTLC_ADD; stage.add.htlc = htlc; add_unacked(&peer->remote, &stage); remote_changes_pending(peer); queue_pkt(peer, PKT__PKT_UPDATE_ADD_HTLC, u); }
void queue_pkt_htlc_add(struct peer *peer, const struct htlc_progress *htlc_prog) { UpdateAddHtlc *u = tal(peer, UpdateAddHtlc); update_add_htlc__init(u); assert(htlc_prog->stage.type == HTLC_ADD); 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); /* 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)); }
void queue_pkt_anchor(struct peer *peer) { OpenAnchor *a = tal(peer, OpenAnchor); open_anchor__init(a); a->txid = sha256_to_proto(a, &peer->anchor.txid.sha); a->output_index = peer->anchor.index; a->amount = peer->anchor.satoshis; /* 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->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_anchor(struct peer *peer) { OpenAnchor *a = tal(peer, OpenAnchor); open_anchor__init(a); a->txid = sha256_to_proto(a, &peer->anchor.txid.sha); a->output_index = peer->anchor.index; a->amount = peer->anchor.satoshis; /* This shouldn't happen! */ if (!setup_first_commit(peer)) { queue_pkt_err(peer, pkt_err(peer, "Own anchor has insufficient funds")); return; } queue_pkt(peer, PKT__PKT_OPEN_ANCHOR, a); }
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->id = htlc_prog->stage.fulfill.id; f->r = sha256_to_proto(f, &htlc_prog->stage.fulfill.r); /* 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)); }
return ret; } struct pkt *open_channel_pkt(const tal_t *ctx, const struct sha256 *revocation_hash, const struct pubkey *commit, const struct pubkey *final, u32 rel_locktime_seconds, OpenChannel__AnchorOffer offer_anchor, u32 min_depth, u64 commitment_fee) { OpenChannel o = OPEN_CHANNEL__INIT; Locktime lt = LOCKTIME__INIT; o.revocation_hash = sha256_to_proto(ctx, revocation_hash); o.commit_key = pubkey_to_proto(ctx, commit); o.final_key = pubkey_to_proto(ctx, final); lt.locktime_case = LOCKTIME__LOCKTIME_SECONDS; lt.seconds = rel_locktime_seconds; o.delay = < o.commitment_fee = commitment_fee; o.anch = offer_anchor; assert(o.anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR || o.anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR); o.min_depth = min_depth; { size_t len = open_channel__get_packed_size(&o); unsigned char *pb = malloc(len);
/* Takes complete update history, gets summary of last state. */ struct channel_state *gather_updates(const tal_t *ctx, const OpenChannel *o1, const OpenChannel *o2, const OpenAnchor *oa, uint64_t fee, char **argv, size_t *num_updates, struct sha256 *our_rhash, struct sha256 *their_rhash, struct signature *their_commit_sig) { Signature *sig = NULL; struct sha256 old_our_rhash, old_their_rhash, rhash1, rhash2; struct channel_state *cstate; /* Start sanity check. */ cstate = initial_funding(NULL, o1, o2, oa, fee); if (!cstate) errx(1, "Invalid open combination (need 1 anchor offer)"); /* If they don't want these, use dummy ones. */ if (!our_rhash) our_rhash = &rhash1; if (!their_rhash) their_rhash = &rhash2; proto_to_sha256(o1->revocation_hash, our_rhash); proto_to_sha256(o2->revocation_hash, their_rhash); assert(tal_count(cstate->a.htlcs) == 0); assert(tal_count(cstate->b.htlcs) == 0); /* If o2 sent anchor, it contains their commit sig. */ if (o2->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) sig = oa->commit_sig; if (num_updates) *num_updates = 0; while (*argv) { int64_t delta, amount; size_t n; bool received; Pkt *pkt; /* + marks messages sent by us, - for messages from them */ if (strstarts(*argv, "+")) { received = false; } else if (strstarts(*argv, "-")) { received = true; } else errx(1, "%s does not start with +/-", *argv); pkt = any_pkt_from_file(*argv + 1); switch (pkt->pkt_case) { case PKT__PKT_OPEN_COMMIT_SIG: if (received) sig = pkt->open_commit_sig->sig; break; case PKT__PKT_UPDATE_ADD_HTLC: amount = pkt->update_add_htlc->amount_msat; if (received) { if (!funding_delta(o2, o1, oa, 0, amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); add_htlc(&cstate->b, pkt->update_add_htlc, *argv); } else { if (!funding_delta(o1, o2, oa, 0, amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); add_htlc(&cstate->a, pkt->update_add_htlc, *argv); } update_rhash(pkt->update_add_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_TIMEDOUT_HTLC: if (received) { n = find_htlc(&cstate->b, pkt->update_timedout_htlc->r_hash); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, 0, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } else { n = find_htlc(&cstate->a, pkt->update_timedout_htlc->r_hash); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, 0, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } update_rhash(pkt->update_timedout_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; /* HTLC acceptor sends this to initiator. */ case PKT__PKT_UPDATE_ROUTEFAIL_HTLC: if (received) { n = find_htlc(&cstate->a, pkt->update_routefail_htlc->r_hash); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, 0, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } else { n = find_htlc(&cstate->b, pkt->update_routefail_htlc->r_hash); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, 0, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } update_rhash(pkt->update_routefail_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_FULFILL_HTLC: { struct sha256 r_hash, r_val; Sha256Hash *rh; /* Get hash, to find the HTLC. */ proto_to_sha256(pkt->update_fulfill_htlc->r, &r_val); sha256(&r_hash, &r_val, sizeof(r_val)); rh = sha256_to_proto(ctx, &r_hash); if (received) { /* HTLC was us->them, funds go to them. */ n = find_htlc(&cstate->a, rh); if (n == tal_count(cstate->a.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->a.htlcs[n]->amount_msat; if (!funding_delta(o1, o2, oa, amount, -amount, &cstate->a, &cstate->b)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->a, n); } else { /* HTLC was them->us, funds go to us. */ n = find_htlc(&cstate->b, rh); if (n == tal_count(cstate->b.htlcs)) errx(1, "Unknown R hash in %s", *argv); amount = cstate->b.htlcs[n]->amount_msat; if (!funding_delta(o2, o1, oa, amount, -amount, &cstate->b, &cstate->a)) errx(1, "Impossible htlc %llu %s", (long long)amount, *argv); remove_htlc(&cstate->b, n); } update_rhash(pkt->update_fulfill_htlc->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; } case PKT__PKT_UPDATE: if (received) delta = -pkt->update->delta_msat; else delta = pkt->update->delta_msat; if (!funding_delta(o1, o2, oa, delta, 0, &cstate->a, &cstate->b)) errx(1, "Impossible funding update %lli %s", (long long)delta, *argv); update_rhash(pkt->update->revocation_hash, received, num_updates, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_ACCEPT: if (received) sig = pkt->update_accept->sig; /* Does not increase num_updates */ update_rhash(pkt->update_accept->revocation_hash, received, NULL, &old_our_rhash, &old_their_rhash, our_rhash, their_rhash); break; case PKT__PKT_UPDATE_SIGNATURE: if (received) { sig = pkt->update_signature->sig; check_preimage(pkt->update_signature ->revocation_preimage, &old_their_rhash, their_rhash, *argv); } else { check_preimage(pkt->update_signature ->revocation_preimage, &old_our_rhash, our_rhash, *argv); } break; case PKT__PKT_UPDATE_COMPLETE: if (received) { check_preimage(pkt->update_complete ->revocation_preimage, &old_their_rhash, their_rhash, *argv); } else { check_preimage(pkt->update_complete ->revocation_preimage, &old_our_rhash, our_rhash, *argv); } break; default: errx(1, "Unexpected packet type %u", pkt->pkt_case); } argv++; } if (their_commit_sig) { if (!sig) errx(1, "No commit signature message found"); if (!proto_to_signature(sig, their_commit_sig)) errx(1, "Invalid signature"); } return cstate; }