diff --git a/contrib/msggen/msggen/schema.json b/contrib/msggen/msggen/schema.json index d187c181ff3a..7f38f8e675ea 100644 --- a/contrib/msggen/msggen/schema.json +++ b/contrib/msggen/msggen/schema.json @@ -5391,1086 +5391,6 @@ } ] }, - "commando-blacklist.json": { - "$schema": "../rpc-schema-draft.json", - "type": "object", - "added": "v23.05", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-blacklist", - "title": "Command to prevent a rune from working", - "description": [ - "The **commando-blacklist** RPC command allows you to effectively revoke the rune you have created (and any runes derived from that rune with additional restictions). Attempting to use these runes will be resulted in a `Blacklisted rune` error message.", - "", - "All runes created by commando have a unique sequential id within them and can be blacklisted in ranges for efficiency. The command always returns the blacklisted ranges on success. If no parameters are specified, no changes have been made. If start specified without end, that single rune is blacklisted. If end is also specified, every rune from start till end inclusive is blacklisted." - ], - "request": { - "required": [], - "additionalProperties": false, - "properties": { - "start": { - "type": "u64", - "description": [ - "First rune unique id to blacklist." - ] - }, - "end": { - "type": "u64", - "description": [ - "Final rune unique id to blacklist (defaults to start)." - ] - } - }, - "dependentUpon": { - "start": [ - "end" - ] - } - }, - "response": { - "required": [ - "blacklist" - ], - "additionalProperties": false, - "properties": { - "blacklist": { - "type": "array", - "description": [ - "The resulting blacklist ranges after the command." - ], - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "start", - "end" - ], - "properties": { - "start": { - "type": "u64", - "description": [ - "Unique id of first rune in this blacklist range." - ] - }, - "end": { - "type": "u64", - "description": [ - "Unique id of last rune in this blacklist range." - ] - } - } - } - } - } - }, - "author": [ - "Shahana Farooqui <> is mainly responsible." - ], - "see_also": [ - "lightning-commando-listrunes(7)" - ], - "resources": [ - "Main web site: " - ], - "examples": [ - { - "request": { - "id": "example:commando-blacklist#1", - "method": "commando-blacklist", - "params": { - "start": 1 - } - }, - "response": { - "blacklist": [ - { - "start": 1, - "end": 1 - } - ] - } - }, - { - "request": { - "id": "example:commando-blacklist#2", - "method": "commando-blacklist", - "params": { - "start": 2, - "end": 3 - } - }, - "response": { - "blacklist": [ - { - "start": 1, - "end": 3 - } - ] - } - } - ] - }, - "commando-listrunes.json": { - "$schema": "../rpc-schema-draft.json", - "type": "object", - "added": "v23.05", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-listrunes", - "title": "Command to list previously generated runes", - "description": [ - "The **commando-listrunes** RPC command either lists runes that we stored as we generate them (see lightning-commando-rune(7)) or decodes the rune given on the command line.", - "", - "NOTE: Runes generated prior to v23.05 were not stored, so will not appear in this list." - ], - "request": { - "required": [], - "additionalProperties": false, - "properties": { - "rune": { - "type": "string", - "description": [ - "Optional rune to list." - ] - } - } - }, - "response": { - "required": [ - "runes" - ], - "additionalProperties": false, - "properties": { - "runes": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "rune", - "unique_id", - "restrictions", - "restrictions_as_english" - ], - "properties": { - "rune": { - "type": "string", - "description": [ - "Base64 encoded rune." - ] - }, - "unique_id": { - "type": "string", - "description": [ - "Unique id assigned when the rune was generated; this is always a u64 for commando runes." - ] - }, - "restrictions": { - "type": "array", - "description": [ - "The restrictions on what commands this rune can authorize." - ], - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "alternatives", - "english" - ], - "properties": { - "alternatives": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "fieldname", - "value", - "condition", - "english" - ], - "properties": { - "fieldname": { - "type": "string", - "description": [ - "The field this restriction applies to; see commando-rune(7)." - ] - }, - "value": { - "type": "string", - "description": [ - "The value accepted for this field." - ] - }, - "condition": { - "type": "string", - "description": [ - "The way to compare fieldname and value." - ] - }, - "english": { - "type": "string", - "description": [ - "English readable description of this alternative." - ] - } - } - } - }, - "english": { - "type": "string", - "description": [ - "English readable summary of alternatives above." - ] - } - } - } - }, - "restrictions_as_english": { - "type": "string", - "description": [ - "English readable description of the restrictions array above." - ] - }, - "stored": { - "type": "boolean", - "enum": [ - false - ], - "description": [ - "This is false if the rune does not appear in our datastore (only possible when `rune` is specified)." - ] - }, - "blacklisted": { - "type": "boolean", - "enum": [ - true - ], - "description": [ - "The rune has been blacklisted; see commando-blacklist(7)." - ] - }, - "last_used": { - "type": "number", - "description": [ - "The last time this rune was successfully used." - ], - "added": "23.11" - }, - "our_rune": { - "type": "boolean", - "enum": [ - false - ], - "description": [ - "This is not a rune for this node (only possible when `rune` is specified)." - ] - } - } - } - } - } - }, - "author": [ - "Shahana Farooqui <> is mainly responsible." - ], - "see_also": [ - "lightning-commando-rune(7)", - "lightning-commando-blacklist(7)" - ], - "resources": [ - "Main web site: " - ], - "examples": [ - { - "request": { - "id": "example:commando-listrunes#1", - "method": "commando-listrunes", - "params": { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz" - } - }, - "response": { - "runes": [ - { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "id starts with 0266e4598d1d3c415f57" - } - ], - "english": "id starts with 0266e4598d1d3c415f57" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - } - ], - "restrictions_as_english": "id starts with 0266e4598d1d3c415f57 AND method equal to listpeers" - } - ] - } - }, - { - "request": { - "id": "example:commando-listrunes#2", - "method": "commando-listrunes", - "params": {} - }, - "response": { - "runes": [ - { - "rune": "zFMd1fjhrAYxUeFA54TjloZqOt8JrA_i_nYwIgXkag49MA==", - "unique_id": "0", - "restrictions": [], - "restrictions_as_english": "" - }, - { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "id starts with 0266e4598d1d3c415f57" - } - ], - "english": "id starts with 0266e4598d1d3c415f57" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - } - ], - "restrictions_as_english": "id starts with 0266e4598d1d3c415f57 AND method equal to listpeers" - }, - { - "rune": "QUJEYMLGgiaJvMDv_MhR2hiMKIBTbq-PrL-KxcIlirQ9MiZtZXRob2Q9cGF5JnBuYW1lYW1vdW50bXNhdDwxMDAwMA==", - "unique_id": "2", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "=", - "english": "method equal to pay" - } - ], - "english": "method equal to pay" - }, - { - "alternatives": [ - { - "fieldname": "pnameamountmsat", - "value": "10000", - "condition": "<", - "english": "pnameamountmsat < 10000" - } - ], - "english": "pnameamountmsat < 10000" - } - ], - "restrictions_as_english": "method equal to pay AND pnameamountmsat < 10000" - }, - { - "rune": "jEx3l0c7NMZPSDYT7xnXXvNA83z5PDNBHRQTIk1BwNw9MyZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTh8cGFycjA9MDI2NmU0NTk4ZDFkM2M0MTVmNTcyYTg0ODg4MzBiNjBmN2U3NDRlZDkyMzVlYjBiMWJhOTMyODNiMzE1YzAzNTE4", - "unique_id": "3", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - }, - { - "alternatives": [ - { - "fieldname": "pnum", - "value": "1", - "condition": "=", - "english": "pnum equal to 1" - } - ], - "english": "pnum equal to 1" - }, - { - "alternatives": [ - { - "fieldname": "pnameid", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "fieldname": "parr0", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 OR parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "restrictions_as_english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 AND method equal to listpeers AND pnum equal to 1 AND pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 OR parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "rune": "8_CRIJ4arWAz72A4ILOZ46MESSJtQQQ9iQZjU28qulA9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - "unique_id": "4", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - }, - { - "alternatives": [ - { - "fieldname": "pnum", - "value": "1", - "condition": "=", - "english": "pnum equal to 1" - } - ], - "english": "pnum equal to 1" - }, - { - "alternatives": [ - { - "fieldname": "pnameid", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "pnameid starts with 0266e4598d1d3c415f57" - }, - { - "fieldname": "parr0", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "parr0 starts with 0266e4598d1d3c415f57" - } - ], - "english": "pnameid starts with 0266e4598d1d3c415f57 OR parr0 starts with 0266e4598d1d3c415f57" - } - ], - "restrictions_as_english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 AND method equal to listpeers AND pnum equal to 1 AND pnameid starts with 0266e4598d1d3c415f57 OR parr0 starts with 0266e4598d1d3c415f57" - }, - { - "rune": "iP1FQEsFmPsu-XW7w8uXIJaJb7jU9PqOfkmXlOyWMuA9NSZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5fG1ldGhvZD1wYXl8bWV0aG9kPXhwYXkmbWV0aG9kL2xpc3RkYXRhc3RvcmUmbWV0aG9kL3BheXxwZXI9MWRheSZtZXRob2QvcGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAxJm1ldGhvZC94cGF5fHBlcj0xZGF5Jm1ldGhvZC94cGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAx", - "unique_id": "5", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "method", - "value": "list", - "condition": "^", - "english": "method starts with list" - }, - { - "fieldname": "method", - "value": "get", - "condition": "^", - "english": "method starts with get" - }, - { - "fieldname": "method", - "value": "summary", - "condition": "=", - "english": "method equal to summary" - }, - { - "fieldname": "method", - "value": "pay", - "condition": "=", - "english": "method equal to pay" - }, - { - "fieldname": "method", - "value": "xpay", - "condition": "=", - "english": "method equal to xpay" - } - ], - "english": "method starts with list OR method starts with get OR method equal to summary OR method equal to pay OR method equal to xpay" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listdatastore", - "condition": "/", - "english": "method unequal to listdatastore" - } - ], - "english": "method unequal to listdatastore" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "/", - "english": "method unequal to pay" - }, - { - "fieldname": "per", - "value": "1day", - "condition": "=", - "english": "per equal to 1day" - } - ], - "english": "method unequal to pay OR per equal to 1day" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "/", - "english": "method unequal to pay" - }, - { - "fieldname": "pnameamount_msat", - "value": "100000001", - "condition": "<", - "english": "pnameamount_msat < 100000001" - } - ], - "english": "method unequal to pay OR pnameamount_msat < 100000001" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "xpay", - "condition": "/", - "english": "method unequal to xpay" - }, - { - "fieldname": "per", - "value": "1day", - "condition": "=", - "english": "per equal to 1day" - } - ], - "english": "method unequal to xpay OR per equal to 1day" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "xpay", - "condition": "/", - "english": "method unequal to xpay" - }, - { - "fieldname": "pnameamount_msat", - "value": "100000001", - "condition": "<", - "english": "pnameamount_msat < 100000001" - } - ], - "english": "method unequal to xpay OR pnameamount_msat < 100000001" - } - ], - "restrictions_as_english": "method starts with list OR method starts with get OR method equal to summary OR method equal to pay OR method equal to xpay AND method unequal to listdatastore AND method unequal to pay OR per equal to 1day AND method unequal to pay OR pnameamount_msat < 100000001 AND method unequal to xpay OR per equal to 1day AND method unequal to xpay OR pnameamount_msat < 100000001" - } - ] - } - } - ] - }, - "commando-rune.json": { - "$schema": "../rpc-schema-draft.json", - "type": "object", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-rune", - "title": "Command to Authorize Remote Peer Access", - "description": [ - "The **commando-rune** 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 (we do store them for lightning-commando- listrunes(7) however)." - ], - "request": { - "required": [], - "additionalProperties": false, - "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" - ], - "additionalProperties": false, - "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!" - ], - "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." - ], - "author": [ - "Rusty Russell <> wrote the original Python commando.py plugin, the in-tree commando plugin, and this manual page.", - "", - "Christian Decker came up with the name \"commando\", which almost excuses his previous adoption of the name \"Eltoo\"." - ], - "see_also": [ - "lightning-commando(7)", - "lightning-decode(7)" - ], - "resources": [ - "Main web site: " - ], - "usage": [ - "- You can 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", - "}", - "```", - "", - "- You can use lightning-checkrune(7) to verify whether a rune is valid for a specific method and its parameters:", - "", - "```shell", - "lightning-cli checkrune -k 'rune'=tU-RLjMiDpY2U0o3W1oFowar36RFGpWloPbW9-RuZdo9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5MyZ0aW1lPDE2NTY5MjA1MzgmcmF0ZT0y 'method'='invoice' 'params'='{\"amount_msat\": 100000001, \"label\": \"invoicelabel\"', \"description\": \"Checking rune validity\"}'", - "```" - ], - "examples": [ - { - "description": [ - "This creates a fresh rune which can do anything:" - ], - "request": { - "id": "example:commando-rune#1", - "method": "commando-rune", - "params": {} - }, - "response": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "unique_id": "0", - "warning_unrestricted_rune": "WARNING: This rune has no restrictions! Anyone who has access to this rune could drain funds from your node. Be careful when giving this to apps that you don't trust. Consider using the restrictions parameter to only allow access to specific rpc methods." - } - }, - { - "description": [ - "We can add restrictions to that rune, like so:", - "", - "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!" - ], - "request": { - "id": "example:commando-rune#2", - "method": "commando-rune", - "params": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "restrictions": "readonly" - } - }, - "response": { - "rune": "oVkzoiQ67VCU1h_aRjPqCeWktGX54ARDsqqQgDL-uMs9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl", - "unique_id": "0" - } - }, - { - "description": [ - "We can do the same manually (readonly), like so:" - ], - "request": { - "id": "example:commando-rune#3", - "method": "commando-rune", - "params": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "restrictions": [ - [ - "method^list", - "method^get", - "method=summary" - ], - [ - "method/listdatastore" - ] - ] - } - }, - "response": { - "rune": "oVkzoiQ67VCU1h_aRjPqCeWktGX54ARDsqqQgDL-uMs9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl", - "unique_id": "0" - } - }, - { - "description": [ - "This will allow the rune to be used for id starting with 0266e4598d1d3c415f57, and for the method listpeers:" - ], - "request": { - "id": "example:commando-rune#4", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id^0266e4598d1d3c415f57" - ], - [ - "method=listpeers" - ] - ] - } - }, - "response": { - "rune": "AzR2J3ym3qYCQpnTCuA7EXd90jhK9qzfRVTiMXhOpzk9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1" - } - }, - { - "description": [ - "This will allow the rune to be used for the method pay, and for the parameter amount\\_msat to be less than 10000:" - ], - "request": { - "id": "example:commando-rune#5", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "method=pay" - ], - [ - "pnameamountmsat<10000" - ] - ] - } - }, - "response": { - "rune": "4Ab5jUyjTVuYBxGTz3KtnR7kT__KDIjYBCvza5e4EVU9MiZtZXRob2Q9cGF5JnBuYW1lYW1vdW50bXNhdDwxMDAwMA==", - "unique_id": "2" - } - }, - { - "description": [ - "Let's create a rune which lets a specific peer run listpeers on themselves:" - ], - "request": { - "id": "example:commando-rune#6", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ], - [ - "method=listpeers" - ], - [ - "pnum=1" - ], - [ - "pnameid=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518", - "parr0=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ] - ] - } - }, - "response": { - "rune": "M8_ecN6cRSI0k14vMKNkkSbI6HIzrS49txY_WFe30y09MyZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTh8cGFycjA9MDI2NmU0NTk4ZDFkM2M0MTVmNTcyYTg0ODg4MzBiNjBmN2U3NDRlZDkyMzVlYjBiMWJhOTMyODNiMzE1YzAzNTE4", - "unique_id": "3" - } - }, - { - "description": [ - "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 10 bytes of the `listpeers` parameter:" - ], - "request": { - "id": "example:commando-rune#7", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ], - [ - "method=listpeers" - ], - [ - "pnum=1" - ], - [ - "pnameid^0266e4598d1d3c415f57", - "parr0^0266e4598d1d3c415f57" - ] - ] - } - }, - "response": { - "rune": "lCryeRwU6TfdsWTzmtv72TBUBAjgyWPwZ0r4GQm8vUs9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - "unique_id": "4" - } - }, - { - "description": [ - "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:" - ], - "request": { - "id": "example:commando-rune#8", - "method": "commando-rune", - "params": [ - "lCryeRwU6TfdsWTzmtv72TBUBAjgyWPwZ0r4GQm8vUs9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - [ - [ - "time<\"$(($(date +%s) + 24*60*60))\"", - "rate=2" - ] - ] - ] - }, - "response": { - "rune": "7nvN7uG2CyTOXe3dYQL38YVdGsnD6d5VNNyeHVl6inc9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZ0aW1lPCIkKCgkKGRhdGUgKyVzKSArIDI0KjYwKjYwKSkifHJhdGU9Mg==", - "unique_id": "4" - } - }, - { - "description": [ - "Now, let us create a rune with `read-only` restrictions, extended to only allow sending payments of `less than 100,000 sats per day` using either the `pay` or `xpay` method. Ideally, the condition would look something like:", - "", - "`[[\"method^list or method^get or ((method=pay or method=xpay) and per=1day and pnameamount\\_msat<100000001)\"],[\"method/listdatastore\"]]`.", - "", - "However, since brackets and AND conditions within OR are currently not supported for rune creation, we can restructure the conditions as follows:", - "", - "- method^list|method^get|method=summary|method=pay|method=xpay", - "- method/listdatastore", - "- method/pay|per=1day", - "- method/pay|pnameamount\\_msat<100000001", - "- method/xpay|per=1day", - "- method/xpay|pnameamount\\_msat<100000001" - ], - "request": { - "id": "example:commando-rune#9", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "method^list", - "method^get", - "method=summary", - "method=pay", - "method=xpay" - ], - [ - "method/listdatastore" - ], - [ - "method/pay", - "per=1day" - ], - [ - "method/pay", - "pnameamount_msat<100000001" - ], - [ - "method/xpay", - "per=1day" - ], - [ - "method/xpay", - "pnameamount_msat<100000001" - ] - ] - } - }, - "response": { - "rune": "QqgK4ZNJOwMjhUAQhHcnkTBXRoLghhPcJVR_Zew97ug9NSZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5fG1ldGhvZD1wYXl8bWV0aG9kPXhwYXkmbWV0aG9kL2xpc3RkYXRhc3RvcmUmbWV0aG9kL3BheXxwZXI9MWRheSZtZXRob2QvcGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAxJm1ldGhvZC94cGF5fHBlcj0xZGF5Jm1ldGhvZC94cGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAx", - "unique_id": "5" - } - } - ] - }, "commando.json": { "$schema": "../rpc-schema-draft.json", "type": "object", diff --git a/doc/Makefile b/doc/Makefile index 94f5cb1a7037..e4707f7fcd64 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -34,10 +34,7 @@ MARKDOWNPAGES := doc/addgossip.7 \ doc/checkmessage.7 \ doc/checkrune.7 \ doc/close.7 \ - doc/commando-blacklist.7 \ doc/commando.7 \ - doc/commando-listrunes.7 \ - doc/commando-rune.7 \ doc/connect.7 \ doc/createinvoice.7 \ doc/createonion.7 \ diff --git a/doc/developers-guide/deprecations.md b/doc/developers-guide/deprecations.md index 2b5e7860de9e..54a5f8e819be 100644 --- a/doc/developers-guide/deprecations.md +++ b/doc/developers-guide/deprecations.md @@ -7,17 +7,7 @@ hidden: false | Name | Type | First Deprecated | Last Supported | Description | |--------------------------------------|--------------------|------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| rest-port.clnrest-prefix | Config | v23.11 | v24.11 | Autodetect where we need to rename `rest-port` to `clnrest-port` (added in v23.11) | -| rest-protocol.clnrest-prefix | Config | v23.11 | v24.11 | Autodetect where we need to rename `rest-protocol` to `clnrest-protocol` (added in v23.11) | -| rest-host.clnrest-prefix | Config | v23.11 | v24.11 | Autodetect where we need to rename `rest-host` to `clnrest-host` (added in v23.11) | -| rest-certs.clnrest-prefix | Config | v23.11 | v24.11 | Autodetect where we need to rename `rest-certs` to `clnrest-certs` (added in v23.11) | -| max-locktime-blocks | Config | v24.05 | v24.11 | --max-locktime-blocks is now set to 2016 in the BOLT 4 spec | -| commando-rune | Command | v23.08 | v25.02 | replaced with `lightning-createrune` | -| commando-listrunes | Command | v23.08 | v25.02 | replaced with `lightning-showrunes` | -| commando-blacklist | Command | v23.08 | v25.02 | replaced with `lightning-blacklistrune` | | listpeers.features.option_anchors_zero_fee_htlc_tx | Field | v24.08 | v25.09 | Renamed to `option_anchors` in the spec: check for that in `features` instead | -| experimental-anchors | Config | v24.02 | v25.02 | Now the default | -| experimental-onion-messages | Config | v24.08 | v25.02 | Now the default | | decode.blinding | Field | v24.11 | v25.05 | Renamed to `first_path_key` in BOLT 4 (available in `decode` from v24.11) | | onion_message_recv.blinding | Hook Field | v24.11 | v25.05 | Renamed to `first_path_key` in BOLT 4 (available in hook from v24.11) | | decodepay | Command | v24.11 | v25.12 | Use `decode` which is more powerful (since v23.05) | diff --git a/doc/index.rst b/doc/index.rst index dcc076bb9ba4..9ef9149fcfde 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -43,9 +43,6 @@ Core Lightning Documentation checkrune close commando - commando-blacklist - commando-listrunes - commando-rune connect createinvoice createonion diff --git a/doc/schemas/commando-blacklist.json b/doc/schemas/commando-blacklist.json deleted file mode 100644 index 14c3722dd3bf..000000000000 --- a/doc/schemas/commando-blacklist.json +++ /dev/null @@ -1,121 +0,0 @@ -{ - "$schema": "../rpc-schema-draft.json", - "type": "object", - "added": "v23.05", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-blacklist", - "title": "Command to prevent a rune from working", - "description": [ - "The **commando-blacklist** RPC command allows you to effectively revoke the rune you have created (and any runes derived from that rune with additional restictions). Attempting to use these runes will be resulted in a `Blacklisted rune` error message.", - "", - "All runes created by commando have a unique sequential id within them and can be blacklisted in ranges for efficiency. The command always returns the blacklisted ranges on success. If no parameters are specified, no changes have been made. If start specified without end, that single rune is blacklisted. If end is also specified, every rune from start till end inclusive is blacklisted." - ], - "request": { - "required": [], - "additionalProperties": false, - "properties": { - "start": { - "type": "u64", - "description": [ - "First rune unique id to blacklist." - ] - }, - "end": { - "type": "u64", - "description": [ - "Final rune unique id to blacklist (defaults to start)." - ] - } - }, - "dependentUpon": { - "start": [ - "end" - ] - } - }, - "response": { - "required": [ - "blacklist" - ], - "additionalProperties": false, - "properties": { - "blacklist": { - "type": "array", - "description": [ - "The resulting blacklist ranges after the command." - ], - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "start", - "end" - ], - "properties": { - "start": { - "type": "u64", - "description": [ - "Unique id of first rune in this blacklist range." - ] - }, - "end": { - "type": "u64", - "description": [ - "Unique id of last rune in this blacklist range." - ] - } - } - } - } - } - }, - "author": [ - "Shahana Farooqui <> is mainly responsible." - ], - "see_also": [ - "lightning-commando-listrunes(7)" - ], - "resources": [ - "Main web site: " - ], - "examples": [ - { - "request": { - "id": "example:commando-blacklist#1", - "method": "commando-blacklist", - "params": { - "start": 1 - } - }, - "response": { - "blacklist": [ - { - "start": 1, - "end": 1 - } - ] - } - }, - { - "request": { - "id": "example:commando-blacklist#2", - "method": "commando-blacklist", - "params": { - "start": 2, - "end": 3 - } - }, - "response": { - "blacklist": [ - { - "start": 1, - "end": 3 - } - ] - } - } - ] -} diff --git a/doc/schemas/commando-listrunes.json b/doc/schemas/commando-listrunes.json deleted file mode 100644 index 0b0d1e629497..000000000000 --- a/doc/schemas/commando-listrunes.json +++ /dev/null @@ -1,528 +0,0 @@ -{ - "$schema": "../rpc-schema-draft.json", - "type": "object", - "added": "v23.05", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-listrunes", - "title": "Command to list previously generated runes", - "description": [ - "The **commando-listrunes** RPC command either lists runes that we stored as we generate them (see lightning-commando-rune(7)) or decodes the rune given on the command line.", - "", - "NOTE: Runes generated prior to v23.05 were not stored, so will not appear in this list." - ], - "request": { - "required": [], - "additionalProperties": false, - "properties": { - "rune": { - "type": "string", - "description": [ - "Optional rune to list." - ] - } - } - }, - "response": { - "required": [ - "runes" - ], - "additionalProperties": false, - "properties": { - "runes": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "rune", - "unique_id", - "restrictions", - "restrictions_as_english" - ], - "properties": { - "rune": { - "type": "string", - "description": [ - "Base64 encoded rune." - ] - }, - "unique_id": { - "type": "string", - "description": [ - "Unique id assigned when the rune was generated; this is always a u64 for commando runes." - ] - }, - "restrictions": { - "type": "array", - "description": [ - "The restrictions on what commands this rune can authorize." - ], - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "alternatives", - "english" - ], - "properties": { - "alternatives": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": [ - "fieldname", - "value", - "condition", - "english" - ], - "properties": { - "fieldname": { - "type": "string", - "description": [ - "The field this restriction applies to; see commando-rune(7)." - ] - }, - "value": { - "type": "string", - "description": [ - "The value accepted for this field." - ] - }, - "condition": { - "type": "string", - "description": [ - "The way to compare fieldname and value." - ] - }, - "english": { - "type": "string", - "description": [ - "English readable description of this alternative." - ] - } - } - } - }, - "english": { - "type": "string", - "description": [ - "English readable summary of alternatives above." - ] - } - } - } - }, - "restrictions_as_english": { - "type": "string", - "description": [ - "English readable description of the restrictions array above." - ] - }, - "stored": { - "type": "boolean", - "enum": [ - false - ], - "description": [ - "This is false if the rune does not appear in our datastore (only possible when `rune` is specified)." - ] - }, - "blacklisted": { - "type": "boolean", - "enum": [ - true - ], - "description": [ - "The rune has been blacklisted; see commando-blacklist(7)." - ] - }, - "last_used": { - "type": "number", - "description": [ - "The last time this rune was successfully used." - ], - "added": "23.11" - }, - "our_rune": { - "type": "boolean", - "enum": [ - false - ], - "description": [ - "This is not a rune for this node (only possible when `rune` is specified)." - ] - } - } - } - } - } - }, - "author": [ - "Shahana Farooqui <> is mainly responsible." - ], - "see_also": [ - "lightning-commando-rune(7)", - "lightning-commando-blacklist(7)" - ], - "resources": [ - "Main web site: " - ], - "examples": [ - { - "request": { - "id": "example:commando-listrunes#1", - "method": "commando-listrunes", - "params": { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz" - } - }, - "response": { - "runes": [ - { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "id starts with 0266e4598d1d3c415f57" - } - ], - "english": "id starts with 0266e4598d1d3c415f57" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - } - ], - "restrictions_as_english": "id starts with 0266e4598d1d3c415f57 AND method equal to listpeers" - } - ] - } - }, - { - "request": { - "id": "example:commando-listrunes#2", - "method": "commando-listrunes", - "params": {} - }, - "response": { - "runes": [ - { - "rune": "zFMd1fjhrAYxUeFA54TjloZqOt8JrA_i_nYwIgXkag49MA==", - "unique_id": "0", - "restrictions": [], - "restrictions_as_english": "" - }, - { - "rune": "RXgu0DD_i0wSPEZkIDyZIWL0bSAGdhvJ_GHOQdTg04A9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "id starts with 0266e4598d1d3c415f57" - } - ], - "english": "id starts with 0266e4598d1d3c415f57" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - } - ], - "restrictions_as_english": "id starts with 0266e4598d1d3c415f57 AND method equal to listpeers" - }, - { - "rune": "QUJEYMLGgiaJvMDv_MhR2hiMKIBTbq-PrL-KxcIlirQ9MiZtZXRob2Q9cGF5JnBuYW1lYW1vdW50bXNhdDwxMDAwMA==", - "unique_id": "2", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "=", - "english": "method equal to pay" - } - ], - "english": "method equal to pay" - }, - { - "alternatives": [ - { - "fieldname": "pnameamountmsat", - "value": "10000", - "condition": "<", - "english": "pnameamountmsat < 10000" - } - ], - "english": "pnameamountmsat < 10000" - } - ], - "restrictions_as_english": "method equal to pay AND pnameamountmsat < 10000" - }, - { - "rune": "jEx3l0c7NMZPSDYT7xnXXvNA83z5PDNBHRQTIk1BwNw9MyZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTh8cGFycjA9MDI2NmU0NTk4ZDFkM2M0MTVmNTcyYTg0ODg4MzBiNjBmN2U3NDRlZDkyMzVlYjBiMWJhOTMyODNiMzE1YzAzNTE4", - "unique_id": "3", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - }, - { - "alternatives": [ - { - "fieldname": "pnum", - "value": "1", - "condition": "=", - "english": "pnum equal to 1" - } - ], - "english": "pnum equal to 1" - }, - { - "alternatives": [ - { - "fieldname": "pnameid", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "fieldname": "parr0", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 OR parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "restrictions_as_english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 AND method equal to listpeers AND pnum equal to 1 AND pnameid equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 OR parr0 equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "rune": "8_CRIJ4arWAz72A4ILOZ46MESSJtQQQ9iQZjU28qulA9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - "unique_id": "4", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "id", - "value": "nodeid010101010101010101010101010101010101010101010101010101010101", - "condition": "=", - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - } - ], - "english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listpeers", - "condition": "=", - "english": "method equal to listpeers" - } - ], - "english": "method equal to listpeers" - }, - { - "alternatives": [ - { - "fieldname": "pnum", - "value": "1", - "condition": "=", - "english": "pnum equal to 1" - } - ], - "english": "pnum equal to 1" - }, - { - "alternatives": [ - { - "fieldname": "pnameid", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "pnameid starts with 0266e4598d1d3c415f57" - }, - { - "fieldname": "parr0", - "value": "0266e4598d1d3c415f57", - "condition": "^", - "english": "parr0 starts with 0266e4598d1d3c415f57" - } - ], - "english": "pnameid starts with 0266e4598d1d3c415f57 OR parr0 starts with 0266e4598d1d3c415f57" - } - ], - "restrictions_as_english": "id equal to 0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518 AND method equal to listpeers AND pnum equal to 1 AND pnameid starts with 0266e4598d1d3c415f57 OR parr0 starts with 0266e4598d1d3c415f57" - }, - { - "rune": "iP1FQEsFmPsu-XW7w8uXIJaJb7jU9PqOfkmXlOyWMuA9NSZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5fG1ldGhvZD1wYXl8bWV0aG9kPXhwYXkmbWV0aG9kL2xpc3RkYXRhc3RvcmUmbWV0aG9kL3BheXxwZXI9MWRheSZtZXRob2QvcGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAxJm1ldGhvZC94cGF5fHBlcj0xZGF5Jm1ldGhvZC94cGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAx", - "unique_id": "5", - "restrictions": [ - { - "alternatives": [ - { - "fieldname": "method", - "value": "list", - "condition": "^", - "english": "method starts with list" - }, - { - "fieldname": "method", - "value": "get", - "condition": "^", - "english": "method starts with get" - }, - { - "fieldname": "method", - "value": "summary", - "condition": "=", - "english": "method equal to summary" - }, - { - "fieldname": "method", - "value": "pay", - "condition": "=", - "english": "method equal to pay" - }, - { - "fieldname": "method", - "value": "xpay", - "condition": "=", - "english": "method equal to xpay" - } - ], - "english": "method starts with list OR method starts with get OR method equal to summary OR method equal to pay OR method equal to xpay" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "listdatastore", - "condition": "/", - "english": "method unequal to listdatastore" - } - ], - "english": "method unequal to listdatastore" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "/", - "english": "method unequal to pay" - }, - { - "fieldname": "per", - "value": "1day", - "condition": "=", - "english": "per equal to 1day" - } - ], - "english": "method unequal to pay OR per equal to 1day" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "pay", - "condition": "/", - "english": "method unequal to pay" - }, - { - "fieldname": "pnameamount_msat", - "value": "100000001", - "condition": "<", - "english": "pnameamount_msat < 100000001" - } - ], - "english": "method unequal to pay OR pnameamount_msat < 100000001" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "xpay", - "condition": "/", - "english": "method unequal to xpay" - }, - { - "fieldname": "per", - "value": "1day", - "condition": "=", - "english": "per equal to 1day" - } - ], - "english": "method unequal to xpay OR per equal to 1day" - }, - { - "alternatives": [ - { - "fieldname": "method", - "value": "xpay", - "condition": "/", - "english": "method unequal to xpay" - }, - { - "fieldname": "pnameamount_msat", - "value": "100000001", - "condition": "<", - "english": "pnameamount_msat < 100000001" - } - ], - "english": "method unequal to xpay OR pnameamount_msat < 100000001" - } - ], - "restrictions_as_english": "method starts with list OR method starts with get OR method equal to summary OR method equal to pay OR method equal to xpay AND method unequal to listdatastore AND method unequal to pay OR per equal to 1day AND method unequal to pay OR pnameamount_msat < 100000001 AND method unequal to xpay OR per equal to 1day AND method unequal to xpay OR pnameamount_msat < 100000001" - } - ] - } - } - ] -} diff --git a/doc/schemas/commando-rune.json b/doc/schemas/commando-rune.json deleted file mode 100644 index 4da4ed833a5e..000000000000 --- a/doc/schemas/commando-rune.json +++ /dev/null @@ -1,431 +0,0 @@ -{ - "$schema": "../rpc-schema-draft.json", - "type": "object", - "deprecated": [ - "v23.08", - "v25.02" - ], - "rpc": "commando-rune", - "title": "Command to Authorize Remote Peer Access", - "description": [ - "The **commando-rune** 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 (we do store them for lightning-commando- listrunes(7) however)." - ], - "request": { - "required": [], - "additionalProperties": false, - "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" - ], - "additionalProperties": false, - "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!" - ], - "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." - ], - "author": [ - "Rusty Russell <> wrote the original Python commando.py plugin, the in-tree commando plugin, and this manual page.", - "", - "Christian Decker came up with the name \"commando\", which almost excuses his previous adoption of the name \"Eltoo\"." - ], - "see_also": [ - "lightning-commando(7)", - "lightning-decode(7)" - ], - "resources": [ - "Main web site: " - ], - "usage": [ - "- You can 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", - "}", - "```", - "", - "- You can use lightning-checkrune(7) to verify whether a rune is valid for a specific method and its parameters:", - "", - "```shell", - "lightning-cli checkrune -k 'rune'=tU-RLjMiDpY2U0o3W1oFowar36RFGpWloPbW9-RuZdo9MyZpZD0wMjRiOWExZmE4ZTAwNmYxZTM5MzdmNjVmNjZjNDA4ZTZkYThlMWNhNzI4ZWE0MzIyMmE3MzgxZGYxY2M0NDk2MDUmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjRiOWExZmE4ZTAwNmYxZTM5M3xwYXJyMF4wMjRiOWExZmE4ZTAwNmYxZTM5MyZ0aW1lPDE2NTY5MjA1MzgmcmF0ZT0y 'method'='invoice' 'params'='{\"amount_msat\": 100000001, \"label\": \"invoicelabel\"', \"description\": \"Checking rune validity\"}'", - "```" - ], - "examples": [ - { - "description": [ - "This creates a fresh rune which can do anything:" - ], - "request": { - "id": "example:commando-rune#1", - "method": "commando-rune", - "params": {} - }, - "response": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "unique_id": "0", - "warning_unrestricted_rune": "WARNING: This rune has no restrictions! Anyone who has access to this rune could drain funds from your node. Be careful when giving this to apps that you don't trust. Consider using the restrictions parameter to only allow access to specific rpc methods." - } - }, - { - "description": [ - "We can add restrictions to that rune, like so:", - "", - "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!" - ], - "request": { - "id": "example:commando-rune#2", - "method": "commando-rune", - "params": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "restrictions": "readonly" - } - }, - "response": { - "rune": "oVkzoiQ67VCU1h_aRjPqCeWktGX54ARDsqqQgDL-uMs9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl", - "unique_id": "0" - } - }, - { - "description": [ - "We can do the same manually (readonly), like so:" - ], - "request": { - "id": "example:commando-rune#3", - "method": "commando-rune", - "params": { - "rune": "OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==", - "restrictions": [ - [ - "method^list", - "method^get", - "method=summary" - ], - [ - "method/listdatastore" - ] - ] - } - }, - "response": { - "rune": "oVkzoiQ67VCU1h_aRjPqCeWktGX54ARDsqqQgDL-uMs9MCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl", - "unique_id": "0" - } - }, - { - "description": [ - "This will allow the rune to be used for id starting with 0266e4598d1d3c415f57, and for the method listpeers:" - ], - "request": { - "id": "example:commando-rune#4", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id^0266e4598d1d3c415f57" - ], - [ - "method=listpeers" - ] - ] - } - }, - "response": { - "rune": "AzR2J3ym3qYCQpnTCuA7EXd90jhK9qzfRVTiMXhOpzk9MSZpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZtZXRob2Q9bGlzdHBlZXJz", - "unique_id": "1" - } - }, - { - "description": [ - "This will allow the rune to be used for the method pay, and for the parameter amount\\_msat to be less than 10000:" - ], - "request": { - "id": "example:commando-rune#5", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "method=pay" - ], - [ - "pnameamountmsat<10000" - ] - ] - } - }, - "response": { - "rune": "4Ab5jUyjTVuYBxGTz3KtnR7kT__KDIjYBCvza5e4EVU9MiZtZXRob2Q9cGF5JnBuYW1lYW1vdW50bXNhdDwxMDAwMA==", - "unique_id": "2" - } - }, - { - "description": [ - "Let's create a rune which lets a specific peer run listpeers on themselves:" - ], - "request": { - "id": "example:commando-rune#6", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ], - [ - "method=listpeers" - ], - [ - "pnum=1" - ], - [ - "pnameid=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518", - "parr0=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ] - ] - } - }, - "response": { - "rune": "M8_ecN6cRSI0k14vMKNkkSbI6HIzrS49txY_WFe30y09MyZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTh8cGFycjA9MDI2NmU0NTk4ZDFkM2M0MTVmNTcyYTg0ODg4MzBiNjBmN2U3NDRlZDkyMzVlYjBiMWJhOTMyODNiMzE1YzAzNTE4", - "unique_id": "3" - } - }, - { - "description": [ - "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 10 bytes of the `listpeers` parameter:" - ], - "request": { - "id": "example:commando-rune#7", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "id=0266e4598d1d3c415f572a8488830b60f7e744ed9235eb0b1ba93283b315c03518" - ], - [ - "method=listpeers" - ], - [ - "pnum=1" - ], - [ - "pnameid^0266e4598d1d3c415f57", - "parr0^0266e4598d1d3c415f57" - ] - ] - } - }, - "response": { - "rune": "lCryeRwU6TfdsWTzmtv72TBUBAjgyWPwZ0r4GQm8vUs9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - "unique_id": "4" - } - }, - { - "description": [ - "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:" - ], - "request": { - "id": "example:commando-rune#8", - "method": "commando-rune", - "params": [ - "lCryeRwU6TfdsWTzmtv72TBUBAjgyWPwZ0r4GQm8vUs9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1Nw==", - [ - [ - "time<\"$(($(date +%s) + 24*60*60))\"", - "rate=2" - ] - ] - ] - }, - "response": { - "rune": "7nvN7uG2CyTOXe3dYQL38YVdGsnD6d5VNNyeHVl6inc9NCZpZD0wMjY2ZTQ1OThkMWQzYzQxNWY1NzJhODQ4ODgzMGI2MGY3ZTc0NGVkOTIzNWViMGIxYmE5MzI4M2IzMTVjMDM1MTgmbWV0aG9kPWxpc3RwZWVycyZwbnVtPTEmcG5hbWVpZF4wMjY2ZTQ1OThkMWQzYzQxNWY1N3xwYXJyMF4wMjY2ZTQ1OThkMWQzYzQxNWY1NyZ0aW1lPCIkKCgkKGRhdGUgKyVzKSArIDI0KjYwKjYwKSkifHJhdGU9Mg==", - "unique_id": "4" - } - }, - { - "description": [ - "Now, let us create a rune with `read-only` restrictions, extended to only allow sending payments of `less than 100,000 sats per day` using either the `pay` or `xpay` method. Ideally, the condition would look something like:", - "", - "`[[\"method^list or method^get or ((method=pay or method=xpay) and per=1day and pnameamount\\_msat<100000001)\"],[\"method/listdatastore\"]]`.", - "", - "However, since brackets and AND conditions within OR are currently not supported for rune creation, we can restructure the conditions as follows:", - "", - "- method^list|method^get|method=summary|method=pay|method=xpay", - "- method/listdatastore", - "- method/pay|per=1day", - "- method/pay|pnameamount\\_msat<100000001", - "- method/xpay|per=1day", - "- method/xpay|pnameamount\\_msat<100000001" - ], - "request": { - "id": "example:commando-rune#9", - "method": "commando-rune", - "params": { - "restrictions": [ - [ - "method^list", - "method^get", - "method=summary", - "method=pay", - "method=xpay" - ], - [ - "method/listdatastore" - ], - [ - "method/pay", - "per=1day" - ], - [ - "method/pay", - "pnameamount_msat<100000001" - ], - [ - "method/xpay", - "per=1day" - ], - [ - "method/xpay", - "pnameamount_msat<100000001" - ] - ] - } - }, - "response": { - "rune": "QqgK4ZNJOwMjhUAQhHcnkTBXRoLghhPcJVR_Zew97ug9NSZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5fG1ldGhvZD1wYXl8bWV0aG9kPXhwYXkmbWV0aG9kL2xpc3RkYXRhc3RvcmUmbWV0aG9kL3BheXxwZXI9MWRheSZtZXRob2QvcGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAxJm1ldGhvZC94cGF5fHBlcj0xZGF5Jm1ldGhvZC94cGF5fHBuYW1lYW1vdW50X21zYXQ8MTAwMDAwMDAx", - "unique_id": "5" - } - } - ] -} diff --git a/lightningd/options.c b/lightningd/options.c index 492c345f34a5..115c7ded7eab 100644 --- a/lightningd/options.c +++ b/lightningd/options.c @@ -616,15 +616,6 @@ static char *opt_set_hsm_password(struct lightningd *ld) return NULL; } -static char *opt_set_max_htlc_cltv(const char *arg, struct lightningd *ld) -{ - if (!opt_deprecated_ok(ld, "max-locktime-blocks", NULL, - "v24.05", "v24.11")) - return "--max-locktime-blocks has been deprecated (BOLT #4 says 2016)"; - - return opt_set_u32(arg, &ld->config.max_htlc_cltv); -} - static char *opt_force_privkey(const char *optarg, struct lightningd *ld) { tal_free(ld->dev_force_privkey); @@ -1242,14 +1233,6 @@ static char *opt_set_splicing(struct lightningd *ld) return NULL; } -static char *opt_set_onion_messages(struct lightningd *ld) -{ - if (!opt_deprecated_ok(ld, "experimental-onion-messages", NULL, - "v24.08", "v25.02")) - return "--experimental-onion-message is now enabled by default"; - return NULL; -} - static char *opt_set_shutdown_wrong_funding(struct lightningd *ld) { feature_set_or(ld->our_features, @@ -1274,14 +1257,6 @@ static char *opt_set_quiesce(struct lightningd *ld) return NULL; } -static char *opt_set_anchor_zero_fee_htlc_tx(struct lightningd *ld) -{ - if (!opt_deprecated_ok(ld, "experimental-anchors", NULL, - "v24.02", "v25.02")) - return "--experimental-anchors is now enabled by default"; - return NULL; -} - static char *opt_set_offers(struct lightningd *ld) { if (!opt_deprecated_ok(ld, "experimental-offers", NULL, @@ -1461,9 +1436,6 @@ static void register_opts(struct lightningd *ld) " channels using splicing"); /* This affects our features, so set early. */ - opt_register_early_noarg("--experimental-onion-messages", - opt_set_onion_messages, ld, - opt_hidden); opt_register_early_noarg("--experimental-offers", opt_set_offers, ld, opt_hidden); @@ -1477,9 +1449,6 @@ static void register_opts(struct lightningd *ld) opt_set_quiesce, ld, "experimental: Advertise ability to quiesce" " channels."); - opt_register_early_noarg("--experimental-anchors", - opt_set_anchor_zero_fee_htlc_tx, ld, - opt_hidden); clnopt_noarg("--help|-h", OPT_EXITS, opt_lightningd_usage, ld, "Print this message."); @@ -1498,8 +1467,6 @@ static void register_opts(struct lightningd *ld) clnopt_witharg("--watchtime-blocks", OPT_SHOWINT, opt_set_u32, opt_show_u32, &ld->config.locktime_blocks, "Blocks before peer can unilaterally spend funds"); - opt_register_arg("--max-locktime-blocks", opt_set_max_htlc_cltv, NULL, - ld, opt_hidden); clnopt_witharg("--funding-confirms", OPT_SHOWINT, opt_set_u32, opt_show_u32, &ld->config.funding_confirms, "Confirmations required for funding transaction"); @@ -1844,48 +1811,8 @@ void handle_early_opts(struct lightningd *ld, int argc, char *argv[]) logging_options_parsed(ld->log_book); } -/* Free *str, set *str to copy with `cln` prepended */ -static void prefix_cln(char **str STEALS) -{ - char *newstr = tal_fmt(tal_parent(*str), "cln%s", *str); - tal_free(*str); - *str = newstr; -} - -/* Due to a conflict between the widely-deployed clightning-rest plugin and - * our own clnrest plugin, and people wanting to run both, in v23.11 we - * renamed some options. This breaks perfectly working v23.08 deployments who - * don't care about clightning-rest, so we work around it here. */ -static void fixup_clnrest_options(struct lightningd *ld) -{ - for (size_t i = 0; i < tal_count(ld->configvars); i++) { - struct configvar *cv = ld->configvars[i]; - - /* These worked for v23.08 */ - if (!strstarts(cv->configline, "rest-port=") - && !strstarts(cv->configline, "rest-protocol=") - && !strstarts(cv->configline, "rest-host=") - && !strstarts(cv->configline, "rest-certs=")) - continue; - /* Did some (plugin) claim it? */ - if (opt_find_long(cv->configline, cast_const2(const char **, &cv->optarg))) - continue; - if (!opt_deprecated_ok(ld, - tal_strndup(tmpctx, cv->configline, - strcspn(cv->configline, "=")), - "clnrest-prefix", - "v23.11", "v24.11")) - continue; - log_unusual(ld->log, "Option %s deprecated in v23.11, renaming to cln%s", - cv->configline, cv->configline); - prefix_cln(&cv->configline); - } -} - void handle_opts(struct lightningd *ld) { - fixup_clnrest_options(ld); - /* Now we know all the options, finish parsing and finish * populating ld->configvars with cmdline. */ parse_configvars_final(ld->configvars, true, ld->developer); diff --git a/plugins/commando.c b/plugins/commando.c index 1c1eea5cb27d..608e8dfe9284 100644 --- a/plugins/commando.c +++ b/plugins/commando.c @@ -711,79 +711,6 @@ static struct command_result *json_commando(struct command *cmd, return send_more_cmd(cmd, NULL, NULL, NULL, outgoing); } -/* Handles error or success */ -static struct command_result *forward_reply(struct command *cmd, - const char *method, - const char *buf, - const jsmntok_t *result, - void *arg) -{ - const jsmntok_t *err = json_get_member(buf, result, "error"); - if (err) - return forward_error(cmd, method, buf, err, arg); - return forward_result(cmd, method, buf, json_get_member(buf, result, "result"), arg); -} - -static struct command_result *forward_command(struct command *cmd, - const char *buffer, - const jsmntok_t *params, - const char *method) -{ - /* params could be an array, so use low-level helper */ - struct out_req *req; - - req = jsonrpc_request_whole_object_start(cmd, method, NULL, - forward_reply, NULL); - json_add_tok(req->js, "params", params, buffer); - return send_outreq(req); -} - -static struct command_result *json_commando_rune(struct command *cmd, - const char *buffer, - const jsmntok_t *params) -{ - const char *unused1, *unused2; - - /* param call needed to generate help messages */ - if (!param(cmd, buffer, params, - p_opt("rune", param_string, &unused1), - p_opt("restrictions", param_string, &unused2), - NULL)) - return command_param_failed(); - - return forward_command(cmd, buffer, params, "createrune"); -} - -static struct command_result *json_commando_blacklist(struct command *cmd, - const char *buffer, - const jsmntok_t *params) -{ - const char *unused1, *unused2; - - /* param call needed to generate help messages */ - if (!param(cmd, buffer, params, - p_opt("start", param_string, &unused1), - p_opt("end", param_string, &unused2), - NULL)) - return command_param_failed(); - - return forward_command(cmd, buffer, params, "blacklistrune"); -} - -static struct command_result *json_commando_listrunes(struct command *cmd, - const char *buffer, - const jsmntok_t *params) -{ - const char *unused; - - /* param call needed to generate help messages */ - if (!param(cmd, buffer, params, - p_opt("rune", param_string, &unused), NULL)) - return command_param_failed(); - - return forward_command(cmd, buffer, params, "showrunes"); -} - static void memleak_mark_globals(struct plugin *p, struct htable *memtable) { memleak_scan_obj(memtable, outgoing_commands); @@ -804,23 +731,6 @@ static const char *init(struct command *init_cmd, static const struct plugin_command commands[] = { { "commando", json_commando, - }, { - "commando-rune", - json_commando_rune, - "v23.08", - "v25.02", - }, - { - "commando-listrunes", - json_commando_listrunes, - "v23.08", - "v25.02", - }, - { - "commando-blacklist", - json_commando_blacklist, - "v23.08", - "v25.02", }, }; diff --git a/tests/autogenerate-rpc-examples.py b/tests/autogenerate-rpc-examples.py index 52a0555f6e81..e5fcb477832f 100644 --- a/tests/autogenerate-rpc-examples.py +++ b/tests/autogenerate-rpc-examples.py @@ -33,9 +33,7 @@ EXAMPLES_JSON = {} LOG_FILE = './tests/autogenerate-examples-status.log' TEMP_EXAMPLES_FILE = './tests/autogenerate-examples.json' -IGNORE_RPCS_LIST = ['dev-splice', 'reckless', 'sql-template', - # Deprecated, pending complete removal - 'commando-rune', 'commando-listrunes', 'commando-blacklist'] +IGNORE_RPCS_LIST = ['dev-splice', 'reckless', 'sql-template'] # Constants for replacing values in examples NEW_VALUES_LIST = { diff --git a/tests/test_clnrest.py b/tests/test_clnrest.py index f38f8555e5e1..ea2f65ba364a 100644 --- a/tests/test_clnrest.py +++ b/tests/test_clnrest.py @@ -1,7 +1,6 @@ from fixtures import * # noqa: F401,F403 from pyln.testing.utils import TEST_NETWORK, wait_for from pyln.client import Millisatoshi -import os import requests from pathlib import Path from requests.adapters import HTTPAdapter @@ -469,43 +468,6 @@ def test_http_headers(node_factory): assert response.headers['Access-Control-Allow-Origin'] == 'http://192.168.1.10:1010' -def test_old_params(node_factory): - """Test that we handle the v23.08-style parameters""" - rest_port = str(node_factory.get_unused_port()) - rest_host = '127.0.0.1' - base_url = f'https://{rest_host}:{rest_port}' - l1 = node_factory.get_node(options={'rest-port': rest_port, - 'rest-host': rest_host, - 'allow-deprecated-apis': True, - 'i-promise-to-fix-broken-api-user': ['rest-port.clnrest-prefix', 'rest-host.clnrest-prefix']}, - broken_log=r'DEPRECATED API USED rest-*') - - # This might happen really early! - l1.daemon.logsearch_start = 0 - l1.daemon.wait_for_logs([r'UNUSUAL lightningd: Option rest-port=.* deprecated in v23\.11, renaming to clnrest-port', - r'UNUSUAL lightningd: Option rest-host=.* deprecated in v23\.11, renaming to clnrest-host']) - l1.daemon.wait_for_log(r'plugin-clnrest: REST server running at ' + base_url) - - # Now try one where a plugin (e.g. clightning-rest) registers the option. - plugin = os.path.join(os.path.dirname(__file__), 'plugins/clnrest-use-options.py') - l2 = node_factory.get_node(options={'rest-port': rest_port, - 'rest-host': rest_host, - 'plugin': plugin, - 'allow-deprecated-apis': True, - 'i-promise-to-fix-broken-api-user': ['rest-port.clnrest-prefix', 'rest-host.clnrest-prefix']}, - broken_log=r'DEPRECATED API USED rest-*') - - l2.daemon.logsearch_start = 0 - # We still rename this one, since it's for clnrest. - assert l2.daemon.is_in_log(r'UNUSUAL lightningd: Option rest-host=.* deprecated in v23\.11, renaming to clnrest-host') - - # This one does not get renamed! - assert not l2.daemon.is_in_log(r'UNUSUAL lightningd: Option rest-port=.* deprecated in v23\.11, renaming to clnrest-host') - assert [p for p in l2.rpc.plugin('list')['plugins'] if p['name'].endswith('clnrest')] == [] - assert l2.daemon.is_in_log(r'plugin-clnrest: Killing plugin: disabled itself at init: `clnrest-port` option is not configured') - assert l2.daemon.is_in_log(rf'clnrest-use-options.py: rest-port is {rest_port}') - - def test_websocket_upgrade_header(node_factory): """Test that not setting an upgrade header leads to rejection""" # start a node with clnrest diff --git a/tests/test_plugin.py b/tests/test_plugin.py index 5d9e58673f1c..761d82df2ce4 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -14,7 +14,6 @@ ) import ast -import base64 import json import os import pytest @@ -2797,324 +2796,6 @@ def test_commando(node_factory, executor): assert exc_info.value.error['data']['erring_index'] == 0 -def test_commando_rune(node_factory): - l1, l2 = node_factory.line_graph(2, fundchannel=False, opts={ - 'i-promise-to-fix-broken-api-user': 'commando-rune' - }) - - rune1 = l1.rpc.commando_rune() - assert rune1['rune'] == 'OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==' - assert rune1['unique_id'] == '0' - rune2 = l1.rpc.commando_rune(restrictions="readonly") - assert rune2['rune'] == 'zm0x_eLgHexaTvZn3Cz7gb_YlvrlYGDo_w4BYlR9SS09MSZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl' - assert rune2['unique_id'] == '1' - rune3 = l1.rpc.commando_rune(restrictions=[["time>1656675211"]]) - assert rune3['rune'] == 'mxHwVsC_W-PH7r79wXQWqxBNHaHncIqIjEPyP_vGOsE9MiZ0aW1lPjE2NTY2NzUyMTE=' - assert rune3['unique_id'] == '2' - rune4 = l1.rpc.commando_rune(restrictions=[["id^022d223620a359a47ff7"], ["method=listpeers"]]) - assert rune4['rune'] == 'YPojv9qgHPa3im0eiqRb-g8aRq76OasyfltGGqdFUOU9MyZpZF4wMjJkMjIzNjIwYTM1OWE0N2ZmNyZtZXRob2Q9bGlzdHBlZXJz' - assert rune4['unique_id'] == '3' - rune5 = l1.rpc.commando_rune(rune4['rune'], [["pnamelevel!", "pnamelevel/io"]]) - assert rune5['rune'] == 'Zm7A2mKkLnd5l6Er_OMAHzGKba97ij8lA-MpNYMw9nk9MyZpZF4wMjJkMjIzNjIwYTM1OWE0N2ZmNyZtZXRob2Q9bGlzdHBlZXJzJnBuYW1lbGV2ZWwhfHBuYW1lbGV2ZWwvaW8=' - assert rune5['unique_id'] == '3' - rune6 = l1.rpc.commando_rune(rune5['rune'], [["parr1!", "parr1/io"]]) - assert rune6['rune'] == 'm_tyR0qqHUuLEbFJW6AhmBg-9npxVX2yKocQBFi9cvY9MyZpZF4wMjJkMjIzNjIwYTM1OWE0N2ZmNyZtZXRob2Q9bGlzdHBlZXJzJnBuYW1lbGV2ZWwhfHBuYW1lbGV2ZWwvaW8mcGFycjEhfHBhcnIxL2lv' - assert rune6['unique_id'] == '3' - rune7 = l1.rpc.commando_rune(restrictions=[["pnum=0"]]) - assert rune7['rune'] == 'enX0sTpHB8y1ktyTAF80CnEvGetG340Ne3AGItudBS49NCZwbnVtPTA=' - assert rune7['unique_id'] == '4' - rune8 = l1.rpc.commando_rune(rune7['rune'], [["rate=3"]]) - assert rune8['rune'] == '_h2eKjoK7ITAF-JQ1S5oum9oMQesrz-t1FR9kDChRB49NCZwbnVtPTAmcmF0ZT0z' - assert rune8['unique_id'] == '4' - rune9 = l1.rpc.commando_rune(rune8['rune'], [["rate=1"]]) - assert rune9['rune'] == 'U1GDXqXRvfN1A4WmDVETazU9YnvMsDyt7WwNzpY0khE9NCZwbnVtPTAmcmF0ZT0zJnJhdGU9MQ==' - assert rune9['unique_id'] == '4' - - # Test rune with \|. - weirdrune = l1.rpc.commando_rune(restrictions=[["method=invoice"], - ["pnamedescription=@tipjar|jb55@sendsats.lol"]]) - with pytest.raises(RpcError, match='Invalid rune: Not permitted: pnamedescription is not equal to @tipjar|jb55@sendsats.lol'): - l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': weirdrune['rune'], - 'method': 'invoice', - 'params': {"amount_msat": "any", - "label": "lbl", - "description": "@tipjar\\|jb55@sendsats.lol"}}) - l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': weirdrune['rune'], - 'method': 'invoice', - 'params': {"amount_msat": "any", - "label": "lbl", - "description": "@tipjar|jb55@sendsats.lol"}}) - - runedecodes = ((rune1, []), - (rune2, [{'alternatives': ['method^list', 'method^get', 'method=summary'], - 'summary': "method (of command) starts with 'list' OR method (of command) starts with 'get' OR method (of command) equal to 'summary'"}, - {'alternatives': ['method/listdatastore'], - 'summary': "method (of command) unequal to 'listdatastore'"}]), - (rune4, [{'alternatives': ['id^022d223620a359a47ff7'], - 'summary': "id (of commanding peer) starts with '022d223620a359a47ff7'"}, - {'alternatives': ['method=listpeers'], - 'summary': "method (of command) equal to 'listpeers'"}]), - (rune5, [{'alternatives': ['id^022d223620a359a47ff7'], - 'summary': "id (of commanding peer) starts with '022d223620a359a47ff7'"}, - {'alternatives': ['method=listpeers'], - 'summary': "method (of command) equal to 'listpeers'"}, - {'alternatives': ['pnamelevel!', 'pnamelevel/io'], - 'summary': "pnamelevel (object parameter 'level') is missing OR pnamelevel (object parameter 'level') unequal to 'io'"}]), - (rune6, [{'alternatives': ['id^022d223620a359a47ff7'], - 'summary': "id (of commanding peer) starts with '022d223620a359a47ff7'"}, - {'alternatives': ['method=listpeers'], - 'summary': "method (of command) equal to 'listpeers'"}, - {'alternatives': ['pnamelevel!', 'pnamelevel/io'], - 'summary': "pnamelevel (object parameter 'level') is missing OR pnamelevel (object parameter 'level') unequal to 'io'"}, - {'alternatives': ['parr1!', 'parr1/io'], - 'summary': "parr1 (array parameter #1) is missing OR parr1 (array parameter #1) unequal to 'io'"}]), - (rune7, [{'alternatives': ['pnum=0'], - 'summary': "pnum (number of command parameters) equal to 0"}])) - for decode in runedecodes: - rune = decode[0] - restrictions = decode[1] - decoded = l1.rpc.decode(rune['rune']) - assert decoded['type'] == 'rune' - assert decoded['unique_id'] == rune['unique_id'] - assert decoded['valid'] is True - assert decoded['restrictions'] == restrictions - - # Time handling is a bit special, since we annotate the timestamp with how far away it is. - decoded = l1.rpc.decode(rune3['rune']) - assert decoded['type'] == 'rune' - assert decoded['unique_id'] == rune3['unique_id'] - assert decoded['valid'] is True - assert len(decoded['restrictions']) == 1 - assert decoded['restrictions'][0]['alternatives'] == ['time>1656675211'] - assert decoded['restrictions'][0]['summary'].startswith("time (in seconds since 1970) greater than 1656675211 (") - - # Replace rune3 with a more useful timestamp! - expiry = int(time.time()) + 15 - rune3 = l1.rpc.commando_rune(restrictions=[["time<{}".format(expiry)]]) - - successes = ((rune1, "listpeers", {}), - (rune2, "listpeers", {}), - (rune2, "getinfo", {}), - (rune2, "getinfo", {}), - (rune3, "getinfo", {}), - (rune4, "listpeers", {}), - (rune5, "listpeers", {'id': l2.info['id']}), - (rune5, "listpeers", {'id': l2.info['id'], 'level': 'broken'}), - (rune6, "listpeers", [l2.info['id'], 'broken']), - (rune6, "listpeers", [l2.info['id']]), - (rune7, "listpeers", []), - (rune7, "getinfo", {})) - - failures = ((rune2, "withdraw", {}), - (rune2, "plugin", {'subcommand': 'list'}), - (rune3, "getinfo", {}), - (rune4, "listnodes", {}), - (rune5, "listpeers", {'id': l2.info['id'], 'level': 'io'}), - (rune6, "listpeers", [l2.info['id'], 'io']), - (rune7, "listpeers", [l2.info['id']]), - (rune7, "listpeers", {'id': l2.info['id']})) - - for rune, cmd, params in successes: - l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune['rune'], - 'method': cmd, - 'params': params}) - - while time.time() < expiry: - time.sleep(1) - - for rune, cmd, params in failures: - with pytest.raises(RpcError, match='Invalid rune: Not permitted:') as exc_info: - l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune['rune'], - 'method': cmd, - 'params': params}) - assert exc_info.value.error['code'] == 0x4c51 - - -def test_commando_listrunes(node_factory): - l1 = node_factory.get_node(options={'i-promise-to-fix-broken-api-user': ['commando-rune', 'commando-listrunes']}) - rune = l1.rpc.commando_rune() - assert rune == { - 'rune': 'OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==', - 'unique_id': '0', - 'warning_unrestricted_rune': 'WARNING: This rune has no restrictions! Anyone who has access to this rune could drain funds from your node. Be careful when giving this to apps that you don\'t trust. Consider using the restrictions parameter to only allow access to specific rpc methods.' - } - listrunes = l1.rpc.commando_listrunes() - assert len(l1.rpc.commando_listrunes()) == 1 - rune = l1.rpc.commando_rune() - listrunes = l1.rpc.commando_listrunes() - assert len(listrunes['runes']) == 2 - assert listrunes == { - 'runes': [ - { - 'rune': 'OSqc7ixY6F-gjcigBfxtzKUI54uzgFSA6YfBQoWGDV89MA==', - 'unique_id': '0', - 'restrictions': [], - 'restrictions_as_english': '' - }, - { - 'rune': 'geZmO6U7yqpHn-moaX93FVMVWrDRfSNY4AXx9ypLcqg9MQ==', - 'unique_id': '1', - 'restrictions': [], - 'restrictions_as_english': '' - } - ] - } - our_unstored_rune = l1.rpc.commando_listrunes(rune='M8f4jNx9gSP2QoiRbr10ybwzFxUgd-rS4CR4yofMSuA9Mg==')['runes'][0] - assert our_unstored_rune['stored'] is False - - our_unstored_rune = l1.rpc.commando_listrunes(rune='m_tyR0qqHUuLEbFJW6AhmBg-9npxVX2yKocQBFi9cvY9MyZpZF4wMjJkMjIzNjIwYTM1OWE0N2ZmNyZtZXRob2Q9bGlzdHBlZXJzJnBuYW1lbGV2ZWwhfHBuYW1lbGV2ZWwvaW8mcGFycjEhfHBhcnIxL2lv')['runes'][0] - assert our_unstored_rune['stored'] is False - - not_our_rune = l1.rpc.commando_listrunes(rune='Am3W_wI0PRn4qVNEsJ2iInHyFPQK8wfdqEXztm8-icQ9MA==')['runes'][0] - assert not_our_rune['stored'] is False - assert not_our_rune['our_rune'] is False - - -def test_commando_rune_pay_amount(node_factory): - l1, l2 = node_factory.line_graph(2, opts={ - 'i-promise-to-fix-broken-api-user': 'commando-rune' - }) - - # This doesn't really work, since amount_msat is illegal if invoice - # includes an amount, and runes aren't smart enough to decode bolt11! - rune = l1.rpc.commando_rune(restrictions=[['method=pay'], - ['pnameamountmsat<10000']])['rune'] - inv1 = l2.rpc.invoice(amount_msat=12300, label='inv1', description='description1')['bolt11'] - inv2 = l2.rpc.invoice(amount_msat='any', label='inv2', description='description2')['bolt11'] - - # Rune requires amount_msat! - with pytest.raises(RpcError, match='Invalid rune: Not permitted: parameter amountmsat not present'): - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params={'bolt11': inv1}) - - # As a named parameter! - with pytest.raises(RpcError, match='Invalid rune: Not permitted: parameter amountmsat not present'): - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params=[inv1]) - - # Can't get around it this way! - with pytest.raises(RpcError, match='Invalid rune: Not permitted: parameter amountmsat not present'): - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params=[inv2, 12000]) - - # Nor this way, using a string! - with pytest.raises(RpcError, match='Invalid rune: Not permitted: parameter amountmsat is not an integer field'): - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params={'bolt11': inv2, 'amount_msat': '10000sat'}) - - # Too much! - with pytest.raises(RpcError, match='Invalid rune: Not permitted: parameter amountmsat is greater or equal to 10000'): - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params={'bolt11': inv2, 'amount_msat': 12000}) - - # This works - l2.rpc.commando(peer_id=l1.info['id'], - rune=rune, - method='pay', - params={'bolt11': inv2, 'amount_msat': 9999}) - - -def test_commando_blacklist(node_factory): - l1, l2 = node_factory.get_nodes(2, opts={ - 'i-promise-to-fix-broken-api-user': ['commando-rune', 'commando-blacklist', 'commando-listrunes'] - }) - - l2.connect(l1) - rune0 = l1.rpc.commando_rune() - assert rune0['unique_id'] == '0' - rune1 = l1.rpc.commando_rune() - assert rune1['unique_id'] == '1' - - # Make sure runes work! - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune0['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune1['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - blacklist = l1.rpc.commando_blacklist(start=1) - assert blacklist == {'blacklist': [{'start': 1, 'end': 1}]} - - # Make sure rune id 1 does not work! - with pytest.raises(RpcError, match='Not authorized: Blacklisted rune'): - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune1['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - # But, other rune still works! - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune0['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - blacklist = l1.rpc.commando_blacklist(start=2) - assert blacklist == {'blacklist': [{'start': 1, 'end': 2}]} - - blacklist = l1.rpc.commando_blacklist(start=6) - assert blacklist == {'blacklist': [{'start': 1, 'end': 2}, - {'start': 6, 'end': 6}]} - - blacklist = l1.rpc.commando_blacklist(start=3, end=5) - assert blacklist == {'blacklist': [{'start': 1, 'end': 6}]} - - blacklist = l1.rpc.commando_blacklist(start=9) - assert blacklist == {'blacklist': [{'start': 1, 'end': 6}, - {'start': 9, 'end': 9}]} - - blacklist = l1.rpc.commando_blacklist(start=0) - assert blacklist == {'blacklist': [{'start': 0, 'end': 6}, - {'start': 9, 'end': 9}]} - - # Now both runes fail! - with pytest.raises(RpcError, match='Not authorized: Blacklisted rune'): - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune0['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - with pytest.raises(RpcError, match='Not authorized: Blacklisted rune'): - assert l2.rpc.call(method='commando', - payload={'peer_id': l1.info['id'], - 'rune': rune1['rune'], - 'method': 'getinfo', - 'params': []})['id'] == l1.info['id'] - - blacklist = l1.rpc.commando_blacklist() - assert blacklist == {'blacklist': [{'start': 0, 'end': 6}, - {'start': 9, 'end': 9}]} - - blacklisted_rune = l1.rpc.commando_listrunes(rune='geZmO6U7yqpHn-moaX93FVMVWrDRfSNY4AXx9ypLcqg9MQ==')['runes'][0]['blacklisted'] - assert blacklisted_rune is True - - @pytest.mark.slow_test def test_commando_stress(node_factory, executor): """Stress test to slam commando with many large queries""" @@ -3152,26 +2833,6 @@ def test_commando_stress(node_factory, executor): assert not nodes[0].daemon.is_in_log(r"New cmd from .*, replacing old") -def test_commando_badrune(node_factory): - """Test invalid UTF-8 encodings in rune: used to make us kill the offers plugin which implements decode, as it gave bad utf8!""" - l1 = node_factory.get_node(options={'i-promise-to-fix-broken-api-user': 'commando-rune'}) - - l1.rpc.decode('5zi6-ugA6hC4_XZ0R7snl5IuiQX4ugL4gm9BQKYaKUU9gCZtZXRob2RebGlzdHxtZXRob2ReZ2V0fG1ldGhvZD1zdW1tYXJ5Jm1ldGhvZC9saXN0ZGF0YXN0b3Jl') - rune = l1.rpc.commando_rune(restrictions="readonly") - - binrune = base64.urlsafe_b64decode(rune['rune']) - # Mangle each part, try decode. Skip most of the boring chars - # (just '|', '&', '#'). - for i in range(32, len(binrune)): - for span in (range(0, 32), (124, 38, 35), range(127, 256)): - for c in span: - modrune = binrune[:i] + bytes([c]) + binrune[i + 1:] - try: - l1.rpc.decode(base64.urlsafe_b64encode(modrune).decode('utf8')) - except RpcError: - pass - - def test_autoclean(node_factory): l1, l2, l3 = node_factory.line_graph(3, opts={'may_reconnect': True}, wait_for_announce=True)