Skip to content

Commit 98ba9eb

Browse files
adi2011sangbida
authored andcommitted
chanbackup: make getemergencyrecoverdata rpc more verbose
Adding more information to geremergencyrecoverdata, to let users know if they are using legacy file format and the list of all the backed up channel ids. Key Changes: - Added: 1. can_create_penalty: To let user know if they need to update the file. 2. backed_up_channel_ids: List of all the backed up channels Changelog-Changed: Made getemergencyrecoverdata more verbose.
1 parent 8c2821e commit 98ba9eb

10 files changed

Lines changed: 1284 additions & 1224 deletions

File tree

.msggen.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,8 @@
20522052
"FundPsbt.reservations[]": 6
20532053
},
20542054
"GetemergencyrecoverdataResponse": {
2055+
"GetEmergencyRecoverData.backed_up_channel_ids[]": 3,
2056+
"GetEmergencyRecoverData.can_create_penalty": 2,
20552057
"GetEmergencyRecoverData.filedata": 1
20562058
},
20572059
"GetinfoAddress": {
@@ -8269,6 +8271,14 @@
82698271
"added": "v24.11",
82708272
"deprecated": null
82718273
},
8274+
"GetEmergencyRecoverData.backed_up_channel_ids[]": {
8275+
"added": "v24.11",
8276+
"deprecated": null
8277+
},
8278+
"GetEmergencyRecoverData.can_create_penalty": {
8279+
"added": "v24.11",
8280+
"deprecated": null
8281+
},
82728282
"GetEmergencyRecoverData.filedata": {
82738283
"added": "v24.11",
82748284
"deprecated": null

cln-grpc/proto/node.proto

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

cln-grpc/src/convert.rs

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

cln-rpc/src/model.rs

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

contrib/msggen/msggen/schema.json

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14678,7 +14678,9 @@
1467814678
},
1467914679
"response": {
1468014680
"required": [
14681-
"filedata"
14681+
"filedata",
14682+
"can_create_penalty",
14683+
"backed_up_channel_ids"
1468214684
],
1468314685
"additionalProperties": false,
1468414686
"properties": {
@@ -14687,6 +14689,21 @@
1468714689
"description": [
1468814690
"The raw, hex-encoded, emergency.recover file"
1468914691
]
14692+
},
14693+
"can_create_penalty": {
14694+
"type": "boolean",
14695+
"description": [
14696+
"If false, you are using legacy file version, which can not create penalty transactions, kindly delete emergency.recover and restart the node!"
14697+
]
14698+
},
14699+
"backed_up_channel_ids": {
14700+
"type": "array",
14701+
"items": {
14702+
"type": "hash",
14703+
"description": [
14704+
"Channel IDs of channels backed up inside emergency.recover"
14705+
]
14706+
}
1469014707
}
1469114708
}
1469214709
},

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

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

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ def emergencyrecover2py(m):
456456

457457
def getemergencyrecoverdata2py(m):
458458
return remove_default({
459+
"backed_up_channel_ids": [hexlify(m.backed_up_channel_ids) for i in hexlify(m.backed_up_channel_ids)], # ArrayField[primitive] in generate_composite
460+
"can_create_penalty": m.can_create_penalty, # PrimitiveField in generate_composite
459461
"filedata": hexlify(m.filedata), # PrimitiveField in generate_composite
460462
})
461463

doc/schemas/getemergencyrecoverdata.json

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
},
1515
"response": {
1616
"required": [
17-
"filedata"
17+
"filedata",
18+
"can_create_penalty",
19+
"backed_up_channel_ids"
1820
],
1921
"additionalProperties": false,
2022
"properties": {
@@ -23,6 +25,21 @@
2325
"description": [
2426
"The raw, hex-encoded, emergency.recover file"
2527
]
28+
},
29+
"can_create_penalty": {
30+
"type": "boolean",
31+
"description": [
32+
"If false, you are using legacy file version, which can not create penalty transactions, kindly delete emergency.recover and restart the node!"
33+
]
34+
},
35+
"backed_up_channel_ids": {
36+
"type": "array",
37+
"items": {
38+
"type": "hash",
39+
"description": [
40+
"Channel IDs of channels backed up inside emergency.recover"
41+
]
42+
}
2643
}
2744
}
2845
},

plugins/chanbackup.c

Lines changed: 79 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,42 @@ static struct modern_scb_chan *convert_from_legacy(const tal_t *ctx, struct lega
318318
return modern_scb_tlv;
319319
}
320320

321+
/* Reads WIRE_STATIC_CHAN_BACKUP and converts from legacy_scb_chan to
322+
* modern_scb_chan, if required. */
323+
static bool read_static_chan_backup(struct command *cmd,
324+
const u8 *blob,
325+
u64 *version,
326+
u32 *timestamp,
327+
struct modern_scb_chan ***scb_tlvs,
328+
bool *is_converted)
329+
{
330+
bool is_tlvs = false;
331+
struct legacy_scb_chan **scb;
332+
333+
if (!fromwire_static_chan_backup(cmd,
334+
blob,
335+
version,
336+
timestamp,
337+
&scb)) {
338+
is_tlvs = true;
339+
if (!fromwire_static_chan_backup_with_tlvs(cmd,
340+
blob,
341+
version,
342+
timestamp,
343+
scb_tlvs)) {
344+
return false;
345+
}
346+
}
347+
*is_converted = !is_tlvs;
348+
if (!is_tlvs) {
349+
*scb_tlvs = tal_count(scb) ? tal_arr(cmd, struct modern_scb_chan *, tal_count(scb)): NULL;
350+
for (size_t i=0; i < tal_count(scb); i++){
351+
(*scb_tlvs)[i] = convert_from_legacy(cmd, scb[i]);
352+
}
353+
}
354+
return true;
355+
}
356+
321357
/* Recovers the channels by making RPC to `recoverchannel` */
322358
static struct command_result *json_emergencyrecover(struct command *cmd,
323359
const char *buf,
@@ -326,28 +362,16 @@ static struct command_result *json_emergencyrecover(struct command *cmd,
326362
struct out_req *req;
327363
u64 version;
328364
u32 timestamp;
329-
struct legacy_scb_chan **scb;
365+
bool is_converted;
330366
struct modern_scb_chan **scb_tlvs;
331367

332368
if (!param(cmd, buf, params, NULL))
333369
return command_param_failed();
334370

335371
u8 *res = decrypt_scb(cmd->plugin);
336-
bool is_tlvs = false;
337-
if (!fromwire_static_chan_backup(cmd,
338-
res,
339-
&version,
340-
&timestamp,
341-
&scb)) {
342-
if(!fromwire_static_chan_backup_with_tlvs(cmd,
343-
res,
344-
&version,
345-
&timestamp,
346-
&scb_tlvs)) {
347-
plugin_err(cmd->plugin, "Corrupted SCB!");
348-
}
349-
is_tlvs = true;
350-
}
372+
if (!read_static_chan_backup(cmd, res, &version, &timestamp, &scb_tlvs, &is_converted))
373+
return command_fail(cmd, LIGHTNINGD,
374+
"Invalid recovery format");
351375

352376
if ((version & 0x5555555555555555ULL) != (VERSION & 0x5555555555555555ULL)) {
353377
plugin_err(cmd->plugin,
@@ -358,26 +382,18 @@ static struct command_result *json_emergencyrecover(struct command *cmd,
358382
after_recover_rpc,
359383
forward_error, NULL);
360384

361-
json_array_start(req->js, "scb");
362-
if (is_tlvs) {
363-
for (size_t i=0; i<tal_count(scb_tlvs); i++) {
364-
u8 *scb_hex = tal_arr(cmd, u8, 0);
365-
towire_modern_scb_chan(&scb_hex,scb_tlvs[i]);
366-
json_add_hex_talarr(req->js, NULL, scb_hex);
367-
}
368-
} else {
385+
if (is_converted) {
369386
plugin_notify_message(cmd, LOG_DBG, "Processing legacy emergency.recover file format. "
370-
"Please migrate to the latest file format for improved "
371-
"compatibility and fund recovery.");
372-
373-
for (size_t i=0; i<tal_count(scb); i++) {
374-
u8 *scb_hex = tal_arr(cmd, u8, 0);
375-
struct modern_scb_chan *tmp_scb = convert_from_legacy(cmd, scb[i]);
376-
towire_modern_scb_chan(&scb_hex, tmp_scb);
377-
json_add_hex_talarr(req->js, NULL, scb_hex);
378-
}
387+
"Please migrate to the latest file format for improved "
388+
"compatibility and fund recovery.");
379389
}
380390

391+
json_array_start(req->js, "scb");
392+
for (size_t i=0; i<tal_count(scb_tlvs); i++) {
393+
u8 *scb_hex = tal_arr(cmd, u8, 0);
394+
towire_modern_scb_chan(&scb_hex, scb_tlvs[i]);
395+
json_add_hex_talarr(req->js, NULL, scb_hex);
396+
}
381397
json_array_end(req->js);
382398

383399
return send_outreq(req);
@@ -912,8 +928,8 @@ static struct command_result *after_latestscb(struct command *cmd,
912928
{
913929
u64 version;
914930
u32 timestamp;
931+
bool is_converted;
915932
struct modern_scb_chan **scb_tlvs;
916-
struct legacy_scb_chan **scb;
917933
struct json_stream *response;
918934
struct out_req *req;
919935

@@ -925,21 +941,8 @@ static struct command_result *after_latestscb(struct command *cmd,
925941
return command_finished(cmd, response);
926942
}
927943

928-
bool is_tlvs = false;
929-
if (!fromwire_static_chan_backup(cmd,
930-
res,
931-
&version,
932-
&timestamp,
933-
&scb)) {
934-
if(!fromwire_static_chan_backup_with_tlvs(cmd,
935-
res,
936-
&version,
937-
&timestamp,
938-
&scb_tlvs)) {
939-
plugin_err(cmd->plugin, "Corrupted SCB!");
940-
}
941-
is_tlvs = true;
942-
}
944+
if (!read_static_chan_backup(cmd, res, &version, &timestamp, &scb_tlvs, &is_converted))
945+
return command_fail(cmd, LIGHTNINGD, "Invalid emergencyrecover");
943946

944947
if ((version & 0x5555555555555555ULL) != (VERSION & 0x5555555555555555ULL)) {
945948
plugin_err(cmd->plugin,
@@ -951,28 +954,11 @@ static struct command_result *after_latestscb(struct command *cmd,
951954
&forward_error, NULL);
952955

953956
json_array_start(req->js, "scb");
954-
if (is_tlvs) {
955-
for (size_t i=0; i<tal_count(scb_tlvs); i++) {
956-
u8 *scb_hex = tal_arr(cmd, u8, 0);
957-
towire_modern_scb_chan(&scb_hex,scb_tlvs[i]);
958-
json_add_hex_talarr(req->js, NULL, scb_hex);
959-
}
960-
} else {
961-
for (size_t i=0; i<tal_count(scb); i++) {
962-
u8 *scb_hex = tal_arr(cmd, u8, 0);
963-
struct modern_scb_chan *tmp_scb_tlv = tal(cmd, struct modern_scb_chan);
964-
tmp_scb_tlv->id = scb[i]->id;
965-
tmp_scb_tlv->addr = scb[i]->addr;
966-
tmp_scb_tlv->cid = scb[i]->cid;
967-
tmp_scb_tlv->funding = scb[i]->funding;
968-
tmp_scb_tlv->funding_sats = scb[i]->funding_sats;
969-
tmp_scb_tlv->type = scb[i]->type;
970-
tmp_scb_tlv->tlvs = tlv_scb_tlvs_new(cmd);
971-
towire_modern_scb_chan(&scb_hex, tmp_scb_tlv);
972-
json_add_hex_talarr(req->js, NULL, scb_hex);
973-
}
957+
for (size_t i=0; i<tal_count(scb_tlvs); i++) {
958+
u8 *scb_hex = tal_arr(cmd, u8, 0);
959+
towire_modern_scb_chan(&scb_hex, scb_tlvs[i]);
960+
json_add_hex_talarr(req->js, NULL, scb_hex);
974961
}
975-
976962
json_array_end(req->js);
977963

978964
return send_outreq(req);
@@ -996,17 +982,36 @@ static struct command_result *json_getemergencyrecoverdata(struct command *cmd,
996982
const char *buf,
997983
const jsmntok_t *params)
998984
{
999-
u8 *filedata;
985+
const u8 *filedata, *decrypted_filedata;
986+
u64 version;
987+
u32 timestamp;
988+
struct modern_scb_chan **scb_tlvs;
989+
bool is_converted;
990+
struct json_stream *response;
991+
1000992
if (!param(cmd, buf, params, NULL))
1001993
return command_param_failed();
1002994

1003-
struct json_stream *response;
1004-
1005995
filedata = get_file_data(tmpctx, cmd->plugin);
996+
decrypted_filedata = decrypt_scb(cmd->plugin);
997+
998+
if (!read_static_chan_backup(cmd, decrypted_filedata,
999+
&version,
1000+
&timestamp,
1001+
&scb_tlvs,
1002+
&is_converted))
1003+
return command_fail(cmd, LIGHTNINGD, "Invalid emergencyrecover");
1004+
10061005
response = jsonrpc_stream_success(cmd);
10071006
json_add_hex_talarr(response, "filedata", filedata);
10081007

1009-
1008+
// If false, update the emergency.recover file immediately!
1009+
json_add_bool(response, "can_create_penalty", !is_converted);
1010+
json_array_start(response, "backed_up_channel_ids");
1011+
for (int i = 0; i < tal_count(scb_tlvs); i++) {
1012+
json_add_channel_id(response, NULL, &scb_tlvs[i]->cid);
1013+
}
1014+
json_array_end(response);
10101015
return command_finished(cmd, response);
10111016
}
10121017

tests/test_misc.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3045,8 +3045,10 @@ def test_getemergencyrecoverdata(node_factory):
30453045
Test getemergencyrecoverdata
30463046
"""
30473047
l1 = node_factory.get_node()
3048-
filedata = l1.rpc.getemergencyrecoverdata()['filedata']
3049-
3048+
rpc = l1.rpc.getemergencyrecoverdata()
3049+
filedata = rpc['filedata']
3050+
assert rpc['can_create_penalty'] is True
3051+
assert len(rpc['backed_up_channel_ids']) == 0
30503052
with open(os.path.join(l1.daemon.lightning_dir, TEST_NETWORK, "emergency.recover"), "rb") as f:
30513053
lines = f.read().hex()
30523054
assert lines == filedata

0 commit comments

Comments
 (0)