lnsocket

A minimal C library for connecting to the lightning network
git clone git://jb55.com/lnsocket
Log | Files | Refs | Submodules | README | LICENSE

commit 775be9d89cf59673aa13238258f1021a91e96d7a
parent 5a81cbf45641c3a199554ea9fdc0f90a1ac44c7b
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 11 Jan 2022 08:08:13 -0800

progress

Diffstat:
A.envrc | 1+
M.gitignore | 1+
MMakefile | 20++++++++++++++++++--
AREADME | 5+++++
Adeps/rotate-bits/package.json | 13+++++++++++++
Adeps/rotate-bits/rotate-bits.h | 46++++++++++++++++++++++++++++++++++++++++++++++
Adeps/sha256/package.json | 15+++++++++++++++
Adeps/sha256/sha256.c | 221+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adeps/sha256/sha256.h | 24++++++++++++++++++++++++
Mhandshake.h | 33+++++++++++++++++++++++++++++----
Mnetln.c | 2+-
Ashell.nix | 6++++++
Atypes.h | 7+++++++
13 files changed, 387 insertions(+), 7 deletions(-)

diff --git a/.envrc b/.envrc @@ -0,0 +1 @@ +use nix diff --git a/.gitignore b/.gitignore @@ -2,3 +2,4 @@ .buildcmd /.direnv /netln +/tags diff --git a/Makefile b/Makefile @@ -1,8 +1,10 @@ -CFLAGS=-Wall -g -Og -Ideps/secp256k1 +CFLAGS=-Wall -g -Og -Ideps/secp256k1/include -Ideps/libsodium/src/libsodium/include -Ideps LDFLAGS= +ARS=deps/secp256k1/.libs/libsecp256k1.a deps/libsodium/src/libsodium/.libs/libsodium.a + all: netln deps/secp256k1/src/libsecp256k1-config.h: deps/secp256k1/configure @@ -12,17 +14,31 @@ deps/secp256k1/configure: cd deps/secp256k1; \ ./autogen.sh +deps/libsodium/configure: + cd deps/libsodium; \ + ./autogen.sh + deps/secp256k1/.libs/libsecp256k1.a: deps/secp256k1/configure cd deps/secp256k1; \ make -j2 libsecp256k1.la -netln: netln.c deps/secp256k1/.libs/libsecp256k1.a + +deps/libsodium/src/libsodium/.libs/libsodium.a: deps/libsodium/configure + cd deps/libsodium/src/libsodium; \ + make -j2 libsodium.la + +netln: netln.c $(ARS) $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ +tags: fake + find . -name '*.c' -or -name '*.h' | xargs ctags + clean: fake rm -f netln cd deps/secp256k1; \ make clean + cd deps/libsodium; \ + make clean .PHONY: fake diff --git a/README b/README @@ -0,0 +1,5 @@ + +lnsocket +======== + +A simple C library for sending messages over the lightning network diff --git a/deps/rotate-bits/package.json b/deps/rotate-bits/package.json @@ -0,0 +1,13 @@ +{ + "name": "rotate-bits", + "version": "0.1.1", + "repo": "jb55/rotate-bits.h", + "description": "rotate bits", + "keywords": ["rotl", "rotr"], + "src": ["rotate-bits.h"], + "license": "Public Domain", + "development": { + "thlorenz/tap.c": "*" + } +} + diff --git a/deps/rotate-bits/rotate-bits.h b/deps/rotate-bits/rotate-bits.h @@ -0,0 +1,46 @@ + + +#ifndef __ROTATE_DEFS_H +#define __ROTATE_DEFS_H + +#ifdef _MSC_VER + +#include <stdlib.h> + +#define ROTL32(v, n) _rotl((v), (n)) +#define ROTL64(v, n) _rotl64((v), (n)) + +#define ROTR32(v, n) _rotr((v), (n)) +#define ROTR64(v, n) _rotr64((v), (n)) + +#else + +#include <stdint.h> + +#define U8V(v) ((uint8_t)(v) & 0xFFU) +#define U16V(v) ((uint16_t)(v) & 0xFFFFU) +#define U32V(v) ((uint32_t)(v) & 0xFFFFFFFFU) +#define U64V(v) ((uint64_t)(v) & 0xFFFFFFFFFFFFFFFFU) + +#define ROTL32(v, n) \ + (U32V((uint32_t)(v) << (n)) | ((uint32_t)(v) >> (32 - (n)))) + +// tests fail if we don't have this cast... +#define ROTL64(v, n) \ + (U64V((uint64_t)(v) << (n)) | ((uint64_t)(v) >> (64 - (n)))) + +#define ROTR32(v, n) ROTL32(v, 32 - (n)) +#define ROTR64(v, n) ROTL64(v, 64 - (n)) + +#endif + +#define ROTL8(v, n) \ + (U8V((uint8_t)(v) << (n)) | ((uint8_t)(v) >> (8 - (n)))) + +#define ROTL16(v, n) \ + (U16V((uint16_t)(v) << (n)) | ((uint16_t)(v) >> (16 - (n)))) + +#define ROTR8(v, n) ROTL8(v, 8 - (n)) +#define ROTR16(v, n) ROTL16(v, 16 - (n)) + +#endif diff --git a/deps/sha256/package.json b/deps/sha256/package.json @@ -0,0 +1,15 @@ +{ + "name": "sha256", + "version": "0.0.2", + "repo": "jb55/sha256.c", + "description": "sha256 in c", + "keywords": ["sha256", "sha2"], + "src": ["sha256.c", "sha256.h"], + "dependencies": { + "jb55/rotate-bits.h": "0.1.1" + }, + "development": { + "thlorenz/tap.c": "*" + } +} + diff --git a/deps/sha256/sha256.c b/deps/sha256/sha256.c @@ -0,0 +1,221 @@ +/* Crypto/Sha256.c -- SHA-256 Hash +2010-06-11 : Igor Pavlov : Public domain +This code is based on public domain code from Wei Dai's Crypto++ library. */ + +#include "rotate-bits/rotate-bits.h" +#include "sha256.h" + +/* define it for speed optimization */ +#define _SHA256_UNROLL +#define _SHA256_UNROLL2 + +void +sha256_init(struct sha256 *p) +{ + p->state[0] = 0x6a09e667; + p->state[1] = 0xbb67ae85; + p->state[2] = 0x3c6ef372; + p->state[3] = 0xa54ff53a; + p->state[4] = 0x510e527f; + p->state[5] = 0x9b05688c; + p->state[6] = 0x1f83d9ab; + p->state[7] = 0x5be0cd19; + p->count = 0; +} + +#define S0(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x, 22)) +#define S1(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x, 25)) +#define s0(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ (x >> 3)) +#define s1(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ (x >> 10)) + +#define blk0(i) (W[i] = data[i]) +#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15])) + +#define Ch(x,y,z) (z^(x&(y^z))) +#define Maj(x,y,z) ((x&y)|(z&(x|y))) + +#define a(i) T[(0-(i))&7] +#define b(i) T[(1-(i))&7] +#define c(i) T[(2-(i))&7] +#define d(i) T[(3-(i))&7] +#define e(i) T[(4-(i))&7] +#define f(i) T[(5-(i))&7] +#define g(i) T[(6-(i))&7] +#define h(i) T[(7-(i))&7] + + +#ifdef _SHA256_UNROLL2 + +#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\ + d += h; h += S0(a) + Maj(a, b, c) + +#define RX_8(i) \ + R(a,b,c,d,e,f,g,h, i); \ + R(h,a,b,c,d,e,f,g, (i+1)); \ + R(g,h,a,b,c,d,e,f, (i+2)); \ + R(f,g,h,a,b,c,d,e, (i+3)); \ + R(e,f,g,h,a,b,c,d, (i+4)); \ + R(d,e,f,g,h,a,b,c, (i+5)); \ + R(c,d,e,f,g,h,a,b, (i+6)); \ + R(b,c,d,e,f,g,h,a, (i+7)) + +#else + +#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\ + d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) + +#ifdef _SHA256_UNROLL + +#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7); + +#endif + +#endif + +static const uint32_t K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, + 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, + 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, + 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, + 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, + 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, + 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, + 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +static void +struct sha256ransform(uint32_t *state, const uint32_t *data) +{ + uint32_t W[16]; + unsigned j; + #ifdef _SHA256_UNROLL2 + uint32_t a,b,c,d,e,f,g,h; + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + f = state[5]; + g = state[6]; + h = state[7]; + #else + uint32_t T[8]; + for (j = 0; j < 8; j++) + T[j] = state[j]; + #endif + + for (j = 0; j < 64; j += 16) + { + #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2) + RX_8(0); RX_8(8); + #else + unsigned i; + for (i = 0; i < 16; i++) { R(i); } + #endif + } + + #ifdef _SHA256_UNROLL2 + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + state[5] += f; + state[6] += g; + state[7] += h; + #else + for (j = 0; j < 8; j++) + state[j] += T[j]; + #endif + + /* Wipe variables */ + /* memset(W, 0, sizeof(W)); */ + /* memset(T, 0, sizeof(T)); */ +} + +#undef S0 +#undef S1 +#undef s0 +#undef s1 + +static void +sha256_write_byte_block(struct sha256 *p) +{ + uint32_t data32[16]; + unsigned i; + for (i = 0; i < 16; i++) + data32[i] = + ((uint32_t)(p->buffer[i * 4 ]) << 24) + + ((uint32_t)(p->buffer[i * 4 + 1]) << 16) + + ((uint32_t)(p->buffer[i * 4 + 2]) << 8) + + ((uint32_t)(p->buffer[i * 4 + 3])); + struct sha256ransform(p->state, data32); +} + + +void +sha256_hash(unsigned char *buf, const unsigned char *data, size_t size) +{ + struct sha256 hash; + sha256_init(&hash); + sha256_update(&hash, data, size); + sha256_final(&hash, buf); +} + + +void +sha256_update(struct sha256 *p, const unsigned char *data, size_t size) +{ + uint32_t curBufferPos = (uint32_t)p->count & 0x3F; + while (size > 0) + { + p->buffer[curBufferPos++] = *data++; + p->count++; + size--; + if (curBufferPos == 64) + { + curBufferPos = 0; + sha256_write_byte_block(p); + } + } +} + + +void +sha256_final(struct sha256 *p, unsigned char *digest) +{ + uint64_t lenInBits = (p->count << 3); + uint32_t curBufferPos = (uint32_t)p->count & 0x3F; + unsigned i; + p->buffer[curBufferPos++] = 0x80; + while (curBufferPos != (64 - 8)) + { + curBufferPos &= 0x3F; + if (curBufferPos == 0) + sha256_write_byte_block(p); + p->buffer[curBufferPos++] = 0; + } + for (i = 0; i < 8; i++) + { + p->buffer[curBufferPos++] = (unsigned char)(lenInBits >> 56); + lenInBits <<= 8; + } + sha256_write_byte_block(p); + + for (i = 0; i < 8; i++) + { + *digest++ = (unsigned char)(p->state[i] >> 24); + *digest++ = (unsigned char)(p->state[i] >> 16); + *digest++ = (unsigned char)(p->state[i] >> 8); + *digest++ = (unsigned char)(p->state[i]); + } + sha256_init(p); +} diff --git a/deps/sha256/sha256.h b/deps/sha256/sha256.h @@ -0,0 +1,24 @@ +/* Sha256.h -- SHA-256 Hash +2010-06-11 : Igor Pavlov : Public domain */ + +#ifndef __CRYPTO_SHA256_H +#define __CRYPTO_SHA256_H + +#include <stdlib.h> +#include <stdint.h> + +#define SHA256_DIGEST_SIZE 32 + +struct sha256 +{ + uint32_t state[8]; + uint64_t count; + unsigned char buffer[64]; +}; + +void sha256_init(struct sha256 *p); +void sha256_update(struct sha256 *p, const unsigned char *data, size_t size); +void sha256_final(struct sha256 *p, unsigned char *digest); +void sha256_hash(unsigned char *buf, const unsigned char *data, size_t size); + +#endif diff --git a/handshake.h b/handshake.h @@ -2,11 +2,34 @@ #ifndef LNLINK_HANDSHAKE_H #define LNLINK_HANDSHAKE_H -#include <secp256k1/> +#include "types.h" + +#include <sodium/crypto_aead_chacha20poly1305.h> +#include <secp256k1_extrakeys.h> +#include <sha256/sha256.h> + +#define PUBKEY_CMPR_LEN 33 + +enum bolt8_side { + INITIATOR, + RESPONDER +}; + +struct secret { + u8 data[32]; +}; struct pubkey { - /* Unpacked pubkey (as used by libsecp256k1 internally) */ - secp256k1_pubkey pubkey; + u8 data[64]; +}; + +struct privkey { + struct secret secret; +}; + +struct keypair { + struct pubkey pub; + struct privkey priv; }; /* BOLT #8: @@ -85,7 +108,7 @@ struct handshake { struct act_three act3; /* Where is connection from/to */ - struct wireaddr_internal addr; + struct addrinfo addr; /* Who we are */ struct pubkey my_id; @@ -96,12 +119,14 @@ struct handshake { enum bolt8_side side; /* Function to call once handshake complete. */ + /* struct io_plan *(*cb)(struct io_conn *conn, const struct pubkey *their_id, const struct wireaddr_internal *wireaddr, struct crypto_state *cs, void *cbarg); void *cbarg; + */ }; #endif /* LNLINK_HANDSHAKE_H */ diff --git a/netln.c b/netln.c @@ -55,7 +55,7 @@ int connect_node(struct netln *netln, unsigned char *pubkey, const char *host) return 1; } -int act_one_initiator(int fd) +void act_one_initiator(int fd) { } diff --git a/shell.nix b/shell.nix @@ -0,0 +1,6 @@ +{ pkgs ? import <nixpkgs> {} }: +with pkgs; +mkShell { + buildInputs = [ ]; + nativeBuildInputs = [ gdb autoreconfHook clib ]; +} diff --git a/types.h b/types.h @@ -0,0 +1,7 @@ + +#ifndef LNSOCKET_TYPES_H +#define LNSOCKET_TYPES_H + +typedef unsigned char u8; + +#endif /* LNSOCKET_TYPES_H */