Skip to content

Commit

Permalink
plugins/chanbackup: Configure the plugin to exchange peer_storage and…
Browse files Browse the repository at this point in the history
… your_peer_storage messages and store in datastore.
  • Loading branch information
adi2011 committed Jul 1, 2022
1 parent a258d1b commit 3627845
Showing 1 changed file with 257 additions and 21 deletions.
278 changes: 257 additions & 21 deletions plugins/chanbackup.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@
#include <sodium.h>
#include <unistd.h>

#define HEADER_LEN crypto_secretstream_xchacha20poly1305_HEADERBYTES
#define ABYTES crypto_secretstream_xchacha20poly1305_ABYTES

/* VERSION is the current version of the data encrypted in the file */
#define VERSION ((u64)1)

/* Global secret object to keep the derived encryption key for the SCB */
struct secret secret;

#define PROVIDE_PEER_STORAGE_FEATUREBIT 43
#define WANT_PEER_STORAGE_FEATUREBIT 41

/* Helper to fetch out SCB from the RPC call */
static bool json_to_str(const char *buffer,
const jsmntok_t *tok,
Expand All @@ -44,8 +50,11 @@ static void write_hsm(struct plugin *p,

json_for_each_arr(i, t, scbtok) {
struct scb_chan *scb_chan;
const u8 *scb_tmp = tal_hexdata(buf, json_strdup(tmpctx, buf, t),
strlen(json_strdup(tmpctx, buf, t)));
const u8 *scb_tmp = tal_hexdata(buf,
json_strdup(buf, buf, t),
strlen(json_strdup(buf,
buf,
t)));
size_t scblen_tmp = tal_count(scb_tmp);

scb_chan = fromwire_scb_chan(buf, &scb_tmp, &scblen_tmp);
Expand All @@ -61,8 +70,8 @@ static void write_hsm(struct plugin *p,
u8 *final = tal_arr(buf,
u8,
tal_bytelen(point) +
crypto_secretstream_xchacha20poly1305_ABYTES +
crypto_secretstream_xchacha20poly1305_HEADERBYTES);
ABYTES +
HEADER_LEN);

crypto_secretstream_xchacha20poly1305_state crypto_state;

Expand All @@ -74,7 +83,7 @@ static void write_hsm(struct plugin *p,

if (crypto_secretstream_xchacha20poly1305_push(&crypto_state,
final +
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
HEADER_LEN,
NULL, point,
tal_bytelen(point),
/* Additional data and tag */
Expand Down Expand Up @@ -161,23 +170,23 @@ static u8 *decrypt_scb(struct plugin *p)
plugin_err(p, "SCB file is corrupted!: %s",
strerror(errno));

u8 final[st.st_size];
u8 *final = tal_arr(tmpctx, u8, st.st_size);

if (!read_all(fd, &final, st.st_size)) {
if (!read_all(fd, final, tal_bytelen(final))) {
plugin_log(p, LOG_DBG, "SCB file is corrupted!: %s",
strerror(errno));
return NULL;
}

crypto_secretstream_xchacha20poly1305_state crypto_state;

if (st.st_size < crypto_secretstream_xchacha20poly1305_ABYTES +
crypto_secretstream_xchacha20poly1305_HEADERBYTES)
if (tal_bytelen(final) < ABYTES +
HEADER_LEN)
plugin_err(p, "SCB file is corrupted!");

u8 *ans = tal_arr(tmpctx, u8, st.st_size -
crypto_secretstream_xchacha20poly1305_ABYTES -
crypto_secretstream_xchacha20poly1305_HEADERBYTES);
u8 *ans = tal_arr(tmpctx, u8, tal_bytelen(final) -
ABYTES -
HEADER_LEN);

/* The header part */
if (crypto_secretstream_xchacha20poly1305_init_pull(&crypto_state, final,
Expand All @@ -188,9 +197,9 @@ static u8 *decrypt_scb(struct plugin *p)
if (crypto_secretstream_xchacha20poly1305_pull(&crypto_state, ans,
NULL, 0,
final +
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
st.st_size -
crypto_secretstream_xchacha20poly1305_HEADERBYTES,
HEADER_LEN,
tal_bytelen(final) -
HEADER_LEN,
NULL, 0) != 0) {
plugin_err(p, "SCB file is corrupted!");
}
Expand Down Expand Up @@ -324,8 +333,9 @@ static struct command_result *json_state_changed(struct command *cmd,

/* FIXME: I wanted to update the file on CHANNELD_AWAITING_LOCKIN,
* But I don't get update for it, maybe because there is no previous_state,
* also apparently `channel_opened` gets published when *peer* funded a channel with us?
* So, is their no way to get a notif on CHANNELD_AWAITING_LOCKIN? */
* also apparently `channel_opened` gets published when *peer*
* funded a channel with us? So, is their no way to get a notif on
* CHANNELD_AWAITING_LOCKIN? */
if (json_tok_streq(buf, statetok, "CLOSED") ||
json_tok_streq(buf, statetok, "CHANNELD_NORMAL")) {

Expand Down Expand Up @@ -366,11 +376,222 @@ static const char *init(struct plugin *p,
return NULL;
}

static struct command_result
*after_send_their_peer_strg(struct command *cmd,
const char *buf,
const jsmntok_t *params,
void *cb_arg UNUSED)
{
plugin_log(cmd->plugin, LOG_DBG, "Sent their peer storage!");
return notification_handled(cmd);
}

static struct command_result *after_listdatastore(struct command *cmd,
const char *buf,
const jsmntok_t *params,
struct node_id *nodeid)
{
const jsmntok_t *datastoretok = json_get_member(buf, params, "datastore");

if (datastoretok->size == 0)
return notification_handled(cmd);

const jsmntok_t *payloadtok = json_get_member(buf, json_get_arr(datastoretok, 0), "hex");
struct out_req *req;


u8 *hexdata = tal_hexdata(cmd,
json_strdup(cmd, buf, payloadtok),
payloadtok->end - payloadtok->start),
*payload = towire_your_peer_storage(cmd, hexdata);

plugin_log(cmd->plugin, LOG_DBG, "sending their backup from our datastore");
// plugin_log(cmd->plugin, LOG_DBG, "payload is %s", tal_hexstr(tmpctx, payload, tal_bytelen(payload)));
// plugin_log(cmd->plugin, LOG_DBG, "size is %d", payloadtok->end - payloadtok->start);
// plugin_log(cmd->plugin, LOG_DBG, "size is %ld", tal_count(hexdata));


req = jsonrpc_request_start(cmd->plugin,
cmd,
"sendcustommsg",
after_send_their_peer_strg,
&forward_error,
NULL);

json_add_node_id(req->js, "node_id", nodeid);
json_add_hex(req->js, "msg", payload,
tal_bytelen(payload));

return send_outreq(cmd->plugin, req);
}

static struct command_result *after_send_scb(struct command *cmd,
const char *buf,
const jsmntok_t *params,
struct node_id *nodeid)
{
plugin_log(cmd->plugin, LOG_DBG, "Peer storage sent!");
struct out_req *req;
req = jsonrpc_request_start(cmd->plugin,
cmd,
"listdatastore",
after_listdatastore,
&forward_error,
nodeid);
json_add_node_id(req->js,"key",nodeid);
return send_outreq(cmd->plugin, req);
}

static struct command_result *json_connect(struct command *cmd,
const char *buf,
const jsmntok_t *params)
{
const jsmntok_t *nodeid = json_get_member(buf,
params,
"id");

struct node_id *node_id = tal(cmd, struct node_id);
json_to_node_id(buf, nodeid, node_id);
struct stat st;
struct out_req *req;

int fd = open("emergency.recover", O_RDONLY);

if (fd < 0)
plugin_err(cmd->plugin, "Opening: %s", strerror(errno));

if (stat("emergency.recover", &st) != 0)
plugin_err(cmd->plugin, "SCB file is corrupted!: %s",
strerror(errno));

u8 *scb = tal_arr(cmd, u8, st.st_size);

if (!read_all(fd, scb, tal_bytelen(scb))) {
plugin_log(cmd->plugin, LOG_DBG, "SCB file is corrupted!: %s",
strerror(errno));
return NULL;
}

u8 *serialise_scb = towire_peer_storage(cmd, scb);

req = jsonrpc_request_start(cmd->plugin,
cmd,
"sendcustommsg",
after_send_scb,
&forward_error,
node_id);

json_add_node_id(req->js, "node_id", node_id);
json_add_hex(req->js, "msg", serialise_scb,
tal_bytelen(serialise_scb));

if (fsync(fd) != 0) {
plugin_err(cmd->plugin, "closing: %s", strerror(errno));
}

if (close(fd) != 0) {
plugin_err(cmd->plugin, "closing: %s", strerror(errno));
}

return send_outreq(cmd->plugin, req);
}

static struct command_result *after_datastore(struct command *cmd,
const char *buf,
const jsmntok_t *params,
void *cb_arg UNUSED)
{
/* FIXME: WHY IS THIS FAILING!? at cmd->id */
return command_hook_success(cmd);
}

static struct command_result *json_your_peer_storage(struct command *cmd,
const char *buf,
const jsmntok_t *params)
{
const jsmntok_t *nodeidtok, *payloadtok;
struct node_id *node_id = tal(cmd, struct node_id);
u8 *payload, *payload_deserialise;
struct out_req *req;

nodeidtok = json_get_member(buf, params, "peer_id");
payloadtok = json_get_member(buf, params, "payload");
json_to_node_id(buf, nodeidtok, node_id);

payload = tal_hexdata(cmd,
json_strdup(tmpctx, buf, payloadtok),
payloadtok->end - payloadtok->start);

if (!fromwire_peer_storage(cmd, payload, &payload_deserialise)) {
if (!fromwire_your_peer_storage(cmd, payload, &payload_deserialise)) {
plugin_log(cmd->plugin, LOG_BROKEN, "Peer sent bad custom message!");
return command_hook_success(cmd);
}
plugin_log(cmd->plugin, LOG_DBG, "Received peer_storage from peer.");

crypto_secretstream_xchacha20poly1305_state crypto_state;

if (tal_bytelen(payload_deserialise) < ABYTES +
HEADER_LEN)
plugin_log(cmd->plugin, LOG_BROKEN, "Peer altered our backup.");

u8 *ans = tal_arr(tmpctx, u8, tal_bytelen(payload_deserialise) -
ABYTES -
HEADER_LEN);

/* The header part */
if (crypto_secretstream_xchacha20poly1305_init_pull(&crypto_state, payload_deserialise,
(&secret)->data) != 0) {
plugin_err(cmd->plugin, "Peer altered our backup.");
}

if (crypto_secretstream_xchacha20poly1305_pull(&crypto_state, ans,
NULL, 0,
payload_deserialise +
HEADER_LEN,
tal_bytelen(payload_deserialise) -
HEADER_LEN,
NULL, 0) != 0) {
plugin_err(cmd->plugin, "Peer altered our backup.");
}

plugin_log(cmd->plugin, LOG_DBG, "ans is %s", tal_hexstr(tmpctx, ans, tal_bytelen(ans)));
return command_hook_success(cmd);
}

req = jsonrpc_request_start(cmd->plugin,
cmd,
"datastore",
after_datastore,
&forward_error,
NULL);

json_array_start(req->js, "key");
json_add_node_id(req->js, NULL, node_id);
json_add_string(req->js, NULL, "chanbackup");
json_array_end(req->js);
json_add_hex(req->js, "hex", payload_deserialise, tal_bytelen(payload_deserialise));
json_add_string(req->js, "mode", "create-or-replace");

return send_outreq(cmd->plugin, req);
}

static const struct plugin_notification notifs[] = {
{
"channel_state_changed",
json_state_changed,
}
},
{
"connect",
json_connect,
},
};

static const struct plugin_hook hooks[] = {
{
"custommsg",
json_your_peer_storage,
},
};

static const struct plugin_command commands[] = { {
Expand All @@ -384,10 +605,25 @@ static const struct plugin_command commands[] = { {

int main(int argc, char *argv[])
{
setup_locale();
plugin_main(argv, init, PLUGIN_RESTARTABLE, true, NULL,
struct feature_set *features = tal(NULL, struct feature_set);
setup_locale();

for (int i=0; i<ARRAY_SIZE(features->bits); i++)
features->bits[i] = tal_arr(features, u8, 0);

set_feature_bit(&features->bits[NODE_ANNOUNCE_FEATURE],
PROVIDE_PEER_STORAGE_FEATUREBIT);
set_feature_bit(&features->bits[INIT_FEATURE],
PROVIDE_PEER_STORAGE_FEATUREBIT);

set_feature_bit(&features->bits[NODE_ANNOUNCE_FEATURE],
WANT_PEER_STORAGE_FEATUREBIT);
set_feature_bit(&features->bits[INIT_FEATURE],
WANT_PEER_STORAGE_FEATUREBIT);

plugin_main(argv, init, PLUGIN_STATIC, true, features,
commands, ARRAY_SIZE(commands),
notifs, ARRAY_SIZE(notifs), NULL, 0,
notifs, ARRAY_SIZE(notifs), hooks, ARRAY_SIZE(hooks),
NULL, 0, /* Notification topics we publish */
NULL);
}

0 comments on commit 3627845

Please sign in to comment.