mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
lightningd: Add signinvoice
to sign a BOLT11 invoice.
Though there's already a `createinvoice` command, there are usecases where a user may want to sign an invoice that they don't yet have the preimage to. For example, they may have an htlc_accepted plugin that pays to obtain the preimage from someone else and returns a `{ "result": "resolve", ... }`. This RPC command addresses this usecase without overly complicating the semantics of the existing `createinvoice` command. Changelog-Added: JSON-RPC: `signinvoice` new command to sign BOLT11 invoices.
This commit is contained in:
parent
f0b8544eba
commit
1dbc29b8c0
@ -84,6 +84,7 @@ MANPAGES := doc/lightning-cli.1 \
|
||||
doc/lightning-sendpay.7 \
|
||||
doc/lightning-setchannel.7 \
|
||||
doc/lightning-sendcustommsg.7 \
|
||||
doc/lightning-signinvoice.7 \
|
||||
doc/lightning-signmessage.7 \
|
||||
doc/lightning-staticbackup.7 \
|
||||
doc/lightning-txprepare.7 \
|
||||
|
@ -116,6 +116,7 @@ Core Lightning Documentation
|
||||
lightning-sendpay <lightning-sendpay.7.md>
|
||||
lightning-sendpsbt <lightning-sendpsbt.7.md>
|
||||
lightning-setchannel <lightning-setchannel.7.md>
|
||||
lightning-signinvoice <lightning-signinvoice.7.md>
|
||||
lightning-signmessage <lightning-signmessage.7.md>
|
||||
lightning-signpsbt <lightning-signpsbt.7.md>
|
||||
lightning-sql <lightning-sql.7.md>
|
||||
|
51
doc/lightning-signinvoice.7.md
Normal file
51
doc/lightning-signinvoice.7.md
Normal file
@ -0,0 +1,51 @@
|
||||
lightning-signinvoice -- Low-level invoice signing
|
||||
=====================================================
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
**signinvoice** *invstring*
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
The **signinvoice** RPC command signs an invoice. Unlike
|
||||
**createinvoice** it does not save the invoice into the database and
|
||||
thus does not require the preimage.
|
||||
|
||||
The *invstring* parameter is of bolt11 form, but the final signature
|
||||
is ignored. Minimal sanity checks are done.
|
||||
|
||||
RETURN VALUE
|
||||
------------
|
||||
|
||||
[comment]: # (GENERATE-FROM-SCHEMA-START)
|
||||
On success, an object is returned, containing:
|
||||
|
||||
- **bolt11** (string): the bolt11 string
|
||||
|
||||
[comment]: # (GENERATE-FROM-SCHEMA-END)
|
||||
|
||||
On failure, an error is returned.
|
||||
|
||||
The following error codes may occur:
|
||||
- -1: Catchall nonspecific error.
|
||||
|
||||
AUTHOR
|
||||
------
|
||||
|
||||
Carl Dong <<contact@carldong.me>> is mainly responsible.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
lightning-createinvoice(7), lightning-invoice(7), lightning-listinvoices(7),
|
||||
lightning-delinvoice(7), lightning-getroute(7), lightning-sendpay(7),
|
||||
lightning-offer(7).
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
|
||||
Main web site: <https://github.com/ElementsProject/lightning>
|
||||
|
||||
[comment]: # ( SHA256STAMP:9348784bd3daaed1cd35b29b2e5c91ea17bc8e11bf5bb6e1de9a098241cb74d6)
|
15
doc/schemas/signinvoice.request.json
Normal file
15
doc/schemas/signinvoice.request.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"added": "v23.02",
|
||||
"required": [
|
||||
"invstring"
|
||||
],
|
||||
"properties": {
|
||||
"invstring": {
|
||||
"type": "string",
|
||||
"description": ""
|
||||
}
|
||||
}
|
||||
}
|
14
doc/schemas/signinvoice.schema.json
Normal file
14
doc/schemas/signinvoice.schema.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"bolt11"
|
||||
],
|
||||
"properties": {
|
||||
"bolt11": {
|
||||
"type": "string",
|
||||
"description": "the bolt11 string"
|
||||
}
|
||||
}
|
||||
}
|
@ -1897,3 +1897,57 @@ static const struct json_command preapprovekeysend_command = {
|
||||
"Ask the HSM to preapprove a keysend payment."
|
||||
};
|
||||
AUTODATA(json_command, &preapprovekeysend_command);
|
||||
|
||||
static struct command_result *json_signinvoice(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
const char *invstring;
|
||||
struct json_stream *response;
|
||||
struct bolt11 *b11;
|
||||
struct sha256 hash;
|
||||
const u5 *sig;
|
||||
bool have_n;
|
||||
char *fail;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_req("invstring", param_string, &invstring),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
b11 = bolt11_decode_nosig(cmd, invstring, cmd->ld->our_features,
|
||||
NULL, chainparams, &hash, &sig, &have_n,
|
||||
&fail);
|
||||
|
||||
if (!b11)
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Unparsable invoice '%s': %s",
|
||||
invstring, fail);
|
||||
|
||||
/* This adds the signature */
|
||||
char *b11enc = bolt11_encode(cmd, b11, have_n,
|
||||
hsm_sign_b11, cmd->ld);
|
||||
|
||||
/* BOLT #11:
|
||||
* A writer:
|
||||
*...
|
||||
* - MUST include either exactly one `d` or exactly one `h` field.
|
||||
*/
|
||||
if (!b11->description && !b11->description_hash)
|
||||
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
|
||||
"Missing description in invoice");
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
json_add_invstring(response, b11enc);
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command signinvoice_command = {
|
||||
"signinvoice",
|
||||
"payment",
|
||||
json_signinvoice,
|
||||
"Lowlevel command to sign invoice {invstring}."
|
||||
};
|
||||
|
||||
AUTODATA(json_command, &signinvoice_command);
|
||||
|
@ -533,6 +533,19 @@ def test_waitanyinvoice(node_factory, executor):
|
||||
l2.rpc.waitanyinvoice('non-number')
|
||||
|
||||
|
||||
def test_signinvoice(node_factory, executor):
|
||||
# Setup
|
||||
l1, l2 = node_factory.line_graph(2)
|
||||
|
||||
# Create an invoice for l1
|
||||
inv1 = l1.rpc.invoice(1000, 'inv1', 'inv1')['bolt11']
|
||||
assert l1.rpc.decodepay(inv1)['payee'] == l1.info['id']
|
||||
|
||||
# Have l2 re-sign the invoice
|
||||
inv2 = l2.rpc.signinvoice(inv1)['bolt11']
|
||||
assert l1.rpc.decodepay(inv2)['payee'] == l2.info['id']
|
||||
|
||||
|
||||
def test_waitanyinvoice_reversed(node_factory, executor):
|
||||
"""Test waiting for invoices, where they are paid in reverse order
|
||||
to when they are created.
|
||||
|
Loading…
Reference in New Issue
Block a user