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 c6265fc81b..08001d78e2 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 b8dba61dd5..a2afa82d1b 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 5fdd392050..10d6039902 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 4dd6f404e0..e5c83d3bad 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 02d56edc51..49c5cf315d 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 c0ce0d4784..72544a2af6 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 5d94587c43..5ba5bc5d31 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 874d2422dd..00f4ffd15b 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 00105c7438..cad72d8f63 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 48d4e16736..b3ce25a418 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"));