mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 22:45:27 +01:00
state: add callbacks for adding/removing watches.
This lets us eliminate struct state_effect altogether (the next patch removes the now-unused arguments). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
1a20e8094f
commit
63ea6bfd7a
3 changed files with 447 additions and 686 deletions
221
state.c
221
state.c
|
@ -12,15 +12,6 @@ static inline bool high_priority(enum state state)
|
|||
#define toggle_prio(state, name) \
|
||||
(!high_priority(state) ? name##_HIGHPRIO : name##_LOWPRIO)
|
||||
|
||||
#define add_effect(e, field, val) \
|
||||
do { \
|
||||
struct state_effect *_e = tal(ctx, struct state_effect); \
|
||||
_e->etype = STATE_EFFECT_##field; \
|
||||
_e->u.field = (val); \
|
||||
_e->next = (*e); \
|
||||
(*e) = _e; \
|
||||
} while(0)
|
||||
|
||||
/* STATE_CLOSE* can be treated as a bitset offset from STATE_CLOSED */
|
||||
#define BITS_TO_STATE(bits) (STATE_CLOSED + (bits))
|
||||
#define STATE_TO_BITS(state) ((state) - STATE_CLOSED)
|
||||
|
@ -110,7 +101,6 @@ enum command_status state(const tal_t *ctx,
|
|||
Pkt *decline;
|
||||
struct bitcoin_tx *tx;
|
||||
Pkt *err;
|
||||
struct htlc_watch *htlcs;
|
||||
enum command_status cstatus = CMD_NONE;
|
||||
|
||||
*out = NULL;
|
||||
|
@ -183,13 +173,12 @@ enum command_status state(const tal_t *ctx,
|
|||
}
|
||||
queue_pkt(out,
|
||||
pkt_open_commit_sig(ctx, peer));
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_anchor(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT,
|
||||
BITCOIN_ANCHOR_UNSPENT,
|
||||
BITCOIN_ANCHOR_THEIRSPEND,
|
||||
BITCOIN_ANCHOR_OTHERSPEND));
|
||||
peer_watch_anchor(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT,
|
||||
BITCOIN_ANCHOR_UNSPENT,
|
||||
BITCOIN_ANCHOR_THEIRSPEND,
|
||||
BITCOIN_ANCHOR_OTHERSPEND);
|
||||
|
||||
return next_state(peer, cstatus,
|
||||
STATE_OPEN_WAITING_THEIRANCHOR);
|
||||
|
@ -210,13 +199,12 @@ enum command_status state(const tal_t *ctx,
|
|||
goto err_start_unilateral_close;
|
||||
}
|
||||
queue_tx_broadcast(broadcast, bitcoin_anchor(ctx, peer));
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_anchor(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE,
|
||||
BITCOIN_ANCHOR_UNSPENT,
|
||||
BITCOIN_ANCHOR_THEIRSPEND,
|
||||
BITCOIN_ANCHOR_OTHERSPEND));
|
||||
peer_watch_anchor(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE,
|
||||
BITCOIN_ANCHOR_UNSPENT,
|
||||
BITCOIN_ANCHOR_THEIRSPEND,
|
||||
BITCOIN_ANCHOR_OTHERSPEND);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_OPEN_WAITING_OURANCHOR);
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
|
@ -249,10 +237,9 @@ enum command_status state(const tal_t *ctx,
|
|||
goto anchor_unspent;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_OTHERSPEND)) {
|
||||
|
@ -260,26 +247,23 @@ enum command_status state(const tal_t *ctx,
|
|||
return next_state(peer, cstatus, STATE_ERR_INFORMATION_LEAK);
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
INPUT_NONE);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt_nocleanup;
|
||||
}
|
||||
|
@ -315,34 +299,30 @@ enum command_status state(const tal_t *ctx,
|
|||
STATE_ERR_INFORMATION_LEAK);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto them_unilateral;
|
||||
} else if (input_is(input, CMD_CLOSE)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto start_closing;
|
||||
} else if (input_is(input, PKT_CLOSE)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto accept_closing;
|
||||
} else if (input_is_pkt(input)) {
|
||||
/* We no longer care about anchor depth. */
|
||||
add_effect(effect, unwatch,
|
||||
bitcoin_unwatch_anchor_depth(ctx, peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT));
|
||||
peer_unwatch_anchor_depth(peer,
|
||||
BITCOIN_ANCHOR_DEPTHOK,
|
||||
BITCOIN_ANCHOR_TIMEOUT);
|
||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||
goto unexpected_pkt;
|
||||
}
|
||||
|
@ -738,8 +718,7 @@ enum command_status state(const tal_t *ctx,
|
|||
/* One a steal is complete, we don't care about htlcs
|
||||
* (we stole them all) */
|
||||
if (bits & STATE_CLOSE_HTLCS_BIT)
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch_all(ctx, peer));
|
||||
peer_unwatch_all_htlc_outputs(peer);
|
||||
return next_state(peer, cstatus, STATE_CLOSED);
|
||||
}
|
||||
|
||||
|
@ -764,9 +743,7 @@ enum command_status state(const tal_t *ctx,
|
|||
tx = bitcoin_spend_ours(ctx, peer);
|
||||
/* Now we need to wait for our commit to be done. */
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx,
|
||||
BITCOIN_SPEND_OURS_DONE));
|
||||
peer_watch_tx(peer, tx, BITCOIN_SPEND_OURS_DONE);
|
||||
bits &= ~STATE_CLOSE_OURCOMMIT_BIT;
|
||||
bits |= STATE_CLOSE_SPENDOURS_BIT;
|
||||
return next_state(peer, cstatus, BITS_TO_STATE(bits));
|
||||
|
@ -791,9 +768,8 @@ enum command_status state(const tal_t *ctx,
|
|||
/* They revealed R value. */
|
||||
peer_tx_revealed_r_value(peer, idata->btc);
|
||||
/* We don't care any more. */
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch(ctx, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_output(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, BITCOIN_HTLC_TOTHEM_TIMEOUT)){
|
||||
tx = bitcoin_htlc_timeout(ctx,
|
||||
|
@ -805,11 +781,8 @@ enum command_status state(const tal_t *ctx,
|
|||
* try to spend, revealing rvalue. */
|
||||
|
||||
/* We're done when that gets buried. */
|
||||
add_effect(effect, watch_htlc_spend,
|
||||
htlc_spend_watch(ctx,
|
||||
tx,
|
||||
idata->cmd,
|
||||
BITCOIN_HTLC_RETURN_SPEND_DONE));
|
||||
peer_watch_htlc_spend(peer, tx, idata->htlc,
|
||||
BITCOIN_HTLC_RETURN_SPEND_DONE);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, INPUT_RVALUE)) {
|
||||
tx = bitcoin_htlc_spend(ctx, peer,
|
||||
|
@ -818,44 +791,34 @@ enum command_status state(const tal_t *ctx,
|
|||
/* Spend it... */
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
/* We're done when it gets buried. */
|
||||
add_effect(effect, watch_htlc_spend,
|
||||
htlc_spend_watch(ctx,
|
||||
tx,
|
||||
idata->cmd,
|
||||
BITCOIN_HTLC_FULFILL_SPEND_DONE));
|
||||
peer_watch_htlc_spend(peer, tx, idata->htlc,
|
||||
BITCOIN_HTLC_FULFILL_SPEND_DONE);
|
||||
/* Don't care about this one any more. */
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch(ctx, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_output(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, BITCOIN_HTLC_FULFILL_SPEND_DONE)) {
|
||||
/* Stop watching spend, send
|
||||
* INPUT_NO_MORE_HTLCS when done. */
|
||||
add_effect(effect, unwatch_htlc_spend,
|
||||
htlc_spend_unwatch(ctx,
|
||||
idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_spend(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, BITCOIN_HTLC_RETURN_SPEND_DONE)) {
|
||||
/* Stop watching spend, send
|
||||
* INPUT_NO_MORE_HTLCS when done. */
|
||||
add_effect(effect, unwatch_htlc_spend,
|
||||
htlc_spend_unwatch(ctx,
|
||||
idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_spend(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
|
||||
/* Don't need to watch the HTLC output any more,
|
||||
* either. */
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch(ctx, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_output(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
return unchanged_state(cstatus);
|
||||
} else if (input_is(input, BITCOIN_HTLC_TOUS_TIMEOUT)) {
|
||||
/* They can spend, we no longer care
|
||||
* about this HTLC. */
|
||||
add_effect(effect, unwatch_htlc,
|
||||
htlc_unwatch(ctx, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS));
|
||||
peer_unwatch_htlc_output(peer, idata->htlc,
|
||||
INPUT_NO_MORE_HTLCS);
|
||||
return unchanged_state(cstatus);
|
||||
}
|
||||
}
|
||||
|
@ -871,19 +834,14 @@ enum command_status state(const tal_t *ctx,
|
|||
if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
|
||||
tx = bitcoin_spend_theirs(ctx, peer, idata->btc);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx,
|
||||
BITCOIN_SPEND_THEIRS_DONE));
|
||||
/* HTLC watches. */
|
||||
htlcs = htlc_outputs_their_commit(ctx, peer,
|
||||
idata->btc,
|
||||
peer_watch_tx(peer, tx, BITCOIN_SPEND_THEIRS_DONE);
|
||||
/* HTLC watches: if any, set HTLCs bit. */
|
||||
if (peer_watch_their_htlc_outputs(peer, idata->btc,
|
||||
BITCOIN_HTLC_TOUS_TIMEOUT,
|
||||
BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
if (htlcs) {
|
||||
add_effect(effect, watch_htlcs, htlcs);
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT))
|
||||
bits |= STATE_CLOSE_HTLCS_BIT;
|
||||
}
|
||||
|
||||
bits |= STATE_CLOSE_SPENDTHEM_BIT;
|
||||
return next_state_bits(peer, cstatus, bits);
|
||||
/* This can happen multiple times: need to steal ALL */
|
||||
|
@ -893,9 +851,7 @@ enum command_status state(const tal_t *ctx,
|
|||
return next_state(peer, cstatus,
|
||||
STATE_ERR_INFORMATION_LEAK);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx,
|
||||
BITCOIN_STEAL_DONE));
|
||||
peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE);
|
||||
bits |= STATE_CLOSE_STEAL_BIT;
|
||||
return next_state_bits(peer, cstatus, bits);
|
||||
} else if (input_is(input, BITCOIN_ANCHOR_UNSPENT))
|
||||
|
@ -981,20 +937,16 @@ start_unilateral_close:
|
|||
set_peer_cond(peer, PEER_CLOSED);
|
||||
tx = bitcoin_commit(ctx, peer);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_delayed(ctx, tx,
|
||||
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
|
||||
peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED);
|
||||
|
||||
/* HTLC watches. */
|
||||
htlcs = htlc_outputs_our_commit(ctx, peer, tx,
|
||||
if (peer_watch_our_htlc_outputs(peer, tx,
|
||||
BITCOIN_HTLC_TOUS_TIMEOUT,
|
||||
BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
if (htlcs) {
|
||||
add_effect(effect, watch_htlcs, htlcs);
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT))
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_OURCOMMIT_WITH_HTLCS);
|
||||
}
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_OURCOMMIT);
|
||||
|
||||
err_start_unilateral_close_already_closing:
|
||||
|
@ -1011,9 +963,7 @@ start_unilateral_close_already_closing:
|
|||
set_peer_cond(peer, PEER_CLOSED);
|
||||
tx = bitcoin_commit(ctx, peer);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_delayed(ctx, tx,
|
||||
BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED));
|
||||
peer_watch_delayed(peer, tx, BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED);
|
||||
|
||||
/* We agreed to close: shouldn't have any HTLCs */
|
||||
if (committed_to_htlcs(peer))
|
||||
|
@ -1033,21 +983,17 @@ them_unilateral:
|
|||
set_peer_cond(peer, PEER_CLOSED);
|
||||
tx = bitcoin_spend_theirs(ctx, peer, idata->btc);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx,
|
||||
BITCOIN_SPEND_THEIRS_DONE));
|
||||
peer_watch_tx(peer, tx, BITCOIN_SPEND_THEIRS_DONE);
|
||||
|
||||
/* HTLC watches (based on what they broadcast, which *may* be out
|
||||
* of step with our current state by +/- 1 htlc. */
|
||||
htlcs = htlc_outputs_their_commit(ctx, peer, idata->btc,
|
||||
if (peer_watch_their_htlc_outputs(peer, idata->btc,
|
||||
BITCOIN_HTLC_TOUS_TIMEOUT,
|
||||
BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
if (htlcs) {
|
||||
add_effect(effect, watch_htlcs, htlcs);
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT))
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_SPENDTHEM_WITH_HTLCS);
|
||||
}
|
||||
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_SPENDTHEM);
|
||||
|
||||
accept_htlc_update:
|
||||
|
@ -1100,10 +1046,7 @@ start_closing:
|
|||
err = pkt_err(ctx, "Close forced due to HTLCs");
|
||||
goto err_start_unilateral_close;
|
||||
}
|
||||
add_effect(effect, close_timeout, INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_close(ctx, peer, BITCOIN_CLOSE_DONE));
|
||||
peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
|
||||
/* No more commands, we're already closing. */
|
||||
set_peer_cond(peer, PEER_CLOSING);
|
||||
|
@ -1116,9 +1059,9 @@ accept_closing:
|
|||
err = accept_pkt_close(ctx, peer, idata->pkt, effect);
|
||||
if (err)
|
||||
goto err_start_unilateral_close;
|
||||
/* As soon as we send packet, they could close. */
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch_close(ctx, peer, BITCOIN_CLOSE_DONE));
|
||||
peer_watch_close(peer, BITCOIN_CLOSE_DONE, INPUT_NONE);
|
||||
/* Send close TX. */
|
||||
queue_tx_broadcast(broadcast, bitcoin_close(ctx, peer));
|
||||
queue_pkt(out, pkt_close_complete(ctx, peer));
|
||||
/* No more commands, we're already closing. */
|
||||
set_peer_cond(peer, PEER_CLOSING);
|
||||
|
@ -1151,18 +1094,14 @@ fail_during_close:
|
|||
/* A reorganization could make this happen. */
|
||||
tx = bitcoin_spend_theirs(ctx, peer, idata->btc);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx,
|
||||
BITCOIN_SPEND_THEIRS_DONE));
|
||||
htlcs = htlc_outputs_their_commit(ctx, peer, idata->btc,
|
||||
peer_watch_tx(peer, tx, BITCOIN_SPEND_THEIRS_DONE);
|
||||
if (peer_watch_their_htlc_outputs(peer, idata->btc,
|
||||
BITCOIN_HTLC_TOUS_TIMEOUT,
|
||||
BITCOIN_HTLC_TOTHEM_SPENT,
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
/* Expect either close or spendthem to complete */
|
||||
if (htlcs) {
|
||||
BITCOIN_HTLC_TOTHEM_TIMEOUT)) {
|
||||
/* Expect either close or spendthem to complete */
|
||||
/* FIXME: Make sure caller uses INPUT_RVAL
|
||||
* if they were in the middle of FULFILL! */
|
||||
add_effect(effect, watch_htlcs, htlcs);
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_SPENDTHEM_CLOSE_WITH_HTLCS);
|
||||
}
|
||||
|
@ -1174,8 +1113,7 @@ fail_during_close:
|
|||
return next_state(peer, cstatus,
|
||||
STATE_ERR_INFORMATION_LEAK);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx, BITCOIN_STEAL_DONE));
|
||||
peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE);
|
||||
/* Expect either close or steal to complete */
|
||||
return next_state(peer, cstatus,
|
||||
STATE_CLOSE_WAIT_STEAL_CLOSE);
|
||||
|
@ -1199,7 +1137,6 @@ old_commit_spotted:
|
|||
return next_state(peer, cstatus,
|
||||
STATE_ERR_INFORMATION_LEAK);
|
||||
queue_tx_broadcast(broadcast, tx);
|
||||
add_effect(effect, watch,
|
||||
bitcoin_watch(ctx, tx, BITCOIN_STEAL_DONE));
|
||||
peer_watch_tx(peer, tx, BITCOIN_STEAL_DONE);
|
||||
return next_state(peer, cstatus, STATE_CLOSE_WAIT_STEAL);
|
||||
}
|
||||
|
|
190
state.h
190
state.h
|
@ -6,51 +6,13 @@
|
|||
#include <state_types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
enum state_effect_type {
|
||||
STATE_EFFECT_watch,
|
||||
STATE_EFFECT_unwatch,
|
||||
/* FIXME: Use a watch for this?. */
|
||||
STATE_EFFECT_close_timeout,
|
||||
/* FIXME: Combine into watches? */
|
||||
STATE_EFFECT_watch_htlcs,
|
||||
STATE_EFFECT_unwatch_htlc,
|
||||
STATE_EFFECT_watch_htlc_spend,
|
||||
STATE_EFFECT_unwatch_htlc_spend
|
||||
};
|
||||
|
||||
/*
|
||||
* This is the core state machine.
|
||||
*
|
||||
* Calling the state machine with an input simply returns the new state,
|
||||
* and populates the "effect" struct with what it wants done.
|
||||
* Calling the state machine updates updates peer->state, and may call
|
||||
* various peer_ callbacks. It also returns the status of the current
|
||||
* command.
|
||||
*/
|
||||
struct state_effect {
|
||||
struct state_effect *next;
|
||||
|
||||
enum state_effect_type etype;
|
||||
union {
|
||||
/* Event to watch for. */
|
||||
struct watch *watch;
|
||||
|
||||
/* Events to no longer watch for. */
|
||||
struct watch *unwatch;
|
||||
|
||||
/* Set a timeout for close tx. */
|
||||
enum state_input close_timeout;
|
||||
|
||||
/* HTLC outputs to watch. */
|
||||
const struct htlc_watch *watch_htlcs;
|
||||
|
||||
/* HTLC output to unwatch. */
|
||||
const struct htlc_unwatch *unwatch_htlc;
|
||||
|
||||
/* HTLC spends to watch/unwatch. */
|
||||
const struct htlc_spend_watch *watch_htlc_spend;
|
||||
const struct htlc_spend_watch *unwatch_htlc_spend;
|
||||
|
||||
/* FIXME: More to come (for accept_*) */
|
||||
} u;
|
||||
};
|
||||
|
||||
static inline bool state_is_error(enum state s)
|
||||
{
|
||||
|
@ -59,6 +21,7 @@ static inline bool state_is_error(enum state s)
|
|||
|
||||
struct peer;
|
||||
struct bitcoin_tx;
|
||||
struct state_effect;
|
||||
|
||||
static inline bool input_is_pkt(enum state_input input)
|
||||
{
|
||||
|
@ -226,8 +189,7 @@ Pkt *accept_pkt_close_ack(const tal_t *ctx,
|
|||
bool committed_to_htlcs(const struct peer *peer);
|
||||
|
||||
/**
|
||||
* bitcoin_watch_anchor: create a watch for the anchor.
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_watch_anchor: create a watch for the anchor transaction.
|
||||
* @peer: the state data for this peer.
|
||||
* @depthok: the input to give when anchor reaches expected depth.
|
||||
* @timeout: the input to give if anchor doesn't reach depth in time.
|
||||
|
@ -238,136 +200,138 @@ bool committed_to_htlcs(const struct peer *peer);
|
|||
* @depthok can be INPUT_NONE if it's our anchor (we don't time
|
||||
* ourselves out).
|
||||
*/
|
||||
struct watch *bitcoin_watch_anchor(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout,
|
||||
enum state_input unspent,
|
||||
enum state_input theyspent,
|
||||
enum state_input otherspent);
|
||||
void peer_watch_anchor(struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout,
|
||||
enum state_input unspent,
|
||||
enum state_input theyspent,
|
||||
enum state_input otherspent);
|
||||
|
||||
/**
|
||||
* bitcoin_unwatch_anchor_depth: remove depth watch for the anchor.
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_unwatch_anchor_depth: remove depth watch for the anchor.
|
||||
* @peer: the state data for this peer.
|
||||
* @depthok: the input to give when anchor reaches expected depth.
|
||||
* @timeout: the input to give if anchor doesn't reach depth in time.
|
||||
*
|
||||
* @depthok and @timeout must match bitcoin_watch_anchor() call.
|
||||
*/
|
||||
struct watch *bitcoin_unwatch_anchor_depth(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout);
|
||||
void peer_unwatch_anchor_depth(struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout);
|
||||
|
||||
/**
|
||||
* bitcoin_watch_delayed: watch this (commit) tx, tell me when I can spend it
|
||||
* @ctx: the context to tal the watch off
|
||||
* peer_watch_delayed: watch this (commit) tx, tell me when I can spend it
|
||||
* @peer: the state data for this peer.
|
||||
* @tx: the tx we're watching.
|
||||
* @canspend: the input to give when commit reaches spendable depth.
|
||||
*
|
||||
* Note that this tx may be malleated, as it's dual-signed.
|
||||
*/
|
||||
struct watch *bitcoin_watch_delayed(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input canspend);
|
||||
void peer_watch_delayed(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input canspend);
|
||||
|
||||
/**
|
||||
* bitcoin_watch: watch this tx until it's "irreversible"
|
||||
* @ctx: the context to tal the watch off
|
||||
* peer_watch_tx: watch this tx until it's "irreversible"
|
||||
* @peer: the state data for this peer.
|
||||
* @tx: the tx we're watching.
|
||||
* @done: the input to give when tx is completely buried.
|
||||
*
|
||||
* The tx should be immalleable by BIP62; once this fires we consider
|
||||
* the channel completely closed and stop watching (eg 100 txs down).
|
||||
* Once this fires we consider the channel completely closed and stop
|
||||
* watching (eg 100 txs down).
|
||||
*
|
||||
* This is used for watching a transaction we sent (such as a steal,
|
||||
* or spend of their close, etc).
|
||||
*/
|
||||
struct watch *bitcoin_watch(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input done);
|
||||
void peer_watch_tx(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input done);
|
||||
|
||||
/**
|
||||
* bitcoin_watch_close: watch close tx until it's "irreversible"
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_watch_close: watch for close tx until it's "irreversible" (or timedout)
|
||||
* @peer: the state data for this peer.
|
||||
* @done: the input to give when tx is completely buried.
|
||||
* @timedout: the input to give if we time out.
|
||||
*
|
||||
* This tx *is* malleable, since the other side can transmit theirs.
|
||||
* Once this fires we consider the channel completely closed and stop
|
||||
* watching (eg 100 txs down).
|
||||
*
|
||||
* This is used for watching a mutual close, or for a transaction we sent
|
||||
* (such as a steal, or spend of their close, etc).
|
||||
*/
|
||||
struct watch *bitcoin_watch_close(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input done);
|
||||
void peer_watch_close(struct peer *peer,
|
||||
enum state_input done, enum state_input timedout);
|
||||
|
||||
/**
|
||||
* htlc_outputs_our_commit: HTLC outputs from our commit tx to watch.
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_watch_our_htlc_outputs: HTLC outputs from our commit tx to watch.
|
||||
* @peer: the state data for this peer.
|
||||
* @tx: the commitment tx
|
||||
* @tous_timeout: input to give when a HTLC output to us times out.
|
||||
* @tothem_spent: input to give when a HTLC output to them is spent.
|
||||
* @tothem_timeout: input to give when a HTLC output to them times out.
|
||||
*
|
||||
* Returns true if there were any htlc outputs to watch.
|
||||
*/
|
||||
struct htlc_watch *htlc_outputs_our_commit(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout);
|
||||
bool peer_watch_our_htlc_outputs(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout);
|
||||
|
||||
/**
|
||||
* htlc_outputs_their_commit: HTLC outputs from their commit tx to watch.
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_watch_their_htlc_outputs: HTLC outputs from their commit tx to watch.
|
||||
* @peer: the state data for this peer.
|
||||
* @tx: the commitment tx
|
||||
* @tous_timeout: input to give when a HTLC output to us times out.
|
||||
* @tothem_spent: input to give when a HTLC output to them is spent.
|
||||
* @tothem_timeout: input to give when a HTLC output to them times out.
|
||||
*
|
||||
* Returns true if there were any htlc outputs to watch.
|
||||
*/
|
||||
struct htlc_watch *htlc_outputs_their_commit(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct bitcoin_event *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout);
|
||||
bool peer_watch_their_htlc_outputs(struct peer *peer,
|
||||
const struct bitcoin_event *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout);
|
||||
|
||||
/**
|
||||
* htlc_unwatch: stop watching an HTLC
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_unwatch_htlc_output: stop watching an HTLC
|
||||
* @peer: the state data for this peer.
|
||||
* @htlc: the htlc to stop watching
|
||||
* @all_done: input to give if we're not watching any anymore.
|
||||
* @all_done: input to give if we're not watching any outputs anymore.
|
||||
*/
|
||||
struct htlc_unwatch *htlc_unwatch(const tal_t *ctx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done);
|
||||
void peer_unwatch_htlc_output(struct peer *peer,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done);
|
||||
|
||||
/**
|
||||
* htlc_unwatch_all: stop watching all HTLCs
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_unwatch_all_htlc_outputs: stop watching all HTLCs
|
||||
* @peer: the state data for this peer.
|
||||
*/
|
||||
struct htlc_unwatch *htlc_unwatch_all(const tal_t *ctx,
|
||||
const struct peer *peer);
|
||||
void peer_unwatch_all_htlc_outputs(struct peer *peer);
|
||||
|
||||
/**
|
||||
* htlc_spend_watch: watch our spend of an HTLC
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* peer_watch_htlc_spend: watch our spend of an HTLC output
|
||||
* @peer: the state data for this peer.
|
||||
* @tx: the commitment tx
|
||||
* @cmd: the command data.
|
||||
* @htlc: the htlc the tx is spending an output of
|
||||
* @done: input to give when it's completely buried.
|
||||
*/
|
||||
struct htlc_spend_watch *htlc_spend_watch(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
const struct command *cmd,
|
||||
enum state_input done);
|
||||
void peer_watch_htlc_spend(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input done);
|
||||
|
||||
/**
|
||||
* htlc_spend_unwatch: stop watching an HTLC spend
|
||||
* @ctx: context to tal the watch struct off.
|
||||
* @htlc: the htlc to stop watching
|
||||
* peer_unwatch_htlc_spend: stop watching our HTLC spend
|
||||
* @peer: the state data for this peer.
|
||||
* @htlc: the htlc to stop watching the spend for.
|
||||
* @all_done: input to give if we're not watching anything anymore.
|
||||
*/
|
||||
struct htlc_spend_watch *htlc_spend_unwatch(const tal_t *ctx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done);
|
||||
void peer_unwatch_htlc_spend(struct peer *peer,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done);
|
||||
|
||||
/* Create a bitcoin anchor tx. */
|
||||
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
|
||||
const struct peer *peer);
|
||||
|
|
|
@ -871,134 +871,6 @@ struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
|
|||
return bitcoin_tx("anchor");
|
||||
}
|
||||
|
||||
static bool have_event(uint64_t events, enum state_input input)
|
||||
{
|
||||
return events & (1ULL << input);
|
||||
}
|
||||
|
||||
static bool add_event_(uint64_t *events, enum state_input input)
|
||||
{
|
||||
/* This is how they say "no event please" */
|
||||
if (input == INPUT_NONE)
|
||||
return true;
|
||||
|
||||
assert(input < 64);
|
||||
if (have_event(*events, input))
|
||||
return false;
|
||||
*events |= (1ULL << input);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool remove_event_(uint64_t *events, enum state_input input)
|
||||
{
|
||||
/* This is how they say "no event please" */
|
||||
if (input == INPUT_NONE)
|
||||
return true;
|
||||
|
||||
assert(input < 64);
|
||||
if (!have_event(*events, input))
|
||||
return false;
|
||||
*events &= ~(1ULL << input);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void remove_event(uint64_t *events, enum state_input input)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
#error "Don't run tests with NDEBUG"
|
||||
#endif
|
||||
assert(remove_event_(events, input));
|
||||
}
|
||||
|
||||
static void add_event(uint64_t *events, enum state_input input)
|
||||
{
|
||||
#ifdef NDEBUG
|
||||
#error "Don't run tests with NDEBUG"
|
||||
#endif
|
||||
assert(add_event_(events, input));
|
||||
}
|
||||
|
||||
struct watch {
|
||||
uint64_t events;
|
||||
};
|
||||
|
||||
struct watch *bitcoin_watch_anchor(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout,
|
||||
enum state_input unspent,
|
||||
enum state_input theyspent,
|
||||
enum state_input otherspent)
|
||||
{
|
||||
struct watch *watch = talz(ctx, struct watch);
|
||||
|
||||
add_event(&watch->events, depthok);
|
||||
add_event(&watch->events, timeout);
|
||||
add_event(&watch->events, unspent);
|
||||
add_event(&watch->events, theyspent);
|
||||
add_event(&watch->events, otherspent);
|
||||
|
||||
/* We assume these values in activate_event. */
|
||||
assert(timeout == BITCOIN_ANCHOR_TIMEOUT
|
||||
|| timeout == INPUT_NONE);
|
||||
assert(depthok == BITCOIN_ANCHOR_DEPTHOK);
|
||||
return watch;
|
||||
}
|
||||
|
||||
struct watch *bitcoin_unwatch_anchor_depth(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout)
|
||||
{
|
||||
struct watch *watch = talz(ctx, struct watch);
|
||||
|
||||
add_event(&watch->events, depthok);
|
||||
add_event(&watch->events, timeout);
|
||||
return watch;
|
||||
}
|
||||
|
||||
/* Wait for our commit to be spendable. */
|
||||
struct watch *bitcoin_watch_delayed(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input canspend)
|
||||
{
|
||||
struct watch *watch = talz(ctx, struct watch);
|
||||
|
||||
assert(bitcoin_tx_is(tx, "our commit"));
|
||||
add_event(&watch->events, canspend);
|
||||
return watch;
|
||||
}
|
||||
|
||||
/* Wait for commit to be very deeply buried (so we no longer need to
|
||||
* even watch) */
|
||||
struct watch *bitcoin_watch(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input done)
|
||||
{
|
||||
struct watch *watch = talz(ctx, struct watch);
|
||||
|
||||
if (done == BITCOIN_STEAL_DONE)
|
||||
assert(bitcoin_tx_is(tx, "steal"));
|
||||
else if (done == BITCOIN_SPEND_THEIRS_DONE)
|
||||
assert(bitcoin_tx_is(tx, "spend their commit"));
|
||||
else if (done == BITCOIN_SPEND_OURS_DONE)
|
||||
assert(bitcoin_tx_is(tx, "spend our commit"));
|
||||
else
|
||||
errx(1, "Unknown watch effect %s", input_name(done));
|
||||
add_event(&watch->events, done);
|
||||
return watch;
|
||||
}
|
||||
|
||||
/* Other side should drop close tx; watch for it. */
|
||||
struct watch *bitcoin_watch_close(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
enum state_input done)
|
||||
{
|
||||
struct watch *watch = talz(ctx, struct watch);
|
||||
add_event(&watch->events, done);
|
||||
return watch;
|
||||
}
|
||||
|
||||
struct bitcoin_tx *bitcoin_close(const tal_t *ctx,
|
||||
const struct peer *peer)
|
||||
{
|
||||
|
@ -1054,143 +926,6 @@ bool committed_to_htlcs(const struct peer *peer)
|
|||
return peer->num_htlcs_to_them != 0 || peer->num_htlcs_to_us != 0;
|
||||
}
|
||||
|
||||
struct htlc_watch
|
||||
{
|
||||
enum state_input tous_timeout;
|
||||
enum state_input tothem_spent;
|
||||
enum state_input tothem_timeout;
|
||||
unsigned int num_htlcs_to_us, num_htlcs_to_them;
|
||||
struct htlc htlcs_to_us[MAX_HTLCS], htlcs_to_them[MAX_HTLCS];
|
||||
};
|
||||
|
||||
struct htlc_unwatch
|
||||
{
|
||||
unsigned int id;
|
||||
enum state_input all_done;
|
||||
};
|
||||
|
||||
struct htlc_watch *htlc_outputs_our_commit(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout)
|
||||
{
|
||||
struct htlc_watch *w = tal(ctx, struct htlc_watch);
|
||||
|
||||
/* We assume these. */
|
||||
assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
|
||||
assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
|
||||
assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
|
||||
w->tous_timeout = tous_timeout;
|
||||
w->tothem_spent = tothem_spent;
|
||||
w->tothem_timeout = tothem_timeout;
|
||||
|
||||
w->num_htlcs_to_us = peer->num_htlcs_to_us;
|
||||
w->num_htlcs_to_them = peer->num_htlcs_to_them;
|
||||
BUILD_ASSERT(sizeof(peer->htlcs_to_us) == sizeof(w->htlcs_to_us));
|
||||
BUILD_ASSERT(sizeof(peer->htlcs_to_them) == sizeof(w->htlcs_to_them));
|
||||
memcpy(w->htlcs_to_us, peer->htlcs_to_us, sizeof(peer->htlcs_to_us));
|
||||
memcpy(w->htlcs_to_them, peer->htlcs_to_them,
|
||||
sizeof(peer->htlcs_to_them));
|
||||
|
||||
if (!w->num_htlcs_to_us && !w->num_htlcs_to_them)
|
||||
return tal_free(w);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_watch *htlc_outputs_their_commit(const tal_t *ctx,
|
||||
const struct peer *peer,
|
||||
const struct bitcoin_event *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout)
|
||||
{
|
||||
struct htlc_watch *w = tal(ctx, struct htlc_watch);
|
||||
unsigned int i;
|
||||
|
||||
/* We assume these. */
|
||||
assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
|
||||
assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
|
||||
assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
|
||||
w->tous_timeout = tous_timeout;
|
||||
w->tothem_spent = tothem_spent;
|
||||
w->tothem_timeout = tothem_timeout;
|
||||
|
||||
/* It's what our peer thinks is current... */
|
||||
w->num_htlcs_to_us = peer->other->num_htlcs_to_them;
|
||||
w->num_htlcs_to_them = peer->other->num_htlcs_to_us;
|
||||
BUILD_ASSERT(sizeof(peer->other->htlcs_to_them) == sizeof(w->htlcs_to_us));
|
||||
BUILD_ASSERT(sizeof(peer->other->htlcs_to_us) == sizeof(w->htlcs_to_them));
|
||||
memcpy(w->htlcs_to_us, peer->other->htlcs_to_them, sizeof(w->htlcs_to_us));
|
||||
memcpy(w->htlcs_to_them, peer->other->htlcs_to_us,
|
||||
sizeof(w->htlcs_to_them));
|
||||
|
||||
if (!w->num_htlcs_to_us && !w->num_htlcs_to_them)
|
||||
return tal_free(w);
|
||||
|
||||
/* Reverse perspective, mark rvalue unknown */
|
||||
for (i = 0; i < w->num_htlcs_to_us; i++) {
|
||||
assert(w->htlcs_to_us[i].to_them);
|
||||
w->htlcs_to_us[i].to_them = false;
|
||||
}
|
||||
for (i = 0; i < w->num_htlcs_to_them; i++) {
|
||||
assert(!w->htlcs_to_them[i].to_them);
|
||||
w->htlcs_to_them[i].to_them = true;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_unwatch *htlc_unwatch(const tal_t *ctx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done)
|
||||
{
|
||||
struct htlc_unwatch *w = tal(ctx, struct htlc_unwatch);
|
||||
|
||||
w->id = htlc->id;
|
||||
assert(w->id != -1U);
|
||||
w->all_done = all_done;
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_unwatch *htlc_unwatch_all(const tal_t *ctx,
|
||||
const struct peer *peer)
|
||||
{
|
||||
struct htlc_unwatch *w = tal(ctx, struct htlc_unwatch);
|
||||
|
||||
w->id = -1U;
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_spend_watch *htlc_spend_watch(const tal_t *ctx,
|
||||
const struct bitcoin_tx *tx,
|
||||
const struct command *cmd,
|
||||
enum state_input done)
|
||||
{
|
||||
struct htlc_spend_watch *w = tal(ctx, struct htlc_spend_watch);
|
||||
w->id = htlc_id_from_tx(tx);
|
||||
w->done = done;
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_spend_watch *htlc_spend_unwatch(const tal_t *ctx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done)
|
||||
{
|
||||
struct htlc_spend_watch *w = tal(ctx, struct htlc_spend_watch);
|
||||
|
||||
w->id = htlc->id;
|
||||
w->done = all_done;
|
||||
return w;
|
||||
}
|
||||
|
||||
struct htlc_rval {
|
||||
unsigned int id;
|
||||
};
|
||||
|
||||
#include "state.c"
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1401,6 +1136,282 @@ static bool outstanding_htlc_watches(const struct peer *peer)
|
|||
|| peer->num_htlc_spends_to_them;
|
||||
}
|
||||
|
||||
static bool have_event(uint64_t events, enum state_input input)
|
||||
{
|
||||
return events & (1ULL << input);
|
||||
}
|
||||
|
||||
static bool add_event_(struct peer *peer, enum state_input input)
|
||||
{
|
||||
/* This is how they say "no event please" */
|
||||
if (input == INPUT_NONE)
|
||||
return true;
|
||||
|
||||
assert(input < 64);
|
||||
if (have_event(peer->core.event_notifies, input))
|
||||
return false;
|
||||
peer->core.event_notifies |= (1ULL << input);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool remove_event_(uint64_t *events, enum state_input input)
|
||||
{
|
||||
/* This is how they say "no event please" */
|
||||
if (input == INPUT_NONE)
|
||||
return true;
|
||||
|
||||
assert(input < 64);
|
||||
if (!have_event(*events, input))
|
||||
return false;
|
||||
*events &= ~(1ULL << input);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void remove_event(struct peer *peer, enum state_input input)
|
||||
{
|
||||
if (!remove_event_(&peer->core.event_notifies, input))
|
||||
report_trail(peer->trail, "Removing event we don't have?");
|
||||
}
|
||||
|
||||
static void add_event(struct peer *peer, enum state_input input)
|
||||
{
|
||||
if (!add_event_(peer, input))
|
||||
report_trail(peer->trail, "Adding event we already have?");
|
||||
}
|
||||
|
||||
void peer_watch_anchor(struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout,
|
||||
enum state_input unspent,
|
||||
enum state_input theyspent,
|
||||
enum state_input otherspent)
|
||||
{
|
||||
/* We assume these values in activate_event. */
|
||||
assert(timeout == BITCOIN_ANCHOR_TIMEOUT
|
||||
|| timeout == INPUT_NONE);
|
||||
assert(depthok == BITCOIN_ANCHOR_DEPTHOK);
|
||||
|
||||
add_event(peer, depthok);
|
||||
add_event(peer, timeout);
|
||||
add_event(peer, unspent);
|
||||
add_event(peer, theyspent);
|
||||
add_event(peer, otherspent);
|
||||
}
|
||||
|
||||
void peer_unwatch_anchor_depth(struct peer *peer,
|
||||
enum state_input depthok,
|
||||
enum state_input timeout)
|
||||
{
|
||||
/* We assume these values in activate_event. */
|
||||
assert(timeout == BITCOIN_ANCHOR_TIMEOUT
|
||||
|| timeout == INPUT_NONE);
|
||||
assert(depthok == BITCOIN_ANCHOR_DEPTHOK);
|
||||
|
||||
remove_event(peer, depthok);
|
||||
remove_event(peer, timeout);
|
||||
}
|
||||
|
||||
/* Wait for our commit to be spendable. */
|
||||
void peer_watch_delayed(struct peer *peer,
|
||||
const struct bitcoin_tx *tx, enum state_input canspend)
|
||||
{
|
||||
assert(bitcoin_tx_is(tx, "our commit"));
|
||||
add_event(peer, canspend);
|
||||
}
|
||||
|
||||
/* Wait for commit to be very deeply buried (so we no longer need to
|
||||
* even watch) */
|
||||
void peer_watch_tx(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input done)
|
||||
{
|
||||
/* We can have multiple steals or spendtheirs in flight, so
|
||||
* allow repeats for
|
||||
* BITCOIN_STEAL_DONE/BITCOIN_SPEND_THEIRS_DONE */
|
||||
if (done == BITCOIN_STEAL_DONE) {
|
||||
assert(bitcoin_tx_is(tx, "steal"));
|
||||
add_event_(peer, done);
|
||||
} else if (done == BITCOIN_SPEND_THEIRS_DONE) {
|
||||
assert(bitcoin_tx_is(tx, "spend their commit"));
|
||||
add_event_(peer, done);
|
||||
} else if (done == BITCOIN_SPEND_OURS_DONE) {
|
||||
assert(bitcoin_tx_is(tx, "spend our commit"));
|
||||
add_event(peer, done);
|
||||
} else
|
||||
report_trail(peer->trail, "Unknown watch effect");
|
||||
}
|
||||
|
||||
/* Other side should drop close tx; watch for it. */
|
||||
void peer_watch_close(struct peer *peer,
|
||||
enum state_input done, enum state_input timedout)
|
||||
{
|
||||
add_event(peer, done);
|
||||
|
||||
/* We assume this. */
|
||||
assert(timedout == INPUT_CLOSE_COMPLETE_TIMEOUT || timedout == INPUT_NONE);
|
||||
add_event(peer, timedout);
|
||||
}
|
||||
|
||||
bool peer_watch_our_htlc_outputs(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout)
|
||||
{
|
||||
/* FIXME: We assume these. */
|
||||
assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
|
||||
assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
|
||||
assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
|
||||
if (!peer->num_htlcs_to_us && !peer->num_htlcs_to_them)
|
||||
return false;
|
||||
|
||||
assert(peer->num_live_htlcs_to_us + peer->num_htlcs_to_us
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_us));
|
||||
assert(peer->num_live_htlcs_to_them + peer->num_htlcs_to_them
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_them));
|
||||
memcpy(peer->live_htlcs_to_us + peer->num_live_htlcs_to_us,
|
||||
peer->htlcs_to_us,
|
||||
peer->num_htlcs_to_us * sizeof(peer->htlcs_to_us[0]));
|
||||
memcpy(peer->live_htlcs_to_them + peer->num_live_htlcs_to_them,
|
||||
peer->htlcs_to_them,
|
||||
peer->num_htlcs_to_them * sizeof(peer->htlcs_to_them[0]));
|
||||
peer->num_live_htlcs_to_us += peer->num_htlcs_to_us;
|
||||
peer->num_live_htlcs_to_them += peer->num_htlcs_to_them;
|
||||
/* Can happen if we were finished, then new commit tx */
|
||||
remove_event_(&peer->core.event_notifies, INPUT_NO_MORE_HTLCS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool peer_watch_their_htlc_outputs(struct peer *peer,
|
||||
const struct bitcoin_event *tx,
|
||||
enum state_input tous_timeout,
|
||||
enum state_input tothem_spent,
|
||||
enum state_input tothem_timeout)
|
||||
{
|
||||
size_t i;
|
||||
struct htlc *htlcs;
|
||||
|
||||
/* We assume these. */
|
||||
assert(tous_timeout == BITCOIN_HTLC_TOUS_TIMEOUT);
|
||||
assert(tothem_spent == BITCOIN_HTLC_TOTHEM_SPENT);
|
||||
assert(tothem_timeout == BITCOIN_HTLC_TOTHEM_TIMEOUT);
|
||||
|
||||
/* It's what our peer thinks is current... */
|
||||
if (!peer->other->num_htlcs_to_them && !peer->other->num_htlcs_to_us)
|
||||
return false;
|
||||
|
||||
assert(peer->num_live_htlcs_to_us + peer->other->num_htlcs_to_them
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_us));
|
||||
assert(peer->num_live_htlcs_to_them + peer->other->num_htlcs_to_us
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_them));
|
||||
|
||||
/* Copy from other peer, but reverse perspective */
|
||||
htlcs = peer->live_htlcs_to_us + peer->num_live_htlcs_to_us;
|
||||
memcpy(htlcs, peer->other->htlcs_to_them,
|
||||
peer->other->num_htlcs_to_them * sizeof(peer->htlcs_to_us[0]));
|
||||
for (i = 0; i < peer->other->num_htlcs_to_them; i++) {
|
||||
assert(htlcs[i].to_them);
|
||||
htlcs[i].to_them = false;
|
||||
}
|
||||
|
||||
htlcs = peer->live_htlcs_to_them + peer->num_live_htlcs_to_them;
|
||||
memcpy(htlcs,
|
||||
peer->other->htlcs_to_us,
|
||||
peer->other->num_htlcs_to_us * sizeof(peer->htlcs_to_them[0]));
|
||||
for (i = 0; i < peer->other->num_htlcs_to_us; i++) {
|
||||
assert(!htlcs[i].to_them);
|
||||
htlcs[i].to_them = true;
|
||||
}
|
||||
|
||||
peer->num_live_htlcs_to_us += peer->other->num_htlcs_to_them;
|
||||
peer->num_live_htlcs_to_them += peer->other->num_htlcs_to_us;
|
||||
/* Can happen if we were finished, then new commit tx */
|
||||
remove_event_(&peer->core.event_notifies, INPUT_NO_MORE_HTLCS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void peer_unwatch_htlc_output(struct peer *peer,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done)
|
||||
{
|
||||
const struct htlc *h;
|
||||
|
||||
/* We assume this. */
|
||||
assert(all_done == INPUT_NO_MORE_HTLCS);
|
||||
|
||||
h = find_live_htlc(peer, htlc->id);
|
||||
|
||||
/* That can fail, when we see them spend (and thus stop
|
||||
* watching) after we've timed out, then our return tx wins
|
||||
* and gets buried. */
|
||||
if (h) {
|
||||
remove_htlc(peer->live_htlcs_to_us,
|
||||
&peer->num_live_htlcs_to_us,
|
||||
peer->live_htlcs_to_them,
|
||||
&peer->num_live_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->live_htlcs_to_us),
|
||||
h);
|
||||
|
||||
/* If that was last, fire INPUT_NO_MORE_HTLCS */
|
||||
if (!outstanding_htlc_watches(peer))
|
||||
add_event(peer, all_done);
|
||||
}
|
||||
}
|
||||
|
||||
void peer_unwatch_all_htlc_outputs(struct peer *peer)
|
||||
{
|
||||
/* This can happen if we get in front of INPUT_NO_MORE_HTLCS */
|
||||
if (!outstanding_htlc_watches(peer)
|
||||
&& !have_event(peer->core.event_notifies, INPUT_NO_MORE_HTLCS))
|
||||
report_trail(peer->trail, "unwatching all with no htlcs?");
|
||||
|
||||
peer->num_htlc_spends_to_us = 0;
|
||||
peer->num_htlc_spends_to_them = 0;
|
||||
peer->num_live_htlcs_to_us = 0;
|
||||
peer->num_live_htlcs_to_them = 0;
|
||||
}
|
||||
|
||||
void peer_watch_htlc_spend(struct peer *peer,
|
||||
const struct bitcoin_tx *tx,
|
||||
const struct htlc *htlc,
|
||||
enum state_input done)
|
||||
{
|
||||
struct htlc *h = find_live_htlc(peer, htlc_id_from_tx(tx));
|
||||
|
||||
add_htlc(peer->htlc_spends_to_us, &peer->num_htlc_spends_to_us,
|
||||
peer->htlc_spends_to_them,
|
||||
&peer->num_htlc_spends_to_them,
|
||||
ARRAY_SIZE(peer->htlc_spends_to_us),
|
||||
h);
|
||||
|
||||
/* We assume this */
|
||||
if (h->to_them)
|
||||
assert(done == BITCOIN_HTLC_RETURN_SPEND_DONE);
|
||||
else
|
||||
assert(done == BITCOIN_HTLC_FULFILL_SPEND_DONE);
|
||||
}
|
||||
|
||||
void peer_unwatch_htlc_spend(struct peer *peer,
|
||||
const struct htlc *htlc,
|
||||
enum state_input all_done)
|
||||
{
|
||||
struct htlc *h = find_htlc_spend(peer, htlc->id);
|
||||
|
||||
assert(all_done == INPUT_NO_MORE_HTLCS);
|
||||
remove_htlc(peer->htlc_spends_to_us,
|
||||
&peer->num_htlc_spends_to_us,
|
||||
peer->htlc_spends_to_them,
|
||||
&peer->num_htlc_spends_to_them,
|
||||
ARRAY_SIZE(peer->htlc_spends_to_us),
|
||||
h);
|
||||
|
||||
if (!outstanding_htlc_watches(peer))
|
||||
add_event(peer, all_done);
|
||||
}
|
||||
|
||||
void peer_unexpected_pkt(struct peer *peer, const Pkt *pkt)
|
||||
{
|
||||
const char *str = (const char *)pkt;
|
||||
|
@ -1471,159 +1482,6 @@ void peer_tx_revealed_r_value(struct peer *peer,
|
|||
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,
|
||||
const struct state_effect *effect,
|
||||
uint64_t *effects)
|
||||
{
|
||||
const struct htlc *h;
|
||||
|
||||
if (!effect)
|
||||
return NULL;
|
||||
|
||||
if (effect->next) {
|
||||
const char *problem = apply_effects(peer, effect->next,
|
||||
effects);
|
||||
if (problem)
|
||||
return problem;
|
||||
}
|
||||
|
||||
if (*effects & (1ULL << effect->etype))
|
||||
return tal_fmt(NULL, "Effect %u twice", effect->etype);
|
||||
*effects |= (1ULL << effect->etype);
|
||||
|
||||
switch (effect->etype) {
|
||||
case STATE_EFFECT_watch:
|
||||
/* We can have multiple steals or spendtheirs
|
||||
in flight, so make exceptions for
|
||||
BITCOIN_STEAL_DONE/BITCOIN_SPEND_THEIRS_DONE */
|
||||
if (peer->core.event_notifies & (1ULL << BITCOIN_STEAL_DONE)
|
||||
& effect->u.watch->events)
|
||||
remove_event(&effect->u.watch->events, BITCOIN_STEAL_DONE);
|
||||
|
||||
if (peer->core.event_notifies
|
||||
& (1ULL << BITCOIN_SPEND_THEIRS_DONE)
|
||||
& effect->u.watch->events)
|
||||
remove_event(&effect->u.watch->events,
|
||||
BITCOIN_SPEND_THEIRS_DONE);
|
||||
|
||||
if (peer->core.event_notifies & effect->u.watch->events)
|
||||
return "event set twice";
|
||||
peer->core.event_notifies |= effect->u.watch->events;
|
||||
break;
|
||||
case STATE_EFFECT_unwatch:
|
||||
if ((peer->core.event_notifies & effect->u.unwatch->events)
|
||||
!= effect->u.unwatch->events)
|
||||
return "unset event unwatched";
|
||||
peer->core.event_notifies &= ~effect->u.unwatch->events;
|
||||
break;
|
||||
case STATE_EFFECT_close_timeout:
|
||||
add_event(&peer->core.event_notifies,
|
||||
effect->u.close_timeout);
|
||||
/* We assume this. */
|
||||
assert(effect->u.close_timeout
|
||||
== INPUT_CLOSE_COMPLETE_TIMEOUT);
|
||||
break;
|
||||
case STATE_EFFECT_watch_htlcs:
|
||||
assert(peer->num_live_htlcs_to_us
|
||||
+ effect->u.watch_htlcs->num_htlcs_to_us
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_us));
|
||||
assert(peer->num_live_htlcs_to_them
|
||||
+ effect->u.watch_htlcs->num_htlcs_to_them
|
||||
<= ARRAY_SIZE(peer->live_htlcs_to_them));
|
||||
memcpy(peer->live_htlcs_to_us + peer->num_live_htlcs_to_us,
|
||||
effect->u.watch_htlcs->htlcs_to_us,
|
||||
effect->u.watch_htlcs->num_htlcs_to_us
|
||||
* sizeof(effect->u.watch_htlcs->htlcs_to_us[0]));
|
||||
memcpy(peer->live_htlcs_to_them + peer->num_live_htlcs_to_them,
|
||||
effect->u.watch_htlcs->htlcs_to_them,
|
||||
effect->u.watch_htlcs->num_htlcs_to_them
|
||||
* sizeof(effect->u.watch_htlcs->htlcs_to_them[0]));
|
||||
peer->num_live_htlcs_to_us
|
||||
+= effect->u.watch_htlcs->num_htlcs_to_us;
|
||||
peer->num_live_htlcs_to_them
|
||||
+= effect->u.watch_htlcs->num_htlcs_to_them;
|
||||
/* Can happen if we were finished, then new commit tx */
|
||||
remove_event_(&peer->core.event_notifies, INPUT_NO_MORE_HTLCS);
|
||||
break;
|
||||
case STATE_EFFECT_unwatch_htlc:
|
||||
/* Unwatch all? */
|
||||
if (effect->u.unwatch_htlc->id == -1) {
|
||||
/* This can happen if we get in front of
|
||||
* INPUT_NO_MORE_HTLCS */
|
||||
if (!outstanding_htlc_watches(peer)
|
||||
&& !have_event(peer->core.event_notifies,
|
||||
INPUT_NO_MORE_HTLCS))
|
||||
return "unwatching all with no htlcs?";
|
||||
peer->num_htlc_spends_to_us = 0;
|
||||
peer->num_htlc_spends_to_them = 0;
|
||||
peer->num_live_htlcs_to_us = 0;
|
||||
peer->num_live_htlcs_to_them = 0;
|
||||
} else {
|
||||
const struct htlc *h;
|
||||
|
||||
h = find_live_htlc(peer, effect->u.unwatch_htlc->id);
|
||||
|
||||
/* That can fail, when we see them spend (and
|
||||
* thus stop watching) after we've timed out,
|
||||
* then our return tx wins and gets buried. */
|
||||
if (h) {
|
||||
remove_htlc(peer->live_htlcs_to_us,
|
||||
&peer->num_live_htlcs_to_us,
|
||||
peer->live_htlcs_to_them,
|
||||
&peer->num_live_htlcs_to_them,
|
||||
ARRAY_SIZE(peer->live_htlcs_to_us),
|
||||
h);
|
||||
|
||||
/* If that was last, fire INPUT_NO_MORE_HTLCS */
|
||||
if (!outstanding_htlc_watches(peer)) {
|
||||
assert(effect->u.unwatch_htlc->all_done
|
||||
== INPUT_NO_MORE_HTLCS);
|
||||
add_event(&peer->core.event_notifies,
|
||||
effect->u.unwatch_htlc->all_done);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STATE_EFFECT_watch_htlc_spend:
|
||||
h = find_live_htlc(peer, effect->u.watch_htlc_spend->id);
|
||||
add_htlc(peer->htlc_spends_to_us, &peer->num_htlc_spends_to_us,
|
||||
peer->htlc_spends_to_them,
|
||||
&peer->num_htlc_spends_to_them,
|
||||
ARRAY_SIZE(peer->htlc_spends_to_us),
|
||||
h);
|
||||
|
||||
/* We assume this */
|
||||
if (h->to_them)
|
||||
assert(effect->u.watch_htlc_spend->done
|
||||
== BITCOIN_HTLC_RETURN_SPEND_DONE);
|
||||
else
|
||||
assert(effect->u.watch_htlc_spend->done
|
||||
== BITCOIN_HTLC_FULFILL_SPEND_DONE);
|
||||
break;
|
||||
case STATE_EFFECT_unwatch_htlc_spend:
|
||||
h = find_htlc_spend(peer, effect->u.unwatch_htlc_spend->id);
|
||||
remove_htlc(peer->htlc_spends_to_us,
|
||||
&peer->num_htlc_spends_to_us,
|
||||
peer->htlc_spends_to_them,
|
||||
&peer->num_htlc_spends_to_them,
|
||||
ARRAY_SIZE(peer->htlc_spends_to_us),
|
||||
h);
|
||||
if (!outstanding_htlc_watches(peer)) {
|
||||
assert(effect->u.unwatch_htlc_spend->done
|
||||
== INPUT_NO_MORE_HTLCS);
|
||||
add_event(&peer->core.event_notifies,
|
||||
effect->u.unwatch_htlc_spend->done);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return tal_fmt(NULL, "Unknown effect %u", effect->etype);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *check_changes(const struct peer *old, struct peer *new,
|
||||
enum state_input input)
|
||||
{
|
||||
|
@ -1661,16 +1519,12 @@ static const char *check_changes(const struct peer *old, struct peer *new,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *apply_all_effects(const struct peer *old,
|
||||
static const char *check_all_effects(const struct peer *old,
|
||||
enum command_status cstatus,
|
||||
enum state_input input,
|
||||
struct peer *peer,
|
||||
const struct state_effect *effect,
|
||||
Pkt *output)
|
||||
{
|
||||
const char *problem;
|
||||
uint64_t effects = 0;
|
||||
|
||||
if (cstatus != CMD_NONE) {
|
||||
assert(peer->core.current_command != INPUT_NONE);
|
||||
/* We should only requeue HTLCs if we're lowprio */
|
||||
|
@ -1717,11 +1571,17 @@ static const char *apply_all_effects(const struct peer *old,
|
|||
peer->pkt_data[peer->core.num_outputs++]
|
||||
= htlc_id_from_pkt(output);
|
||||
}
|
||||
|
||||
problem = apply_effects(peer, effect, &effects);
|
||||
if (!problem)
|
||||
problem = check_changes(old, peer, input);
|
||||
return problem;
|
||||
|
||||
if (peer->state >= STATE_CLOSE_WAIT_STEAL
|
||||
&& peer->state <= STATE_CLOSE_WAIT_STEAL_SPENDTHEM_CLOSE_SPENDOURS_WITH_HTLCS) {
|
||||
if (STATE_TO_BITS(peer->state) & STATE_CLOSE_HTLCS_BIT) {
|
||||
if (!outstanding_htlc_watches(peer)
|
||||
&& !have_event(peer->core.event_notifies, INPUT_NO_MORE_HTLCS))
|
||||
return "CLOSE_HTLCS with no outstanding watches?";
|
||||
}
|
||||
}
|
||||
|
||||
return check_changes(old, peer, input);
|
||||
}
|
||||
|
||||
static void eliminate_input(enum state_input **inputs, enum state_input in)
|
||||
|
@ -1958,7 +1818,7 @@ static void try_input(const struct peer *peer,
|
|||
add_dot(&hist->edges, oldstr, newstr, i, output);
|
||||
}
|
||||
|
||||
problem = apply_all_effects(peer, cstatus, i, ©, effect, output);
|
||||
problem = check_all_effects(peer, cstatus, i, ©, output);
|
||||
update_trail(&t, ©, output);
|
||||
if (problem)
|
||||
report_trail(&t, problem);
|
||||
|
@ -2069,7 +1929,7 @@ static void activate_event(struct peer *peer, enum state_input i)
|
|||
break;
|
||||
case BITCOIN_ANCHOR_TIMEOUT:
|
||||
/* Can't sent DEPTHOK */
|
||||
remove_event(&peer->core.event_notifies, BITCOIN_ANCHOR_DEPTHOK);
|
||||
remove_event(peer, BITCOIN_ANCHOR_DEPTHOK);
|
||||
break;
|
||||
/* And of the "done" cases means we won't give the others. */
|
||||
case BITCOIN_SPEND_THEIRS_DONE:
|
||||
|
@ -2160,7 +2020,7 @@ static void run_peer(const struct peer *peer,
|
|||
|
||||
/* Don't re-fire most events */
|
||||
if (!can_refire(i))
|
||||
remove_event(©.core.event_notifies, i);
|
||||
remove_event(©, i);
|
||||
activate_event(©, i);
|
||||
try_input(©, i, idata, normalpath, errorpath,
|
||||
prev_trail, hist);
|
||||
|
|
Loading…
Add table
Reference in a new issue