From ec64e7756efcc97ba175650ad4a4374eeac8785a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 7 Oct 2016 17:39:34 +1030 Subject: [PATCH] protocol: pkt_reconnect becomes pkt_init, and always send. Make this always the first packet after auth. That means there's no reliance on whether a node remembers an aborted connection. It also gives us a place to put version bits. Signed-off-by: Rusty Russell --- daemon/packets.c | 10 +-- daemon/packets.h | 2 +- daemon/peer.c | 166 ++++++++++++++++++++++++----------------------- lightning.pb-c.c | 72 ++++++++++---------- lightning.pb-c.h | 54 +++++++-------- lightning.proto | 6 +- 6 files changed, 156 insertions(+), 154 deletions(-) diff --git a/daemon/packets.c b/daemon/packets.c index 985231777..cee0f518a 100644 --- a/daemon/packets.c +++ b/daemon/packets.c @@ -236,12 +236,12 @@ Pkt *pkt_err(struct peer *peer, const char *msg, ...) return make_pkt(peer, PKT__PKT_ERROR, e); } -Pkt *pkt_reconnect(struct peer *peer, u64 ack) +Pkt *pkt_init(struct peer *peer, u64 ack) { - Reconnect *r = tal(peer, Reconnect); - reconnect__init(r); - r->ack = ack; - return make_pkt(peer, PKT__PKT_RECONNECT, r); + Init *i = tal(peer, Init); + init__init(i); + i->ack = ack; + return make_pkt(peer, PKT__PKT_INIT, i); } void queue_pkt_err(struct peer *peer, Pkt *err) diff --git a/daemon/packets.h b/daemon/packets.h index ae99395b9..111fe1c7a 100644 --- a/daemon/packets.h +++ b/daemon/packets.h @@ -26,7 +26,7 @@ void queue_pkt_close_shutdown(struct peer *peer); void queue_pkt_close_signature(struct peer *peer); Pkt *pkt_err(struct peer *peer, const char *msg, ...); -Pkt *pkt_reconnect(struct peer *peer, u64 ack); +Pkt *pkt_init(struct peer *peer, u64 ack); void queue_pkt_err(struct peer *peer, Pkt *err); Pkt *pkt_err_unexpected(struct peer *peer, const Pkt *pkt); diff --git a/daemon/peer.c b/daemon/peer.c index e8b824543..aed157824 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -2091,6 +2091,86 @@ static void peer_has_connected(struct peer *peer) } } +static struct io_plan *init_pkt_in(struct io_conn *conn, struct peer *peer) +{ + if (peer->inpkt->pkt_case != PKT__PKT_INIT) { + peer_received_unexpected_pkt(peer, peer->inpkt, __func__); + return pkt_out(conn, peer); + } + + /* They might have missed the error, tell them before hanging up */ + if (state_is_error(peer->state)) { + queue_pkt_err(peer, pkt_err(peer, "In error state %s", + state_name(peer->state))); + return pkt_out(conn, peer); + } + + /* Send any packets they missed. */ + retransmit_pkts(peer, peer->inpkt->init->ack); + + /* We let the conversation go this far in case they missed the + * close packets. But now we can close if we're done. */ + if (!state_can_io(peer->state)) { + log_debug(peer->log, "State %s, closing immediately", + state_name(peer->state)); + return pkt_out(conn, peer); + } + + /* Back into normal mode. */ + peer_has_connected(peer); + return io_duplex(conn, + peer_read_packet(conn, peer, pkt_in), + pkt_out(conn, peer)); +} + +static struct io_plan *read_init_pkt(struct io_conn *conn, + struct peer *peer) +{ + return peer_read_packet(conn, peer, init_pkt_in); +} + +static u64 peer_commitsigs_received(struct peer *peer) +{ + return peer->their_commitsigs; +} + +static u64 peer_revocations_received(struct peer *peer) +{ + /* How many preimages we've received. */ + return -peer->their_preimages.min_index; +} + +static struct io_plan *peer_send_init(struct io_conn *conn, struct peer *peer) +{ + u64 sigs, revokes, shutdown, closing; + + 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); + + /* BOLT #2: + * + * A node reconnecting after receiving or sending an `open_channel` + * message SHOULD send a `reconnect` message on the new connection + * immediately after it has validated the `authenticate` message. */ + + /* BOLT #2: + * + * A node MUST set the `ack` field in the `reconnect` message to the + * the sum of previously-processed messages of types + * `open_commit_sig`, `update_commit`, `update_revocation`, + * `close_shutdown` and `close_signature`. */ + return peer_write_packet(conn, peer, + pkt_init(peer, sigs + revokes + + shutdown + closing), + read_init_pkt); +} + /* Crypto is on, we are live. */ static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer) { @@ -2107,10 +2187,7 @@ static struct io_plan *peer_crypto_on(struct io_conn *conn, struct peer *peer) state_event(peer, peer->local.offer_anchor, NULL); - peer_has_connected(peer); - return io_duplex(conn, - peer_read_packet(conn, peer, pkt_in), - pkt_out(conn, peer)); + return peer_send_init(conn,peer); } static void destroy_peer(struct peer *peer) @@ -2484,17 +2561,6 @@ static bool peer_first_connected(struct peer *peer, return true; } -static u64 peer_commitsigs_received(struct peer *peer) -{ - return peer->their_commitsigs; -} - -static u64 peer_revocations_received(struct peer *peer) -{ - /* How many preimages we've received. */ - return -peer->their_preimages.min_index; -} - static void htlc_destroy(struct htlc *htlc) { if (!htlc_map_del(&htlc->peer->htlcs, htlc)) @@ -2540,48 +2606,6 @@ struct htlc *peer_new_htlc(struct peer *peer, return h; } - -static struct io_plan *reconnect_pkt_in(struct io_conn *conn, struct peer *peer) -{ - if (peer->inpkt->pkt_case != PKT__PKT_RECONNECT) { - peer_received_unexpected_pkt(peer, peer->inpkt, __func__); - return pkt_out(conn, peer); - } - - /* We need to eliminate queue now. */ - clear_output_queue(peer); - - /* They might have missed the error, tell them before hanging up */ - if (state_is_error(peer->state)) { - queue_pkt_err(peer, pkt_err(peer, "In error state %s", - state_name(peer->state))); - return pkt_out(conn, peer); - } - - /* Send any packets they missed. */ - retransmit_pkts(peer, peer->inpkt->reconnect->ack); - - /* We let the conversation go this far in case they missed the - * close packets. But now we can close if we're done. */ - if (!state_can_io(peer->state)) { - log_debug(peer->log, "State %s, closing immediately", - state_name(peer->state)); - return pkt_out(conn, peer); - } - - /* Back into normal mode. */ - peer_has_connected(peer); - return io_duplex(conn, - peer_read_packet(conn, peer, pkt_in), - pkt_out(conn, peer)); -} - -static struct io_plan *read_reconnect_pkt(struct io_conn *conn, - struct peer *peer) -{ - return peer_read_packet(conn, peer, reconnect_pkt_in); -} - static struct io_plan *crypto_on_reconnect(struct io_conn *conn, struct lightningd_state *dstate, struct io_data *iod, @@ -2589,37 +2613,15 @@ static struct io_plan *crypto_on_reconnect(struct io_conn *conn, struct peer *peer, bool we_connected) { - u64 sigs, revokes, shutdown, closing; - /* Setup peer->conn and peer->io_data */ if (!peer_reconnected(peer, conn, SOCK_STREAM, IPPROTO_TCP, iod, id, we_connected)) return io_close(conn); - 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, - "Reconnecting with ack %"PRIu64" sigs + %"PRIu64" revokes" - " + %"PRIu64" shutdown + %"PRIu64" closing", - sigs, revokes, shutdown, closing); - /* BOLT #2: - * - * A node reconnecting after receiving or sending an `open_channel` - * message SHOULD send a `reconnect` message on the new connection - * immediately after it has validated the `authenticate` message. */ + /* We need to eliminate queue now. */ + clear_output_queue(peer); - /* BOLT #2: - * - * A node MUST set the `ack` field in the `reconnect` message to the - * the sum of previously-processed messages of types - * `open_commit_sig`, `update_commit`, `update_revocation`, - * `close_shutdown` and `close_signature`. */ - return peer_write_packet(conn, peer, - pkt_reconnect(peer, sigs + revokes - + shutdown + closing), - read_reconnect_pkt); + return peer_send_init(conn, peer); } static struct io_plan *crypto_on_reconnect_in(struct io_conn *conn, diff --git a/lightning.pb-c.c b/lightning.pb-c.c index d642b7d6f..ec4bd9b4d 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -308,47 +308,47 @@ void authenticate__free_unpacked assert(message->base.descriptor == &authenticate__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void reconnect__init - (Reconnect *message) +void init__init + (Init *message) { - static Reconnect init_value = RECONNECT__INIT; + static Init init_value = INIT__INIT; *message = init_value; } -size_t reconnect__get_packed_size - (const Reconnect *message) +size_t init__get_packed_size + (const Init *message) { - assert(message->base.descriptor == &reconnect__descriptor); + assert(message->base.descriptor == &init__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t reconnect__pack - (const Reconnect *message, +size_t init__pack + (const Init *message, uint8_t *out) { - assert(message->base.descriptor == &reconnect__descriptor); + assert(message->base.descriptor == &init__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t reconnect__pack_to_buffer - (const Reconnect *message, +size_t init__pack_to_buffer + (const Init *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &reconnect__descriptor); + assert(message->base.descriptor == &init__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -Reconnect * - reconnect__unpack +Init * + init__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (Reconnect *) - protobuf_c_message_unpack (&reconnect__descriptor, + return (Init *) + protobuf_c_message_unpack (&init__descriptor, allocator, len, data); } -void reconnect__free_unpacked - (Reconnect *message, +void init__free_unpacked + (Init *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &reconnect__descriptor); + assert(message->base.descriptor == &init__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void open_channel__init @@ -1644,7 +1644,7 @@ const ProtobufCMessageDescriptor authenticate__descriptor = (ProtobufCMessageInit) authenticate__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor reconnect__field_descriptors[1] = +static const ProtobufCFieldDescriptor init__field_descriptors[1] = { { "ack", @@ -1652,34 +1652,34 @@ static const ProtobufCFieldDescriptor reconnect__field_descriptors[1] = PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Reconnect, ack), + offsetof(Init, ack), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned reconnect__field_indices_by_name[] = { +static const unsigned init__field_indices_by_name[] = { 0, /* field[0] = ack */ }; -static const ProtobufCIntRange reconnect__number_ranges[1 + 1] = +static const ProtobufCIntRange init__number_ranges[1 + 1] = { { 1, 0 }, { 0, 1 } }; -const ProtobufCMessageDescriptor reconnect__descriptor = +const ProtobufCMessageDescriptor init__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "reconnect", - "Reconnect", - "Reconnect", + "init", + "Init", + "Init", "", - sizeof(Reconnect), + sizeof(Init), 1, - reconnect__field_descriptors, - reconnect__field_indices_by_name, - 1, reconnect__number_ranges, - (ProtobufCMessageInit) reconnect__init, + init__field_descriptors, + init__field_indices_by_name, + 1, init__number_ranges, + (ProtobufCMessageInit) init__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCEnumValue open_channel__anchor_offer__enum_values_by_number[2] = @@ -2840,13 +2840,13 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[15] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "reconnect", + "init", 51, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), - offsetof(Pkt, reconnect), - &reconnect__descriptor, + offsetof(Pkt, init), + &init__descriptor, NULL, 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -2857,11 +2857,11 @@ static const unsigned pkt__field_indices_by_name[] = { 10, /* field[10] = close_shutdown */ 11, /* field[11] = close_signature */ 12, /* field[12] = error */ + 14, /* field[14] = init */ 6, /* field[6] = open */ 7, /* field[7] = open_anchor */ 8, /* field[8] = open_commit_sig */ 9, /* field[9] = open_complete */ - 14, /* field[14] = reconnect */ 0, /* field[0] = update_add_htlc */ 4, /* field[4] = update_commit */ 2, /* field[2] = update_fail_htlc */ diff --git a/lightning.pb-c.h b/lightning.pb-c.h index 5eb0b9d1f..514d2ce46 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -10,7 +10,7 @@ PROTOBUF_C__BEGIN_DECLS #if PROTOBUF_C_VERSION_NUMBER < 1000000 # error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. -#elif 1001001 < PROTOBUF_C_MIN_COMPILER_VERSION +#elif 1002001 < PROTOBUF_C_MIN_COMPILER_VERSION # error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. #endif @@ -22,7 +22,7 @@ typedef struct _Locktime Locktime; typedef struct _BitcoinPubkey BitcoinPubkey; typedef struct _Funding Funding; typedef struct _Authenticate Authenticate; -typedef struct _Reconnect Reconnect; +typedef struct _Init Init; typedef struct _OpenChannel OpenChannel; typedef struct _OpenAnchor OpenAnchor; typedef struct _OpenCommitSig OpenCommitSig; @@ -123,7 +123,7 @@ struct _Locktime }; #define LOCKTIME__INIT \ { PROTOBUF_C_MESSAGE_INIT (&locktime__descriptor) \ - , LOCKTIME__LOCKTIME__NOT_SET, {} } + , LOCKTIME__LOCKTIME__NOT_SET, {0} } /* @@ -185,9 +185,9 @@ struct _Authenticate /* - * We're reconnecting, here's what we've received already. + * We're authenticated. Here's what we've received already. */ -struct _Reconnect +struct _Init { ProtobufCMessage base; /* @@ -195,8 +195,8 @@ struct _Reconnect */ uint64_t ack; }; -#define RECONNECT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&reconnect__descriptor) \ +#define INIT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&init__descriptor) \ , 0 } @@ -328,7 +328,7 @@ struct _RouteStep }; #define ROUTE_STEP__INIT \ { PROTOBUF_C_MESSAGE_INIT (&route_step__descriptor) \ - , 0, ROUTE_STEP__NEXT__NOT_SET, {} } + , 0, ROUTE_STEP__NEXT__NOT_SET, {0} } struct _Route @@ -544,7 +544,7 @@ struct _Error typedef enum { PKT__PKT__NOT_SET = 0, PKT__PKT_AUTH = 50, - PKT__PKT_RECONNECT = 51, + PKT__PKT_INIT = 51, PKT__PKT_OPEN = 20, PKT__PKT_OPEN_ANCHOR = 21, PKT__PKT_OPEN_COMMIT_SIG = 22, @@ -572,7 +572,7 @@ struct _Pkt * Start of connection */ Authenticate *auth; - Reconnect *reconnect; + Init *init; /* * Opening */ @@ -602,7 +602,7 @@ struct _Pkt }; #define PKT__INIT \ { PROTOBUF_C_MESSAGE_INIT (&pkt__descriptor) \ - , PKT__PKT__NOT_SET, {} } + , PKT__PKT__NOT_SET, {0} } /* Sha256Hash methods */ @@ -738,24 +738,24 @@ Authenticate * void authenticate__free_unpacked (Authenticate *message, ProtobufCAllocator *allocator); -/* Reconnect methods */ -void reconnect__init - (Reconnect *message); -size_t reconnect__get_packed_size - (const Reconnect *message); -size_t reconnect__pack - (const Reconnect *message, +/* Init methods */ +void init__init + (Init *message); +size_t init__get_packed_size + (const Init *message); +size_t init__pack + (const Init *message, uint8_t *out); -size_t reconnect__pack_to_buffer - (const Reconnect *message, +size_t init__pack_to_buffer + (const Init *message, ProtobufCBuffer *buffer); -Reconnect * - reconnect__unpack +Init * + init__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void reconnect__free_unpacked - (Reconnect *message, +void init__free_unpacked + (Init *message, ProtobufCAllocator *allocator); /* OpenChannel methods */ void open_channel__init @@ -1141,8 +1141,8 @@ typedef void (*Funding_Closure) typedef void (*Authenticate_Closure) (const Authenticate *message, void *closure_data); -typedef void (*Reconnect_Closure) - (const Reconnect *message, +typedef void (*Init_Closure) + (const Init *message, void *closure_data); typedef void (*OpenChannel_Closure) (const OpenChannel *message, @@ -1214,7 +1214,7 @@ extern const ProtobufCMessageDescriptor locktime__descriptor; extern const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor; extern const ProtobufCMessageDescriptor funding__descriptor; extern const ProtobufCMessageDescriptor authenticate__descriptor; -extern const ProtobufCMessageDescriptor reconnect__descriptor; +extern const ProtobufCMessageDescriptor init__descriptor; extern const ProtobufCMessageDescriptor open_channel__descriptor; extern const ProtobufCEnumDescriptor open_channel__anchor_offer__descriptor; extern const ProtobufCMessageDescriptor open_anchor__descriptor; diff --git a/lightning.proto b/lightning.proto index 05f581e11..f03706984 100644 --- a/lightning.proto +++ b/lightning.proto @@ -66,8 +66,8 @@ message authenticate { required signature session_sig = 2; }; -// We're reconnecting, here's what we've received already. -message reconnect { +// We're authenticated. Here's what we've received already. +message init { // How many update_commit and update_revocation messages already received required uint64 ack = 1; }; @@ -226,7 +226,7 @@ message pkt { oneof pkt { // Start of connection authenticate auth = 50; - reconnect reconnect = 51; + init init = 51; // Opening open_channel open = 20;