state: allow multiple SPENDTHEM.

Malleability, there could be many of these.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2015-09-25 11:51:18 +09:30
parent 92bb5f03de
commit fbe6e9e0cf
2 changed files with 13 additions and 8 deletions

View file

@ -626,9 +626,8 @@ enum state state(const enum state state, const struct state_data *sdata,
} }
/* Now, other side can always spring a commit transaction on us /* Now, other side can always spring a commit transaction on us
* (if they haven't already) */ * (even if they already have, due to tx malleability) */
if (!(bits & STATE_CLOSE_SPENDTHEM_BIT) if (input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
&& input_is(input, BITCOIN_ANCHOR_THEIRSPEND)) {
set_effect(effect, broadcast, set_effect(effect, broadcast,
bitcoin_spend_theirs(effect, sdata)); bitcoin_spend_theirs(effect, sdata));
set_effect(effect, watch, set_effect(effect, watch,

View file

@ -635,12 +635,16 @@ static const char *apply_effects(struct state_data *sdata,
sdata->outputs[sdata->num_outputs++] = input_by_name(pkt); sdata->outputs[sdata->num_outputs++] = input_by_name(pkt);
} }
if (effect->watch) { if (effect->watch) {
/* We can have multiple steals in flight, so make an exception /* We can have multiple steals or spendtheirs in flight,
* for BITCOIN_STEAL_DONE */ so make exceptions for BITCOIN_STEAL_DONE/BITCOIN_SPEND_THEIRS_DONE */
if (sdata->event_notifies & (1ULL << BITCOIN_STEAL_DONE) if (sdata->event_notifies & (1ULL << BITCOIN_STEAL_DONE)
& effect->watch->events) & effect->watch->events)
effect->watch->events &= ~(1ULL << BITCOIN_STEAL_DONE); effect->watch->events &= ~(1ULL << BITCOIN_STEAL_DONE);
if (sdata->event_notifies & (1ULL << BITCOIN_SPEND_THEIRS_DONE)
& effect->watch->events)
effect->watch->events &= ~(1ULL << BITCOIN_SPEND_THEIRS_DONE);
if (sdata->event_notifies & effect->watch->events) if (sdata->event_notifies & effect->watch->events)
return "event set twice"; return "event set twice";
sdata->event_notifies |= effect->watch->events; sdata->event_notifies |= effect->watch->events;
@ -950,7 +954,7 @@ static struct trail *try_input(const struct state_data *sdata,
/* /*
* We expect to loop if: * We expect to loop if:
* 1) We deferred, OR * 1) We deferred, OR
* 2) We get repeated BITCOIN_ANCHOR_OTHERSPEND, OR * 2) We get repeated BITCOIN_ANCHOR_OTHERSPEND/THEIRSPEND, OR
* 3) We pass through NORMAL state. * 3) We pass through NORMAL state.
* *
* And if we're being quick, always stop. * And if we're being quick, always stop.
@ -958,6 +962,7 @@ static struct trail *try_input(const struct state_data *sdata,
if (effect->defer != INPUT_NONE if (effect->defer != INPUT_NONE
|| newstate == STATE_NORMAL_LOWPRIO || newstate == STATE_NORMAL_LOWPRIO
|| i == BITCOIN_ANCHOR_OTHERSPEND || i == BITCOIN_ANCHOR_OTHERSPEND
|| i == BITCOIN_ANCHOR_THEIRSPEND
|| quick) { || quick) {
tal_free(effect); tal_free(effect);
return NULL; return NULL;
@ -1057,8 +1062,9 @@ static struct trail *run_peer(const struct state_data *sdata,
if (!(copy.event_notifies & (1ULL << i))) if (!(copy.event_notifies & (1ULL << i)))
continue; continue;
/* Don't re-fire (except OTHERSPEND can reoccur) */ /* Don't re-fire (except OTHERSPEND/THEIRSPEND can reoccur) */
if (i != BITCOIN_ANCHOR_OTHERSPEND) if (i != BITCOIN_ANCHOR_OTHERSPEND
&& i != BITCOIN_ANCHOR_THEIRSPEND)
copy.event_notifies &= ~(1ULL << i); copy.event_notifies &= ~(1ULL << i);
activate_event(&copy, i); activate_event(&copy, i);
t = try_input(&copy, i, normalpath, errorpath, depth, hist); t = try_input(&copy, i, normalpath, errorpath, depth, hist);