mirror of
https://github.com/aljazceru/lightning.git
synced 2025-12-19 23:24:27 +01:00
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>
This commit is contained in:
22
state.c
22
state.c
@@ -149,9 +149,9 @@ enum command_status state(const tal_t *ctx,
|
|||||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||||
goto err_close_nocleanup;
|
goto err_close_nocleanup;
|
||||||
}
|
}
|
||||||
queue_pkt(out, pkt_anchor(ctx, peer));
|
bitcoin_create_anchor(peer, BITCOIN_ANCHOR_CREATED);
|
||||||
return next_state(peer, cstatus,
|
return next_state(peer, cstatus,
|
||||||
STATE_OPEN_WAIT_FOR_COMMIT_SIG);
|
STATE_OPEN_WAIT_FOR_ANCHOR_CREATE);
|
||||||
} else if (input_is(input, CMD_CLOSE)) {
|
} else if (input_is(input, CMD_CLOSE)) {
|
||||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||||
goto instant_close;
|
goto instant_close;
|
||||||
@@ -160,6 +160,21 @@ enum command_status state(const tal_t *ctx,
|
|||||||
goto unexpected_pkt_nocleanup;
|
goto unexpected_pkt_nocleanup;
|
||||||
}
|
}
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case STATE_OPEN_WAIT_FOR_ANCHOR:
|
case STATE_OPEN_WAIT_FOR_ANCHOR:
|
||||||
if (input_is(input, PKT_OPEN_ANCHOR)) {
|
if (input_is(input, PKT_OPEN_ANCHOR)) {
|
||||||
err = accept_pkt_anchor(ctx, peer, idata->pkt);
|
err = accept_pkt_anchor(ctx, peer, idata->pkt);
|
||||||
@@ -190,6 +205,7 @@ enum command_status state(const tal_t *ctx,
|
|||||||
if (input_is(input, PKT_OPEN_COMMIT_SIG)) {
|
if (input_is(input, PKT_OPEN_COMMIT_SIG)) {
|
||||||
err = accept_pkt_open_commit_sig(ctx, peer, idata->pkt);
|
err = accept_pkt_open_commit_sig(ctx, peer, idata->pkt);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||||
goto err_start_unilateral_close;
|
goto err_start_unilateral_close;
|
||||||
}
|
}
|
||||||
@@ -203,9 +219,11 @@ enum command_status state(const tal_t *ctx,
|
|||||||
return next_state(peer, cstatus,
|
return next_state(peer, cstatus,
|
||||||
STATE_OPEN_WAITING_OURANCHOR);
|
STATE_OPEN_WAITING_OURANCHOR);
|
||||||
} else if (input_is(input, CMD_CLOSE)) {
|
} else if (input_is(input, CMD_CLOSE)) {
|
||||||
|
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||||
goto instant_close;
|
goto instant_close;
|
||||||
} else if (input_is_pkt(input)) {
|
} else if (input_is_pkt(input)) {
|
||||||
|
bitcoin_release_anchor(peer, INPUT_NONE);
|
||||||
complete_cmd(peer, &cstatus, CMD_FAIL);
|
complete_cmd(peer, &cstatus, CMD_FAIL);
|
||||||
goto unexpected_pkt_nocleanup;
|
goto unexpected_pkt_nocleanup;
|
||||||
}
|
}
|
||||||
|
|||||||
12
state.h
12
state.h
@@ -318,9 +318,15 @@ void peer_unwatch_htlc_spend(struct peer *peer,
|
|||||||
const struct htlc *htlc,
|
const struct htlc *htlc,
|
||||||
enum state_input all_done);
|
enum state_input all_done);
|
||||||
|
|
||||||
/* Create a bitcoin anchor tx. */
|
/* Start creation of the bitcoin anchor tx. */
|
||||||
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
|
void bitcoin_create_anchor(struct peer *peer, enum state_input done);
|
||||||
const struct peer *peer);
|
|
||||||
|
/* 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. */
|
/* Create a bitcoin close tx. */
|
||||||
struct bitcoin_tx *bitcoin_close(const tal_t *ctx,
|
struct bitcoin_tx *bitcoin_close(const tal_t *ctx,
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ enum state {
|
|||||||
*/
|
*/
|
||||||
STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR,
|
STATE_OPEN_WAIT_FOR_OPEN_NOANCHOR,
|
||||||
STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR,
|
STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR,
|
||||||
|
STATE_OPEN_WAIT_FOR_ANCHOR_CREATE,
|
||||||
STATE_OPEN_WAIT_FOR_ANCHOR,
|
STATE_OPEN_WAIT_FOR_ANCHOR,
|
||||||
STATE_OPEN_WAIT_FOR_COMMIT_SIG,
|
STATE_OPEN_WAIT_FOR_COMMIT_SIG,
|
||||||
STATE_OPEN_WAITING_OURANCHOR,
|
STATE_OPEN_WAITING_OURANCHOR,
|
||||||
@@ -220,6 +221,8 @@ enum state_input {
|
|||||||
/*
|
/*
|
||||||
* Bitcoin events
|
* Bitcoin events
|
||||||
*/
|
*/
|
||||||
|
/* Bitcoin anchor tx created. */
|
||||||
|
BITCOIN_ANCHOR_CREATED,
|
||||||
/* It reached the required depth. */
|
/* It reached the required depth. */
|
||||||
BITCOIN_ANCHOR_DEPTHOK,
|
BITCOIN_ANCHOR_DEPTHOK,
|
||||||
/* It didn't reach the required depth in time. */
|
/* It didn't reach the required depth in time. */
|
||||||
|
|||||||
@@ -123,6 +123,9 @@ struct peer {
|
|||||||
/* Transitory: True if we just declined an HTLC. */
|
/* Transitory: True if we just declined an HTLC. */
|
||||||
bool htlc_declined;
|
bool htlc_declined;
|
||||||
|
|
||||||
|
/* Have we created an anchor tx? */
|
||||||
|
bool anchor;
|
||||||
|
|
||||||
unsigned int num_htlcs_to_them, num_htlcs_to_us;
|
unsigned int num_htlcs_to_them, num_htlcs_to_us;
|
||||||
struct htlc htlcs_to_them[MAX_HTLCS], htlcs_to_us[MAX_HTLCS];
|
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);
|
return streq((const char *)btx, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx,
|
struct bitcoin_tx *bitcoin_anchor(const tal_t *ctx, struct peer *peer)
|
||||||
const struct peer *peer)
|
|
||||||
{
|
{
|
||||||
|
if (!peer->anchor)
|
||||||
|
report_trail(peer->trail, "Can't create anchor tx: no anchor!");
|
||||||
|
peer->anchor = false;
|
||||||
return bitcoin_tx("anchor");
|
return bitcoin_tx("anchor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -937,6 +942,7 @@ static void peer_init(struct peer *peer,
|
|||||||
peer->num_rvals_known = 0;
|
peer->num_rvals_known = 0;
|
||||||
peer->error = NULL;
|
peer->error = NULL;
|
||||||
peer->htlc_declined = false;
|
peer->htlc_declined = false;
|
||||||
|
peer->anchor = false;
|
||||||
memset(peer->core.outputs, 0, sizeof(peer->core.outputs));
|
memset(peer->core.outputs, 0, sizeof(peer->core.outputs));
|
||||||
peer->pkt_data[0] = -1;
|
peer->pkt_data[0] = -1;
|
||||||
peer->core.current_command = INPUT_NONE;
|
peer->core.current_command = INPUT_NONE;
|
||||||
@@ -1188,6 +1194,26 @@ void peer_watch_anchor(struct peer *peer,
|
|||||||
add_event(peer, otherspent);
|
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,
|
void peer_unwatch_anchor_depth(struct peer *peer,
|
||||||
enum state_input depthok,
|
enum state_input depthok,
|
||||||
enum state_input timeout)
|
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)
|
if (new->current_htlc.htlc.id != -1)
|
||||||
return tal_fmt(NULL,
|
return tal_fmt(NULL,
|
||||||
"cond CLOSE with pending htlc");
|
"cond CLOSE with pending htlc");
|
||||||
|
if (new->anchor)
|
||||||
|
return tal_fmt(NULL,
|
||||||
|
"cond CLOSE with anchor");
|
||||||
}
|
}
|
||||||
if (new->cond == PEER_CLOSED) {
|
if (new->cond == PEER_CLOSED) {
|
||||||
/* FIXME: Move to state core */
|
/* 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
|
if (a == STATE_OPEN_WAITING_OURANCHOR
|
||||||
|| a == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|
|| a == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|
||||||
|| a == STATE_OPEN_WAITING_THEIRANCHOR
|
|| 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;
|
return true;
|
||||||
|
|
||||||
if (b == STATE_OPEN_WAITING_OURANCHOR
|
if (b == STATE_OPEN_WAITING_OURANCHOR
|
||||||
|| b == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|
|| b == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED
|
||||||
|| b == STATE_OPEN_WAITING_THEIRANCHOR
|
|| 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;
|
return true;
|
||||||
|
|
||||||
/* We don't need inputs at start of main loop. */
|
/* 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)
|
|| i == STATE_ERR_ANCHOR_TIMEOUT)
|
||||||
a_expect = false;
|
a_expect = false;
|
||||||
if (i == STATE_OPEN_WAIT_FOR_OPEN_WITHANCHOR
|
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_COMMIT_SIG
|
||||||
|| i == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR
|
|| i == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR
|
||||||
|| i == STATE_OPEN_WAITING_OURANCHOR
|
|| i == STATE_OPEN_WAITING_OURANCHOR
|
||||||
|
|||||||
Reference in New Issue
Block a user