/* This is a fake channeld: it doesn't talk to the peer at all, it just * pretends to. It knows secret keys though, for a fake network, and can * respond as if we are connected to that network. * * Example known payment_hashes (0000000..., 0100000..., 020000..., ... FF0000...): * 66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925 * 01d0fabd251fcbbe2b93b4b927b26ad2a1a99077152e45ded1e678afa45dbec5 * 5778f985db754c6628691f56fadae50c65fddbe8eb2e93039633fefa05d45e31 * 91d3827f052f5a4b44d5fe2bed657c752247365d94f80a33cb09c1436a16b125 * 4b78063b9c224da311bd1d3fb969bba19e7e91ee07b506f9c4c438828915563f * aae761377f3b4f1f07d982783b902314b61a9cbe6ccfdfa96559039f07e332ed */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* stdin == requests, 3 == peer, 4 = HSM */ #define MASTER_FD STDIN_FILENO #define PEER_FD 3 #define HSM_FD 4 /* Map public keys to the private key */ struct node { struct privkey p; struct node_id id; const char *name; }; static const struct node_id *node_key(const struct node *n) { return &n->id; } static bool node_cmp(const struct node *n, const struct node_id *node_id) { return node_id_eq(&n->id, node_id); } HTABLE_DEFINE_NODUPS_TYPE(struct node, node_key, node_id_hash, node_cmp, node_map); struct info { /* To talk to lightningd */ struct daemon_conn *dc; /* The actual channel (to make sure we can fit!) */ struct channel *channel; /* Peer's privkey */ struct node *peer; /* Fast lookup for node ids to get privkeys */ struct node_map *node_map; /* Gossip map for lookup up our "channels" */ struct gossmap *gossmap; /* To check cltv delays */ u32 current_block_height; /* lightningd wants these when we tell it about a "new commitment" */ size_t commit_num; /* MPP parts we've gathered */ struct multi_payment **multi_payments; /* For MPP timers, delay timers */ struct timers timers; /* Seed for channel feature determination (e.g. delay time) */ struct siphash_seed seed; /* Currently used channels */ struct reservation **reservations; /* Fake stuff we feed into lightningd */ struct fee_states *fee_states; struct height_states *blockheight_states; struct bitcoin_tx *commit_tx; struct bitcoin_signature fakesig; struct sha256 peer_shaseed; }; /* FIXME: For the ecdh() function called by onion routines */ static struct node *current_node; /* Core of an outgoing HTLC: freed by succeed() or fail() */ struct fake_htlc { /* The HTLC id we assigned this */ u64 htlc_id; /* The payment hash */ struct sha256 payment_hash; /* The shared secrets from each decryption */ struct secret *secrets; }; struct payment { struct fake_htlc *htlc; /* onion payload at the final hop */ const struct onion_payload *payload; }; /* To re-combine MPP */ struct multi_payment { /* For use in the timeout timer */ struct info *info; /* The key to collect payments by */ struct sha256 payment_hash; /* All the payloads we've gathered */ struct payment **payments; }; /* We've taken up some part of a channel */ struct reservation { struct short_channel_id_dir scidd; struct amount_msat amount; }; /* Return deterministic value >= min < max for this channel */ static u64 channel_range(const struct info *info, const struct short_channel_id_dir *scidd, u64 min, u64 max) { return min + (siphash24(&info->seed, scidd, sizeof(scidd)) % max); } void ecdh(const struct pubkey *point, struct secret *ss) { if (secp256k1_ecdh(secp256k1_ctx, ss->data, &point->pubkey, current_node->p.secret.data, NULL, NULL) != 1) abort(); } static void pretend_got_revoke(struct info *info, u64 htlc_id, enum htlc_state newstate) { struct changed_htlc *changed; struct secret secret; struct pubkey next_per_commit_point; const u8 *msg; changed = tal_arr(tmpctx, struct changed_htlc, 1); changed->id = htlc_id; changed->newstate = newstate; if (!per_commit_secret(&info->peer_shaseed, &secret, info->commit_num - 1)) abort(); if (!per_commit_point(&info->peer_shaseed, &next_per_commit_point, info->commit_num + 1)) abort(); msg = towire_channeld_got_revoke(NULL, info->commit_num - 1, &secret, &next_per_commit_point, info->fee_states, info->blockheight_states, changed, NULL, NULL); daemon_conn_send(info->dc, take(msg)); } /* Tell lightningd that htlc is fully committed. */ static void update_commitment_tx_added(struct info *info, u64 htlc_id) { struct changed_htlc *changed; u8 *msg; const struct htlc **htlcs = tal_arr(tmpctx, const struct htlc *, 0); changed = tal_arr(tmpctx, struct changed_htlc, 1); changed->id = htlc_id; changed->newstate = SENT_ADD_COMMIT; /* Tell it we committed */ msg = towire_channeld_sending_commitsig(NULL, info->commit_num, NULL, info->fee_states, info->blockheight_states, changed); daemon_conn_send(info->dc, take(msg)); channel_sending_commit(info->channel, &htlcs); /* Tell it we got revoke & ack from them. */ pretend_got_revoke(info, htlc_id, RCVD_ADD_REVOCATION); changed->newstate = RCVD_ADD_ACK_COMMIT; msg = towire_channeld_got_commitsig(NULL, info->commit_num, info->fee_states, info->blockheight_states, &info->fakesig, NULL, NULL, NULL, NULL, changed, info->commit_tx, NULL); daemon_conn_send(info->dc, take(msg)); /* Tell full_channel.c the htlc is totally committed. */ channel_rcvd_revoke_and_ack(info->channel, &htlcs); channel_rcvd_commit(info->channel, &htlcs); channel_sending_revoke_and_ack(info->channel); /* Final change to SENT_ADD_ACK_REVOCATION is implied */ info->commit_num++; } static bool ecdh_maybe_blinding(const struct pubkey *ephemeral_key, const struct pubkey *blinding, struct secret *ss) { struct pubkey point = *ephemeral_key; if (blinding) { struct secret hmac; struct secret blinding_ss; ecdh(blinding, &blinding_ss); /* b(i) = HMAC256("blinded_node_id", ss(i)) * k(i) */ subkey_from_hmac("blinded_node_id", &blinding_ss, &hmac); /* We instead tweak the *ephemeral* key from the onion and use * our normal privkey: since hsmd knows only how to ECDH with * our real key */ if (secp256k1_ec_pubkey_tweak_mul(secp256k1_ctx, &point.pubkey, hmac.data) != 1) { return false; } } ecdh(&point, ss); return true; } static u8 *get_next_onion(const tal_t *ctx, const struct route_step *rs) { switch (rs->nextcase) { case ONION_END: return NULL; case ONION_FORWARD: return serialize_onionpacket(ctx, rs->next); } abort(); } static struct node *make_peer_node(const tal_t *ctx) { struct node *n = tal(ctx, struct node); u32 salt = 0; struct secret hsm_secret; struct pubkey pubkey; memset(&hsm_secret, 0, sizeof(hsm_secret)); snprintf((char *)&hsm_secret, sizeof(hsm_secret), "lightning-2"); /* This maps hsm_secret -> node privkey */ hkdf_sha256(&n->p, sizeof(n->p), &salt, sizeof(salt), &hsm_secret, sizeof(hsm_secret), "nodeid", 6); pubkey_from_privkey(&n->p, &pubkey); node_id_from_pubkey(&n->id, &pubkey); n->name = tal_fmt(n, "lightningd-2"); return n; } /* expected_id is NULL for initial node (aka l2) */ static struct node *get_current_node(struct info *info, const struct node_id *expected_id) { if (!expected_id) return info->peer; return node_map_get(info->node_map, expected_id); } static void populate_node_map(const struct gossmap *gossmap, struct node_map *node_map) { for (size_t i = 0; i < gossmap_max_node_idx(gossmap); i++) { struct node *n = tal(node_map, struct node); struct pubkey pubkey; /* gossmap-compress uses the node index (size_t, native endian), then all ones */ memset(&n->p, 1, sizeof(n->p)); memcpy(&n->p, &i, sizeof(i)); n->name = tal_fmt(n, "node#%zu", i); pubkey_from_privkey(&n->p, &pubkey); node_id_from_pubkey(&n->id, &pubkey); node_map_add(node_map, n); } } /* Sets current_node, *next_onion_packet, *shared_secret and *me, and decodes */ static struct onion_payload *decode_onion(const tal_t *ctx, struct info *info, const u8 onion_routing_packet[], const struct pubkey *path_key, const struct sha256 *payment_hash, struct amount_msat amount, u32 cltv, u8 **next_onion_packet, struct secret *shared_secret, struct gossmap_node **me) { struct onionpacket *op; enum onion_wire failcode; struct route_step *rs = NULL; struct onion_payload *payload; u64 failtlvtype; size_t failtlvpos; const char *explanation; op = parse_onionpacket(tmpctx, onion_routing_packet, TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE), &failcode); if (!op) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could not parse onion (failcode %u)", failcode); if (!ecdh_maybe_blinding(&op->ephemeralkey, path_key, shared_secret)) abort(); rs = process_onionpacket(tmpctx, op, shared_secret, payment_hash->u.u8, sizeof(*payment_hash)); if (!rs) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could not decode onion for %s", current_node->name); *next_onion_packet = get_next_onion(ctx, rs); payload = onion_decode(tmpctx, rs, path_key, NULL, amount, cltv, &failtlvtype, &failtlvpos, &explanation); if (!payload) { status_failed(STATUS_FAIL_INTERNAL_ERROR, "Failed tlvtype %"PRIu64" at %zu: %s", failtlvtype, failtlvpos, explanation); } /* Find ourselves in the gossmap, so we know our channels */ *me = gossmap_find_node(info->gossmap, ¤t_node->id); if (!*me) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Cannot find %s (%s) in gossmap", current_node->name, fmt_node_id(tmpctx, ¤t_node->id)); status_debug("Unpacked onion for %s", current_node->name); return payload; } static void fail(struct info *info, struct fake_htlc *htlc STEALS, const struct onion_payload *payload, enum onion_wire failcode) { struct failed_htlc *failed; const struct failed_htlc **failed_arr; u8 *msg; struct changed_htlc *changed; enum channel_remove_err err; msg = tal_arr(tmpctx, u8, 0); towire_u16(&msg, failcode); status_debug("Failing payment at %s due to %s", fmt_node_id(tmpctx, ¤t_node->id), onion_wire_name(failcode)); err = channel_fail_htlc(info->channel, LOCAL, htlc->htlc_id, NULL); assert(err == CHANNEL_ERR_REMOVE_OK); failed_arr = tal_arr(tmpctx, const struct failed_htlc *, 1); failed_arr[0] = failed = tal(failed_arr, struct failed_htlc); failed->id = htlc->htlc_id; failed->sha256_of_onion = NULL; failed->onion = create_onionreply(failed, &htlc->secrets[tal_count(htlc->secrets) - 1], msg); /* We create backwards, using shared secrets to wrap */ for (int i = tal_count(htlc->secrets) - 1; i >= 0; i--) failed->onion = wrap_onionreply(failed, &htlc->secrets[i], failed->onion); msg = towire_channeld_got_commitsig(NULL, info->commit_num, info->fee_states, info->blockheight_states, &info->fakesig, NULL, NULL, NULL, failed_arr, NULL, info->commit_tx, NULL); daemon_conn_send(info->dc, take(msg)); changed = tal_arr(tmpctx, struct changed_htlc, 1); changed->id = htlc->htlc_id; changed->newstate = SENT_REMOVE_ACK_COMMIT; /* Tell it we committed, too */ msg = towire_channeld_sending_commitsig(NULL, info->commit_num, NULL, info->fee_states, info->blockheight_states, changed); daemon_conn_send(info->dc, take(msg)); /* Tell it we got revoke & ack from them. */ pretend_got_revoke(info, htlc->htlc_id, RCVD_REMOVE_ACK_REVOCATION); info->commit_num++; tal_free(htlc); } static void destroy_multi_payment(struct multi_payment *mp) { for (size_t i = 0; i < tal_count(mp->info->multi_payments); i++) { if (mp->info->multi_payments[i] == mp) { tal_arr_remove(&mp->info->multi_payments, i); return; } } abort(); } static void multi_payment_timeout(struct multi_payment *mp) { for (size_t i = 0; i < tal_count(mp->payments); i++) { struct payment *p = mp->payments[i]; fail(mp->info, p->htlc, p->payload, WIRE_MPP_TIMEOUT); } tal_free(mp); } static struct multi_payment *add_payment_part(struct info *info, struct fake_htlc *htlc STEALS, const struct onion_payload *payload STEALS) { struct multi_payment *mp; struct payment *p; struct amount_msat total; for (size_t i = 0; i < tal_count(info->multi_payments); i++) { mp = info->multi_payments[i]; if (sha256_eq(&mp->payment_hash, &htlc->payment_hash)) { /* Cannot change total! */ assert(amount_msat_eq(*mp->payments[0]->payload->total_msat, *payload->total_msat)); goto found; } } mp = tal(info->multi_payments, struct multi_payment); mp->payment_hash = htlc->payment_hash; mp->payments = tal_arr(mp, struct payment *, 0); mp->info = info; tal_arr_expand(&info->multi_payments, mp); tal_add_destructor(mp, destroy_multi_payment); /* BOLT #4: * - MUST fail all HTLCs in the HTLC set after some reasonable timeout. * - SHOULD wait for at least 60 seconds after the initial HTLC. * - SHOULD use `mpp_timeout` for the failure message. */ new_reltimer(&info->timers, mp, time_from_sec(60), multi_payment_timeout, mp); found: p = tal(mp, struct payment); p->htlc = tal_steal(p, htlc); p->payload = tal_steal(p, payload); tal_arr_expand(&mp->payments, p); /* If amount is enough, return it */ total = AMOUNT_MSAT(0); for (size_t i = 0; i < tal_count(mp->payments); i++) { p = mp->payments[i]; if (!amount_msat_accumulate(&total, p->payload->amt_to_forward)) abort(); } if (amount_msat_less(total, *mp->payments[0]->payload->total_msat)) return NULL; /* Done! */ return mp; } static void succeed(struct info *info, struct fake_htlc *htlc STEALS, const struct onion_payload *payload, const struct preimage *preimage) { struct changed_htlc *changed; struct fulfilled_htlc *fulfilled; u8 *msg; enum channel_remove_err err; err = channel_fulfill_htlc(info->channel, LOCAL, htlc->htlc_id, preimage, NULL); status_debug("channel_fulfill_htlc = %i", err); assert(err == CHANNEL_ERR_REMOVE_OK); fulfilled = tal_arr(tmpctx, struct fulfilled_htlc, 1); fulfilled->id = htlc->htlc_id; fulfilled->payment_preimage = *preimage; msg = towire_channeld_got_commitsig(NULL, info->commit_num, info->fee_states, info->blockheight_states, &info->fakesig, NULL, NULL, fulfilled, NULL, NULL, info->commit_tx, NULL); daemon_conn_send(info->dc, take(msg)); changed = tal_arr(tmpctx, struct changed_htlc, 1); changed->id = htlc->htlc_id; changed->newstate = SENT_REMOVE_ACK_COMMIT; /* Tell it we committed, too */ msg = towire_channeld_sending_commitsig(NULL, info->commit_num, NULL, info->fee_states, info->blockheight_states, changed); daemon_conn_send(info->dc, take(msg)); /* Tell it we got revoke & ack from them. */ pretend_got_revoke(info, htlc->htlc_id, RCVD_REMOVE_ACK_REVOCATION); info->commit_num++; tal_free(htlc); } static void add_mpp(struct info *info, struct fake_htlc *htlc STEALS, const struct onion_payload *payload STEALS) { struct preimage preimage; struct multi_payment *mp; status_debug("Received payment at %s", current_node->name); mp = add_payment_part(info, htlc, payload); if (!mp) return; /* Completed payment. Guess payment_hash */ memset(&preimage, 0, sizeof(preimage)); for (size_t n = 0; n < 256; n++) { struct sha256 hash; preimage.r[0] = n; sha256(&hash, &preimage, sizeof(preimage)); if (sha256_eq(&hash, &mp->payment_hash)) { for (size_t i = 0; i < tal_count(mp->payments); i++) { struct payment *p = mp->payments[i]; succeed(info, p->htlc, p->payload, &preimage); } tal_free(mp); return; } status_debug("payment_hash %zu = %s", n, fmt_sha256(tmpctx, &hash)); } /* Unknown, fail them all. */ for (size_t i = 0; i < tal_count(mp->payments); i++) { struct payment *p = mp->payments[i]; fail(info, p->htlc, p->payload, WIRE_INCORRECT_OR_UNKNOWN_PAYMENT_DETAILS); } tal_free(mp); } static void destroy_reservation(struct reservation *r, struct info *info) { for (size_t i = 0; i < tal_count(info->reservations); i++) { if (info->reservations[i] == r) { tal_arr_remove(&info->reservations, i); return; } } abort(); } static void add_reservation(const tal_t *ctx, struct info *info, const struct short_channel_id_dir *scidd, struct amount_msat amount) { struct reservation *r = tal(ctx, struct reservation); r->scidd = *scidd; r->amount = amount; tal_arr_expand(&info->reservations, r); tal_add_destructor2(r, destroy_reservation, info); } /* We determine capacity for one side, then we derive the other side. * Reservations, however, do *not* credit the other side, since * they're htlcs in flight. (We don't update after payments, either!) */ static struct amount_msat calc_capacity(struct info *info, const struct gossmap_chan *c, const struct short_channel_id_dir *scidd) { struct short_channel_id_dir base_scidd; struct amount_msat base_capacity, dynamic_capacity; base_scidd.scid = scidd->scid; base_scidd.dir = 0; base_capacity = gossmap_chan_get_capacity(info->gossmap, c); dynamic_capacity = amount_msat(channel_range(info, &base_scidd, 0, base_capacity.millisatoshis)); /* Raw: rand function */ /* Invert capacity if that is backwards */ if (scidd->dir != base_scidd.dir) { if (!amount_msat_sub(&dynamic_capacity, base_capacity, dynamic_capacity)) abort(); } status_debug("Capacity for %s is %s, dynamic capacity is %s", fmt_short_channel_id_dir(tmpctx, scidd), fmt_amount_msat(tmpctx, base_capacity), fmt_amount_msat(tmpctx, dynamic_capacity)); /* Take away any reservations */ for (size_t i = 0; i < tal_count(info->reservations); i++) { if (!short_channel_id_dir_eq(&info->reservations[i]->scidd, scidd)) continue; /* We should never use more that we have! */ if (!amount_msat_sub(&dynamic_capacity, dynamic_capacity, info->reservations[i]->amount)) abort(); status_debug("... minus reservation %s", fmt_amount_msat(tmpctx, info->reservations[i]->amount)); } return dynamic_capacity; } /* Mutual recursion via timer */ struct delayed_forward { struct info *info; struct fake_htlc *htlc; struct amount_msat amount; u32 cltv_expiry; const u8 *onion_routing_packet; const struct pubkey *path_key; struct node_id expected; }; static void delayed_forward(struct delayed_forward *dfwd); static void forward_htlc(struct info *info, struct fake_htlc *htlc, struct amount_msat amount, u32 cltv_expiry, const u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)], const struct pubkey *path_key, const struct node_id *expected) { struct onion_payload *payload; u8 *next_onion_packet; struct gossmap_node *me; struct secret shared_secret; struct node_id next; struct gossmap_chan *c; struct short_channel_id_dir scidd; struct amount_msat amt_expected, htlc_min, htlc_max; struct pubkey *next_path_key; struct oneshot *timer; struct delayed_forward *dfwd; unsigned int msec_delay; current_node = get_current_node(info, expected); if (!current_node) { status_failed(STATUS_FAIL_INTERNAL_ERROR, "Could not find privkey for %s", fmt_node_id(tmpctx, expected)); } /* Decode, and figure out who I am */ payload = decode_onion(tmpctx, info, onion_routing_packet, path_key, &htlc->payment_hash, amount, cltv_expiry, &next_onion_packet, &shared_secret, &me); tal_arr_expand(&htlc->secrets, shared_secret); if (!next_onion_packet) { if (cltv_expiry < payload->outgoing_cltv) { fail(info, htlc, payload, WIRE_FINAL_INCORRECT_CLTV_EXPIRY); return; } if (cltv_expiry < info->current_block_height + 18) { fail(info, htlc, payload, WIRE_FINAL_INCORRECT_CLTV_EXPIRY); return; } /* MPP: consume htlc and payload */ add_mpp(info, htlc, payload); return; } /* Find next node by channel or scid */ for (size_t i = 0; i < me->num_chans; i++) { c = gossmap_nth_chan(info->gossmap, me, i, &scidd.dir); /* Get peer on other end */ gossmap_node_get_id(info->gossmap, gossmap_nth_node(info->gossmap, c, !scidd.dir), &next); scidd.scid = gossmap_chan_scid(info->gossmap, c); if (payload->forward_channel) { if (short_channel_id_eq(scidd.scid, *payload->forward_channel)) { goto found_next; } } else { struct node_id fwd; node_id_from_pubkey(&fwd, payload->forward_node_id); if (node_id_eq(&next, &fwd)) goto found_next; } } fail(info, htlc, payload, WIRE_UNKNOWN_NEXT_PEER); return; found_next: /* CLTV delta and fees must be correct */ if (!gossmap_chan_set(c, scidd.dir)) { status_failed(STATUS_FAIL_INTERNAL_ERROR, "Channel used %s is not set?", fmt_short_channel_id_dir(tmpctx, &scidd)); } if (payload->outgoing_cltv + c->half[scidd.dir].delay < cltv_expiry) { status_broken("%s: incoming cltv %u (delay=%u), but outgoing %u", fmt_short_channel_id_dir(tmpctx, &scidd), cltv_expiry, c->half[scidd.dir].delay, payload->outgoing_cltv); fail(info, htlc, payload, WIRE_INCORRECT_CLTV_EXPIRY); return; } amt_expected = payload->amt_to_forward; if (!amount_msat_add_fee(&amt_expected, c->half[scidd.dir].base_fee, c->half[scidd.dir].proportional_fee)) abort(); if (amount_msat_less(amount, amt_expected)) { status_broken("%s: expected %s (base=%u, prop=%u), but got %s to fwd %s", fmt_short_channel_id_dir(tmpctx, &scidd), fmt_amount_msat(tmpctx, amt_expected), c->half[scidd.dir].base_fee, c->half[scidd.dir].proportional_fee, fmt_amount_msat(tmpctx, amount), fmt_amount_msat(tmpctx, payload->amt_to_forward)); fail(info, htlc, payload, WIRE_FEE_INSUFFICIENT); return; } /* Obey our HTLC rules please! */ gossmap_chan_get_update_details(info->gossmap, c, scidd.dir, NULL, NULL, NULL, NULL, NULL, NULL, &htlc_min, &htlc_max); if (amount_msat_less(payload->amt_to_forward, htlc_min)) { status_broken("Amount %s is below minimum (%s) for %s!", fmt_amount_msat(tmpctx, payload->amt_to_forward), fmt_amount_msat(tmpctx, htlc_min), fmt_short_channel_id_dir(tmpctx, &scidd)); fail(info, htlc, payload, WIRE_AMOUNT_BELOW_MINIMUM); return; } if (amount_msat_greater(payload->amt_to_forward, htlc_max)) { status_broken("Amount %s is above maximum (%s) for %s!", fmt_amount_msat(tmpctx, payload->amt_to_forward), fmt_amount_msat(tmpctx, htlc_max), fmt_short_channel_id_dir(tmpctx, &scidd)); fail(info, htlc, payload, WIRE_TEMPORARY_CHANNEL_FAILURE); return; } if (amount_msat_greater(amount, calc_capacity(info, c, &scidd))) { fail(info, htlc, payload, WIRE_TEMPORARY_CHANNEL_FAILURE); return; } /* When we resolve the HTLC, we'll cancel the reservations */ add_reservation(htlc, info, &scidd, amount); if (payload->path_key) { struct sha256 sha; blinding_hash_e_and_ss(payload->path_key, &payload->blinding_ss, &sha); next_path_key = tal(tmpctx, struct pubkey); blinding_next_path_key(payload->path_key, &sha, next_path_key); } else next_path_key = NULL; dfwd = tal(NULL, struct delayed_forward); dfwd->info = info; dfwd->htlc = htlc; dfwd->amount = payload->amt_to_forward; dfwd->cltv_expiry = payload->outgoing_cltv; dfwd->onion_routing_packet = tal_steal(dfwd, next_onion_packet); dfwd->path_key = tal_steal(dfwd, next_path_key); dfwd->expected = next; /* Delay 0.1 - 1 seconds, but skewed lower */ msec_delay = channel_range(info, &scidd, 0, 900); msec_delay = 100 + channel_range(info, &scidd, 0, msec_delay); status_debug("Delaying %u msec for %s", msec_delay, fmt_short_channel_id_dir(tmpctx, &scidd)); timer = new_reltimer(&info->timers, info, time_from_msec(msec_delay), delayed_forward, dfwd); /* Free dfwd after timer expires */ tal_steal(timer, dfwd); } static void delayed_forward(struct delayed_forward *dfwd) { forward_htlc(dfwd->info, dfwd->htlc, dfwd->amount, dfwd->cltv_expiry, dfwd->onion_routing_packet, dfwd->path_key, &dfwd->expected); } static void handle_offer_htlc(struct info *info, const u8 *inmsg) { u8 *msg; u32 cltv_expiry; struct amount_msat amount; u8 onion_routing_packet[TOTAL_PACKET_SIZE(ROUTING_INFO_SIZE)]; enum channel_add_err e; const u8 *failwiremsg; const char *failstr; struct amount_sat htlc_fee; struct pubkey *blinding; static u64 htlc_id; struct fake_htlc *htlc = tal(info, struct fake_htlc); htlc->secrets = tal_arr(htlc, struct secret, 0); htlc->htlc_id = htlc_id; if (!fromwire_channeld_offer_htlc(tmpctx, inmsg, &amount, &cltv_expiry, &htlc->payment_hash, onion_routing_packet, &blinding)) master_badmsg(WIRE_CHANNELD_OFFER_HTLC, inmsg); e = channel_add_htlc(info->channel, LOCAL, htlc->htlc_id, amount, cltv_expiry, &htlc->payment_hash, onion_routing_packet, take(blinding), NULL, &htlc_fee, true); status_debug("Adding HTLC %"PRIu64" amount=%s cltv=%u gave %s", htlc->htlc_id, fmt_amount_msat(tmpctx, amount), cltv_expiry, channel_add_err_name(e)); switch (e) { case CHANNEL_ERR_ADD_OK: /* Tell lightningd. */ msg = towire_channeld_offer_htlc_reply(NULL, htlc_id, 0, ""); daemon_conn_send(info->dc, take(msg)); /* Tell it it's locked in */ update_commitment_tx_added(info, htlc_id); /* Handle it. */ forward_htlc(info, htlc, amount, cltv_expiry, onion_routing_packet, blinding, NULL); htlc_id++; return; case CHANNEL_ERR_INVALID_EXPIRY: failwiremsg = towire_incorrect_cltv_expiry(inmsg, cltv_expiry, NULL); failstr = tal_fmt(inmsg, "Invalid cltv_expiry %u", cltv_expiry); goto failed; case CHANNEL_ERR_DUPLICATE: case CHANNEL_ERR_DUPLICATE_ID_DIFFERENT: status_failed(STATUS_FAIL_MASTER_IO, "Duplicate HTLC %"PRIu64, htlc_id); case CHANNEL_ERR_MAX_HTLC_VALUE_EXCEEDED: failwiremsg = towire_required_node_feature_missing(inmsg); failstr = "Mini mode: maximum value exceeded"; goto failed; /* FIXME: Fuzz the boundaries a bit to avoid probing? */ case CHANNEL_ERR_CHANNEL_CAPACITY_EXCEEDED: failwiremsg = towire_temporary_channel_failure(inmsg, NULL); failstr = tal_fmt(inmsg, "Capacity exceeded - HTLC fee: %s", fmt_amount_sat(inmsg, htlc_fee)); goto failed; case CHANNEL_ERR_HTLC_BELOW_MINIMUM: failwiremsg = towire_amount_below_minimum(inmsg, amount, NULL); failstr = tal_fmt(inmsg, "HTLC too small (%s minimum)", fmt_amount_msat(tmpctx, info->channel->config[REMOTE].htlc_minimum)); goto failed; case CHANNEL_ERR_TOO_MANY_HTLCS: failwiremsg = towire_temporary_channel_failure(inmsg, NULL); failstr = "Too many HTLCs"; goto failed; case CHANNEL_ERR_DUST_FAILURE: /* BOLT-919 #2: * - upon an outgoing HTLC: * - if a HTLC's `amount_msat` is inferior the counterparty's... * - SHOULD NOT send this HTLC * - SHOULD fail this HTLC if it's forwarded */ failwiremsg = towire_temporary_channel_failure(inmsg, NULL); failstr = "HTLC too dusty, allowed dust limit reached"; goto failed; } /* Shouldn't return anything else! */ abort(); failed: /* lightningd appends update to this for us */ msg = towire_channeld_offer_htlc_reply(NULL, 0, failwiremsg, failstr); daemon_conn_send(info->dc, take(msg)); } static void handle_feerates(struct info *info, const u8 *inmsg) { u32 feerate, min, max, penalty; if (!fromwire_channeld_feerates(inmsg, &feerate, &min, &max, &penalty)) master_badmsg(WIRE_CHANNELD_FEERATES, inmsg); /* BOLT #2: * * The node _responsible_ for paying the Bitcoin fee: * - SHOULD send `update_fee` to ensure the current fee rate is * sufficient (by a significant margin) for timely processing of the * commitment transaction. */ if (info->channel->opener == LOCAL) { if (!channel_update_feerate(info->channel, feerate)) { abort(); } } } static void handle_blockheight(struct info *info, const u8 *inmsg) { if (!fromwire_channeld_blockheight(inmsg, &info->current_block_height)) master_badmsg(WIRE_CHANNELD_BLOCKHEIGHT, inmsg); } static void handle_funding_depth(struct info *info, const u8 *inmsg) { struct short_channel_id *short_channel_id; u32 depth; bool splicing; struct bitcoin_txid txid; struct pubkey somepoint; if (!fromwire_channeld_funding_depth(tmpctx, inmsg, &short_channel_id, &depth, &splicing, &txid)) master_badmsg(WIRE_CHANNELD_FUNDING_DEPTH, inmsg); /* Tell it the channel is ready ONCE, so it goes into CHANNELD_NORMAL. * We make up the remote_per_commit */ if (depth != 1) return; pubkey_from_hexstr("0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518", strlen("0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518"), &somepoint); /* Tell the peer we are ready: it will send a channel_update * then to make lightningd happy */ wire_sync_write(PEER_FD, take(towire_channel_ready(NULL, &info->channel->cid, &somepoint, NULL))); /* Ignore peer msgs except for channel_ready */ while (fromwire_peektype(wire_sync_read(tmpctx, PEER_FD)) != WIRE_CHANNEL_READY); daemon_conn_send(info->dc, take(towire_channeld_got_channel_ready(NULL, &somepoint, NULL))); } static void handle_dev_peer_shachain(struct info *info, const u8 *msg) { if (!fromwire_channeld_dev_peer_shachain(msg, &info->peer_shaseed)) master_badmsg(WIRE_CHANNELD_DEV_PEER_SHACHAIN, msg); } /* We don't care, but lightningd expects channeld to respond. */ static void handle_dev_memleak(struct info *info, const u8 *msg) { daemon_conn_send(info->dc, take(towire_channeld_dev_memleak_reply(NULL, false))); } static struct channel *handle_init(struct info *info, const u8 *init_msg) { struct feature_set *our_features; u32 *hsm_capabilities; struct channel_id channel_id; struct basepoints points[NUM_SIDES]; struct amount_sat funding_sats; struct amount_msat local_msat; struct pubkey funding_pubkey[NUM_SIDES]; struct channel_config conf[NUM_SIDES]; struct bitcoin_outpoint funding; enum side opener; struct existing_htlc **htlcs; bool reconnected; u32 final_index; struct ext_key final_ext_key; u8 *fwd_msg; u32 minimum_depth, lease_expiry; struct secret last_remote_per_commit_secret; struct penalty_base *pbases; bool reestablish_only; struct channel_type *channel_type; u32 feerate_min, feerate_max, feerate_penalty; struct pubkey remote_per_commit; struct pubkey old_remote_per_commit; u32 commit_msec; bool last_was_revoke; struct changed_htlc *last_sent_commit; u64 revocations_received; u8 channel_flags; bool channel_ready[NUM_SIDES]; u64 next_index[NUM_SIDES]; u64 htlc_id; struct bitcoin_signature their_commit_sig; struct short_channel_id short_channel_ids[NUM_SIDES]; bool send_shutdown; bool shutdown_sent[NUM_SIDES]; u8 *final_scriptpubkey; u8 *their_features; u8 *remote_upfront_shutdown_script; bool experimental_upgrade; u32 *dev_disable_commit; struct inflight **inflights; struct short_channel_id local_alias; struct channel *channel; const u8 *wscript; char *err_reason; struct wally_tx_output *direct_outputs[NUM_SIDES]; struct htlc_map *htlc_map; if (!fromwire_channeld_init(info, init_msg, &chainparams, &our_features, &hsm_capabilities, &channel_id, &funding, &funding_sats, &minimum_depth, &info->current_block_height, &info->blockheight_states, &lease_expiry, &conf[LOCAL], &conf[REMOTE], &info->fee_states, &feerate_min, &feerate_max, &feerate_penalty, &their_commit_sig, &funding_pubkey[REMOTE], &points[REMOTE], &remote_per_commit, &old_remote_per_commit, &opener, &local_msat, &points[LOCAL], &funding_pubkey[LOCAL], &commit_msec, &last_was_revoke, &last_sent_commit, &next_index[LOCAL], &next_index[REMOTE], &revocations_received, &htlc_id, &htlcs, &channel_ready[LOCAL], &channel_ready[REMOTE], &short_channel_ids[LOCAL], &reconnected, &send_shutdown, &shutdown_sent[REMOTE], &final_index, &final_ext_key, &final_scriptpubkey, &channel_flags, &fwd_msg, &last_remote_per_commit_secret, &their_features, &remote_upfront_shutdown_script, &channel_type, &dev_disable_commit, &pbases, &reestablish_only, &experimental_upgrade, &inflights, &local_alias)) abort(); status_debug("Parsed init..."); channel = new_full_channel(info, &channel_id, &funding, minimum_depth, info->blockheight_states, lease_expiry, funding_sats, local_msat, info->fee_states, &conf[LOCAL], &conf[REMOTE], &points[LOCAL], &points[REMOTE], &funding_pubkey[LOCAL], &funding_pubkey[REMOTE], take(channel_type), feature_offered(their_features, OPT_LARGE_CHANNELS), opener); /* We need a tx, so use this. It gets upset if channel->htlcs * is set, so temporarily clear that! */ htlc_map = channel->htlcs; channel->htlcs = NULL; info->commit_tx = initial_channel_tx(info, &wscript, channel, &remote_per_commit, LOCAL, direct_outputs, &err_reason); channel->htlcs = htlc_map; status_debug("Created channel"); daemon_conn_send(info->dc, take(towire_channeld_reestablished(NULL))); return channel; } static void master_gone(struct daemon_conn *dc UNUSED) { daemon_shutdown(); /* Can't tell master, it's gone. */ exit(2); } static struct io_plan *recv_req(struct io_conn *conn, const u8 *msg, struct info *info) { enum channeld_wire t = fromwire_peektype(msg); switch (t) { /* We ignore these */ case WIRE_CHANNELD_SEND_ERROR: case WIRE_CHANNELD_SENDING_COMMITSIG_REPLY: case WIRE_CHANNELD_GOT_REVOKE_REPLY: case WIRE_CHANNELD_GOT_COMMITSIG_REPLY: goto out; case WIRE_CHANNELD_INIT: info->channel = handle_init(info, msg); goto out; case WIRE_CHANNELD_BLOCKHEIGHT: handle_blockheight(info, msg); goto out; case WIRE_CHANNELD_OFFER_HTLC: handle_offer_htlc(info, msg); goto out; case WIRE_CHANNELD_FEERATES: handle_feerates(info, msg); goto out; case WIRE_CHANNELD_FUNDING_DEPTH: handle_funding_depth(info, msg); goto out; case WIRE_CHANNELD_DEV_MEMLEAK: handle_dev_memleak(info, msg); goto out; case WIRE_CHANNELD_DEV_PEER_SHACHAIN: handle_dev_peer_shachain(info, msg); goto out; /* No incoming HTLCs, these should not happen */ case WIRE_CHANNELD_FULFILL_HTLC: case WIRE_CHANNELD_FAIL_HTLC: /* Don't try closing this channel! */ case WIRE_CHANNELD_SEND_SHUTDOWN: /* Don't try to splice */ case WIRE_CHANNELD_SPLICE_INIT: case WIRE_CHANNELD_SPLICE_UPDATE: case WIRE_CHANNELD_SPLICE_SIGNED: case WIRE_CHANNELD_SPLICE_CONFIRMED_INIT: case WIRE_CHANNELD_SPLICE_CONFIRMED_SIGNED: case WIRE_CHANNELD_SPLICE_SENDING_SIGS: case WIRE_CHANNELD_SPLICE_CONFIRMED_UPDATE: case WIRE_CHANNELD_SPLICE_LOOKUP_TX: case WIRE_CHANNELD_SPLICE_LOOKUP_TX_RESULT: case WIRE_CHANNELD_SPLICE_FEERATE_ERROR: case WIRE_CHANNELD_SPLICE_FUNDING_ERROR: case WIRE_CHANNELD_SPLICE_ABORT: case WIRE_CHANNELD_STFU: case WIRE_CHANNELD_CONFIRMED_STFU: case WIRE_CHANNELD_ABORT: /* Not supported */ case WIRE_CHANNELD_DEV_REENABLE_COMMIT: case WIRE_CHANNELD_DEV_QUIESCE: /* We send these, not receive */ case WIRE_CHANNELD_OFFER_HTLC_REPLY: case WIRE_CHANNELD_SENDING_COMMITSIG: case WIRE_CHANNELD_GOT_COMMITSIG: case WIRE_CHANNELD_GOT_REVOKE: case WIRE_CHANNELD_GOT_CHANNEL_READY: case WIRE_CHANNELD_GOT_SPLICE_LOCKED: case WIRE_CHANNELD_GOT_ANNOUNCEMENT: case WIRE_CHANNELD_GOT_SHUTDOWN: case WIRE_CHANNELD_SHUTDOWN_COMPLETE: case WIRE_CHANNELD_DEV_REENABLE_COMMIT_REPLY: case WIRE_CHANNELD_FAIL_FALLEN_BEHIND: case WIRE_CHANNELD_DEV_MEMLEAK_REPLY: case WIRE_CHANNELD_SEND_ERROR_REPLY: case WIRE_CHANNELD_DEV_QUIESCE_REPLY: case WIRE_CHANNELD_UPGRADED: case WIRE_CHANNELD_ADD_INFLIGHT: case WIRE_CHANNELD_UPDATE_INFLIGHT: case WIRE_CHANNELD_GOT_INFLIGHT: case WIRE_CHANNELD_SPLICE_STATE_ERROR: case WIRE_CHANNELD_LOCAL_ANCHOR_INFO: case WIRE_CHANNELD_REESTABLISHED: break; } master_badmsg(-1, msg); out: /* Read the next message. */ return daemon_conn_read_next(conn, info->dc); } int main(int argc, char *argv[]) { struct info *info; setup_locale(); subdaemon_setup(argc, argv); info = tal(NULL, struct info); info->dc = daemon_conn_new(info, MASTER_FD, recv_req, NULL, info); tal_add_destructor(info->dc, master_gone); status_setup_async(info->dc); info->gossmap = gossmap_load(info, GOSSIP_STORE_FILENAME, NULL, NULL); if (!info->gossmap) status_failed(STATUS_FAIL_INTERNAL_ERROR, "Loading gossmap %s", strerror(errno)); info->node_map = tal(info, struct node_map); node_map_init(info->node_map); populate_node_map(info->gossmap, info->node_map); info->peer = make_peer_node(info); info->multi_payments = tal_arr(info, struct multi_payment *, 0); info->reservations = tal_arr(info, struct reservation *, 0); timers_init(&info->timers, time_mono()); info->commit_num = 1; info->fakesig.sighash_type = SIGHASH_ALL; memset(&info->fakesig.s, 0, sizeof(info->fakesig.s)); memset(&info->seed, 0, sizeof(info->seed)); if (getenv("CHANNELD_FAKENET_SEED")) info->seed.u.u64[0] = atol(getenv("CHANNELD_FAKENET_SEED")); status_debug("channeld_fakenet seed is %"PRIu64, info->seed.u.u64[0]); /* This loop never exits. io_loop() only returns if a timer has * expired, or io_break() is called, or all fds are closed. We don't * use io_break and closing the lightningd fd calls master_gone() * which exits. */ for (;;) { struct timer *expired = NULL; io_loop(&info->timers, &expired); timer_expired(expired); } }