Skip to content

Commit

Permalink
askrene: really fix race between layer creation and persistent layer …
Browse files Browse the repository at this point in the history
…loading.

Using jsonrpc_request_sync, layers are loaded before we finish init,
so we never can be asked to create a layer before we've loaded it
(xpay creates a layer immediately on startup).

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-None: persistent layers new this release.
  • Loading branch information
rustyrussell committed Nov 26, 2024
1 parent 42b66df commit bf052db
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 36 deletions.
5 changes: 3 additions & 2 deletions plugins/askrene/askrene.c
Original file line number Diff line number Diff line change
Expand Up @@ -1239,9 +1239,10 @@ static const char *init(struct command *init_cmd,
plugin_set_data(plugin, askrene);
plugin_set_memleak_handler(plugin, askrene_markmem);

/* Layer needs its own command to access datastore */
load_layers(askrene, init_cmd);

/* Layer needs its own command to write to the datastore */
askrene->layer_cmd = aux_command(init_cmd);
load_layers(askrene);
return NULL;
}

Expand Down
51 changes: 18 additions & 33 deletions plugins/askrene/layer.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "config.h"
#include <ccan/array_size/array_size.h>
#include <ccan/htable/htable_type.h>
#include <ccan/json_out/json_out.h>
#include <ccan/tal/str/str.h>
#include <common/gossmap.h>
#include <common/json_stream.h>
Expand Down Expand Up @@ -683,16 +684,7 @@ static void populate_layer(struct askrene *askrene,
struct layer *layer;
size_t len = tal_bytelen(data);

/* FIXME: They can race us, creating a layer while we're loading! */
layer = find_layer(askrene, layername);
if (layer) {
/* We promised to take this! */
if (taken(layername))
tal_free(layername);
} else {
layer = add_layer(askrene, layername, true);
}

layer = add_layer(askrene, layername, true);
plugin_log(askrene->plugin, LOG_DBG,
"Loaded level %s (%zu bytes)",
layer->name, len);
Expand Down Expand Up @@ -727,18 +719,26 @@ static void populate_layer(struct askrene *askrene,
layer->name);
}

static struct command_result *listdatastore_done(struct command *aux_cmd,
const char *method,
const char *buf,
const jsmntok_t *result,
struct askrene *askrene)
void load_layers(struct askrene *askrene, struct command *init_cmd)
{
struct json_out *params = json_out_new(init_cmd);
const jsmntok_t *result;
const char *buf;
const jsmntok_t *datastore, *t, *key, *data;
size_t i;

plugin_log(aux_cmd->plugin, LOG_DBG, "datastore = %.*s",
json_tok_full_len(result),
json_tok_full(buf, result));

json_out_start(params, NULL, '{');
json_out_start(params, "key", '[');
json_out_addstr(params, NULL, "askrene");
json_out_addstr(params, NULL, "layers");
json_out_end(params, ']');
json_out_end(params, '}');

result = jsonrpc_request_sync(tmpctx, init_cmd,
"listdatastore",
params, &buf);

datastore = json_get_member(buf, result, "datastore");
json_for_each_arr(i, t, datastore) {
const char *layername;
Expand All @@ -754,21 +754,6 @@ static struct command_result *listdatastore_done(struct command *aux_cmd,
take(layername),
json_tok_bin_from_hex(tmpctx, buf, data));
}
return command_still_pending(aux_cmd);
}

void load_layers(struct askrene *askrene)
{
struct out_req *req = jsonrpc_request_start(askrene->layer_cmd,
"listdatastore",
listdatastore_done,
plugin_broken_cb,
askrene);
json_array_start(req->js, "key");
json_add_string(req->js, NULL, "askrene");
json_add_string(req->js, NULL, "layers");
json_array_end(req->js);
send_outreq(req);
}

void remove_layer(struct layer *l)
Expand Down
2 changes: 1 addition & 1 deletion plugins/askrene/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const struct local_channel *layer_find_local_channel(const struct layer *layer,
struct amount_msat local_channel_capacity(const struct local_channel *lc);

/* Load any persistent layers */
void load_layers(struct askrene *askrene);
void load_layers(struct askrene *askrene, struct command *init_cmd);

/* Check local channel matches these */
bool layer_check_local_channel(const struct local_channel *lc,
Expand Down

0 comments on commit bf052db

Please sign in to comment.