Browse Source

peer: fix retransmission before open packet.

Re-enabling the next test revealed bugs: if we need to retransmit the
initial open_commit_sig packet, we currently tried to send it as an
UPDATE_COMMIT, which isn't allowed.  Fixing that revealed that if
we have to retransmit the initial open, we didn't do that either.

Thus the initial open should count towards the ack count, and we should
special case transmissions of 0 (pkt_open) and 1
(pkt_open_commit_sig).

We also save those early state changes to the database.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 8 years ago
parent
commit
56b0f03c5a
  1. 10
      daemon/db.c
  2. 3
      daemon/db.h
  3. 47
      daemon/peer.c

10
daemon/db.c

@ -931,7 +931,6 @@ static void restore_peer_local_visible_state(struct peer *peer)
if (!peer->anchor.ours)
peer->their_commitsigs--;
peer->order_counter = 0;
if (peer->local.commit->order + 1 > peer->order_counter)
peer->order_counter = peer->local.commit->order + 1;
if (peer->remote.commit->order + 1 > peer->order_counter)
@ -980,6 +979,7 @@ static void db_load_peers(struct lightningd_state *dstate)
peer->htlc_id_counter = 0;
peer->id = tal_dup(peer, struct pubkey, &id);
peer->local.commit_fee_rate = sqlite3_column_int64(stmt, 3);
peer->order_counter = 1;
log_debug(peer->log, "%s:%s",
__func__, state_name(peer->state));
}
@ -1439,13 +1439,13 @@ void db_update_next_revocation_hash(struct peer *peer)
tal_free(ctx);
}
bool db_create_peer(struct peer *peer)
void db_create_peer(struct peer *peer)
{
const char *errmsg, *ctx = tal_tmpctx(peer);
const char *ctx = tal_tmpctx(peer);
const char *peerid = pubkey_to_hexstr(ctx, peer->dstate->secpctx, peer->id);
log_debug(peer->log, "%s(%s)", __func__, peerid);
db_start_transaction(peer);
assert(peer->dstate->db->in_transaction);
db_exec(__func__, peer->dstate,
"INSERT INTO peers VALUES (x'%s', '%s', %s, %"PRIi64");",
peerid,
@ -1470,9 +1470,7 @@ bool db_create_peer(struct peer *peer)
pubkey_to_hexstr(ctx, peer->dstate->secpctx,
&peer->anchor.input->walletkey));
errmsg = db_commit_transaction(peer);
tal_free(ctx);
return !errmsg;
}
void db_start_transaction(struct peer *peer)

3
daemon/db.h

@ -6,8 +6,6 @@
void db_init(struct lightningd_state *dstate);
bool db_create_peer(struct peer *peer);
void db_start_transaction(struct peer *peer);
void db_abort_transaction(struct peer *peer);
const char *db_commit_transaction(struct peer *peer);
@ -42,6 +40,7 @@ bool db_remove_invoice(struct lightningd_state *dstate,
* which have to be inside transaction anyway. */
/* Must be inside transaction. */
void db_create_peer(struct peer *peer);
void db_set_visible_state(struct peer *peer);
void db_set_anchor(struct peer *peer);
void db_new_htlc(struct peer *peer, const struct htlc *htlc);

47
daemon/peer.c

@ -588,14 +588,14 @@ static bool open_pkt_in(struct peer *peer, const Pkt *pkt)
return peer_comms_err(peer, err);
}
set_peer_state(peer, STATE_OPEN_WAIT_FOR_COMMIT_SIGPKT,
__func__, false);
__func__, true);
if (db_commit_transaction(peer) != NULL)
return peer_database_err(peer);
queue_pkt_anchor(peer);
return true;
} else {
set_peer_state(peer, STATE_OPEN_WAIT_FOR_ANCHORPKT,
__func__, false);
__func__, true);
if (db_commit_transaction(peer) != NULL)
return peer_database_err(peer);
return true;
@ -646,7 +646,7 @@ static bool open_ouranchor_pkt_in(struct peer *peer, const Pkt *pkt)
db_new_commit_info(peer, LOCAL, NULL);
set_peer_state(peer,
STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE,
__func__, false);
__func__, true);
if (db_commit_transaction(peer) != NULL)
return peer_database_err(peer);
@ -697,7 +697,7 @@ static bool open_theiranchor_pkt_in(struct peer *peer, const Pkt *pkt)
&peer->remote.commit->txid,
peer->remote.commit->commit_num);
set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE,
__func__, false);
__func__, true);
db_err = db_commit_transaction(peer);
if (db_err) {
peer_open_complete(peer, db_err);
@ -748,7 +748,7 @@ static bool open_wait_pkt_in(struct peer *peer, const Pkt *pkt)
set_peer_state(peer, STATE_NORMAL, __func__, true);
} else {
set_peer_state(peer, STATE_OPEN_WAIT_ANCHORDEPTH,
__func__, false);
__func__, true);
}
db_err = db_commit_transaction(peer);
@ -2352,7 +2352,12 @@ static void retransmit_pkts(struct peer *peer, s64 ack)
* type which was not counted by the `ack` field.
*/
while (ack < peer->order_counter) {
if (peer->remote.commit && ack == peer->remote.commit->order) {
if (ack == 0) {
queue_pkt_open(peer, peer->local.offer_anchor);
} else if (ack == 1) {
queue_pkt_open_commit_sig(peer);
} else if (peer->remote.commit
&& ack == peer->remote.commit->order) {
/* BOLT #2:
*
* Before retransmitting `update_commit`, the node
@ -2516,27 +2521,28 @@ static u64 peer_revocations_received(struct peer *peer)
static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer)
{
u64 sigs, revokes, shutdown, closing;
u64 open, sigs, revokes, shutdown, closing;
open = (peer->state == STATE_OPEN_WAIT_FOR_OPENPKT ? 0 : 1);
sigs = peer_commitsigs_received(peer);
revokes = peer_revocations_received(peer);
shutdown = peer->closing.their_script ? 1 : 0;
closing = peer->closing.sigs_in;
log_debug(peer->log,
"Init with ack %"PRIu64" sigs + %"PRIu64" revokes"
" + %"PRIu64" shutdown + %"PRIu64" closing",
sigs, revokes, shutdown, closing);
"Init with ack %"PRIu64" opens + %"PRIu64" sigs + %"
PRIu64" revokes + %"PRIu64" shutdown + %"PRIu64" closing",
open, sigs, revokes, shutdown, closing);
/* BOLT #2:
*
* A node MUST send an `init` message immediately immediately after
* it has validated the `authenticate` message. A node MUST set
* the `ack` field in the `init` message to the the sum of
* previously-processed messages of types `open_commit_sig`,
* previously-processed messages of types `open`, `open_commit_sig`,
* `update_commit`, `update_revocation`, `close_shutdown` and
* `close_signature`. */
return peer_write_packet(conn, peer,
pkt_init(peer, sigs + revokes
pkt_init(peer, open + sigs + revokes
+ shutdown + closing),
read_init_pkt);
}
@ -2550,12 +2556,18 @@ static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer)
assert(peer->state == STATE_INIT);
set_peer_state(peer, STATE_OPEN_WAIT_FOR_OPENPKT, __func__, false);
/* Counter is 1 for sending pkt_open: we'll do it in retransmit_pkts */
peer->order_counter++;
/* FIXME: Start timeout, and close peer if they don't progress! */
db_start_transaction(peer);
set_peer_state(peer, STATE_OPEN_WAIT_FOR_OPENPKT, __func__, true);
if (!db_create_peer(peer))
fatal("Database error in %s", __func__);
/* FIXME: Start timeout, and close peer if they don't progress! */
db_create_peer(peer);
if (db_commit_transaction(peer) != NULL) {
peer_database_err(peer);
return peer_close(conn, peer);
}
/* Set up out commit info now: rest gets done in setup_first_commit
* once anchor is established. */
@ -2563,7 +2575,6 @@ static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer)
peer->local.commit->revocation_hash = peer->local.next_revocation_hash;
peer_get_revocation_hash(peer, 1, &peer->local.next_revocation_hash);
queue_pkt_open(peer, peer->local.offer_anchor);
return peer_send_init(conn,peer);
}
@ -3261,7 +3272,7 @@ static void peer_depth_ok(struct peer *peer)
switch (peer->state) {
case STATE_OPEN_WAIT_ANCHORDEPTH_AND_THEIRCOMPLETE:
set_peer_state(peer, STATE_OPEN_WAIT_THEIRCOMPLETE,
__func__, false);
__func__, true);
break;
case STATE_OPEN_WAIT_ANCHORDEPTH:
peer_open_complete(peer, NULL);

Loading…
Cancel
Save