datastore: allow strings.

It's common, and the simplest case.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-08-25 12:20:13 +09:30 committed by Christian Decker
parent dfe2693bbd
commit e711f6c589
11 changed files with 74 additions and 37 deletions

View file

@ -3,7 +3,7 @@
lightning-datastore - Command for storing (plugin) data
.SH SYNOPSIS
\fBdatastore\fR \fIkey\fR \fIhex\fR
\fBdatastore\fR \fIkey\fR [\fIstring\fR|\fIhex\fR]
.SH DESCRIPTION
@ -23,6 +23,8 @@ On success, an object is returned, containing:
\fBkey\fR (string): The key which has been added to the datastore
.IP \[bu]
\fBhex\fR (hex): The hex data which has been added to the datastore
.IP \[bu]
\fBstring\fR (string, optional): The data as a string, if it's valid utf-8
.RE
@ -48,4 +50,4 @@ Rusty Russell \fI<rusty@rustcorp.com.au\fR> is mainly responsible\.
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
\" SHA256STAMP:1972be4c054c35bf2e0fdbf2e7bb9a3870b3322a008ae29e6a84207c7b527458
\" SHA256STAMP:e0ea91fb846859bc22af6e4beacd5fb726d6c4ffefea5cc4e3a1250b81665317

View file

@ -4,7 +4,7 @@ lightning-datastore -- Command for storing (plugin) data
SYNOPSIS
--------
**datastore** *key* *hex*
**datastore** *key* [*string*|*hex*]
DESCRIPTION
-----------
@ -22,6 +22,7 @@ RETURN VALUE
On success, an object is returned, containing:
- **key** (string): The key which has been added to the datastore
- **hex** (hex): The hex data which has been added to the datastore
- **string** (string, optional): The data as a string, if it's valid utf-8
[comment]: # (GENERATE-FROM-SCHEMA-END)
The main cause of failure is an already-existing entry.
@ -44,4 +45,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:692c74ea1dea25266d8d562bc23e5c3c14223f62c9152a223cbd9c2de4d01efb)
[comment]: # ( SHA256STAMP:5eda4592b0a5e893853ea15ce7e800bb94e3a26ebd932507c2a55890f56fee14)

View file

@ -22,6 +22,8 @@ On success, an object is returned, containing:
\fBkey\fR (string): The key which has been removed from the datastore
.IP \[bu]
\fBhex\fR (hex): The hex data which has removed from the datastore
.IP \[bu]
\fBstring\fR (string, optional): The data as a string, if it's valid utf-8
.RE
@ -47,4 +49,4 @@ Rusty Russell \fI<rusty@rustcorp.com.au\fR> is mainly responsible\.
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
\" SHA256STAMP:61af040ae88b08a8cc0e5f0d510a9613fbdc89e6e8d5b7dfebedcd134a91fb4b
\" SHA256STAMP:8e1a383ed176a0b7f8b849bf2bb05f5caaaf0de4f375afd38cbc668f1f17d9a2

View file

@ -21,6 +21,7 @@ RETURN VALUE
On success, an object is returned, containing:
- **key** (string): The key which has been removed from the datastore
- **hex** (hex): The hex data which has removed from the datastore
- **string** (string, optional): The data as a string, if it's valid utf-8
[comment]: # (GENERATE-FROM-SCHEMA-END)
The main cause of failure is an non-existing entry.
@ -43,4 +44,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:8e732382fa499ed98dc015a1525b4fa07a2d20d5009c305945f06dae84b408c7)
[comment]: # ( SHA256STAMP:cc1dedfded4902f59879665e95a1a877c8c72c0e217a3db3de3ae8dde859e67a)

View file

@ -23,6 +23,8 @@ On success, an object containing \fBdatastore\fR is returned\. It is an array o
\fBkey\fR (string): The key which from the datastore
.IP \[bu]
\fBhex\fR (hex): The hex data from the datastore
.IP \[bu]
\fBstring\fR (string, optional): The data as a string, if it's valid utf-8
.RE
@ -45,4 +47,4 @@ Rusty Russell \fI<rusty@rustcorp.com.au\fR> is mainly responsible\.
Main web site: \fIhttps://github.com/ElementsProject/lightning\fR
\" SHA256STAMP:a501f1c8a7517726a49e48180c5d20966df7158f1af3afdd1654a435473efb5d
\" SHA256STAMP:bcc83095fc1695b0c81a2763109e280d711e29edbc395672314d052f9d99a72c

View file

@ -22,6 +22,7 @@ RETURN VALUE
On success, an object containing **datastore** is returned. It is an array of objects, where each object contains:
- **key** (string): The key which from the datastore
- **hex** (hex): The hex data from the datastore
- **string** (string, optional): The data as a string, if it's valid utf-8
[comment]: # (GENERATE-FROM-SCHEMA-END)
The following error codes may occur:
@ -42,4 +43,4 @@ RESOURCES
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:660d1723bcea3d4800db72a9204ed577426e7b3ab99f491145e633df89a46fac)
[comment]: # ( SHA256STAMP:b93d725952e9ac5134dc25711d9bfbbd8b719e8ee8592f27bd1becbb56f89971)

View file

@ -11,6 +11,10 @@
"hex": {
"type": "hex",
"description": "The hex data which has been added to the datastore"
},
"string": {
"type": "string",
"description": "The data as a string, if it's valid utf-8"
}
}
}

View file

@ -11,6 +11,10 @@
"hex": {
"type": "hex",
"description": "The hex data which has removed from the datastore"
},
"string": {
"type": "string",
"description": "The data as a string, if it's valid utf-8"
}
}
}

View file

@ -18,6 +18,10 @@
"hex": {
"type": "hex",
"description": "The hex data from the datastore"
},
"string": {
"type": "string",
"description": "The data as a string, if it's valid utf-8"
}
}
}

View file

@ -7,8 +7,12 @@
static void json_add_datastore(struct json_stream *response,
const char *key, const u8 *data)
{
const char *str;
json_add_string(response, "key", key);
json_add_hex(response, "hex", data, tal_bytelen(data));
str = utf8_str(response, data, tal_bytelen(data));
if (str)
json_add_string(response, "string", str);
}
static struct command_result *json_datastore(struct command *cmd,
@ -17,15 +21,27 @@ static struct command_result *json_datastore(struct command *cmd,
const jsmntok_t *params)
{
struct json_stream *response;
const char *key;
const char *key, *strdata;
u8 *data;
if (!param(cmd, buffer, params,
p_req("key", param_string, &key),
p_req("hex", param_bin_from_hex, &data),
p_opt("string", param_string, &strdata),
p_opt("hex", param_bin_from_hex, &data),
NULL))
return command_param_failed();
if (strdata) {
if (data)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Cannot have both hex and string");
data = tal_dup_arr(cmd, u8, (u8 *)strdata, strlen(strdata), 0);
} else {
if (!data)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Must have either hex or string");
}
if (!wallet_datastore_add(cmd->ld->wallet, key, data))
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Key already exists");
@ -103,7 +119,7 @@ static const struct json_command datastore_command = {
"datastore",
"utility",
json_datastore,
"Add a {key} and {hex} data to the data store",
"Add a {key} and {hex}/{string} data to the data store",
};
AUTODATA(json_command, &datastore_command);

View file

@ -2635,45 +2635,45 @@ def test_datastore(node_factory):
# Add entries.
somedata = b'somedata'.hex()
assert l1.rpc.datastore('somekey', somedata) == {'key': 'somekey',
'hex': somedata}
somedata_expect = {'key': 'somekey',
'hex': somedata,
'string': 'somedata'}
assert l1.rpc.datastore(key='somekey', hex=somedata) == somedata_expect
assert l1.rpc.listdatastore() == {'datastore': [{'key': 'somekey',
'hex': somedata}]}
assert l1.rpc.listdatastore('somekey') == {'datastore': [{'key': 'somekey',
'hex': somedata}]}
assert l1.rpc.listdatastore() == {'datastore': [somedata_expect]}
assert l1.rpc.listdatastore('somekey') == {'datastore': [somedata_expect]}
assert l1.rpc.listdatastore('otherkey') == {'datastore': []}
otherdata = b'otherdata'.hex()
assert l1.rpc.datastore('otherkey', otherdata) == {'key': 'otherkey',
'hex': otherdata}
otherdata_expect = {'key': 'otherkey',
'hex': otherdata,
'string': 'otherdata'}
assert l1.rpc.datastore(key='otherkey', string='otherdata') == otherdata_expect
assert l1.rpc.listdatastore('somekey') == {'datastore': [{'key': 'somekey',
'hex': somedata}]}
assert l1.rpc.listdatastore('otherkey') == {'datastore': [{'key': 'otherkey',
'hex': otherdata}]}
assert l1.rpc.listdatastore('somekey') == {'datastore': [somedata_expect]}
assert l1.rpc.listdatastore('otherkey') == {'datastore': [otherdata_expect]}
assert l1.rpc.listdatastore('badkey') == {'datastore': []}
ds = l1.rpc.listdatastore()
# Order is undefined!
assert (ds == {'datastore': [{'key': 'somekey', 'hex': somedata},
{'key': 'otherkey', 'hex': otherdata}]}
or ds == {'datastore': [{'key': 'otherkey', 'hex': otherdata},
{'key': 'somekey', 'hex': somedata}]})
assert (ds == {'datastore': [somedata_expect, otherdata_expect]}
or ds == {'datastore': [otherdata_expect, somedata_expect]})
assert l1.rpc.deldatastore('somekey') == {'key': 'somekey',
'hex': somedata}
assert l1.rpc.listdatastore() == {'datastore': [{'key': 'otherkey',
'hex': otherdata}]}
assert l1.rpc.deldatastore('somekey') == somedata_expect
assert l1.rpc.listdatastore() == {'datastore': [otherdata_expect]}
assert l1.rpc.listdatastore('somekey') == {'datastore': []}
assert l1.rpc.listdatastore('otherkey') == {'datastore': [{'key': 'otherkey',
'hex': otherdata}]}
assert l1.rpc.listdatastore('otherkey') == {'datastore': [otherdata_expect]}
assert l1.rpc.listdatastore('badkey') == {'datastore': []}
assert l1.rpc.listdatastore() == {'datastore': [{'key': 'otherkey',
'hex': otherdata}]}
assert l1.rpc.listdatastore() == {'datastore': [otherdata_expect]}
# if it's not a string, won't print
badstring_expect = {'key': 'badstring',
'hex': '00'}
assert l1.rpc.datastore(key='badstring', hex='00') == badstring_expect
assert l1.rpc.listdatastore('badstring') == {'datastore': [badstring_expect]}
assert l1.rpc.deldatastore('badstring') == badstring_expect
# It's persistent
l1.restart()
assert l1.rpc.listdatastore() == {'datastore': [{'key': 'otherkey',
'hex': otherdata}]}
assert l1.rpc.listdatastore() == {'datastore': [otherdata_expect]}