Browse Source

Use raw 64-byte signatures in protocol.

DER encoding introduces problems for non-canonical encodings; we should
do that only at the lightning<->bitcoin interface.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 10 years ago
parent
commit
eec612af9f
  1. 25
      bitcoin_script.c
  2. 4
      bitcoin_script.h
  3. 269
      lightning.pb-c.c
  4. 96
      lightning.pb-c.h
  5. 34
      lightning.proto
  6. 4
      open-anchor-sig.c
  7. 4
      open-commit-sig.c
  8. 41
      pkt.c
  9. 9
      pkt.h
  10. 31
      signature.c
  11. 16
      signature.h

25
bitcoin_script.c

@ -1,6 +1,7 @@
#include "bitcoin_script.h" #include "bitcoin_script.h"
#include "bitcoin_address.h" #include "bitcoin_address.h"
#include "pkt.h" #include "pkt.h"
#include "signature.h"
#include <openssl/ripemd.h> #include <openssl/ripemd.h>
#include <ccan/endian/endian.h> #include <ccan/endian/endian.h>
#include <ccan/crypto/sha256/sha256.h> #include <ccan/crypto/sha256/sha256.h>
@ -59,6 +60,25 @@ static void add_push_bytes(u8 **scriptp, const void *mem, size_t len)
add(scriptp, mem, len); add(scriptp, mem, len);
} }
/* Bitcoin wants DER encoding. */
static void add_push_sig(u8 **scriptp, const struct signature *sig)
{
u8 der[2 + 2 + sizeof(sig->r) + 2 + sizeof(sig->s)];
der[0] = 0x30; /* Type */
der[1] = sizeof(der) - 2; /* Total length */
der[2] = 0x2; /* r value type. */
der[3] = sizeof(sig->r); /* r length */
memcpy(der+4, sig->r, sizeof(sig->r));
der[4 + sizeof(sig->r)] = 0x2; /* s value type. */
der[4 + sizeof(sig->r) + 1] = sizeof(sig->s); /* s value length. */
memcpy(der+4+sizeof(sig->r)+2, sig->s, sizeof(sig->s));
add_push_bytes(scriptp, der, sizeof(der));
}
/* FIXME: permute? */ /* FIXME: permute? */
/* Is a < b? (If equal we don't care) */ /* Is a < b? (If equal we don't care) */
static bool key_less(const BitcoinPubkey *a, const BitcoinPubkey *b) static bool key_less(const BitcoinPubkey *a, const BitcoinPubkey *b)
@ -140,12 +160,11 @@ u8 *scriptpubkey_pay_to_pubkeyhash(const tal_t *ctx,
u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx, u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr, const struct bitcoin_address *addr,
const u8 *signature, const struct signature *sig)
size_t sig_len)
{ {
u8 *script = tal_arr(ctx, u8, 0); u8 *script = tal_arr(ctx, u8, 0);
add_push_bytes(&script, signature, sig_len); add_push_sig(&script, sig);
add_push_bytes(&script, addr, sizeof(*addr)); add_push_bytes(&script, addr, sizeof(*addr));
return script; return script;

4
bitcoin_script.h

@ -6,6 +6,7 @@
struct bitcoin_address; struct bitcoin_address;
struct bitcoin_compressed_pubkey; struct bitcoin_compressed_pubkey;
struct signature;
/* tal_count() gives the length of the script. */ /* tal_count() gives the length of the script. */
u8 *bitcoin_redeem_2of2(const tal_t *ctx, u8 *bitcoin_redeem_2of2(const tal_t *ctx,
@ -35,8 +36,7 @@ u8 *scriptpubkey_pay_to_pubkeyhash(const tal_t *ctx,
/* Create an input script to accept pay to pubkey */ /* Create an input script to accept pay to pubkey */
u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx, u8 *scriptsig_pay_to_pubkeyhash(const tal_t *ctx,
const struct bitcoin_address *addr, const struct bitcoin_address *addr,
const u8 *signature, const struct signature *sig);
size_t sig_len);
/* Is this a normal pay to pubkey hash? */ /* Is this a normal pay to pubkey hash? */
bool is_pay_to_pubkey_hash(const ProtobufCBinaryData *script); bool is_pay_to_pubkey_hash(const ProtobufCBinaryData *script);

269
lightning.pb-c.c

@ -50,6 +50,49 @@ void sha256_hash__free_unpacked
assert(message->base.descriptor == &sha256_hash__descriptor); assert(message->base.descriptor == &sha256_hash__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
} }
void signature__init
(Signature *message)
{
static Signature init_value = SIGNATURE__INIT;
*message = init_value;
}
size_t signature__get_packed_size
(const Signature *message)
{
assert(message->base.descriptor == &signature__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t signature__pack
(const Signature *message,
uint8_t *out)
{
assert(message->base.descriptor == &signature__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t signature__pack_to_buffer
(const Signature *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &signature__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
Signature *
signature__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (Signature *)
protobuf_c_message_unpack (&signature__descriptor,
allocator, len, data);
}
void signature__free_unpacked
(Signature *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &signature__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_input__init void bitcoin_input__init
(BitcoinInput *message) (BitcoinInput *message)
{ {
@ -136,49 +179,6 @@ void bitcoin_output__free_unpacked
assert(message->base.descriptor == &bitcoin_output__descriptor); assert(message->base.descriptor == &bitcoin_output__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
} }
void bitcoin_signature__init
(BitcoinSignature *message)
{
static BitcoinSignature init_value = BITCOIN_SIGNATURE__INIT;
*message = init_value;
}
size_t bitcoin_signature__get_packed_size
(const BitcoinSignature *message)
{
assert(message->base.descriptor == &bitcoin_signature__descriptor);
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
}
size_t bitcoin_signature__pack
(const BitcoinSignature *message,
uint8_t *out)
{
assert(message->base.descriptor == &bitcoin_signature__descriptor);
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
}
size_t bitcoin_signature__pack_to_buffer
(const BitcoinSignature *message,
ProtobufCBuffer *buffer)
{
assert(message->base.descriptor == &bitcoin_signature__descriptor);
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
}
BitcoinSignature *
bitcoin_signature__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data)
{
return (BitcoinSignature *)
protobuf_c_message_unpack (&bitcoin_signature__descriptor,
allocator, len, data);
}
void bitcoin_signature__free_unpacked
(BitcoinSignature *message,
ProtobufCAllocator *allocator)
{
assert(message->base.descriptor == &bitcoin_signature__descriptor);
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
}
void bitcoin_pubkey__init void bitcoin_pubkey__init
(BitcoinPubkey *message) (BitcoinPubkey *message)
{ {
@ -1073,6 +1073,135 @@ const ProtobufCMessageDescriptor sha256_hash__descriptor =
(ProtobufCMessageInit) sha256_hash__init, (ProtobufCMessageInit) sha256_hash__init,
NULL,NULL,NULL /* reserved[123] */ NULL,NULL,NULL /* reserved[123] */
}; };
static const ProtobufCFieldDescriptor signature__field_descriptors[8] =
{
{
"r1",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, r1),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"r2",
2,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, r2),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"r3",
3,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, r3),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"r4",
4,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, r4),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"s1",
5,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, s1),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"s2",
6,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, s2),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"s3",
7,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, s3),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"s4",
8,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */
offsetof(Signature, s4),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned signature__field_indices_by_name[] = {
0, /* field[0] = r1 */
1, /* field[1] = r2 */
2, /* field[2] = r3 */
3, /* field[3] = r4 */
4, /* field[4] = s1 */
5, /* field[5] = s2 */
6, /* field[6] = s3 */
7, /* field[7] = s4 */
};
static const ProtobufCIntRange signature__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 8 }
};
const ProtobufCMessageDescriptor signature__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"signature",
"Signature",
"Signature",
"",
sizeof(Signature),
8,
signature__field_descriptors,
signature__field_indices_by_name,
1, signature__number_ranges,
(ProtobufCMessageInit) signature__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_input__field_descriptors[4] = static const ProtobufCFieldDescriptor bitcoin_input__field_descriptors[4] =
{ {
{ {
@ -1201,44 +1330,6 @@ const ProtobufCMessageDescriptor bitcoin_output__descriptor =
(ProtobufCMessageInit) bitcoin_output__init, (ProtobufCMessageInit) bitcoin_output__init,
NULL,NULL,NULL /* reserved[123] */ NULL,NULL,NULL /* reserved[123] */
}; };
static const ProtobufCFieldDescriptor bitcoin_signature__field_descriptors[1] =
{
{
"der_then_sigtype",
1,
PROTOBUF_C_LABEL_REQUIRED,
PROTOBUF_C_TYPE_BYTES,
0, /* quantifier_offset */
offsetof(BitcoinSignature, der_then_sigtype),
NULL,
NULL,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
};
static const unsigned bitcoin_signature__field_indices_by_name[] = {
0, /* field[0] = der_then_sigtype */
};
static const ProtobufCIntRange bitcoin_signature__number_ranges[1 + 1] =
{
{ 1, 0 },
{ 0, 1 }
};
const ProtobufCMessageDescriptor bitcoin_signature__descriptor =
{
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
"bitcoin_signature",
"BitcoinSignature",
"BitcoinSignature",
"",
sizeof(BitcoinSignature),
1,
bitcoin_signature__field_descriptors,
bitcoin_signature__field_indices_by_name,
1, bitcoin_signature__number_ranges,
(ProtobufCMessageInit) bitcoin_signature__init,
NULL,NULL,NULL /* reserved[123] */
};
static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] = static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] =
{ {
{ {
@ -1509,7 +1600,7 @@ static const ProtobufCFieldDescriptor open_commit_sig__field_descriptors[1] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(OpenCommitSig, sig), offsetof(OpenCommitSig, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -1685,7 +1776,7 @@ static const ProtobufCFieldDescriptor update__field_descriptors[4] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(Update, sig), offsetof(Update, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -1697,7 +1788,7 @@ static const ProtobufCFieldDescriptor update__field_descriptors[4] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(Update, old_anchor_sig), offsetof(Update, old_anchor_sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -1738,7 +1829,7 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(UpdateAccept, sig), offsetof(UpdateAccept, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -1750,7 +1841,7 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(UpdateAccept, old_anchor_sig), offsetof(UpdateAccept, old_anchor_sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -1916,7 +2007,7 @@ static const ProtobufCFieldDescriptor new_anchor_commit_sig__field_descriptors[1
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(NewAnchorCommitSig, sig), offsetof(NewAnchorCommitSig, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -2030,7 +2121,7 @@ static const ProtobufCFieldDescriptor close_channel__field_descriptors[1] =
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(CloseChannel, sig), offsetof(CloseChannel, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
@ -2068,7 +2159,7 @@ static const ProtobufCFieldDescriptor close_channel_complete__field_descriptors[
PROTOBUF_C_TYPE_MESSAGE, PROTOBUF_C_TYPE_MESSAGE,
0, /* quantifier_offset */ 0, /* quantifier_offset */
offsetof(CloseChannelComplete, sig), offsetof(CloseChannelComplete, sig),
&bitcoin_signature__descriptor, &signature__descriptor,
NULL, NULL,
0, /* flags */ 0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */

96
lightning.pb-c.h

@ -16,9 +16,9 @@ PROTOBUF_C__BEGIN_DECLS
typedef struct _Sha256Hash Sha256Hash; typedef struct _Sha256Hash Sha256Hash;
typedef struct _Signature Signature;
typedef struct _BitcoinInput BitcoinInput; typedef struct _BitcoinInput BitcoinInput;
typedef struct _BitcoinOutput BitcoinOutput; typedef struct _BitcoinOutput BitcoinOutput;
typedef struct _BitcoinSignature BitcoinSignature;
typedef struct _BitcoinPubkey BitcoinPubkey; typedef struct _BitcoinPubkey BitcoinPubkey;
typedef struct _Anchor Anchor; typedef struct _Anchor Anchor;
typedef struct _OpenChannel OpenChannel; typedef struct _OpenChannel OpenChannel;
@ -46,7 +46,7 @@ typedef struct _Pkt Pkt;
/* --- messages --- */ /* --- messages --- */
/* /*
* Protobufs don't have fixed-length fields, so this is a hack. * Protobufs don't have fixed-length fields, so these are a hack.
*/ */
struct _Sha256Hash struct _Sha256Hash
{ {
@ -61,6 +61,23 @@ struct _Sha256Hash
, 0, 0, 0, 0 } , 0, 0, 0, 0 }
struct _Signature
{
ProtobufCMessage base;
uint64_t r1;
uint64_t r2;
uint64_t r3;
uint64_t r4;
uint64_t s1;
uint64_t s2;
uint64_t s3;
uint64_t s4;
};
#define SIGNATURE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&signature__descriptor) \
, 0, 0, 0, 0, 0, 0, 0, 0 }
/* /*
* Identifies consumption of a bitcoin output. * Identifies consumption of a bitcoin output.
*/ */
@ -103,19 +120,6 @@ struct _BitcoinOutput
, 0, {0,NULL} } , 0, {0,NULL} }
/*
* A signature to use for a transaction; DER encoded with sigtype at the end.
*/
struct _BitcoinSignature
{
ProtobufCMessage base;
ProtobufCBinaryData der_then_sigtype;
};
#define BITCOIN_SIGNATURE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&bitcoin_signature__descriptor) \
, {0,NULL} }
/* /*
* Pubkey for commitment transaction input. * Pubkey for commitment transaction input.
*/ */
@ -215,7 +219,7 @@ struct _OpenChannel
struct _OpenCommitSig struct _OpenCommitSig
{ {
ProtobufCMessage base; ProtobufCMessage base;
BitcoinSignature *sig; Signature *sig;
}; };
#define OPEN_COMMIT_SIG__INIT \ #define OPEN_COMMIT_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \
@ -291,14 +295,14 @@ struct _Update
/* /*
* Signature for new commitment tx. * Signature for new commitment tx.
*/ */
BitcoinSignature *sig; Signature *sig;
/* /*
* Signature for old anchor (if any) * Signature for old anchor (if any)
*/ */
/* /*
* FIXME: optional HTLC ops. * FIXME: optional HTLC ops.
*/ */
BitcoinSignature *old_anchor_sig; Signature *old_anchor_sig;
}; };
#define UPDATE__INIT \ #define UPDATE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&update__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&update__descriptor) \
@ -314,11 +318,11 @@ struct _UpdateAccept
/* /*
* Signature for new commitment tx. * Signature for new commitment tx.
*/ */
BitcoinSignature *sig; Signature *sig;
/* /*
* Signature for old anchor (if any) * Signature for old anchor (if any)
*/ */
BitcoinSignature *old_anchor_sig; Signature *old_anchor_sig;
/* /*
* Hash preimage which revokes old commitment tx. * Hash preimage which revokes old commitment tx.
*/ */
@ -380,7 +384,7 @@ struct _NewAnchorAck
struct _NewAnchorCommitSig struct _NewAnchorCommitSig
{ {
ProtobufCMessage base; ProtobufCMessage base;
BitcoinSignature *sig; Signature *sig;
}; };
#define NEW_ANCHOR_COMMIT_SIG__INIT \ #define NEW_ANCHOR_COMMIT_SIG__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&new_anchor_commit_sig__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&new_anchor_commit_sig__descriptor) \
@ -425,7 +429,7 @@ struct _CloseChannel
* This is our signature a new transaction which spends my current * This is our signature a new transaction which spends my current
* commitment tx output 0 (which is 2/2) to script_to_me. * commitment tx output 0 (which is 2/2) to script_to_me.
*/ */
BitcoinSignature *sig; Signature *sig;
}; };
#define CLOSE_CHANNEL__INIT \ #define CLOSE_CHANNEL__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \
@ -442,7 +446,7 @@ struct _CloseChannelComplete
* This is our signature a new transaction which spends your current * This is our signature a new transaction which spends your current
* commitment tx output 0 (which is 2/2) to your script_to_me. * commitment tx output 0 (which is 2/2) to your script_to_me.
*/ */
BitcoinSignature *sig; Signature *sig;
}; };
#define CLOSE_CHANNEL_COMPLETE__INIT \ #define CLOSE_CHANNEL_COMPLETE__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \
@ -545,6 +549,25 @@ Sha256Hash *
void sha256_hash__free_unpacked void sha256_hash__free_unpacked
(Sha256Hash *message, (Sha256Hash *message,
ProtobufCAllocator *allocator); ProtobufCAllocator *allocator);
/* Signature methods */
void signature__init
(Signature *message);
size_t signature__get_packed_size
(const Signature *message);
size_t signature__pack
(const Signature *message,
uint8_t *out);
size_t signature__pack_to_buffer
(const Signature *message,
ProtobufCBuffer *buffer);
Signature *
signature__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void signature__free_unpacked
(Signature *message,
ProtobufCAllocator *allocator);
/* BitcoinInput methods */ /* BitcoinInput methods */
void bitcoin_input__init void bitcoin_input__init
(BitcoinInput *message); (BitcoinInput *message);
@ -583,25 +606,6 @@ BitcoinOutput *
void bitcoin_output__free_unpacked void bitcoin_output__free_unpacked
(BitcoinOutput *message, (BitcoinOutput *message,
ProtobufCAllocator *allocator); ProtobufCAllocator *allocator);
/* BitcoinSignature methods */
void bitcoin_signature__init
(BitcoinSignature *message);
size_t bitcoin_signature__get_packed_size
(const BitcoinSignature *message);
size_t bitcoin_signature__pack
(const BitcoinSignature *message,
uint8_t *out);
size_t bitcoin_signature__pack_to_buffer
(const BitcoinSignature *message,
ProtobufCBuffer *buffer);
BitcoinSignature *
bitcoin_signature__unpack
(ProtobufCAllocator *allocator,
size_t len,
const uint8_t *data);
void bitcoin_signature__free_unpacked
(BitcoinSignature *message,
ProtobufCAllocator *allocator);
/* BitcoinPubkey methods */ /* BitcoinPubkey methods */
void bitcoin_pubkey__init void bitcoin_pubkey__init
(BitcoinPubkey *message); (BitcoinPubkey *message);
@ -968,15 +972,15 @@ void pkt__free_unpacked
typedef void (*Sha256Hash_Closure) typedef void (*Sha256Hash_Closure)
(const Sha256Hash *message, (const Sha256Hash *message,
void *closure_data); void *closure_data);
typedef void (*Signature_Closure)
(const Signature *message,
void *closure_data);
typedef void (*BitcoinInput_Closure) typedef void (*BitcoinInput_Closure)
(const BitcoinInput *message, (const BitcoinInput *message,
void *closure_data); void *closure_data);
typedef void (*BitcoinOutput_Closure) typedef void (*BitcoinOutput_Closure)
(const BitcoinOutput *message, (const BitcoinOutput *message,
void *closure_data); void *closure_data);
typedef void (*BitcoinSignature_Closure)
(const BitcoinSignature *message,
void *closure_data);
typedef void (*BitcoinPubkey_Closure) typedef void (*BitcoinPubkey_Closure)
(const BitcoinPubkey *message, (const BitcoinPubkey *message,
void *closure_data); void *closure_data);
@ -1041,9 +1045,9 @@ typedef void (*Pkt_Closure)
/* --- descriptors --- */ /* --- descriptors --- */
extern const ProtobufCMessageDescriptor sha256_hash__descriptor; extern const ProtobufCMessageDescriptor sha256_hash__descriptor;
extern const ProtobufCMessageDescriptor signature__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_input__descriptor; extern const ProtobufCMessageDescriptor bitcoin_input__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_output__descriptor; extern const ProtobufCMessageDescriptor bitcoin_output__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_signature__descriptor;
extern const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor; extern const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor;
extern const ProtobufCMessageDescriptor anchor__descriptor; extern const ProtobufCMessageDescriptor anchor__descriptor;
extern const ProtobufCMessageDescriptor open_channel__descriptor; extern const ProtobufCMessageDescriptor open_channel__descriptor;

34
lightning.proto

@ -5,7 +5,7 @@
// Helper Types // Helper Types
// //
// Protobufs don't have fixed-length fields, so this is a hack. // Protobufs don't have fixed-length fields, so these are a hack.
message sha256_hash { message sha256_hash {
required fixed64 a = 1; required fixed64 a = 1;
required fixed64 b = 2; required fixed64 b = 2;
@ -13,6 +13,17 @@ message sha256_hash {
required fixed64 d = 4; required fixed64 d = 4;
} }
message signature {
required fixed64 r1 = 1;
required fixed64 r2 = 2;
required fixed64 r3 = 3;
required fixed64 r4 = 4;
required fixed64 s1 = 5;
required fixed64 s2 = 6;
required fixed64 s3 = 7;
required fixed64 s4 = 8;
}
// Identifies consumption of a bitcoin output. // Identifies consumption of a bitcoin output.
message bitcoin_input { message bitcoin_input {
// This is the transaction ID. // This is the transaction ID.
@ -31,11 +42,6 @@ message bitcoin_output {
required bytes script = 2; required bytes script = 2;
} }
// A signature to use for a transaction; DER encoded with sigtype at the end.
message bitcoin_signature {
required bytes der_then_sigtype = 1;
};
// Pubkey for commitment transaction input. // Pubkey for commitment transaction input.
message bitcoin_pubkey { message bitcoin_pubkey {
// Either 65 or 33 bytes. // Either 65 or 33 bytes.
@ -82,7 +88,7 @@ message open_channel {
// Supply signature for commitment tx // Supply signature for commitment tx
message open_commit_sig { message open_commit_sig {
required bitcoin_signature sig = 1; required signature sig = 1;
} }
// Supply ScriptSig for each anchor tx inputs. // Supply ScriptSig for each anchor tx inputs.
@ -116,18 +122,18 @@ message update {
// Change in current payment to-me (implies reverse to-you). // Change in current payment to-me (implies reverse to-you).
required sint64 delta = 2; required sint64 delta = 2;
// Signature for new commitment tx. // Signature for new commitment tx.
required bitcoin_signature sig = 3; required signature sig = 3;
// Signature for old anchor (if any) // Signature for old anchor (if any)
optional bitcoin_signature old_anchor_sig = 4; optional signature old_anchor_sig = 4;
// FIXME: optional HTLC ops. // FIXME: optional HTLC ops.
} }
// OK, I accept that update. // OK, I accept that update.
message update_accept { message update_accept {
// Signature for new commitment tx. // Signature for new commitment tx.
required bitcoin_signature sig = 1; required signature sig = 1;
// Signature for old anchor (if any) // Signature for old anchor (if any)
optional bitcoin_signature old_anchor_sig = 2; optional signature old_anchor_sig = 2;
// Hash preimage which revokes old commitment tx. // Hash preimage which revokes old commitment tx.
required sha256_hash revocation_preimage = 3; required sha256_hash revocation_preimage = 3;
} }
@ -151,7 +157,7 @@ message new_anchor_ack {
// Now we both send signatures for new commit sig. // Now we both send signatures for new commit sig.
message new_anchor_commit_sig { message new_anchor_commit_sig {
required bitcoin_signature sig = 1; required signature sig = 1;
} }
// Here are the script sigs for the new anchor's new inputs. // Here are the script sigs for the new anchor's new inputs.
@ -169,14 +175,14 @@ message new_anchor_complete {
message close_channel { message close_channel {
// This is our signature a new transaction which spends my current // This is our signature a new transaction which spends my current
// commitment tx output 0 (which is 2/2) to script_to_me. // commitment tx output 0 (which is 2/2) to script_to_me.
required bitcoin_signature sig = 1; required signature sig = 1;
} }
// OK, here's my sig so you can broadcast it too. // OK, here's my sig so you can broadcast it too.
message close_channel_complete { message close_channel_complete {
// This is our signature a new transaction which spends your current // This is our signature a new transaction which spends your current
// commitment tx output 0 (which is 2/2) to your script_to_me. // commitment tx output 0 (which is 2/2) to your script_to_me.
required bitcoin_signature sig = 1; required signature sig = 1;
} }
// This means we're going to hang up; it's to help diagnose only! // This means we're going to hang up; it's to help diagnose only!

4
open-anchor-sig.c

@ -25,7 +25,7 @@ static u8 *tx_scriptsig(const tal_t *ctx,
EC_KEY *privkey, EC_KEY *privkey,
const struct bitcoin_compressed_pubkey *pubkey) const struct bitcoin_compressed_pubkey *pubkey)
{ {
u8 *sig; struct signature *sig;
struct bitcoin_address addr; struct bitcoin_address addr;
sig = sign_tx_input(ctx, tx, i, sig = sign_tx_input(ctx, tx, i,
@ -37,7 +37,7 @@ static u8 *tx_scriptsig(const tal_t *ctx,
if (!is_pay_to_pubkey_hash(&input->subscript)) if (!is_pay_to_pubkey_hash(&input->subscript))
errx(1, "FIXME: Don't know how to handle input"); errx(1, "FIXME: Don't know how to handle input");
bitcoin_address(pubkey, &addr); bitcoin_address(pubkey, &addr);
return scriptsig_pay_to_pubkeyhash(ctx, &addr, sig, tal_count(sig)); return scriptsig_pay_to_pubkeyhash(ctx, &addr, sig);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])

4
open-commit-sig.c

@ -27,7 +27,7 @@ int main(int argc, char *argv[])
struct bitcoin_tx *anchor, *commit; struct bitcoin_tx *anchor, *commit;
struct sha256_double txid; struct sha256_double txid;
struct pkt *pkt; struct pkt *pkt;
u8 *sig; struct signature *sig;
size_t *inmap, *outmap; size_t *inmap, *outmap;
EC_KEY *privkey; EC_KEY *privkey;
bool testnet; bool testnet;
@ -76,7 +76,7 @@ int main(int argc, char *argv[])
sig = sign_tx_input(ctx, commit, 0, anchor->output[outmap[0]].script, sig = sign_tx_input(ctx, commit, 0, anchor->output[outmap[0]].script,
anchor->output[outmap[0]].script_length, privkey); anchor->output[outmap[0]].script_length, privkey);
pkt = open_commit_sig_pkt(ctx, sig, tal_count(sig)); pkt = open_commit_sig_pkt(ctx, sig);
if (!write_all(STDOUT_FILENO, pkt, if (!write_all(STDOUT_FILENO, pkt,
sizeof(pkt->len) + le32_to_cpu(pkt->len))) sizeof(pkt->len) + le32_to_cpu(pkt->len)))
err(1, "Writing out packet"); err(1, "Writing out packet");

41
pkt.c

@ -1,10 +1,10 @@
#include <ccan/crypto/sha256/sha256.h> #include <ccan/crypto/sha256/sha256.h>
#include <ccan/tal/grab_file/grab_file.h> #include <ccan/tal/grab_file/grab_file.h>
#include <ccan/err/err.h> #include <ccan/err/err.h>
#include <ccan/cast/cast.h>
#include "pkt.h" #include "pkt.h"
#include "bitcoin_tx.h" #include "bitcoin_tx.h"
#include "bitcoin_address.h" #include "bitcoin_address.h"
#include "signature.h"
#include <stdio.h> #include <stdio.h>
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg) static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg)
@ -47,6 +47,37 @@ void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash)
memcpy(hash->u.u8 + 24, &pb->d, 8); memcpy(hash->u.u8 + 24, &pb->d, 8);
} }
Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig)
{
Signature *pb = tal(ctx, Signature);
signature__init(pb);
/* Kill me now... */
memcpy(&pb->r1, sig->r, 8);
memcpy(&pb->r2, sig->r + 8, 8);
memcpy(&pb->r3, sig->r + 16, 8);
memcpy(&pb->r4, sig->r + 24, 8);
memcpy(&pb->s1, sig->s, 8);
memcpy(&pb->s2, sig->s + 8, 8);
memcpy(&pb->s3, sig->s + 16, 8);
memcpy(&pb->s4, sig->s + 24, 8);
return pb;
}
void proto_to_signature(const Signature *pb, struct signature *sig)
{
/* Kill me again. */
memcpy(sig->r, &pb->r1, 8);
memcpy(sig->r + 8, &pb->r2, 8);
memcpy(sig->r + 16, &pb->r3, 8);
memcpy(sig->r + 24, &pb->r4, 8);
memcpy(sig->s, &pb->s1, 8);
memcpy(sig->s + 8, &pb->s2, 8);
memcpy(sig->s + 16, &pb->s3, 8);
memcpy(sig->s + 24, &pb->s4, 8);
}
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key) const struct bitcoin_compressed_pubkey *key)
{ {
@ -142,14 +173,10 @@ struct pkt *leak_anchor_sigs_and_pretend_we_didnt_pkt(const tal_t *ctx,
return to_pkt(ctx, PKT__PKT_OMG_FAIL, &omg_fail); return to_pkt(ctx, PKT__PKT_OMG_FAIL, &omg_fail);
} }
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const u8 *sig, size_t siglen) struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig)
{ {
OpenCommitSig o = OPEN_COMMIT_SIG__INIT; OpenCommitSig o = OPEN_COMMIT_SIG__INIT;
BitcoinSignature s = BITCOIN_SIGNATURE__INIT;
o.sig = &s;
s.der_then_sigtype.len = siglen;
s.der_then_sigtype.data = cast_const(u8 *, sig);
o.sig = signature_to_proto(ctx, sig);
return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o); return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o);
} }

9
pkt.h

@ -21,6 +21,7 @@ Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect);
struct sha256; struct sha256;
struct bitcoin_compressed_pubkey; struct bitcoin_compressed_pubkey;
struct signature;
/** /**
* openchannel_pkt - create an openchannel message * openchannel_pkt - create an openchannel message
@ -61,15 +62,17 @@ struct pkt *leak_anchor_sigs_and_pretend_we_didnt_pkt(const tal_t *ctx,
/** /**
* open_commit_sig_pkt - create an open_commit_sig message * open_commit_sig_pkt - create an open_commit_sig message
* @ctx: tal context to allocate off. * @ctx: tal context to allocate off.
* @sig: the der-encoded signature for the commit transaction input. * @sig: the signature for the commit transaction input.
* @siglen: the length of @sig.
*/ */
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const u8 *sig, size_t siglen); struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig);
/* Useful helper for allocating & populating a protobuf Sha256Hash */ /* Useful helper for allocating & populating a protobuf Sha256Hash */
Sha256Hash *sha256_to_proto(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); void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash);
Signature *signature_to_proto(const tal_t *ctx, const struct signature *sig);
void proto_to_signature(const Signature *pb, struct signature *sig);
BitcoinPubkey *pubkey_to_proto(const tal_t *ctx, BitcoinPubkey *pubkey_to_proto(const tal_t *ctx,
const struct bitcoin_compressed_pubkey *key); const struct bitcoin_compressed_pubkey *key);
#endif /* LIGHTNING_PKT_H */ #endif /* LIGHTNING_PKT_H */

31
signature.c

@ -6,12 +6,12 @@
#include <assert.h> #include <assert.h>
#include <ccan/cast/cast.h> #include <ccan/cast/cast.h>
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key, struct signature *sign_hash(const tal_t *ctx, EC_KEY *private_key,
const struct sha256_double *h) const struct sha256_double *h)
{ {
ECDSA_SIG *sig; ECDSA_SIG *sig;
int len; int len;
unsigned char *der, *ret; struct signature *s;
sig = ECDSA_do_sign(h->sha.u.u8, sizeof(*h), private_key); sig = ECDSA_do_sign(h->sha.u.u8, sizeof(*h), private_key);
if (!sig) if (!sig)
@ -33,21 +33,24 @@ u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key,
assert(!BN_is_odd(sig->s)); assert(!BN_is_odd(sig->s));
} }
/* This tells it to allocate for us. */ s = talz(ctx, struct signature);
der = NULL;
len = i2d_ECDSA_SIG(sig, &der);
ECDSA_SIG_free(sig);
if (len <= 0) /* Pack r and s into signature, 32 bytes each. */
return NULL; len = BN_num_bytes(sig->r);
assert(len <= sizeof(s->r));
BN_bn2bin(sig->r, s->r + sizeof(s->r) - len);
len = BN_num_bytes(sig->s);
assert(len <= sizeof(s->s));
BN_bn2bin(sig->s, s->s + sizeof(s->s) - len);
ret = tal_dup_arr(ctx, u8, der, len, 0); ECDSA_SIG_free(sig);
OPENSSL_free(der); return s;
return ret;
} }
u8 *sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx, unsigned int in, struct signature *sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx,
const u8 *subscript, size_t subscript_len, EC_KEY *privkey) unsigned int in,
const u8 *subscript, size_t subscript_len,
EC_KEY *privkey)
{ {
struct sha256_double hash; struct sha256_double hash;
struct sha256_ctx shactx; struct sha256_ctx shactx;

16
signature.h

@ -11,14 +11,22 @@ enum sighash_type {
SIGHASH_ANYONECANPAY = 0x80 SIGHASH_ANYONECANPAY = 0x80
}; };
/* ECDSA of double SHA256. */
struct signature {
u8 r[32];
u8 s[32];
};
struct sha256_double; struct sha256_double;
struct bitcoin_tx; struct bitcoin_tx;
u8 *sign_hash(const tal_t *ctx, EC_KEY *private_key, struct signature *sign_hash(const tal_t *ctx, EC_KEY *private_key,
const struct sha256_double *h); const struct sha256_double *h);
/* All tx input scripts must be set to 0 len. */ /* All tx input scripts must be set to 0 len. */
u8 *sign_tx_input(const tal_t *ctx, struct bitcoin_tx *tx, unsigned int in, struct signature *sign_tx_input(const tal_t *ctx,
const u8 *subscript, size_t subscript_len, EC_KEY *privkey); struct bitcoin_tx *tx, unsigned int in,
const u8 *subscript, size_t subscript_len,
EC_KEY *privkey);
#endif /* LIGHTNING_SIGNATURE_H */ #endif /* LIGHTNING_SIGNATURE_H */

Loading…
Cancel
Save