/* Process various packets: return an error packet on failure. */ Pkt *accept_pkt_open(struct peer *peer, const Pkt *pkt) { struct rel_locktime locktime; const OpenChannel *o = pkt->open; if (!proto_to_rel_locktime(o->delay, &locktime)) return pkt_err(peer, "Invalid delay"); if (o->delay->locktime_case != LOCKTIME__LOCKTIME_BLOCKS) return pkt_err(peer, "Delay in seconds not accepted"); if (o->delay->blocks > peer->dstate->config.locktime_max) return pkt_err(peer, "Delay too great"); if (o->min_depth > peer->dstate->config.anchor_confirms_max) return pkt_err(peer, "min_depth too great"); if (o->initial_fee_rate < peer->dstate->config.commitment_fee_rate_min) return pkt_err(peer, "Commitment fee rate too low"); if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) peer->remote.offer_anchor = CMD_OPEN_WITH_ANCHOR; else if (o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR) peer->remote.offer_anchor = CMD_OPEN_WITHOUT_ANCHOR; else return pkt_err(peer, "Unknown offer anchor value"); if (peer->remote.offer_anchor == peer->local.offer_anchor) return pkt_err(peer, "Only one side can offer anchor"); if (!proto_to_rel_locktime(o->delay, &peer->remote.locktime)) return pkt_err(peer, "Malformed locktime"); peer->remote.mindepth = o->min_depth; peer->remote.commit_fee_rate = o->initial_fee_rate; if (!proto_to_pubkey(peer->dstate->secpctx, o->commit_key, &peer->remote.commitkey)) return pkt_err(peer, "Bad commitkey"); if (!proto_to_pubkey(peer->dstate->secpctx, 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; }
Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) { const UpdateRevocation *r = pkt->update_revocation; struct commit_info *ci = peer->remote.commit->prev; /* BOLT #2: * * The receiver of `update_revocation` MUST check that the * 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)) 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)) 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)); /* 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; }
Pkt *accept_pkt_htlc_fulfill(struct peer *peer, const Pkt *pkt) { const UpdateFulfillHtlc *f = pkt->update_fulfill_htlc; size_t n_us, n_them; struct sha256 r, rhash; Pkt *err; err = find_commited_htlc(peer, f->id, &n_us, &n_them); if (err) return err; /* Now, it must solve the HTLC rhash puzzle. */ proto_to_sha256(f->r, &r); sha256(&rhash, &r, sizeof(r)); if (!structeq(&rhash, &peer->us.staging_cstate->a.htlcs[n_us].rhash)) return pkt_err(peer, "Invalid r for %"PRIu64, f->id); /* Same ID must have same rhash */ assert(structeq(&rhash, &peer->them.staging_cstate->b.htlcs[n_them].rhash)); funding_a_fulfill_htlc(peer->us.staging_cstate, n_us); funding_b_fulfill_htlc(peer->them.staging_cstate, n_them); return NULL; }
static bool check_preimage(const Sha256Hash *preimage, const struct sha256 *hash) { struct sha256 h; proto_to_sha256(preimage, &h); sha256(&h, &h, sizeof(h)); return structeq(&h, hash); }
static void update_rhash(const Sha256Hash *rhash, bool received, size_t *num_updates, struct sha256 *old_our_rhash, struct sha256 *old_their_rhash, struct sha256 *our_rhash, struct sha256 *their_rhash) { /* Update rhash (and save old one for checking) */ if (received) { *old_their_rhash = *their_rhash; proto_to_sha256(rhash, their_rhash); } else { *old_our_rhash = *our_rhash; proto_to_sha256(rhash, our_rhash); } /* If they care, we count number of updates. */ if (num_updates) (*num_updates)++; }
Pkt *accept_pkt_revocation(struct peer *peer, const Pkt *pkt) { 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; }
static void check_preimage(const Sha256Hash *preimage, const struct sha256 *old, const struct sha256 *h, const char *file) { struct sha256 sha; if (!h) return; proto_to_sha256(preimage, &sha); sha256(&sha, &sha, sizeof(sha)); if (!structeq(&sha, old)) errx(1, "Invalid preimage in %s!", file); }
Pkt *accept_pkt_anchor(struct peer *peer, const Pkt *pkt) { const OpenAnchor *a = pkt->open_anchor; /* They must be offering anchor for us to try accepting */ assert(peer->local.offer_anchor == CMD_OPEN_WITHOUT_ANCHOR); assert(peer->remote.offer_anchor == CMD_OPEN_WITH_ANCHOR); 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; }
int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); struct sha256 seed, revocation_hash, their_rhash; OpenChannel *o1, *o2; Update *update; struct bitcoin_tx *anchor, *commit; struct sha256_double anchor_txid; struct pkt *pkt; struct bitcoin_signature sig; EC_KEY *privkey; bool testnet; struct pubkey pubkey1, pubkey2; u8 *redeemscript; int64_t delta; size_t i, p2sh_out; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, "<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> [previous-updates]\n" "Accept a new update message", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); if (argc < 6) opt_usage_exit_fail("Expected 5+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); anchor = bitcoin_tx_from_file(ctx, argv[2]); bitcoin_txid(anchor, &anchor_txid); o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; privkey = key_from_base58(argv[5], strlen(argv[5]), &testnet, &pubkey1); if (!privkey) errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) errx(1, "Private key '%s' not on testnet!", argv[5]); update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update; /* Figure out cumulative delta since anchor. */ delta = update->delta; for (i = 7; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* Get next revocation hash. */ shachain_from_seed(&seed, argc - 6, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); /* Get pubkeys */ if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2)) errx(1, "Invalid o1 commit pubkey"); if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2) || memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0) errx(1, "o1 pubkey != this privkey"); if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) errx(1, "Invalid o2 final pubkey"); /* This is what the anchor pays to; figure out whick output. */ redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); p2sh_out = find_p2sh_out(anchor, redeemscript); /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ proto_to_sha256(update->revocation_hash, &their_rhash); commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta, &anchor_txid, p2sh_out); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Delta too large"); /* Sign it for them. */ sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), privkey, &pubkey1, &sig.sig); pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); tal_free(ctx); return 0; }
/* * 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 sha256 rhash; struct abs_locktime expiry; struct htlc *htlc; union htlc_staging stage; /* 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"); if (abs_locktime_is_seconds(&expiry)) return pkt_err(peer, "HTLC expiry in seconds not supported!"); /* BOLT #2: * * A node MUST NOT add a HTLC if it would result in it * offering more than 300 HTLCs in the remote commitment transaction. */ if (tal_count(peer->remote.staging_cstate->side[THEIRS].htlcs) == 300) return pkt_err(peer, "Too many HTLCs"); /* BOLT #2: * * A node MUST set `id` to a unique identifier for this HTLC * amongst all past or future `update_add_htlc` messages. */ /* Note that it's not *our* problem if they do this, it's * theirs (future confusion). Nonetheless, we detect and * error for them. */ if (htlc_map_get(&peer->remote.htlcs, u->id)) return pkt_err(peer, "HTLC id %"PRIu64" clashes for you", u->id); /* BOLT #2: * * ...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, THEIRS); /* 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); return NULL; }
/* 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; }
/* * 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 sha256 rhash; struct abs_locktime expiry; /* 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(&expiry)) return pkt_err(peer, "HTLC expiry in blocks not supported!"); /* 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"); /* 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); /* 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); /* 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. */ return NULL; }