Skip to content

Commit 443621c

Browse files
gudnufdaywalker90
authored andcommitted
add clnrest object to plugin manifest
1 parent e5ec688 commit 443621c

File tree

14 files changed

+555
-257
lines changed

14 files changed

+555
-257
lines changed

.msggen.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1871,10 +1871,17 @@
18711871
},
18721872
"HelpHelp": {
18731873
"Help.help[].category": 2,
1874+
"Help.help[].clnrest": 5,
18741875
"Help.help[].command": 1,
18751876
"Help.help[].description": 3,
18761877
"Help.help[].verbose": 4
18771878
},
1879+
"HelpHelpClnrest": {
1880+
"Help.help[].clnrest.content_type": 3,
1881+
"Help.help[].clnrest.method": 2,
1882+
"Help.help[].clnrest.path": 1,
1883+
"Help.help[].clnrest.rune": 4
1884+
},
18781885
"HelpRequest": {
18791886
"Help.command": 1
18801887
},
@@ -7676,6 +7683,26 @@
76767683
"added": "pre-v0.10.1",
76777684
"deprecated": null
76787685
},
7686+
"Help.help[].clnrest": {
7687+
"added": "v24.08",
7688+
"deprecated": null
7689+
},
7690+
"Help.help[].clnrest.content_type": {
7691+
"added": "v24.08",
7692+
"deprecated": null
7693+
},
7694+
"Help.help[].clnrest.method": {
7695+
"added": "v24.08",
7696+
"deprecated": null
7697+
},
7698+
"Help.help[].clnrest.path": {
7699+
"added": "v24.08",
7700+
"deprecated": null
7701+
},
7702+
"Help.help[].clnrest.rune": {
7703+
"added": "v24.08",
7704+
"deprecated": null
7705+
},
76797706
"Help.help[].command": {
76807707
"added": "pre-v0.10.1",
76817708
"deprecated": null

cln-grpc/proto/node.proto

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-grpc/src/convert.rs

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cln-rpc/src/model.rs

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/msggen/msggen/schema.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15298,6 +15298,34 @@
1529815298
"description": [
1529915299
"The command."
1530015300
]
15301+
},
15302+
"clnrest": {
15303+
"type": "object",
15304+
"additionalProperties": false,
15305+
"required": [],
15306+
"added": "v24.08",
15307+
"properties": {
15308+
"path": {
15309+
"type": "string",
15310+
"description": "the path to the HTTP endpoint for this command",
15311+
"added": "v24.08"
15312+
},
15313+
"method": {
15314+
"type": "string",
15315+
"description": "the HTTP method for this command",
15316+
"added": "v24.08"
15317+
},
15318+
"content_type": {
15319+
"type": "string",
15320+
"description": "http content-type that clnrest should return",
15321+
"added": "v24.08"
15322+
},
15323+
"rune": {
15324+
"type": "boolean",
15325+
"description": "whether or not this command requires a rune for authentication",
15326+
"added": "v24.08"
15327+
}
15328+
}
1530115329
}
1530215330
}
1530315331
}

contrib/pyln-client/pyln/client/plugin.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from dataclasses import dataclass
1313
from enum import Enum
1414
from threading import RLock
15-
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
15+
from typing import Any, Callable, Dict, List, Optional, Tuple, Union, TypedDict
1616

1717
from .lightning import LightningRpc, Millisatoshi
1818

@@ -38,6 +38,13 @@ class RequestState(Enum):
3838
FAILED = 'failed'
3939

4040

41+
class CLNRestData(TypedDict):
42+
path: str
43+
method: str
44+
content_type: str
45+
rune: bool
46+
47+
4148
class Method(object):
4249
"""Description of methods that are registered with the plugin.
4350
@@ -49,7 +56,8 @@ class Method(object):
4956
def __init__(self, name: str, func: Callable[..., JSONType],
5057
mtype: MethodType = MethodType.RPCMETHOD,
5158
deprecated: Union[bool, List[str]] = None,
52-
description: str = None):
59+
description: str = None,
60+
clnrest_data: CLNRestData = None):
5361
self.name = name
5462
self.func = func
5563
self.mtype = mtype
@@ -58,6 +66,7 @@ def __init__(self, name: str, func: Callable[..., JSONType],
5866
self.description = description
5967
self.before: List[str] = []
6068
self.after: List[str] = []
69+
self.clnrest = clnrest_data
6170

6271
def get_usage(self):
6372
# Handles out-of-order use of parameters like:
@@ -357,7 +366,8 @@ def convert_featurebits(
357366
def add_method(self, name: str, func: Callable[..., Any],
358367
background: bool = False,
359368
deprecated: Optional[Union[bool, List[str]]] = None,
360-
description: str = None) -> None:
369+
description: str = None,
370+
clnrest_data: CLNRestData = None) -> None:
361371
"""Add a plugin method to the dispatch table.
362372
363373
The function will be expected at call time (see `_dispatch`)
@@ -394,7 +404,7 @@ def add_method(self, name: str, func: Callable[..., Any],
394404
)
395405

396406
# Register the function with the name
397-
method = Method(name, func, MethodType.RPCMETHOD, deprecated, description)
407+
method = Method(name, func, MethodType.RPCMETHOD, deprecated, description, clnrest_data)
398408
method.background = background
399409
self.methods[name] = method
400410

@@ -511,7 +521,8 @@ def get_option(self, name: str) -> Optional[Any]:
511521
def async_method(self, method_name: str, category: Optional[str] = None,
512522
desc: Optional[str] = None,
513523
long_desc: Optional[str] = None,
514-
deprecated: Optional[Union[bool, List[str]]] = None) -> NoneDecoratorType:
524+
deprecated: Optional[Union[bool, List[str]]] = None,
525+
clnrest_data: CLNRestData = None) -> NoneDecoratorType:
515526
"""Decorator to add an async plugin method to the dispatch table.
516527
517528
Internally uses add_method.
@@ -520,15 +531,16 @@ def decorator(f: Callable[..., None]) -> Callable[..., None]:
520531
for attr, attr_name in [(category, "Category"), (desc, "Description"), (long_desc, "Long description")]:
521532
if attr is not None:
522533
self.log("{} is deprecated but defined in method {}; it will be ignored by Core Lightning".format(attr_name, method_name), level="warn")
523-
self.add_method(method_name, f, background=True, deprecated=deprecated)
534+
self.add_method(method_name, f, background=True, deprecated=deprecated, clnrest_data=clnrest_data)
524535
return f
525536
return decorator
526537

527538
def method(self, method_name: str, category: Optional[str] = None,
528539
desc: Optional[str] = None,
529540
long_desc: Optional[str] = None,
530541
deprecated: Union[bool, List[str]] = None,
531-
description: str = None) -> JsonDecoratorType:
542+
description: str = None,
543+
clnrest_data: Optional[CLNRestData] = None) -> JsonDecoratorType:
532544
"""Decorator to add a plugin method to the dispatch table.
533545
534546
Internally uses add_method.
@@ -537,7 +549,7 @@ def decorator(f: Callable[..., JSONType]) -> Callable[..., JSONType]:
537549
for attr, attr_name in [(category, "Category"), (desc, "Description"), (long_desc, "Long description")]:
538550
if attr is not None:
539551
self.log("{} is deprecated but defined in method {}; it will be ignored by Core Lightning".format(attr_name, method_name), level="warn")
540-
self.add_method(method_name, f, background=False, deprecated=deprecated, description=f.__doc__)
552+
self.add_method(method_name, f, background=False, deprecated=deprecated, description=f.__doc__, clnrest_data=clnrest_data)
541553
return f
542554
return decorator
543555

@@ -951,6 +963,9 @@ def _getmanifest(self, **kwargs) -> JSONType:
951963
'usage': method.get_usage(),
952964
'description': description,
953965
})
966+
if method.clnrest:
967+
m = methods[len(methods) - 1]
968+
m["clnrest"] = method.clnrest
954969

955970
manifest = {
956971
'options': list(d.json() for d in self.options.values()),

contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py

Lines changed: 236 additions & 234 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contrib/pyln-testing/pyln/testing/grpc2py.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2656,6 +2656,15 @@ def stop2py(m):
26562656
})
26572657

26582658

2659+
def help_help_clnrest2py(m):
2660+
return remove_default({
2661+
"content_type": m.content_type, # PrimitiveField in generate_composite
2662+
"method": m.method, # PrimitiveField in generate_composite
2663+
"path": m.path, # PrimitiveField in generate_composite
2664+
"rune": m.rune, # PrimitiveField in generate_composite
2665+
})
2666+
2667+
26592668
def help_help2py(m):
26602669
return remove_default({
26612670
"command": m.command, # PrimitiveField in generate_composite

doc/schemas/help.json

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,34 @@
4040
"description": [
4141
"The command."
4242
]
43+
},
44+
"clnrest": {
45+
"type": "object",
46+
"additionalProperties": false,
47+
"required": [],
48+
"added": "v24.08",
49+
"properties": {
50+
"path": {
51+
"type": "string",
52+
"description": "the path to the HTTP endpoint for this command",
53+
"added": "v24.08"
54+
},
55+
"method": {
56+
"type": "string",
57+
"description": "the HTTP method for this command",
58+
"added": "v24.08"
59+
},
60+
"content_type": {
61+
"type": "string",
62+
"description": "http content-type that clnrest should return",
63+
"added": "v24.08"
64+
},
65+
"rune": {
66+
"type": "boolean",
67+
"description": "whether or not this command requires a rune for authentication",
68+
"added": "v24.08"
69+
}
70+
}
4371
}
4472
}
4573
}

lightningd/jsonrpc.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,23 @@ static void json_add_help_command(struct command *cmd,
462462
json_command->name));
463463
json_object_start(response, NULL);
464464
json_add_string(response, "command", usage);
465+
466+
if (json_command->clnrest) {
467+
json_object_start(response, "clnrest");
468+
if (json_command->clnrest->method) {
469+
json_add_string(response, "method", json_command->clnrest->method);
470+
}
471+
if (json_command->clnrest->path) {
472+
json_add_string(response, "path", json_command->clnrest->path);
473+
}
474+
if (json_command->clnrest->content_type) {
475+
json_add_string(response, "content_type", json_command->clnrest->content_type);
476+
}
477+
if (json_command->clnrest->rune) {
478+
json_add_bool(response, "rune", *json_command->clnrest->rune);
479+
}
480+
json_object_end(response);
481+
}
465482
json_object_end(response);
466483
}
467484

@@ -1360,14 +1377,39 @@ static void destroy_json_command(struct json_command *command, struct jsonrpc *r
13601377
abort();
13611378
}
13621379

1363-
static bool command_add(struct jsonrpc *rpc, struct json_command *command)
1380+
static bool command_add(struct jsonrpc *rpc, struct json_command *command,
1381+
char **collision_name)
13641382
{
13651383
size_t count = tal_count(rpc->commands);
13661384

13671385
/* Check that we don't clobber a method */
1368-
for (size_t i = 0; i < count; i++)
1369-
if (streq(rpc->commands[i]->name, command->name))
1386+
for (size_t i = 0; i < count; i++) {
1387+
1388+
if (streq(rpc->commands[i]->name, command->name)) {
1389+
if (collision_name) {
1390+
*collision_name =
1391+
tal_strdup(tmpctx, rpc->commands[i]->name);
1392+
}
13701393
return false;
1394+
}
1395+
1396+
/* Check for clnrest conflict */
1397+
if (command->clnrest && rpc->commands[i]->clnrest) {
1398+
bool method_match =
1399+
streq(command->clnrest->method,
1400+
rpc->commands[i]->clnrest->method);
1401+
bool path_match =
1402+
streq(command->clnrest->path,
1403+
rpc->commands[i]->clnrest->path);
1404+
if (method_match && path_match) {
1405+
if (collision_name) {
1406+
*collision_name = tal_strdup(
1407+
tmpctx, rpc->commands[i]->name);
1408+
}
1409+
return false;
1410+
}
1411+
}
1412+
}
13711413

13721414
tal_arr_expand(&rpc->commands, command);
13731415
return true;
@@ -1391,12 +1433,12 @@ static void setup_command_usage(struct lightningd *ld,
13911433
}
13921434

13931435
bool jsonrpc_command_add(struct jsonrpc *rpc, struct json_command *command,
1394-
const char *usage TAKES)
1436+
const char *usage TAKES, char **collision_name)
13951437
{
13961438
struct json_escape *esc;
13971439
const char *unescaped;
13981440

1399-
if (!command_add(rpc, command))
1441+
if (!command_add(rpc, command, collision_name))
14001442
return false;
14011443

14021444
esc = json_escape_string_(tmpctx, usage, strlen(usage));
@@ -1417,7 +1459,7 @@ static bool jsonrpc_command_add_perm(struct lightningd *ld,
14171459
struct jsonrpc *rpc,
14181460
struct json_command *command)
14191461
{
1420-
if (!command_add(rpc, command))
1462+
if (!command_add(rpc, command, NULL))
14211463
return false;
14221464
setup_command_usage(ld, command);
14231465
return true;

0 commit comments

Comments
 (0)