Browse Source
And rename JSON's accept-payment command to invoice. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>ppa-0.6.1
Rusty Russell
8 years ago
13 changed files with 209 additions and 167 deletions
@ -0,0 +1,127 @@ |
|||
#include "db.h" |
|||
#include "invoice.h" |
|||
#include "jsonrpc.h" |
|||
#include "lightningd.h" |
|||
#include <ccan/str/hex/hex.h> |
|||
#include <ccan/structeq/structeq.h> |
|||
#include <ccan/tal/str/str.h> |
|||
#include <sodium/randombytes.h> |
|||
|
|||
struct invoice *find_invoice(struct lightningd_state *dstate, |
|||
const struct sha256 *rhash) |
|||
{ |
|||
struct invoice *i; |
|||
|
|||
list_for_each(&dstate->invoices, i, list) { |
|||
if (structeq(rhash, &i->rhash)) |
|||
return i; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
static struct invoice *find_invoice_by_label(struct lightningd_state *dstate, |
|||
const char *label) |
|||
{ |
|||
struct invoice *i; |
|||
|
|||
list_for_each(&dstate->invoices, i, list) { |
|||
if (streq(i->label, label)) |
|||
return i; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void invoice_add(struct lightningd_state *dstate, |
|||
const struct rval *r, |
|||
u64 msatoshis, |
|||
const char *label, |
|||
bool complete) |
|||
{ |
|||
struct invoice *invoice = tal(dstate, struct invoice); |
|||
|
|||
invoice->msatoshis = msatoshis; |
|||
invoice->r = *r; |
|||
invoice->complete = complete; |
|||
invoice->label = tal_strdup(invoice, label); |
|||
sha256(&invoice->rhash, invoice->r.r, sizeof(invoice->r.r)); |
|||
list_add(&dstate->invoices, &invoice->list); |
|||
} |
|||
|
|||
static void json_invoice(struct command *cmd, |
|||
const char *buffer, const jsmntok_t *params) |
|||
{ |
|||
struct invoice *invoice; |
|||
jsmntok_t *msatoshis, *r, *label; |
|||
struct json_result *response = new_json_result(cmd); |
|||
|
|||
if (!json_get_params(buffer, params, |
|||
"amount", &msatoshis, |
|||
"label", &label, |
|||
"?r", &r, |
|||
NULL)) { |
|||
command_fail(cmd, "Need {amount} and {label}"); |
|||
return; |
|||
} |
|||
|
|||
invoice = tal(cmd, struct invoice); |
|||
if (r) { |
|||
if (!hex_decode(buffer + r->start, r->end - r->start, |
|||
invoice->r.r, sizeof(invoice->r.r))) { |
|||
command_fail(cmd, "Invalid hex r '%.*s'", |
|||
r->end - r->start, buffer + r->start); |
|||
return; |
|||
} |
|||
} else |
|||
randombytes_buf(invoice->r.r, sizeof(invoice->r.r)); |
|||
|
|||
sha256(&invoice->rhash, invoice->r.r, sizeof(invoice->r.r)); |
|||
if (find_invoice(cmd->dstate, &invoice->rhash)) { |
|||
command_fail(cmd, "Duplicate r value '%.*s'", |
|||
r->end - r->start, buffer + r->start); |
|||
return; |
|||
} |
|||
|
|||
if (!json_tok_u64(buffer, msatoshis, &invoice->msatoshis) |
|||
|| invoice->msatoshis == 0) { |
|||
command_fail(cmd, "'%.*s' is not a valid positive number", |
|||
msatoshis->end - msatoshis->start, |
|||
buffer + msatoshis->start); |
|||
return; |
|||
} |
|||
|
|||
invoice->label = tal_strndup(invoice, buffer + label->start, |
|||
label->end - label->start); |
|||
if (find_invoice_by_label(cmd->dstate, invoice->label)) { |
|||
command_fail(cmd, "Duplicate label '%s'", invoice->label); |
|||
return; |
|||
} |
|||
if (strlen(invoice->label) > INVOICE_MAX_LABEL_LEN) { |
|||
command_fail(cmd, "label '%s' over %u bytes", invoice->label, |
|||
INVOICE_MAX_LABEL_LEN); |
|||
return; |
|||
} |
|||
invoice->complete = false; |
|||
|
|||
if (!db_new_invoice(cmd->dstate, invoice->msatoshis, invoice->label, |
|||
&invoice->r)) { |
|||
command_fail(cmd, "database error"); |
|||
return; |
|||
} |
|||
/* OK, connect it to main state, respond with hash */ |
|||
tal_steal(cmd->dstate, invoice); |
|||
list_add(&cmd->dstate->invoices, &invoice->list); |
|||
|
|||
json_object_start(response, NULL); |
|||
json_add_hex(response, "rhash", |
|||
&invoice->rhash, sizeof(invoice->rhash)); |
|||
json_object_end(response); |
|||
|
|||
command_success(cmd, response); |
|||
} |
|||
|
|||
const struct json_command invoice_command = { |
|||
"invoice", |
|||
json_invoice, |
|||
"Create invoice for {msatoshis} with {label} (with a set {r}, otherwise generate one)", |
|||
"Returns the {rhash} on success. " |
|||
}; |
@ -0,0 +1,29 @@ |
|||
#ifndef LIGHTNING_DAEMON_INVOICE_H |
|||
#define LIGHTNING_DAEMON_INVOICE_H |
|||
#include "config.h" |
|||
#include "peer.h" |
|||
|
|||
struct lightningd_state; |
|||
|
|||
struct invoice { |
|||
struct list_node list; |
|||
const char *label; |
|||
u64 msatoshis; |
|||
struct rval r; |
|||
struct sha256 rhash; |
|||
bool complete; |
|||
}; |
|||
|
|||
#define INVOICE_MAX_LABEL_LEN 128 |
|||
|
|||
/* From database */ |
|||
void invoice_add(struct lightningd_state *dstate, |
|||
const struct rval *r, |
|||
u64 msatoshis, |
|||
const char *label, |
|||
bool complete); |
|||
|
|||
struct invoice *find_invoice(struct lightningd_state *dstate, |
|||
const struct sha256 *rhash); |
|||
|
|||
#endif /* LIGHTNING_DAEMON_INVOICE_H */ |
@ -1,98 +0,0 @@ |
|||
#include "db.h" |
|||
#include "jsonrpc.h" |
|||
#include "lightningd.h" |
|||
#include "payment.h" |
|||
#include <ccan/str/hex/hex.h> |
|||
#include <ccan/structeq/structeq.h> |
|||
#include <sodium/randombytes.h> |
|||
|
|||
struct payment *find_payment(struct lightningd_state *dstate, |
|||
const struct sha256 *rhash) |
|||
{ |
|||
struct payment *i; |
|||
|
|||
list_for_each(&dstate->payments, i, list) { |
|||
if (structeq(rhash, &i->rhash)) |
|||
return i; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
void payment_add(struct lightningd_state *dstate, |
|||
const struct rval *r, |
|||
u64 msatoshis, |
|||
bool complete) |
|||
{ |
|||
struct payment *payment = tal(dstate, struct payment); |
|||
|
|||
payment->msatoshis = msatoshis; |
|||
payment->r = *r; |
|||
payment->complete = complete; |
|||
sha256(&payment->rhash, payment->r.r, sizeof(payment->r.r)); |
|||
list_add(&dstate->payments, &payment->list); |
|||
} |
|||
|
|||
static void json_accept_payment(struct command *cmd, |
|||
const char *buffer, const jsmntok_t *params) |
|||
{ |
|||
struct payment *payment; |
|||
jsmntok_t *msatoshis, *r; |
|||
struct json_result *response = new_json_result(cmd); |
|||
|
|||
if (!json_get_params(buffer, params, |
|||
"amount", &msatoshis, |
|||
"?r", &r, |
|||
NULL)) { |
|||
command_fail(cmd, "Need {amount}"); |
|||
return; |
|||
} |
|||
|
|||
payment = tal(cmd, struct payment); |
|||
if (r) { |
|||
if (!hex_decode(buffer + r->start, r->end - r->start, |
|||
payment->r.r, sizeof(payment->r.r))) { |
|||
command_fail(cmd, "Invalid hex r '%.*s'", |
|||
r->end - r->start, buffer + r->start); |
|||
return; |
|||
} |
|||
} else |
|||
randombytes_buf(payment->r.r, sizeof(payment->r.r)); |
|||
|
|||
sha256(&payment->rhash, payment->r.r, sizeof(payment->r.r)); |
|||
if (find_payment(cmd->dstate, &payment->rhash)) { |
|||
command_fail(cmd, "Duplicate r value '%.*s'", |
|||
r->end - r->start, buffer + r->start); |
|||
return; |
|||
} |
|||
|
|||
if (!json_tok_u64(buffer, msatoshis, &payment->msatoshis) |
|||
|| payment->msatoshis == 0) { |
|||
command_fail(cmd, "'%.*s' is not a valid positive number", |
|||
msatoshis->end - msatoshis->start, |
|||
buffer + msatoshis->start); |
|||
return; |
|||
} |
|||
payment->complete = false; |
|||
|
|||
if (!db_new_payment(cmd->dstate, payment->msatoshis, &payment->r)) { |
|||
command_fail(cmd, "database error"); |
|||
return; |
|||
} |
|||
/* OK, connect it to main state, respond with hash */ |
|||
tal_steal(cmd->dstate, payment); |
|||
list_add(&cmd->dstate->payments, &payment->list); |
|||
|
|||
json_object_start(response, NULL); |
|||
json_add_hex(response, "rhash", |
|||
&payment->rhash, sizeof(payment->rhash)); |
|||
json_object_end(response); |
|||
|
|||
command_success(cmd, response); |
|||
} |
|||
|
|||
const struct json_command accept_payment_command = { |
|||
"accept-payment", |
|||
json_accept_payment, |
|||
"Accept payment for {amount} (with a set {r}, otherwise generate one)", |
|||
"Returns the {rhash} on success. " |
|||
}; |
@ -1,25 +0,0 @@ |
|||
#ifndef LIGHTNING_DAEMON_PAYMENT_H |
|||
#define LIGHTNING_DAEMON_PAYMENT_H |
|||
#include "config.h" |
|||
#include "peer.h" |
|||
|
|||
struct lightningd_state; |
|||
|
|||
struct payment { |
|||
struct list_node list; |
|||
u64 msatoshis; |
|||
struct rval r; |
|||
struct sha256 rhash; |
|||
bool complete; |
|||
}; |
|||
|
|||
/* From database */ |
|||
void payment_add(struct lightningd_state *dstate, |
|||
const struct rval *r, |
|||
u64 msatoshis, |
|||
bool complete); |
|||
|
|||
struct payment *find_payment(struct lightningd_state *dstate, |
|||
const struct sha256 *rhash); |
|||
|
|||
#endif /* LIGHTNING_DAEMON_PAYMENT_H */ |
Loading…
Reference in new issue