close-channel: create message to mutually close channel.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2015-06-08 14:44:47 +09:30
parent 16baa1dae9
commit 38f7a23064
8 changed files with 183 additions and 4 deletions

View File

@ -3,9 +3,9 @@
# Needs to have oneof support: Ubuntu vivid's is too old :(
PROTOCC:=protoc-c
PROGRAMS := open-channel open-anchor-scriptsigs leak-anchor-sigs open-commit-sig check-commit-sig check-anchor-scriptsigs get-anchor-depth create-steal-tx create-commit-spend-tx
PROGRAMS := open-channel open-anchor-scriptsigs leak-anchor-sigs open-commit-sig check-commit-sig check-anchor-scriptsigs get-anchor-depth create-steal-tx create-commit-spend-tx close-channel
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o commit_tx.o pubkey.o opt_bits.o
HELPER_OBJS := base58.o lightning.pb-c.o shadouble.o pkt.o bitcoin_script.o permute_tx.o signature.o bitcoin_tx.o bitcoin_address.o anchor.o commit_tx.o pubkey.o opt_bits.o close_tx.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

101
close-channel.c Normal file
View File

@ -0,0 +1,101 @@
/* My example:
* ./close-channel A-anchor.tx A-open.pb B-open.pb cUBCjrdJu8tfvM7FT8So6aqs6G6bZS1Cax6Rc9rFzYL6nYG4XNEC > A-close.pb
*/
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <ccan/opt/opt.h>
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "base58.h"
#include "pkt.h"
#include "bitcoin_script.h"
#include "permute_tx.h"
#include "signature.h"
#include "pubkey.h"
#include "close_tx.h"
#include <openssl/ec.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
const tal_t *ctx = tal_arr(NULL, char, 0);
OpenChannel *o1, *o2;
struct bitcoin_tx *anchor, *close_tx;
struct sha256_double anchor_txid;
struct pkt *pkt;
struct signature sig;
EC_KEY *privkey;
bool testnet;
struct pubkey pubkey1, pubkey2;
u8 *redeemscript, *p2sh;
size_t i;
err_set_progname(argv[0]);
/* FIXME: Take update.pbs to adjust channel */
opt_register_noarg("--help|-h", opt_usage_and_exit,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey>\n"
"Create the signature needed for the close transaction",
"Print this message.");
opt_parse(&argc, argv, opt_log_stderr_exit);
if (argc != 5)
opt_usage_exit_fail("Expected 4 arguments");
anchor = bitcoin_tx_from_file(ctx, argv[1]);
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
privkey = key_from_base58(argv[4], strlen(argv[4]), &testnet, &pubkey1);
if (!privkey)
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
bitcoin_txid(anchor, &anchor_txid);
/* Get pubkeys */
if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2))
errx(1, "Invalid o1 commit pubkey");
if (pubkey_len(&pubkey1) != pubkey_len(&pubkey2)
|| memcmp(pubkey1.key, pubkey2.key, pubkey_len(&pubkey2)) != 0)
errx(1, "o1 pubkey != this privkey");
if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2))
errx(1, "Invalid o2 final pubkey");
/* This is what the anchor pays to; figure out whick output. */
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
/* This is the scriptPubKey commit tx will have */
p2sh = scriptpubkey_p2sh(ctx, redeemscript);
for (i = 0; i < anchor->output_count; i++) {
if (anchor->output[i].script_length != tal_count(p2sh))
continue;
if (memcmp(anchor->output[i].script, p2sh, tal_count(p2sh)) == 0)
break;
}
if (i == anchor->output_count)
errx(1, "No matching output in %s", argv[1]);
/* Now create the close tx to spend 2/2 output of anchor. */
close_tx = create_close_tx(ctx, o1, o2, &anchor_txid, i);
/* Sign it for them. */
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
privkey, &sig);
pkt = close_channel_pkt(ctx, &sig);
if (!write_all(STDOUT_FILENO, pkt,
sizeof(pkt->len) + le32_to_cpu(pkt->len)))
err(1, "Writing out packet");
tal_free(ctx);
return 0;
}

49
close_tx.c Normal file
View File

@ -0,0 +1,49 @@
#include "close_tx.h"
#include "shadouble.h"
#include "bitcoin_tx.h"
#include "bitcoin_script.h"
#include "permute_tx.h"
#include "pubkey.h"
#include "pkt.h"
struct bitcoin_tx *create_close_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
const struct sha256_double *anchor_txid,
unsigned int anchor_output)
{
struct bitcoin_tx *tx;
const u8 *redeemscript;
struct pubkey ourkey, theirkey;
struct sha256 redeem;
/* Now create close tx: one input, two outputs. */
tx = bitcoin_tx(ctx, 1, 2);
/* Our input spends the anchor tx output. */
tx->input[0].txid = *anchor_txid;
tx->input[0].index = anchor_output;
/* Outputs goes to final pubkey */
if (!proto_to_pubkey(ours->final, &ourkey))
return tal_free(tx);
if (!proto_to_pubkey(theirs->final, &theirkey))
return tal_free(tx);
proto_to_sha256(ours->revocation_hash, &redeem);
/* One output is to us. */
tx->output[0].amount = ours->anchor->total - ours->commitment_fee;
redeemscript = bitcoin_redeem_single(tx, &ourkey);
tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[0].script_length = tal_count(tx->output[0].script);
/* Other output is to them. */
tx->output[1].amount = theirs->anchor->total - theirs->commitment_fee;
redeemscript = bitcoin_redeem_single(tx, &theirkey);
tx->output[1].script = scriptpubkey_p2sh(tx, redeemscript);
tx->output[1].script_length = tal_count(tx->output[1].script);
permute_outputs(ours->seed, theirs->seed, 1, tx->output, 2, NULL);
return tx;
}

15
close_tx.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef LIGHTNING_CLOSE_TX_H
#define LIGHTNING_CLOSE_TX_H
#include <ccan/tal/tal.h>
#include "lightning.pb-c.h"
struct sha256_double;
/* Create close tx to spend the anchor tx output; doesn't fill in
* input scriptsig. */
struct bitcoin_tx *create_close_tx(const tal_t *ctx,
OpenChannel *ours,
OpenChannel *theirs,
const struct sha256_double *anchor_txid,
unsigned int anchor_output);
#endif

View File

@ -431,7 +431,7 @@ struct _CloseChannel
ProtobufCMessage base;
/*
* This is our signature a new transaction which spends the anchor
* output to my open->script_to_me and your open->script_to_me,
* output to my open->final and your open->final,
* as per the last commit tx.
*/
Signature *sig;

View File

@ -176,7 +176,7 @@ message new_anchor_complete {
// Begin cooperative close of channel.
message close_channel {
// This is our signature a new transaction which spends the anchor
// output to my open->script_to_me and your open->script_to_me,
// output to my open->final and your open->final,
// as per the last commit tx.
required signature sig = 1;
}

7
pkt.c
View File

@ -137,3 +137,10 @@ struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig)
o.sig = signature_to_proto(ctx, sig);
return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o);
}
struct pkt *close_channel_pkt(const tal_t *ctx, const struct signature *sig)
{
CloseChannel c = CLOSE_CHANNEL__INIT;
c.sig = signature_to_proto(ctx, sig);
return to_pkt(ctx, PKT__PKT_CLOSE, &c);
}

7
pkt.h
View File

@ -66,6 +66,13 @@ struct pkt *leak_anchor_sigs_and_pretend_we_didnt_pkt(const tal_t *ctx,
*/
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig);
/**
* close_channel_pkt - create an close_channel message
* @ctx: tal context to allocate off.
* @sig: the signature for the close transaction input.
*/
struct pkt *close_channel_pkt(const tal_t *ctx, const struct signature *sig);
/* Useful helper for allocating & populating a protobuf Sha256Hash */
Sha256Hash *sha256_to_proto(const tal_t *ctx, const struct sha256 *hash);
void proto_to_sha256(const Sha256Hash *pb, struct sha256 *hash);