Rusty Russell
10 years ago
commit
1c4fdce514
13 changed files with 3953 additions and 0 deletions
@ -0,0 +1,3 @@ |
|||
*~ |
|||
*.o |
|||
openchannel |
@ -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 $@ $< |
|||
|
@ -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; |
|||
} |
@ -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 */ |
File diff suppressed because it is too large
@ -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 */ |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
} |
@ -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). */ |
|||
|
|||
|
@ -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); |
|||
} |
@ -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 */ |
@ -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); |
|||
} |
@ -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