diff --git a/daemon/cryptopkt.c b/daemon/cryptopkt.c index e4d5865ff..e74931fa0 100644 --- a/daemon/cryptopkt.c +++ b/daemon/cryptopkt.c @@ -34,8 +34,10 @@ struct crypto_pkt { u8 data[]; }; -/* Temporary structure for negotiation (peer->io_data->neg) */ +/* Temporary structure for negotiation */ struct key_negotiate { + struct lightningd_state *dstate; + /* Our session secret key. */ u8 seckey[32]; @@ -43,8 +45,19 @@ struct key_negotiate { le32 keylen; u8 our_sessionpubkey[33], their_sessionpubkey[33]; + /* After DH key exchange, we create io_data to check auth. */ + struct io_data *iod; + + /* Did we expect a particular ID? */ + const struct pubkey *expected_id; + /* Callback once it's all done. */ - struct io_plan *(*cb)(struct io_conn *, struct peer *); + struct io_plan *(*cb)(struct io_conn *conn, + struct lightningd_state *dstate, + struct io_data *iod, + const struct pubkey *id, + void *arg); + void *arg; }; struct enckey { @@ -74,9 +87,6 @@ struct dir_state { u64 nonce; struct enckey enckey; - /* Non-`authenticate` packets sent/seen */ - u64 count; - /* Current packet (encrypted). */ struct crypto_pkt *cpkt; size_t pkt_len; @@ -90,7 +100,6 @@ static void setup_crypto(struct dir_state *dir, dir->enckey = enckey_from_secret(shared_secret, serial_pubkey); - dir->count = 0; dir->cpkt = NULL; } @@ -103,9 +112,9 @@ struct io_data { /* Callback once packet decrypted. */ struct io_plan *(*cb)(struct io_conn *, struct peer *); - - /* For negotiation phase. */ - struct key_negotiate *neg; + + /* Once peer is assigned, this is set. */ + struct peer *peer; }; static void *proto_tal_alloc(void *allocator_data, size_t size) @@ -175,45 +184,50 @@ static bool decrypt_in_place(void *data, size_t len, return false; } -static Pkt *decrypt_pkt(struct peer *peer, struct crypto_pkt *cpkt, - size_t data_len) +static Pkt *decrypt_body(const tal_t *ctx, struct io_data *iod, struct log *log, + struct crypto_pkt *cpkt, size_t data_len) { - struct io_data *iod = peer->io_data; struct ProtobufCAllocator prototal; Pkt *ret; if (!decrypt_in_place(cpkt->data, data_len, &iod->in.nonce, &iod->in.enckey)) { - log_unusual(peer->log, "Body decryption failed"); + log_unusual(log, "Body decryption failed"); return NULL; } /* De-protobuf it. */ prototal.alloc = proto_tal_alloc; prototal.free = proto_tal_free; - prototal.allocator_data = tal(iod, char); + prototal.allocator_data = tal(ctx, char); ret = pkt__unpack(&prototal, data_len, cpkt->data); if (!ret) { - log_unusual(peer->log, "Packet failed to unpack!"); + log_unusual(log, "Packet failed to unpack!"); tal_free(prototal.allocator_data); - } else + } else { /* Make sure packet owns contents */ + tal_steal(ctx, ret); tal_steal(ret, prototal.allocator_data); + + log_debug(log, "Received packet LEN=%u, type=%s", + le32_to_cpu(iod->hdr_in.length), + ret->pkt_case == PKT__PKT_AUTH ? "PKT_AUTH" + : pkt_name(ret->pkt_case)); + } return ret; } -static struct crypto_pkt *encrypt_pkt(struct peer *peer, const Pkt *pkt, +static struct crypto_pkt *encrypt_pkt(struct io_data *iod, const Pkt *pkt, size_t *totlen) { struct crypto_pkt *cpkt; size_t len; - struct io_data *iod = peer->io_data; len = pkt__get_packed_size(pkt); *totlen = sizeof(*cpkt) + len + crypto_aead_chacha20poly1305_ABYTES; - cpkt = (struct crypto_pkt *)tal_arr(peer, char, *totlen); + cpkt = (struct crypto_pkt *)tal_arr(iod, char, *totlen); cpkt->length = cpu_to_le32(len); /* Encrypt header. */ @@ -227,59 +241,58 @@ static struct crypto_pkt *encrypt_pkt(struct peer *peer, const Pkt *pkt, return cpkt; } -static struct io_plan *decrypt_body(struct io_conn *conn, struct peer *peer) +static struct io_plan *recv_body(struct io_conn *conn, struct peer *peer) { struct io_data *iod = peer->io_data; /* We have full packet. */ - peer->inpkt = decrypt_pkt(peer, iod->in.cpkt, - le32_to_cpu(iod->hdr_in.length)); + peer->inpkt = decrypt_body(iod, iod, peer->log, iod->in.cpkt, + le32_to_cpu(iod->hdr_in.length)); if (!peer->inpkt) return io_close(conn); - /* Increment count if it wasn't an authenticate packet */ - if (peer->inpkt->pkt_case != PKT__PKT_AUTH) - iod->in.count++; - - log_debug(peer->log, "Received packet LEN=%u, type=%s", - le32_to_cpu(iod->hdr_in.length), - peer->inpkt->pkt_case == PKT__PKT_AUTH ? "PKT_AUTH" - : pkt_name(peer->inpkt->pkt_case)); - return iod->cb(conn, peer); } -static struct io_plan *decrypt_header(struct io_conn *conn, struct peer *peer) +static bool decrypt_header(struct log *log, struct io_data *iod, + size_t *body_len) { - struct io_data *iod = peer->io_data; - size_t body_len; - /* We have length: Check it. */ if (!decrypt_in_place(&iod->hdr_in.length, sizeof(iod->hdr_in.length), &iod->in.nonce, &iod->in.enckey)) { - log_unusual(peer->log, "Header decryption failed"); - return io_close(conn); + log_unusual(log, "Header decryption failed"); + return false; } - log_debug(peer->log, "Decrypted header len %u", + log_debug(log, "Decrypted header len %u", le32_to_cpu(iod->hdr_in.length)); /* BOLT #1: `length` MUST NOT exceed 1MB (1048576 bytes). */ if (le32_to_cpu(iod->hdr_in.length) > MAX_PKT_LEN) { - log_unusual(peer->log, + log_unusual(log, "Packet overlength: %"PRIu64, le64_to_cpu(iod->hdr_in.length)); - return io_close(conn); + return false; } /* Allocate room for body, copy header. */ - body_len = le32_to_cpu(iod->hdr_in.length) + *body_len = le32_to_cpu(iod->hdr_in.length) + crypto_aead_chacha20poly1305_ABYTES; iod->in.cpkt = (struct crypto_pkt *) - tal_arr(peer, char, sizeof(iod->hdr_in) + body_len); + tal_arr(iod, char, sizeof(iod->hdr_in) + *body_len); *iod->in.cpkt = iod->hdr_in; + return true; +} - return io_read(conn, iod->in.cpkt->data, body_len, decrypt_body, peer); +static struct io_plan *recv_header(struct io_conn *conn, struct peer *peer) +{ + struct io_data *iod = peer->io_data; + size_t body_len; + + if (!decrypt_header(peer->log, iod, &body_len)) + return io_close(conn); + + return io_read(conn, iod->in.cpkt->data, body_len, recv_body, peer); } struct io_plan *peer_read_packet(struct io_conn *conn, @@ -291,7 +304,7 @@ struct io_plan *peer_read_packet(struct io_conn *conn, iod->cb = cb; return io_read(conn, &iod->hdr_in, sizeof(iod->hdr_in), - decrypt_header, peer); + recv_header, peer); } /* Caller must free data! */ @@ -308,55 +321,51 @@ struct io_plan *peer_write_packet(struct io_conn *conn, * via io_write */ tal_free(iod->out.cpkt); - iod->out.cpkt = encrypt_pkt(peer, pkt, &totlen); - - /* We don't add to count for authenticate case. */ - if (pkt->pkt_case != PKT__PKT_AUTH) - peer->io_data->out.count++; + iod->out.cpkt = encrypt_pkt(iod, pkt, &totlen); return io_write(conn, iod->out.cpkt, totlen, next, peer); } -static void *pkt_unwrap(struct peer *peer, Pkt__PktCase which) +static void *pkt_unwrap(Pkt *inpkt, struct log *log, Pkt__PktCase which) { size_t i; const ProtobufCMessage *base; - if (peer->inpkt->pkt_case != which) { - log_unusual(peer->log, "Expected %u, got %u", - which, peer->inpkt->pkt_case); + if (inpkt->pkt_case != which) { + log_unusual(log, "Expected %u, got %u", + which, inpkt->pkt_case); return NULL; } /* It's a union, and each member starts with base. Pick one */ - base = &peer->inpkt->error->base; + base = &inpkt->error->base; /* Look for unknown fields. Remember, "It's OK to be odd!" */ for (i = 0; i < base->n_unknown_fields; i++) { - log_debug(peer->log, "Unknown field in %u: %u", + log_debug(log, "Unknown field in %u: %u", which, base->unknown_fields[i].tag); /* Odd is OK */ if (base->unknown_fields[i].tag & 1) continue; - log_unusual(peer->log, "Unknown field %u in %u", + log_unusual(log, "Unknown field %u in %u", base->unknown_fields[i].tag, which); return NULL; } - return peer->inpkt->error; + return inpkt->error; } -static struct io_plan *check_proof(struct io_conn *conn, struct peer *peer) +static bool check_proof(struct key_negotiate *neg, struct log *log, + Pkt *inpkt, + const struct pubkey *expected_id, + struct pubkey *id) { - struct key_negotiate *neg = peer->io_data->neg; struct sha256_double sha; struct signature sig; - struct io_plan *(*cb)(struct io_conn *, struct peer *); Authenticate *auth; - struct pubkey id; - auth = pkt_unwrap(peer, PKT__PKT_AUTH); + auth = pkt_unwrap(inpkt, log, PKT__PKT_AUTH); if (!auth) - return io_close(conn); + return false; /* BOLT #1: * @@ -364,16 +373,14 @@ static struct io_plan *check_proof(struct io_conn *conn, struct peer *peer) * * 1. `node_id` is the expected value for the sending node. */ - if (!proto_to_pubkey(peer->dstate->secpctx, auth->node_id, &id)) { - log_unusual(peer->log, "Invalid auth id"); - return io_close(conn); + if (!proto_to_pubkey(neg->dstate->secpctx, auth->node_id, id)) { + log_unusual(log, "Invalid auth id"); + return false; } - if (!peer->id) - peer->id = tal_dup(peer, struct pubkey, &id); - else if (!structeq(&id, peer->id)) { - log_unusual(peer->log, "Incorrect auth id"); - return io_close(conn); + if (expected_id && !structeq(id, expected_id)) { + log_unusual(log, "Incorrect auth id"); + return false; } /* BOLT #1: @@ -382,10 +389,10 @@ static struct io_plan *check_proof(struct io_conn *conn, struct peer *peer) * a 32-byte big endian R value, followed by a 32-byte big * endian S value. */ - if (!proto_to_signature(peer->dstate->secpctx, auth->session_sig, + if (!proto_to_signature(neg->dstate->secpctx, auth->session_sig, &sig)) { - log_unusual(peer->log, "Invalid auth signature"); - return io_close(conn); + log_unusual(log, "Invalid auth signature"); + return false; } @@ -398,43 +405,54 @@ static struct io_plan *check_proof(struct io_conn *conn, struct peer *peer) sha256_double(&sha, neg->our_sessionpubkey, sizeof(neg->our_sessionpubkey)); - if (!check_signed_hash(peer->dstate->secpctx, &sha, &sig, peer->id)) { - log_unusual(peer->log, "Bad auth signature"); - return io_close(conn); + if (!check_signed_hash(neg->dstate->secpctx, &sha, &sig, id)) { + log_unusual(log, "Bad auth signature"); + return false; } - /* Auth messages don't add to count. */ - assert(peer->io_data->in.count == 0); - - /* BOLT #1: - * - * The receiver MUST NOT examine the `ack` value until after the - * authentication fields have been successfully validated. - * - * The `ack` field MUST BE set to the number of `update_commit`, - * `open_commit_sig` and `update_revocation` messages received and - * processed. - */ - /* FIXME: Handle reconnects. */ - if (auth->ack != 0) { - log_unusual(peer->log, "FIXME: non-zero ack %"PRIu64, auth->ack); - return io_close(conn); - } - - tal_free(auth); - - /* All complete, return to caller. */ - cb = neg->cb; - peer->io_data->neg = tal_free(neg); - return cb(conn, peer); + return true; } -static struct io_plan *receive_proof(struct io_conn *conn, struct peer *peer) +static struct io_plan *recv_body_negotiate(struct io_conn *conn, + struct key_negotiate *neg) { - /* The sent auth message doesn't add to count. */ - assert(peer->io_data->out.count == 0); + struct io_data *iod = neg->iod; + struct io_plan *plan; + Pkt *pkt; + struct pubkey id; - return peer_read_packet(conn, peer, check_proof); + /* We have full packet. */ + pkt = decrypt_body(neg, iod, neg->dstate->base_log, iod->in.cpkt, + le32_to_cpu(iod->hdr_in.length)); + if (!pkt) + return io_close(conn); + + if (!check_proof(neg, neg->dstate->base_log, pkt, neg->expected_id, &id)) + return io_close(conn); + + plan = neg->cb(conn, neg->dstate, neg->iod, &id, neg->arg); + tal_free(neg); + return plan; +} + +static struct io_plan *recv_header_negotiate(struct io_conn *conn, + struct key_negotiate *neg) +{ + size_t body_len; + struct io_data *iod = neg->iod; + + if (!decrypt_header(neg->dstate->base_log, iod, &body_len)) + return io_close(conn); + + return io_read(conn, iod->in.cpkt->data, body_len, recv_body_negotiate, + neg); +} + +static struct io_plan *receive_proof(struct io_conn *conn, + struct key_negotiate *neg) +{ + return io_read(conn, &neg->iod->hdr_in, sizeof(neg->iod->hdr_in), + recv_header_negotiate, neg); } /* Steals w onto the returned Pkt */ @@ -460,35 +478,35 @@ static Pkt *authenticate_pkt(const tal_t *ctx, return pkt_wrap(ctx, auth, PKT__PKT_AUTH); } -static struct io_plan *keys_exchanged(struct io_conn *conn, struct peer *peer) +static struct io_plan *keys_exchanged(struct io_conn *conn, + struct key_negotiate *neg) { u8 shared_secret[32]; struct pubkey sessionkey; struct signature sig; - struct key_negotiate *neg = peer->io_data->neg; Pkt *auth; + size_t totlen; - if (!pubkey_from_der(peer->dstate->secpctx, + if (!pubkey_from_der(neg->dstate->secpctx, neg->their_sessionpubkey, sizeof(neg->their_sessionpubkey), &sessionkey)) { /* FIXME: Dump key in this case. */ - log_unusual(peer->log, "Bad sessionkey"); + log_unusual(neg->dstate->base_log, "Bad sessionkey"); return io_close(conn); } /* Derive shared secret. */ - if (!secp256k1_ecdh(peer->dstate->secpctx, shared_secret, + if (!secp256k1_ecdh(neg->dstate->secpctx, shared_secret, &sessionkey.pubkey, neg->seckey)) { - log_unusual(peer->log, "Bad ECDH"); + log_unusual(neg->dstate->base_log, "Bad ECDH"); return io_close(conn); } /* Each side combines with their OWN session key to SENDING crypto. */ - setup_crypto(&peer->io_data->in, shared_secret, - neg->their_sessionpubkey); - setup_crypto(&peer->io_data->out, shared_secret, - neg->our_sessionpubkey); + neg->iod = tal(neg, struct io_data); + setup_crypto(&neg->iod->in, shared_secret, neg->their_sessionpubkey); + setup_crypto(&neg->iod->out, shared_secret, neg->our_sessionpubkey); /* BOLT #1: * @@ -496,19 +514,20 @@ static struct io_plan *keys_exchanged(struct io_conn *conn, struct peer *peer) * own sessionpubkey, using the secret key corresponding to the * sender's `node_id`. */ - privkey_sign(peer, neg->their_sessionpubkey, + privkey_sign(neg->dstate, neg->their_sessionpubkey, sizeof(neg->their_sessionpubkey), &sig); - /* FIXME: Free auth afterwards. */ - auth = authenticate_pkt(peer, peer->dstate->secpctx, - &peer->dstate->id, &sig); - return peer_write_packet(conn, peer, auth, receive_proof); + auth = authenticate_pkt(neg, neg->dstate->secpctx, + &neg->dstate->id, &sig); + + neg->iod->out.cpkt = encrypt_pkt(neg->iod, auth, &totlen); + return io_write(conn, neg->iod->out.cpkt, totlen, receive_proof, neg); } /* Read and ignore any extra bytes... */ -static struct io_plan *discard_extra(struct io_conn *conn, struct peer *peer) +static struct io_plan *discard_extra(struct io_conn *conn, + struct key_negotiate *neg) { - struct key_negotiate *neg = peer->io_data->neg; size_t len = le32_to_cpu(neg->keylen); /* BOLT#1: Additional fields MAY be added, and MUST be @@ -519,48 +538,48 @@ static struct io_plan *discard_extra(struct io_conn *conn, struct peer *peer) len -= sizeof(neg->their_sessionpubkey); discard = tal_arr(neg, char, len); - log_unusual(peer->log, "Ignoring %zu extra handshake bytes", + log_unusual(neg->dstate->base_log, + "Ignoring %zu extra handshake bytes", len); - return io_read(conn, discard, len, keys_exchanged, peer); + return io_read(conn, discard, len, keys_exchanged, neg); } - return keys_exchanged(conn, peer); + return keys_exchanged(conn, neg); } static struct io_plan *session_key_receive(struct io_conn *conn, - struct peer *peer) + struct key_negotiate *neg) { - struct key_negotiate *neg = peer->io_data->neg; - /* BOLT#1: The `length` field is the length after the field itself, and MUST be 33 or greater. */ if (le32_to_cpu(neg->keylen) < sizeof(neg->their_sessionpubkey)) { - log_unusual(peer->log, "short session key length %u", + log_unusual(neg->dstate->base_log, "short session key length %u", le32_to_cpu(neg->keylen)); return io_close(conn); } /* BOLT#1: `length` MUST NOT exceed 1MB (1048576 bytes). */ if (le32_to_cpu(neg->keylen) > 1048576) { - log_unusual(peer->log, "Oversize session key length %u", + log_unusual(neg->dstate->base_log, + "Oversize session key length %u", le32_to_cpu(neg->keylen)); return io_close(conn); } - log_debug(peer->log, "Session key length %u", le32_to_cpu(neg->keylen)); + log_debug(neg->dstate->base_log, + "Session key length %u", le32_to_cpu(neg->keylen)); /* Now read their key. */ return io_read(conn, neg->their_sessionpubkey, - sizeof(neg->their_sessionpubkey), discard_extra, peer); + sizeof(neg->their_sessionpubkey), discard_extra, neg); } static struct io_plan *session_key_len_receive(struct io_conn *conn, - struct peer *peer) + struct key_negotiate *neg) { - struct key_negotiate *neg = peer->io_data->neg; /* Read the amount of data they will send.. */ return io_read(conn, &neg->keylen, sizeof(neg->keylen), - session_key_receive, peer); + session_key_receive, neg); } static void gen_sessionkey(secp256k1_context *ctx, @@ -572,18 +591,23 @@ static void gen_sessionkey(secp256k1_context *ctx, } while (!secp256k1_ec_pubkey_create(ctx, pubkey, seckey)); } -static struct io_plan *write_sessionkey(struct io_conn *conn, struct peer *peer) +static struct io_plan *write_sessionkey(struct io_conn *conn, + struct key_negotiate *neg) { - struct key_negotiate *neg = peer->io_data->neg; - return io_write(conn, neg->our_sessionpubkey, sizeof(neg->our_sessionpubkey), - session_key_len_receive, peer); + session_key_len_receive, neg); } -struct io_plan *peer_crypto_setup(struct io_conn *conn, struct peer *peer, - struct io_plan *(*cb)(struct io_conn *, - struct peer *)) +struct io_plan *peer_crypto_setup_(struct io_conn *conn, + struct lightningd_state *dstate, + const struct pubkey *id, + struct io_plan *(*cb)(struct io_conn *conn, + struct lightningd_state *dstate, + struct io_data *iod, + const struct pubkey *id, + void *arg), + void *arg) { size_t outputlen; secp256k1_pubkey sessionkey; @@ -596,21 +620,23 @@ struct io_plan *peer_crypto_setup(struct io_conn *conn, struct peer *peer, * is appended) */ BUILD_ASSERT(sizeof(struct crypto_pkt) == 20); - peer->io_data = tal(peer, struct io_data); - /* We store negotiation state here. */ - neg = peer->io_data->neg = tal(peer->io_data, struct key_negotiate); + neg = tal(dstate, struct key_negotiate); neg->cb = cb; + neg->arg = arg; + neg->dstate = dstate; + neg->expected_id = id; + /* FIXME: Create log buffer for neg, use that then pass to peer. */ - gen_sessionkey(peer->dstate->secpctx, neg->seckey, &sessionkey); + gen_sessionkey(dstate->secpctx, neg->seckey, &sessionkey); outputlen = sizeof(neg->our_sessionpubkey); - secp256k1_ec_pubkey_serialize(peer->dstate->secpctx, + secp256k1_ec_pubkey_serialize(dstate->secpctx, neg->our_sessionpubkey, &outputlen, &sessionkey, SECP256K1_EC_COMPRESSED); assert(outputlen == sizeof(neg->our_sessionpubkey)); neg->keylen = cpu_to_le32(sizeof(neg->our_sessionpubkey)); return io_write(conn, &neg->keylen, sizeof(neg->keylen), - write_sessionkey, peer); + write_sessionkey, neg); } diff --git a/daemon/cryptopkt.h b/daemon/cryptopkt.h index 39b19f8d0..fbf16b1a4 100644 --- a/daemon/cryptopkt.h +++ b/daemon/cryptopkt.h @@ -5,12 +5,30 @@ #include #include +struct io_data; +struct json_connecting; +struct lightningd_state; struct peer; -struct io_plan *peer_crypto_setup(struct io_conn *conn, - struct peer *peer, - struct io_plan *(*cb)(struct io_conn *, - struct peer *)); +struct io_plan *peer_crypto_setup_(struct io_conn *conn, + struct lightningd_state *dstate, + const struct pubkey *id, + struct io_plan *(*cb)(struct io_conn *conn, + struct lightningd_state *dstate, + struct io_data *iod, + const struct pubkey *id, + void *arg), + void *arg); + +#define peer_crypto_setup(conn, dstate, id, cb, arg) \ + peer_crypto_setup_((conn), (dstate), (id), \ + typesafe_cb_preargs(struct io_plan *, void *, \ + (cb), (arg), \ + struct io_conn *, \ + struct lightningd_state *, \ + struct io_data *, \ + const struct pubkey *), \ + (arg)) /* Reads packet into peer->inpkt/peer->inpkt_len */ struct io_plan *peer_read_packet(struct io_conn *conn, diff --git a/daemon/peer.c b/daemon/peer.c index 4b7486ab3..e362a8755 100644 --- a/daemon/peer.c +++ b/daemon/peer.c @@ -886,6 +886,7 @@ static Pkt *handle_pkt_commit(struct peer *peer, const Pkt *pkt) peer->local.commit = ci; peer_get_revocation_hash(peer, ci->commit_num + 1, &peer->local.next_revocation_hash); + peer->their_commitsigs++; /* Now, send the revocation. */ ci = peer->local.commit->prev; @@ -1798,6 +1799,7 @@ static struct peer *new_peer(struct lightningd_state *dstate, list_head_init(&peer->pay_commands); list_head_init(&peer->their_commits); peer->anchor.ok_depth = -1; + peer->their_commitsigs = 0; peer->cur_commit.watch = NULL; peer->closing.their_sig = NULL; peer->closing.our_script = NULL; @@ -1849,6 +1851,20 @@ static struct peer *new_peer(struct lightningd_state *dstate, return peer; } +/* Unused for the moment. */ +#if 0 +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; +} +#endif + static void htlc_destroy(struct htlc *htlc) { if (!htlc_map_del(&htlc->peer->htlcs, htlc)) @@ -1894,9 +1910,11 @@ struct htlc *peer_new_htlc(struct peer *peer, return h; } -static struct io_plan *peer_connected_out(struct io_conn *conn, - struct lightningd_state *dstate, - struct json_connecting *connect) +static struct io_plan *crypto_on_out(struct io_conn *conn, + struct lightningd_state *dstate, + struct io_data *iod, + const struct pubkey *id, + struct json_connecting *connect) { /* Initiator currently funds channel */ struct peer *peer = new_peer(dstate, conn, SOCK_STREAM, IPPROTO_TCP, @@ -1906,25 +1924,48 @@ static struct io_plan *peer_connected_out(struct io_conn *conn, connect->name, connect->port); return io_close(conn); } - log_info(peer->log, "Connected out to %s:%s", - connect->name, connect->port); - + peer->io_data = tal_steal(peer, iod); + peer->id = tal_dup(peer, struct pubkey, id); peer->anchor.input = tal_steal(peer, connect->input); command_success(connect->cmd, null_response(connect)); - return peer_crypto_setup(conn, peer, peer_crypto_on); + return peer_crypto_on(conn, peer); } -static struct io_plan *peer_connected_in(struct io_conn *conn, - struct lightningd_state *dstate) +static struct io_plan *peer_connected_out(struct io_conn *conn, + struct lightningd_state *dstate, + struct json_connecting *connect) { + log_debug(dstate->base_log, "Connected out to %s:%s", + connect->name, connect->port); + + return peer_crypto_setup(conn, dstate, NULL, crypto_on_out, connect); +} + +static struct io_plan *crypto_on_in(struct io_conn *conn, + struct lightningd_state *dstate, + struct io_data *iod, + const struct pubkey *id, + void *unused) +{ + /* Initiator currently funds channel */ struct peer *peer = new_peer(dstate, conn, SOCK_STREAM, IPPROTO_TCP, CMD_OPEN_WITHOUT_ANCHOR, "in"); if (!peer) return io_close(conn); - log_info(peer->log, "Peer connected in"); - return peer_crypto_setup(conn, peer, peer_crypto_on); + peer->io_data = tal_steal(peer, iod); + peer->id = tal_dup(peer, struct pubkey, id); + return peer_crypto_on(conn, peer); +} + +static struct io_plan *peer_connected_in(struct io_conn *conn, + struct lightningd_state *dstate) +{ + /* FIXME: log incoming address. */ + log_debug(dstate->base_log, "Connected in"); + + return peer_crypto_setup(conn, dstate, NULL, crypto_on_in, NULL); } static int make_listen_fd(struct lightningd_state *dstate, diff --git a/daemon/peer.h b/daemon/peer.h index 1b3404788..541870a22 100644 --- a/daemon/peer.h +++ b/daemon/peer.h @@ -151,6 +151,9 @@ struct peer { /* Their commitments we have signed (which could appear on chain). */ struct list_head their_commits; + + /* Number of commitment signatures we've received. */ + u64 their_commitsigs; /* Anchor tx output */ struct { diff --git a/daemon/secrets.c b/daemon/secrets.c index 92755652d..81a3ec862 100644 --- a/daemon/secrets.c +++ b/daemon/secrets.c @@ -24,14 +24,13 @@ struct secret { struct privkey privkey; }; -void privkey_sign(struct peer *peer, const void *src, size_t len, +void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len, struct signature *sig) { struct sha256_double h; sha256_double(&h, memcheck(src, len), len); - sign_hash(peer->dstate->secpctx, - &peer->dstate->secret->privkey, &h, sig); + sign_hash(dstate->secpctx, &dstate->secret->privkey, &h, sig); } struct peer_secrets { diff --git a/daemon/secrets.h b/daemon/secrets.h index 96d41025c..b1fdf6869 100644 --- a/daemon/secrets.h +++ b/daemon/secrets.h @@ -9,7 +9,7 @@ struct lightningd_state; struct signature; struct sha256; -void privkey_sign(struct peer *peer, const void *src, size_t len, +void privkey_sign(struct lightningd_state *dstate, const void *src, size_t len, struct signature *sig); void peer_sign_theircommit(const struct peer *peer, diff --git a/lightning.pb-c.c b/lightning.pb-c.c index d1a3ead3c..dc81d308b 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -308,6 +308,49 @@ void authenticate__free_unpacked assert(message->base.descriptor == &authenticate__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void reconnect__init + (Reconnect *message) +{ + static Reconnect init_value = RECONNECT__INIT; + *message = init_value; +} +size_t reconnect__get_packed_size + (const Reconnect *message) +{ + assert(message->base.descriptor == &reconnect__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t reconnect__pack + (const Reconnect *message, + uint8_t *out) +{ + assert(message->base.descriptor == &reconnect__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t reconnect__pack_to_buffer + (const Reconnect *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &reconnect__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Reconnect * + reconnect__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Reconnect *) + protobuf_c_message_unpack (&reconnect__descriptor, + allocator, len, data); +} +void reconnect__free_unpacked + (Reconnect *message, + ProtobufCAllocator *allocator) +{ + assert(message->base.descriptor == &reconnect__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void open_channel__init (OpenChannel *message) { @@ -1464,8 +1507,7 @@ const ProtobufCMessageDescriptor funding__descriptor = (ProtobufCMessageInit) funding__init, NULL,NULL,NULL /* reserved[123] */ }; -static const uint64_t authenticate__ack__default_value = 0ull; -static const ProtobufCFieldDescriptor authenticate__field_descriptors[3] = +static const ProtobufCFieldDescriptor authenticate__field_descriptors[2] = { { "node_id", @@ -1491,28 +1533,15 @@ static const ProtobufCFieldDescriptor authenticate__field_descriptors[3] = 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, - { - "ack", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_UINT64, - offsetof(Authenticate, has_ack), - offsetof(Authenticate, ack), - NULL, - &authenticate__ack__default_value, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, }; static const unsigned authenticate__field_indices_by_name[] = { - 2, /* field[2] = ack */ 0, /* field[0] = node_id */ 1, /* field[1] = session_sig */ }; static const ProtobufCIntRange authenticate__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 3 } + { 0, 2 } }; const ProtobufCMessageDescriptor authenticate__descriptor = { @@ -1522,13 +1551,51 @@ const ProtobufCMessageDescriptor authenticate__descriptor = "Authenticate", "", sizeof(Authenticate), - 3, + 2, authenticate__field_descriptors, authenticate__field_indices_by_name, 1, authenticate__number_ranges, (ProtobufCMessageInit) authenticate__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor reconnect__field_descriptors[1] = +{ + { + "ack", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Reconnect, ack), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned reconnect__field_indices_by_name[] = { + 0, /* field[0] = ack */ +}; +static const ProtobufCIntRange reconnect__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor reconnect__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "reconnect", + "Reconnect", + "Reconnect", + "", + sizeof(Reconnect), + 1, + reconnect__field_descriptors, + reconnect__field_indices_by_name, + 1, reconnect__number_ranges, + (ProtobufCMessageInit) reconnect__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCEnumValue open_channel__anchor_offer__enum_values_by_number[2] = { { "WILL_CREATE_ANCHOR", "OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR", 1 }, @@ -2414,7 +2481,7 @@ const ProtobufCMessageDescriptor error__descriptor = (ProtobufCMessageInit) error__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor pkt__field_descriptors[13] = +static const ProtobufCFieldDescriptor pkt__field_descriptors[14] = { { "update_add_htlc", @@ -2572,6 +2639,18 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[13] = 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "reconnect", + 51, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Pkt, pkt_case), + offsetof(Pkt, reconnect), + &reconnect__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned pkt__field_indices_by_name[] = { 12, /* field[12] = auth */ @@ -2582,6 +2661,7 @@ static const unsigned pkt__field_indices_by_name[] = { 6, /* field[6] = open_anchor */ 7, /* field[7] = open_commit_sig */ 8, /* field[8] = open_complete */ + 13, /* field[13] = reconnect */ 0, /* field[0] = update_add_htlc */ 3, /* field[3] = update_commit */ 2, /* field[2] = update_fail_htlc */ @@ -2595,7 +2675,7 @@ static const ProtobufCIntRange pkt__number_ranges[5 + 1] = { 30, 9 }, { 40, 11 }, { 50, 12 }, - { 0, 13 } + { 0, 14 } }; const ProtobufCMessageDescriptor pkt__descriptor = { @@ -2605,7 +2685,7 @@ const ProtobufCMessageDescriptor pkt__descriptor = "Pkt", "", sizeof(Pkt), - 13, + 14, pkt__field_descriptors, pkt__field_indices_by_name, 5, pkt__number_ranges, diff --git a/lightning.pb-c.h b/lightning.pb-c.h index 7fdf9aa40..ebfc8251e 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -22,6 +22,7 @@ typedef struct _Locktime Locktime; typedef struct _BitcoinPubkey BitcoinPubkey; typedef struct _Funding Funding; typedef struct _Authenticate Authenticate; +typedef struct _Reconnect Reconnect; typedef struct _OpenChannel OpenChannel; typedef struct _OpenAnchor OpenAnchor; typedef struct _OpenCommitSig OpenCommitSig; @@ -175,15 +176,26 @@ struct _Authenticate * Signature of your session key. * */ Signature *session_sig; - /* - * How many update_commit and update_revocation messages already received - */ - protobuf_c_boolean has_ack; - uint64_t ack; }; #define AUTHENTICATE__INIT \ { PROTOBUF_C_MESSAGE_INIT (&authenticate__descriptor) \ - , NULL, NULL, 0,0ull } + , NULL, NULL } + + +/* + * We're reconnecting, here's what we've received already. + */ +struct _Reconnect +{ + ProtobufCMessage base; + /* + * How many update_commit and update_revocation messages already received + */ + uint64_t ack; +}; +#define RECONNECT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&reconnect__descriptor) \ + , 0 } /* @@ -505,6 +517,7 @@ struct _Error typedef enum { PKT__PKT__NOT_SET = 0, PKT__PKT_AUTH = 50, + PKT__PKT_RECONNECT = 51, PKT__PKT_OPEN = 20, PKT__PKT_OPEN_ANCHOR = 21, PKT__PKT_OPEN_COMMIT_SIG = 22, @@ -531,6 +544,7 @@ struct _Pkt * Start of connection */ Authenticate *auth; + Reconnect *reconnect; /* * Opening */ @@ -695,6 +709,25 @@ 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, + uint8_t *out); +size_t reconnect__pack_to_buffer + (const Reconnect *message, + ProtobufCBuffer *buffer); +Reconnect * + reconnect__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void reconnect__free_unpacked + (Reconnect *message, + ProtobufCAllocator *allocator); /* OpenChannel methods */ void open_channel__init (OpenChannel *message); @@ -1041,6 +1074,9 @@ typedef void (*Funding_Closure) typedef void (*Authenticate_Closure) (const Authenticate *message, void *closure_data); +typedef void (*Reconnect_Closure) + (const Reconnect *message, + void *closure_data); typedef void (*OpenChannel_Closure) (const OpenChannel *message, void *closure_data); @@ -1105,6 +1141,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 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 ce951414e..856da0b7f 100644 --- a/lightning.proto +++ b/lightning.proto @@ -64,8 +64,12 @@ message authenticate { required bitcoin_pubkey node_id = 1; // Signature of your session key. */ required signature session_sig = 2; +}; + +// We're reconnecting, here's what we've received already. +message reconnect { // How many update_commit and update_revocation messages already received - optional uint64 ack = 3 [ default = 0 ]; + required uint64 ack = 1; }; // Set channel params. @@ -211,6 +215,8 @@ message pkt { oneof pkt { // Start of connection authenticate auth = 50; + reconnect reconnect = 51; + // Opening open_channel open = 20; open_anchor open_anchor = 21; diff --git a/state.c b/state.c index 17d46826c..05f6cc8ac 100644 --- a/state.c +++ b/state.c @@ -188,6 +188,7 @@ enum state state(struct peer *peer, peer_open_complete(peer, err->error->problem); goto err_breakdown; } + peer->their_commitsigs++; queue_tx_broadcast(broadcast, bitcoin_anchor(peer)); peer_watch_anchor(peer, peer->local.mindepth,