mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
state: use callbacks for htlc management.
We only have one htlc in flight at a time, but sometimes it changes: particularly when we are lowpriority and a highpriority request comes in. Handle this using a set of callbacks for htlc handling. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
c1dc7137ba
commit
63cb0667f6
3 changed files with 293 additions and 224 deletions
99
state.c
99
state.c
|
@ -94,7 +94,6 @@ enum command_status state(const tal_t *ctx,
|
|||
struct bitcoin_tx *tx;
|
||||
Pkt *err;
|
||||
struct htlc_watch *htlcs;
|
||||
struct htlc_progress *htlcprog;
|
||||
enum command_status cstatus = CMD_NONE;
|
||||
|
||||
/* NULL-terminated linked list. */
|
||||
|
@ -376,19 +375,14 @@ enum command_status state(const tal_t *ctx,
|
|||
add_effect(effect, send_pkt,
|
||||
pkt_htlc_update(ctx, peer,
|
||||
idata->htlc_prog));
|
||||
add_effect(effect, htlc_in_progress, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_HTLC_ACCEPT));
|
||||
} else if (input_is(input, CMD_SEND_HTLC_FULFILL)) {
|
||||
/* We are to send an HTLC fulfill. */
|
||||
/* This gives us the r value (FIXME: type!) */
|
||||
add_effect(effect, r_value,
|
||||
r_value_from_cmd(ctx, peer, idata->htlc));
|
||||
add_effect(effect, send_pkt,
|
||||
pkt_htlc_fulfill(ctx, peer,
|
||||
idata->htlc_prog));
|
||||
add_effect(effect, htlc_in_progress, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
|
@ -397,7 +391,6 @@ enum command_status state(const tal_t *ctx,
|
|||
add_effect(effect, send_pkt,
|
||||
pkt_htlc_timedout(ctx, peer,
|
||||
idata->htlc_prog));
|
||||
add_effect(effect, htlc_in_progress, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
|
@ -406,7 +399,6 @@ enum command_status state(const tal_t *ctx,
|
|||
add_effect(effect, send_pkt,
|
||||
pkt_htlc_routefail(ctx, peer,
|
||||
idata->htlc_prog));
|
||||
add_effect(effect, htlc_in_progress, idata->htlc_prog);
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_ACCEPT));
|
||||
|
@ -440,16 +432,11 @@ enum command_status state(const tal_t *ctx,
|
|||
case STATE_WAIT_FOR_HTLC_ACCEPT_HIGHPRIO:
|
||||
/* HTLCs can also evoke a refusal. */
|
||||
if (input_is(input, PKT_UPDATE_DECLINE_HTLC)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_declined(peer, idata->pkt);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
/* No update means no priority change. */
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_NORMAL));
|
||||
/* They can't close with an HTLC, so only possible here */
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto accept_closing;
|
||||
}
|
||||
/* Fall thru */
|
||||
case STATE_WAIT_FOR_UPDATE_ACCEPT_LOWPRIO:
|
||||
|
@ -460,8 +447,8 @@ enum command_status state(const tal_t *ctx,
|
|||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_update;
|
||||
|
@ -471,8 +458,8 @@ enum command_status state(const tal_t *ctx,
|
|||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_fulfill;
|
||||
|
@ -482,8 +469,8 @@ enum command_status state(const tal_t *ctx,
|
|||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_timedout;
|
||||
|
@ -493,77 +480,87 @@ enum command_status state(const tal_t *ctx,
|
|||
return cstatus;
|
||||
|
||||
/* Otherwise, process their request first: defer ours */
|
||||
peer_htlc_ours_deferred(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_REQUEUE);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
/* Stay busy, since we're processing theirs. */
|
||||
change_peer_cond(peer, PEER_CMD_OK, PEER_BUSY);
|
||||
goto accept_htlc_routefail;
|
||||
} else if (input_is(input, PKT_UPDATE_ACCEPT)) {
|
||||
struct signature *sig;
|
||||
err = accept_pkt_update_accept(ctx, peer, idata->pkt,
|
||||
&sig, effect);
|
||||
&sig);
|
||||
if (err) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
add_effect(effect, update_theirsig, sig);
|
||||
add_effect(effect, send_pkt,
|
||||
pkt_update_signature(ctx, peer));
|
||||
/* HTLC is signed (though old tx not revoked yet!) */
|
||||
add_effect(effect, htlc_fulfill, true);
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_COMPLETE));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto start_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
case STATE_WAIT_FOR_UPDATE_COMPLETE_LOWPRIO:
|
||||
case STATE_WAIT_FOR_UPDATE_COMPLETE_HIGHPRIO:
|
||||
if (input_is(input, PKT_UPDATE_COMPLETE)) {
|
||||
err = accept_pkt_update_complete(ctx, peer, idata->pkt,
|
||||
effect);
|
||||
err = accept_pkt_update_complete(ctx, peer, idata->pkt);
|
||||
if (err) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
peer_htlc_done(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_SUCCESS);
|
||||
return next_state(peer, cstatus,
|
||||
toggle_prio(peer->state, STATE_NORMAL));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
peer_htlc_aborted(peer);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
|
@ -573,36 +570,37 @@ enum command_status state(const tal_t *ctx,
|
|||
if (input_is(input, PKT_UPDATE_SIGNATURE)) {
|
||||
struct signature *sig;
|
||||
err = accept_pkt_update_signature(ctx, peer, idata->pkt,
|
||||
&sig, effect);
|
||||
&sig);
|
||||
if (err) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
add_effect(effect, update_theirsig, sig);
|
||||
add_effect(effect, send_pkt,
|
||||
pkt_update_complete(ctx, peer));
|
||||
add_effect(effect, htlc_fulfill, true);
|
||||
|
||||
peer_htlc_done(peer);
|
||||
change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK);
|
||||
/* Toggle between high and low priority states. */
|
||||
return next_state(peer, cstatus,
|
||||
toggle_prio(peer->state, STATE_NORMAL));
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto old_commit_spotted;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto accept_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
add_effect(effect, htlc_abandon, true);
|
||||
peer_htlc_aborted(peer);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
break;
|
||||
|
@ -780,8 +778,7 @@ enum command_status state(const tal_t *ctx,
|
|||
BITS_TO_STATE(bits));
|
||||
} else if (input_is(input, BITCOIN_HTLC_TOTHEM_SPENT)) {
|
||||
/* They revealed R value. */
|
||||
add_effect(effect, r_value,
|
||||
bitcoin_r_value(ctx, idata->htlc));
|
||||
peer_tx_revealed_r_value(peer, idata->btc);
|
||||
/* We don't care any more. */
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch(ctx, idata->htlc,
|
||||
|
@ -807,10 +804,6 @@ enum command_status state(const tal_t *ctx,
|
|||
tx = bitcoin_htlc_spend(ctx, peer,
|
||||
idata->htlc);
|
||||
|
||||
/* This gives us the r value. */
|
||||
add_effect(effect, r_value,
|
||||
r_value_from_cmd(ctx, peer,
|
||||
idata->htlc));
|
||||
/* Spend it... */
|
||||
add_effect(effect, broadcast_tx, tx);
|
||||
/* We're done when it gets buried. */
|
||||
|
@ -1047,51 +1040,43 @@ them_unilateral:
|
|||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_SPENDTHEM);
|
||||
|
||||
accept_htlc_update:
|
||||
err = accept_pkt_htlc_update(ctx, peer, idata->pkt, &decline, &htlcprog,
|
||||
effect);
|
||||
err = accept_pkt_htlc_update(ctx, peer, idata->pkt, &decline, effect);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
if (decline) {
|
||||
add_effect(effect, send_pkt, decline);
|
||||
peer_htlc_declined(peer, decline);
|
||||
/* No update means no priority change. */
|
||||
change_peer_cond(peer, PEER_BUSY, PEER_CMD_OK);
|
||||
/* We may already be in STATE_NORMAL */
|
||||
return next_state_nocheck(peer, cstatus,
|
||||
prio(peer->state, STATE_NORMAL));
|
||||
}
|
||||
add_effect(effect, htlc_in_progress, htlcprog);
|
||||
add_effect(effect, send_pkt, pkt_update_accept(ctx, peer));
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
accept_htlc_routefail:
|
||||
err = accept_pkt_htlc_routefail(ctx, peer, idata->pkt, &htlcprog,
|
||||
effect);
|
||||
err = accept_pkt_htlc_routefail(ctx, peer, idata->pkt, effect);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
add_effect(effect, htlc_in_progress, htlcprog);
|
||||
add_effect(effect, send_pkt, pkt_update_accept(ctx, peer));
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
accept_htlc_timedout:
|
||||
err = accept_pkt_htlc_timedout(ctx, peer, idata->pkt, &htlcprog,
|
||||
effect);
|
||||
err = accept_pkt_htlc_timedout(ctx, peer, idata->pkt, effect);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
add_effect(effect, htlc_in_progress, htlcprog);
|
||||
add_effect(effect, send_pkt, pkt_update_accept(ctx, peer));
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
accept_htlc_fulfill:
|
||||
err = accept_pkt_htlc_fulfill(ctx, peer, idata->pkt, &htlcprog,
|
||||
effect);
|
||||
err = accept_pkt_htlc_fulfill(ctx, peer, idata->pkt);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
add_effect(effect, htlc_in_progress, htlcprog);
|
||||
add_effect(effect, send_pkt, pkt_update_accept(ctx, peer));
|
||||
add_effect(effect, r_value, r_value_from_pkt(ctx, idata->pkt));
|
||||
return next_state(peer, cstatus,
|
||||
prio(peer->state, STATE_WAIT_FOR_UPDATE_SIG));
|
||||
|
||||
|
|
77
state.h
77
state.h
|
@ -13,11 +13,7 @@ enum state_effect_type {
|
|||
STATE_EFFECT_unwatch,
|
||||
/* FIXME: Use a watch for this?. */
|
||||
STATE_EFFECT_close_timeout,
|
||||
STATE_EFFECT_htlc_in_progress,
|
||||
STATE_EFFECT_update_theirsig,
|
||||
STATE_EFFECT_htlc_abandon,
|
||||
STATE_EFFECT_htlc_fulfill,
|
||||
STATE_EFFECT_r_value,
|
||||
/* FIXME: Combine into watches? */
|
||||
STATE_EFFECT_watch_htlcs,
|
||||
STATE_EFFECT_unwatch_htlc,
|
||||
|
@ -51,21 +47,9 @@ struct state_effect {
|
|||
/* Set a timeout for close tx. */
|
||||
enum state_input close_timeout;
|
||||
|
||||
/* HTLC we're working on. */
|
||||
struct htlc_progress *htlc_in_progress;
|
||||
|
||||
/* Their signature for the new commit tx. */
|
||||
struct signature *update_theirsig;
|
||||
|
||||
/* Stop working on HTLC. */
|
||||
bool htlc_abandon;
|
||||
|
||||
/* Finished working on HTLC. */
|
||||
bool htlc_fulfill;
|
||||
|
||||
/* R value. */
|
||||
const struct htlc_rval *r_value;
|
||||
|
||||
/* HTLC outputs to watch. */
|
||||
const struct htlc_watch *watch_htlcs;
|
||||
|
||||
|
@ -132,6 +116,35 @@ struct signature;
|
|||
/* Inform peer have an unexpected packet. */
|
||||
void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt);
|
||||
|
||||
/* Current HTLC management.
|
||||
* The "current" htlc is set before sending CMD_SEND_HTLC_*, or by
|
||||
* accept_pkt_htlc_*.
|
||||
*
|
||||
* After that the state machine manages the current htlc, eventually giving one
|
||||
* of the following calls (which should reset the current HTLC):
|
||||
*
|
||||
* - peer_htlc_declined: sent PKT_UPDATE_DECLINE_HTLC.
|
||||
* - peer_htlc_ours_deferred: their update was higher priority, retry later.
|
||||
* - peer_htlc_added: a new HTLC was added successfully.
|
||||
* - peer_htlc_fulfilled: an existing HTLC was fulfilled successfully.
|
||||
* - peer_htlc_timedout: an existing HTLC was timed out successfully.
|
||||
* - peer_htlc_routefail: an existing HTLC failed to route.
|
||||
* - peer_htlc_aborted: eg. comms error
|
||||
*/
|
||||
|
||||
/* Someone declined our HTLC: details in pkt (we will also get CMD_FAIL) */
|
||||
void peer_htlc_declined(struct peer *peer, const Pkt *pkt);
|
||||
/* Called when their update overrides our update cmd. */
|
||||
void peer_htlc_ours_deferred(struct peer *peer);
|
||||
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
|
||||
void peer_htlc_done(struct peer *peer);
|
||||
/* Someone aborted an existing HTLC. */
|
||||
void peer_htlc_aborted(struct peer *peer);
|
||||
|
||||
/* An on-chain transaction revealed an R value. */
|
||||
void peer_tx_revealed_r_value(struct peer *peer,
|
||||
const struct bitcoin_event *btc);
|
||||
|
||||
/* Create various kinds of packets, allocated off @ctx */
|
||||
Pkt *pkt_open(const tal_t *ctx, const struct peer *peer,
|
||||
OpenChannel__AnchorOffer anchor);
|
||||
|
@ -171,40 +184,32 @@ Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
|
|||
struct state_effect **effect);
|
||||
|
||||
Pkt *accept_pkt_htlc_update(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
Pkt **decline,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct state_effect **effect);
|
||||
|
||||
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect);
|
||||
|
||||
Pkt *accept_pkt_htlc_timedout(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect);
|
||||
|
||||
Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct state_effect **effect);
|
||||
struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_update_accept(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig,
|
||||
struct state_effect **effect);
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig);
|
||||
|
||||
Pkt *accept_pkt_update_complete(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect);
|
||||
struct peer *peer, const Pkt *pkt);
|
||||
|
||||
Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
struct peer *peer,
|
||||
const Pkt *pkt,
|
||||
struct signature **sig,
|
||||
struct state_effect **effect);
|
||||
struct signature **sig);
|
||||
|
||||
Pkt *accept_pkt_close(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
|
@ -410,10 +415,4 @@ struct bitcoin_tx *bitcoin_htlc_spend(const tal_t *ctx,
|
|||
const struct peer *peer,
|
||||
const struct htlc *htlc);
|
||||
|
||||
struct htlc_rval *r_value_from_cmd(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct htlc *htlc);
|
||||
struct htlc_rval *bitcoin_r_value(const tal_t *ctx, const struct htlc *htlc);
|
||||
struct htlc_rval *r_value_from_pkt(const tal_t *ctx, const Pkt *pkt);
|
||||
|
||||
#endif /* LIGHTNING_STATE_H */
|
||||
|
|
|
@ -119,6 +119,9 @@ struct peer {
|
|||
|
||||
/* id == -1 if none currently. */
|
||||
struct htlc_progress current_htlc;
|
||||
|
||||
/* Transitory: True if we just declined an HTLC. */
|
||||
bool htlc_declined;
|
||||
|
||||
unsigned int num_htlcs_to_them, num_htlcs_to_us;
|
||||
struct htlc htlcs_to_them[MAX_HTLCS], htlcs_to_us[MAX_HTLCS];
|
||||
|
@ -479,6 +482,7 @@ static unsigned int htlc_id_from_pkt(const Pkt *pkt)
|
|||
|
||||
static Pkt *htlc_pkt(const tal_t *ctx, const char *prefix, unsigned int id)
|
||||
{
|
||||
assert(id != -1);
|
||||
return (Pkt *)tal_fmt(ctx, "%s: HTLC #%u", prefix, id);
|
||||
}
|
||||
|
||||
|
@ -543,6 +547,48 @@ static struct htlc *find_htlc_spend(const struct peer *peer,
|
|||
return (struct htlc *)h;
|
||||
}
|
||||
|
||||
/* FIXME: order functions correctly. */
|
||||
static void report_trail(const struct trail *t, const char *problem);
|
||||
|
||||
static void set_current_htlc(struct peer *peer,
|
||||
unsigned int id,
|
||||
bool to_them, bool adding)
|
||||
{
|
||||
if (peer->current_htlc.htlc.id != -1)
|
||||
report_trail(peer->trail, "Already have current htlc");
|
||||
|
||||
assert(id != -1);
|
||||
peer->current_htlc.htlc.id = id;
|
||||
peer->current_htlc.htlc.to_them = to_them;
|
||||
peer->current_htlc.adding = adding;
|
||||
}
|
||||
|
||||
static void clear_current_htlc(struct peer *peer)
|
||||
{
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
report_trail(peer->trail, "No current htlc");
|
||||
|
||||
peer->current_htlc.htlc.id = -1;
|
||||
}
|
||||
|
||||
static bool rval_known(const struct peer *peer, unsigned int id)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < peer->num_rvals_known; i++)
|
||||
if (peer->rvals_known[i] == id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void add_rval(struct peer *peer, unsigned int id)
|
||||
{
|
||||
if (!rval_known(peer, id)) {
|
||||
assert(peer->num_rvals_known < ARRAY_SIZE(peer->rvals_known));
|
||||
peer->rvals_known[peer->num_rvals_known++] = id;
|
||||
}
|
||||
}
|
||||
|
||||
Pkt *pkt_open(const tal_t *ctx, const struct peer *peer,
|
||||
OpenChannel__AnchorOffer anchor)
|
||||
{
|
||||
|
@ -590,17 +636,19 @@ Pkt *pkt_htlc_routefail(const tal_t *ctx, const struct peer *peer,
|
|||
|
||||
Pkt *pkt_update_accept(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
return new_pkt(ctx, PKT_UPDATE_ACCEPT);
|
||||
return htlc_pkt(ctx, "PKT_UPDATE_ACCEPT", peer->current_htlc.htlc.id);
|
||||
}
|
||||
|
||||
Pkt *pkt_update_signature(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
return new_pkt(ctx, PKT_UPDATE_SIGNATURE);
|
||||
return htlc_pkt(ctx, "PKT_UPDATE_SIGNATURE",
|
||||
peer->current_htlc.htlc.id);
|
||||
}
|
||||
|
||||
Pkt *pkt_update_complete(const tal_t *ctx, const struct peer *peer)
|
||||
{
|
||||
return new_pkt(ctx, PKT_UPDATE_COMPLETE);
|
||||
return htlc_pkt(ctx, "PKT_UPDATE_COMPLETE",
|
||||
peer->current_htlc.htlc.id);
|
||||
}
|
||||
|
||||
Pkt *pkt_err(const tal_t *ctx, const char *msg)
|
||||
|
@ -657,30 +705,26 @@ Pkt *accept_pkt_open_commit_sig(const tal_t *ctx,
|
|||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_update(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
Pkt **decline,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct state_effect **effect)
|
||||
{
|
||||
if (fail(peer, FAIL_ACCEPT_HTLC_UPDATE))
|
||||
return pkt_err(ctx, "Error inject");
|
||||
|
||||
/* This is the current htlc: If they propose it, it's to us. */
|
||||
set_current_htlc(peer, htlc_id_from_pkt(pkt), false, true);
|
||||
|
||||
if (fail(peer, FAIL_DECLINE_HTLC))
|
||||
*decline = new_pkt(ctx, PKT_UPDATE_DECLINE_HTLC);
|
||||
else {
|
||||
else
|
||||
*decline = NULL;
|
||||
*htlcprog = tal(ctx, struct htlc_progress);
|
||||
/* If they propose it, it's to us. */
|
||||
(*htlcprog)->htlc.to_them = false;
|
||||
(*htlcprog)->htlc.id = htlc_id_from_pkt(pkt);
|
||||
(*htlcprog)->adding = true;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
|
@ -692,15 +736,13 @@ Pkt *accept_pkt_htlc_routefail(const tal_t *ctx,
|
|||
/* The shouldn't fail unless it's to them */
|
||||
assert(h->to_them);
|
||||
|
||||
*htlcprog = tal(ctx, struct htlc_progress);
|
||||
(*htlcprog)->htlc = *h;
|
||||
(*htlcprog)->adding = false;
|
||||
/* This is the current htlc */
|
||||
set_current_htlc(peer, h->id, h->to_them, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_timedout(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
|
@ -711,17 +753,14 @@ Pkt *accept_pkt_htlc_timedout(const tal_t *ctx,
|
|||
|
||||
/* The shouldn't timeout unless it's to us */
|
||||
assert(!h->to_them);
|
||||
|
||||
*htlcprog = tal(ctx, struct htlc_progress);
|
||||
(*htlcprog)->htlc = *h;
|
||||
(*htlcprog)->adding = false;
|
||||
|
||||
/* This is the current htlc */
|
||||
set_current_htlc(peer, h->id, h->to_them, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct htlc_progress **htlcprog,
|
||||
struct state_effect **effect)
|
||||
struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
const struct htlc *h = find_htlc(peer, id);
|
||||
|
@ -732,17 +771,22 @@ Pkt *accept_pkt_htlc_fulfill(const tal_t *ctx,
|
|||
/* The shouldn't complete unless it's to them */
|
||||
assert(h->to_them);
|
||||
|
||||
*htlcprog = tal(ctx, struct htlc_progress);
|
||||
(*htlcprog)->htlc = *h;
|
||||
(*htlcprog)->adding = false;
|
||||
/* This gives us the r value. */
|
||||
add_rval(peer, htlc_id_from_pkt(pkt));
|
||||
|
||||
/* This is the current htlc */
|
||||
set_current_htlc(peer, h->id, h->to_them, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_accept(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig,
|
||||
struct state_effect **effect)
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
|
||||
assert(id == peer->current_htlc.htlc.id);
|
||||
|
||||
if (fail(peer, FAIL_ACCEPT_UPDATE_ACCEPT))
|
||||
return pkt_err(ctx, "Error inject");
|
||||
|
||||
|
@ -751,22 +795,30 @@ Pkt *accept_pkt_update_accept(const tal_t *ctx,
|
|||
}
|
||||
|
||||
Pkt *accept_pkt_update_complete(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct state_effect **effect)
|
||||
struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
|
||||
assert(id == peer->current_htlc.htlc.id);
|
||||
|
||||
if (fail(peer, FAIL_ACCEPT_UPDATE_COMPLETE))
|
||||
return pkt_err(ctx, "Error inject");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Pkt *accept_pkt_update_signature(const tal_t *ctx,
|
||||
const struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig,
|
||||
struct state_effect **effect)
|
||||
struct peer *peer, const Pkt *pkt,
|
||||
struct signature **sig)
|
||||
{
|
||||
unsigned int id = htlc_id_from_pkt(pkt);
|
||||
|
||||
assert(id == peer->current_htlc.htlc.id);
|
||||
|
||||
if (fail(peer, FAIL_ACCEPT_UPDATE_SIGNATURE))
|
||||
return pkt_err(ctx, "Error inject");
|
||||
*sig = (struct signature *)tal_strdup(ctx, "from PKT_UPDATE_SIGNATURE");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1143,29 +1195,6 @@ struct htlc_rval {
|
|||
unsigned int id;
|
||||
};
|
||||
|
||||
struct htlc_rval *r_value_from_cmd(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct htlc *htlc)
|
||||
{
|
||||
struct htlc_rval *r = tal(ctx, struct htlc_rval);
|
||||
r->id = htlc->id;
|
||||
return r;
|
||||
}
|
||||
|
||||
struct htlc_rval *bitcoin_r_value(const tal_t *ctx, const struct htlc *htlc)
|
||||
{
|
||||
struct htlc_rval *r = tal(ctx, struct htlc_rval);
|
||||
r->id = htlc->id;
|
||||
return r;
|
||||
}
|
||||
|
||||
struct htlc_rval *r_value_from_pkt(const tal_t *ctx, const Pkt *pkt)
|
||||
{
|
||||
struct htlc_rval *r = tal(ctx, struct htlc_rval);
|
||||
r->id = htlc_id_from_pkt(pkt);
|
||||
return r;
|
||||
}
|
||||
|
||||
#include "state.c"
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1186,6 +1215,7 @@ static void peer_init(struct peer *peer,
|
|||
peer->num_htlc_spends_to_them = 0;
|
||||
peer->num_rvals_known = 0;
|
||||
peer->error = NULL;
|
||||
peer->htlc_declined = false;
|
||||
memset(peer->core.outputs, 0, sizeof(peer->core.outputs));
|
||||
peer->pkt_data[0] = -1;
|
||||
peer->core.current_command = INPUT_NONE;
|
||||
|
@ -1352,6 +1382,21 @@ static void remove_htlc(struct htlc *to_us, unsigned int *num_to_us,
|
|||
(*n)--;
|
||||
}
|
||||
|
||||
static void remove_htlc_id(struct peer *peer, unsigned int id)
|
||||
{
|
||||
const struct htlc *h = find_htlc(peer, id);
|
||||
|
||||
if (!h)
|
||||
report_trail(peer->trail, "Removing nonexistent HTLC?");
|
||||
if (h->to_them != peer->current_htlc.htlc.to_them)
|
||||
report_trail(peer->trail,
|
||||
"Removing disagreed about to_them");
|
||||
remove_htlc(peer->htlcs_to_us, &peer->num_htlcs_to_us,
|
||||
peer->htlcs_to_them, &peer->num_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->htlcs_to_us), h);
|
||||
}
|
||||
|
||||
|
||||
static bool outstanding_htlc_watches(const struct peer *peer)
|
||||
{
|
||||
return peer->num_live_htlcs_to_us
|
||||
|
@ -1360,16 +1405,6 @@ static bool outstanding_htlc_watches(const struct peer *peer)
|
|||
|| peer->num_htlc_spends_to_them;
|
||||
}
|
||||
|
||||
static bool rval_known(const struct peer *peer, unsigned int id)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < peer->num_rvals_known; i++)
|
||||
if (peer->rvals_known[i] == id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const char *str = (const char *)pkt;
|
||||
|
@ -1382,6 +1417,64 @@ void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
|
|||
report_trail(peer->trail, "Unexpected packet");
|
||||
}
|
||||
|
||||
/* Called when their update overrides our update cmd. */
|
||||
void peer_htlc_ours_deferred(struct peer *peer)
|
||||
{
|
||||
/* Only happens for HTLC commands of low priority. */
|
||||
if (high_priority(peer->state))
|
||||
report_trail(peer->trail, "Defer while high priority");
|
||||
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
report_trail(peer->trail, "Deferred with no current HTLC");
|
||||
if (!input_is(peer->core.current_command, CMD_SEND_UPDATE_ANY))
|
||||
report_trail(peer->trail, "Deferred their HTLC?");
|
||||
|
||||
/* FIXME: Expect CMD_REQUEUE */
|
||||
clear_current_htlc(peer);
|
||||
}
|
||||
|
||||
/* Successfully added/fulfilled/timedout/routefail an HTLC. */
|
||||
void peer_htlc_done(struct peer *peer)
|
||||
{
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
report_trail(peer->trail, "Adding with no current HTLC");
|
||||
|
||||
if (peer->current_htlc.adding) {
|
||||
add_htlc(peer->htlcs_to_us, &peer->num_htlcs_to_us,
|
||||
peer->htlcs_to_them, &peer->num_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->htlcs_to_us),
|
||||
&peer->current_htlc.htlc);
|
||||
} else {
|
||||
remove_htlc_id(peer, peer->current_htlc.htlc.id);
|
||||
}
|
||||
clear_current_htlc(peer);
|
||||
}
|
||||
|
||||
/* Someone aborted an existing HTLC update. */
|
||||
void peer_htlc_aborted(struct peer *peer)
|
||||
{
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
report_trail(peer->trail, "Abort with no current HTLC");
|
||||
clear_current_htlc(peer);
|
||||
}
|
||||
|
||||
void peer_htlc_declined(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
report_trail(peer->trail, "Decline with no current HTLC");
|
||||
if (!peer->current_htlc.adding)
|
||||
report_trail(peer->trail, "Decline but HTLC not marked for add");
|
||||
clear_current_htlc(peer);
|
||||
peer->htlc_declined = true;
|
||||
}
|
||||
|
||||
void peer_tx_revealed_r_value(struct peer *peer,
|
||||
const struct bitcoin_event *btc)
|
||||
{
|
||||
const struct htlc *htlc = (struct htlc *)btc;
|
||||
add_rval(peer, htlc->id);
|
||||
}
|
||||
|
||||
/* We apply them backwards, which helps our assertions. It's not actually
|
||||
* required. */
|
||||
static const char *apply_effects(struct peer *peer,
|
||||
|
@ -1463,60 +1556,8 @@ static const char *apply_effects(struct peer *peer,
|
|||
assert(effect->u.close_timeout
|
||||
== INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
break;
|
||||
case STATE_EFFECT_htlc_in_progress:
|
||||
if (peer->current_htlc.htlc.id != -1)
|
||||
return "HTLC already in progress";
|
||||
peer->current_htlc = *effect->u.htlc_in_progress;
|
||||
break;
|
||||
case STATE_EFFECT_update_theirsig:
|
||||
break;
|
||||
case STATE_EFFECT_htlc_abandon:
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
return "HTLC not in progress, can't abandon";
|
||||
peer->current_htlc.htlc.id = -1;
|
||||
break;
|
||||
case STATE_EFFECT_htlc_fulfill:
|
||||
if (peer->current_htlc.htlc.id == -1)
|
||||
return "HTLC not in progress, can't complete";
|
||||
|
||||
if (peer->current_htlc.adding) {
|
||||
add_htlc(peer->htlcs_to_us,
|
||||
&peer->num_htlcs_to_us,
|
||||
peer->htlcs_to_them,
|
||||
&peer->num_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->htlcs_to_us),
|
||||
&peer->current_htlc.htlc);
|
||||
} else {
|
||||
const struct htlc *h;
|
||||
h = find_htlc(peer,
|
||||
peer->current_htlc.htlc.id);
|
||||
if (!h)
|
||||
return "Removing nonexistent HTLC?";
|
||||
if (h->to_them !=
|
||||
peer->current_htlc.htlc.to_them)
|
||||
return "Removing disagreed about to_them";
|
||||
remove_htlc(peer->htlcs_to_us, &peer->num_htlcs_to_us,
|
||||
peer->htlcs_to_them,
|
||||
&peer->num_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->htlcs_to_us),
|
||||
h);
|
||||
}
|
||||
peer->current_htlc.htlc.id = -1;
|
||||
break;
|
||||
case STATE_EFFECT_r_value:
|
||||
/* We set r_value when they spend an HTLC, so
|
||||
* we can set this multiple times (multiple commit
|
||||
* txs) */
|
||||
if (!rval_known(peer, effect->u.r_value->id)) {
|
||||
if (peer->num_rvals_known
|
||||
== ARRAY_SIZE(peer->rvals_known))
|
||||
return "Too many rvals";
|
||||
|
||||
peer->rvals_known[peer->num_rvals_known++]
|
||||
= effect->u.r_value->id;
|
||||
}
|
||||
break;
|
||||
|
||||
case STATE_EFFECT_watch_htlcs:
|
||||
assert(peer->num_live_htlcs_to_us
|
||||
+ effect->u.watch_htlcs->num_htlcs_to_us
|
||||
|
@ -1632,6 +1673,9 @@ static const char *check_changes(const struct peer *old, struct peer *new,
|
|||
return tal_fmt(NULL,
|
||||
"cond CLOSE with pending command %s",
|
||||
input_name(new->core.current_command));
|
||||
if (new->current_htlc.htlc.id != -1)
|
||||
return tal_fmt(NULL,
|
||||
"cond CLOSE with pending htlc");
|
||||
}
|
||||
if (new->cond == PEER_CLOSED) {
|
||||
/* FIXME: Move to state core */
|
||||
|
@ -1646,6 +1690,7 @@ static const char *check_changes(const struct peer *old, struct peer *new,
|
|||
&& new->cond != PEER_CLOSED)
|
||||
return "packets still open after error pkt";
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1663,10 +1708,25 @@ static const char *apply_all_effects(const struct peer *old,
|
|||
if (cstatus != CMD_NONE) {
|
||||
assert(peer->core.current_command != INPUT_NONE);
|
||||
/* We should only requeue HTLCs if we're lowprio */
|
||||
if (cstatus == CMD_REQUEUE)
|
||||
assert(!high_priority(old->state)
|
||||
&& input_is(peer->core.current_command,
|
||||
CMD_SEND_UPDATE_ANY));
|
||||
if (cstatus == CMD_REQUEUE) {
|
||||
if (high_priority(old->state))
|
||||
return "CMD_REQUEUE despite high prio state";
|
||||
else if (!input_is(peer->core.current_command,
|
||||
CMD_SEND_UPDATE_ANY))
|
||||
return tal_fmt(NULL, "CMD_REQUEUE on cmd %s",
|
||||
input_name(peer->core.current_command));
|
||||
/* We expect to be replaced by their HTLC
|
||||
* (unless we inject an error!). */
|
||||
if (peer->current_htlc.htlc.id == -1
|
||||
&& peer->cond != PEER_CLOSED
|
||||
&& !peer->htlc_declined)
|
||||
return tal_fmt(NULL, "CMD_REQUEUE but no new htlc?");
|
||||
} else {
|
||||
/* Expect no HTLCs in other cases. */
|
||||
if (peer->current_htlc.htlc.id != -1)
|
||||
return tal_fmt(NULL, "%s but still have htlc?",
|
||||
cstatus_name(cstatus));
|
||||
}
|
||||
peer->core.current_command = INPUT_NONE;
|
||||
}
|
||||
|
||||
|
@ -1939,6 +1999,8 @@ static void try_input(const struct peer *peer,
|
|||
if (strstarts(state_name(copy.state), "STATE_UNUSED"))
|
||||
report_trail(&t, "Unused state");
|
||||
|
||||
/* Re-set htlc_declined */
|
||||
copy.htlc_declined = false;
|
||||
|
||||
/* Record any output. */
|
||||
if (output) {
|
||||
|
@ -2149,6 +2211,9 @@ static void run_peer(const struct peer *peer,
|
|||
if (peer->cond == PEER_CMD_OK) {
|
||||
unsigned int i;
|
||||
|
||||
/* Shouldn't be currently doing an HTLC. */
|
||||
assert(copy.current_htlc.htlc.id == -1);
|
||||
|
||||
/* Add a new HTLC if not at max. */
|
||||
if (copy.num_htlcs_to_them < MAX_HTLCS) {
|
||||
copy.core.current_command = CMD_SEND_HTLC_UPDATE;
|
||||
|
@ -2156,11 +2221,17 @@ static void run_peer(const struct peer *peer,
|
|||
idata->htlc_prog->adding = true;
|
||||
idata->htlc_prog->htlc.to_them = true;
|
||||
idata->htlc_prog->htlc.id = next_htlc_id();
|
||||
|
||||
|
||||
set_current_htlc(©,
|
||||
idata->htlc_prog->htlc.id,
|
||||
idata->htlc_prog->htlc.to_them,
|
||||
idata->htlc_prog->adding);
|
||||
try_input(©, copy.core.current_command, idata,
|
||||
normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
idata->htlc_prog = tal_free(idata->htlc_prog);
|
||||
/* If it was requeued, may already be reset. */
|
||||
copy.current_htlc.htlc.id = -1;
|
||||
}
|
||||
|
||||
/* We can complete or routefail an HTLC they offered */
|
||||
|
@ -2169,6 +2240,11 @@ static void run_peer(const struct peer *peer,
|
|||
idata->htlc_prog->htlc = peer->htlcs_to_us[i];
|
||||
idata->htlc_prog->adding = false;
|
||||
|
||||
set_current_htlc(©,
|
||||
idata->htlc_prog->htlc.id,
|
||||
idata->htlc_prog->htlc.to_them,
|
||||
idata->htlc_prog->adding);
|
||||
|
||||
/* Only send this once. */
|
||||
if (!rval_known(peer, idata->htlc_prog->htlc.id)) {
|
||||
copy.core.current_command
|
||||
|
@ -2181,6 +2257,8 @@ static void run_peer(const struct peer *peer,
|
|||
try_input(©, copy.core.current_command,
|
||||
idata, normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
/* If it was requeued, may already be reset. */
|
||||
copy.current_htlc.htlc.id = -1;
|
||||
}
|
||||
|
||||
/* We can timeout an HTLC we offered. */
|
||||
|
@ -2189,10 +2267,16 @@ static void run_peer(const struct peer *peer,
|
|||
idata->htlc_prog->htlc = peer->htlcs_to_them[i];
|
||||
idata->htlc_prog->adding = false;
|
||||
|
||||
set_current_htlc(©,
|
||||
idata->htlc_prog->htlc.id,
|
||||
idata->htlc_prog->htlc.to_them,
|
||||
idata->htlc_prog->adding);
|
||||
copy.core.current_command = CMD_SEND_HTLC_TIMEDOUT;
|
||||
try_input(©, copy.core.current_command,
|
||||
idata, normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
/* If it was requeued, may already be reset. */
|
||||
copy.current_htlc.htlc.id = -1;
|
||||
}
|
||||
|
||||
/* Restore current_command */
|
||||
|
@ -2214,10 +2298,11 @@ static void run_peer(const struct peer *peer,
|
|||
}
|
||||
|
||||
for (i = 0; i < peer->num_live_htlcs_to_them; i++) {
|
||||
idata->htlc = (struct htlc *)©.live_htlcs_to_them[i];
|
||||
idata->btc = (struct bitcoin_event *)©.live_htlcs_to_them[i];
|
||||
try_input(©, BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
idata, normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
idata->htlc = (struct htlc *)©.live_htlcs_to_them[i];
|
||||
try_input(©, BITCOIN_HTLC_TOTHEM_TIMEOUT,
|
||||
idata, normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
|
|
Loading…
Add table
Reference in a new issue