From ee00f84fed9b4ca6375ebcd4ecbeaecbdb9dea92 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 2 Feb 2024 14:54:54 +1030 Subject: [PATCH] JSON: don't return a raw result string for "stop" and "recover". In general, results should always be an object, so we can add new fields later (e.g. warnings!). But we violated this for "stop", and when "recover" used the same infrastructure, it started doing the same thing. I'm assuming nobody cares, so we don't need to do a deprecation cycle. Changelog-Changed: JSON-RPC: `stop` and `recover` now return a JSON object (not a raw string!) like every other command does. Signed-off-by: Rusty Russell --- .msggen.json | 10 +++++++ cln-grpc/proto/node.proto | 5 ++++ cln-grpc/src/convert.rs | 1 + cln-rpc/src/model.rs | 26 +++++++++++++++++++ contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py | 1 + .../pyln/grpc/primitives_pb2.py | 1 + contrib/pyln-testing/pyln/testing/grpc2py.py | 1 + doc/lightning-stop.7.md | 7 +++-- doc/schemas/stop.schema.json | 18 ++++++++++--- lightningd/jsonrpc.c | 5 ++-- 10 files changed, 67 insertions(+), 8 deletions(-) diff --git a/.msggen.json b/.msggen.json index c6265fc81..08001d78e 100644 --- a/.msggen.json +++ b/.msggen.json @@ -334,6 +334,9 @@ "complete": 1, "pending": 0 }, + "StopResult": { + "Shutdown complete": 0 + }, "WaitIndexname": { "created": 0, "deleted": 2, @@ -1687,6 +1690,9 @@ "StaticbackupResponse": { "StaticBackup.scb[]": 1 }, + "StopResponse": { + "Stop.result": 1 + }, "TxdiscardRequest": { "TxDiscard.txid": 1 }, @@ -5982,6 +5988,10 @@ "added": "pre-v0.10.1", "deprecated": null }, + "Stop.result": { + "added": "v24.05", + "deprecated": false + }, "TxDiscard": { "added": "pre-v0.10.1", "deprecated": null diff --git a/cln-grpc/proto/node.proto b/cln-grpc/proto/node.proto index b8dba61dd..a2afa82d1 100644 --- a/cln-grpc/proto/node.proto +++ b/cln-grpc/proto/node.proto @@ -1951,6 +1951,11 @@ message StopRequest { } message StopResponse { + // Stop.result + enum StopResult { + SHUTDOWN_COMPLETE = 0; + } + optional StopResult result = 1; } message PreapprovekeysendRequest { diff --git a/cln-grpc/src/convert.rs b/cln-grpc/src/convert.rs index 5fdd39205..10d603990 100644 --- a/cln-grpc/src/convert.rs +++ b/cln-grpc/src/convert.rs @@ -1825,6 +1825,7 @@ impl From for pb::WaitResponse { impl From for pb::StopResponse { fn from(c: responses::StopResponse) -> Self { Self { + result: c.result.map(|v| v as i32), } } } diff --git a/cln-rpc/src/model.rs b/cln-rpc/src/model.rs index 4dd6f404e..e5c83d3ba 100644 --- a/cln-rpc/src/model.rs +++ b/cln-rpc/src/model.rs @@ -5951,8 +5951,34 @@ pub mod responses { } } + #[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] + pub enum StopResult { + #[serde(rename = "Shutdown complete")] + SHUTDOWN_COMPLETE, + } + + impl TryFrom for StopResult { + type Error = anyhow::Error; + fn try_from(c: i32) -> Result { + match c { + 0 => Ok(StopResult::SHUTDOWN_COMPLETE), + o => Err(anyhow::anyhow!("Unknown variant {} for enum StopResult", o)), + } + } + } + + impl ToString for StopResult { + fn to_string(&self) -> String { + match self { + StopResult::SHUTDOWN_COMPLETE => "SHUTDOWN_COMPLETE", + }.to_string() + } + } + #[derive(Clone, Debug, Deserialize, Serialize)] pub struct StopResponse { + #[serde(skip_serializing_if = "Option::is_none")] + pub result: Option, } impl TryFrom for StopResponse { diff --git a/contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py b/contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py index 02d56edc5..49c5cf315 100644 --- a/contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py +++ b/contrib/pyln-grpc-proto/pyln/grpc/node_pb2.py @@ -20,6 +20,7 @@ _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'node_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None _globals['_GETINFOREQUEST']._serialized_start=37 _globals['_GETINFOREQUEST']._serialized_end=53 diff --git a/contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py b/contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py index c0ce0d478..72544a2af 100644 --- a/contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py +++ b/contrib/pyln-grpc-proto/pyln/grpc/primitives_pb2.py @@ -19,6 +19,7 @@ _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'primitives_pb2', _globals) if _descriptor._USE_C_DESCRIPTORS == False: + DESCRIPTOR._options = None _globals['_CHANNELSIDE']._serialized_start=718 _globals['_CHANNELSIDE']._serialized_end=754 diff --git a/contrib/pyln-testing/pyln/testing/grpc2py.py b/contrib/pyln-testing/pyln/testing/grpc2py.py index 5d94587c4..5ba5bc5d3 100644 --- a/contrib/pyln-testing/pyln/testing/grpc2py.py +++ b/contrib/pyln-testing/pyln/testing/grpc2py.py @@ -1515,6 +1515,7 @@ def wait2py(m): def stop2py(m): return remove_default({ + "result": str(m.result), # EnumField in generate_composite }) diff --git a/doc/lightning-stop.7.md b/doc/lightning-stop.7.md index 874d2422d..00f4ffd15 100644 --- a/doc/lightning-stop.7.md +++ b/doc/lightning-stop.7.md @@ -25,7 +25,10 @@ RETURN VALUE ------------ [comment]: # (GENERATE-FROM-SCHEMA-START) -On success, returns a single element (string) (always "Shutdown complete") +On success, an object is returned, containing: + +- **result** (string) (always "Shutdown complete") *(added v24.05)* + [comment]: # (GENERATE-FROM-SCHEMA-END) Once it has returned, the daemon has cleaned up completely, and if @@ -43,4 +46,4 @@ RESOURCES Main web site: -[comment]: # ( SHA256STAMP:d070207640745cfc9b9ba26e5d023e96a3befcdde9a2c9b17d48d46dafb460f9) +[comment]: # ( SHA256STAMP:879e99c76bb615e2c7f7356ff24b748ef42ff11cf692d1f199c60aacf9c09e0b) diff --git a/doc/schemas/stop.schema.json b/doc/schemas/stop.schema.json index 00105c743..cad72d8f6 100644 --- a/doc/schemas/stop.schema.json +++ b/doc/schemas/stop.schema.json @@ -1,7 +1,17 @@ { "$schema": "http://json-schema.org/draft-07/schema#", - "type": "string", - "enum": [ - "Shutdown complete" - ] + "type": "object", + "additionalProperties": false, + "required": [ + "result" + ], + "properties": { + "result": { + "type": "string", + "added": "v24.05", + "enum": [ + "Shutdown complete" + ] + } + } } diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index 48d4e1673..b3ce25a41 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -213,16 +213,17 @@ static struct command_result *prepare_stop_conn(struct command *cmd, cmd->ld->stop_conn = cmd->jcon->conn; - /* This is the one place where result is a literal string. */ jout = json_out_new(tmpctx); json_out_start(jout, NULL, '{'); json_out_addstr(jout, "jsonrpc", "2.0"); /* Copy input id token exactly */ memcpy(json_out_member_direct(jout, "id", strlen(cmd->id)), cmd->id, strlen(cmd->id)); + json_out_start(jout, "result", '{'); json_out_addstr(jout, "result", why); json_out_end(jout, '}'); - json_out_finished(jout); + json_out_end(jout, '}'); + json_out_finished(jout); /* Add two \n */ memcpy(json_out_direct(jout, 2), "\n\n", strlen("\n\n"));