mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-21 22:31:48 +01:00
Merge information from `*.request.json` & `*.schema.json`. Also consolidate remaining details from `*.md` files and create a single file in schemas folder.
280 lines
13 KiB
JSON
280 lines
13 KiB
JSON
{
|
|
"$schema": "../rpc-schema-draft.json",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"added": "v23.08",
|
|
"rpc": "createrune",
|
|
"title": "Command to Create/Update Rune for Authorizing Remote Peer Access",
|
|
"description": [
|
|
"The **createrune** RPC command creates a base64 string called a *rune* which can be used to access commands on this node. Each *rune* contains a unique id (a number starting at 0), and can have restrictions inside it. Nobody can remove restrictions from a rune: if you try, the rune will be rejected. There is no limit on how many runes you can issue; the node simply decodes and checks them as they are received.",
|
|
"",
|
|
"Oh, I almost forgot. Runes can also be invoked like in ancient times with the **invokerune** command. Feel the magical powers of a rune by invoking it."
|
|
],
|
|
"request": {
|
|
"required": [],
|
|
"properties": {
|
|
"rune": {
|
|
"type": "string",
|
|
"description": [
|
|
"If supplied, the restrictions are simple appended to that *rune* (it doesn't need to be a rune belonging to this node). If not supplied, a new *rune* is constructed, with a new unique id."
|
|
]
|
|
},
|
|
"restrictions": {
|
|
"description": [
|
|
"It can be the string `readonly`, or an array of restrictions.",
|
|
"Each restriction is an array of one or more alternatives, such as \"method is listpeers\", or \"method is listpeers OR time is before 2023\"."
|
|
],
|
|
"oneOf": [
|
|
{
|
|
"type": "array",
|
|
"description": [
|
|
"Alternatives use a simple language to examine the command which is being run:",
|
|
" * time: the current UNIX time, e.g. \"time<1656759180\".",
|
|
" * id: the node_id of the peer, e.g. \"id=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\".",
|
|
" * method: the command being run, e.g. \"method=withdraw\".",
|
|
" * per: how often the rune can be used, with suffix \"sec\" (default), \"min\", \"hour\", \"day\" or \"msec\", \"usec\" or \"nsec\". e.g. \"per=5sec\".",
|
|
" * rate: the rate limit, per minute, e.g. \"rate=60\" is equivalent to \"per=1sec\".",
|
|
" * pnum: the number of parameters. e.g. \"pnum<2\".",
|
|
" * pnameX: the parameter named X (with any punctuation like `_` removed). e.g. \"pnamedestination=1RustyRX2oai4EYYDpQGWvEL62BBGqN9T\".",
|
|
" * parrN: the N'th parameter. e.g. \"parr0=1RustyRX2oai4EYYDpQGWvEL62BBGqN9T\"."
|
|
],
|
|
"items": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
{
|
|
"type": "string",
|
|
"enum": [
|
|
"readonly"
|
|
],
|
|
"description": [
|
|
"A rune which allows most *get* and *list* commands, and the *summary* command."
|
|
]
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"response": {
|
|
"required": [
|
|
"rune",
|
|
"unique_id"
|
|
],
|
|
"properties": {
|
|
"rune": {
|
|
"type": "string",
|
|
"description": [
|
|
"The resulting rune."
|
|
]
|
|
},
|
|
"unique_id": {
|
|
"type": "string",
|
|
"description": [
|
|
"The id of this rune: this is set at creation and cannot be changed (even as restrictions are added)."
|
|
]
|
|
},
|
|
"warning_unrestricted_rune": {
|
|
"type": "string",
|
|
"description": [
|
|
"A warning shown when runes are created with powers that could drain your node."
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"restriction_format": [
|
|
"Restrictions are one or more alternatives. Each alternative is *name* *operator* *value*. The valid names are shown above.",
|
|
"",
|
|
"Note that if a value contains `\\`, it must be preceeded by another `\\` to form valid JSON:",
|
|
"* `=`: passes if equal ie. identical. e.g. `method=withdraw`",
|
|
"* `/`: not equals, e.g. `method/withdraw`",
|
|
"* `^`: starts with, e.g. `id^024b9a1fa8e006f1e3937f`",
|
|
"* `$`: ends with, e.g. `id$381df1cc449605`.",
|
|
"* `~`: contains, e.g. `id~006f1e3937f65f66c40`.",
|
|
"* `<`: is a decimal integer, and is less than. e.g. `time<1656759180`",
|
|
"* `>`: is a decimal integer, and is greater than. e.g. `time>1656759180`",
|
|
"* `{`: preceeds in alphabetical order (or matches but is shorter),",
|
|
" e.g. `id{02ff`.",
|
|
"* `}`: follows in alphabetical order (or matches but is longer),",
|
|
" e.g. `id}02ff`.",
|
|
"* `#`: a comment, ignored, e.g. `dumb example#`.",
|
|
"* `!`: only passes if the *name* does *not* exist. e.g. `pnamedestination!`.",
|
|
"Every other operator except `#` fails if *name* does not exist!"
|
|
],
|
|
"example_usage": [
|
|
"This creates a fresh rune which can do anything:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune",
|
|
"{",
|
|
" \"rune\": \"KUhZzNlECC7pYsz3QVbF1TqjIUYi3oyESTI7n60hLMs9MA==\",",
|
|
" \"unique_id\": \"0\"",
|
|
"}",
|
|
"```",
|
|
"We can add restrictions to that rune, like so:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune rune=KUhZzNlECC7pYsz3QVbF1TqjIUYi3oyESTI7n60hLMs9MA== restrictions=readonly",
|
|
"{",
|
|
" \"rune\": \"NbL7KkXcPQsVseJ9TdJNjJK2KsPjnt_q4cE_wvc873I9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl\",",
|
|
" \"unique_id\": \"0\"",
|
|
"}",
|
|
"```",
|
|
"The \"readonly\" restriction is a short-cut for two restrictions:",
|
|
"",
|
|
"1. `[\"method^list\", \"method^get\", \"method=summary\"]`: You may call list, get or summary.",
|
|
"2. `[\"method/listdatastore\"]`: But not listdatastore: that contains sensitive stuff!",
|
|
"",
|
|
"We can do the same manually, like so:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune rune=KUhZzNlECC7pYsz3QVbF1TqjIUYi3oyESTI7n60hLMs9MA== restrictions='[[\"method^list\", \"method^get\", \"method=summary\"],[\"method/listdatastore\"]]'",
|
|
"{",
|
|
" \"rune\": \"NbL7KkXcPQsVseJ9TdJNjJK2KsPjnt_q4cE_wvc873I9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl\",",
|
|
" \"unique_id\": \"0\"",
|
|
"}",
|
|
"```",
|
|
"Let's create a rune which lets a specific peer (024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605) run \"listpeers\" on themselves:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune restrictions='[[\"id=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\"],[\"method=listpeers\"],[\"pnum=1\"],[\"pnameid=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\",\"parr0=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\"]]'",
|
|
"{",
|
|
" \"rune\": \"FE8GHiGVvxcFqCQcClVRRiNE_XEeLYQzyG2jmqto4jM9MiZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDV8cGFycjA9MDI0YjlhMWZhOGUwMDZmMWUzOTM3ZjY1ZjY2YzQwOGU2ZGE4ZTFjYTcyOGVhNDMyMjJhNzM4MWRmMWNjNDQ5NjA1\",",
|
|
" \"unique_id\": \"2\"",
|
|
"}",
|
|
"```",
|
|
"This allows `listpeers` with 1 argument (`pnum=1`), which is either by name (`pnameid`), or position (`parr0`). We could shorten this in several ways: either allowing only positional or named parameters, or by testing the start of the parameters only. Here's an example which only checks the first 9 bytes of the `listpeers` parameter:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune restrictions='[[\"id=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\"],[\"method=listpeers\"],[\"pnum=1\"],[\"pnameid^024b9a1fa8e006f1e393\", \"parr0^024b9a1fa8e006f1e393\"]'",
|
|
" {",
|
|
" \"rune\": \"fTQnfL05coEbiBO8SS0cvQwCcPLxE9c02pZCC6HRVEY9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5Mw==\",",
|
|
" \"unique_id\": \"3\"",
|
|
"}",
|
|
"```",
|
|
"Before we give this to our peer, let's add two more restrictions: that it only be usable for 24 hours from now (`time<`), and that it can only be used twice a minute (`rate=2`). `date +%s` can give us the current time in seconds:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli commando-rune rune=fTQnfL05coEbiBO8SS0cvQwCcPLxE9c02pZCC6HRVEY9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5Mw== restrictions='[[\"time<'$(($(date +%s) + 24*60*60))'\",\"rate=2\"]]'",
|
|
"{",
|
|
" \"rune\": \"tU-RLjMiDpY2U0o3W1oFowar36RFGpWloPbW9-RuZdo9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5MyZ0aW1lPDE2NTY5MjA1MzgmcmF0ZT0y\",",
|
|
" \"unique_id\": \"3\"",
|
|
"}",
|
|
"```",
|
|
"You can also use lightning-decode(7) to examine runes you have been given:",
|
|
"",
|
|
"```shell",
|
|
"$ lightning-cli decode tU-RLjMiDpY2U0o3W1oFowar36RFGpWloPbW9-RuZdo9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5MyZ0aW1lPDE2NTY5MjA1MzgmcmF0ZT0y",
|
|
"{",
|
|
" \"type\": \"rune\",",
|
|
" \"unique_id\": \"3\",",
|
|
" \"string\": \"b54f912e33220e9636534a375b5a05a306abdfa4451a95a5a0f6d6f7e46e65da:=3&id=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605&method=listpeers&pnum=1&pnameid^024b9a1fa8e006f1e393|parr0^024b9a1fa8e006f1e393&time<1656920538&rate=2\",",
|
|
" \"restrictions\": [",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"id=024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605\"",
|
|
" ],",
|
|
" \"summary\": \"id (of commanding peer) equal to '024b9a1fa8e006f1e3937f65f66c408e6da8e1ca728ea43222a7381df1cc449605'\"",
|
|
" },",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"method=listpeers\"",
|
|
" ],",
|
|
" \"summary\": \"method (of command) equal to 'listpeers'\"",
|
|
" },",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"pnum=1\"",
|
|
" ],",
|
|
" \"summary\": \"pnum (number of command parameters) equal to 1\"",
|
|
" },",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"pnameid^024b9a1fa8e006f1e393\",",
|
|
" \"parr0^024b9a1fa8e006f1e393\"",
|
|
" ],",
|
|
" \"summary\": \"pnameid (object parameter 'id') starts with '024b9a1fa8e006f1e393' OR parr0 (array parameter #0) starts with '024b9a1fa8e006f1e393'\"",
|
|
" },",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"time<1656920538\"",
|
|
" ],",
|
|
" \"summary\": \"time (in seconds since 1970) less than 1656920538 (approximately 19 hours 18 minutes from now)\"",
|
|
" },",
|
|
" {",
|
|
" \"alternatives\": [",
|
|
" \"rate=2\"",
|
|
" ],",
|
|
" \"summary\": \"rate (max per minute) equal to 2\"",
|
|
" }",
|
|
" ],",
|
|
" \"valid\": true",
|
|
"}",
|
|
"```"
|
|
],
|
|
"sharing_runes": [
|
|
"Because anyone can add a restriction to a rune, you can always turn a normal rune into a read-only rune, or restrict access for 30 minutes from the time you give it to someone. Adding restrictions before sharing runes is best practice.",
|
|
"",
|
|
"If a rune has a ratelimit, any derived rune will have the same id, and thus will compete for that ratelimit. You might want to consider adding a tighter ratelimit to a rune before sharing it, so you will keep the remainder. For example, if you rune has a limit of 60 times per minute, adding a limit of 5 times per minute and handing that rune out means you can still use your original rune 55 times per minute."
|
|
],
|
|
"example_json_request": [
|
|
{
|
|
"id": "example:createrune#1",
|
|
"method": "createrune",
|
|
"params": {
|
|
"restrictions": [
|
|
[
|
|
"method/getinfo"
|
|
]
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"id": "example:createrune#2",
|
|
"method": "createrune",
|
|
"params": {
|
|
"restrictions": "readonly"
|
|
}
|
|
},
|
|
{
|
|
"id": "example:createrune#3",
|
|
"method": "createrune",
|
|
"params": [
|
|
"enX0sTpHB8y1ktyTAF80CnEvGetG340Ne3AGItudBS49NCZwbnVtPTA=",
|
|
[
|
|
[
|
|
"rate=3"
|
|
]
|
|
]
|
|
]
|
|
}
|
|
],
|
|
"example_json_response": [
|
|
{
|
|
"rune": "S5f-BKt3rR-cvJmujdpDCUQm_XLahfB4iQuDlwqMJiQ9MCZtZXRob2QvZ2V0aW5mbw==",
|
|
"unique_id": "0"
|
|
},
|
|
{
|
|
"rune": "oVkzoiQ67VCU1h_aRjPqCeWktGX54ARDsqqQgDL-uMs9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl",
|
|
"unique_id": "1"
|
|
},
|
|
{
|
|
"rune": "_h2eKjoK7ITAF-JQ1S5oum9oMQesrz-t1FR9kDChRB49NCZwbnVtPTAmcmF0ZT0z",
|
|
"unique_id": "2"
|
|
}
|
|
],
|
|
"author": [
|
|
"Rusty Russell <<rusty@rustcorp.com.au>> wrote the original Python commando.py plugin, the in-tree commando plugin, and this manual page.",
|
|
"",
|
|
"Shahana Farooqui <<sfarooqui@blockstream.com>> is mainly responsible for migrating commando-rune to createrune."
|
|
],
|
|
"see_also": [
|
|
"lightning-commando-rune(7)",
|
|
"lightning-checkrune(7)"
|
|
],
|
|
"resources": [
|
|
"Main web site: <https://github.com/ElementsProject/lightning>"
|
|
]
|
|
}
|