mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
protocol: use separate ack packet.
It's a data-leak to send ack before we have verified identity of peer. Plus, we can't send it until we know which peer it is, anyway! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
5c9dfd5206
commit
7709eb9b4a
@ -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;
|
||||
}
|
||||
|
||||
@ -104,8 +113,8 @@ 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,
|
||||
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);
|
||||
}
|
||||
|
@ -5,12 +5,30 @@
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/typesafe_cb/typesafe_cb.h>
|
||||
|
||||
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,
|
||||
|
@ -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,8 +1910,10 @@ struct htlc *peer_new_htlc(struct peer *peer,
|
||||
return h;
|
||||
}
|
||||
|
||||
static struct io_plan *peer_connected_out(struct io_conn *conn,
|
||||
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 */
|
||||
@ -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,
|
||||
|
@ -152,6 +152,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 {
|
||||
struct sha256_double txid;
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
120
lightning.pb-c.c
120
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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user