#include "log.h" #include "onion.h" #include "peer.h" #include "protobuf_convert.h" #include "routing.h" #include /* FIXME: http://www.cypherpunks.ca/~iang/pubs/Sphinx_Oakland09.pdf */ /* Frees r */ static const u8 *to_onion(const tal_t *ctx, const Route *r) { u8 *onion = tal_arr(ctx, u8, route__get_packed_size(r)); route__pack(r, onion); tal_free(r); return onion; } /* Create an onion for this path. */ const u8 *onion_create(const tal_t *ctx, secp256k1_context *secpctx, const struct pubkey *ids, const u64 *amounts, size_t num_hops) { Route *r = tal(ctx, Route); size_t i; route__init(r); r->n_steps = num_hops + 1; r->steps = tal_arr(r, RouteStep *, r->n_steps); for (i = 0; i < num_hops; i++) { r->steps[i] = tal(r, RouteStep); route_step__init(r->steps[i]); r->steps[i]->next_case = ROUTE_STEP__NEXT_BITCOIN; r->steps[i]->bitcoin = pubkey_to_proto(r, secpctx, &ids[i]); r->steps[i]->amount = amounts[i]; } /* Now the stop marker. */ r->steps[i] = tal(r, RouteStep); route_step__init(r->steps[i]); r->steps[i]->next_case = ROUTE_STEP__NEXT_END; r->steps[i]->end = true; r->steps[i]->amount = 0; return to_onion(ctx, r); } /* Decode next step in the route, and fill out the onion to send onwards. */ RouteStep *onion_unwrap(struct peer *peer, const void *data, size_t len, const u8 **next) { struct ProtobufCAllocator *prototal = make_prototal(peer); Route *r; RouteStep *step; r = route__unpack(prototal, len, data); if (!r || r->n_steps == 0) { log_unusual(peer->log, "Failed to unwrap onion"); tal_free(prototal); return NULL; } /* Remove first step. */ step = r->steps[0]; /* Make sure that step owns the rest */ steal_from_prototal(peer, prototal, step); /* Re-pack with remaining steps. */ r->n_steps--; memmove(r->steps, r->steps + 1, sizeof(*r->steps) * r->n_steps); if (!r->n_steps) { *next = NULL; tal_free(r); } else *next = to_onion(peer, r); return step; }