mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 01:43:36 +01:00
open-anchor-sig, many fixes for open-channel.
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
c46842e0ba
commit
670670f138
25
Makefile
25
Makefile
@ -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
|
||||
|
11
base58.h
11
base58.h
@ -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
11
bitcoin_address.c
Normal 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
18
bitcoin_address.h
Normal 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
161
bitcoin_script.c
Normal 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
34
bitcoin_script.h
Normal 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
64
bitcoin_tx.c
Normal 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
38
bitcoin_tx.h
Normal 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
35
getinput.sh
Executable 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
|
459
lightning.pb-c.c
459
lightning.pb-c.c
@ -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,
|
||||
|
206
lightning.pb-c.h
206
lightning.pb-c.h
@ -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;
|
||||
|
@ -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
197
open-anchor-sig.c
Normal 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;
|
||||
}
|
117
open-channel.c
117
open-channel.c
@ -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
14
overflows.h
Normal 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 */
|
20
pd_channel.h
20
pd_channel.h
@ -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
186
perturb.c
Normal 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
25
perturb.h
Normal 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
85
pkt.c
@ -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
18
pkt.h
@ -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
45
signature.c
Normal 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
19
signature.h
Normal 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 */
|
Loading…
Reference in New Issue
Block a user