mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-20 07:34:24 +01:00
lightningd: use the async mechanism for channel_update access.
Instead of saving a stripped_update, we use the new local_fail_in_htlc_needs_update. One minor change: we return the more correct towire_temporary_channel_failure when the node is still syncing. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -265,7 +265,6 @@ struct channel *new_channel(struct peer *peer, u64 dbid,
|
|||||||
= tal_steal(channel, remote_upfront_shutdown_script);
|
= tal_steal(channel, remote_upfront_shutdown_script);
|
||||||
channel->option_static_remotekey = option_static_remotekey;
|
channel->option_static_remotekey = option_static_remotekey;
|
||||||
channel->forgets = tal_arr(channel, struct command *, 0);
|
channel->forgets = tal_arr(channel, struct command *, 0);
|
||||||
channel->stripped_update = NULL;
|
|
||||||
|
|
||||||
list_add_tail(&peer->channels, &channel->list);
|
list_add_tail(&peer->channels, &channel->list);
|
||||||
tal_add_destructor(channel, destroy_channel);
|
tal_add_destructor(channel, destroy_channel);
|
||||||
|
|||||||
@@ -123,9 +123,6 @@ struct channel {
|
|||||||
|
|
||||||
/* Any commands trying to forget us. */
|
/* Any commands trying to forget us. */
|
||||||
struct command **forgets;
|
struct command **forgets;
|
||||||
|
|
||||||
/* Lastest channel_update from gossipd, if any: type stripped! */
|
|
||||||
const u8 *stripped_update;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct channel *new_channel(struct peer *peer, u64 dbid,
|
struct channel *new_channel(struct peer *peer, u64 dbid,
|
||||||
|
|||||||
@@ -513,8 +513,6 @@ static void shutdown_subdaemons(struct lightningd *ld)
|
|||||||
/*~ The three "global" daemons, which we shutdown explicitly: we
|
/*~ The three "global" daemons, which we shutdown explicitly: we
|
||||||
* give them 10 seconds to exit gracefully before killing them. */
|
* give them 10 seconds to exit gracefully before killing them. */
|
||||||
ld->connectd = subd_shutdown(ld->connectd, 10);
|
ld->connectd = subd_shutdown(ld->connectd, 10);
|
||||||
ld->gossip = subd_shutdown(ld->gossip, 10);
|
|
||||||
ld->hsm = subd_shutdown(ld->hsm, 10);
|
|
||||||
|
|
||||||
/* Now we free all the HTLCs */
|
/* Now we free all the HTLCs */
|
||||||
free_htlcs(ld, NULL);
|
free_htlcs(ld, NULL);
|
||||||
@@ -547,6 +545,11 @@ static void shutdown_subdaemons(struct lightningd *ld)
|
|||||||
tal_free(p);
|
tal_free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*~ Now they're all dead, we can stop gossipd: doing it before HTLCs is
|
||||||
|
* problematic because local_fail_in_htlc_needs_update() asks gossipd */
|
||||||
|
ld->gossip = subd_shutdown(ld->gossip, 10);
|
||||||
|
ld->hsm = subd_shutdown(ld->hsm, 10);
|
||||||
|
|
||||||
/*~ Commit the transaction. Note that the db is actually
|
/*~ Commit the transaction. Note that the db is actually
|
||||||
* single-threaded, so commits never fail and we don't need
|
* single-threaded, so commits never fail and we don't need
|
||||||
* spin-and-retry logic everywhere. */
|
* spin-and-retry logic everywhere. */
|
||||||
|
|||||||
@@ -741,11 +741,13 @@ static const u8 *send_onion(const tal_t *ctx, struct lightningd *ld,
|
|||||||
{
|
{
|
||||||
const u8 *onion;
|
const u8 *onion;
|
||||||
unsigned int base_expiry;
|
unsigned int base_expiry;
|
||||||
|
bool dont_care_about_channel_update;
|
||||||
base_expiry = get_block_height(ld->topology) + 1;
|
base_expiry = get_block_height(ld->topology) + 1;
|
||||||
onion = serialize_onionpacket(tmpctx, packet);
|
onion = serialize_onionpacket(tmpctx, packet);
|
||||||
return send_htlc_out(ctx, channel, first_hop->amount,
|
return send_htlc_out(ctx, channel, first_hop->amount,
|
||||||
base_expiry + first_hop->delay,
|
base_expiry + first_hop->delay,
|
||||||
payment_hash, partid, onion, NULL, hout);
|
payment_hash, partid, onion, NULL, hout,
|
||||||
|
&dont_care_about_channel_update);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* destination/route_channels/route_nodes are NULL (and path_secrets may be NULL)
|
/* destination/route_channels/route_nodes are NULL (and path_secrets may be NULL)
|
||||||
|
|||||||
@@ -280,14 +280,23 @@ const u8 *failmsg_incorrect_or_unknown(const tal_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* localfail are for handing to the local payer if it's local. */
|
/* localfail are for handing to the local payer if it's local. */
|
||||||
static void fail_out_htlc(struct htlc_out *hout, const char *localfail)
|
static void fail_out_htlc(struct htlc_out *hout,
|
||||||
|
const char *localfail,
|
||||||
|
const u8 *failmsg_needs_update TAKES)
|
||||||
{
|
{
|
||||||
htlc_out_check(hout, __func__);
|
htlc_out_check(hout, __func__);
|
||||||
assert(hout->failmsg || hout->failonion);
|
assert(hout->failmsg || hout->failonion);
|
||||||
|
|
||||||
if (hout->am_origin) {
|
if (hout->am_origin) {
|
||||||
payment_failed(hout->key.channel->peer->ld, hout, localfail);
|
payment_failed(hout->key.channel->peer->ld, hout, localfail);
|
||||||
|
if (taken(failmsg_needs_update))
|
||||||
|
tal_free(failmsg_needs_update);
|
||||||
} else if (hout->in) {
|
} else if (hout->in) {
|
||||||
|
if (failmsg_needs_update) {
|
||||||
|
local_fail_in_htlc_needs_update(hout->in,
|
||||||
|
failmsg_needs_update,
|
||||||
|
hout->key.channel->scid);
|
||||||
|
} else {
|
||||||
const struct onionreply *failonion;
|
const struct onionreply *failonion;
|
||||||
|
|
||||||
/* If we have an onion, simply copy it. */
|
/* If we have an onion, simply copy it. */
|
||||||
@@ -300,6 +309,7 @@ static void fail_out_htlc(struct htlc_out *hout, const char *localfail)
|
|||||||
hout->failmsg);
|
hout->failmsg);
|
||||||
fail_in_htlc(hout->in, failonion);
|
fail_in_htlc(hout->in, failonion);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BOLT #4:
|
/* BOLT #4:
|
||||||
@@ -495,15 +505,16 @@ static void destroy_hout_subd_died(struct htlc_out *hout)
|
|||||||
"Failing HTLC %"PRIu64" due to peer death",
|
"Failing HTLC %"PRIu64" due to peer death",
|
||||||
hout->key.id);
|
hout->key.id);
|
||||||
|
|
||||||
hout->failmsg = towire_temporary_channel_failure(hout,
|
/* This isn't really used, except as sanity check */
|
||||||
hout->key.channel->stripped_update);
|
hout->failmsg = towire_temporary_node_failure(hout);
|
||||||
|
|
||||||
/* Assign a temporary state (we're about to free it!) so checks
|
/* Assign a temporary state (we're about to free it!) so checks
|
||||||
* are happy that it has a failure message */
|
* are happy that it has a failure message */
|
||||||
assert(hout->hstate == SENT_ADD_HTLC);
|
assert(hout->hstate == SENT_ADD_HTLC);
|
||||||
hout->hstate = RCVD_REMOVE_HTLC;
|
hout->hstate = RCVD_REMOVE_HTLC;
|
||||||
|
|
||||||
fail_out_htlc(hout, "Outgoing subdaemon died");
|
fail_out_htlc(hout, "Outgoing subdaemon died",
|
||||||
|
take(towire_temporary_channel_failure(NULL, NULL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is where channeld gives us the HTLC id, and also reports if it
|
/* This is where channeld gives us the HTLC id, and also reports if it
|
||||||
@@ -595,11 +606,13 @@ const u8 *send_htlc_out(const tal_t *ctx,
|
|||||||
u64 partid,
|
u64 partid,
|
||||||
const u8 *onion_routing_packet,
|
const u8 *onion_routing_packet,
|
||||||
struct htlc_in *in,
|
struct htlc_in *in,
|
||||||
struct htlc_out **houtp)
|
struct htlc_out **houtp,
|
||||||
|
bool *needs_update_appended)
|
||||||
{
|
{
|
||||||
u8 *msg;
|
u8 *msg;
|
||||||
|
|
||||||
*houtp = NULL;
|
*houtp = NULL;
|
||||||
|
*needs_update_appended = false;
|
||||||
|
|
||||||
if (!channel_can_add_htlc(out)) {
|
if (!channel_can_add_htlc(out)) {
|
||||||
log_info(out->log, "Attempt to send HTLC but not ready (%s)",
|
log_info(out->log, "Attempt to send HTLC but not ready (%s)",
|
||||||
@@ -610,15 +623,14 @@ const u8 *send_htlc_out(const tal_t *ctx,
|
|||||||
if (!out->owner) {
|
if (!out->owner) {
|
||||||
log_info(out->log, "Attempt to send HTLC but unowned (%s)",
|
log_info(out->log, "Attempt to send HTLC but unowned (%s)",
|
||||||
channel_state_name(out));
|
channel_state_name(out));
|
||||||
return towire_temporary_channel_failure(ctx,
|
*needs_update_appended = true;
|
||||||
out->stripped_update);
|
return towire_temporary_channel_failure(ctx, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!topology_synced(out->peer->ld->topology)) {
|
if (!topology_synced(out->peer->ld->topology)) {
|
||||||
log_info(out->log, "Attempt to send HTLC but still syncing"
|
log_info(out->log, "Attempt to send HTLC but still syncing"
|
||||||
" with bitcoin network");
|
" with bitcoin network");
|
||||||
return towire_temporary_channel_failure(ctx,
|
return towire_temporary_node_failure(ctx);
|
||||||
out->stripped_update);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make peer's daemon own it, catch if it dies. */
|
/* Make peer's daemon own it, catch if it dies. */
|
||||||
@@ -646,7 +658,6 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
struct amount_msat amt_to_forward,
|
struct amount_msat amt_to_forward,
|
||||||
u32 outgoing_cltv_value,
|
u32 outgoing_cltv_value,
|
||||||
const struct node_id *next_hop,
|
const struct node_id *next_hop,
|
||||||
const u8 *stripped_update TAKES,
|
|
||||||
const u8 next_onion[TOTAL_PACKET_SIZE])
|
const u8 next_onion[TOTAL_PACKET_SIZE])
|
||||||
{
|
{
|
||||||
const u8 *failmsg;
|
const u8 *failmsg;
|
||||||
@@ -654,6 +665,7 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
struct lightningd *ld = hin->key.channel->peer->ld;
|
struct lightningd *ld = hin->key.channel->peer->ld;
|
||||||
struct channel *next = active_channel_by_id(ld, next_hop, NULL);
|
struct channel *next = active_channel_by_id(ld, next_hop, NULL);
|
||||||
struct htlc_out *hout = NULL;
|
struct htlc_out *hout = NULL;
|
||||||
|
bool needs_update_appended;
|
||||||
|
|
||||||
/* Unknown peer, or peer not ready. */
|
/* Unknown peer, or peer not ready. */
|
||||||
if (!next || !next->scid) {
|
if (!next || !next->scid) {
|
||||||
@@ -662,17 +674,9 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
hin, next ? next->scid : NULL, NULL,
|
hin, next ? next->scid : NULL, NULL,
|
||||||
FORWARD_LOCAL_FAILED,
|
FORWARD_LOCAL_FAILED,
|
||||||
WIRE_UNKNOWN_NEXT_PEER);
|
WIRE_UNKNOWN_NEXT_PEER);
|
||||||
if (taken(stripped_update))
|
|
||||||
tal_free(stripped_update);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK, apply any channel_update gossipd gave us for this channel. */
|
|
||||||
tal_free(next->stripped_update);
|
|
||||||
next->stripped_update
|
|
||||||
= tal_dup_arr(next, u8, stripped_update,
|
|
||||||
tal_count(stripped_update), 0);
|
|
||||||
|
|
||||||
/* BOLT #7:
|
/* BOLT #7:
|
||||||
*
|
*
|
||||||
* The origin node:
|
* The origin node:
|
||||||
@@ -685,26 +689,28 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
log_broken(ld->log, "Fee overflow forwarding %s!",
|
log_broken(ld->log, "Fee overflow forwarding %s!",
|
||||||
type_to_string(tmpctx, struct amount_msat,
|
type_to_string(tmpctx, struct amount_msat,
|
||||||
&amt_to_forward));
|
&amt_to_forward));
|
||||||
failmsg = towire_fee_insufficient(tmpctx, hin->msat,
|
needs_update_appended = true;
|
||||||
next->stripped_update);
|
failmsg = towire_fee_insufficient(tmpctx, hin->msat, NULL);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!check_fwd_amount(hin, amt_to_forward, hin->msat, fee)) {
|
if (!check_fwd_amount(hin, amt_to_forward, hin->msat, fee)) {
|
||||||
failmsg = towire_fee_insufficient(tmpctx, hin->msat,
|
needs_update_appended = true;
|
||||||
next->stripped_update);
|
failmsg = towire_fee_insufficient(tmpctx, hin->msat, NULL);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!check_cltv(hin, cltv_expiry, outgoing_cltv_value,
|
if (!check_cltv(hin, cltv_expiry, outgoing_cltv_value,
|
||||||
ld->config.cltv_expiry_delta)) {
|
ld->config.cltv_expiry_delta)) {
|
||||||
|
needs_update_appended = true;
|
||||||
failmsg = towire_incorrect_cltv_expiry(tmpctx, cltv_expiry,
|
failmsg = towire_incorrect_cltv_expiry(tmpctx, cltv_expiry,
|
||||||
next->stripped_update);
|
NULL);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (amount_msat_greater(amt_to_forward,
|
if (amount_msat_greater(amt_to_forward,
|
||||||
chainparams->max_payment)) {
|
chainparams->max_payment)) {
|
||||||
/* ENOWUMBO! */
|
/* ENOWUMBO! */
|
||||||
|
needs_update_appended = false;
|
||||||
failmsg = towire_required_channel_feature_missing(tmpctx);
|
failmsg = towire_required_channel_feature_missing(tmpctx);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -723,8 +729,8 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
"Expiry cltv %u too close to current %u",
|
"Expiry cltv %u too close to current %u",
|
||||||
outgoing_cltv_value,
|
outgoing_cltv_value,
|
||||||
get_block_height(ld->topology));
|
get_block_height(ld->topology));
|
||||||
failmsg = towire_expiry_too_soon(tmpctx,
|
needs_update_appended = true;
|
||||||
next->stripped_update);
|
failmsg = towire_expiry_too_soon(tmpctx, NULL);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,17 +746,22 @@ static void forward_htlc(struct htlc_in *hin,
|
|||||||
outgoing_cltv_value,
|
outgoing_cltv_value,
|
||||||
get_block_height(ld->topology),
|
get_block_height(ld->topology),
|
||||||
ld->config.locktime_max);
|
ld->config.locktime_max);
|
||||||
|
needs_update_appended = false;
|
||||||
failmsg = towire_expiry_too_far(tmpctx);
|
failmsg = towire_expiry_too_far(tmpctx);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
failmsg = send_htlc_out(tmpctx, next, amt_to_forward,
|
failmsg = send_htlc_out(tmpctx, next, amt_to_forward,
|
||||||
outgoing_cltv_value, &hin->payment_hash,
|
outgoing_cltv_value, &hin->payment_hash,
|
||||||
0, next_onion, hin, &hout);
|
0, next_onion, hin,
|
||||||
|
&hout, &needs_update_appended);
|
||||||
if (!failmsg)
|
if (!failmsg)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
if (needs_update_appended)
|
||||||
|
local_fail_in_htlc_needs_update(hin, failmsg, next->scid);
|
||||||
|
else
|
||||||
local_fail_in_htlc(hin, failmsg);
|
local_fail_in_htlc(hin, failmsg);
|
||||||
wallet_forwarded_payment_add(ld->wallet,
|
wallet_forwarded_payment_add(ld->wallet,
|
||||||
hin, next->scid, hout,
|
hin, next->scid, hout,
|
||||||
@@ -798,7 +809,6 @@ static void channel_resolve_reply(struct subd *gossip, const u8 *msg,
|
|||||||
|
|
||||||
forward_htlc(gr->hin, gr->hin->cltv_expiry,
|
forward_htlc(gr->hin, gr->hin->cltv_expiry,
|
||||||
gr->amt_to_forward, gr->outgoing_cltv_value, peer_id,
|
gr->amt_to_forward, gr->outgoing_cltv_value, peer_id,
|
||||||
take(stripped_update),
|
|
||||||
gr->next_onion);
|
gr->next_onion);
|
||||||
tal_free(gr);
|
tal_free(gr);
|
||||||
}
|
}
|
||||||
@@ -1421,7 +1431,7 @@ static void remove_htlc_out(struct channel *channel, struct htlc_out *hout)
|
|||||||
|
|
||||||
/* If it's failed, now we can forward since it's completely locked-in */
|
/* If it's failed, now we can forward since it's completely locked-in */
|
||||||
if (!hout->preimage) {
|
if (!hout->preimage) {
|
||||||
fail_out_htlc(hout, NULL);
|
fail_out_htlc(hout, NULL, NULL);
|
||||||
} else {
|
} else {
|
||||||
struct amount_msat oldamt = channel->our_msat;
|
struct amount_msat oldamt = channel->our_msat;
|
||||||
/* We paid for this HTLC, so deduct balance. */
|
/* We paid for this HTLC, so deduct balance. */
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void peer_got_revoke(struct channel *channel, const u8 *msg);
|
|||||||
void update_per_commit_point(struct channel *channel,
|
void update_per_commit_point(struct channel *channel,
|
||||||
const struct pubkey *per_commitment_point);
|
const struct pubkey *per_commitment_point);
|
||||||
|
|
||||||
/* Returns NULL on success, otherwise failmsg */
|
/* Returns NULL on success, otherwise failmsg (and sets *needs_update_appended)*/
|
||||||
const u8 *send_htlc_out(const tal_t *ctx,
|
const u8 *send_htlc_out(const tal_t *ctx,
|
||||||
struct channel *out,
|
struct channel *out,
|
||||||
struct amount_msat amount, u32 cltv,
|
struct amount_msat amount, u32 cltv,
|
||||||
@@ -55,7 +55,8 @@ const u8 *send_htlc_out(const tal_t *ctx,
|
|||||||
u64 partid,
|
u64 partid,
|
||||||
const u8 *onion_routing_packet,
|
const u8 *onion_routing_packet,
|
||||||
struct htlc_in *in,
|
struct htlc_in *in,
|
||||||
struct htlc_out **houtp);
|
struct htlc_out **houtp,
|
||||||
|
bool *needs_update_appended);
|
||||||
|
|
||||||
void onchain_failed_our_htlc(const struct channel *channel,
|
void onchain_failed_our_htlc(const struct channel *channel,
|
||||||
const struct htlc_stub *htlc,
|
const struct htlc_stub *htlc,
|
||||||
|
|||||||
@@ -184,8 +184,11 @@ def test_lightningd_still_loading(node_factory, bitcoind, executor):
|
|||||||
assert 'warning_bitcoind_sync' not in l1.rpc.getinfo()
|
assert 'warning_bitcoind_sync' not in l1.rpc.getinfo()
|
||||||
assert 'warning_lightningd_sync' in l1.rpc.getinfo()
|
assert 'warning_lightningd_sync' in l1.rpc.getinfo()
|
||||||
|
|
||||||
|
# Make sure it's connected to l2 (otherwise we get TEMPORARY_CHANNEL_FAILURE)
|
||||||
|
wait_for(lambda: only_one(l1.rpc.listpeers(l2.info['id'])['peers'])['connected'])
|
||||||
|
|
||||||
# Payments will fail. FIXME: More informative msg?
|
# Payments will fail. FIXME: More informative msg?
|
||||||
with pytest.raises(RpcError, match=r'TEMPORARY_CHANNEL_FAILURE'):
|
with pytest.raises(RpcError, match=r'TEMPORARY_NODE_FAILURE'):
|
||||||
l1.pay(l2, 1000)
|
l1.pay(l2, 1000)
|
||||||
|
|
||||||
# Can't fund a new channel.
|
# Can't fund a new channel.
|
||||||
|
|||||||
Reference in New Issue
Block a user