diff --git a/common/sphinx.c b/common/sphinx.c index ffccf3c2d..3695be913 100644 --- a/common/sphinx.c +++ b/common/sphinx.c @@ -604,12 +604,12 @@ u8 *wrap_onionreply(const tal_t *ctx, return result; } -struct onionreply *unwrap_onionreply(const tal_t *ctx, - const struct secret *shared_secrets, - const int numhops, const u8 *reply) +u8 *unwrap_onionreply(const tal_t *ctx, + const struct secret *shared_secrets, + const int numhops, const u8 *reply, + int *origin_index) { - struct onionreply *oreply = tal(tmpctx, struct onionreply); - u8 *msg = tal_arr(oreply, u8, tal_count(reply)); + u8 *msg = tal_arr(tmpctx, u8, tal_count(reply)), *final; u8 key[KEY_LEN], hmac[HMAC_SIZE]; const u8 *cursor; size_t max; @@ -620,7 +620,7 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx, } memcpy(msg, reply, tal_count(reply)); - oreply->origin_index = -1; + *origin_index = -1; for (int i = 0; i < numhops; i++) { /* Since the encryption is just XORing with the cipher @@ -633,11 +633,11 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx, compute_hmac(hmac, msg + sizeof(hmac), tal_count(msg) - sizeof(hmac), key, KEY_LEN); if (memcmp(hmac, msg, sizeof(hmac)) == 0) { - oreply->origin_index = i; + *origin_index = i; break; } } - if (oreply->origin_index == -1) { + if (*origin_index == -1) { return NULL; } @@ -649,10 +649,8 @@ struct onionreply *unwrap_onionreply(const tal_t *ctx, return NULL; } - oreply->msg = tal_arr(oreply, u8, msglen); - fromwire(&cursor, &max, oreply->msg, msglen); - - tal_steal(ctx, oreply); - return oreply; + final = tal_arr(ctx, u8, msglen); + fromwire(&cursor, &max, final, msglen); + return final; } diff --git a/common/sphinx.h b/common/sphinx.h index 945dffe32..d20050f3a 100644 --- a/common/sphinx.h +++ b/common/sphinx.h @@ -156,12 +156,6 @@ enum onion_type parse_onionpacket(const u8 *src, const size_t srclen, struct onionpacket *dest); -struct onionreply { - /* Node index in the path that is replying */ - int origin_index; - u8 *msg; -}; - /** * create_onionreply - Format a failure message so we can return it * @@ -191,10 +185,12 @@ u8 *wrap_onionreply(const tal_t *ctx, const struct secret *shared_secret, * @shared_secrets: shared secrets from the forward path * @numhops: path length and number of shared_secrets provided * @reply: the incoming reply + * @origin_index: the index in the path where the reply came from (-1 if unknown) */ -struct onionreply *unwrap_onionreply(const tal_t *ctx, - const struct secret *shared_secrets, - const int numhops, const u8 *reply); +u8 *unwrap_onionreply(const tal_t *ctx, + const struct secret *shared_secrets, + const int numhops, const u8 *reply, + int *origin_index); /** * Create a new empty sphinx_path. diff --git a/common/test/run-sphinx.c b/common/test/run-sphinx.c index 5b4c4b1c4..38936d6dc 100644 --- a/common/test/run-sphinx.c +++ b/common/test/run-sphinx.c @@ -60,7 +60,8 @@ static struct secret secret_from_hex(const char *hex) * we match the test vectors and that we can also unwrap it. */ static void run_unit_tests(void) { - struct onionreply *oreply; + u8 *oreply; + int origin_index; u8 *reply; u8 *raw = tal_hexdata(tmpctx, "2002", 4); @@ -163,9 +164,10 @@ static void run_unit_tests(void) assert(memcmp(reply, intermediates[i], tal_count(reply)) == 0); } - oreply = unwrap_onionreply(tmpctx, ss, 5, reply); - printf("unwrapped %s\n", tal_hex(tmpctx, oreply->msg)); - assert(memcmp(raw, oreply->msg, tal_bytelen(raw)) == 0); + oreply = unwrap_onionreply(tmpctx, ss, 5, reply, &origin_index); + printf("unwrapped %s\n", tal_hex(tmpctx, oreply)); + assert(memeq(raw, tal_bytelen(raw), oreply, tal_bytelen(oreply))); + assert(origin_index == 4); } int main(int argc, char **argv) diff --git a/lightningd/pay.c b/lightningd/pay.c index 07ee300c0..823e429f7 100644 --- a/lightningd/pay.c +++ b/lightningd/pay.c @@ -373,23 +373,22 @@ static struct routing_failure* remote_routing_failure(const tal_t *ctx, struct lightningd *ld, const struct wallet_payment *payment, - const struct onionreply *failure, + const u8 *failuremsg, + int origin_index, struct log *log, int *pay_errcode) { - enum onion_type failcode = fromwire_peektype(failure->msg); + enum onion_type failcode = fromwire_peektype(failuremsg); struct routing_failure *routing_failure; const struct node_id *route_nodes; const struct node_id *erring_node; const struct short_channel_id *route_channels; const struct short_channel_id *erring_channel; - int origin_index; int dir; routing_failure = tal(ctx, struct routing_failure); route_nodes = payment->route_nodes; route_channels = payment->route_channels; - origin_index = failure->origin_index; assert(route_nodes == NULL || origin_index < tal_count(route_nodes)); @@ -448,7 +447,7 @@ remote_routing_failure(const tal_t *ctx, * following node. */ if (failcode & BADONION) { log_debug(log, "failcode %u from onionreply %s", - failcode, tal_hex(tmpctx, failure->msg)); + failcode, tal_hex(tmpctx, failuremsg)); erring_node = &route_nodes[origin_index + 1]; } else erring_node = &route_nodes[origin_index]; @@ -460,14 +459,14 @@ remote_routing_failure(const tal_t *ctx, erring_node, erring_channel, dir, - failure->msg); + failuremsg); subd_send_msg(ld->gossip, take(gossip_msg)); } routing_failure->erring_index = (unsigned int) (origin_index + 1); routing_failure->failcode = failcode; - routing_failure->msg = tal_dup_arr(routing_failure, u8, failure->msg, - tal_count(failure->msg), 0); + routing_failure->msg = tal_dup_arr(routing_failure, u8, failuremsg, + tal_count(failuremsg), 0); if (erring_node != NULL) routing_failure->erring_node = @@ -557,11 +556,12 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, failmsg = "reply from remote"; /* Try to parse reply. */ struct secret *path_secrets = payment->path_secrets; - struct onionreply *reply; + u8 *reply; + int origin_index; reply = unwrap_onionreply(tmpctx, path_secrets, tal_count(path_secrets), - hout->failuremsg); + hout->failuremsg, &origin_index); if (!reply) { log_info(hout->key.channel->log, "htlc %"PRIu64" failed with bad reply (%s)", @@ -571,18 +571,19 @@ void payment_failed(struct lightningd *ld, const struct htlc_out *hout, fail = NULL; pay_errcode = PAY_UNPARSEABLE_ONION; } else { - enum onion_type failcode = fromwire_peektype(reply->msg); + enum onion_type failcode = fromwire_peektype(reply); log_info(hout->key.channel->log, "htlc %"PRIu64" " "failed from %ith node " "with code 0x%04x (%s)", hout->key.id, - reply->origin_index, + origin_index, failcode, onion_type_name(failcode)); log_debug(hout->key.channel->log, "failmsg: %s", - tal_hex(tmpctx, reply->msg)); + tal_hex(tmpctx, reply)); fail = remote_routing_failure(tmpctx, ld, payment, reply, + origin_index, hout->key.channel->log, &pay_errcode); }