Browse Source

state: add async anchor creation.

Actually generating the anchor transaction in my implementation
requires interaction with bitcoind, which we want to be async.  So add
a callback and a new state to wait for it.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
ebf2bc57d8
  1. 18
      state.c
  2. 12
      state.h
  3. 3
      state_types.h
  4. 40
      test/test_state_coverage.c

18
state.c

@ -149,13 +149,28 @@ enum command_status state(const tal_t *ctx,
complete_cmd(peer, &cstatus, CMD_FAIL);
goto err_close_nocleanup;
}
bitcoin_create_anchor(peer, BITCOIN_ANCHOR_CREATED);
return next_state(peer, cstatus,
STATE_OPEN_WAIT_FOR_ANCHOR_CREATE);
} else if (input_is(input, CMD_CLOSE)) {
complete_cmd(peer, &cstatus, CMD_FAIL);
goto instant_close;
} else if (input_is_pkt(input)) {
complete_cmd(peer, &cstatus, CMD_FAIL);
goto unexpected_pkt_nocleanup;
}
break;
case STATE_OPEN_WAIT_FOR_ANCHOR_CREATE:
if (input_is(input, BITCOIN_ANCHOR_CREATED)) {
queue_pkt(out, pkt_anchor(ctx, peer));
return next_state(peer, cstatus,
STATE_OPEN_WAIT_FOR_COMMIT_SIG);
} else if (input_is(input, CMD_CLOSE)) {
bitcoin_release_anchor(peer, BITCOIN_ANCHOR_CREATED);
complete_cmd(peer, &cstatus, CMD_FAIL);
goto instant_close;
} else if (input_is_pkt(input)) {
bitcoin_release_anchor(peer, BITCOIN_ANCHOR_CREATED);
complete_cmd(peer, &cstatus, CMD_FAIL);
goto unexpected_pkt_nocleanup;
}
@ -190,6 +205,7 @@ enum command_status state(const tal_t *ctx,
if (input_is(input, PKT_OPEN_COMMIT_SIG)) {
err = accept_pkt_open_commit_sig(ctx, peer, idata->pkt);
if (err) {
bitcoin_release_anchor(peer, INPUT_NONE);
complete_cmd(peer, &cstatus, CMD_FAIL);
goto err_start_unilateral_close;
}
@ -203,9 +219,11 @@ enum command_status state(const tal_t *ctx,
return next_state(peer, cstatus,
STATE_OPEN_WAITING_OURANCHOR);
} else if (input_is(input, CMD_CLOSE)) {
bitcoin_release_anchor(peer, INPUT_NONE);
complete_cmd(peer, &cstatus, CMD_FAIL);
goto instant_close;
} else if (input_is_pkt(input)) {
bitcoin_release_anchor(peer, INPUT_NONE);
complete_cmd(peer, &cstatus, CMD_FAIL);
goto unexpected_pkt_nocleanup;
}

12
state.h

@ -318,9 +318,15 @@ 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);
/* Start creation of the bitcoin anchor tx. */
void bitcoin_create_anchor(struct peer *peer, enum state_input done);
/* We didn't end up broadcasting the anchor: release the utxos.
* If done != INPUT_NONE, remove existing create_anchor too. */
void bitcoin_release_anchor(struct peer *peer, enum state_input done);
/* Get the bitcoin anchor tx. */
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer);
/* Create a bitcoin close tx. */
struct bitcoin_tx *bitcoin_close(const tal_t *ctx,

3
state_types.h

@ -19,6 +19,7 @@ enum state {
*/
STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR,
STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR,
STATE_OPEN_WAIT_FOR_ANCHOR_CREATE,
STATE_OPEN_WAIT_FOR_ANCHOR,
STATE_OPEN_WAIT_FOR_COMMIT_SIG,
STATE_OPEN_WAITING_OURANCHOR,
@ -220,6 +221,8 @@ enum state_input {
/*
* Bitcoin events
*/
/* Bitcoin anchor tx created. */
BITCOIN_ANCHOR_CREATED,
/* It reached the required depth. */
BITCOIN_ANCHOR_DEPTHOK,
/* It didn't reach the required depth in time. */

40
test/test_state_coverage.c

@ -123,6 +123,9 @@ struct peer {
/* Transitory: True if we just declined an HTLC. */
bool htlc_declined;
/* Have we created an anchor tx? */
bool anchor;
unsigned int num_htlcs_to_them, num_htlcs_to_us;
struct htlc htlcs_to_them[MAX_HTLCS], htlcs_to_us[MAX_HTLCS];
@ -855,9 +858,11 @@ static bool bitcoin_tx_is(const struct bitcoin_tx *btx, const char *str)
return streq((const char *)btx, str);
}
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
const struct peer *peer)
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer)
{
if (!peer->anchor)
report_trail(peer->trail, "Can't create anchor tx: no anchor!");
peer->anchor = false;
return bitcoin_tx("anchor");
}
@ -937,6 +942,7 @@ static void peer_init(struct peer *peer,
peer->num_rvals_known = 0;
peer->error = NULL;
peer->htlc_declined = false;
peer->anchor = false;
memset(peer->core.outputs, 0, sizeof(peer->core.outputs));
peer->pkt_data[0] = -1;
peer->core.current_command = INPUT_NONE;
@ -1188,6 +1194,26 @@ void peer_watch_anchor(struct peer *peer,
add_event(peer, otherspent);
}
void bitcoin_create_anchor(struct peer *peer, enum state_input done)
{
/* We assume this below */
assert(done == BITCOIN_ANCHOR_CREATED);
if (peer->anchor)
report_trail(peer->trail, "Anchor already created?");
peer->anchor = true;
add_event(peer, done);
}
void bitcoin_release_anchor(struct peer *peer, enum state_input done)
{
if (!peer->anchor)
report_trail(peer->trail, "Anchor not created?");
peer->anchor = false;
remove_event(peer, done);
}
void peer_unwatch_anchor_depth(struct peer *peer,
enum state_input depthok,
enum state_input timeout)
@ -1492,6 +1518,9 @@ static const char *check_changes(const struct peer *old, struct peer *new,
if (new->current_htlc.htlc.id != -1)
return tal_fmt(NULL,
"cond CLOSE with pending htlc");
if (new->anchor)
return tal_fmt(NULL,
"cond CLOSE with anchor");
}
if (new->cond == PEER_CLOSED) {
/* FIXME: Move to state core */
@ -1736,13 +1765,15 @@ static bool waiting_statepair(enum state a, enum state b)
if (a == STATE_OPEN_WAITING_OURANCHOR
|| a == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|| a == STATE_OPEN_WAITING_THEIRANCHOR
|| a == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED)
|| a == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED
|| a == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE)
return true;
if (b == STATE_OPEN_WAITING_OURANCHOR
|| b == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|| b == STATE_OPEN_WAITING_THEIRANCHOR
|| b == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED)
|| b == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED
|| b == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE)
return true;
/* We don't need inputs at start of main loop. */
@ -2364,6 +2395,7 @@ int main(int argc, char *argv[])
|| i == STATE_ERR_ANCHOR_TIMEOUT)
a_expect = false;
if (i == STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR
|| i == STATE_OPEN_WAIT_FOR_ANCHOR_CREATE
|| i == STATE_OPEN_WAIT_FOR_COMMIT_SIG
|| i == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR
|| i == STATE_OPEN_WAITING_OURANCHOR

Loading…
Cancel
Save