mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
Initial silly cmdline util to create an openchannel packet.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
commit
1c4fdce514
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*~
|
||||||
|
*.o
|
||||||
|
openchannel
|
61
Makefile
Normal file
61
Makefile
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#! /usr/bin/make
|
||||||
|
|
||||||
|
# Needs to have oneof support: Ubuntu vivid's is too old :(
|
||||||
|
PROTOCC:=protoc-c
|
||||||
|
|
||||||
|
PROGRAMS := openchannel
|
||||||
|
|
||||||
|
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o
|
||||||
|
CCAN_OBJS := ccan-crypto-sha256.o ccan-crypto-shachain.o ccan-err.o ccan-tal.o ccan-tal-str.o ccan-take.o ccan-list.o ccan-str.o ccan-opt-helpers.o ccan-opt.o ccan-opt-parse.o ccan-opt-usage.o ccan-read_write_all.o ccan-str-hex.o
|
||||||
|
|
||||||
|
OPENCHANNEL_OBJS := openchannel.o $(HELPER_OBJS) $(CCAN_OBJS)
|
||||||
|
|
||||||
|
HEADERS := base58.h lightning.pb-c.h pd_channel.h pkt.h shadouble.h
|
||||||
|
|
||||||
|
CCANDIR := ../ccan/
|
||||||
|
CFLAGS := -g -Wall -I $(CCANDIR) #-I $(PROTO_INCLUDE_DIR)
|
||||||
|
LDLIBS := -lcrypto -lprotobuf-c
|
||||||
|
|
||||||
|
default: openchannel
|
||||||
|
|
||||||
|
lightning.pb-c.c lightning.pb-c.h: lightning.proto
|
||||||
|
$(PROTOCC) lightning.proto --c_out=.
|
||||||
|
|
||||||
|
openchannel: $(OPENCHANNEL_OBJS)
|
||||||
|
$(OPENCHANNEL_OBJS): $(HEADERS)
|
||||||
|
|
||||||
|
distclean: clean
|
||||||
|
$(RM) lightning.pb-c.c lightning.pb-c.h
|
||||||
|
|
||||||
|
clean:
|
||||||
|
$(RM) $(OPENCHANNEL_OBJS)
|
||||||
|
|
||||||
|
ccan-tal.o: $(CCANDIR)/ccan/tal/tal.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-tal-str.o: $(CCANDIR)/ccan/tal/str/str.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-take.o: $(CCANDIR)/ccan/take/take.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-list.o: $(CCANDIR)/ccan/list/list.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-read_write_all.o: $(CCANDIR)/ccan/read_write_all/read_write_all.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-str.o: $(CCANDIR)/ccan/str/str.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-opt.o: $(CCANDIR)/ccan/opt/opt.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-opt-helpers.o: $(CCANDIR)/ccan/opt/helpers.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-opt-parse.o: $(CCANDIR)/ccan/opt/parse.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-opt-usage.o: $(CCANDIR)/ccan/opt/usage.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-err.o: $(CCANDIR)/ccan/err/err.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-str-hex.o: $(CCANDIR)/ccan/str/hex/hex.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-crypto-shachain.o: $(CCANDIR)/ccan/crypto/shachain/shachain.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
ccan-crypto-sha256.o: $(CCANDIR)/ccan/crypto/sha256/sha256.c
|
||||||
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
361
base58.c
Normal file
361
base58.c
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/* Converted to C by Rusty Russell, based on bitcoin source: */
|
||||||
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||||
|
// Copyright (c) 2009-2012 The Bitcoin Developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
#include "base58.h"
|
||||||
|
#include "shadouble.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <ccan/build_assert/build_assert.h>
|
||||||
|
#include <ccan/tal/str/str.h>
|
||||||
|
#include <openssl/obj_mac.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const char enc_16[] = "0123456789abcdef";
|
||||||
|
static const char enc_58[] =
|
||||||
|
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
||||||
|
|
||||||
|
static char encode_char(unsigned long val, const char *enc)
|
||||||
|
{
|
||||||
|
assert(val < strlen(enc));
|
||||||
|
return enc[val];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int decode_char(char c, const char *enc)
|
||||||
|
{
|
||||||
|
const char *pos = strchr(enc, c);
|
||||||
|
if (!pos)
|
||||||
|
return -1;
|
||||||
|
return pos - enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Encode a byte sequence as a base58-encoded string. This is a bit
|
||||||
|
* weird: returns pointer into buf (or NULL if wouldn't fit).
|
||||||
|
*/
|
||||||
|
static char *encode_base58(char *buf, size_t buflen,
|
||||||
|
const u8 *data, size_t data_len)
|
||||||
|
{
|
||||||
|
char *p;
|
||||||
|
BIGNUM bn;
|
||||||
|
|
||||||
|
/* Convert to a bignum. */
|
||||||
|
BN_init(&bn);
|
||||||
|
BN_bin2bn(data, data_len, &bn);
|
||||||
|
|
||||||
|
/* Add NUL terminator */
|
||||||
|
if (!buflen) {
|
||||||
|
p = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
p = buf + buflen;
|
||||||
|
*(--p) = '\0';
|
||||||
|
|
||||||
|
/* Fill from the back, using a series of divides. */
|
||||||
|
while (!BN_is_zero(&bn)) {
|
||||||
|
int rem = BN_div_word(&bn, 58);
|
||||||
|
if (--p < buf) {
|
||||||
|
p = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*p = encode_char(rem, enc_58);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, this is really weird. We pad with zeroes, but not at
|
||||||
|
* base 58, but in terms of zero bytes. This means that some
|
||||||
|
* encodings are shorter than others! */
|
||||||
|
while (data_len && *data == '\0') {
|
||||||
|
if (--p < buf) {
|
||||||
|
p = NULL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
*p = encode_char(0, enc_58);
|
||||||
|
data_len--;
|
||||||
|
data++;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
BN_free(&bn);
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode a base_n-encoded string into a byte sequence.
|
||||||
|
*/
|
||||||
|
bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base)
|
||||||
|
{
|
||||||
|
const char *enc;
|
||||||
|
|
||||||
|
BN_zero(bn);
|
||||||
|
|
||||||
|
assert(base == 16 || base == 58);
|
||||||
|
switch (base) {
|
||||||
|
case 16:
|
||||||
|
enc = enc_16;
|
||||||
|
break;
|
||||||
|
case 58:
|
||||||
|
enc = enc_58;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len) {
|
||||||
|
char current = *src;
|
||||||
|
|
||||||
|
if (base == 16)
|
||||||
|
current = tolower(current); /* TODO: Not in ccan. */
|
||||||
|
int val = decode_char(current, enc);
|
||||||
|
if (val < 0) {
|
||||||
|
BN_free(bn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
BN_mul_word(bn, base);
|
||||||
|
BN_add_word(bn, val);
|
||||||
|
src++;
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode a base58-encoded string into a byte sequence.
|
||||||
|
*/
|
||||||
|
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len)
|
||||||
|
{
|
||||||
|
return raw_decode_base_n(bn, src, len, 58);
|
||||||
|
}
|
||||||
|
|
||||||
|
void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen)
|
||||||
|
{
|
||||||
|
struct sha256_double sha_result;
|
||||||
|
|
||||||
|
/* Form checksum, using double SHA2 (as per bitcoin standard) */
|
||||||
|
sha256_double(&sha_result, buf, buflen);
|
||||||
|
|
||||||
|
/* Use first four bytes of that as the checksum. */
|
||||||
|
memcpy(csum, sha_result.sha.u.u8, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *bitcoin_to_base58(const tal_t *ctx, bool test_net,
|
||||||
|
const struct bitcoin_address *addr)
|
||||||
|
{
|
||||||
|
u8 buf[1 + RIPEMD160_DIGEST_LENGTH + 4];
|
||||||
|
char out[BASE58_ADDR_MAX_LEN + 2], *p;
|
||||||
|
|
||||||
|
buf[0] = test_net ? 111 : 0;
|
||||||
|
|
||||||
|
BUILD_ASSERT(sizeof(*addr) == RIPEMD160_DIGEST_LENGTH);
|
||||||
|
memcpy(buf+1, addr, RIPEMD160_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
/* Append checksum */
|
||||||
|
base58_get_checksum(buf + 1 + RIPEMD160_DIGEST_LENGTH,
|
||||||
|
buf, 1 + RIPEMD160_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
p = encode_base58(out, BASE58_ADDR_MAX_LEN, buf, sizeof(buf));
|
||||||
|
return tal_strdup(ctx, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool bitcoin_from_base58(bool *test_net,
|
||||||
|
struct bitcoin_address *addr,
|
||||||
|
const char *base58, size_t base58_len)
|
||||||
|
{
|
||||||
|
u8 buf[1 + RIPEMD160_DIGEST_LENGTH + 4];
|
||||||
|
BIGNUM bn;
|
||||||
|
size_t len;
|
||||||
|
u8 csum[4];
|
||||||
|
|
||||||
|
BN_init(&bn);
|
||||||
|
if (!raw_decode_base58(&bn, base58, base58_len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
len = BN_num_bytes(&bn);
|
||||||
|
if (len > sizeof(buf))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof(buf));
|
||||||
|
BN_bn2bin(&bn, buf + sizeof(buf) - len);
|
||||||
|
BN_free(&bn);
|
||||||
|
|
||||||
|
if (buf[0] == 111)
|
||||||
|
*test_net = true;
|
||||||
|
else if (buf[0] == 0)
|
||||||
|
*test_net = false;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
base58_get_checksum(csum, buf, 1 + RIPEMD160_DIGEST_LENGTH);
|
||||||
|
if (memcmp(csum, buf + 1 + RIPEMD160_DIGEST_LENGTH, sizeof(csum)) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BUILD_ASSERT(sizeof(*addr) == RIPEMD160_DIGEST_LENGTH);
|
||||||
|
memcpy(addr, buf+1, sizeof(*addr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* buf already contains version and ripemd160. Append checksum and encode */
|
||||||
|
char *base58_with_check(char dest[BASE58_ADDR_MAX_LEN],
|
||||||
|
u8 buf[1 + RIPEMD160_DIGEST_LENGTH + 4])
|
||||||
|
{
|
||||||
|
/* Append checksum */
|
||||||
|
base58_get_checksum(buf + 1 + RIPEMD160_DIGEST_LENGTH,
|
||||||
|
buf, 1 + RIPEMD160_DIGEST_LENGTH);
|
||||||
|
|
||||||
|
/* Now encode. */
|
||||||
|
return encode_base58(dest, BASE58_ADDR_MAX_LEN, buf,
|
||||||
|
1 + RIPEMD160_DIGEST_LENGTH + 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ripemd_from_base58(u8 *version, u8 ripemd160[RIPEMD160_DIGEST_LENGTH],
|
||||||
|
const char *base58)
|
||||||
|
{
|
||||||
|
u8 buf[1 + RIPEMD160_DIGEST_LENGTH + 4];
|
||||||
|
u8 csum[4];
|
||||||
|
BIGNUM bn;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
/* Too long? Check here before doing arithmetic. */
|
||||||
|
if (strlen(base58) > BASE58_ADDR_MAX_LEN - 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
BN_init(&bn);
|
||||||
|
/* Fails if it contains invalid characters. */
|
||||||
|
if (!raw_decode_base58(&bn, base58, strlen(base58)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Too big? */
|
||||||
|
len = BN_num_bytes(&bn);
|
||||||
|
if (len > sizeof(buf)) {
|
||||||
|
BN_free(&bn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill start with zeroes. */
|
||||||
|
memset(buf, 0, sizeof(buf) - len);
|
||||||
|
BN_bn2bin(&bn, buf + sizeof(buf) - len);
|
||||||
|
BN_free(&bn);
|
||||||
|
|
||||||
|
/* Check checksum is correct. */
|
||||||
|
base58_get_checksum(csum, buf, sizeof(buf));
|
||||||
|
if (memcmp(csum, buf + 1 + RIPEMD160_DIGEST_LENGTH, 4) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*version = buf[0];
|
||||||
|
memcpy(ripemd160, buf + 1, RIPEMD160_DIGEST_LENGTH);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *key_to_base58(const tal_t *ctx, bool test_net, EC_KEY *key)
|
||||||
|
{
|
||||||
|
u8 buf[1 + 32 + 1 + 4];
|
||||||
|
char out[BASE58_KEY_MAX_LEN + 2], *p;
|
||||||
|
const BIGNUM *bn = EC_KEY_get0_private_key(key);
|
||||||
|
int len;
|
||||||
|
|
||||||
|
buf[0] = test_net ? 239 : 128;
|
||||||
|
|
||||||
|
/* Make sure any zeroes are at the front of number (MSB) */
|
||||||
|
len = BN_num_bytes(bn);
|
||||||
|
assert(len <= 32);
|
||||||
|
memset(buf + 1, 0, 32 - len);
|
||||||
|
BN_bn2bin(bn, buf + 1 + 32 - len);
|
||||||
|
|
||||||
|
/* Mark this as a compressed key. */
|
||||||
|
buf[1 + 32] = 1;
|
||||||
|
|
||||||
|
/* Append checksum */
|
||||||
|
base58_get_checksum(buf + 1 + 32 + 1, buf, 1 + 32 + 1);
|
||||||
|
|
||||||
|
p = encode_base58(out, BASE58_KEY_MAX_LEN, buf, sizeof(buf));
|
||||||
|
return tal_strdup(ctx, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thus function based on bitcoin's key.cpp:
|
||||||
|
// Copyright (c) 2009-2012 The Bitcoin developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
static bool EC_KEY_regenerate_key(EC_KEY *eckey, BIGNUM *priv_key)
|
||||||
|
{
|
||||||
|
BN_CTX *ctx = NULL;
|
||||||
|
EC_POINT *pub_key = NULL;
|
||||||
|
const EC_GROUP *group = EC_KEY_get0_group(eckey);
|
||||||
|
|
||||||
|
if ((ctx = BN_CTX_new()) == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
pub_key = EC_POINT_new(group);
|
||||||
|
if (pub_key == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, ctx))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EC_KEY_set_private_key(eckey, priv_key);
|
||||||
|
EC_KEY_set_public_key(eckey, pub_key);
|
||||||
|
|
||||||
|
BN_CTX_free(ctx);
|
||||||
|
EC_POINT_free(pub_key);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
EC_KEY *key_from_base58(const char *base58, size_t base58_len,
|
||||||
|
bool *test_net, struct bitcoin_compressed_pubkey *key)
|
||||||
|
{
|
||||||
|
size_t keylen;
|
||||||
|
u8 keybuf[1 + 32 + 1 + 4], *pubkey;
|
||||||
|
u8 csum[4];
|
||||||
|
EC_KEY *priv;
|
||||||
|
BIGNUM bn;
|
||||||
|
|
||||||
|
BN_init(&bn);
|
||||||
|
if (!raw_decode_base58(&bn, base58, base58_len))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
keylen = BN_num_bytes(&bn);
|
||||||
|
/* FIXME: Handle non-compressed keys! */
|
||||||
|
if (keylen == 1 + 32 + 4)
|
||||||
|
goto fail_free_bn;
|
||||||
|
if (keylen != 1 + 32 + 1 + 4)
|
||||||
|
goto fail_free_bn;
|
||||||
|
BN_bn2bin(&bn, keybuf);
|
||||||
|
|
||||||
|
base58_get_checksum(csum, keybuf, keylen - sizeof(csum));
|
||||||
|
if (memcmp(csum, keybuf + keylen - sizeof(csum), sizeof(csum)) != 0)
|
||||||
|
goto fail_free_bn;
|
||||||
|
|
||||||
|
/* Byte after key should be 1 to represent a compressed key. */
|
||||||
|
if (keybuf[1 + 32] != 1)
|
||||||
|
goto fail_free_bn;
|
||||||
|
|
||||||
|
if (keybuf[0] == 128)
|
||||||
|
*test_net = false;
|
||||||
|
else if (keybuf[0] == 239)
|
||||||
|
*test_net = true;
|
||||||
|
else
|
||||||
|
goto fail_free_bn;
|
||||||
|
|
||||||
|
priv = EC_KEY_new_by_curve_name(NID_secp256k1);
|
||||||
|
/* We *always* used compressed form keys. */
|
||||||
|
EC_KEY_set_conv_form(priv, POINT_CONVERSION_COMPRESSED);
|
||||||
|
|
||||||
|
BN_free(&bn);
|
||||||
|
BN_init(&bn);
|
||||||
|
if (!BN_bin2bn(keybuf + 1, 32, &bn))
|
||||||
|
goto fail_free_priv;
|
||||||
|
if (!EC_KEY_regenerate_key(priv, &bn))
|
||||||
|
goto fail_free_priv;
|
||||||
|
|
||||||
|
/* Save public key */
|
||||||
|
pubkey = key->key;
|
||||||
|
keylen = i2o_ECPublicKey(priv, &pubkey);
|
||||||
|
assert(keylen == sizeof(key->key));
|
||||||
|
|
||||||
|
BN_free(&bn);
|
||||||
|
return priv;
|
||||||
|
|
||||||
|
fail_free_priv:
|
||||||
|
EC_KEY_free(priv);
|
||||||
|
fail_free_bn:
|
||||||
|
BN_free(&bn);
|
||||||
|
return NULL;
|
||||||
|
}
|
54
base58.h
Normal file
54
base58.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#ifndef LIGHTNING_BASE58_H
|
||||||
|
#define LIGHTNING_BASE58_H
|
||||||
|
/* FIXME: Use libsecpk1 */
|
||||||
|
#include <ccan/tal/tal.h>
|
||||||
|
#include <ccan/short_types/short_types.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/ec.h>
|
||||||
|
#include <openssl/ripemd.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* Encoding is version byte + ripemd160 + 4-byte checksum == 200 bits => 2^200.
|
||||||
|
*
|
||||||
|
* Now, 58^34 < 2^200, but 58^35 > 2^200. So 35 digits is sufficient,
|
||||||
|
* plus 1 terminator.
|
||||||
|
*/
|
||||||
|
#define BASE58_ADDR_MAX_LEN 36
|
||||||
|
|
||||||
|
/* For encoding private keys, it's 302 bits.
|
||||||
|
* 58^51 < 2^302, but 58^52 > 2^302. So 52 digits, plus one terminator. */
|
||||||
|
#define BASE58_KEY_MAX_LEN 53
|
||||||
|
|
||||||
|
/* An ECDSA compressed public key. 33 chars long, even on ARM. */
|
||||||
|
struct bitcoin_compressed_pubkey {
|
||||||
|
u8 key[33];
|
||||||
|
} __attribute__((aligned(1)));
|
||||||
|
|
||||||
|
/* An address is the RIPEMD160 of the SHA of the public key. */
|
||||||
|
struct bitcoin_address {
|
||||||
|
u8 addr[RIPEMD160_DIGEST_LENGTH]; /* 20 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Bitcoin address encoded in base58, with version and checksum */
|
||||||
|
char *bitcoin_to_base58(const tal_t *ctx, bool test_net,
|
||||||
|
const struct bitcoin_address *addr);
|
||||||
|
bool bitcoin_from_base58(bool *test_net,
|
||||||
|
struct bitcoin_address *addr,
|
||||||
|
const char *base58, size_t len);
|
||||||
|
|
||||||
|
bool ripemd_from_base58(u8 *version, u8 ripemd160[RIPEMD160_DIGEST_LENGTH],
|
||||||
|
const char *base58);
|
||||||
|
|
||||||
|
char *base58_with_check(char dest[BASE58_ADDR_MAX_LEN],
|
||||||
|
u8 buf[1 + RIPEMD160_DIGEST_LENGTH + 4]);
|
||||||
|
|
||||||
|
char *key_to_base58(const tal_t *ctx, bool test_net, EC_KEY *key);
|
||||||
|
EC_KEY *key_from_base58(const char *base58, size_t base58_len,
|
||||||
|
bool *test_net, struct bitcoin_compressed_pubkey *key);
|
||||||
|
|
||||||
|
bool raw_decode_base_n(BIGNUM *bn, const char *src, size_t len, int base);
|
||||||
|
bool raw_decode_base58(BIGNUM *bn, const char *src, size_t len);
|
||||||
|
void base58_get_checksum(u8 csum[4], const u8 buf[], size_t buflen);
|
||||||
|
|
||||||
|
#endif /* PETTYCOIN_BASE58_H */
|
2051
lightning.pb-c.c
Normal file
2051
lightning.pb-c.c
Normal file
File diff suppressed because it is too large
Load Diff
933
lightning.pb-c.h
Normal file
933
lightning.pb-c.h
Normal file
@ -0,0 +1,933 @@
|
|||||||
|
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
||||||
|
/* Generated from: lightning.proto */
|
||||||
|
|
||||||
|
#ifndef PROTOBUF_C_lightning_2eproto__INCLUDED
|
||||||
|
#define PROTOBUF_C_lightning_2eproto__INCLUDED
|
||||||
|
|
||||||
|
#include <protobuf-c/protobuf-c.h>
|
||||||
|
|
||||||
|
PROTOBUF_C__BEGIN_DECLS
|
||||||
|
|
||||||
|
#if PROTOBUF_C_VERSION_NUMBER < 1000000
|
||||||
|
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
|
||||||
|
#elif 1001001 < PROTOBUF_C_MIN_COMPILER_VERSION
|
||||||
|
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _Sha256Hash Sha256Hash;
|
||||||
|
typedef struct _BitcoinOutputId BitcoinOutputId;
|
||||||
|
typedef struct _BitcoinOutput BitcoinOutput;
|
||||||
|
typedef struct _BitcoinSignature BitcoinSignature;
|
||||||
|
typedef struct _Anchor Anchor;
|
||||||
|
typedef struct _OpenChannel OpenChannel;
|
||||||
|
typedef struct _OpenCommitSig OpenCommitSig;
|
||||||
|
typedef struct _OpenAnchorSig OpenAnchorSig;
|
||||||
|
typedef struct _OpenComplete OpenComplete;
|
||||||
|
typedef struct _Update Update;
|
||||||
|
typedef struct _UpdateAccept UpdateAccept;
|
||||||
|
typedef struct _UpdateComplete UpdateComplete;
|
||||||
|
typedef struct _NewAnchor NewAnchor;
|
||||||
|
typedef struct _NewAnchorAck NewAnchorAck;
|
||||||
|
typedef struct _NewAnchorAccept NewAnchorAccept;
|
||||||
|
typedef struct _NewAnchorComplete NewAnchorComplete;
|
||||||
|
typedef struct _CloseChannel CloseChannel;
|
||||||
|
typedef struct _CloseChannelComplete CloseChannelComplete;
|
||||||
|
typedef struct _Error Error;
|
||||||
|
typedef struct _Pkt Pkt;
|
||||||
|
|
||||||
|
|
||||||
|
/* --- enums --- */
|
||||||
|
|
||||||
|
|
||||||
|
/* --- messages --- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protobufs don't have fixed-length fields, so this is a hack.
|
||||||
|
*/
|
||||||
|
struct _Sha256Hash
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
uint64_t a;
|
||||||
|
uint64_t b;
|
||||||
|
uint64_t c;
|
||||||
|
uint64_t d;
|
||||||
|
};
|
||||||
|
#define SHA256_HASH__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&sha256_hash__descriptor) \
|
||||||
|
, 0, 0, 0, 0 }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Identifies a bitcoin output.
|
||||||
|
*/
|
||||||
|
struct _BitcoinOutputId
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* This is the transaction ID.
|
||||||
|
*/
|
||||||
|
Sha256Hash *txid;
|
||||||
|
/*
|
||||||
|
* This is the output number.
|
||||||
|
*/
|
||||||
|
uint32_t output;
|
||||||
|
};
|
||||||
|
#define BITCOIN_OUTPUT_ID__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_output_id__descriptor) \
|
||||||
|
, NULL, 0 }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A bitcoin output
|
||||||
|
*/
|
||||||
|
struct _BitcoinOutput
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
uint64_t amount;
|
||||||
|
ProtobufCBinaryData script;
|
||||||
|
};
|
||||||
|
#define BITCOIN_OUTPUT__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_output__descriptor) \
|
||||||
|
, 0, {0,NULL} }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A signature to use for a transaction; DER encoded with sigtype at the end.
|
||||||
|
*/
|
||||||
|
struct _BitcoinSignature
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
ProtobufCBinaryData der_then_sigtype;
|
||||||
|
};
|
||||||
|
#define BITCOIN_SIGNATURE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_signature__descriptor) \
|
||||||
|
, {0,NULL} }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All about an anchor transaction.
|
||||||
|
*/
|
||||||
|
struct _Anchor
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* 0 or more unspent inputs we want to use for anchor.
|
||||||
|
*/
|
||||||
|
size_t n_inputs;
|
||||||
|
BitcoinOutputId **inputs;
|
||||||
|
/*
|
||||||
|
* Any change from anchor (in case we don't want to use them all)
|
||||||
|
*/
|
||||||
|
BitcoinOutput *anchor_change;
|
||||||
|
/*
|
||||||
|
* How much transaction fee we'll pay in the anchor tx.
|
||||||
|
*/
|
||||||
|
uint64_t fee;
|
||||||
|
/*
|
||||||
|
* How many confirmations on anchor before we'll use channel.
|
||||||
|
*/
|
||||||
|
uint32_t min_confirms;
|
||||||
|
};
|
||||||
|
#define ANCHOR__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&anchor__descriptor) \
|
||||||
|
, 0,NULL, NULL, 0, 0 }
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
OPEN_CHANNEL__LOCKTIME__NOT_SET = 0,
|
||||||
|
OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS = 2,
|
||||||
|
OPEN_CHANNEL__LOCKTIME_LOCKTIME_BLOCKS = 3,
|
||||||
|
} OpenChannel__LocktimeCase;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set channel params.
|
||||||
|
*/
|
||||||
|
struct _OpenChannel
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* Seed which sets order we create outputs for all transactions.
|
||||||
|
*/
|
||||||
|
uint64_t seed;
|
||||||
|
/*
|
||||||
|
* Hash seed for revoking commitment transactions.
|
||||||
|
*/
|
||||||
|
Sha256Hash *revocation_hash;
|
||||||
|
/*
|
||||||
|
* How to pay money to us.
|
||||||
|
*/
|
||||||
|
ProtobufCBinaryData script_to_me;
|
||||||
|
/*
|
||||||
|
* How much transaction fee we'll pay for commitment txs.
|
||||||
|
*/
|
||||||
|
uint64_t commitment_fee;
|
||||||
|
/*
|
||||||
|
* The anchor transaction details.
|
||||||
|
*/
|
||||||
|
Anchor *anchor;
|
||||||
|
OpenChannel__LocktimeCase locktime_case;
|
||||||
|
union {
|
||||||
|
uint32_t locktime_seconds;
|
||||||
|
uint32_t locktime_blocks;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#define OPEN_CHANNEL__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \
|
||||||
|
, 0, NULL, {0,NULL}, 0, NULL, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supply signature for commitment tx
|
||||||
|
*/
|
||||||
|
struct _OpenCommitSig
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define OPEN_COMMIT_SIG__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Supply signature for anchor tx
|
||||||
|
*/
|
||||||
|
struct _OpenAnchorSig
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define OPEN_ANCHOR_SIG__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&open_anchor_sig__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Indicates we've seen transaction reach min-depth.
|
||||||
|
*/
|
||||||
|
struct _OpenComplete
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* Block it went into.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FIXME: add a merkle proof plus block headers here?
|
||||||
|
*/
|
||||||
|
Sha256Hash *blockid;
|
||||||
|
};
|
||||||
|
#define OPEN_COMPLETE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&open_complete__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let's spend some money in the channel!
|
||||||
|
*/
|
||||||
|
struct _Update
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* Hash for which I will supply preimage to revoke this.
|
||||||
|
*/
|
||||||
|
Sha256Hash *revocation_hash;
|
||||||
|
/*
|
||||||
|
* Change in current payment to-me (implies reverse to-you).
|
||||||
|
*/
|
||||||
|
int64_t delta;
|
||||||
|
/*
|
||||||
|
* Signature for new commitment tx.
|
||||||
|
*/
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
/*
|
||||||
|
* Signature for old anchor (if any)
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* FIXME: optional HTLC ops.
|
||||||
|
*/
|
||||||
|
BitcoinSignature *old_anchor_sig;
|
||||||
|
};
|
||||||
|
#define UPDATE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&update__descriptor) \
|
||||||
|
, NULL, 0, NULL, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OK, I accept that update.
|
||||||
|
*/
|
||||||
|
struct _UpdateAccept
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* Signature for new commitment tx.
|
||||||
|
*/
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
/*
|
||||||
|
* Signature for old anchor (if any)
|
||||||
|
*/
|
||||||
|
BitcoinSignature *old_anchor_sig;
|
||||||
|
/*
|
||||||
|
* Hash preimage which revokes old commitment tx.
|
||||||
|
*/
|
||||||
|
Sha256Hash *revocation_preimage;
|
||||||
|
};
|
||||||
|
#define UPDATE_ACCEPT__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \
|
||||||
|
, NULL, NULL, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complete the update.
|
||||||
|
*/
|
||||||
|
struct _UpdateComplete
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* Hash preimage which revokes old commitment tx.
|
||||||
|
*/
|
||||||
|
Sha256Hash *revocation_preimage;
|
||||||
|
};
|
||||||
|
#define UPDATE_COMPLETE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&update_complete__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Let's change the channel funding source.
|
||||||
|
*/
|
||||||
|
struct _NewAnchor
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* The new anchor: previous anchor 2x2 input assumed.
|
||||||
|
*/
|
||||||
|
Anchor *anchor;
|
||||||
|
};
|
||||||
|
#define NEW_ANCHOR__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* That seems OK to me!
|
||||||
|
*/
|
||||||
|
struct _NewAnchorAck
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define NEW_ANCHOR_ACK__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_ack__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here's my signature on the new anchor to complete it.
|
||||||
|
*/
|
||||||
|
struct _NewAnchorAccept
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define NEW_ANCHOR_ACCEPT__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_accept__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Complete the transfer to new anchor (both ends need to send this,
|
||||||
|
* once they're happy that it's reached their required depth).
|
||||||
|
*/
|
||||||
|
struct _NewAnchorComplete
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
Sha256Hash *revocation_preimage;
|
||||||
|
};
|
||||||
|
#define NEW_ANCHOR_COMPLETE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_complete__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Begin cooperative close of channel.
|
||||||
|
*/
|
||||||
|
struct _CloseChannel
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* This is our signature a new transaction which spends my current
|
||||||
|
* commitment tx output 0 (which is 2/2) to script_to_me.
|
||||||
|
*/
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define CLOSE_CHANNEL__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OK, here's my sig so you can broadcast it too.
|
||||||
|
*/
|
||||||
|
struct _CloseChannelComplete
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
/*
|
||||||
|
* This is our signature a new transaction which spends your current
|
||||||
|
* commitment tx output 0 (which is 2/2) to your script_to_me.
|
||||||
|
*/
|
||||||
|
BitcoinSignature *sig;
|
||||||
|
};
|
||||||
|
#define CLOSE_CHANNEL_COMPLETE__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This means we're going to hang up; it's to help diagnose only!
|
||||||
|
*/
|
||||||
|
struct _Error
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
char *problem;
|
||||||
|
};
|
||||||
|
#define ERROR__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&error__descriptor) \
|
||||||
|
, NULL }
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PKT__PKT__NOT_SET = 0,
|
||||||
|
PKT__PKT_OPEN = 201,
|
||||||
|
PKT__PKT_OPEN_COMMIT_SIG = 202,
|
||||||
|
PKT__PKT_OPEN_ANCHOR_SIG = 203,
|
||||||
|
PKT__PKT_OPEN_COMPLETE = 204,
|
||||||
|
PKT__PKT_UPDATE = 1,
|
||||||
|
PKT__PKT_UPDATE_ACCEPT = 2,
|
||||||
|
PKT__PKT_UPDATE_COMPLETE = 3,
|
||||||
|
PKT__PKT_NEW_ANCHOR = 301,
|
||||||
|
PKT__PKT_NEW_ANCHOR_ACK = 302,
|
||||||
|
PKT__PKT_NEW_ANCHOR_ACCEPT = 303,
|
||||||
|
PKT__PKT_NEW_ANCHOR_COMPLETE = 304,
|
||||||
|
PKT__PKT_CLOSE = 401,
|
||||||
|
PKT__PKT_CLOSE_COMPLETE = 402,
|
||||||
|
PKT__PKT_ERROR = 1000,
|
||||||
|
} Pkt__PktCase;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the union which defines all of them
|
||||||
|
*/
|
||||||
|
struct _Pkt
|
||||||
|
{
|
||||||
|
ProtobufCMessage base;
|
||||||
|
Pkt__PktCase pkt_case;
|
||||||
|
union {
|
||||||
|
/*
|
||||||
|
* Opening
|
||||||
|
*/
|
||||||
|
OpenChannel *open;
|
||||||
|
OpenCommitSig *open_commit_sig;
|
||||||
|
OpenAnchorSig *open_anchor_sig;
|
||||||
|
OpenComplete *open_complete;
|
||||||
|
/*
|
||||||
|
* Updating (most common)
|
||||||
|
*/
|
||||||
|
Update *update;
|
||||||
|
UpdateAccept *update_accept;
|
||||||
|
UpdateComplete *update_complete;
|
||||||
|
/*
|
||||||
|
* Topping up
|
||||||
|
*/
|
||||||
|
NewAnchor *new_anchor;
|
||||||
|
NewAnchorAck *new_anchor_ack;
|
||||||
|
NewAnchorAccept *new_anchor_accept;
|
||||||
|
NewAnchorComplete *new_anchor_complete;
|
||||||
|
/*
|
||||||
|
* Closing
|
||||||
|
*/
|
||||||
|
CloseChannel *close;
|
||||||
|
CloseChannelComplete *close_complete;
|
||||||
|
/*
|
||||||
|
* Unexpected issue.
|
||||||
|
*/
|
||||||
|
Error *error;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
#define PKT__INIT \
|
||||||
|
{ PROTOBUF_C_MESSAGE_INIT (&pkt__descriptor) \
|
||||||
|
, PKT__PKT__NOT_SET, {} }
|
||||||
|
|
||||||
|
|
||||||
|
/* Sha256Hash methods */
|
||||||
|
void sha256_hash__init
|
||||||
|
(Sha256Hash *message);
|
||||||
|
size_t sha256_hash__get_packed_size
|
||||||
|
(const Sha256Hash *message);
|
||||||
|
size_t sha256_hash__pack
|
||||||
|
(const Sha256Hash *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t sha256_hash__pack_to_buffer
|
||||||
|
(const Sha256Hash *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
Sha256Hash *
|
||||||
|
sha256_hash__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void sha256_hash__free_unpacked
|
||||||
|
(Sha256Hash *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* BitcoinOutputId methods */
|
||||||
|
void bitcoin_output_id__init
|
||||||
|
(BitcoinOutputId *message);
|
||||||
|
size_t bitcoin_output_id__get_packed_size
|
||||||
|
(const BitcoinOutputId *message);
|
||||||
|
size_t bitcoin_output_id__pack
|
||||||
|
(const BitcoinOutputId *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t bitcoin_output_id__pack_to_buffer
|
||||||
|
(const BitcoinOutputId *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
BitcoinOutputId *
|
||||||
|
bitcoin_output_id__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void bitcoin_output_id__free_unpacked
|
||||||
|
(BitcoinOutputId *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* BitcoinOutput methods */
|
||||||
|
void bitcoin_output__init
|
||||||
|
(BitcoinOutput *message);
|
||||||
|
size_t bitcoin_output__get_packed_size
|
||||||
|
(const BitcoinOutput *message);
|
||||||
|
size_t bitcoin_output__pack
|
||||||
|
(const BitcoinOutput *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t bitcoin_output__pack_to_buffer
|
||||||
|
(const BitcoinOutput *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
BitcoinOutput *
|
||||||
|
bitcoin_output__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void bitcoin_output__free_unpacked
|
||||||
|
(BitcoinOutput *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* BitcoinSignature methods */
|
||||||
|
void bitcoin_signature__init
|
||||||
|
(BitcoinSignature *message);
|
||||||
|
size_t bitcoin_signature__get_packed_size
|
||||||
|
(const BitcoinSignature *message);
|
||||||
|
size_t bitcoin_signature__pack
|
||||||
|
(const BitcoinSignature *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t bitcoin_signature__pack_to_buffer
|
||||||
|
(const BitcoinSignature *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
BitcoinSignature *
|
||||||
|
bitcoin_signature__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void bitcoin_signature__free_unpacked
|
||||||
|
(BitcoinSignature *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* Anchor methods */
|
||||||
|
void anchor__init
|
||||||
|
(Anchor *message);
|
||||||
|
size_t anchor__get_packed_size
|
||||||
|
(const Anchor *message);
|
||||||
|
size_t anchor__pack
|
||||||
|
(const Anchor *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t anchor__pack_to_buffer
|
||||||
|
(const Anchor *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
Anchor *
|
||||||
|
anchor__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void anchor__free_unpacked
|
||||||
|
(Anchor *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* OpenChannel methods */
|
||||||
|
void open_channel__init
|
||||||
|
(OpenChannel *message);
|
||||||
|
size_t open_channel__get_packed_size
|
||||||
|
(const OpenChannel *message);
|
||||||
|
size_t open_channel__pack
|
||||||
|
(const OpenChannel *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t open_channel__pack_to_buffer
|
||||||
|
(const OpenChannel *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
OpenChannel *
|
||||||
|
open_channel__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void open_channel__free_unpacked
|
||||||
|
(OpenChannel *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* OpenCommitSig methods */
|
||||||
|
void open_commit_sig__init
|
||||||
|
(OpenCommitSig *message);
|
||||||
|
size_t open_commit_sig__get_packed_size
|
||||||
|
(const OpenCommitSig *message);
|
||||||
|
size_t open_commit_sig__pack
|
||||||
|
(const OpenCommitSig *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t open_commit_sig__pack_to_buffer
|
||||||
|
(const OpenCommitSig *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
OpenCommitSig *
|
||||||
|
open_commit_sig__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void open_commit_sig__free_unpacked
|
||||||
|
(OpenCommitSig *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* OpenAnchorSig methods */
|
||||||
|
void open_anchor_sig__init
|
||||||
|
(OpenAnchorSig *message);
|
||||||
|
size_t open_anchor_sig__get_packed_size
|
||||||
|
(const OpenAnchorSig *message);
|
||||||
|
size_t open_anchor_sig__pack
|
||||||
|
(const OpenAnchorSig *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t open_anchor_sig__pack_to_buffer
|
||||||
|
(const OpenAnchorSig *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
OpenAnchorSig *
|
||||||
|
open_anchor_sig__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void open_anchor_sig__free_unpacked
|
||||||
|
(OpenAnchorSig *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* OpenComplete methods */
|
||||||
|
void open_complete__init
|
||||||
|
(OpenComplete *message);
|
||||||
|
size_t open_complete__get_packed_size
|
||||||
|
(const OpenComplete *message);
|
||||||
|
size_t open_complete__pack
|
||||||
|
(const OpenComplete *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t open_complete__pack_to_buffer
|
||||||
|
(const OpenComplete *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
OpenComplete *
|
||||||
|
open_complete__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void open_complete__free_unpacked
|
||||||
|
(OpenComplete *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* Update methods */
|
||||||
|
void update__init
|
||||||
|
(Update *message);
|
||||||
|
size_t update__get_packed_size
|
||||||
|
(const Update *message);
|
||||||
|
size_t update__pack
|
||||||
|
(const Update *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t update__pack_to_buffer
|
||||||
|
(const Update *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
Update *
|
||||||
|
update__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void update__free_unpacked
|
||||||
|
(Update *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* UpdateAccept methods */
|
||||||
|
void update_accept__init
|
||||||
|
(UpdateAccept *message);
|
||||||
|
size_t update_accept__get_packed_size
|
||||||
|
(const UpdateAccept *message);
|
||||||
|
size_t update_accept__pack
|
||||||
|
(const UpdateAccept *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t update_accept__pack_to_buffer
|
||||||
|
(const UpdateAccept *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
UpdateAccept *
|
||||||
|
update_accept__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void update_accept__free_unpacked
|
||||||
|
(UpdateAccept *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* UpdateComplete methods */
|
||||||
|
void update_complete__init
|
||||||
|
(UpdateComplete *message);
|
||||||
|
size_t update_complete__get_packed_size
|
||||||
|
(const UpdateComplete *message);
|
||||||
|
size_t update_complete__pack
|
||||||
|
(const UpdateComplete *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t update_complete__pack_to_buffer
|
||||||
|
(const UpdateComplete *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
UpdateComplete *
|
||||||
|
update_complete__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void update_complete__free_unpacked
|
||||||
|
(UpdateComplete *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* NewAnchor methods */
|
||||||
|
void new_anchor__init
|
||||||
|
(NewAnchor *message);
|
||||||
|
size_t new_anchor__get_packed_size
|
||||||
|
(const NewAnchor *message);
|
||||||
|
size_t new_anchor__pack
|
||||||
|
(const NewAnchor *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t new_anchor__pack_to_buffer
|
||||||
|
(const NewAnchor *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
NewAnchor *
|
||||||
|
new_anchor__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void new_anchor__free_unpacked
|
||||||
|
(NewAnchor *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* NewAnchorAck methods */
|
||||||
|
void new_anchor_ack__init
|
||||||
|
(NewAnchorAck *message);
|
||||||
|
size_t new_anchor_ack__get_packed_size
|
||||||
|
(const NewAnchorAck *message);
|
||||||
|
size_t new_anchor_ack__pack
|
||||||
|
(const NewAnchorAck *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t new_anchor_ack__pack_to_buffer
|
||||||
|
(const NewAnchorAck *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
NewAnchorAck *
|
||||||
|
new_anchor_ack__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void new_anchor_ack__free_unpacked
|
||||||
|
(NewAnchorAck *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* NewAnchorAccept methods */
|
||||||
|
void new_anchor_accept__init
|
||||||
|
(NewAnchorAccept *message);
|
||||||
|
size_t new_anchor_accept__get_packed_size
|
||||||
|
(const NewAnchorAccept *message);
|
||||||
|
size_t new_anchor_accept__pack
|
||||||
|
(const NewAnchorAccept *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t new_anchor_accept__pack_to_buffer
|
||||||
|
(const NewAnchorAccept *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
NewAnchorAccept *
|
||||||
|
new_anchor_accept__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void new_anchor_accept__free_unpacked
|
||||||
|
(NewAnchorAccept *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* NewAnchorComplete methods */
|
||||||
|
void new_anchor_complete__init
|
||||||
|
(NewAnchorComplete *message);
|
||||||
|
size_t new_anchor_complete__get_packed_size
|
||||||
|
(const NewAnchorComplete *message);
|
||||||
|
size_t new_anchor_complete__pack
|
||||||
|
(const NewAnchorComplete *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t new_anchor_complete__pack_to_buffer
|
||||||
|
(const NewAnchorComplete *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
NewAnchorComplete *
|
||||||
|
new_anchor_complete__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void new_anchor_complete__free_unpacked
|
||||||
|
(NewAnchorComplete *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* CloseChannel methods */
|
||||||
|
void close_channel__init
|
||||||
|
(CloseChannel *message);
|
||||||
|
size_t close_channel__get_packed_size
|
||||||
|
(const CloseChannel *message);
|
||||||
|
size_t close_channel__pack
|
||||||
|
(const CloseChannel *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t close_channel__pack_to_buffer
|
||||||
|
(const CloseChannel *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
CloseChannel *
|
||||||
|
close_channel__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void close_channel__free_unpacked
|
||||||
|
(CloseChannel *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* CloseChannelComplete methods */
|
||||||
|
void close_channel_complete__init
|
||||||
|
(CloseChannelComplete *message);
|
||||||
|
size_t close_channel_complete__get_packed_size
|
||||||
|
(const CloseChannelComplete *message);
|
||||||
|
size_t close_channel_complete__pack
|
||||||
|
(const CloseChannelComplete *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t close_channel_complete__pack_to_buffer
|
||||||
|
(const CloseChannelComplete *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
CloseChannelComplete *
|
||||||
|
close_channel_complete__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void close_channel_complete__free_unpacked
|
||||||
|
(CloseChannelComplete *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* Error methods */
|
||||||
|
void error__init
|
||||||
|
(Error *message);
|
||||||
|
size_t error__get_packed_size
|
||||||
|
(const Error *message);
|
||||||
|
size_t error__pack
|
||||||
|
(const Error *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t error__pack_to_buffer
|
||||||
|
(const Error *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
Error *
|
||||||
|
error__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void error__free_unpacked
|
||||||
|
(Error *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* Pkt methods */
|
||||||
|
void pkt__init
|
||||||
|
(Pkt *message);
|
||||||
|
size_t pkt__get_packed_size
|
||||||
|
(const Pkt *message);
|
||||||
|
size_t pkt__pack
|
||||||
|
(const Pkt *message,
|
||||||
|
uint8_t *out);
|
||||||
|
size_t pkt__pack_to_buffer
|
||||||
|
(const Pkt *message,
|
||||||
|
ProtobufCBuffer *buffer);
|
||||||
|
Pkt *
|
||||||
|
pkt__unpack
|
||||||
|
(ProtobufCAllocator *allocator,
|
||||||
|
size_t len,
|
||||||
|
const uint8_t *data);
|
||||||
|
void pkt__free_unpacked
|
||||||
|
(Pkt *message,
|
||||||
|
ProtobufCAllocator *allocator);
|
||||||
|
/* --- per-message closures --- */
|
||||||
|
|
||||||
|
typedef void (*Sha256Hash_Closure)
|
||||||
|
(const Sha256Hash *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*BitcoinOutputId_Closure)
|
||||||
|
(const BitcoinOutputId *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*BitcoinOutput_Closure)
|
||||||
|
(const BitcoinOutput *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*BitcoinSignature_Closure)
|
||||||
|
(const BitcoinSignature *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*Anchor_Closure)
|
||||||
|
(const Anchor *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*OpenChannel_Closure)
|
||||||
|
(const OpenChannel *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*OpenCommitSig_Closure)
|
||||||
|
(const OpenCommitSig *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*OpenAnchorSig_Closure)
|
||||||
|
(const OpenAnchorSig *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*OpenComplete_Closure)
|
||||||
|
(const OpenComplete *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*Update_Closure)
|
||||||
|
(const Update *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*UpdateAccept_Closure)
|
||||||
|
(const UpdateAccept *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*UpdateComplete_Closure)
|
||||||
|
(const UpdateComplete *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*NewAnchor_Closure)
|
||||||
|
(const NewAnchor *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*NewAnchorAck_Closure)
|
||||||
|
(const NewAnchorAck *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*NewAnchorAccept_Closure)
|
||||||
|
(const NewAnchorAccept *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*NewAnchorComplete_Closure)
|
||||||
|
(const NewAnchorComplete *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*CloseChannel_Closure)
|
||||||
|
(const CloseChannel *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*CloseChannelComplete_Closure)
|
||||||
|
(const CloseChannelComplete *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*Error_Closure)
|
||||||
|
(const Error *message,
|
||||||
|
void *closure_data);
|
||||||
|
typedef void (*Pkt_Closure)
|
||||||
|
(const Pkt *message,
|
||||||
|
void *closure_data);
|
||||||
|
|
||||||
|
/* --- services --- */
|
||||||
|
|
||||||
|
|
||||||
|
/* --- descriptors --- */
|
||||||
|
|
||||||
|
extern const ProtobufCMessageDescriptor sha256_hash__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor bitcoin_output_id__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor bitcoin_output__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor bitcoin_signature__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor anchor__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor open_channel__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor open_commit_sig__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor open_anchor_sig__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor open_complete__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor update__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor update_accept__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor update_complete__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor new_anchor__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor new_anchor_ack__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor new_anchor_accept__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor new_anchor_complete__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor close_channel__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor close_channel_complete__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor error__descriptor;
|
||||||
|
extern const ProtobufCMessageDescriptor pkt__descriptor;
|
||||||
|
|
||||||
|
PROTOBUF_C__END_DECLS
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PROTOBUF_C_lightning_2eproto__INCLUDED */
|
181
lightning.proto
Normal file
181
lightning.proto
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
// The outer layer handles encryption, authentication and message
|
||||||
|
// boundaries.
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helper Types
|
||||||
|
//
|
||||||
|
|
||||||
|
// Protobufs don't have fixed-length fields, so this is a hack.
|
||||||
|
message sha256_hash {
|
||||||
|
required fixed64 a = 1;
|
||||||
|
required fixed64 b = 2;
|
||||||
|
required fixed64 c = 3;
|
||||||
|
required fixed64 d = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identifies a bitcoin output.
|
||||||
|
message bitcoin_output_id {
|
||||||
|
// This is the transaction ID.
|
||||||
|
required sha256_hash txid = 1;
|
||||||
|
// This is the output number.
|
||||||
|
required uint32 output = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A bitcoin output
|
||||||
|
message bitcoin_output {
|
||||||
|
required uint64 amount = 1;
|
||||||
|
required bytes script = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A signature to use for a transaction; DER encoded with sigtype at the end.
|
||||||
|
message bitcoin_signature {
|
||||||
|
required bytes der_then_sigtype = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// All about an anchor transaction.
|
||||||
|
message anchor {
|
||||||
|
// 0 or more unspent inputs we want to use for anchor.
|
||||||
|
repeated bitcoin_output_id inputs = 1;
|
||||||
|
// Any change from anchor (in case we don't want to use them all)
|
||||||
|
optional bitcoin_output anchor_change = 2;
|
||||||
|
// How much transaction fee we'll pay in the anchor tx.
|
||||||
|
required uint64 fee = 8;
|
||||||
|
// How many confirmations on anchor before we'll use channel.
|
||||||
|
required uint32 min_confirms = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Packet Types
|
||||||
|
//
|
||||||
|
|
||||||
|
// Set channel params.
|
||||||
|
message open_channel {
|
||||||
|
// Seed which sets order we create outputs for all transactions.
|
||||||
|
required uint64 seed = 1;
|
||||||
|
// Relative locktime for outputs going to us.
|
||||||
|
oneof locktime {
|
||||||
|
uint32 locktime_seconds = 2;
|
||||||
|
uint32 locktime_blocks = 3;
|
||||||
|
}
|
||||||
|
// Hash seed for revoking commitment transactions.
|
||||||
|
required sha256_hash revocation_hash = 4;
|
||||||
|
// How to pay money to us.
|
||||||
|
required bytes script_to_me = 5;
|
||||||
|
// How much transaction fee we'll pay for commitment txs.
|
||||||
|
required uint64 commitment_fee = 6;
|
||||||
|
// The anchor transaction details.
|
||||||
|
required anchor anchor = 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supply signature for commitment tx
|
||||||
|
message open_commit_sig {
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Supply signature for anchor tx
|
||||||
|
message open_anchor_sig {
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicates we've seen transaction reach min-depth.
|
||||||
|
message open_complete {
|
||||||
|
// Block it went into.
|
||||||
|
optional sha256_hash blockid = 1;
|
||||||
|
// FIXME: add a merkle proof plus block headers here?
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's spend some money in the channel!
|
||||||
|
message update {
|
||||||
|
// Hash for which I will supply preimage to revoke this.
|
||||||
|
required sha256_hash revocation_hash = 1;
|
||||||
|
// Change in current payment to-me (implies reverse to-you).
|
||||||
|
required sint64 delta = 2;
|
||||||
|
// Signature for new commitment tx.
|
||||||
|
required bitcoin_signature sig = 3;
|
||||||
|
// Signature for old anchor (if any)
|
||||||
|
optional bitcoin_signature old_anchor_sig = 4;
|
||||||
|
// FIXME: optional HTLC ops.
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, I accept that update.
|
||||||
|
message update_accept {
|
||||||
|
// Signature for new commitment tx.
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
// Signature for old anchor (if any)
|
||||||
|
optional bitcoin_signature old_anchor_sig = 2;
|
||||||
|
// Hash preimage which revokes old commitment tx.
|
||||||
|
required sha256_hash revocation_preimage = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the update.
|
||||||
|
message update_complete {
|
||||||
|
// Hash preimage which revokes old commitment tx.
|
||||||
|
required sha256_hash revocation_preimage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's change the channel funding source.
|
||||||
|
message new_anchor {
|
||||||
|
// The new anchor: previous anchor 2x2 input assumed.
|
||||||
|
required anchor anchor = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// That seems OK to me!
|
||||||
|
message new_anchor_ack {
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Here's my signature on the new anchor to complete it.
|
||||||
|
message new_anchor_accept {
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Complete the transfer to new anchor (both ends need to send this,
|
||||||
|
// once they're happy that it's reached their required depth).
|
||||||
|
message new_anchor_complete {
|
||||||
|
required sha256_hash revocation_preimage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Begin cooperative close of channel.
|
||||||
|
message close_channel {
|
||||||
|
// This is our signature a new transaction which spends my current
|
||||||
|
// commitment tx output 0 (which is 2/2) to script_to_me.
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OK, here's my sig so you can broadcast it too.
|
||||||
|
message close_channel_complete {
|
||||||
|
// This is our signature a new transaction which spends your current
|
||||||
|
// commitment tx output 0 (which is 2/2) to your script_to_me.
|
||||||
|
required bitcoin_signature sig = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This means we're going to hang up; it's to help diagnose only!
|
||||||
|
message error {
|
||||||
|
optional string problem = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the union which defines all of them
|
||||||
|
message pkt {
|
||||||
|
oneof pkt {
|
||||||
|
// Opening
|
||||||
|
open_channel open = 201;
|
||||||
|
open_commit_sig open_commit_sig = 202;
|
||||||
|
open_anchor_sig open_anchor_sig = 203;
|
||||||
|
open_complete open_complete = 204;
|
||||||
|
// Updating (most common)
|
||||||
|
update update = 1;
|
||||||
|
update_accept update_accept = 2;
|
||||||
|
update_complete update_complete = 3;
|
||||||
|
// Topping up
|
||||||
|
new_anchor new_anchor = 301;
|
||||||
|
new_anchor_ack new_anchor_ack = 302;
|
||||||
|
new_anchor_accept new_anchor_accept = 303;
|
||||||
|
new_anchor_complete new_anchor_complete = 304;
|
||||||
|
// Closing
|
||||||
|
close_channel close = 401;
|
||||||
|
close_channel_complete close_complete = 402;
|
||||||
|
|
||||||
|
// Unexpected issue.
|
||||||
|
error error = 1000;
|
||||||
|
}
|
||||||
|
}
|
163
openchannel.c
Normal file
163
openchannel.c
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
#include <ccan/crypto/shachain/shachain.h>
|
||||||
|
#include <ccan/short_types/short_types.h>
|
||||||
|
#include <ccan/tal/tal.h>
|
||||||
|
#include <ccan/opt/opt.h>
|
||||||
|
#include <ccan/str/hex/hex.h>
|
||||||
|
#include <ccan/err/err.h>
|
||||||
|
#include <ccan/read_write_all/read_write_all.h>
|
||||||
|
#include "lightning.pb-c.h"
|
||||||
|
#include "base58.h"
|
||||||
|
#include "pkt.h"
|
||||||
|
#include <openssl/ec.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* Bitcoin nodes are allowed to be 2 hours in the future. */
|
||||||
|
#define LOCKTIME_MIN (2 * 60 * 60)
|
||||||
|
|
||||||
|
static char *opt_set_bits(const char *arg, u64 *satoshi)
|
||||||
|
{
|
||||||
|
unsigned long long ll;
|
||||||
|
char *ret = opt_set_ulonglongval_si(arg, &ll);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
*satoshi = ll * 100;
|
||||||
|
if (*satoshi / 100 != ll)
|
||||||
|
return "Invalid number of bits";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void opt_show_bits(char buf[OPT_SHOW_LEN], const u64 *bits)
|
||||||
|
{
|
||||||
|
unsigned long long ll = *bits / 100;
|
||||||
|
opt_show_ulonglongval_si(buf, &ll);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BitcoinOutputId *parse_anchor_input(const tal_t *ctx, const char *spec)
|
||||||
|
{
|
||||||
|
BitcoinOutputId *o = tal(ctx, BitcoinOutputId);
|
||||||
|
struct sha256 txid;
|
||||||
|
const char *slash;
|
||||||
|
char *end;
|
||||||
|
long l;
|
||||||
|
|
||||||
|
bitcoin_output_id__init(o);
|
||||||
|
|
||||||
|
slash = strchr(spec, '/');
|
||||||
|
if (!slash)
|
||||||
|
errx(1, "Expected / in <txid>/<outputnum>");
|
||||||
|
o->output = l = strtol(slash + 1, &end, 10);
|
||||||
|
if (end == slash + 1 || *end || (int64_t)o->output != (int64_t)l)
|
||||||
|
errx(1, "Expected <outputnum> after /");
|
||||||
|
|
||||||
|
if (!hex_decode(spec, slash - spec, &txid, sizeof(txid)))
|
||||||
|
errx(1, "Expected 256-bit hex txid before /");
|
||||||
|
|
||||||
|
o->txid = proto_sha256_hash(o, &txid);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 *pay_to_pubkey(const tal_t *ctx, const struct bitcoin_address *addr)
|
||||||
|
{
|
||||||
|
u8 *script = tal_arr(ctx, u8, 2 + 20 + 2);
|
||||||
|
script[0] = 0x76; /* OP_DUP */
|
||||||
|
script[1] = 0xA9; /* OP_HASH160 */
|
||||||
|
memcpy(script+2, addr, 20);
|
||||||
|
script[22] = 0x88; /* OP_EQUALVERIFY */
|
||||||
|
script[23] = 0xAC; /* OP_CHECKSIG */
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: This is too weak, even for us! */
|
||||||
|
static u64 weak_random64(void)
|
||||||
|
{
|
||||||
|
return time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Simple helper to open a channel. */
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
struct sha256 seed, revocation_hash;
|
||||||
|
struct bitcoin_address ouraddr;
|
||||||
|
EC_KEY *privkey;
|
||||||
|
struct pkt *pkt;
|
||||||
|
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||||
|
Anchor anchor = ANCHOR__INIT;
|
||||||
|
u64 commit_tx_fee;
|
||||||
|
unsigned int locktime_seconds;
|
||||||
|
bool testnet;
|
||||||
|
struct bitcoin_compressed_pubkey pubkey;
|
||||||
|
u8 *script_to_me;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
err_set_progname(argv[0]);
|
||||||
|
|
||||||
|
/* Default values. */
|
||||||
|
anchor.min_confirms = 3;
|
||||||
|
/* Remember, other side contributes to fee, too. */
|
||||||
|
anchor.fee = 5000;
|
||||||
|
/* We only need this for involuntary close, so make it larger. */
|
||||||
|
commit_tx_fee = 100000;
|
||||||
|
/* This means we have ~1 day before they can steal our money. */
|
||||||
|
locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60;
|
||||||
|
|
||||||
|
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||||
|
"<seed> <privkey> <ouraddr> <txid>/<outnum>...\n"
|
||||||
|
"A test program to output openchannel on stdout.",
|
||||||
|
"Print this message.");
|
||||||
|
opt_register_arg("--min-anchor-confirms",
|
||||||
|
opt_set_uintval, opt_show_uintval, &anchor.min_confirms,
|
||||||
|
"Number of anchor confirmations before channel is active");
|
||||||
|
opt_register_arg("--anchor-fee=<bits>",
|
||||||
|
opt_set_bits, opt_show_bits, &anchor.fee,
|
||||||
|
"100's of satoshi to pay for anchor");
|
||||||
|
opt_register_arg("--commitment-fee=<bits>",
|
||||||
|
opt_set_bits, opt_show_bits, &commit_tx_fee,
|
||||||
|
"100's of satoshi to pay for commitment");
|
||||||
|
opt_register_arg("--locktime=<seconds>",
|
||||||
|
opt_set_uintval, opt_show_uintval, &locktime_seconds,
|
||||||
|
"Seconds to lock out our transaction redemption");
|
||||||
|
/* FIXME: Implement change address and amount. */
|
||||||
|
|
||||||
|
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||||
|
|
||||||
|
if (argc < 5)
|
||||||
|
opt_usage_and_exit(NULL);
|
||||||
|
|
||||||
|
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||||
|
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||||
|
|
||||||
|
privkey = key_from_base58(argv[2], strlen(argv[2]), &testnet, &pubkey);
|
||||||
|
if (!privkey)
|
||||||
|
errx(1, "Invalid private key '%s'", argv[2]);
|
||||||
|
if (!testnet)
|
||||||
|
errx(1, "Private key '%s' not a testnet key!", argv[2]);
|
||||||
|
|
||||||
|
if (!bitcoin_from_base58(&testnet, &ouraddr, argv[3], strlen(argv[3])))
|
||||||
|
errx(1, "Invalid bitcoin address '%s'", argv[3]);
|
||||||
|
if (!testnet)
|
||||||
|
errx(1, "Bitcoin address '%s' not on testnet!", argv[3]);
|
||||||
|
|
||||||
|
anchor.n_inputs = (argc - 4);
|
||||||
|
anchor.inputs = tal_arr(ctx, BitcoinOutputId *, anchor.n_inputs);
|
||||||
|
|
||||||
|
for (i = 0; i < anchor.n_inputs; i++)
|
||||||
|
anchor.inputs[i] = parse_anchor_input(anchor.inputs, argv[i+4]);
|
||||||
|
|
||||||
|
/* Get first revocation hash. */
|
||||||
|
shachain_from_seed(&seed, 0, &revocation_hash);
|
||||||
|
|
||||||
|
/* Make simple output script to pay to my pubkey. */
|
||||||
|
script_to_me = pay_to_pubkey(ctx, &ouraddr);
|
||||||
|
|
||||||
|
pkt = openchannel_pkt(ctx, weak_random64(), &revocation_hash,
|
||||||
|
tal_count(script_to_me), script_to_me,
|
||||||
|
commit_tx_fee, locktime_seconds, &anchor);
|
||||||
|
|
||||||
|
if (!write_all(STDOUT_FILENO, pkt,
|
||||||
|
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
|
||||||
|
err(1, "Writing out packet");
|
||||||
|
|
||||||
|
tal_free(ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
20
pd_channel.h
Normal file
20
pd_channel.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Poon-Dryja Generalized Channel Implementation.
|
||||||
|
*
|
||||||
|
* It's fairly symmetrical, but for clarity the api divides into
|
||||||
|
* client and server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Construct the inputs they want to use. */
|
||||||
|
struct input *pd_ask_anchor_inputs(void);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Client creates an unsigned transaction using their own funds: */
|
||||||
|
struct tx *client_anchor_tx(struct input *spend, u64 amount);
|
||||||
|
|
||||||
|
/* Then, from that we create an updatable commitment transaction,
|
||||||
|
* with two outputs (one is zero val). */
|
||||||
|
|
||||||
|
|
55
pkt.c
Normal file
55
pkt.c
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#include <ccan/crypto/sha256/sha256.h>
|
||||||
|
#include "pkt.h"
|
||||||
|
|
||||||
|
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
|
||||||
|
{
|
||||||
|
struct pkt *ret;
|
||||||
|
size_t len;
|
||||||
|
Pkt p = PKT__INIT;
|
||||||
|
|
||||||
|
p.pkt_case = type;
|
||||||
|
/* This is a union, so doesn't matter which we assign. */
|
||||||
|
p.error = msg;
|
||||||
|
|
||||||
|
len = pkt__get_packed_size(&p);
|
||||||
|
ret = (struct pkt *)tal_arr(ctx, u8, sizeof(ret->len) + len);
|
||||||
|
ret->len = cpu_to_le32(len);
|
||||||
|
pkt__pack(&p, ret->data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sha256Hash *proto_sha256_hash(const tal_t *ctx, const struct sha256 *hash)
|
||||||
|
{
|
||||||
|
Sha256Hash *h = tal(ctx, Sha256Hash);
|
||||||
|
sha256_hash__init(h);
|
||||||
|
|
||||||
|
/* Kill me now... */
|
||||||
|
memcpy(&h->a, hash->u.u8, 8);
|
||||||
|
memcpy(&h->b, hash->u.u8 + 8, 8);
|
||||||
|
memcpy(&h->c, hash->u.u8 + 16, 8);
|
||||||
|
memcpy(&h->d, hash->u.u8 + 24, 8);
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pkt *openchannel_pkt(const tal_t *ctx,
|
||||||
|
u64 seed,
|
||||||
|
const struct sha256 *revocation_hash,
|
||||||
|
size_t script_len,
|
||||||
|
const void *script,
|
||||||
|
u64 commitment_fee,
|
||||||
|
u32 rel_locktime_seconds,
|
||||||
|
Anchor *anchor)
|
||||||
|
{
|
||||||
|
OpenChannel o = OPEN_CHANNEL__INIT;
|
||||||
|
|
||||||
|
o.seed = seed;
|
||||||
|
o.revocation_hash = proto_sha256_hash(ctx, revocation_hash);
|
||||||
|
o.script_to_me.len = script_len;
|
||||||
|
o.script_to_me.data = (void *)script;
|
||||||
|
o.commitment_fee = commitment_fee;
|
||||||
|
o.anchor = anchor;
|
||||||
|
o.locktime_case = OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS;
|
||||||
|
o.locktime_seconds = rel_locktime_seconds;
|
||||||
|
|
||||||
|
return to_pkt(ctx, PKT__PKT_OPEN, &o);
|
||||||
|
}
|
44
pkt.h
Normal file
44
pkt.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#ifndef LIGHTNING_PKT_H
|
||||||
|
#define LIGHTNING_PKT_H
|
||||||
|
/* Simple (non-threadsafe!) wrapper for protobufs.
|
||||||
|
*
|
||||||
|
* This could be a simple set of macros, if the protobuf-c people hadn't
|
||||||
|
* insisted on "prettifing" the names they generate into CamelCase.
|
||||||
|
*/
|
||||||
|
#include "lightning.pb-c.h"
|
||||||
|
#include <ccan/endian/endian.h>
|
||||||
|
#include <ccan/short_types/short_types.h>
|
||||||
|
#include <ccan/tal/tal.h>
|
||||||
|
|
||||||
|
/* A packet, ready to be de-protobuf'ed. */
|
||||||
|
struct pkt {
|
||||||
|
le32 len;
|
||||||
|
u8 data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sha256;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tal_openchannel - create an openchannel message
|
||||||
|
* @ctx: tal context to allocate off.
|
||||||
|
* @seed: psuedo-random seed to shuffle inputs.
|
||||||
|
* @revocation_hash: first hash value generated from seed.
|
||||||
|
* @script_len, @script: the script which pays to us.
|
||||||
|
* @commitment_fee: the fee to use for commitment tx.
|
||||||
|
* @rel_locktime_seconds: relative seconds for commitment locktime.
|
||||||
|
* @anchor: the anchor transaction details.
|
||||||
|
*/
|
||||||
|
struct pkt *openchannel_pkt(const tal_t *ctx,
|
||||||
|
u64 seed,
|
||||||
|
const struct sha256 *revocation_hash,
|
||||||
|
size_t script_len,
|
||||||
|
const void *script,
|
||||||
|
u64 commitment_fee,
|
||||||
|
u32 rel_locktime_seconds,
|
||||||
|
Anchor *anchor);
|
||||||
|
|
||||||
|
|
||||||
|
/* Useful helper for allocating & populating a protobuf Sha256Hash */
|
||||||
|
Sha256Hash *proto_sha256_hash(const tal_t *ctx, const struct sha256 *hash);
|
||||||
|
|
||||||
|
#endif /* LIGHTNING_PKT_H */
|
13
shadouble.c
Normal file
13
shadouble.c
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#include "shadouble.h"
|
||||||
|
|
||||||
|
void sha256_double(struct sha256_double *shadouble, const void *p, size_t len)
|
||||||
|
{
|
||||||
|
sha256(&shadouble->sha, (unsigned char *)p, len);
|
||||||
|
sha256(&shadouble->sha, &shadouble->sha, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha256_double_done(struct sha256_ctx *sha256, struct sha256_double *res)
|
||||||
|
{
|
||||||
|
sha256_done(sha256, &res->sha);
|
||||||
|
sha256(&res->sha, &res->sha, 1);
|
||||||
|
}
|
14
shadouble.h
Normal file
14
shadouble.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef LIGHTNING_SHADOUBLE_H
|
||||||
|
#define LIGHTNING_SHADOUBLE_H
|
||||||
|
#include "config.h"
|
||||||
|
#include <ccan/crypto/sha256/sha256.h>
|
||||||
|
|
||||||
|
/* To explicitly distinguish between single sha and bitcoin's standard double */
|
||||||
|
struct sha256_double {
|
||||||
|
struct sha256 sha;
|
||||||
|
};
|
||||||
|
|
||||||
|
void sha256_double(struct sha256_double *shadouble, const void *p, size_t len);
|
||||||
|
|
||||||
|
void sha256_double_done(struct sha256_ctx *sha256, struct sha256_double *res);
|
||||||
|
#endif /* PETTYCOIN_SHADOUBLE_H */
|
Loading…
Reference in New Issue
Block a user