From 4902907628f38cdfa66e5e10b20e23b91f6e4ef2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 30 Jun 2016 09:08:05 +0930 Subject: [PATCH] daemon: onion routing API No meat; it doesn't encrypt as yet, but the API to wrap/unwrap routes is here. Signed-off-by: Rusty Russell --- daemon/Makefile | 2 + daemon/onion.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++ daemon/onion.h | 18 +++++++++ 3 files changed, 122 insertions(+) create mode 100644 daemon/onion.c create mode 100644 daemon/onion.h diff --git a/daemon/Makefile b/daemon/Makefile index 80e6226fe..eee698adc 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -22,6 +22,7 @@ DAEMON_SRC := \ daemon/jsonrpc.c \ daemon/lightningd.c \ daemon/netaddr.c \ + daemon/onion.c \ daemon/opt_time.c \ daemon/peer.c \ daemon/packets.c \ @@ -54,6 +55,7 @@ DAEMON_HEADERS := \ daemon/lightningd.h \ daemon/log.h \ daemon/netaddr.h \ + daemon/onion.h \ daemon/opt_time.h \ daemon/payment.h \ daemon/peer.h \ diff --git a/daemon/onion.c b/daemon/onion.c new file mode 100644 index 000000000..3cb71afe9 --- /dev/null +++ b/daemon/onion.c @@ -0,0 +1,102 @@ +#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 sending msatoshi_with_fees down path. */ +const u8 *onion_create(const tal_t *ctx, + struct node_connection **path, + u64 msatoshi, s64 fees) +{ + Route *r = tal(ctx, Route); + int i; + u64 amount = msatoshi; + + route__init(r); + r->n_steps = tal_count(path) + 1; + r->steps = tal_arr(r, RouteStep *, r->n_steps); + + /* Create backwards, so we can get fees correct. */ + for (i = tal_count(path) - 1; i >= 0; 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, &path[i]->dst->id); + r->steps[i]->amount = amount; + amount += connection_fee(path[i], amount); + } + + /* Now the stop marker. */ + i = tal_count(path); + 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; + + assert(amount == msatoshi + fees); + + return to_onion(ctx, r); +} + +static void *proto_tal_alloc(void *allocator_data, size_t size) +{ + return tal_arr(allocator_data, char, size); +} + +static void proto_tal_free(void *allocator_data, void *pointer) +{ + tal_free(pointer); +} + +/* 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; + Route *r; + RouteStep *step; + + /* De-protobuf it. */ + prototal.alloc = proto_tal_alloc; + prototal.free = proto_tal_free; + prototal.allocator_data = tal(peer, char); + + r = route__unpack(&prototal, len, data); + if (!r || r->n_steps == 0) { + log_unusual(peer->log, "Failed to unwrap onion"); + tal_free(prototal.allocator_data); + return NULL; + } + + /* Remove first step. */ + step = r->steps[0]; + /* Make sure that step owns the rest */ + tal_steal(peer, step); + tal_steal(step, prototal.allocator_data); + + /* 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; +} diff --git a/daemon/onion.h b/daemon/onion.h new file mode 100644 index 000000000..1d8be70ca --- /dev/null +++ b/daemon/onion.h @@ -0,0 +1,18 @@ +#ifndef LIGHTNING_DAEMON_ONION_H +#define LIGHTNING_DAEMON_ONION_H +#include "config.h" +#include "lightning.pb-c.h" +#include + +struct peer; +struct node_connection; + +/* 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); + +/* Create an onion for sending msatoshi down path, paying fees. */ +const u8 *onion_create(const tal_t *ctx, + struct node_connection **path, + u64 msatoshi, s64 fees); +#endif /* LIGHTNING_DAEMON_ONION_H */