From d30c470c7da1d7d66e062aa5ff9001f8be5bb113 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 5 Jun 2015 12:24:58 +0930 Subject: [PATCH] anchor: change is not an arbitrary output, but a pubkey we p2sh to. Gets rid of the last pubkey user; they're generally deprecated. Signed-off-by: Rusty Russell --- anchor.c | 20 ++++- lightning.pb-c.c | 190 +++++++++++++++++++++++------------------------ lightning.pb-c.h | 78 +++++++++---------- lightning.proto | 14 ++-- open-channel.c | 27 +++---- pubkey.c | 13 ++++ pubkey.h | 3 + 7 files changed, 183 insertions(+), 162 deletions(-) diff --git a/anchor.c b/anchor.c index a9f2f5292..c81c6509b 100644 --- a/anchor.c +++ b/anchor.c @@ -66,15 +66,27 @@ struct bitcoin_tx *anchor_tx_create(const tal_t *ctx, n_out = 1; if (o1->anchor->change) { struct bitcoin_tx_output *out = &tx->output[n_out++]; + struct pubkey key; + + if (!proto_to_pubkey(o1->anchor->change->pubkey, &key)) + return tal_free(tx); + out->amount = o1->anchor->change->amount; - out->script_length = o1->anchor->change->script.len; - out->script = o1->anchor->change->script.data; + out->script = scriptpubkey_p2sh(tx, + bitcoin_redeem_single(tx, &key)); + out->script_length = tal_count(out->script); } if (o2->anchor->change) { struct bitcoin_tx_output *out = &tx->output[n_out++]; + struct pubkey key; + + if (!proto_to_pubkey(o2->anchor->change->pubkey, &key)) + return tal_free(tx); + out->amount = o2->anchor->change->amount; - out->script_length = o2->anchor->change->script.len; - out->script = o2->anchor->change->script.data; + out->script = scriptpubkey_p2sh(tx, + bitcoin_redeem_single(tx, &key)); + out->script_length = tal_count(out->script); } assert(n_out == tx->output_count); diff --git a/lightning.pb-c.c b/lightning.pb-c.c index c55dc1957..bf4a6a3b3 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -136,49 +136,6 @@ void bitcoin_input__free_unpacked assert(message->base.descriptor == &bitcoin_input__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void bitcoin_output__init - (BitcoinOutput *message) -{ - static BitcoinOutput init_value = BITCOIN_OUTPUT__INIT; - *message = init_value; -} -size_t bitcoin_output__get_packed_size - (const BitcoinOutput *message) -{ - assert(message->base.descriptor == &bitcoin_output__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t bitcoin_output__pack - (const BitcoinOutput *message, - uint8_t *out) -{ - assert(message->base.descriptor == &bitcoin_output__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t bitcoin_output__pack_to_buffer - (const BitcoinOutput *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &bitcoin_output__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -BitcoinOutput * - bitcoin_output__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (BitcoinOutput *) - protobuf_c_message_unpack (&bitcoin_output__descriptor, - allocator, len, data); -} -void bitcoin_output__free_unpacked - (BitcoinOutput *message, - ProtobufCAllocator *allocator) -{ - assert(message->base.descriptor == &bitcoin_output__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} void bitcoin_pubkey__init (BitcoinPubkey *message) { @@ -222,6 +179,49 @@ void bitcoin_pubkey__free_unpacked assert(message->base.descriptor == &bitcoin_pubkey__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void change__init + (Change *message) +{ + static Change init_value = CHANGE__INIT; + *message = init_value; +} +size_t change__get_packed_size + (const Change *message) +{ + assert(message->base.descriptor == &change__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t change__pack + (const Change *message, + uint8_t *out) +{ + assert(message->base.descriptor == &change__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t change__pack_to_buffer + (const Change *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &change__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Change * + change__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Change *) + protobuf_c_message_unpack (&change__descriptor, + allocator, len, data); +} +void change__free_unpacked + (Change *message, + ProtobufCAllocator *allocator) +{ + assert(message->base.descriptor == &change__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void anchor__init (Anchor *message) { @@ -1279,57 +1279,6 @@ const ProtobufCMessageDescriptor bitcoin_input__descriptor = (ProtobufCMessageInit) bitcoin_input__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor bitcoin_output__field_descriptors[2] = -{ - { - "amount", - 1, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(BitcoinOutput, amount), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "script", - 2, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_BYTES, - 0, /* quantifier_offset */ - offsetof(BitcoinOutput, script), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned bitcoin_output__field_indices_by_name[] = { - 0, /* field[0] = amount */ - 1, /* field[1] = script */ -}; -static const ProtobufCIntRange bitcoin_output__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 2 } -}; -const ProtobufCMessageDescriptor bitcoin_output__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "bitcoin_output", - "BitcoinOutput", - "BitcoinOutput", - "", - sizeof(BitcoinOutput), - 2, - bitcoin_output__field_descriptors, - bitcoin_output__field_indices_by_name, - 1, bitcoin_output__number_ranges, - (ProtobufCMessageInit) bitcoin_output__init, - NULL,NULL,NULL /* reserved[123] */ -}; static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] = { { @@ -1368,6 +1317,57 @@ const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor = (ProtobufCMessageInit) bitcoin_pubkey__init, NULL,NULL,NULL /* reserved[123] */ }; +static const ProtobufCFieldDescriptor change__field_descriptors[2] = +{ + { + "amount", + 1, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_UINT64, + 0, /* quantifier_offset */ + offsetof(Change, amount), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "pubkey", + 2, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Change, pubkey), + &bitcoin_pubkey__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned change__field_indices_by_name[] = { + 0, /* field[0] = amount */ + 1, /* field[1] = pubkey */ +}; +static const ProtobufCIntRange change__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor change__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "change", + "Change", + "Change", + "", + sizeof(Change), + 2, + change__field_descriptors, + change__field_indices_by_name, + 1, change__number_ranges, + (ProtobufCMessageInit) change__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCFieldDescriptor anchor__field_descriptors[6] = { { @@ -1389,7 +1389,7 @@ static const ProtobufCFieldDescriptor anchor__field_descriptors[6] = PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ offsetof(Anchor, change), - &bitcoin_output__descriptor, + &change__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ diff --git a/lightning.pb-c.h b/lightning.pb-c.h index f826ba60d..df8f90c29 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -18,8 +18,8 @@ PROTOBUF_C__BEGIN_DECLS typedef struct _Sha256Hash Sha256Hash; typedef struct _Signature Signature; typedef struct _BitcoinInput BitcoinInput; -typedef struct _BitcoinOutput BitcoinOutput; typedef struct _BitcoinPubkey BitcoinPubkey; +typedef struct _Change Change; typedef struct _Anchor Anchor; typedef struct _OpenChannel OpenChannel; typedef struct _OpenCommitSig OpenCommitSig; @@ -106,20 +106,6 @@ struct _BitcoinInput , NULL, 0, {0,NULL}, 0 } -/* - * A bitcoin output - */ -struct _BitcoinOutput -{ - ProtobufCMessage base; - uint64_t amount; - ProtobufCBinaryData script; -}; -#define BITCOIN_OUTPUT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&bitcoin_output__descriptor) \ - , 0, {0,NULL} } - - /* * Pubkey for commitment transaction input. */ @@ -136,6 +122,20 @@ struct _BitcoinPubkey , {0,NULL} } +/* + * Change, if we want any. + */ +struct _Change +{ + ProtobufCMessage base; + uint64_t amount; + BitcoinPubkey *pubkey; +}; +#define CHANGE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&change__descriptor) \ + , 0, NULL } + + /* * All about an anchor transaction. */ @@ -154,7 +154,7 @@ struct _Anchor /* * Any change from anchor (in case we don't want to use them all) */ - BitcoinOutput *change; + Change *change; /* * How much transaction fee we'll pay in the anchor tx. */ @@ -591,25 +591,6 @@ BitcoinInput * void bitcoin_input__free_unpacked (BitcoinInput *message, ProtobufCAllocator *allocator); -/* BitcoinOutput methods */ -void bitcoin_output__init - (BitcoinOutput *message); -size_t bitcoin_output__get_packed_size - (const BitcoinOutput *message); -size_t bitcoin_output__pack - (const BitcoinOutput *message, - uint8_t *out); -size_t bitcoin_output__pack_to_buffer - (const BitcoinOutput *message, - ProtobufCBuffer *buffer); -BitcoinOutput * - bitcoin_output__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void bitcoin_output__free_unpacked - (BitcoinOutput *message, - ProtobufCAllocator *allocator); /* BitcoinPubkey methods */ void bitcoin_pubkey__init (BitcoinPubkey *message); @@ -629,6 +610,25 @@ BitcoinPubkey * void bitcoin_pubkey__free_unpacked (BitcoinPubkey *message, ProtobufCAllocator *allocator); +/* Change methods */ +void change__init + (Change *message); +size_t change__get_packed_size + (const Change *message); +size_t change__pack + (const Change *message, + uint8_t *out); +size_t change__pack_to_buffer + (const Change *message, + ProtobufCBuffer *buffer); +Change * + change__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void change__free_unpacked + (Change *message, + ProtobufCAllocator *allocator); /* Anchor methods */ void anchor__init (Anchor *message); @@ -982,12 +982,12 @@ typedef void (*Signature_Closure) typedef void (*BitcoinInput_Closure) (const BitcoinInput *message, void *closure_data); -typedef void (*BitcoinOutput_Closure) - (const BitcoinOutput *message, - void *closure_data); typedef void (*BitcoinPubkey_Closure) (const BitcoinPubkey *message, void *closure_data); +typedef void (*Change_Closure) + (const Change *message, + void *closure_data); typedef void (*Anchor_Closure) (const Anchor *message, void *closure_data); @@ -1051,8 +1051,8 @@ typedef void (*Pkt_Closure) extern const ProtobufCMessageDescriptor sha256_hash__descriptor; extern const ProtobufCMessageDescriptor signature__descriptor; extern const ProtobufCMessageDescriptor bitcoin_input__descriptor; -extern const ProtobufCMessageDescriptor bitcoin_output__descriptor; extern const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor; +extern const ProtobufCMessageDescriptor change__descriptor; extern const ProtobufCMessageDescriptor anchor__descriptor; extern const ProtobufCMessageDescriptor open_channel__descriptor; extern const ProtobufCMessageDescriptor open_commit_sig__descriptor; diff --git a/lightning.proto b/lightning.proto index 1455117d4..509af4245 100644 --- a/lightning.proto +++ b/lightning.proto @@ -36,18 +36,18 @@ message bitcoin_input { required uint64 amount = 4; } -// A bitcoin output -message bitcoin_output { - required uint64 amount = 1; - required bytes script = 2; -} - // Pubkey for commitment transaction input. message bitcoin_pubkey { // Either 65 or 33 bytes. required bytes key = 1; }; +// Change, if we want any. +message change { + required uint64 amount = 1; + required bitcoin_pubkey pubkey = 2; +} + // All about an anchor transaction. message anchor { // 0 or more unspent inputs we want to use for anchor. @@ -55,7 +55,7 @@ message anchor { // 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 change = 2; + optional change 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) diff --git a/open-channel.c b/open-channel.c index e6acabfb4..e6381b7fa 100644 --- a/open-channel.c +++ b/open-channel.c @@ -1,6 +1,6 @@ /* My example: - * ./open-channel 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff 50000000000 mzqiPPbjTdcgM6NpNWJLHFt29tWD69bciE cUBCjrdJu8tfvM7FT8So6aqs6G6bZS1Cax6Rc9rFzYL6nYG4XNEC cTuY5gncxDymqe9dfF7R8QFdAsxMZxdViRMjs8Dj7xJJRsQcmPCt 08ffaf638849198f9c8f04aa75d225a5a104d5e7c540770ca55ad08b9a32d10c/1/100000000000/76a9148d2d939aa2aff2d341cde3e61a89bf9c2c21d12388ac > A-open.pb - * ./open-channel 112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 9795000 mpDyc5kPAJZB7Zz9iW9acq3Jk8yiTJ7HKj cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi 8cb044605f33ca907b966701f49e0bd80b4294696b57f8cf45f22398a1e63a23/0/9800000/76a9143b2aab840afb327a12c8a90fb4ed45b6892eb80988ac > B-open.pb + * ./open-channel 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff 50000000000 030da36b810c0930e5fe8b74014665873f6901d9f46018a5fda743a93dec7f0e4e cUBCjrdJu8tfvM7FT8So6aqs6G6bZS1Cax6Rc9rFzYL6nYG4XNEC cTuY5gncxDymqe9dfF7R8QFdAsxMZxdViRMjs8Dj7xJJRsQcmPCt 08ffaf638849198f9c8f04aa75d225a5a104d5e7c540770ca55ad08b9a32d10c/1/100000000000/76a9148d2d939aa2aff2d341cde3e61a89bf9c2c21d12388ac > A-open.pb + * ./open-channel 112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 9795000 022e314a8f7a814e0900bf094f704b233dc693349cf55b888b43d902d7be251e95 cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi cQXhbUnNRsFcdzTQwjbCrud5yVskHTEas7tZPUWoJYNk5htGQrpi 8cb044605f33ca907b966701f49e0bd80b4294696b57f8cf45f22398a1e63a23/0/9800000/76a9143b2aab840afb327a12c8a90fb4ed45b6892eb80988ac > B-open.pb */ #include #include @@ -102,7 +102,6 @@ static u64 weak_random64(void) int main(int argc, char *argv[]) { struct sha256 seed, revocation_hash; - struct bitcoin_address changeaddr; struct pkt *pkt; const tal_t *ctx = tal_arr(NULL, char, 0); Anchor anchor = ANCHOR__INIT; @@ -110,7 +109,7 @@ int main(int argc, char *argv[]) unsigned int locktime_seconds; bool testnet; size_t i; - struct pubkey commitkey, outkey; + struct pubkey commitkey, outkey, changekey; EC_KEY *commitprivkey, *outprivkey; err_set_progname(argv[0]); @@ -125,7 +124,7 @@ int main(int argc, char *argv[]) locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60; opt_register_noarg("--help|-h", opt_usage_and_exit, - " ///...\n" + " ///...\n" "A test program to output openchannel on stdout.", "Print this message."); opt_register_arg("--min-anchor-confirms", @@ -153,10 +152,8 @@ int main(int argc, char *argv[]) if (!anchor.total) errx(1, "Invalid total: must be > 0"); - 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]); + if (!pubkey_from_hexstr(argv[3], &changekey)) + errx(1, "Invalid bitcoin pubkey '%s'", argv[3]); /* We don't really need the privkey here, but it's the most * convenient way to get the pubkey from bitcoind. */ @@ -192,15 +189,11 @@ int main(int argc, char *argv[]) /* 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 = tal(ctx, Change); + change__init(anchor.change); + anchor.change->pubkey = pubkey_to_proto(anchor.change, + &changekey); 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. */ diff --git a/pubkey.c b/pubkey.c index 064175e82..da77a30ae 100644 --- a/pubkey.c +++ b/pubkey.c @@ -1,5 +1,6 @@ #include "pubkey.h" #include +#include /* Must agree on key validity with bitcoin! Stolen from bitcoin/src/pubkey.h's * GetLen: @@ -52,3 +53,15 @@ bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key) memcpy(key->key, pb->key.data, pb->key.len); return true; } + +bool pubkey_from_hexstr(const char *str, struct pubkey *key) +{ + size_t slen = strlen(str), dlen; + dlen = hex_data_size(slen); + + if (dlen != 33 && dlen != 65) + return false; + if (!hex_decode(str, slen, key->key, dlen)) + return false; + return GetLen(key->key[0]) == dlen; +} diff --git a/pubkey.h b/pubkey.h index fd6c932fc..33cc8bc8b 100644 --- a/pubkey.h +++ b/pubkey.h @@ -15,4 +15,7 @@ bool proto_to_pubkey(const BitcoinPubkey *pb, struct pubkey *key); /* 33 or 65 bytes? */ size_t pubkey_len(const struct pubkey *key); +/* Convert from hex string (scriptPubKey from validateaddress) */ +bool pubkey_from_hexstr(const char *str, struct pubkey *key); + #endif /* LIGHTNING_PUBKEY_H */