From 29d0cdc3cdb9a4b72558a2969d5ba24953f34e99 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 5 Jun 2015 11:37:27 +0930 Subject: [PATCH] open-channel: use pubkey, not arbitrary script for final outout address. We need to pay to this from two places: on their side, it's a simple payment, on our side, it's a complex timeout-or-mutual-or-hval script, which doesn't lend itself to arbitrary scripts. Use P2SH, of course. Signed-off-by: Rusty Russell --- commit_tx.c | 14 +++++++++----- lightning.pb-c.c | 10 +++++----- lightning.pb-c.h | 4 ++-- lightning.proto | 2 +- open-channel.c | 27 ++++++++++++--------------- pkt.c | 7 +++---- pkt.h | 6 +++--- 7 files changed, 35 insertions(+), 35 deletions(-) diff --git a/commit_tx.c b/commit_tx.c index 52e371bda..0aaf1ffb8 100644 --- a/commit_tx.c +++ b/commit_tx.c @@ -14,7 +14,7 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, { struct bitcoin_tx *tx; const u8 *redeemscript; - struct pubkey ourkey, theirkey; + struct pubkey ourkey, theirkey, to_me; struct sha256 redeem; /* Now create commitment tx: one input, two outputs. */ @@ -42,10 +42,14 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, return tal_free(tx); tx->output[0].amount = ours->anchor->total - ours->commitment_fee; - /* Second output is a simple payment to them. */ - tx->output[1].script = theirs->script_to_me.data; - tx->output[1].script_length = theirs->script_to_me.len; - + /* Second output is a P2SH payment to them. */ + if (!proto_to_pubkey(theirs->to_me, &to_me)) + return tal_free(tx); + tx->output[1].script = scriptpubkey_p2sh(ctx, + bitcoin_redeem_single(ctx, + &to_me)); + tx->output[1].script_length = tal_count(tx->output[1].script); + if (theirs->anchor->total < theirs->commitment_fee) return tal_free(tx); tx->output[1].amount = theirs->anchor->total - theirs->commitment_fee; diff --git a/lightning.pb-c.c b/lightning.pb-c.c index f5909c94d..c55dc1957 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -1513,13 +1513,13 @@ static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "script_to_me", + "to_me", 5, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_BYTES, + PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(OpenChannel, script_to_me), - NULL, + offsetof(OpenChannel, to_me), + &bitcoin_pubkey__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1566,8 +1566,8 @@ static const unsigned open_channel__field_indices_by_name[] = { 4, /* field[4] = commitment_fee */ 1, /* field[1] = locktime_seconds */ 2, /* field[2] = revocation_hash */ - 3, /* field[3] = script_to_me */ 0, /* field[0] = seed */ + 3, /* field[3] = to_me */ 6, /* field[6] = tx_version */ }; static const ProtobufCIntRange open_channel__number_ranges[2 + 1] = diff --git a/lightning.pb-c.h b/lightning.pb-c.h index de1ce7118..f826ba60d 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -194,7 +194,7 @@ struct _OpenChannel /* * How to pay money to us from commit_tx. */ - ProtobufCBinaryData script_to_me; + BitcoinPubkey *to_me; /* * How much transaction fee we'll pay for commitment txs. */ @@ -210,7 +210,7 @@ struct _OpenChannel }; #define OPEN_CHANNEL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \ - , 0, 0, NULL, {0,NULL}, 0, NULL, 0 } + , 0, 0, NULL, NULL, 0, NULL, 0 } /* diff --git a/lightning.proto b/lightning.proto index 9b448613f..1455117d4 100644 --- a/lightning.proto +++ b/lightning.proto @@ -77,7 +77,7 @@ message open_channel { // Hash seed for revoking commitment transactions. required sha256_hash revocation_hash = 4; // How to pay money to us from commit_tx. - required bytes script_to_me = 5; + required bitcoin_pubkey to_me = 5; // How much transaction fee we'll pay for commitment txs. required uint64 commitment_fee = 6; // The anchor transaction details. diff --git a/open-channel.c b/open-channel.c index 8888a053d..e6acabfb4 100644 --- a/open-channel.c +++ b/open-channel.c @@ -1,6 +1,6 @@ /* 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 + * ./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 */ #include #include @@ -102,17 +102,16 @@ static u64 weak_random64(void) int main(int argc, char *argv[]) { struct sha256 seed, revocation_hash; - struct bitcoin_address changeaddr, returnaddr; + struct bitcoin_address changeaddr; struct pkt *pkt; const tal_t *ctx = tal_arr(NULL, char, 0); Anchor anchor = ANCHOR__INIT; u64 commit_tx_fee, total_in; unsigned int locktime_seconds; bool testnet; - u8 *script_to_me; size_t i; - struct pubkey commitkey; - EC_KEY *commitprivkey; + struct pubkey commitkey, outkey; + EC_KEY *commitprivkey, *outprivkey; err_set_progname(argv[0]); @@ -126,7 +125,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", @@ -168,10 +167,12 @@ int main(int argc, char *argv[]) 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]); + outprivkey = key_from_base58(argv[5], strlen(argv[5]), &testnet, + &outkey); + if (!outprivkey) + errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) - errx(1, "Bitcoin address '%s' not on testnet!", argv[5]); + errx(1, "Private key '%s' not on testnet!", argv[5]); anchor.n_inputs = (argc - 6); anchor.inputs = tal_arr(ctx, BitcoinInput *, anchor.n_inputs); @@ -205,11 +206,7 @@ int main(int argc, char *argv[]) /* Get first revocation hash. */ shachain_from_seed(&seed, 0, &revocation_hash); - /* Make simple output script to pay to my pubkey. */ - 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, + pkt = openchannel_pkt(ctx, weak_random64(), &revocation_hash, &outkey, commit_tx_fee, locktime_seconds, &anchor); if (!write_all(STDOUT_FILENO, pkt, diff --git a/pkt.c b/pkt.c index 8a4f53509..aa22e7e44 100644 --- a/pkt.c +++ b/pkt.c @@ -4,6 +4,7 @@ #include "pkt.h" #include "bitcoin_tx.h" #include "bitcoin_address.h" +#include "pubkey.h" #include "signature.h" #include @@ -50,8 +51,7 @@ void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash) struct pkt *openchannel_pkt(const tal_t *ctx, u64 seed, const struct sha256 *revocation_hash, - size_t script_len, - const void *script, + const struct pubkey *to_me, u64 commitment_fee, u32 rel_locktime_seconds, Anchor *anchor) @@ -64,8 +64,7 @@ struct pkt *openchannel_pkt(const tal_t *ctx, o.seed = seed; o.revocation_hash = sha256_to_proto(ctx, revocation_hash); - o.script_to_me.len = script_len; - o.script_to_me.data = (void *)script; + o.to_me = pubkey_to_proto(ctx, to_me); o.commitment_fee = commitment_fee; o.anchor = anchor; o.locktime_seconds = rel_locktime_seconds; diff --git a/pkt.h b/pkt.h index 361650f73..7bf91b31d 100644 --- a/pkt.h +++ b/pkt.h @@ -22,13 +22,14 @@ Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect); struct sha256; struct bitcoin_compressed_pubkey; struct signature; +struct pubkey; /** * 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. - * @script_len, @script: the script which pays to us. + * @to_me: the pubkey for the commit transactions' P2SH output. * @commitment_fee: the fee to use for commitment tx. * @rel_locktime_seconds: relative seconds for commitment locktime. * @anchor: the anchor transaction details. @@ -36,8 +37,7 @@ struct signature; struct pkt *openchannel_pkt(const tal_t *ctx, u64 seed, const struct sha256 *revocation_hash, - size_t script_len, - const void *script, + const struct pubkey *to_me, u64 commitment_fee, u32 rel_locktime_seconds, Anchor *anchor);