commit 49d9ca46a254a3ede2cd917aae2c499378873a11
parent c161f4d25ea5e484bc06b7f2381da7203e7945c3
Author: William Casarin <jb55@jb55.com>
Date: Mon, 17 Jan 2022 20:44:28 -0800
ping/pong working!
Diffstat:
M | Makefile | | | 2 | +- |
M | README | | | 2 | +- |
A | bigsize.c | | | 118 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | bigsize.h | | | 31 | +++++++++++++++++++++++++++++++ |
M | crypto.c | | | 6 | +++--- |
M | crypto.h | | | 7 | +++++++ |
M | cursor.h | | | 7 | +------ |
M | endian.h | | | 15 | +++++++++++++++ |
M | lnsocket.c | | | 226 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
M | lnsocket.h | | | 65 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
M | lnsocket_internal.h | | | 1 | + |
M | test.c | | | 80 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
12 files changed, 524 insertions(+), 36 deletions(-)
diff --git a/Makefile b/Makefile
@@ -5,7 +5,7 @@ LDFLAGS=
SUBMODULES=deps/libsodium deps/secp256k1
ARS=deps/secp256k1/.libs/libsecp256k1.a deps/libsodium/src/libsodium/.libs/libsodium.a
-OBJS=sha256.o hkdf.o hmac.o sha512.o lnsocket.o error.o handshake.o crypto.o
+OBJS=sha256.o hkdf.o hmac.o sha512.o lnsocket.o error.o handshake.o crypto.o bigsize.o
DEPS=$(OBJS) config.h
all: test
diff --git a/README b/README
@@ -16,7 +16,7 @@ make
Contributing
------------
-Send patches to me at jb55@jb55.com:
+Send patches to jb55@jb55.com:
$ git config format.subjectPrefix 'PATCH lnsocket'
$ git config sendemail.to 'William Casarin <jb55@jb55.com>'
diff --git a/bigsize.c b/bigsize.c
@@ -0,0 +1,118 @@
+
+#include <assert.h>
+#include "config.h"
+#include "bigsize.h"
+
+#ifndef SUPERVERBOSE
+#define SUPERVERBOSE(...)
+#endif
+
+size_t bigsize_len(bigsize_t v)
+{
+ if (v < 0xfd) {
+ return 1;
+ } else if (v <= 0xffff) {
+ return 3;
+ } else if (v <= 0xffffffff) {
+ return 5;
+ } else {
+ return 9;
+ }
+}
+
+size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN], bigsize_t v)
+{
+ u8 *p = buf;
+
+ if (v < 0xfd) {
+ *(p++) = v;
+ } else if (v <= 0xffff) {
+ (*p++) = 0xfd;
+ (*p++) = v >> 8;
+ (*p++) = v;
+ } else if (v <= 0xffffffff) {
+ (*p++) = 0xfe;
+ (*p++) = v >> 24;
+ (*p++) = v >> 16;
+ (*p++) = v >> 8;
+ (*p++) = v;
+ } else {
+ (*p++) = 0xff;
+ (*p++) = v >> 56;
+ (*p++) = v >> 48;
+ (*p++) = v >> 40;
+ (*p++) = v >> 32;
+ (*p++) = v >> 24;
+ (*p++) = v >> 16;
+ (*p++) = v >> 8;
+ (*p++) = v;
+ }
+ return p - buf;
+}
+
+size_t bigsize_get(const u8 *p, size_t max, bigsize_t *val)
+{
+ if (max < 1) {
+ SUPERVERBOSE("EOF");
+ return 0;
+ }
+
+ switch (*p) {
+ case 0xfd:
+ if (max < 3) {
+ SUPERVERBOSE("unexpected EOF");
+ return 0;
+ }
+ *val = ((u64)p[1] << 8) + p[2];
+ if (*val < 0xfd) {
+ SUPERVERBOSE("decoded bigsize is not canonical");
+ return 0;
+ }
+ return 3;
+ case 0xfe:
+ if (max < 5) {
+ SUPERVERBOSE("unexpected EOF");
+ return 0;
+ }
+ *val = ((u64)p[1] << 24) + ((u64)p[2] << 16)
+ + ((u64)p[3] << 8) + p[4];
+ if ((*val >> 16) == 0) {
+ SUPERVERBOSE("decoded bigsize is not canonical");
+ return 0;
+ }
+ return 5;
+ case 0xff:
+ if (max < 9) {
+ SUPERVERBOSE("unexpected EOF");
+ return 0;
+ }
+ *val = ((u64)p[1] << 56) + ((u64)p[2] << 48)
+ + ((u64)p[3] << 40) + ((u64)p[4] << 32)
+ + ((u64)p[5] << 24) + ((u64)p[6] << 16)
+ + ((u64)p[7] << 8) + p[8];
+ if ((*val >> 32) == 0) {
+ SUPERVERBOSE("decoded bigsize is not canonical");
+ return 0;
+ }
+ return 9;
+ default:
+ *val = *p;
+ return 1;
+ }
+}
+
+int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out)
+{
+ return bigsize_get(cur->p, cur->end - cur->p, out);
+}
+
+int cursor_push_bigsize(struct cursor *cur, const bigsize_t val)
+{
+ u8 buf[BIGSIZE_MAX_LEN];
+ size_t len;
+
+ len = bigsize_put(buf, val);
+
+ return cursor_push(cur, buf, len);
+}
+
diff --git a/bigsize.h b/bigsize.h
@@ -0,0 +1,31 @@
+#ifndef LNSOCKET_BIGSIZE_H
+#define LNSOCKET_BIGSIZE_H
+#include "config.h"
+#include "cursor.h"
+#include <stddef.h>
+
+/* typedef for clarity. */
+typedef u64 bigsize_t;
+
+#define BIGSIZE_MAX_LEN 9
+
+/* Returns length of buf used. */
+size_t bigsize_put(unsigned char buf[BIGSIZE_MAX_LEN], bigsize_t v);
+
+/* Returns 0 on failure, otherwise length (<= max) used. */
+size_t bigsize_get(const unsigned char *p, size_t max, bigsize_t *val);
+
+/* How many bytes does it take to encode v? */
+size_t bigsize_len(bigsize_t v);
+
+/* Used for wire generation */
+typedef bigsize_t bigsize;
+
+/* marshal/unmarshal functions */
+void towire_bigsize(unsigned char **pptr, const bigsize_t val);
+bigsize_t fromwire_bigsize(const unsigned char **cursor, size_t *max);
+
+int cursor_pull_bigsize(struct cursor *cur, bigsize_t *out);
+int cursor_push_bigsize(struct cursor *cur, const bigsize_t val);
+
+#endif /* LNSOCKET_BIGSIZE_H */
diff --git a/crypto.c b/crypto.c
@@ -86,7 +86,7 @@ int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen,
unsigned char npub[crypto_aead_chacha20poly1305_ietf_NPUBBYTES];
unsigned long long mlen;
- if (inlen < 16 || outcap < inlen - 16)
+ if (inlen < 16 || outcap < cryptomsg_decrypt_size(inlen))
return 0;
le64_nonce(npub, cs->rn++);
@@ -107,7 +107,7 @@ int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen,
return 0;
}
- assert(mlen == inlen - 16);
+ assert(mlen == cryptomsg_decrypt_size(inlen));
maybe_rotate_key(&cs->rn, &cs->rk, &cs->r_ck);
@@ -152,7 +152,7 @@ u8 *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long
*outlen = sizeof(l) + 16 + mlen + 16;
- if (outcap < *outlen) {
+ if (outcap < mlen) {
*outlen = 0;
return NULL;
}
diff --git a/crypto.h b/crypto.h
@@ -43,6 +43,13 @@ void hkdf_two_keys(struct secret *out1, struct secret *out2,
const struct secret *in1,
const struct secret *in2);
+int cryptomsg_decrypt_body(struct crypto_state *cs, const u8 *in, size_t inlen, u8 *out, size_t outcap);
+int cryptomsg_decrypt_header(struct crypto_state *cs, u8 hdr[18], u16 *lenp);
unsigned char *cryptomsg_encrypt_msg(struct crypto_state *cs, const u8 *msg, unsigned long long mlen, u8 *out, size_t *outlen, size_t outcap);
+static inline int cryptomsg_decrypt_size(size_t inlen)
+{
+ return inlen - 16;
+}
+
#endif /* LNSOCKET_CRYPTO_H */
diff --git a/cursor.h b/cursor.h
@@ -224,7 +224,7 @@ static inline int cursor_pop(struct cursor *cur, u8 *data, int len)
return 1;
}
-static inline int cursor_push(struct cursor *cursor, u8 *data, int len)
+static inline int cursor_push(struct cursor *cursor, const void *data, int len)
{
if (unlikely(cursor->p + len >= cursor->end)) {
return 0;
@@ -303,11 +303,6 @@ static inline int cursor_pull_int(struct cursor *cursor, int *i)
return cursor_pull(cursor, (u8*)i, sizeof(*i));
}
-static inline int cursor_push_u16(struct cursor *cursor, u16 i)
-{
- return cursor_push(cursor, (u8*)&i, sizeof(i));
-}
-
static inline void *index_cursor(struct cursor *cursor, unsigned int index, int elem_size)
{
u8 *p;
diff --git a/endian.h b/endian.h
@@ -3,6 +3,7 @@
#define CCAN_ENDIAN_H
#include <stdint.h>
#include "config.h"
+#include "cursor.h"
/**
* BSWAP_16 - reverse bytes in a constant uint16_t value.
@@ -357,4 +358,18 @@ typedef beint16_t be16;
typedef leint64_t le64;
typedef leint32_t le32;
typedef leint16_t le16;
+
+static inline int cursor_push_u16(struct cursor *cursor, u16 i)
+{
+ be16 v = cpu_to_be16(i);
+ return cursor_push(cursor, &v, sizeof(v));
+}
+
+static inline int cursor_push_u64(struct cursor *cur, u64 v)
+{
+ be64 l = cpu_to_be64(v);
+ return cursor_push(cur, (u8*)&l, sizeof(l));
+}
+
+
#endif /* CCAN_ENDIAN_H */
diff --git a/lnsocket.c b/lnsocket.c
@@ -2,6 +2,7 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <inttypes.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,11 +18,18 @@
#include "handshake.h"
#include "error.h"
+#include "crypto.h"
+#include "endian.h"
+#include "bigsize.h"
#include "compiler.h"
#include "lnsocket_internal.h"
+#include "lnsocket.h"
#define array_len(x) (sizeof(x)/sizeof(x[0]))
+#define MSGBUF_MEM 65536
+#define ERROR_MEM 4096
+
int push_error(struct lnsocket *lnsocket, const char *err);
static int char_to_hex(unsigned char *val, char c)
@@ -74,13 +82,205 @@ static int pubkey_from_node_id(secp256k1_context *secp, struct pubkey *key,
sizeof(id->k));
}
+
+static int read_all(int fd, void *data, size_t size)
+{
+ while (size) {
+ ssize_t done;
+
+ done = read(fd, data, size);
+ if (done < 0 && errno == EINTR)
+ continue;
+ if (done <= 0)
+ return 0;
+ data = (char *)data + done;
+ size -= done;
+ }
+
+ return 1;
+}
+
+
+int lnsocket_read(struct lnsocket *ln, unsigned char **buf, int *len)
+{
+ struct cursor enc, dec;
+ u8 hdr[18];
+ u16 size;
+
+ reset_cursor(&ln->errs.cur);
+ reset_cursor(&ln->msgbuf);
+
+ if (!read_all(ln->socket, hdr, sizeof(hdr)))
+ return note_error(&ln->errs,"Failed reading header: %s",
+ strerror(errno));
+
+ if (!cryptomsg_decrypt_header(&ln->crypto_state, hdr, &size))
+ return note_error(&ln->errs,
+ "Failed hdr decrypt with rn=%"PRIu64,
+ ln->crypto_state.rn-1);
+
+ if (!cursor_slice(&ln->msgbuf, &enc, size + 16))
+ return note_error(&ln->errs, "out of memory");
+
+ if (!cursor_slice(&ln->msgbuf, &dec, size))
+ return note_error(&ln->errs, "out of memory");
+
+ if (!read_all(ln->socket, enc.p, enc.end - enc.start))
+ return note_error(&ln->errs, "Failed reading body: %s",
+ strerror(errno));
+
+ if (!cryptomsg_decrypt_body(&ln->crypto_state,
+ enc.start, enc.end - enc.start,
+ dec.start, dec.end - dec.start))
+ return note_error(&ln->errs, "error decrypting body");
+
+ *buf = dec.start;
+ *len = dec.end - dec.start;
+
+ return 1;
+}
+
+static int highest_byte(unsigned char *buf, int buflen)
+{
+ int i, highest;
+ for (i = 0, highest = 0; i < buflen; i++) {
+ if (buf[i] != 0)
+ highest = i;
+ }
+ return highest;
+}
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+int lnsocket_set_feature_bit(unsigned char *buf, int buflen, int *newlen, unsigned int bit)
+{
+ if (newlen == NULL)
+ return 0;
+
+ if (bit / 8 >= buflen)
+ return 0;
+
+ *newlen = max(highest_byte(buf, buflen), (bit / 8) + 1);
+ buf[*newlen - 1 - bit / 8] |= (1 << (bit % 8));
+
+ return 1;
+}
+#undef max
+
+int cursor_push_tlv(struct cursor *cur, const struct tlv *tlv)
+{
+ /* BOLT #1:
+ *
+ * The sending node:
+ ...
+ * - MUST minimally encode `type` and `length`.
+ */
+ return cursor_push_bigsize(cur, tlv->type) &&
+ cursor_push_bigsize(cur, tlv->length) &&
+ cursor_push(cur, tlv->value, tlv->length);
+}
+
+int cursor_push_tlvs(struct cursor *cur, const struct tlv **tlvs, int n_tlvs)
+{
+ int i;
+ for (i = 0; i < n_tlvs; i++) {
+ if (!cursor_push_tlv(cur, tlvs[i]))
+ return 0;
+ }
+
+ return 1;
+}
+
+int lnsocket_make_network_tlv(unsigned char *buf, int buflen,
+ const unsigned char **blockids, int num_blockids,
+ struct tlv *tlv_out)
+{
+ struct cursor cur;
+
+ if (!tlv_out)
+ return 0;
+
+ tlv_out->type = 1;
+ tlv_out->value = buf;
+
+ make_cursor(buf, buf + buflen, &cur);
+
+ for (size_t i = 0; i < num_blockids; i++) {
+ if (!cursor_push(&cur, memcheck(blockids[i], 32), 32))
+ return 0;
+ }
+
+ tlv_out->length = cur.p - cur.start;
+ return 1;
+}
+
+int lnsocket_make_ping_msg(unsigned char *buf, int buflen, u16 num_pong_bytes, u16 ignored_bytes, int *outlen)
+{
+ struct cursor msg;
+ int i;
+
+ make_cursor(buf, buf + buflen, &msg);
+
+ if (!cursor_push_u16(&msg, WIRE_PING))
+ return 0;
+ if (!cursor_push_u16(&msg, num_pong_bytes))
+ return 0;
+ if (!cursor_push_u16(&msg, ignored_bytes))
+ return 0;
+ for (i = 0; i < ignored_bytes; i++) {
+ if (!cursor_push_byte(&msg, 0))
+ return 0;
+ }
+
+ *outlen = msg.p - msg.start;
+
+ return 1;
+}
+
+int lnsocket_make_init_msg(unsigned char *buf, int buflen,
+ const unsigned char *globalfeatures, u16 gflen,
+ const unsigned char *features, u16 flen,
+ const struct tlv **tlvs,
+ unsigned short num_tlvs,
+ int *outlen)
+{
+ struct cursor msg;
+
+ make_cursor(buf, buf + buflen, &msg);
+
+ if (!cursor_push_u16(&msg, WIRE_INIT))
+ return 0;
+
+ if (!cursor_push_u16(&msg, gflen))
+ return 0;
+
+ if (!cursor_push(&msg, globalfeatures, gflen))
+ return 0;
+
+ if (!cursor_push_u16(&msg, flen))
+ return 0;
+
+ if (!cursor_push(&msg, features, flen))
+ return 0;
+
+ if (!cursor_push_tlvs(&msg, tlvs, num_tlvs))
+ return 0;
+
+ *outlen = msg.p - msg.start;
+
+ return 1;
+}
+
int lnsocket_write(struct lnsocket *ln, const u8 *msg, int msglen)
{
- // this is just temporary so we don't need to move the memory cursor
- u8 *out = ln->mem.p;
- ssize_t outcap = ln->mem.end - ln->mem.p;
- ssize_t writelen;
+ ssize_t writelen, outcap;
size_t outlen;
+ u8 *out;
+
+ // this is just temporary so we don't need to move the memory cursor
+ reset_cursor(&ln->msgbuf);
+
+ out = ln->msgbuf.start;
+ outcap = ln->msgbuf.end - ln->msgbuf.start;
if (!ln->socket)
return note_error(&ln->errs, "not connected");
@@ -100,9 +300,11 @@ int lnsocket_write(struct lnsocket *ln, const u8 *msg, int msglen)
return 1;
}
-struct lnsocket *lnsocket_create_with(int memory)
+struct lnsocket *lnsocket_create()
{
struct cursor mem;
+ int memory = MSGBUF_MEM + ERROR_MEM + sizeof(struct lnsocket);
+
void *arena = malloc(memory);
if (!arena)
@@ -115,22 +317,20 @@ struct lnsocket *lnsocket_create_with(int memory)
return NULL;
lnsocket->secp = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
- SECP256K1_CONTEXT_SIGN);
+ SECP256K1_CONTEXT_SIGN);
- if (!cursor_slice(&mem, &lnsocket->errs.cur, memory / 2)) {
+ if (!cursor_slice(&mem, &lnsocket->msgbuf, MSGBUF_MEM))
return NULL;
- }
+
+ if (!cursor_slice(&mem, &lnsocket->errs.cur, ERROR_MEM))
+ return NULL;
+
lnsocket->errs.enabled = 1;
lnsocket->mem = mem;
return lnsocket;
}
-struct lnsocket *lnsocket_create()
-{
- return lnsocket_create_with(16384);
-}
-
void lnsocket_destroy(struct lnsocket *lnsocket)
{
if (!lnsocket)
diff --git a/lnsocket.h b/lnsocket.h
@@ -1,12 +1,75 @@
#ifndef LNSOCKET_H
#define LNSOCKET_H
+#include <stdint.h>
+#include <stdlib.h>
+
struct lnsocket;
+enum peer_wire {
+ WIRE_INIT = 16,
+ WIRE_ERROR = 17,
+ WIRE_WARNING = 1,
+ WIRE_PING = 18,
+ WIRE_PONG = 19,
+ WIRE_TX_ADD_INPUT = 66,
+ WIRE_TX_ADD_OUTPUT = 67,
+ WIRE_TX_REMOVE_INPUT = 68,
+ WIRE_TX_REMOVE_OUTPUT = 69,
+ WIRE_TX_COMPLETE = 70,
+ WIRE_TX_SIGNATURES = 71,
+ WIRE_OPEN_CHANNEL = 32,
+ WIRE_ACCEPT_CHANNEL = 33,
+ WIRE_FUNDING_CREATED = 34,
+ WIRE_FUNDING_SIGNED = 35,
+ WIRE_FUNDING_LOCKED = 36,
+ WIRE_OPEN_CHANNEL2 = 64,
+ WIRE_ACCEPT_CHANNEL2 = 65,
+ WIRE_INIT_RBF = 72,
+ WIRE_ACK_RBF = 73,
+ WIRE_SHUTDOWN = 38,
+ WIRE_CLOSING_SIGNED = 39,
+ WIRE_UPDATE_ADD_HTLC = 128,
+ WIRE_UPDATE_FULFILL_HTLC = 130,
+ WIRE_UPDATE_FAIL_HTLC = 131,
+ WIRE_UPDATE_FAIL_MALFORMED_HTLC = 135,
+ WIRE_COMMITMENT_SIGNED = 132,
+ WIRE_REVOKE_AND_ACK = 133,
+ WIRE_UPDATE_FEE = 134,
+ WIRE_UPDATE_BLOCKHEIGHT = 137,
+ WIRE_CHANNEL_REESTABLISH = 136,
+ WIRE_ANNOUNCEMENT_SIGNATURES = 259,
+ WIRE_CHANNEL_ANNOUNCEMENT = 256,
+ WIRE_NODE_ANNOUNCEMENT = 257,
+ WIRE_CHANNEL_UPDATE = 258,
+ WIRE_QUERY_SHORT_CHANNEL_IDS = 261,
+ WIRE_REPLY_SHORT_CHANNEL_IDS_END = 262,
+ WIRE_QUERY_CHANNEL_RANGE = 263,
+ WIRE_REPLY_CHANNEL_RANGE = 264,
+ WIRE_GOSSIP_TIMESTAMP_FILTER = 265,
+ WIRE_OBS2_ONION_MESSAGE = 387,
+ WIRE_ONION_MESSAGE = 513,
+};
+
+/* A single TLV field, consisting of the data and its associated metadata. */
+struct tlv {
+ uint64_t type;
+ size_t length;
+ unsigned char *value;
+};
+
+struct lnsocket *lnsocket_create();
+
+/* messages */
+
+int lnsocket_make_network_tlv(unsigned char *buf, int buflen, const unsigned char **blockids, int num_blockids, struct tlv *tlv_out);
+int lnsocket_make_ping_msg(unsigned char *buf, int buflen, unsigned short num_pong_bytes, unsigned short ignored_bytes, int *outlen);
+int lnsocket_make_init_msg(unsigned char *buf, int buflen, const unsigned char *globalfeatures, unsigned short gflen, const unsigned char *features, unsigned short flen, const struct tlv **tlvs, unsigned short num_tlvs, int *outlen);
+
int lnsocket_connect(struct lnsocket *, const char *node_id, const char *host);
int lnsocket_write(struct lnsocket *, const unsigned char *msg, int msg_len);
+int lnsocket_read(struct lnsocket *, unsigned char **buf, int *len);
void lnsocket_genkey(struct lnsocket *);
-struct lnsocket *lnsocket_create();
void lnsocket_destroy(struct lnsocket *);
void lnsocket_print_errors(struct lnsocket *);
diff --git a/lnsocket_internal.h b/lnsocket_internal.h
@@ -6,6 +6,7 @@
struct lnsocket {
const char *errors[8];
struct cursor mem;
+ struct cursor msgbuf;
struct errors errs;
int num_errors;
int socket;
diff --git a/test.c b/test.c
@@ -1,31 +1,89 @@
#include "lnsocket.h"
+#include "endian.h"
+#include "typedefs.h"
#include <stdio.h>
+#include <assert.h>
+
+static void print_data(unsigned char *buf, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ printf("%02x", buf[i]);
+ }
+ printf("\n");
+}
int main(int argc, const char *argv[])
{
- struct lnsocket *ln = lnsocket_create();
+ static u8 tlvbuf[1024];
+ static u8 msgbuf[4096];
+ u8 *buf;
+ u8 global_features[2] = {0};
+ u8 features[5] = {0};
+ struct tlv network_tlv;
+ struct lnsocket *ln;
+ int len;
+
int ok = 1;
- const char *nodeid = "03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71";
+ ln = lnsocket_create();
+ assert(ln);
lnsocket_genkey(ln);
- if (!(ok = lnsocket_connect(ln, nodeid, "24.84.152.187"))) {
- lnsocket_print_errors(ln);
+
+ const char *nodeid = "03f3c108ccd536b8526841f0a5c58212bb9e6584a1eb493080e7c1cc34f82dad71";
+ if (!(ok = lnsocket_connect(ln, nodeid, "24.84.152.187")))
goto done;
- }
- printf("connected!\n");
+ if (!(ok = lnsocket_read(ln, &buf, &len)))
+ goto done;
- const unsigned char msg[] = {'h', 'i'};
+ printf("got "); print_data(buf, len);
- if (!lnsocket_write(ln, msg, sizeof(msg))) {
- lnsocket_print_errors(ln);
+ const u8 genesis_block[] = {
+ 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, 0xc1, 0xa6, 0xa2, 0x46,
+ 0xae, 0x63, 0xf7, 0x4f, 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c,
+ 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ const u8 *blockids[] = { genesis_block };
+
+ if (!(ok = lnsocket_make_network_tlv(tlvbuf, sizeof(tlvbuf), blockids, 1, &network_tlv)))
+ goto done;
+
+ const struct tlv *init_tlvs[] = { &network_tlv } ;
+
+ if (!(ok = lnsocket_make_init_msg(msgbuf, sizeof(msgbuf),
+ global_features, sizeof(global_features),
+ features, sizeof(features),
+ init_tlvs, 1,
+ &len)))
+ goto done;
+
+ if (!(ok = lnsocket_write(ln, msgbuf, len)))
+ goto done;
+
+ printf("sent init ");
+ print_data(msgbuf, len);
+
+ if (!(ok = lnsocket_make_ping_msg(msgbuf, sizeof(msgbuf), 1, 1, &len)))
+ goto done;
+
+ if (!(ok = lnsocket_write(ln, msgbuf, len)))
+ goto done;
+
+ printf("sent ping ");
+ print_data(msgbuf, len);
+
+ if (!(ok = lnsocket_read(ln, &buf, &len)))
goto done;
- }
- printf("wrote message.\n");
+ printf("got ");
+ print_data(buf, len);
done:
+ lnsocket_print_errors(ln);
lnsocket_destroy(ln);
return !ok;
}