open-anchor-sig, many fixes for open-channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2015-05-29 07:08:27 +09:30
parent c46842e0ba
commit 670670f138
22 changed files with 1638 additions and 202 deletions

View File

@ -3,37 +3,44 @@
# Needs to have oneof support: Ubuntu vivid's is too old :(
PROTOCC:=protoc-c
PROGRAMS := open-channel
PROGRAMS := open-channel open-anchor-sig
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
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o perturb.o signature.o bitcoin_tx.o bitcoin_address.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 ccan-tal-grab_file.o ccan-noerr.o
OPEN_CHANNEL_OBJS := open-channel.o $(HELPER_OBJS) $(CCAN_OBJS)
OPEN_CHANNEL_OBJS := open-channel.o
OPEN_ANCHOR_SIG_OBJS := open-anchor-sig.o
HEADERS := base58.h lightning.pb-c.h pd_channel.h pkt.h shadouble.h
HEADERS := $(wildcard *.h)
CCANDIR := ../ccan/
CFLAGS := -g -Wall -I $(CCANDIR) #-I $(PROTO_INCLUDE_DIR)
LDLIBS := -lcrypto -lprotobuf-c
default: open-channel
default: $(PROGRAMS)
lightning.pb-c.c lightning.pb-c.h: lightning.proto
$(PROTOCC) lightning.proto --c_out=.
open-channel: $(OPEN_CHANNEL_OBJS)
open-channel: $(OPEN_CHANNEL_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
$(OPEN_CHANNEL_OBJS): $(HEADERS)
open-anchor-sig: $(OPEN_ANCHOR_SIG_OBJS) $(HELPER_OBJS) $(CCAN_OBJS)
$(OPEN_ANCHOR_SIG_OBJS): $(HEADERS)
distclean: clean
$(RM) lightning.pb-c.c lightning.pb-c.h
clean:
$(RM) $(OPEN_CHANNEL_OBJS)
$(RM) $(PROGRAMS)
$(RM) $(OPEN_CHANNEL_OBJS) $(OPEN_ANCHOR_SIG_OBJS) $(HELPER_OBJS) $(CCAN_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-tal-grab_file.o: $(CCANDIR)/ccan/tal/grab_file/grab_file.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
@ -52,6 +59,8 @@ 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-noerr.o: $(CCANDIR)/ccan/noerr/noerr.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

View File

@ -8,6 +8,7 @@
#include <openssl/ripemd.h>
#include <stdbool.h>
#include <stdlib.h>
#include "bitcoin_address.h"
/* Encoding is version byte + ripemd160 + 4-byte checksum == 200 bits => 2^200.
*
@ -20,16 +21,6 @@
* 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);

11
bitcoin_address.c Normal file
View File

@ -0,0 +1,11 @@
#include "bitcoin_address.h"
#include <ccan/crypto/sha256/sha256.h>
void bitcoin_address(const struct bitcoin_compressed_pubkey *key,
struct bitcoin_address *addr)
{
struct sha256 h;
sha256(&h, key, sizeof(*key));
RIPEMD160(h.u.u8, sizeof(h), addr->addr);
}

18
bitcoin_address.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef LIGHTNING_BITCOIN_ADDRESS_H
#define LIGHTNING_BITCOIN_ADDRESS_H
#include <openssl/ripemd.h>
#include <ccan/short_types/short_types.h>
/* An address is the RIPEMD160 of the SHA of the public key. */
struct bitcoin_address {
u8 addr[RIPEMD160_DIGEST_LENGTH]; /* 20 */
};
/* An ECDSA compressed public key. 33 chars long, even on ARM. */
struct bitcoin_compressed_pubkey {
u8 key[33];
} __attribute__((aligned(1)));
void bitcoin_address(const struct bitcoin_compressed_pubkey *key,
struct bitcoin_address *addr);
#endif /* LIGHTNING_BITCOIN_ADDRESS_H */

161
bitcoin_script.c Normal file
View File

@ -0,0 +1,161 @@
#include "bitcoin_script.h"
#include "bitcoin_address.h"
#include <openssl/ripemd.h>
#include <ccan/endian/endian.h>
#include <ccan/crypto/sha256/sha256.h>
/* Some standard ops */
#define OP_PUSHBYTES(val) (val)
#define OP_LITERAL(val) (0x51 + (val))
#define OP_PUSHDATA1 0x4C
#define OP_PUSHDATA2 0x4D
#define OP_PUSHDATA4 0x4E
#define OP_NOP 0x61
#define OP_DUP 0x76
#define OP_EQUAL 0x87
#define OP_EQUALVERIFY 0x88
#define OP_CHECKSIG 0xAC
#define OP_CHECKMULTISIG 0xAE
#define OP_HASH160 0xA9
static void add(u8 **scriptp, const void *mem, size_t len)
{
size_t oldlen = tal_count(*scriptp);
tal_resize(scriptp, oldlen + len);
memcpy(*scriptp + oldlen, mem, len);
}
static void add_op(u8 **scriptp, u8 op)
{
add(scriptp, &op, 1);
}
static void add_push_bytes(u8 **scriptp, const void *mem, size_t len)
{
if (len < 76)
add_op(scriptp, OP_PUSHBYTES(len));
else if (len < 256) {
char c = len;
add_op(scriptp, OP_PUSHDATA1);
add(scriptp, &c, 1);
} else if (len < 65536) {
le16 v = cpu_to_le16(len);
add_op(scriptp, OP_PUSHDATA2);
add(scriptp, &v, 2);
} else {
le32 v = cpu_to_le32(len);
add_op(scriptp, OP_PUSHDATA4);
add(scriptp, &v, 4);
}
add(scriptp, mem, len);
}
/* FIXME: permute? */
/* Is a < b? (If equal we don't care) */
static bool key_less(const BitcoinPubkey *a, const BitcoinPubkey *b)
{
size_t len;
int cmp;
if (a->key.len < b->key.len)
len = a->key.len;
else
len = b->key.len;
cmp = memcmp(a->key.data, b->key.data, len);
if (cmp < 0)
return true;
else if (cmp > 0)
return false;
/* Corner case: if it's shorter, it's less. */
return a->key.len < b->key.len;
}
/* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_2of2(const tal_t *ctx,
const BitcoinPubkey *key1,
const BitcoinPubkey *key2)
{
u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_LITERAL(2));
if (key_less(key1, key2)) {
add_push_bytes(&script, key1->key.data, key1->key.len);
add_push_bytes(&script, key2->key.data, key2->key.len);
} else {
add_push_bytes(&script, key2->key.data, key2->key.len);
add_push_bytes(&script, key1->key.data, key1->key.len);
}
add_op(&script, OP_CHECKMULTISIG);
return script;
}
/* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_single(const tal_t *ctx, const u8 *key, size_t keylen)
{
u8 *script = tal_arr(ctx, u8, 0);
add_push_bytes(&script, key, keylen);
add_op(&script, OP_CHECKSIG);
return script;
}
/* Create p2sh for this redeem script. */
u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript)
{
struct sha256 h;
u8 redeemhash[RIPEMD160_DIGEST_LENGTH];
u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_HASH160);
sha256(&h, redeemscript, tal_count(redeemscript));
RIPEMD160(h.u.u8, sizeof(h), redeemhash);
add_push_bytes(&script, redeemhash, sizeof(redeemhash));
add_op(&script, OP_EQUAL);
return script;
}
u8 *scriptpubkey_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr)
{
u8 *script = tal_arr(ctx, u8, 0);
add_op(&script, OP_DUP);
add_op(&script, OP_HASH160);
add_push_bytes(&script, addr, sizeof(addr));
add_op(&script, OP_EQUALVERIFY);
add_op(&script, OP_CHECKSIG);
return script;
}
u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr,
const u8 *signature,
size_t sig_len)
{
u8 *script = tal_arr(ctx, u8, 0);
add_push_bytes(&script, signature, sig_len);
add_push_bytes(&script, addr, sizeof(*addr));
return script;
}
/* Is this a normal pay to pubkey hash? */
bool is_pay_to_pubkey_hash(const ProtobufCBinaryData *script)
{
if (script->len != 25)
return false;
if (script->data[0] != OP_DUP)
return false;
if (script->data[1] != OP_HASH160)
return false;
if (script->data[2] != OP_PUSHBYTES(20))
return false;
if (script->data[23] != OP_EQUALVERIFY)
return false;
if (script->data[24] != OP_CHECKSIG)
return false;
return true;
}

34
bitcoin_script.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef LIGHTNING_BITCOIN_SCRIPT_H
#define LIGHTNING_BITCOIN_SCRIPT_H
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include "lightning.pb-c.h"
struct bitcoin_address;
struct bitcoin_compressed_pubkey;
/* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_2of2(const tal_t *ctx,
const BitcoinPubkey *key1,
const BitcoinPubkey *key2);
/* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_single(const tal_t *ctx, const u8 *key, size_t keylen);
/* Create an output script using p2sh for this redeem script. */
u8 *scriptpubkey_p2sh(const tal_t *ctx, const u8 *redeemscript);
/* Create an output script to pay to pubkey hash */
u8 *scriptpubkey_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr);
/* Create an input script to accept pay to pubkey */
u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr,
const u8 *signature,
size_t sig_len);
/* Is this a normal pay to pubkey hash? */
bool is_pay_to_pubkey_hash(const ProtobufCBinaryData *script);
#endif /* LIGHTNING_BITCOIN_SCRIPT_H */

64
bitcoin_tx.c Normal file
View File

@ -0,0 +1,64 @@
#include "bitcoin_tx.h"
#include <ccan/crypto/sha256/sha256.h>
static void sha256_varint(struct sha256_ctx *ctx, varint_t v)
{
u8 buf[9], *p = buf;
if (v < 0xfd) {
*(p++) = v;
} else if (v <= 0xffff) {
(*p++) = 0xfd;
(*p++) = v >> 8;
(*p++) = v;
} else if (v <= 0xffffffff) {
(*p++) = 0xfe;
(*p++) = v >> 24;
(*p++) = v >> 16;
(*p++) = v >> 8;
(*p++) = v;
} else {
(*p++) = 0xff;
(*p++) = v >> 56;
(*p++) = v >> 48;
(*p++) = v >> 40;
(*p++) = v >> 32;
(*p++) = v >> 24;
(*p++) = v >> 16;
(*p++) = v >> 8;
(*p++) = v;
}
sha256_update(ctx, buf, p - buf);
}
static void sha256_tx_input(struct sha256_ctx *ctx,
const struct bitcoin_tx_input *input)
{
sha256_update(ctx, &input->txid, sizeof(input->txid));
sha256_le32(ctx, input->index);
sha256_varint(ctx, input->script_length);
sha256_update(ctx, input->script, input->script_length);
sha256_le32(ctx, input->sequence_number);
}
static void sha256_tx_output(struct sha256_ctx *ctx,
const struct bitcoin_tx_output *output)
{
sha256_le64(ctx, output->amount);
sha256_varint(ctx, output->script_length);
sha256_update(ctx, output->script, output->script_length);
}
void sha256_tx(struct sha256_ctx *ctx, const struct bitcoin_tx *tx)
{
varint_t i;
sha256_le32(ctx, tx->version);
sha256_varint(ctx, tx->input_count);
for (i = 0; i < tx->input_count; i++)
sha256_tx_input(ctx, &tx->input[i]);
sha256_varint(ctx, tx->output_count);
for (i = 0; i < tx->output_count; i++)
sha256_tx_output(ctx, &tx->output[i]);
sha256_le32(ctx, tx->lock_time);
}

38
bitcoin_tx.h Normal file
View File

@ -0,0 +1,38 @@
#ifndef LIGHTNING_BITCOIN_TX_H
#define LIGHTNING_BITCOIN_TX_H
#include <ccan/short_types/short_types.h>
#include "shadouble.h"
#define BITCOIN_TX_VERSION 1
/* We unpack varints for our in-memory representation */
#define varint_t u64
struct bitcoin_tx {
u32 version;
varint_t input_count;
struct bitcoin_tx_input *input;
varint_t output_count;
struct bitcoin_tx_output *output;
u32 lock_time;
};
struct bitcoin_tx_output {
u64 amount;
varint_t script_length;
u8 *script;
};
struct bitcoin_tx_input {
struct sha256_double txid;
u32 index; /* output number referred to by above */
varint_t script_length;
u8 *script;
u32 sequence_number;
};
/* Linearize the tx. This is good for deriving the txid, as well as the
* signature. */
void sha256_tx(struct sha256_ctx *shactx, const struct bitcoin_tx *tx);
#endif /* LIGHTNING_BITCOIN_TX_H */

35
getinput.sh Executable file
View File

@ -0,0 +1,35 @@
#! /bin/sh
# Query bitcoind to get (first) unspent output to spend.
###
# Nobody should *EVER* write code like this. EVER!!
###
set -e
if [ n"$1" = n--privkey ]; then
KEY=1
shift
fi
NUM=1
if [ $# = 1 ]; then
NUM=$1
shift
fi
if [ $# -gt 0 ]; then
echo "Usage: getinput.sh [--privkey] [INPUT-INDEX]"
exit 1
fi
if [ -n "$KEY" ]; then
ADDR=`bitcoin-cli -testnet listunspent | sed -n 's/^ "address" : "\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1`
bitcoin-cli dumpprivkey $ADDR
else
TXID=`bitcoin-cli -testnet listunspent | sed -n 's/^ "txid" : "\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
OUTNUM=`bitcoin-cli -testnet listunspent | sed -n 's/^ "vout" : \([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1`
AMOUNT=`bitcoin-cli -testnet listunspent | sed -n 's/^ "amount" : \([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'`
SCRIPT=`bitcoin-cli -testnet listunspent | sed -n 's/^ "scriptPubKey" : "\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT
fi

View File

@ -50,47 +50,47 @@ void sha256_hash__free_unpacked
assert(message->base.descriptor == &sha256_hash__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_output_id__init
(BitcoinOutputId *message)
void bitcoin_input__init
(BitcoinInput *message)
{
static BitcoinOutputId init_value = BITCOIN_OUTPUT_ID__INIT;
static BitcoinInput init_value = BITCOIN_INPUT__INIT;
*message = init_value;
}
size_t bitcoin_output_id__get_packed_size
(const BitcoinOutputId *message)
size_t bitcoin_input__get_packed_size
(const BitcoinInput *message)
{
assert(message->base.descriptor == &bitcoin_output_id__descriptor);
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t bitcoin_output_id__pack
(const BitcoinOutputId *message,
size_t bitcoin_input__pack
(const BitcoinInput *message,
uint8_t *out)
{
assert(message->base.descriptor == &bitcoin_output_id__descriptor);
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t bitcoin_output_id__pack_to_buffer
(const BitcoinOutputId *message,
size_t bitcoin_input__pack_to_buffer
(const BitcoinInput *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &bitcoin_output_id__descriptor);
assert(message->base.descriptor == &bitcoin_input__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
BitcoinOutputId *
bitcoin_output_id__unpack
BitcoinInput *
bitcoin_input__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (BitcoinOutputId *)
protobuf_c_message_unpack (&bitcoin_output_id__descriptor,
return (BitcoinInput *)
protobuf_c_message_unpack (&bitcoin_input__descriptor,
allocator, len, data);
}
void bitcoin_output_id__free_unpacked
(BitcoinOutputId *message,
void bitcoin_input__free_unpacked
(BitcoinInput *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &bitcoin_output_id__descriptor);
assert(message->base.descriptor == &bitcoin_input__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_output__init
@ -179,6 +179,49 @@ void bitcoin_signature__free_unpacked
assert(message->base.descriptor == &bitcoin_signature__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_pubkey__init
(BitcoinPubkey *message)
{
static BitcoinPubkey init_value = BITCOIN_PUBKEY__INIT;
*message = init_value;
}
size_t bitcoin_pubkey__get_packed_size
(const BitcoinPubkey *message)
{
assert(message->base.descriptor == &bitcoin_pubkey__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t bitcoin_pubkey__pack
(const BitcoinPubkey *message,
uint8_t *out)
{
assert(message->base.descriptor == &bitcoin_pubkey__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t bitcoin_pubkey__pack_to_buffer
(const BitcoinPubkey *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &bitcoin_pubkey__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
BitcoinPubkey *
bitcoin_pubkey__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (BitcoinPubkey *)
protobuf_c_message_unpack (&bitcoin_pubkey__descriptor,
allocator, len, data);
}
void bitcoin_pubkey__free_unpacked
(BitcoinPubkey *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &bitcoin_pubkey__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void anchor__init
(Anchor *message)
{
@ -351,6 +394,49 @@ void open_anchor_sig__free_unpacked
assert(message->base.descriptor == &open_anchor_sig__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void give_early_anchor_sig_and_pretend_we_didnt__init
(GiveEarlyAnchorSigAndPretendWeDidnt *message)
{
static GiveEarlyAnchorSigAndPretendWeDidnt init_value = GIVE_EARLY_ANCHOR_SIG_AND_PRETEND_WE_DIDNT__INIT;
*message = init_value;
}
size_t give_early_anchor_sig_and_pretend_we_didnt__get_packed_size
(const GiveEarlyAnchorSigAndPretendWeDidnt *message)
{
assert(message->base.descriptor == &give_early_anchor_sig_and_pretend_we_didnt__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t give_early_anchor_sig_and_pretend_we_didnt__pack
(const GiveEarlyAnchorSigAndPretendWeDidnt *message,
uint8_t *out)
{
assert(message->base.descriptor == &give_early_anchor_sig_and_pretend_we_didnt__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t give_early_anchor_sig_and_pretend_we_didnt__pack_to_buffer
(const GiveEarlyAnchorSigAndPretendWeDidnt *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &give_early_anchor_sig_and_pretend_we_didnt__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
GiveEarlyAnchorSigAndPretendWeDidnt *
give_early_anchor_sig_and_pretend_we_didnt__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (GiveEarlyAnchorSigAndPretendWeDidnt *)
protobuf_c_message_unpack (&give_early_anchor_sig_and_pretend_we_didnt__descriptor,
allocator, len, data);
}
void give_early_anchor_sig_and_pretend_we_didnt__free_unpacked
(GiveEarlyAnchorSigAndPretendWeDidnt *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &give_early_anchor_sig_and_pretend_we_didnt__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void open_complete__init
(OpenComplete *message)
{
@ -609,6 +695,49 @@ void new_anchor_ack__free_unpacked
assert(message->base.descriptor == &new_anchor_ack__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void new_anchor_commit_sig__init
(NewAnchorCommitSig *message)
{
static NewAnchorCommitSig init_value = NEW_ANCHOR_COMMIT_SIG__INIT;
*message = init_value;
}
size_t new_anchor_commit_sig__get_packed_size
(const NewAnchorCommitSig *message)
{
assert(message->base.descriptor == &new_anchor_commit_sig__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t new_anchor_commit_sig__pack
(const NewAnchorCommitSig *message,
uint8_t *out)
{
assert(message->base.descriptor == &new_anchor_commit_sig__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t new_anchor_commit_sig__pack_to_buffer
(const NewAnchorCommitSig *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &new_anchor_commit_sig__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
NewAnchorCommitSig *
new_anchor_commit_sig__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (NewAnchorCommitSig *)
protobuf_c_message_unpack (&new_anchor_commit_sig__descriptor,
allocator, len, data);
}
void new_anchor_commit_sig__free_unpacked
(NewAnchorCommitSig *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &new_anchor_commit_sig__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void new_anchor_accept__init
(NewAnchorAccept *message)
{
@ -944,7 +1073,7 @@ const ProtobufCMessageDescriptor sha256_hash__descriptor =
(ProtobufCMessageInit) sha256_hash__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_output_id__field_descriptors[2] =
static const ProtobufCFieldDescriptor bitcoin_input__field_descriptors[4] =
{
{
"txid",
@ -952,7 +1081,7 @@ static const ProtobufCFieldDescriptor bitcoin_output_id__field_descriptors[2] =
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(BitcoinOutputId, txid),
offsetof(BitcoinInput, txid),
&sha256_hash__descriptor,
NULL,
0, /* flags */
@ -964,35 +1093,61 @@ static const ProtobufCFieldDescriptor bitcoin_output_id__field_descriptors[2] =
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT32,
0, /* quantifier_offset */
offsetof(BitcoinOutputId, output),
offsetof(BitcoinInput, output),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"subscript",
3,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_BYTES,
0, /* quantifier_offset */
offsetof(BitcoinInput, subscript),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"amount",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(BitcoinInput, amount),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned bitcoin_output_id__field_indices_by_name[] = {
static const unsigned bitcoin_input__field_indices_by_name[] = {
3, /* field[3] = amount */
1, /* field[1] = output */
2, /* field[2] = subscript */
0, /* field[0] = txid */
};
static const ProtobufCIntRange bitcoin_output_id__number_ranges[1 + 1] =
static const ProtobufCIntRange bitcoin_input__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 2 }
{ 0, 4 }
};
const ProtobufCMessageDescriptor bitcoin_output_id__descriptor =
const ProtobufCMessageDescriptor bitcoin_input__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"bitcoin_output_id",
"BitcoinOutputId",
"BitcoinOutputId",
"bitcoin_input",
"BitcoinInput",
"BitcoinInput",
"",
sizeof(BitcoinOutputId),
2,
bitcoin_output_id__field_descriptors,
bitcoin_output_id__field_indices_by_name,
1, bitcoin_output_id__number_ranges,
(ProtobufCMessageInit) bitcoin_output_id__init,
sizeof(BitcoinInput),
4,
bitcoin_input__field_descriptors,
bitcoin_input__field_indices_by_name,
1, bitcoin_input__number_ranges,
(ProtobufCMessageInit) bitcoin_input__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_output__field_descriptors[2] =
@ -1084,7 +1239,45 @@ const ProtobufCMessageDescriptor bitcoin_signature__descriptor =
(ProtobufCMessageInit) bitcoin_signature__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor anchor__field_descriptors[4] =
static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] =
{
{
"key",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_BYTES,
0, /* quantifier_offset */
offsetof(BitcoinPubkey, key),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned bitcoin_pubkey__field_indices_by_name[] = {
0, /* field[0] = key */
};
static const ProtobufCIntRange bitcoin_pubkey__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"bitcoin_pubkey",
"BitcoinPubkey",
"BitcoinPubkey",
"",
sizeof(BitcoinPubkey),
1,
bitcoin_pubkey__field_descriptors,
bitcoin_pubkey__field_indices_by_name,
1, bitcoin_pubkey__number_ranges,
(ProtobufCMessageInit) bitcoin_pubkey__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor anchor__field_descriptors[6] =
{
{
"inputs",
@ -1093,23 +1286,47 @@ static const ProtobufCFieldDescriptor anchor__field_descriptors[4] =
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Anchor, n_inputs),
offsetof(Anchor, inputs),
&bitcoin_output_id__descriptor,
&bitcoin_input__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"anchor_change",
"change",
2,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(Anchor, anchor_change),
offsetof(Anchor, change),
&bitcoin_output__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"total",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_UINT64,
0, /* quantifier_offset */
offsetof(Anchor, total),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"pubkey",
5,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(Anchor, pubkey),
&bitcoin_pubkey__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"fee",
8,
@ -1136,17 +1353,20 @@ static const ProtobufCFieldDescriptor anchor__field_descriptors[4] =
},
};
static const unsigned anchor__field_indices_by_name[] = {
1, /* field[1] = anchor_change */
2, /* field[2] = fee */
1, /* field[1] = change */
4, /* field[4] = fee */
0, /* field[0] = inputs */
3, /* field[3] = min_confirms */
5, /* field[5] = min_confirms */
3, /* field[3] = pubkey */
2, /* field[2] = total */
};
static const ProtobufCIntRange anchor__number_ranges[3 + 1] =
static const ProtobufCIntRange anchor__number_ranges[4 + 1] =
{
{ 1, 0 },
{ 8, 2 },
{ 10, 3 },
{ 0, 4 }
{ 4, 2 },
{ 8, 4 },
{ 10, 5 },
{ 0, 6 }
};
const ProtobufCMessageDescriptor anchor__descriptor =
{
@ -1156,10 +1376,10 @@ const ProtobufCMessageDescriptor anchor__descriptor =
"Anchor",
"",
sizeof(Anchor),
4,
6,
anchor__field_descriptors,
anchor__field_indices_by_name,
3, anchor__number_ranges,
4, anchor__number_ranges,
(ProtobufCMessageInit) anchor__init,
NULL,NULL,NULL /* reserved[123] */
};
@ -1333,20 +1553,20 @@ const ProtobufCMessageDescriptor open_commit_sig__descriptor =
static const ProtobufCFieldDescriptor open_anchor_sig__field_descriptors[1] =
{
{
"sig",
"script",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(OpenAnchorSig, sig),
&bitcoin_signature__descriptor,
PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_BYTES,
offsetof(OpenAnchorSig, n_script),
offsetof(OpenAnchorSig, script),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned open_anchor_sig__field_indices_by_name[] = {
0, /* field[0] = sig */
0, /* field[0] = script */
};
static const ProtobufCIntRange open_anchor_sig__number_ranges[1 + 1] =
{
@ -1368,6 +1588,44 @@ const ProtobufCMessageDescriptor open_anchor_sig__descriptor =
(ProtobufCMessageInit) open_anchor_sig__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor give_early_anchor_sig_and_pretend_we_didnt__field_descriptors[1] =
{
{
"anchor_scriptsigs",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(GiveEarlyAnchorSigAndPretendWeDidnt, anchor_scriptsigs),
&open_anchor_sig__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned give_early_anchor_sig_and_pretend_we_didnt__field_indices_by_name[] = {
0, /* field[0] = anchor_scriptsigs */
};
static const ProtobufCIntRange give_early_anchor_sig_and_pretend_we_didnt__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor give_early_anchor_sig_and_pretend_we_didnt__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"give_early_anchor_sig_and_pretend_we_didnt",
"GiveEarlyAnchorSigAndPretendWeDidnt",
"GiveEarlyAnchorSigAndPretendWeDidnt",
"",
sizeof(GiveEarlyAnchorSigAndPretendWeDidnt),
1,
give_early_anchor_sig_and_pretend_we_didnt__field_descriptors,
give_early_anchor_sig_and_pretend_we_didnt__field_indices_by_name,
1, give_early_anchor_sig_and_pretend_we_didnt__number_ranges,
(ProtobufCMessageInit) give_early_anchor_sig_and_pretend_we_didnt__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor open_complete__field_descriptors[1] =
{
{
@ -1626,20 +1884,20 @@ const ProtobufCMessageDescriptor new_anchor__descriptor =
static const ProtobufCFieldDescriptor new_anchor_ack__field_descriptors[1] =
{
{
"sig",
"anchor",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(NewAnchorAck, sig),
&bitcoin_signature__descriptor,
offsetof(NewAnchorAck, anchor),
&anchor__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned new_anchor_ack__field_indices_by_name[] = {
0, /* field[0] = sig */
0, /* field[0] = anchor */
};
static const ProtobufCIntRange new_anchor_ack__number_ranges[1 + 1] =
{
@ -1661,7 +1919,7 @@ const ProtobufCMessageDescriptor new_anchor_ack__descriptor =
(ProtobufCMessageInit) new_anchor_ack__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor new_anchor_accept__field_descriptors[1] =
static const ProtobufCFieldDescriptor new_anchor_commit_sig__field_descriptors[1] =
{
{
"sig",
@ -1669,16 +1927,54 @@ static const ProtobufCFieldDescriptor new_anchor_accept__field_descriptors[1] =
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */
offsetof(NewAnchorAccept, sig),
offsetof(NewAnchorCommitSig, sig),
&bitcoin_signature__descriptor,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned new_anchor_accept__field_indices_by_name[] = {
static const unsigned new_anchor_commit_sig__field_indices_by_name[] = {
0, /* field[0] = sig */
};
static const ProtobufCIntRange new_anchor_commit_sig__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor new_anchor_commit_sig__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"new_anchor_commit_sig",
"NewAnchorCommitSig",
"NewAnchorCommitSig",
"",
sizeof(NewAnchorCommitSig),
1,
new_anchor_commit_sig__field_descriptors,
new_anchor_commit_sig__field_indices_by_name,
1, new_anchor_commit_sig__number_ranges,
(ProtobufCMessageInit) new_anchor_commit_sig__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor new_anchor_accept__field_descriptors[1] =
{
{
"script",
1,
PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_BYTES,
offsetof(NewAnchorAccept, n_script),
offsetof(NewAnchorAccept, script),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned new_anchor_accept__field_indices_by_name[] = {
0, /* field[0] = script */
};
static const ProtobufCIntRange new_anchor_accept__number_ranges[1 + 1] =
{
{ 1, 0 },
@ -1851,7 +2147,7 @@ const ProtobufCMessageDescriptor error__descriptor =
(ProtobufCMessageInit) error__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor pkt__field_descriptors[14] =
static const ProtobufCFieldDescriptor pkt__field_descriptors[15] =
{
{
"update",
@ -1937,6 +2233,18 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[14] =
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"omg_fail",
205,
PROTOBUF_C_LABEL_OPTIONAL,
PROTOBUF_C_TYPE_MESSAGE,
offsetof(Pkt, pkt_case),
offsetof(Pkt, omg_fail),
&give_early_anchor_sig_and_pretend_we_didnt__descriptor,
NULL,
0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"new_anchor",
301,
@ -2023,13 +2331,14 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[14] =
},
};
static const unsigned pkt__field_indices_by_name[] = {
11, /* field[11] = close */
12, /* field[12] = close_complete */
13, /* field[13] = error */
7, /* field[7] = new_anchor */
9, /* field[9] = new_anchor_accept */
8, /* field[8] = new_anchor_ack */
10, /* field[10] = new_anchor_complete */
12, /* field[12] = close */
13, /* field[13] = close_complete */
14, /* field[14] = error */
8, /* field[8] = new_anchor */
10, /* field[10] = new_anchor_accept */
9, /* field[9] = new_anchor_ack */
11, /* field[11] = new_anchor_complete */
7, /* field[7] = omg_fail */
3, /* field[3] = open */
5, /* field[5] = open_anchor_sig */
4, /* field[4] = open_commit_sig */
@ -2042,10 +2351,10 @@ static const ProtobufCIntRange pkt__number_ranges[5 + 1] =
{
{ 1, 0 },
{ 201, 3 },
{ 301, 7 },
{ 401, 11 },
{ 1000, 13 },
{ 0, 14 }
{ 301, 8 },
{ 401, 12 },
{ 1000, 14 },
{ 0, 15 }
};
const ProtobufCMessageDescriptor pkt__descriptor =
{
@ -2055,7 +2364,7 @@ const ProtobufCMessageDescriptor pkt__descriptor =
"Pkt",
"",
sizeof(Pkt),
14,
15,
pkt__field_descriptors,
pkt__field_indices_by_name,
5, pkt__number_ranges,

View File

@ -16,19 +16,22 @@ PROTOBUF_C__BEGIN_DECLS
typedef struct _Sha256Hash Sha256Hash;
typedef struct _BitcoinOutputId BitcoinOutputId;
typedef struct _BitcoinInput BitcoinInput;
typedef struct _BitcoinOutput BitcoinOutput;
typedef struct _BitcoinSignature BitcoinSignature;
typedef struct _BitcoinPubkey BitcoinPubkey;
typedef struct _Anchor Anchor;
typedef struct _OpenChannel OpenChannel;
typedef struct _OpenCommitSig OpenCommitSig;
typedef struct _OpenAnchorSig OpenAnchorSig;
typedef struct _GiveEarlyAnchorSigAndPretendWeDidnt GiveEarlyAnchorSigAndPretendWeDidnt;
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 _NewAnchorCommitSig NewAnchorCommitSig;
typedef struct _NewAnchorAccept NewAnchorAccept;
typedef struct _NewAnchorComplete NewAnchorComplete;
typedef struct _CloseChannel CloseChannel;
@ -59,9 +62,9 @@ struct _Sha256Hash
/*
* Identifies a bitcoin output.
* Identifies consumption of a bitcoin output.
*/
struct _BitcoinOutputId
struct _BitcoinInput
{
ProtobufCMessage base;
/*
@ -72,10 +75,18 @@ struct _BitcoinOutputId
* This is the output number.
*/
uint32_t output;
/*
* And the subscript we're signing.
*/
ProtobufCBinaryData subscript;
/*
* The amount this input is worth.
*/
uint64_t amount;
};
#define BITCOIN_OUTPUT_ID__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_output_id__descriptor) \
, NULL, 0 }
#define BITCOIN_INPUT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_input__descriptor) \
, NULL, 0, {0,NULL}, 0 }
/*
@ -105,6 +116,22 @@ struct _BitcoinSignature
, {0,NULL} }
/*
* Pubkey for commitment transaction input.
*/
struct _BitcoinPubkey
{
ProtobufCMessage base;
/*
* Either 65 or 33 bytes.
*/
ProtobufCBinaryData key;
};
#define BITCOIN_PUBKEY__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_pubkey__descriptor) \
, {0,NULL} }
/*
* All about an anchor transaction.
*/
@ -115,15 +142,23 @@ struct _Anchor
* 0 or more unspent inputs we want to use for anchor.
*/
size_t n_inputs;
BitcoinOutputId **inputs;
BitcoinInput **inputs;
/*
* Pubkey for anchor to pay to for commitment tx (p2sh)
*/
BitcoinPubkey *pubkey;
/*
* Any change from anchor (in case we don't want to use them all)
*/
BitcoinOutput *anchor_change;
BitcoinOutput *change;
/*
* How much transaction fee we'll pay in the anchor tx.
*/
uint64_t fee;
/*
* How much we'll be putting into channel (== sum(inputs) - change - fee)
*/
uint64_t total;
/*
* How many confirmations on anchor before we'll use channel.
*/
@ -131,7 +166,7 @@ struct _Anchor
};
#define ANCHOR__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&anchor__descriptor) \
, 0,NULL, NULL, 0, 0 }
, 0,NULL, NULL, NULL, 0, 0, 0 }
typedef enum {
@ -155,7 +190,7 @@ struct _OpenChannel
*/
Sha256Hash *revocation_hash;
/*
* How to pay money to us.
* How to pay money to us from commit_tx.
*/
ProtobufCBinaryData script_to_me;
/*
@ -195,15 +230,35 @@ struct _OpenCommitSig
/*
* Supply signature for anchor tx
* Supply ScriptSig for each anchor tx inputs.
*/
struct _OpenAnchorSig
{
ProtobufCMessage base;
BitcoinSignature *sig;
size_t n_script;
ProtobufCBinaryData *script;
};
#define OPEN_ANCHOR_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_anchor_sig__descriptor) \
, 0,NULL }
/*
* BROKEN AND INSECURE!!!
* This should not exist; it's completely insecure! But we need to sign
* the commitment transaction before we sign the anchor transaction, which
* doesn't work at all with current bitcoin (as we don't know the anchor
* txid until it's signed by both sides, and then we'd have to worry about
* malleability anyway). So for testing, we send the scriptsigs for the
* anchor transaction's inputs immediately.
*/
struct _GiveEarlyAnchorSigAndPretendWeDidnt
{
ProtobufCMessage base;
OpenAnchorSig *anchor_scriptsigs;
};
#define GIVE_EARLY_ANCHOR_SIG_AND_PRETEND_WE_DIDNT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&give_early_anchor_sig_and_pretend_we_didnt__descriptor) \
, NULL }
@ -314,12 +369,12 @@ struct _NewAnchor
/*
* That seems OK to me!
* That seems OK to me, let's add these too (if any).
*/
struct _NewAnchorAck
{
ProtobufCMessage base;
BitcoinSignature *sig;
Anchor *anchor;
};
#define NEW_ANCHOR_ACK__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_ack__descriptor) \
@ -327,16 +382,30 @@ struct _NewAnchorAck
/*
* Here's my signature on the new anchor to complete it.
* Now we both send signatures for new commit sig.
*/
struct _NewAnchorAccept
struct _NewAnchorCommitSig
{
ProtobufCMessage base;
BitcoinSignature *sig;
};
#define NEW_ANCHOR_COMMIT_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_commit_sig__descriptor) \
, NULL }
/*
* Here are the script sigs for the new anchor's new inputs.
*/
struct _NewAnchorAccept
{
ProtobufCMessage base;
size_t n_script;
ProtobufCBinaryData *script;
};
#define NEW_ANCHOR_ACCEPT__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_accept__descriptor) \
, NULL }
, 0,NULL }
/*
@ -403,6 +472,7 @@ struct _Error
typedef enum {
PKT__PKT__NOT_SET = 0,
PKT__PKT_OPEN = 201,
PKT__PKT_OMG_FAIL = 205,
PKT__PKT_OPEN_COMMIT_SIG = 202,
PKT__PKT_OPEN_ANCHOR_SIG = 203,
PKT__PKT_OPEN_COMPLETE = 204,
@ -430,6 +500,7 @@ struct _Pkt
* Opening
*/
OpenChannel *open;
GiveEarlyAnchorSigAndPretendWeDidnt *omg_fail;
OpenCommitSig *open_commit_sig;
OpenAnchorSig *open_anchor_sig;
OpenComplete *open_complete;
@ -481,24 +552,24 @@ Sha256Hash *
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,
/* BitcoinInput methods */
void bitcoin_input__init
(BitcoinInput *message);
size_t bitcoin_input__get_packed_size
(const BitcoinInput *message);
size_t bitcoin_input__pack
(const BitcoinInput *message,
uint8_t *out);
size_t bitcoin_output_id__pack_to_buffer
(const BitcoinOutputId *message,
size_t bitcoin_input__pack_to_buffer
(const BitcoinInput *message,
ProtobufCBuffer *buffer);
BitcoinOutputId *
bitcoin_output_id__unpack
BitcoinInput *
bitcoin_input__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void bitcoin_output_id__free_unpacked
(BitcoinOutputId *message,
void bitcoin_input__free_unpacked
(BitcoinInput *message,
ProtobufCAllocator *allocator);
/* BitcoinOutput methods */
void bitcoin_output__init
@ -538,6 +609,25 @@ BitcoinSignature *
void bitcoin_signature__free_unpacked
(BitcoinSignature *message,
ProtobufCAllocator *allocator);
/* BitcoinPubkey methods */
void bitcoin_pubkey__init
(BitcoinPubkey *message);
size_t bitcoin_pubkey__get_packed_size
(const BitcoinPubkey *message);
size_t bitcoin_pubkey__pack
(const BitcoinPubkey *message,
uint8_t *out);
size_t bitcoin_pubkey__pack_to_buffer
(const BitcoinPubkey *message,
ProtobufCBuffer *buffer);
BitcoinPubkey *
bitcoin_pubkey__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void bitcoin_pubkey__free_unpacked
(BitcoinPubkey *message,
ProtobufCAllocator *allocator);
/* Anchor methods */
void anchor__init
(Anchor *message);
@ -614,6 +704,25 @@ OpenAnchorSig *
void open_anchor_sig__free_unpacked
(OpenAnchorSig *message,
ProtobufCAllocator *allocator);
/* GiveEarlyAnchorSigAndPretendWeDidnt methods */
void give_early_anchor_sig_and_pretend_we_didnt__init
(GiveEarlyAnchorSigAndPretendWeDidnt *message);
size_t give_early_anchor_sig_and_pretend_we_didnt__get_packed_size
(const GiveEarlyAnchorSigAndPretendWeDidnt *message);
size_t give_early_anchor_sig_and_pretend_we_didnt__pack
(const GiveEarlyAnchorSigAndPretendWeDidnt *message,
uint8_t *out);
size_t give_early_anchor_sig_and_pretend_we_didnt__pack_to_buffer
(const GiveEarlyAnchorSigAndPretendWeDidnt *message,
ProtobufCBuffer *buffer);
GiveEarlyAnchorSigAndPretendWeDidnt *
give_early_anchor_sig_and_pretend_we_didnt__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void give_early_anchor_sig_and_pretend_we_didnt__free_unpacked
(GiveEarlyAnchorSigAndPretendWeDidnt *message,
ProtobufCAllocator *allocator);
/* OpenComplete methods */
void open_complete__init
(OpenComplete *message);
@ -728,6 +837,25 @@ NewAnchorAck *
void new_anchor_ack__free_unpacked
(NewAnchorAck *message,
ProtobufCAllocator *allocator);
/* NewAnchorCommitSig methods */
void new_anchor_commit_sig__init
(NewAnchorCommitSig *message);
size_t new_anchor_commit_sig__get_packed_size
(const NewAnchorCommitSig *message);
size_t new_anchor_commit_sig__pack
(const NewAnchorCommitSig *message,
uint8_t *out);
size_t new_anchor_commit_sig__pack_to_buffer
(const NewAnchorCommitSig *message,
ProtobufCBuffer *buffer);
NewAnchorCommitSig *
new_anchor_commit_sig__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void new_anchor_commit_sig__free_unpacked
(NewAnchorCommitSig *message,
ProtobufCAllocator *allocator);
/* NewAnchorAccept methods */
void new_anchor_accept__init
(NewAnchorAccept *message);
@ -847,8 +975,8 @@ void pkt__free_unpacked
typedef void (*Sha256Hash_Closure)
(const Sha256Hash *message,
void *closure_data);
typedef void (*BitcoinOutputId_Closure)
(const BitcoinOutputId *message,
typedef void (*BitcoinInput_Closure)
(const BitcoinInput *message,
void *closure_data);
typedef void (*BitcoinOutput_Closure)
(const BitcoinOutput *message,
@ -856,6 +984,9 @@ typedef void (*BitcoinOutput_Closure)
typedef void (*BitcoinSignature_Closure)
(const BitcoinSignature *message,
void *closure_data);
typedef void (*BitcoinPubkey_Closure)
(const BitcoinPubkey *message,
void *closure_data);
typedef void (*Anchor_Closure)
(const Anchor *message,
void *closure_data);
@ -868,6 +999,9 @@ typedef void (*OpenCommitSig_Closure)
typedef void (*OpenAnchorSig_Closure)
(const OpenAnchorSig *message,
void *closure_data);
typedef void (*GiveEarlyAnchorSigAndPretendWeDidnt_Closure)
(const GiveEarlyAnchorSigAndPretendWeDidnt *message,
void *closure_data);
typedef void (*OpenComplete_Closure)
(const OpenComplete *message,
void *closure_data);
@ -886,6 +1020,9 @@ typedef void (*NewAnchor_Closure)
typedef void (*NewAnchorAck_Closure)
(const NewAnchorAck *message,
void *closure_data);
typedef void (*NewAnchorCommitSig_Closure)
(const NewAnchorCommitSig *message,
void *closure_data);
typedef void (*NewAnchorAccept_Closure)
(const NewAnchorAccept *message,
void *closure_data);
@ -911,19 +1048,22 @@ typedef void (*Pkt_Closure)
/* --- descriptors --- */
extern const ProtobufCMessageDescriptor sha256_hash__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_output_id__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_input__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_output__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_signature__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_pubkey__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 give_early_anchor_sig_and_pretend_we_didnt__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_commit_sig__descriptor;
extern const ProtobufCMessageDescriptor new_anchor_accept__descriptor;
extern const ProtobufCMessageDescriptor new_anchor_complete__descriptor;
extern const ProtobufCMessageDescriptor close_channel__descriptor;

View File

@ -13,12 +13,16 @@ message sha256_hash {
required fixed64 d = 4;
}
// Identifies a bitcoin output.
message bitcoin_output_id {
// Identifies consumption of a bitcoin output.
message bitcoin_input {
// This is the transaction ID.
required sha256_hash txid = 1;
// This is the output number.
required uint32 output = 2;
// And the subscript we're signing.
required bytes subscript = 3;
// The amount this input is worth.
required uint64 amount = 4;
}
// A bitcoin output
@ -32,14 +36,24 @@ message bitcoin_signature {
required bytes der_then_sigtype = 1;
};
// Pubkey for commitment transaction input.
message bitcoin_pubkey {
// Either 65 or 33 bytes.
required bytes key = 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;
repeated bitcoin_input inputs = 1;
// Pubkey for anchor to pay to for commitment tx (p2sh)
required bitcoin_pubkey pubkey = 5;
// Any change from anchor (in case we don't want to use them all)
optional bitcoin_output anchor_change = 2;
optional bitcoin_output change = 2;
// How much transaction fee we'll pay in the anchor tx.
required uint64 fee = 8;
// How much we'll be putting into channel (== sum(inputs) - change - fee)
required uint64 total = 4;
// How many confirmations on anchor before we'll use channel.
required uint32 min_confirms = 10;
}
@ -59,7 +73,7 @@ message open_channel {
}
// Hash seed for revoking commitment transactions.
required sha256_hash revocation_hash = 4;
// How to pay money to us.
// How to pay money to us from commit_tx.
required bytes script_to_me = 5;
// How much transaction fee we'll pay for commitment txs.
required uint64 commitment_fee = 6;
@ -74,9 +88,21 @@ message open_commit_sig {
required bitcoin_signature sig = 1;
}
// Supply signature for anchor tx
// Supply ScriptSig for each anchor tx inputs.
message open_anchor_sig {
required bitcoin_signature sig = 1;
repeated bytes script = 1;
}
// BROKEN AND INSECURE!!!
//
// This should not exist; it's completely insecure! But we need to sign
// the commitment transaction before we sign the anchor transaction, which
// doesn't work at all with current bitcoin (as we don't know the anchor
// txid until it's signed by both sides, and then we'd have to worry about
// malleability anyway). So for testing, we send the scriptsigs for the
// anchor transaction's inputs immediately.
message give_early_anchor_sig_and_pretend_we_didnt {
required open_anchor_sig anchor_scriptsigs = 1;
}
// Indicates we've seen transaction reach min-depth.
@ -121,14 +147,19 @@ message new_anchor {
required anchor anchor = 1;
}
// That seems OK to me!
// That seems OK to me, let's add these too (if any).
message new_anchor_ack {
required anchor anchor = 1;
}
// Now we both send signatures for new commit sig.
message new_anchor_commit_sig {
required bitcoin_signature sig = 1;
}
// Here's my signature on the new anchor to complete it.
// Here are the script sigs for the new anchor's new inputs.
message new_anchor_accept {
required bitcoin_signature sig = 1;
repeated bytes script = 1;
}
// Complete the transfer to new anchor (both ends need to send this,
@ -161,6 +192,7 @@ message pkt {
oneof pkt {
// Opening
open_channel open = 201;
give_early_anchor_sig_and_pretend_we_didnt omg_fail = 205;
open_commit_sig open_commit_sig = 202;
open_anchor_sig open_anchor_sig = 203;
open_complete open_complete = 204;

197
open-anchor-sig.c Normal file
View File

@ -0,0 +1,197 @@
/* My example:
* ./open-anchor-sig A-open.pb B-open.pb cUjoranStkpgTRumAJZNiNEkknJv5UA7wzW1nZ7aPsm9ZWjkxypZ > A-anchor-scriptsigs.pb
* ./open-anchor-sig B-open.pb A-open.pb cNggXygY8fPHWHEdoDqRa6xALau8gVMLq6q6vzMs2eNegLrJGNAW > B-anchor-scriptsigs.pb
*/
#include <ccan/err/err.h>
#include <ccan/opt/opt.h>
#include <ccan/read_write_all/read_write_all.h>
#include "bitcoin_tx.h"
#include "signature.h"
#include "lightning.pb-c.h"
#include "overflows.h"
#include "pkt.h"
#include "bitcoin_script.h"
#include "perturb.h"
#include "bitcoin_address.h"
#include "base58.h"
#include <openssl/ec.h>
#include <unistd.h>
/* Produce an anchor transaction from what both sides want. */
static struct bitcoin_tx *merge_transaction(const tal_t *ctx,
const OpenChannel *o1,
const OpenChannel *o2,
size_t *inmap)
{
uint64_t i;
struct bitcoin_tx *tx = tal(ctx, struct bitcoin_tx);
u8 *redeemscript;
/* Use lesser of two versions. */
if (o1->tx_version < o2->tx_version)
tx->version = o1->tx_version;
else
tx->version = o2->tx_version;
if (add_overflows_size_t(o1->anchor->n_inputs, o2->anchor->n_inputs))
return tal_free(tx);
tx->input_count = o1->anchor->n_inputs + o2->anchor->n_inputs;
tx->input = tal_arr(tx, struct bitcoin_tx_input, tx->input_count);
/* Populate inputs. */
for (i = 0; i < o1->anchor->n_inputs; i++) {
BitcoinInput *pb = o1->anchor->inputs[i];
struct bitcoin_tx_input *in = &tx->input[i];
proto_to_sha256(pb->txid, &in->txid.sha);
in->index = pb->output;
in->sequence_number = 0xFFFFFFFF;
/* Leave inputs as stubs for now, for signing. */
in->script_length = 0;
in->script = NULL;
}
for (i = 0; i < o2->anchor->n_inputs; i++) {
BitcoinInput *pb = o2->anchor->inputs[i];
struct bitcoin_tx_input *in
= &tx->input[o1->anchor->n_inputs + i];
proto_to_sha256(pb->txid, &in->txid.sha);
in->index = pb->output;
in->sequence_number = 0xFFFFFFFF;
/* Leave inputs as stubs for now, for signing. */
in->script_length = 0;
in->script = NULL;
}
/* Populate outputs. */
tx->output_count = 1;
/* Allocate for worst case. */
tx->output = tal_arr(tx, struct bitcoin_tx_output, 3);
if (add_overflows_u64(o1->anchor->total, o2->anchor->total))
return tal_free(tx);
/* Make the 2 of 2 payment for the commitment txs. */
redeemscript = bitcoin_redeem_2of2(tx, o1->anchor->pubkey,
o2->anchor->pubkey);
tx->output[0].amount = o1->anchor->total + o2->anchor->total;
tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[0].script_length = tal_count(tx->output[0].script);
/* Add change transactions (if any) */
if (o1->anchor->change) {
struct bitcoin_tx_output *out = &tx->output[tx->output_count++];
out->amount = o1->anchor->change->amount;
out->script_length = o1->anchor->change->script.len;
out->script = o1->anchor->change->script.data;
}
if (o2->anchor->change) {
struct bitcoin_tx_output *out = &tx->output[tx->output_count++];
out->amount = o2->anchor->change->amount;
out->script_length = o2->anchor->change->script.len;
out->script = o2->anchor->change->script.data;
}
perturb_inputs(o1->seed, o2->seed, 0, tx->input, tx->input_count, inmap);
perturb_outputs(o1->seed, o2->seed, 0, tx->output, tx->output_count, NULL);
return tx;
}
/* All the input scripts are already set to 0. We just need to make this one. */
static u8 *sign_tx_input(const tal_t *ctx,
struct bitcoin_tx *tx,
unsigned int i,
const BitcoinInput *input,
EC_KEY *privkey,
const struct bitcoin_compressed_pubkey *pubkey)
{
struct sha256_double hash;
struct sha256_ctx shactx;
struct bitcoin_address addr;
u8 *sig;
/* Transaction gets signed as if the output subscript is the
* only input script. */
tx->input[i].script_length = input->subscript.len;
tx->input[i].script = input->subscript.data;
sha256_init(&shactx);
sha256_tx(&shactx, tx);
sha256_le32(&shactx, SIGHASH_ALL);
sha256_double_done(&shactx, &hash);
/* Reset it for next time. */
tx->input[i].script_length = 0;
tx->input[i].script = NULL;
sig = sign_hash(ctx, privkey, &hash);
if (!sig)
return NULL;
if (!is_pay_to_pubkey_hash(&input->subscript))
errx(1, "FIXME: Don't know how to handle input");
bitcoin_address(pubkey, &addr);
return scriptsig_pay_to_pubkeyhash(ctx, &addr, sig, tal_count(sig));
}
int main(int argc, char *argv[])
{
OpenChannel *o1, *o2;
const tal_t *ctx = tal_arr(NULL, char, 0);
struct bitcoin_tx *anchor;
struct pkt *pkt;
size_t i;
u8 **sigs;
size_t *map;
err_set_progname(argv[0]);
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<open-channel-file1> <open-channel-file2> <privkey>...\n"
"Create signatures for transactions, and output to stdout",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc < 3)
opt_usage_and_exit(NULL);
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
map = tal_arr(ctx, size_t, o1->anchor->n_inputs + o2->anchor->n_inputs);
/* Create merged transaction */
anchor = merge_transaction(ctx, o1, o2, map);
if (!anchor)
errx(1, "Failed transaction merge");
/* Sign our inputs. */
if (o1->anchor->n_inputs != argc - 3)
errx(1, "Expected %zu private keys", o1->anchor->n_inputs);
sigs = tal_arr(ctx, u8 *, o1->anchor->n_inputs);
for (i = 0; i < o1->anchor->n_inputs; i++) {
/* FIXME: Support non-compressed keys? */
struct bitcoin_compressed_pubkey pubkey;
EC_KEY *privkey;
bool testnet;
privkey = key_from_base58(argv[3+i], strlen(argv[3+i]),
&testnet, &pubkey);
if (!privkey)
errx(1, "Invalid private key '%s'", argv[3+i]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[3+i]);
sigs[i] = sign_tx_input(sigs, anchor, map[i],
o1->anchor->inputs[i],
privkey, &pubkey);
}
pkt = open_anchor_sig_pkt(ctx, sigs, o1->anchor->n_inputs);
if (!write_all(STDOUT_FILENO, pkt,
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
err(1, "Writing out packet");
tal_free(ctx);
return 0;
}

View File

@ -1,3 +1,7 @@
/* My example:
* ./open-channel 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff 50000000000 mzqiPPbjTdcgM6NpNWJLHFt29tWD69bciE cUBCjrdJu8tfvM7FT8So6aqs6G6bZS1Cax6Rc9rFzYL6nYG4XNEC mi1BzT4tCB7K4kZH3yK1hM517bXH4pNmEH 08ffaf638849198f9c8f04aa75d225a5a104d5e7c540770ca55ad08b9a32d10c/1/100000000000/76a9148d2d939aa2aff2d341cde3e61a89bf9c2c21d12388ac > A-open.pb
* ./open-channel 112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 9795000 mpDyc5kPAJZB7Zz9iW9acq3Jk8yiTJ7HKj cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi mrvw5JC5SKcEsRpSaRss6A3jLR6DMwpxep 8cb044605f33ca907b966701f49e0bd80b4294696b57f8cf45f22398a1e63a23/0/9800000/76a9143b2aab840afb327a12c8a90fb4ed45b6892eb80988ac > B-open.pb
*/
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
@ -8,6 +12,7 @@
#include "lightning.pb-c.h"
#include "base58.h"
#include "pkt.h"
#include "bitcoin_script.h"
#include <openssl/ec.h>
#include <unistd.h>
@ -32,40 +37,41 @@ static void opt_show_bits(char buf[OPT_SHOW_LEN], const u64 *bits)
opt_show_ulonglongval_si(buf, &ll);
}
static BitcoinOutputId *parse_anchor_input(const tal_t *ctx, const char *spec)
static BitcoinInput *parse_anchor_input(const tal_t *ctx, const char *spec)
{
BitcoinOutputId *o = tal(ctx, BitcoinOutputId);
BitcoinInput *in = tal(ctx, BitcoinInput);
struct sha256 txid;
const char *slash;
char *end;
long l;
bitcoin_output_id__init(o);
bitcoin_input__init(in);
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 /");
errx(1, "Expected / in <txid>/<num>/<satoshis>/<hexscript>");
if (!hex_decode(spec, slash - spec, &txid, sizeof(txid)))
errx(1, "Expected 256-bit hex txid before /");
in->txid = sha256_to_proto(in, &txid);
o->txid = proto_sha256_hash(o, &txid);
return o;
}
in->output = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->output != (int64_t)l)
errx(1, "Expected <outputnum> after /");
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 */
slash = end;
in->amount = l = strtol(slash + 1, &end, 10);
if (end == slash + 1 || *end != '/' || (int64_t)in->amount != (int64_t)l)
errx(1, "Expected <satoshis> after second /");
return script;
slash = end;
in->subscript.len = strlen(slash + 1) / 2;
in->subscript.data = tal_arr(in, u8, in->subscript.len);
if (!hex_decode(slash + 1, strlen(slash + 1),
in->subscript.data, in->subscript.len))
errx(1, "Expected hex string after third /");
return in;
}
/* FIXME: This is too weak, even for us! */
@ -78,17 +84,17 @@ static u64 weak_random64(void)
int main(int argc, char *argv[])
{
struct sha256 seed, revocation_hash;
struct bitcoin_address ouraddr;
EC_KEY *privkey;
struct bitcoin_address changeaddr, returnaddr;
struct pkt *pkt;
const tal_t *ctx = tal_arr(NULL, char, 0);
Anchor anchor = ANCHOR__INIT;
u64 commit_tx_fee;
u64 commit_tx_fee, total_in;
unsigned int locktime_seconds;
bool testnet;
struct bitcoin_compressed_pubkey pubkey;
u8 *script_to_me;
size_t i;
struct bitcoin_compressed_pubkey commitkey;
EC_KEY *commitprivkey;
err_set_progname(argv[0]);
@ -102,7 +108,7 @@ int main(int argc, char *argv[])
locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60;
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<seed> <privkey> <ouraddr> <txid>/<outnum>...\n"
"<seed> <amount> <changeaddr> <commitprivkey> <returnaddr> <txid>/<outnum>/<satoshis>/<script-in-hex>...\n"
"A test program to output openchannel on stdout.",
"Print this message.");
opt_register_arg("--min-anchor-confirms",
@ -111,44 +117,75 @@ int main(int argc, char *argv[])
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)
if (argc < 7)
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]);
anchor.total = atol(argv[2]);
if (!anchor.total)
errx(1, "Invalid total: must be > 0");
if (!bitcoin_from_base58(&testnet, &ouraddr, argv[3], strlen(argv[3])))
if (!bitcoin_from_base58(&testnet, &changeaddr, 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]);
/* We don't really need the privkey here, but it's the most
* convenient way to get the pubkey from bitcoind. */
commitprivkey = key_from_base58(argv[4], strlen(argv[4]), &testnet,
&commitkey);
if (!commitprivkey)
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
if (!bitcoin_from_base58(&testnet, &returnaddr, argv[5], strlen(argv[5])))
errx(1, "Invalid bitcoin address '%s'", argv[5]);
if (!testnet)
errx(1, "Bitcoin address '%s' not on testnet!", argv[5]);
anchor.n_inputs = (argc - 4);
anchor.inputs = tal_arr(ctx, BitcoinOutputId *, anchor.n_inputs);
anchor.n_inputs = (argc - 6);
anchor.inputs = tal_arr(ctx, BitcoinInput *, anchor.n_inputs);
anchor.pubkey = pubkey_to_proto(ctx, &commitkey);
for (i = 0; i < anchor.n_inputs; i++)
anchor.inputs[i] = parse_anchor_input(anchor.inputs, argv[i+4]);
total_in = 0;
for (i = 0; i < anchor.n_inputs; i++) {
anchor.inputs[i] = parse_anchor_input(anchor.inputs, argv[i+6]);
total_in += anchor.inputs[i]->amount;
}
if (total_in < anchor.total + anchor.fee)
errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)",
(unsigned long long)total_in,
(unsigned long long)anchor.total,
(unsigned long long)anchor.fee);
/* If there's change, say where to send it. */
if (total_in != anchor.total + anchor.fee) {
anchor.change = tal(ctx, BitcoinOutput);
bitcoin_output__init(anchor.change);
anchor.change->amount = total_in - (anchor.total + anchor.fee);
/* FIXME: Use p2sh? */
anchor.change->script.data
= scriptpubkey_pay_to_pubkeyhash(anchor.change,
&changeaddr);
anchor.change->script.len
= tal_count(anchor.change->script.data);
}
/* 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);
script_to_me = scriptpubkey_pay_to_pubkeyhash(ctx, &returnaddr);
pkt = openchannel_pkt(ctx, weak_random64(), &revocation_hash,
tal_count(script_to_me), script_to_me,

14
overflows.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef LIGHTNING_OVERFLOWS_H
#define LIGHTNING_OVERFLOWS_H
static inline bool add_overflows_size_t(uint64_t a, uint64_t b)
{
return (size_t)a != a || (size_t)b != b || (a + b) < (size_t)a;
}
static inline bool add_overflows_u64(uint64_t a, uint64_t b)
{
return (a + b) < a;
}
#endif /* LIGHTNING_OVERFLOWS_H */

View File

@ -1,20 +0,0 @@
/*
* 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). */

186
perturb.c Normal file
View File

@ -0,0 +1,186 @@
#include "perturb.h"
#include <ccan/crypto/sha256/sha256.h>
#include <stdbool.h>
#include <string.h>
static u32 get_next_rand(struct sha256 *h, size_t *randidx)
{
u32 ret = h->u.u32[(*randidx)++];
if (*randidx == 8) {
*randidx = 0;
sha256(h, h, sizeof(*h));
}
return ret;
}
static void init_rand(struct sha256 *h, size_t *randidx,
uint64_t seed1, uint64_t seed2,
uint64_t transaction_num,
enum perturb_style style)
{
struct sha256_ctx shactx;
sha256_init(&shactx);
if (seed1 < seed2) {
sha256_le64(&shactx, seed1);
sha256_le64(&shactx, seed2);
} else {
sha256_le64(&shactx, seed2);
sha256_le64(&shactx, seed1);
}
sha256_le64(&shactx, transaction_num);
sha256_u8(&shactx, style);
sha256_done(&shactx, h);
*randidx = 0;
}
static void init_map(size_t *map, size_t len)
{
size_t i;
if (!map)
return;
for (i = 0; i < len; i++)
map[i] = i;
}
static bool input_better(const struct bitcoin_tx_input *a,
const struct bitcoin_tx_input *b)
{
int cmp;
cmp = memcmp(&a->txid, &b->txid, sizeof(a->txid));
if (cmp != 0)
return cmp < 0;
if (a->index != b->index)
return a->index < b->index;
/* These shouldn't happen, but let's get a canonical order anyway. */
if (a->script_length != b->script_length)
return a->script_length < b->script_length;
cmp = memcmp(a->script, b->script, a->script_length);
if (cmp != 0)
return cmp < 0;
return a->sequence_number < b->sequence_number;
}
static size_t find_best_in(struct bitcoin_tx_input *inputs, size_t num)
{
size_t i, best = 0;
for (i = 1; i < num; i++) {
if (input_better(&inputs[i], &inputs[best]))
best = i;
}
return best;
}
static void swap_inputs(struct bitcoin_tx_input *inputs, size_t *map,
size_t i1, size_t i2)
{
struct bitcoin_tx_input tmpinput;
size_t tmpidx;
tmpinput = inputs[i1];
inputs[i1] = inputs[i2];
inputs[i2] = tmpinput;
if (map) {
tmpidx = map[i1];
map[i1] = map[i2];
map[i2] = tmpidx;
}
}
void perturb_inputs(uint64_t seed1, uint64_t seed2, uint64_t tx_num,
struct bitcoin_tx_input *inputs,
size_t num_inputs,
size_t *map)
{
struct sha256 h;
size_t i, randidx;
init_map(map, num_inputs);
/* Now do a dumb sort (num_inputs is small). */
for (i = 0; i < num_inputs; i++) {
/* Swap best into first place. */
swap_inputs(inputs, map,
i, i + find_best_in(inputs + i, num_inputs - i));
}
init_rand(&h, &randidx, seed1, seed2, tx_num, PERTURB_INPUT_STYLE);
/* Now, Fisher-Yates shuffle, but using SHA256 as "random" source. */
for (i = 0; i + 1 < num_inputs; i++) {
size_t r = get_next_rand(&h, &randidx) % (num_inputs - i - 1);
swap_inputs(inputs, map, i, i + 1 + r);
}
}
static void swap_outputs(struct bitcoin_tx_output *outputs, size_t *map,
size_t i1, size_t i2)
{
struct bitcoin_tx_output tmpoutput;
size_t tmpidx;
tmpoutput = outputs[i1];
outputs[i1] = outputs[i2];
outputs[i2] = tmpoutput;
if (map) {
tmpidx = map[i1];
map[i1] = map[i2];
map[i2] = tmpidx;
}
}
static bool output_better(const struct bitcoin_tx_output *a,
const struct bitcoin_tx_output *b)
{
if (a->amount != b->amount)
return a->amount < b->amount;
if (a->script_length != b->script_length)
return a->script_length < b->script_length;
return memcmp(a->script, b->script, a->script_length) < 0;
}
static size_t find_best_out(struct bitcoin_tx_output *outputs, size_t num)
{
size_t i, best = 0;
for (i = 1; i < num; i++) {
if (output_better(&outputs[i], &outputs[best]))
best = i;
}
return best;
}
void perturb_outputs(uint64_t seed1, uint64_t seed2, size_t tx_num,
struct bitcoin_tx_output *outputs,
size_t num_outputs,
size_t *map)
{
struct sha256 h;
size_t i, randidx;
init_map(map, num_outputs);
/* Now do a dumb sort (num_outputs is small). */
for (i = 0; i < num_outputs; i++) {
/* Swap best into first place. */
swap_outputs(outputs, map,
i, i + find_best_out(outputs + i, num_outputs - i));
}
init_rand(&h, &randidx, seed1, seed2, tx_num, PERTURB_OUTPUT_STYLE);
/* Now, Fisher-Yates shuffle, but using SHA256 as "random" source. */
for (i = 0; i + 1 < num_outputs; i++) {
size_t r = get_next_rand(&h, &randidx) % (num_outputs - i - 1);
swap_outputs(outputs, map, i, i + 1 + r);
}
}

25
perturb.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef LIGHTNING_PERTURB_H
#define LIGHTNING_PERTURB_H
#include "bitcoin_tx.h"
/* Given the two seeds, perturb the transaction inputs.
* map[0] is set to the new index of input 0, etc.
*/
void perturb_inputs(uint64_t seed1, uint64_t seed2,
size_t transaction_num,
struct bitcoin_tx_input *inputs,
size_t num_inputs,
size_t *map);
void perturb_outputs(uint64_t seed1, uint64_t seed2,
size_t transaction_num,
struct bitcoin_tx_output *outputs,
size_t num_outputs,
size_t *map);
enum perturb_style {
PERTURB_INPUT_STYLE = 0,
PERTURB_OUTPUT_STYLE = 1
};
#endif /* LIGHTNING_PERTURB_H */

85
pkt.c
View File

@ -1,6 +1,11 @@
#include <ccan/crypto/sha256/sha256.h>
#include <ccan/tal/grab_file/grab_file.h>
#include <ccan/err/err.h>
#include "pkt.h"
#include "bitcoin_tx.h"
#include "bitcoin_address.h"
#include <stdio.h>
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
{
struct pkt *ret;
@ -14,11 +19,12 @@ static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *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 *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash)
{
Sha256Hash *h = tal(ctx, Sha256Hash);
sha256_hash__init(h);
@ -31,6 +37,26 @@ Sha256Hash *proto_sha256_hash(const tal_t *ctx, const struct sha256 *hash)
return h;
}
void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash)
{
/* Kill me again. */
memcpy(hash->u.u8, &pb->a, 8);
memcpy(hash->u.u8 + 8, &pb->b, 8);
memcpy(hash->u.u8 + 16, &pb->c, 8);
memcpy(hash->u.u8 + 24, &pb->d, 8);
}
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key)
{
BitcoinPubkey *p = tal(ctx, BitcoinPubkey);
bitcoin_pubkey__init(p);
p->key.data = tal_dup_arr(ctx, u8, key->key, sizeof(key->key), 0);
p->key.len = sizeof(key->key);
return p;
}
struct pkt *openchannel_pkt(const tal_t *ctx,
u64 seed,
const struct sha256 *revocation_hash,
@ -42,15 +68,66 @@ struct pkt *openchannel_pkt(const tal_t *ctx,
{
OpenChannel o = OPEN_CHANNEL__INIT;
/* Required fields must be set: pack functions don't check! */
assert(anchor->inputs);
assert(anchor->pubkey);
o.seed = seed;
o.revocation_hash = proto_sha256_hash(ctx, revocation_hash);
o.revocation_hash = sha256_to_proto(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;
o.tx_version = 1;
o.tx_version = BITCOIN_TX_VERSION;
{
size_t len = open_channel__get_packed_size(&o);
unsigned char *pb = malloc(len);
open_channel__pack(&o, pb);
assert(open_channel__unpack(NULL, len, pb));
}
return to_pkt(ctx, PKT__PKT_OPEN, &o);
}
Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect)
{
struct pkt *pkt;
Pkt *ret;
size_t len;
pkt = grab_file(NULL, filename);
if (!pkt)
err(1, "Opening %s", filename);
len = tal_count(pkt) - 1;
if (len < sizeof(pkt->len)
|| len != sizeof(pkt->len) + le32_to_cpu(pkt->len))
errx(1, "%s length is wrong", filename);
len -= sizeof(pkt->len);
ret = pkt__unpack(NULL, len, pkt->data);
if (!ret)
errx(1, "Unpack failed for %s", filename);
if (ret->pkt_case != expect)
errx(1, "Unexpected type %i in %s", ret->pkt_case, filename);
return ret;
}
struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs)
{
OpenAnchorSig o = OPEN_ANCHOR_SIG__INIT;
size_t i;
o.n_script = num_sigs;
o.script = tal_arr(ctx, ProtobufCBinaryData, num_sigs);
for (i = 0; i < num_sigs; i++) {
o.script[i].data = sigs[i];
o.script[i].len = tal_count(sigs[i]);
}
return to_pkt(ctx, PKT__PKT_OPEN_ANCHOR_SIG, &o);
}

18
pkt.h
View File

@ -16,10 +16,14 @@ struct pkt {
u8 data[];
};
/* Utility helper: dies if there's a problem. */
Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect);
struct sha256;
struct bitcoin_compressed_pubkey;
/**
* tal_openchannel - create an openchannel message
* openchannel_pkt - 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.
@ -37,8 +41,18 @@ struct pkt *openchannel_pkt(const tal_t *ctx,
u32 rel_locktime_seconds,
Anchor *anchor);
/**
* open_anchor_sig_pkt - create an open_anchor_sig message
* @ctx: tal context to allocate off.
* @sigs: the der-encoded signatures (tal_count() gives len).
* @num_sigs: the number of sigs.
*/
struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs);
/* Useful helper for allocating & populating a protobuf Sha256Hash */
Sha256Hash *proto_sha256_hash(const tal_t *ctx, const struct sha256 *hash);
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash);
void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash);
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key);
#endif /* LIGHTNING_PKT_H */

45
signature.c Normal file
View File

@ -0,0 +1,45 @@
#include "signature.h"
#include "shadouble.h"
#include <openssl/bn.h>
#include <openssl/obj_mac.h>
#include <assert.h>
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
const struct sha256_double *h)
{
ECDSA_SIG *sig;
int len;
unsigned char *der, *ret;
sig = ECDSA_do_sign(h->sha.u.u8, sizeof(*h), private_key);
if (!sig)
return NULL;
/* See https://github.com/sipa/bitcoin/commit/a81cd9680.
* There can only be one signature with an even S, so make sure we
* get that one. */
if (BN_is_odd(sig->s)) {
const EC_GROUP *group;
BIGNUM order;
BN_init(&order);
group = EC_KEY_get0_group(private_key);
EC_GROUP_get_order(group, &order, NULL);
BN_sub(sig->s, &order, sig->s);
BN_free(&order);
assert(!BN_is_odd(sig->s));
}
/* This tells it to allocate for us. */
der = NULL;
len = i2d_ECDSA_SIG(sig, &der);
ECDSA_SIG_free(sig);
if (len <= 0)
return NULL;
ret = tal_dup_arr(ctx, u8, der, len, 0);
OPENSSL_free(der);
return ret;
}

19
signature.h Normal file
View File

@ -0,0 +1,19 @@
#ifndef LIGHTNING_SIGNATURE_H
#define LIGHTNING_SIGNATURE_H
#include <ccan/short_types/short_types.h>
#include <openssl/ecdsa.h>
#include <ccan/tal/tal.h>
enum sighash_type {
SIGHASH_ALL = 1,
SIGHASH_NONE = 2,
SIGHASH_SINGLE = 3,
SIGHASH_ANYONECANPAY = 0x80
};
struct sha256_double;
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
const struct sha256_double *h);
#endif /* LIGHTNING_SIGNATURE_H */