From eedf95a8fc0a87e48028f86dfa588bbccfa895f4 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 9 Nov 2016 08:04:26 +1030 Subject: [PATCH] state_types: simplify open states. The state now doesn't differentiate between who is funding. Signed-off-by: Rusty Russell --- daemon/db.c | 6 +- daemon/peer.c | 287 +++++++++++++++++++------------------------- daemon/test/test.sh | 6 +- state.h | 23 ++-- state_types.h | 17 +-- 5 files changed, 152 insertions(+), 187 deletions(-) diff --git a/daemon/db.c b/daemon/db.c index 7e787b122..afd0ad4a6 100644 --- a/daemon/db.c +++ b/daemon/db.c @@ -59,8 +59,8 @@ static const char *sqlite3_column_str(sqlite3_stmt *stmt, int iCol) #define SQL_RHASH(var) stringify(var)" CHAR(32)" #define SQL_SHA256(var) stringify(var)" CHAR(32)" #define SQL_R(var) stringify(var)" CHAR(32)" -/* STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED == 44*/ -#define SQL_STATENAME(var) stringify(var)" VARCHAR(44)" +/* STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE == 45*/ +#define SQL_STATENAME(var) stringify(var)" VARCHAR(45)" #define SQL_INVLABEL(var) stringify(var)" VARCHAR("stringify(INVOICE_MAX_LABEL_LEN)")" /* 8 + 4 + (8 + 32) * (64 + 1) */ @@ -953,7 +953,7 @@ static void db_load_peers(struct lightningd_state *dstate) load_peer_secrets(peer); load_peer_closing(peer); peer->anchor.min_depth = 0; - if (peer->state >= STATE_OPEN_WAITING_OURANCHOR + if (peer->state >= STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE && !state_is_error(peer->state)) { load_peer_anchor(peer); load_peer_visible_state(peer); diff --git a/daemon/peer.c b/daemon/peer.c index 427574a7c..33bbf0746 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -558,7 +558,6 @@ static bool open_pkt_in(struct peer *peer, const Pkt *pkt) assert(peer->state == STATE_OPEN_WAIT_FOR_OPENPKT); - /* FIXME: Handle PKT_SHUTDOWN? */ if (pkt->pkt_case != PKT__PKT_OPEN) return peer_received_unexpected_pkt(peer, pkt, __func__); @@ -595,7 +594,7 @@ static bool open_pkt_in(struct peer *peer, const Pkt *pkt) err = pkt_err(peer, "Own anchor has insufficient funds"); return peer_comms_err(peer, err); } - set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMMIT_SIG, + set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT, __func__, false); if (db_commit_transaction(peer) != NULL) { err = pkt_err(peer, "database error"); @@ -604,7 +603,7 @@ static bool open_pkt_in(struct peer *peer, const Pkt *pkt) queue_pkt_anchor(peer); return true; } else { - set_peer_state(peer, STATE_OPEN_WAIT_FOR_ANCHOR, + set_peer_state(peer, STATE_OPEN_WAIT_FOR_ANCHORPKT, __func__, false); if (db_commit_transaction(peer) != NULL) { err = pkt_err(peer, "database error"); @@ -630,187 +629,151 @@ static bool open_ouranchor_pkt_in(struct peer *peer, const Pkt *pkt) { Pkt *err; - if (pkt->pkt_case == PKT__PKT_CLOSE_SHUTDOWN) { - err = accept_pkt_close_shutdown(peer, pkt); - if (err) - return peer_comms_err(peer, err); - - set_peer_state(peer, STATE_SHUTDOWN, __func__, false); - peer_breakdown(peer); - return false; - } - - switch (peer->state) { - case STATE_OPEN_WAIT_FOR_COMMIT_SIG: - if (pkt->pkt_case != PKT__PKT_OPEN_COMMIT_SIG) - return peer_received_unexpected_pkt(peer, pkt, __func__); - - peer->local.commit->sig = tal(peer->local.commit, - struct bitcoin_signature); - err = accept_pkt_open_commit_sig(peer, pkt, - peer->local.commit->sig); - if (!err && - !check_tx_sig(peer->dstate->secpctx, - peer->local.commit->tx, 0, - NULL, 0, - peer->anchor.witnessscript, - &peer->remote.commitkey, - peer->local.commit->sig)) - err = pkt_err(peer, "Bad signature"); - - if (err) { - peer->local.commit->sig - = tal_free(peer->local.commit->sig); - return peer_comms_err(peer, err); - } - - peer->their_commitsigs++; - - db_start_transaction(peer); - db_set_anchor(peer); - db_new_commit_info(peer, LOCAL, NULL); - set_peer_state(peer, STATE_OPEN_WAITING_OURANCHOR, - __func__, false); - if (db_commit_transaction(peer) != NULL) { - err = pkt_err(peer, "database error"); - return peer_comms_err(peer, err); - } - broadcast_tx(peer, peer->anchor.tx, funding_tx_failed); - peer_watch_anchor(peer, peer->local.mindepth); - return true; - - case STATE_OPEN_WAITING_OURANCHOR: - case STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR: - if (pkt->pkt_case == PKT__PKT_OPEN_COMPLETE) { - err = accept_pkt_open_complete(peer, pkt); - if (err) - return peer_comms_err(peer, err); - - db_start_transaction(peer); - /* We've already noticed anchor reach depth? */ - if (peer->state == STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR) { - peer_open_complete(peer, NULL); - set_peer_state(peer, STATE_NORMAL, - __func__, true); - } else { - set_peer_state(peer, - STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED, - __func__, false); - } - if (db_commit_transaction(peer) != NULL) { - err = pkt_err(peer, "database error"); - return peer_comms_err(peer, err); - } - return true; - } - /* Fall thru */ - case STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED: + if (pkt->pkt_case != PKT__PKT_OPEN_COMMIT_SIG) return peer_received_unexpected_pkt(peer, pkt, __func__); - default: - log_unusual(peer->log, - "%s: unexpected state %s", - __func__, state_name(peer->state)); - peer_fail(peer, __func__); - return false; + peer->local.commit->sig = tal(peer->local.commit, + struct bitcoin_signature); + err = accept_pkt_open_commit_sig(peer, pkt, + peer->local.commit->sig); + if (!err && + !check_tx_sig(peer->dstate->secpctx, + peer->local.commit->tx, 0, + NULL, 0, + peer->anchor.witnessscript, + &peer->remote.commitkey, + peer->local.commit->sig)) + err = pkt_err(peer, "Bad signature"); + + if (err) { + peer->local.commit->sig = tal_free(peer->local.commit->sig); + return peer_comms_err(peer, err); } + + peer->their_commitsigs++; + + db_start_transaction(peer); + db_set_anchor(peer); + db_new_commit_info(peer, LOCAL, NULL); + set_peer_state(peer, + STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, + __func__, false); + if (db_commit_transaction(peer) != NULL) { + err = pkt_err(peer, "database error"); + return peer_comms_err(peer, err); + } + broadcast_tx(peer, peer->anchor.tx, funding_tx_failed); + peer_watch_anchor(peer, peer->local.mindepth); + return true; } + static bool open_theiranchor_pkt_in(struct peer *peer, const Pkt *pkt) { Pkt *err; const char *db_err; + if (pkt->pkt_case != PKT__PKT_OPEN_ANCHOR) + return peer_received_unexpected_pkt(peer, pkt, __func__); + + err = accept_pkt_anchor(peer, pkt); + if (err) { + peer_open_complete(peer, err->error->problem); + return peer_comms_err(peer, err); + } + + peer->anchor.ours = false; + if (!setup_first_commit(peer)) { + err = pkt_err(peer, "Insufficient funds for fee"); + peer_open_complete(peer, err->error->problem); + return peer_comms_err(peer, err); + } + + log_debug_struct(peer->log, "Creating sig for %s", + struct bitcoin_tx, + peer->remote.commit->tx); + log_add_struct(peer->log, " using key %s", + struct pubkey, &peer->local.commitkey); + + peer->remote.commit->sig = tal(peer->remote.commit, + struct bitcoin_signature); + peer->remote.commit->sig->stype = SIGHASH_ALL; + peer_sign_theircommit(peer, peer->remote.commit->tx, + &peer->remote.commit->sig->sig); + + peer->remote.commit->order = peer->order_counter++; + db_start_transaction(peer); + db_set_anchor(peer); + db_new_commit_info(peer, REMOTE, NULL); + peer_add_their_commit(peer, + &peer->remote.commit->txid, + peer->remote.commit->commit_num); + set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, + __func__, false); + db_err = db_commit_transaction(peer); + if (db_err) { + err = pkt_err(peer, "database error"); + peer_open_complete(peer, db_err); + return peer_comms_err(peer, err); + } + + queue_pkt_open_commit_sig(peer); + peer_watch_anchor(peer, peer->local.mindepth); + return true; +} + +static bool open_wait_pkt_in(struct peer *peer, const Pkt *pkt) +{ + Pkt *err; + const char *db_err; + + /* If they want to shutdown during this, we do mutual close dance. */ if (pkt->pkt_case == PKT__PKT_CLOSE_SHUTDOWN) { err = accept_pkt_close_shutdown(peer, pkt); if (err) return peer_comms_err(peer, err); - set_peer_state(peer, STATE_SHUTDOWN, __func__, false); - peer_breakdown(peer); + /* FIXME: All in one transaction! */ + if (!db_set_their_closing_script(peer)) + err = pkt_err(peer, "database error"); + else + err = start_closing(peer); + + if (err) + return peer_comms_err(peer, err); return false; } switch (peer->state) { - case STATE_OPEN_WAIT_FOR_ANCHOR: - if (pkt->pkt_case != PKT__PKT_OPEN_ANCHOR) + case STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE: + case STATE_OPEN_WAIT_THEIRCOMPLETE: + if (pkt->pkt_case != PKT__PKT_OPEN_COMPLETE) return peer_received_unexpected_pkt(peer, pkt, __func__); - - err = accept_pkt_anchor(peer, pkt); + + err = accept_pkt_open_complete(peer, pkt); if (err) { peer_open_complete(peer, err->error->problem); return peer_comms_err(peer, err); } - peer->anchor.ours = false; - if (!setup_first_commit(peer)) { - err = pkt_err(peer, "Insufficient funds for fee"); - peer_open_complete(peer, err->error->problem); - return peer_comms_err(peer, err); + db_start_transaction(peer); + if (peer->state == STATE_OPEN_WAIT_THEIRCOMPLETE) { + peer_open_complete(peer, NULL); + set_peer_state(peer, STATE_NORMAL, __func__, true); + } else { + set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH, + __func__, false); } - log_debug_struct(peer->log, "Creating sig for %s", - struct bitcoin_tx, - peer->remote.commit->tx); - log_add_struct(peer->log, " using key %s", - struct pubkey, &peer->local.commitkey); - - peer->remote.commit->sig = tal(peer->remote.commit, - struct bitcoin_signature); - peer->remote.commit->sig->stype = SIGHASH_ALL; - peer_sign_theircommit(peer, peer->remote.commit->tx, - &peer->remote.commit->sig->sig); - - peer->remote.commit->order = peer->order_counter++; - db_start_transaction(peer); - db_set_anchor(peer); - db_new_commit_info(peer, REMOTE, NULL); - peer_add_their_commit(peer, - &peer->remote.commit->txid, - peer->remote.commit->commit_num); - set_peer_state(peer, STATE_OPEN_WAITING_THEIRANCHOR, __func__, - false); db_err = db_commit_transaction(peer); if (db_err) { err = pkt_err(peer, "database error"); peer_open_complete(peer, db_err); return peer_comms_err(peer, err); } - - queue_pkt_open_commit_sig(peer); - peer_watch_anchor(peer, peer->local.mindepth); return true; - case STATE_OPEN_WAITING_THEIRANCHOR: - case STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR: - if (pkt->pkt_case == PKT__PKT_OPEN_COMPLETE) { - err = accept_pkt_open_complete(peer, pkt); - if (err) { - peer_open_complete(peer, err->error->problem); - return peer_comms_err(peer, err); - } - - db_start_transaction(peer); - if (peer->state == STATE_OPEN_WAITING_THEIRANCHOR) { - set_peer_state(peer, - STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED, - __func__, false); - } else { - peer_open_complete(peer, NULL); - set_peer_state(peer, STATE_NORMAL, - __func__, true); - } - - db_err = db_commit_transaction(peer); - if (db_err) { - err = pkt_err(peer, "database error"); - peer_open_complete(peer, db_err); - return peer_comms_err(peer, err); - } - return true; - } - /* Fall thru */ - case STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED: + case STATE_OPEN_WAIT_ANCHORDEPTH: return peer_received_unexpected_pkt(peer, pkt, __func__); default: @@ -821,7 +784,7 @@ static bool open_theiranchor_pkt_in(struct peer *peer, const Pkt *pkt) return false; } } - + static void set_htlc_rval(struct peer *peer, struct htlc *htlc, const struct rval *rval) { @@ -2229,12 +2192,13 @@ static struct io_plan *pkt_in(struct io_conn *conn, struct peer *peer) keep_going = closing_pkt_in(peer, peer->inpkt); else if (peer->state == STATE_OPEN_WAIT_FOR_OPENPKT) keep_going = open_pkt_in(peer, peer->inpkt); - else if (state_is_opening(peer->state)) { - if (peer->local.offer_anchor) - keep_going = open_ouranchor_pkt_in(peer, peer->inpkt); - else - keep_going = open_theiranchor_pkt_in(peer, peer->inpkt); - } else { + else if (peer->state == STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT) + keep_going = open_ouranchor_pkt_in(peer, peer->inpkt); + else if (peer->state == STATE_OPEN_WAIT_FOR_ANCHORPKT) + keep_going = open_theiranchor_pkt_in(peer, peer->inpkt); + else if (state_is_openwait(peer->state)) + keep_going = open_wait_pkt_in(peer, peer->inpkt); + else { log_unusual(peer->log, "Unexpected state %s", state_name(peer->state)); keep_going = false; @@ -3305,16 +3269,11 @@ static void peer_depth_ok(struct peer *peer) db_start_transaction(peer); switch (peer->state) { - case STATE_OPEN_WAITING_OURANCHOR: - set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR, + case STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE: + set_peer_state(peer, STATE_OPEN_WAIT_THEIRCOMPLETE, __func__, false); break; - case STATE_OPEN_WAITING_THEIRANCHOR: - set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR, - __func__, false); - break; - case STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED: - case STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED: + case STATE_OPEN_WAIT_ANCHORDEPTH: peer_open_complete(peer, NULL); set_peer_state(peer, STATE_NORMAL, __func__, true); break; diff --git a/daemon/test/test.sh b/daemon/test/test.sh index 9db2853a8..a7939c6ee 100755 --- a/daemon/test/test.sh +++ b/daemon/test/test.sh @@ -475,9 +475,9 @@ $CLI generate 1 lcli1 connect localhost $PORT2 $TX & -# Expect them to be waiting for anchor. -check_peerstate lcli1 STATE_OPEN_WAITING_OURANCHOR -check_peerstate lcli2 STATE_OPEN_WAITING_THEIRANCHOR +# Expect them to be waiting for anchor, and ack from other side. +check_peerstate lcli1 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE +check_peerstate lcli2 STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE DO_RECONNECT=$RECONNECT diff --git a/state.h b/state.h index a5507f717..175340027 100644 --- a/state.h +++ b/state.h @@ -35,17 +35,22 @@ static inline bool state_is_normal(enum state s) return s == STATE_NORMAL || s == STATE_NORMAL_COMMITTING; } -static inline bool state_is_opening(enum state s) -{ - return s < STATE_NORMAL; -} - static inline bool state_is_waiting_for_anchor(enum state s) { - return s == STATE_OPEN_WAITING_OURANCHOR - || s == STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED - || s == STATE_OPEN_WAITING_THEIRANCHOR - || s == STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED; + return s == STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE + || s == STATE_OPEN_WAIT_ANCHORDEPTH; +} + +static inline bool state_is_openwait(enum state s) +{ + return s == STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE + || s == STATE_OPEN_WAIT_ANCHORDEPTH + || s == STATE_OPEN_WAIT_THEIRCOMPLETE; +} + +static inline bool state_is_opening(enum state s) +{ + return s <= STATE_OPEN_WAIT_THEIRCOMPLETE; } static inline bool state_can_io(enum state s) diff --git a/state_types.h b/state_types.h index 6ede4f7bf..2286a492b 100644 --- a/state_types.h +++ b/state_types.h @@ -11,14 +11,15 @@ enum state { * Opening. */ STATE_OPEN_WAIT_FOR_OPENPKT, - STATE_OPEN_WAIT_FOR_ANCHOR, - STATE_OPEN_WAIT_FOR_COMMIT_SIG, - STATE_OPEN_WAITING_OURANCHOR, - STATE_OPEN_WAITING_THEIRANCHOR, - STATE_OPEN_WAITING_OURANCHOR_THEYCOMPLETED, - STATE_OPEN_WAITING_THEIRANCHOR_THEYCOMPLETED, - STATE_OPEN_WAIT_FOR_COMPLETE_OURANCHOR, - STATE_OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR, + STATE_OPEN_WAIT_FOR_ANCHORPKT, + STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT, + + /* We're waiting for depth+their complete. */ + STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE, + /* Got their pkt_complete. */ + STATE_OPEN_WAIT_ANCHORDEPTH, + /* Got anchor depth. */ + STATE_OPEN_WAIT_THEIRCOMPLETE, /* * Normal state.