From c03c878afc9e0a98f48112fbb0f4b7dc8a2d034d Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 24 Jul 2015 16:00:10 +0930 Subject: [PATCH] Split into two anchors. This is a major change; instead of creating a mutual anchor (funding) transaction, each side creates its own. We use escape transactions in case anything goes wrong; these will be revoked later. Signed-off-by: Rusty Russell --- .gitignore | 2 + Makefile | 2 +- anchor.c | 333 +++++++------ anchor.h | 60 ++- close_tx.c | 32 +- close_tx.h | 8 +- commit_tx.c | 39 +- commit_tx.h | 9 +- lightning.pb-c.c | 699 +++++++++++----------------- lightning.pb-c.h | 332 ++++++------- lightning.proto | 97 ++-- pkt.c | 74 +-- pkt.h | 48 +- test-cli/HOWTO-USE.md | 112 +++-- test-cli/check-anchor-scriptsigs.c | 61 --- test-cli/check-commit-sig.c | 104 +++-- test-cli/close-channel.c | 92 ++-- test-cli/create-anchor-tx.c | 188 ++++++++ test-cli/create-close-tx.c | 95 ++-- test-cli/create-commit-spend-tx.c | 1 - test-cli/create-commit-tx.c | 113 +++-- test-cli/create-steal-tx.c | 1 - test-cli/get-anchor-depth.c | 3 +- test-cli/open-anchor-id.c | 79 ++++ test-cli/open-anchor-scriptsigs.c | 98 ---- test-cli/open-channel.c | 114 +---- test-cli/open-commit-sig.c | 73 +-- test-cli/scripts/getinput.sh | 23 +- test-cli/scripts/test.sh | 67 +-- test-cli/update-channel-accept.c | 70 +-- test-cli/update-channel-complete.c | 64 +-- test-cli/update-channel-signature.c | 99 ++-- test-cli/update-channel.c | 1 - 33 files changed, 1607 insertions(+), 1586 deletions(-) delete mode 100644 test-cli/check-anchor-scriptsigs.c create mode 100644 test-cli/create-anchor-tx.c create mode 100644 test-cli/open-anchor-id.c delete mode 100644 test-cli/open-anchor-scriptsigs.c diff --git a/.gitignore b/.gitignore index aa083cd26..cd6ca2767 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ txid-of ccan/tools/configurator/configurator libsecp256k1.a libsecp256k1.la +create-anchor-tx +open-anchor-id diff --git a/Makefile b/Makefile index e3087faeb..56899faa7 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ FEATURES := -DHAS_CSV=1 -DALPHA_TXSTYLE=1 -DUSE_SCHNORR=1 # Bitcoin uses DER for signatures #FEATURES := -DSCRIPTS_USE_DER -PROGRAMS := test-cli/open-channel test-cli/open-anchor-scriptsigs test-cli/open-commit-sig test-cli/check-commit-sig test-cli/check-anchor-scriptsigs test-cli/get-anchor-depth test-cli/create-steal-tx test-cli/create-commit-spend-tx test-cli/close-channel test-cli/create-close-tx test-cli/update-channel test-cli/update-channel-accept test-cli/update-channel-signature test-cli/update-channel-complete test-cli/create-commit-tx test-cli/txid-of +PROGRAMS := test-cli/open-channel test-cli/open-commit-sig test-cli/check-commit-sig test-cli/get-anchor-depth test-cli/create-steal-tx test-cli/create-commit-spend-tx test-cli/close-channel test-cli/create-close-tx test-cli/update-channel test-cli/update-channel-accept test-cli/update-channel-signature test-cli/update-channel-complete test-cli/create-commit-tx test-cli/txid-of test-cli/create-anchor-tx test-cli/open-anchor-id BITCOIN_OBJS := bitcoin/address.o bitcoin/base58.o bitcoin/pubkey.o bitcoin/script.o bitcoin/shadouble.o bitcoin/signature.o bitcoin/tx.o diff --git a/anchor.c b/anchor.c index 69f5059f9..dd4c27207 100644 --- a/anchor.c +++ b/anchor.c @@ -1,165 +1,200 @@ -#include #include "anchor.h" -#include "bitcoin/pubkey.h" #include "bitcoin/script.h" -#include "bitcoin/tx.h" -#include "overflows.h" -#include "permute_tx.h" -#include "pkt.h" #include "protobuf_convert.h" -struct bitcoin_tx *anchor_tx_create(const tal_t *ctx, - const OpenChannel *o1, - const OpenChannel *o2, - size_t **inmapp, size_t **outmapp) +#undef DEBUG +#ifdef DEBUG +#include +#include "bitcoin/pubkey.h" + +static void dump_anchor_spend(const char *what, + size_t input, + const struct pubkey *commitkey1, + const struct pubkey *commitkey2, + const struct pubkey *finalkey, + const struct sha256 *escapehash, + const struct pubkey *signingkey, + const struct signature *sig) +{ + size_t i; + fprintf(stderr, "%s input %zu:", what, input); + fprintf(stderr, " commitkey1="); + for (i = 0; i < pubkey_len(commitkey1); i++) + fprintf(stderr, "%02x", commitkey1->key[i]); + fprintf(stderr, " commitkey2="); + for (i = 0; i < pubkey_len(commitkey2); i++) + fprintf(stderr, "%02x", commitkey2->key[i]); + fprintf(stderr, " finalkey="); + for (i = 0; i < pubkey_len(finalkey); i++) + fprintf(stderr, "%02x", finalkey->key[i]); + fprintf(stderr, " escapehash="); + for (i = 0; i < sizeof(escapehash->u.u8); i++) + fprintf(stderr, "%02x", escapehash->u.u8[i]); + fprintf(stderr, " signingkey="); + for (i = 0; i < pubkey_len(signingkey); i++) + fprintf(stderr, "%02x", signingkey->key[i]); + fprintf(stderr, " -> sig {r="); + for (i = 0; i < sizeof(sig->r); i++) + fprintf(stderr, "%02x", sig->r[i]); + fprintf(stderr, ", s="); + for (i = 0; i < sizeof(sig->s); i++) + fprintf(stderr, "%02x", sig->s[i]); + fprintf(stderr, "}\n"); +} +#else +static void dump_anchor_spend(const char *what, + size_t input, + const struct pubkey *commitkey1, + const struct pubkey *commitkey2, + const struct pubkey *finalkey, + const struct sha256 *escapehash, + const struct pubkey *signingkey, + const struct signature *sig) +{ +} +#endif + +bool sign_anchor_spend(struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const struct pubkey *signing_pubkey, + const struct privkey *signing_privkey, + struct signature sig[2]) { - uint64_t i, n_out; - struct bitcoin_tx *tx; + const tal_t *ctx = tal(NULL, char); u8 *redeemscript; - size_t *inmap, *outmap; - struct pubkey key1, key2; - uint64_t total_in = 0, total_change = 0; - - if (add_overflows_size_t(o1->anchor->n_inputs, o2->anchor->n_inputs)) - return NULL; - - n_out = 1 + !!o1->anchor->change + !!o2->anchor->change; - tx = bitcoin_tx(ctx, o1->anchor->n_inputs+o2->anchor->n_inputs, n_out); - - /* Override version to use lesser of two versions. */ - if (o1->tx_version < o2->tx_version) - tx->version = o1->tx_version; - else - tx->version = o2->tx_version; - - /* 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->input_amount = pb->amount; - if (add_overflows_u64(total_in, in->input_amount)) - return tal_free(tx); - total_in += in->input_amount; - /* Leave inputs as stubs for now, for signing. */ - } - 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->input_amount = pb->amount; - if (add_overflows_u64(total_in, in->input_amount)) - return tal_free(tx); - total_in += in->input_amount; - /* Leave inputs as stubs for now, for signing. */ - } - - /* Populate outputs. */ - if (add_overflows_u64(o1->anchor->total, o2->anchor->total)) - return tal_free(tx); - - /* Pubkeys both valid, right? */ - if (!proto_to_pubkey(o1->anchor->pubkey, &key1) - || !proto_to_pubkey(o2->anchor->pubkey, &key2)) - return tal_free(tx); - - /* Make the 2 of 2 payment for the commitment txs. */ - redeemscript = bitcoin_redeem_2of2(tx, &key1, &key2); - 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) */ - 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 = scriptpubkey_p2sh(tx, - bitcoin_redeem_single(tx, &key)); - out->script_length = tal_count(out->script); - total_change += out->amount; - } - 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 = scriptpubkey_p2sh(tx, - bitcoin_redeem_single(tx, &key)); - out->script_length = tal_count(out->script); - if (add_overflows_u64(total_change, out->amount)) - return tal_free(tx); - total_change += out->amount; - } - assert(n_out == tx->output_count); - - /* Figure out fee we're paying; check for over and underflow */ - if (add_overflows_u64(total_change, tx->output[0].amount)) - return tal_free(tx); - if (total_in < total_change + tx->output[0].amount) - return tal_free(tx); - tx->fee = total_in - (total_change + tx->output[0].amount); - - /* Check that the fees add up correctly. */ - if (add_overflows_u64(o1->anchor->fee, o2->anchor->fee)) - return tal_free(tx); - if (tx->fee != o1->anchor->fee + o2->anchor->fee) - return tal_free(tx); - - if (inmapp) - inmap = *inmapp = tal_arr(ctx, size_t, tx->input_count); - else - inmap = NULL; - - if (outmapp) - outmap = *outmapp = tal_arr(ctx, size_t, tx->output_count); - else - outmap = NULL; - - permute_inputs(tx->input, tx->input_count, inmap); - permute_outputs(tx->output, tx->output_count, outmap); - return tx; + bool ret; + + /* Sign input for our anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey, + their_finalkey, my_escapehash); + ret = sign_tx_input(ctx, tx, inmap[0], + redeemscript, tal_count(redeemscript), + signing_privkey, signing_pubkey, &sig[inmap[0]]); + dump_anchor_spend("signed from_mine", inmap[0], + my_commitkey, their_commitkey, their_finalkey, + my_escapehash, signing_pubkey, &sig[inmap[0]]); + + /* Sign input for their anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey, + my_finalkey, their_escapehash); + ret &= sign_tx_input(ctx, tx, inmap[1], + redeemscript, tal_count(redeemscript), + signing_privkey, signing_pubkey, &sig[inmap[1]]); + + dump_anchor_spend("signed from_yours", inmap[1], + their_commitkey, my_commitkey, my_finalkey, + their_escapehash, signing_pubkey, &sig[inmap[1]]); + tal_free(ctx); + return ret; } -/* This may create an invalid anchor. That's actually OK, as the bitcoin - * network won't accept it and we'll ds our way out. */ -bool anchor_add_scriptsigs(struct bitcoin_tx *anchor, - OpenAnchorScriptsigs *ssigs1, - OpenAnchorScriptsigs *ssigs2, - const size_t *inmap) +/* Check that their sigs sign this tx as expected. */ +bool check_anchor_spend(struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const struct pubkey *signing_pubkey, + const AnchorSpend *their_sigs) { - size_t i; + const tal_t *ctx; + u8 *redeemscript; + bool ret; + struct bitcoin_signature sigs[2]; - if (ssigs1->n_script + ssigs2->n_script != anchor->input_count) - return NULL; + sigs[0].stype = sigs[1].stype = SIGHASH_ALL; - for (i = 0; i < ssigs1->n_script; i++) { - size_t n = inmap[i]; - anchor->input[n].script = ssigs1->script[i].data; - anchor->input[n].script_length = ssigs1->script[i].len; - } + if (!proto_to_signature(their_sigs->sig0, &sigs[0].sig) + || !proto_to_signature(their_sigs->sig1, &sigs[1].sig)) + return false; - for (i = 0; i < ssigs2->n_script; i++) { - size_t n = inmap[ssigs1->n_script + i]; - anchor->input[n].script = ssigs2->script[i].data; - anchor->input[n].script_length = ssigs2->script[i].len; - } + ctx = tal(NULL, char); - return true; + /* Input for our anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey, + their_finalkey, my_escapehash); + ret = check_tx_sig(tx, inmap[0], redeemscript, tal_count(redeemscript), + signing_pubkey, &sigs[inmap[0]]); + + dump_anchor_spend("checking from_mine", inmap[0], + my_commitkey, their_commitkey, their_finalkey, + my_escapehash, signing_pubkey, &sigs[inmap[0]].sig); + + /* Input for their anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey, + my_finalkey, their_escapehash); + ret &= check_tx_sig(tx, inmap[1], redeemscript, tal_count(redeemscript), + signing_pubkey, &sigs[inmap[1]]); + + dump_anchor_spend("checking from_yours", inmap[1], + their_commitkey, my_commitkey, my_finalkey, + their_escapehash, signing_pubkey, &sigs[inmap[1]].sig); + + tal_free(ctx); + return ret; } - -void anchor_txid(struct bitcoin_tx *anchor, struct sha256_double *txid) + +/* Set up input scriptsigs for this transaction. */ +bool populate_anchor_inscripts(const tal_t *ctx, + struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const AnchorSpend *my_sigs, + const AnchorSpend *their_sigs) { - bitcoin_txid(anchor, txid); + u8 *redeemscript; + struct bitcoin_signature theirs[2], mine[2]; + + theirs[0].stype = theirs[1].stype = mine[0].stype = mine[1].stype + = SIGHASH_ALL; + + if (!proto_to_signature(their_sigs->sig0, &theirs[0].sig) + || !proto_to_signature(their_sigs->sig1, &theirs[1].sig) + || !proto_to_signature(my_sigs->sig0, &mine[0].sig) + || !proto_to_signature(my_sigs->sig1, &mine[1].sig)) + return false; + + /* Input for our anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, my_commitkey, their_commitkey, + their_finalkey, my_escapehash); + + tx->input[inmap[0]].script + = scriptsig_p2sh_anchor_commit(ctx, + &theirs[inmap[0]], + &mine[inmap[0]], + redeemscript, + tal_count(redeemscript)); + tal_free(redeemscript); + + /* Input for their anchor. */ + redeemscript = bitcoin_redeem_anchor(ctx, their_commitkey, my_commitkey, + my_finalkey, their_escapehash); + /* They created their anchor to expect sigs in other order. */ + tx->input[inmap[1]].script + = scriptsig_p2sh_anchor_commit(ctx, + &mine[inmap[1]], + &theirs[inmap[1]], + redeemscript, + tal_count(redeemscript)); + tal_free(redeemscript); + + /* Set up lengths. */ + tx->input[0].script_length = tal_count(tx->input[0].script); + tx->input[1].script_length = tal_count(tx->input[1].script); + + return true; } diff --git a/anchor.h b/anchor.h index e1bfe3cf7..acbd913a5 100644 --- a/anchor.h +++ b/anchor.h @@ -1,31 +1,45 @@ #ifndef LIGHTNING_ANCHOR_H #define LIGHTNING_ANCHOR_H #include +#include "bitcoin/signature.h" +#include "bitcoin/tx.h" #include "lightning.pb-c.h" -struct sha256_double; +/* Sign this transaction which spends the anchors. */ +bool sign_anchor_spend(struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const struct pubkey *signing_pubkey, + const struct privkey *signing_privkey, + struct signature sig[2]); -/* Create an anchor transaction based on both sides' requests. - * The scriptSigs are left empty. - * - * Allocate an input and output map (if non-NULL); the first - * o1->anchor->n_inputs of inmap are the location of o1's inputs, the - * next o2->anchor->n_inputs are o2's. outmap[0] is the location of - * output for the commitment tx, then o1's change (if - * o1->anchor->change), then o2's change if o2->anchor->change. - */ -struct bitcoin_tx *anchor_tx_create(const tal_t *ctx, - const OpenChannel *o1, - const OpenChannel *o2, - size_t **inmap, size_t **outmap); +/* Check that their sigs sign this tx as expected. */ +bool check_anchor_spend(struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const struct pubkey *signing_pubkey, + const AnchorSpend *their_sigs); -/* Add these scriptsigs to the anchor transaction. */ -bool anchor_add_scriptsigs(struct bitcoin_tx *anchor, - OpenAnchorScriptsigs *ssigs1, - OpenAnchorScriptsigs *ssigs2, - const size_t *inmap); - -/* We wouldn't need the leak files if we had normalized txids! */ -void anchor_txid(struct bitcoin_tx *anchor, - struct sha256_double *txid); +/* Set up input scriptsigs for this transaction. */ +bool populate_anchor_inscripts(const tal_t *ctx, + struct bitcoin_tx *tx, + const size_t inmap[2], + const struct pubkey *my_commitkey, + const struct pubkey *my_finalkey, + const struct sha256 *my_escapehash, + const struct pubkey *their_commitkey, + const struct pubkey *their_finalkey, + const struct sha256 *their_escapehash, + const AnchorSpend *my_sigs, + const AnchorSpend *their_sigs); #endif /* LIGHTNING_ANCHOR_H */ diff --git a/close_tx.c b/close_tx.c index 7ee22b8bb..64987d561 100644 --- a/close_tx.c +++ b/close_tx.c @@ -11,22 +11,27 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx, OpenChannel *ours, OpenChannel *theirs, int64_t delta, - const struct sha256_double *anchor_txid, - uint64_t input_amount, - unsigned int anchor_output) + const struct sha256_double *anchor_txid1, + unsigned int index1, uint64_t input_amount1, + const struct sha256_double *anchor_txid2, + unsigned int index2, uint64_t input_amount2, + size_t inmap[2]) { 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); + /* Now create close tx: two inputs, two outputs. */ + tx = bitcoin_tx(ctx, 2, 2); - /* Our input spends the anchor tx output. */ - tx->input[0].txid = *anchor_txid; - tx->input[0].index = anchor_output; - tx->input[0].input_amount = input_amount; + /* Our inputs spend the anchor tx outputs. */ + tx->input[0].txid = *anchor_txid1; + tx->input[0].index = index1; + tx->input[0].input_amount = input_amount1; + tx->input[1].txid = *anchor_txid2; + tx->input[1].index = index2; + tx->input[1].input_amount = input_amount2; /* Outputs goes to final pubkey */ if (!proto_to_pubkey(ours->final, &ourkey)) @@ -35,26 +40,27 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx, return tal_free(tx); /* delta must make sense. */ - if (delta < 0 && ours->anchor->total - ours->commitment_fee < -delta) + if (delta < 0 && ours->total_input - ours->commitment_fee < -delta) return tal_free(tx); - if (delta > 0 && theirs->anchor->total - theirs->commitment_fee < delta) + if (delta > 0 && theirs->total_input - theirs->commitment_fee < delta) 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 + delta; + tx->output[0].amount = ours->total_input - ours->commitment_fee + delta; 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 - delta; + tx->output[1].amount = theirs->total_input - theirs->commitment_fee - delta; 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); tx->fee = ours->commitment_fee + theirs->commitment_fee; + permute_inputs(tx->input, 2, inmap); permute_outputs(tx->output, 2, NULL); return tx; } diff --git a/close_tx.h b/close_tx.h index feb81086c..525122c3e 100644 --- a/close_tx.h +++ b/close_tx.h @@ -11,7 +11,9 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx, OpenChannel *ours, OpenChannel *theirs, int64_t delta, - const struct sha256_double *anchor_txid, - uint64_t input_amount, - unsigned int anchor_output); + const struct sha256_double *anchor_txid1, + unsigned int index1, uint64_t input_amount1, + const struct sha256_double *anchor_txid2, + unsigned int index2, uint64_t input_amount2, + size_t inmap[2]); #endif diff --git a/commit_tx.c b/commit_tx.c index f28cc3e8b..48a0c500f 100644 --- a/commit_tx.c +++ b/commit_tx.c @@ -13,23 +13,31 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, OpenChannel *theirs, const struct sha256 *rhash, int64_t delta, - const struct sha256_double *anchor_txid, - unsigned int anchor_output) + const struct sha256_double *anchor_txid1, + unsigned int index1, uint64_t input_amount1, + const struct sha256_double *anchor_txid2, + unsigned int index2, uint64_t input_amount2, + size_t inmap[2]) { struct bitcoin_tx *tx; const u8 *redeemscript; struct pubkey ourkey, theirkey, to_me; u32 locktime; - /* Now create commitment tx: one input, two outputs. */ - tx = bitcoin_tx(ctx, 1, 2); + /* Now create commitment tx: two inputs, two outputs. */ + tx = bitcoin_tx(ctx, 2, 2); - /* Our input spends the anchor tx output. */ - tx->input[0].txid = *anchor_txid; - tx->input[0].index = anchor_output; - if (add_overflows_u64(ours->anchor->total, theirs->anchor->total)) + /* Our inputs spend the anchor txs outputs. */ + tx->input[0].txid = *anchor_txid1; + tx->input[0].index = index1; + tx->input[0].input_amount = input_amount1; + tx->input[1].txid = *anchor_txid2; + tx->input[1].index = index2; + tx->input[1].input_amount = input_amount2; + + if (add_overflows_u64(tx->input[0].input_amount, + tx->input[1].input_amount)) return tal_free(tx); - tx->input[0].input_amount = ours->anchor->total + theirs->anchor->total; /* Output goes to our final pubkeys */ if (!proto_to_pubkey(ours->final, &ourkey)) @@ -48,9 +56,9 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, tx->output[0].script = scriptpubkey_p2sh(tx, redeemscript); tx->output[0].script_length = tal_count(tx->output[0].script); - if (ours->anchor->total < ours->commitment_fee) + if (ours->total_input < ours->commitment_fee) return tal_free(tx); - tx->output[0].amount = ours->anchor->total - ours->commitment_fee; + tx->output[0].amount = ours->total_input - ours->commitment_fee; /* Asking for more than we have? */ if (delta < 0 && -delta > tx->output[0].amount) return tal_free(tx); @@ -64,18 +72,19 @@ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, &to_me)); tx->output[1].script_length = tal_count(tx->output[1].script); - if (theirs->anchor->total < theirs->commitment_fee) + if (theirs->total_input < theirs->commitment_fee) return tal_free(tx); - tx->output[1].amount = theirs->anchor->total - theirs->commitment_fee; + tx->output[1].amount = theirs->total_input - theirs->commitment_fee; /* Asking for more than they have? */ if (delta > 0 && delta > tx->output[1].amount) return tal_free(tx); tx->output[0].amount -= delta; /* Calculate fee; difference of inputs and outputs. */ - tx->fee = tx->input[0].input_amount + tx->fee = tx->input[0].input_amount + tx->input[1].input_amount - (tx->output[0].amount + tx->output[1].amount); - + + permute_inputs(tx->input, 2, inmap); permute_outputs(tx->output, 2, NULL); return tx; } diff --git a/commit_tx.h b/commit_tx.h index e24c76cb1..fce4b2dba 100644 --- a/commit_tx.h +++ b/commit_tx.h @@ -6,13 +6,16 @@ struct sha256_double; struct sha256; -/* Create commitment tx to spend the anchor tx output; doesn't fill in +/* Create commitment tx to spend the anchor tx outputs; doesn't fill in * input scriptsig. */ struct bitcoin_tx *create_commit_tx(const tal_t *ctx, OpenChannel *ours, OpenChannel *theirs, const struct sha256 *revocation_hash, int64_t delta, - const struct sha256_double *anchor_txid, - unsigned int anchor_output); + const struct sha256_double *anchor_txid1, + unsigned int index1, uint64_t input_amount1, + const struct sha256_double *anchor_txid2, + unsigned int index2, uint64_t input_amount2, + size_t inmap[2]); #endif diff --git a/lightning.pb-c.c b/lightning.pb-c.c index 38861fdc2..fecfc8dcf 100644 --- a/lightning.pb-c.c +++ b/lightning.pb-c.c @@ -93,47 +93,47 @@ void signature__free_unpacked assert(message->base.descriptor == &signature__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void bitcoin_input__init - (BitcoinInput *message) +void anchor_spend__init + (AnchorSpend *message) { - static BitcoinInput init_value = BITCOIN_INPUT__INIT; + static AnchorSpend init_value = ANCHOR_SPEND__INIT; *message = init_value; } -size_t bitcoin_input__get_packed_size - (const BitcoinInput *message) +size_t anchor_spend__get_packed_size + (const AnchorSpend *message) { - assert(message->base.descriptor == &bitcoin_input__descriptor); + assert(message->base.descriptor == &anchor_spend__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t bitcoin_input__pack - (const BitcoinInput *message, +size_t anchor_spend__pack + (const AnchorSpend *message, uint8_t *out) { - assert(message->base.descriptor == &bitcoin_input__descriptor); + assert(message->base.descriptor == &anchor_spend__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t bitcoin_input__pack_to_buffer - (const BitcoinInput *message, +size_t anchor_spend__pack_to_buffer + (const AnchorSpend *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &bitcoin_input__descriptor); + assert(message->base.descriptor == &anchor_spend__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -BitcoinInput * - bitcoin_input__unpack +AnchorSpend * + anchor_spend__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (BitcoinInput *) - protobuf_c_message_unpack (&bitcoin_input__descriptor, + return (AnchorSpend *) + protobuf_c_message_unpack (&anchor_spend__descriptor, allocator, len, data); } -void bitcoin_input__free_unpacked - (BitcoinInput *message, +void anchor_spend__free_unpacked + (AnchorSpend *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &bitcoin_input__descriptor); + assert(message->base.descriptor == &anchor_spend__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void bitcoin_pubkey__init @@ -179,133 +179,133 @@ 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) +void open_channel__init + (OpenChannel *message) { - static Change init_value = CHANGE__INIT; + static OpenChannel init_value = OPEN_CHANNEL__INIT; *message = init_value; } -size_t change__get_packed_size - (const Change *message) +size_t open_channel__get_packed_size + (const OpenChannel *message) { - assert(message->base.descriptor == &change__descriptor); + assert(message->base.descriptor == &open_channel__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t change__pack - (const Change *message, +size_t open_channel__pack + (const OpenChannel *message, uint8_t *out) { - assert(message->base.descriptor == &change__descriptor); + assert(message->base.descriptor == &open_channel__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t change__pack_to_buffer - (const Change *message, +size_t open_channel__pack_to_buffer + (const OpenChannel *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &change__descriptor); + assert(message->base.descriptor == &open_channel__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -Change * - change__unpack +OpenChannel * + open_channel__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (Change *) - protobuf_c_message_unpack (&change__descriptor, + return (OpenChannel *) + protobuf_c_message_unpack (&open_channel__descriptor, allocator, len, data); } -void change__free_unpacked - (Change *message, +void open_channel__free_unpacked + (OpenChannel *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &change__descriptor); + assert(message->base.descriptor == &open_channel__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void anchor__init - (Anchor *message) +void open_anchor__init + (OpenAnchor *message) { - static Anchor init_value = ANCHOR__INIT; + static OpenAnchor init_value = OPEN_ANCHOR__INIT; *message = init_value; } -size_t anchor__get_packed_size - (const Anchor *message) +size_t open_anchor__get_packed_size + (const OpenAnchor *message) { - assert(message->base.descriptor == &anchor__descriptor); + assert(message->base.descriptor == &open_anchor__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t anchor__pack - (const Anchor *message, +size_t open_anchor__pack + (const OpenAnchor *message, uint8_t *out) { - assert(message->base.descriptor == &anchor__descriptor); + assert(message->base.descriptor == &open_anchor__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t anchor__pack_to_buffer - (const Anchor *message, +size_t open_anchor__pack_to_buffer + (const OpenAnchor *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &anchor__descriptor); + assert(message->base.descriptor == &open_anchor__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -Anchor * - anchor__unpack +OpenAnchor * + open_anchor__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (Anchor *) - protobuf_c_message_unpack (&anchor__descriptor, + return (OpenAnchor *) + protobuf_c_message_unpack (&open_anchor__descriptor, allocator, len, data); } -void anchor__free_unpacked - (Anchor *message, +void open_anchor__free_unpacked + (OpenAnchor *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &anchor__descriptor); + assert(message->base.descriptor == &open_anchor__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void open_channel__init - (OpenChannel *message) +void open_escape_sigs__init + (OpenEscapeSigs *message) { - static OpenChannel init_value = OPEN_CHANNEL__INIT; + static OpenEscapeSigs init_value = OPEN_ESCAPE_SIGS__INIT; *message = init_value; } -size_t open_channel__get_packed_size - (const OpenChannel *message) +size_t open_escape_sigs__get_packed_size + (const OpenEscapeSigs *message) { - assert(message->base.descriptor == &open_channel__descriptor); + assert(message->base.descriptor == &open_escape_sigs__descriptor); return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); } -size_t open_channel__pack - (const OpenChannel *message, +size_t open_escape_sigs__pack + (const OpenEscapeSigs *message, uint8_t *out) { - assert(message->base.descriptor == &open_channel__descriptor); + assert(message->base.descriptor == &open_escape_sigs__descriptor); return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); } -size_t open_channel__pack_to_buffer - (const OpenChannel *message, +size_t open_escape_sigs__pack_to_buffer + (const OpenEscapeSigs *message, ProtobufCBuffer *buffer) { - assert(message->base.descriptor == &open_channel__descriptor); + assert(message->base.descriptor == &open_escape_sigs__descriptor); return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); } -OpenChannel * - open_channel__unpack +OpenEscapeSigs * + open_escape_sigs__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data) { - return (OpenChannel *) - protobuf_c_message_unpack (&open_channel__descriptor, + return (OpenEscapeSigs *) + protobuf_c_message_unpack (&open_escape_sigs__descriptor, allocator, len, data); } -void open_channel__free_unpacked - (OpenChannel *message, +void open_escape_sigs__free_unpacked + (OpenEscapeSigs *message, ProtobufCAllocator *allocator) { - assert(message->base.descriptor == &open_channel__descriptor); + assert(message->base.descriptor == &open_escape_sigs__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } void open_commit_sig__init @@ -351,49 +351,6 @@ void open_commit_sig__free_unpacked assert(message->base.descriptor == &open_commit_sig__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } -void open_anchor_scriptsigs__init - (OpenAnchorScriptsigs *message) -{ - static OpenAnchorScriptsigs init_value = OPEN_ANCHOR_SCRIPTSIGS__INIT; - *message = init_value; -} -size_t open_anchor_scriptsigs__get_packed_size - (const OpenAnchorScriptsigs *message) -{ - assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor); - return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); -} -size_t open_anchor_scriptsigs__pack - (const OpenAnchorScriptsigs *message, - uint8_t *out) -{ - assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor); - return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); -} -size_t open_anchor_scriptsigs__pack_to_buffer - (const OpenAnchorScriptsigs *message, - ProtobufCBuffer *buffer) -{ - assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor); - return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); -} -OpenAnchorScriptsigs * - open_anchor_scriptsigs__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data) -{ - return (OpenAnchorScriptsigs *) - protobuf_c_message_unpack (&open_anchor_scriptsigs__descriptor, - allocator, len, data); -} -void open_anchor_scriptsigs__free_unpacked - (OpenAnchorScriptsigs *message, - ProtobufCAllocator *allocator) -{ - assert(message->base.descriptor == &open_anchor_scriptsigs__descriptor); - protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); -} void open_complete__init (OpenComplete *message) { @@ -987,81 +944,55 @@ const ProtobufCMessageDescriptor signature__descriptor = (ProtobufCMessageInit) signature__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor bitcoin_input__field_descriptors[4] = +static const ProtobufCFieldDescriptor anchor_spend__field_descriptors[2] = { { - "txid", + "sig0", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(BitcoinInput, txid), - &sha256_hash__descriptor, + offsetof(AnchorSpend, sig0), + &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "output", + "sig1", 2, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT32, - 0, /* quantifier_offset */ - 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, + PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(BitcoinInput, amount), - NULL, + offsetof(AnchorSpend, sig1), + &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -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 unsigned anchor_spend__field_indices_by_name[] = { + 0, /* field[0] = sig0 */ + 1, /* field[1] = sig1 */ }; -static const ProtobufCIntRange bitcoin_input__number_ranges[1 + 1] = +static const ProtobufCIntRange anchor_spend__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 4 } + { 0, 2 } }; -const ProtobufCMessageDescriptor bitcoin_input__descriptor = +const ProtobufCMessageDescriptor anchor_spend__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "bitcoin_input", - "BitcoinInput", - "BitcoinInput", + "anchor_spend", + "AnchorSpend", + "AnchorSpend", "", - sizeof(BitcoinInput), - 4, - bitcoin_input__field_descriptors, - bitcoin_input__field_indices_by_name, - 1, bitcoin_input__number_ranges, - (ProtobufCMessageInit) bitcoin_input__init, + sizeof(AnchorSpend), + 2, + anchor_spend__field_descriptors, + anchor_spend__field_indices_by_name, + 1, anchor_spend__number_ranges, + (ProtobufCMessageInit) anchor_spend__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCFieldDescriptor bitcoin_pubkey__field_descriptors[1] = @@ -1102,296 +1033,267 @@ const ProtobufCMessageDescriptor bitcoin_pubkey__descriptor = (ProtobufCMessageInit) bitcoin_pubkey__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor change__field_descriptors[2] = +static const ProtobufCFieldDescriptor open_channel__field_descriptors[9] = { { - "amount", - 1, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT64, - 0, /* quantifier_offset */ - offsetof(Change, amount), + "locktime_seconds", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT32, + offsetof(OpenChannel, locktime_case), + offsetof(OpenChannel, locktime_seconds), NULL, NULL, - 0, /* flags */ + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* 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, + "locktime_blocks", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT32, + offsetof(OpenChannel, locktime_case), + offsetof(OpenChannel, locktime_blocks), NULL, - 0, /* flags */ + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* 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] = -{ { - "inputs", - 1, - PROTOBUF_C_LABEL_REPEATED, + "revocation_hash", + 4, + PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, - offsetof(Anchor, n_inputs), - offsetof(Anchor, inputs), - &bitcoin_input__descriptor, + 0, /* quantifier_offset */ + offsetof(OpenChannel, revocation_hash), + &sha256_hash__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "change", - 2, - PROTOBUF_C_LABEL_OPTIONAL, + "final", + 5, + PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(Anchor, change), - &change__descriptor, + offsetof(OpenChannel, final), + &bitcoin_pubkey__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "total", - 4, + "commitment_fee", + 6, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Anchor, total), + offsetof(OpenChannel, commitment_fee), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "pubkey", - 5, + "commitkey", + 7, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(Anchor, pubkey), + offsetof(OpenChannel, commitkey), &bitcoin_pubkey__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "fee", + "total_input", 8, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_UINT64, 0, /* quantifier_offset */ - offsetof(Anchor, fee), + offsetof(OpenChannel, total_input), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "escape_hash", + 9, + PROTOBUF_C_LABEL_REQUIRED, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(OpenChannel, escape_hash), + &sha256_hash__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "min_confirms", 10, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(Anchor, min_confirms), + offsetof(OpenChannel, min_confirms), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned anchor__field_indices_by_name[] = { - 1, /* field[1] = change */ - 4, /* field[4] = fee */ - 0, /* field[0] = inputs */ - 5, /* field[5] = min_confirms */ - 3, /* field[3] = pubkey */ - 2, /* field[2] = total */ +static const unsigned open_channel__field_indices_by_name[] = { + 5, /* field[5] = commitkey */ + 4, /* field[4] = commitment_fee */ + 7, /* field[7] = escape_hash */ + 3, /* field[3] = final */ + 1, /* field[1] = locktime_blocks */ + 0, /* field[0] = locktime_seconds */ + 8, /* field[8] = min_confirms */ + 2, /* field[2] = revocation_hash */ + 6, /* field[6] = total_input */ }; -static const ProtobufCIntRange anchor__number_ranges[4 + 1] = +static const ProtobufCIntRange open_channel__number_ranges[1 + 1] = { - { 1, 0 }, - { 4, 2 }, - { 8, 4 }, - { 10, 5 }, - { 0, 6 } + { 2, 0 }, + { 0, 9 } }; -const ProtobufCMessageDescriptor anchor__descriptor = +const ProtobufCMessageDescriptor open_channel__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "anchor", - "Anchor", - "Anchor", + "open_channel", + "OpenChannel", + "OpenChannel", "", - sizeof(Anchor), - 6, - anchor__field_descriptors, - anchor__field_indices_by_name, - 4, anchor__number_ranges, - (ProtobufCMessageInit) anchor__init, + sizeof(OpenChannel), + 9, + open_channel__field_descriptors, + open_channel__field_indices_by_name, + 1, open_channel__number_ranges, + (ProtobufCMessageInit) open_channel__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor open_channel__field_descriptors[7] = +static const ProtobufCFieldDescriptor open_anchor__field_descriptors[2] = { { - "locktime_seconds", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_UINT32, - offsetof(OpenChannel, locktime_case), - offsetof(OpenChannel, locktime_seconds), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "locktime_blocks", - 3, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_UINT32, - offsetof(OpenChannel, locktime_case), - offsetof(OpenChannel, locktime_blocks), - NULL, - NULL, - 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "revocation_hash", - 4, + "anchor_txid", + 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(OpenChannel, revocation_hash), + offsetof(OpenAnchor, anchor_txid), &sha256_hash__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "final", - 5, - PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(OpenChannel, final), - &bitcoin_pubkey__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "commitment_fee", - 6, + "index", + 2, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT64, + PROTOBUF_C_TYPE_UINT32, 0, /* quantifier_offset */ - offsetof(OpenChannel, commitment_fee), + offsetof(OpenAnchor, index), NULL, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, +}; +static const unsigned open_anchor__field_indices_by_name[] = { + 0, /* field[0] = anchor_txid */ + 1, /* field[1] = index */ +}; +static const ProtobufCIntRange open_anchor__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor open_anchor__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "open_anchor", + "OpenAnchor", + "OpenAnchor", + "", + sizeof(OpenAnchor), + 2, + open_anchor__field_descriptors, + open_anchor__field_indices_by_name, + 1, open_anchor__number_ranges, + (ProtobufCMessageInit) open_anchor__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor open_escape_sigs__field_descriptors[2] = +{ { - "anchor", - 7, + "escape", + 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(OpenChannel, anchor), - &anchor__descriptor, + offsetof(OpenEscapeSigs, escape), + &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "tx_version", - 8, + "fast_escape", + 2, PROTOBUF_C_LABEL_REQUIRED, - PROTOBUF_C_TYPE_UINT32, + PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(OpenChannel, tx_version), - NULL, + offsetof(OpenEscapeSigs, fast_escape), + &signature__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; -static const unsigned open_channel__field_indices_by_name[] = { - 5, /* field[5] = anchor */ - 4, /* field[4] = commitment_fee */ - 3, /* field[3] = final */ - 1, /* field[1] = locktime_blocks */ - 0, /* field[0] = locktime_seconds */ - 2, /* field[2] = revocation_hash */ - 6, /* field[6] = tx_version */ +static const unsigned open_escape_sigs__field_indices_by_name[] = { + 0, /* field[0] = escape */ + 1, /* field[1] = fast_escape */ }; -static const ProtobufCIntRange open_channel__number_ranges[1 + 1] = +static const ProtobufCIntRange open_escape_sigs__number_ranges[1 + 1] = { - { 2, 0 }, - { 0, 7 } + { 1, 0 }, + { 0, 2 } }; -const ProtobufCMessageDescriptor open_channel__descriptor = +const ProtobufCMessageDescriptor open_escape_sigs__descriptor = { PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "open_channel", - "OpenChannel", - "OpenChannel", + "open_escape_sigs", + "OpenEscapeSigs", + "OpenEscapeSigs", "", - sizeof(OpenChannel), - 7, - open_channel__field_descriptors, - open_channel__field_indices_by_name, - 1, open_channel__number_ranges, - (ProtobufCMessageInit) open_channel__init, + sizeof(OpenEscapeSigs), + 2, + open_escape_sigs__field_descriptors, + open_escape_sigs__field_indices_by_name, + 1, open_escape_sigs__number_ranges, + (ProtobufCMessageInit) open_escape_sigs__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCFieldDescriptor open_commit_sig__field_descriptors[1] = { { - "sig", + "sigs", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(OpenCommitSig, sig), - &signature__descriptor, + offsetof(OpenCommitSig, sigs), + &anchor_spend__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; static const unsigned open_commit_sig__field_indices_by_name[] = { - 0, /* field[0] = sig */ + 0, /* field[0] = sigs */ }; static const ProtobufCIntRange open_commit_sig__number_ranges[1 + 1] = { @@ -1413,44 +1315,6 @@ const ProtobufCMessageDescriptor open_commit_sig__descriptor = (ProtobufCMessageInit) open_commit_sig__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor open_anchor_scriptsigs__field_descriptors[1] = -{ - { - "script", - 1, - PROTOBUF_C_LABEL_REPEATED, - PROTOBUF_C_TYPE_BYTES, - offsetof(OpenAnchorScriptsigs, n_script), - offsetof(OpenAnchorScriptsigs, script), - NULL, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, -}; -static const unsigned open_anchor_scriptsigs__field_indices_by_name[] = { - 0, /* field[0] = script */ -}; -static const ProtobufCIntRange open_anchor_scriptsigs__number_ranges[1 + 1] = -{ - { 1, 0 }, - { 0, 1 } -}; -const ProtobufCMessageDescriptor open_anchor_scriptsigs__descriptor = -{ - PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, - "open_anchor_scriptsigs", - "OpenAnchorScriptsigs", - "OpenAnchorScriptsigs", - "", - sizeof(OpenAnchorScriptsigs), - 1, - open_anchor_scriptsigs__field_descriptors, - open_anchor_scriptsigs__field_indices_by_name, - 1, open_anchor_scriptsigs__number_ranges, - (ProtobufCMessageInit) open_anchor_scriptsigs__init, - NULL,NULL,NULL /* reserved[123] */ -}; static const ProtobufCFieldDescriptor open_complete__field_descriptors[1] = { { @@ -1540,28 +1404,16 @@ const ProtobufCMessageDescriptor update__descriptor = (ProtobufCMessageInit) update__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] = +static const ProtobufCFieldDescriptor update_accept__field_descriptors[2] = { { - "sig", + "sigs", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(UpdateAccept, sig), - &signature__descriptor, - NULL, - 0, /* flags */ - 0,NULL,NULL /* reserved1,reserved2, etc */ - }, - { - "old_anchor_sig", - 2, - PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_MESSAGE, - 0, /* quantifier_offset */ - offsetof(UpdateAccept, old_anchor_sig), - &signature__descriptor, + offsetof(UpdateAccept, sigs), + &anchor_spend__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1580,14 +1432,14 @@ static const ProtobufCFieldDescriptor update_accept__field_descriptors[3] = }, }; static const unsigned update_accept__field_indices_by_name[] = { - 1, /* field[1] = old_anchor_sig */ - 2, /* field[2] = revocation_hash */ - 0, /* field[0] = sig */ + 1, /* field[1] = revocation_hash */ + 0, /* field[0] = sigs */ }; -static const ProtobufCIntRange update_accept__number_ranges[1 + 1] = +static const ProtobufCIntRange update_accept__number_ranges[2 + 1] = { { 1, 0 }, - { 0, 3 } + { 3, 1 }, + { 0, 2 } }; const ProtobufCMessageDescriptor update_accept__descriptor = { @@ -1597,23 +1449,23 @@ const ProtobufCMessageDescriptor update_accept__descriptor = "UpdateAccept", "", sizeof(UpdateAccept), - 3, + 2, update_accept__field_descriptors, update_accept__field_indices_by_name, - 1, update_accept__number_ranges, + 2, update_accept__number_ranges, (ProtobufCMessageInit) update_accept__init, NULL,NULL,NULL /* reserved[123] */ }; static const ProtobufCFieldDescriptor update_signature__field_descriptors[2] = { { - "sig", + "sigs", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(UpdateSignature, sig), - &signature__descriptor, + offsetof(UpdateSignature, sigs), + &anchor_spend__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1633,7 +1485,7 @@ static const ProtobufCFieldDescriptor update_signature__field_descriptors[2] = }; static const unsigned update_signature__field_indices_by_name[] = { 1, /* field[1] = revocation_preimage */ - 0, /* field[0] = sig */ + 0, /* field[0] = sigs */ }; static const ProtobufCIntRange update_signature__number_ranges[1 + 1] = { @@ -1696,20 +1548,20 @@ const ProtobufCMessageDescriptor update_complete__descriptor = static const ProtobufCFieldDescriptor close_channel__field_descriptors[1] = { { - "sig", + "sigs", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(CloseChannel, sig), - &signature__descriptor, + offsetof(CloseChannel, sigs), + &anchor_spend__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; static const unsigned close_channel__field_indices_by_name[] = { - 0, /* field[0] = sig */ + 0, /* field[0] = sigs */ }; static const ProtobufCIntRange close_channel__number_ranges[1 + 1] = { @@ -1734,20 +1586,20 @@ const ProtobufCMessageDescriptor close_channel__descriptor = static const ProtobufCFieldDescriptor close_channel_complete__field_descriptors[1] = { { - "sig", + "sigs", 1, PROTOBUF_C_LABEL_REQUIRED, PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(CloseChannelComplete, sig), - &signature__descriptor, + offsetof(CloseChannelComplete, sigs), + &anchor_spend__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, }; static const unsigned close_channel_complete__field_indices_by_name[] = { - 0, /* field[0] = sig */ + 0, /* field[0] = sigs */ }; static const ProtobufCIntRange close_channel_complete__number_ranges[1 + 1] = { @@ -1807,7 +1659,7 @@ const ProtobufCMessageDescriptor error__descriptor = (ProtobufCMessageInit) error__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor pkt__field_descriptors[11] = +static const ProtobufCFieldDescriptor pkt__field_descriptors[12] = { { "update", @@ -1882,13 +1734,13 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[11] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "open_anchor_scriptsigs", + "open_anchor", 203, PROTOBUF_C_LABEL_OPTIONAL, PROTOBUF_C_TYPE_MESSAGE, offsetof(Pkt, pkt_case), - offsetof(Pkt, open_anchor_scriptsigs), - &open_anchor_scriptsigs__descriptor, + offsetof(Pkt, open_anchor), + &open_anchor__descriptor, NULL, 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -1905,6 +1757,18 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[11] = 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "open_escape_sigs", + 205, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Pkt, pkt_case), + offsetof(Pkt, open_escape_sigs), + &open_escape_sigs__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, { "close", 401, @@ -1943,13 +1807,14 @@ static const ProtobufCFieldDescriptor pkt__field_descriptors[11] = }, }; static const unsigned pkt__field_indices_by_name[] = { - 8, /* field[8] = close */ - 9, /* field[9] = close_complete */ - 10, /* field[10] = error */ + 9, /* field[9] = close */ + 10, /* field[10] = close_complete */ + 11, /* field[11] = error */ 4, /* field[4] = open */ - 6, /* field[6] = open_anchor_scriptsigs */ + 6, /* field[6] = open_anchor */ 5, /* field[5] = open_commit_sig */ 7, /* field[7] = open_complete */ + 8, /* field[8] = open_escape_sigs */ 0, /* field[0] = update */ 1, /* field[1] = update_accept */ 3, /* field[3] = update_complete */ @@ -1959,9 +1824,9 @@ static const ProtobufCIntRange pkt__number_ranges[4 + 1] = { { 1, 0 }, { 201, 4 }, - { 401, 8 }, - { 1000, 10 }, - { 0, 11 } + { 401, 9 }, + { 1000, 11 }, + { 0, 12 } }; const ProtobufCMessageDescriptor pkt__descriptor = { @@ -1971,7 +1836,7 @@ const ProtobufCMessageDescriptor pkt__descriptor = "Pkt", "", sizeof(Pkt), - 11, + 12, pkt__field_descriptors, pkt__field_indices_by_name, 4, pkt__number_ranges, diff --git a/lightning.pb-c.h b/lightning.pb-c.h index 452e22d98..30866a17e 100644 --- a/lightning.pb-c.h +++ b/lightning.pb-c.h @@ -17,13 +17,12 @@ PROTOBUF_C__BEGIN_DECLS typedef struct _Sha256Hash Sha256Hash; typedef struct _Signature Signature; -typedef struct _BitcoinInput BitcoinInput; +typedef struct _AnchorSpend AnchorSpend; typedef struct _BitcoinPubkey BitcoinPubkey; -typedef struct _Change Change; -typedef struct _Anchor Anchor; typedef struct _OpenChannel OpenChannel; +typedef struct _OpenAnchor OpenAnchor; +typedef struct _OpenEscapeSigs OpenEscapeSigs; typedef struct _OpenCommitSig OpenCommitSig; -typedef struct _OpenAnchorScriptsigs OpenAnchorScriptsigs; typedef struct _OpenComplete OpenComplete; typedef struct _Update Update; typedef struct _UpdateAccept UpdateAccept; @@ -74,31 +73,24 @@ struct _Signature /* - * Identifies consumption of a bitcoin output. + * To update the channel (commit tx or close tx) we need a signature for each + * input. */ -struct _BitcoinInput +struct _AnchorSpend { ProtobufCMessage base; /* - * This is the transaction ID. + * From first anchor input. */ - Sha256Hash *txid; + Signature *sig0; /* - * This is the output number. + * From second anchor input. */ - uint32_t output; - /* - * And the subscript we're signing. - */ - ProtobufCBinaryData subscript; - /* - * The amount this input is worth. - */ - uint64_t amount; + Signature *sig1; }; -#define BITCOIN_INPUT__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&bitcoin_input__descriptor) \ - , NULL, 0, {0,NULL}, 0 } +#define ANCHOR_SPEND__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&anchor_spend__descriptor) \ + , NULL, NULL } /* @@ -117,57 +109,6 @@ 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. - */ -struct _Anchor -{ - ProtobufCMessage base; - /* - * 0 or more unspent inputs we want to use for anchor. - */ - size_t n_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) - */ - Change *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. - */ - uint32_t min_confirms; -}; -#define ANCHOR__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&anchor__descriptor) \ - , 0,NULL, NULL, NULL, 0, 0, 0 } - - typedef enum { OPEN_CHANNEL__LOCKTIME__NOT_SET = 0, OPEN_CHANNEL__LOCKTIME_LOCKTIME_SECONDS = 2, @@ -185,7 +126,7 @@ struct _OpenChannel */ Sha256Hash *revocation_hash; /* - * How to pay money to us from commit_tx. + * How to pay money to us from commit_tx (also for escape txs) */ BitcoinPubkey *final; /* @@ -193,13 +134,21 @@ struct _OpenChannel */ uint64_t commitment_fee; /* - * The anchor transaction details. + * Key for commitment tx 2of2. + */ + BitcoinPubkey *commitkey; + /* + * How much we'll be putting into channel */ - Anchor *anchor; + uint64_t total_input; /* - * Maximum transaction version we support. + * Secret hash for escape transactions. + */ + Sha256Hash *escape_hash; + /* + * How many confirmations on anchor before we'll use channel. */ - uint32_t tx_version; + uint32_t min_confirms; OpenChannel__LocktimeCase locktime_case; union { uint32_t locktime_seconds; @@ -208,34 +157,57 @@ struct _OpenChannel }; #define OPEN_CHANNEL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&open_channel__descriptor) \ - , NULL, NULL, 0, NULL, 0, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} } + , NULL, NULL, 0, NULL, 0, NULL, 0, OPEN_CHANNEL__LOCKTIME__NOT_SET, {} } /* - * Supply signature for commitment tx + * Give them the txid of our anchor transaction. */ -struct _OpenCommitSig +struct _OpenAnchor { ProtobufCMessage base; - Signature *sig; + Sha256Hash *anchor_txid; + /* + * Which output of anchor goes to this. + */ + uint32_t index; }; -#define OPEN_COMMIT_SIG__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \ - , NULL } +#define OPEN_ANCHOR__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&open_anchor__descriptor) \ + , NULL, 0 } + + +/* + * Give them signatures for their escape transactions. + */ +struct _OpenEscapeSigs +{ + ProtobufCMessage base; + /* + * Signature for their escape tx. + */ + Signature *escape; + /* + * Signature for their fast-escape tx. + */ + Signature *fast_escape; +}; +#define OPEN_ESCAPE_SIGS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&open_escape_sigs__descriptor) \ + , NULL, NULL } /* - * Supply ScriptSig for each anchor tx inputs. + * Supply signatures for commitment tx */ -struct _OpenAnchorScriptsigs +struct _OpenCommitSig { ProtobufCMessage base; - size_t n_script; - ProtobufCBinaryData *script; + AnchorSpend *sigs; }; -#define OPEN_ANCHOR_SCRIPTSIGS__INIT \ - { PROTOBUF_C_MESSAGE_INIT (&open_anchor_scriptsigs__descriptor) \ - , 0,NULL } +#define OPEN_COMMIT_SIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&open_commit_sig__descriptor) \ + , NULL } /* @@ -287,13 +259,9 @@ struct _UpdateAccept { ProtobufCMessage base; /* - * Signature for your new commitment tx. + * Signatures for your new commitment tx. */ - Signature *sig; - /* - * Signature for old anchor (if any) - */ - Signature *old_anchor_sig; + AnchorSpend *sigs; /* * Hash for which I will supply preimage to revoke this new commit tx. */ @@ -301,7 +269,7 @@ struct _UpdateAccept }; #define UPDATE_ACCEPT__INIT \ { PROTOBUF_C_MESSAGE_INIT (&update_accept__descriptor) \ - , NULL, NULL, NULL } + , NULL, NULL } /* @@ -311,9 +279,9 @@ struct _UpdateSignature { ProtobufCMessage base; /* - * Signature for your new commitment tx. + * Signatures for your new commitment tx. */ - Signature *sig; + AnchorSpend *sigs; /* * Hash preimage which revokes old commitment tx. */ @@ -347,11 +315,10 @@ struct _CloseChannel { ProtobufCMessage base; /* - * This is our signature a new transaction which spends the anchor - * output to my open->final and your open->final, - * as per the last commit tx. + * These are our signatures on a new transaction which spends the anchor + * outputs to my open->final and your open->final, as per the last commit tx. */ - Signature *sig; + AnchorSpend *sigs; }; #define CLOSE_CHANNEL__INIT \ { PROTOBUF_C_MESSAGE_INIT (&close_channel__descriptor) \ @@ -365,9 +332,9 @@ struct _CloseChannelComplete { ProtobufCMessage base; /* - * This is my signature for that same tx. + * These are my signatures for that same tx. */ - Signature *sig; + AnchorSpend *sigs; }; #define CLOSE_CHANNEL_COMPLETE__INIT \ { PROTOBUF_C_MESSAGE_INIT (&close_channel_complete__descriptor) \ @@ -390,8 +357,9 @@ struct _Error typedef enum { PKT__PKT__NOT_SET = 0, PKT__PKT_OPEN = 201, + PKT__PKT_OPEN_ANCHOR = 203, + PKT__PKT_OPEN_ESCAPE_SIGS = 205, PKT__PKT_OPEN_COMMIT_SIG = 202, - PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS = 203, PKT__PKT_OPEN_COMPLETE = 204, PKT__PKT_UPDATE = 1, PKT__PKT_UPDATE_ACCEPT = 2, @@ -414,8 +382,9 @@ struct _Pkt * Opening */ OpenChannel *open; + OpenAnchor *open_anchor; + OpenEscapeSigs *open_escape_sigs; OpenCommitSig *open_commit_sig; - OpenAnchorScriptsigs *open_anchor_scriptsigs; OpenComplete *open_complete; /* * Updating (most common) @@ -478,24 +447,24 @@ Signature * void signature__free_unpacked (Signature *message, ProtobufCAllocator *allocator); -/* 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, +/* AnchorSpend methods */ +void anchor_spend__init + (AnchorSpend *message); +size_t anchor_spend__get_packed_size + (const AnchorSpend *message); +size_t anchor_spend__pack + (const AnchorSpend *message, uint8_t *out); -size_t bitcoin_input__pack_to_buffer - (const BitcoinInput *message, +size_t anchor_spend__pack_to_buffer + (const AnchorSpend *message, ProtobufCBuffer *buffer); -BitcoinInput * - bitcoin_input__unpack +AnchorSpend * + anchor_spend__unpack (ProtobufCAllocator *allocator, size_t len, const uint8_t *data); -void bitcoin_input__free_unpacked - (BitcoinInput *message, +void anchor_spend__free_unpacked + (AnchorSpend *message, ProtobufCAllocator *allocator); /* BitcoinPubkey methods */ void bitcoin_pubkey__init @@ -516,44 +485,6 @@ 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); -size_t anchor__get_packed_size - (const Anchor *message); -size_t anchor__pack - (const Anchor *message, - uint8_t *out); -size_t anchor__pack_to_buffer - (const Anchor *message, - ProtobufCBuffer *buffer); -Anchor * - anchor__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void anchor__free_unpacked - (Anchor *message, - ProtobufCAllocator *allocator); /* OpenChannel methods */ void open_channel__init (OpenChannel *message); @@ -573,6 +504,44 @@ OpenChannel * void open_channel__free_unpacked (OpenChannel *message, ProtobufCAllocator *allocator); +/* OpenAnchor methods */ +void open_anchor__init + (OpenAnchor *message); +size_t open_anchor__get_packed_size + (const OpenAnchor *message); +size_t open_anchor__pack + (const OpenAnchor *message, + uint8_t *out); +size_t open_anchor__pack_to_buffer + (const OpenAnchor *message, + ProtobufCBuffer *buffer); +OpenAnchor * + open_anchor__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void open_anchor__free_unpacked + (OpenAnchor *message, + ProtobufCAllocator *allocator); +/* OpenEscapeSigs methods */ +void open_escape_sigs__init + (OpenEscapeSigs *message); +size_t open_escape_sigs__get_packed_size + (const OpenEscapeSigs *message); +size_t open_escape_sigs__pack + (const OpenEscapeSigs *message, + uint8_t *out); +size_t open_escape_sigs__pack_to_buffer + (const OpenEscapeSigs *message, + ProtobufCBuffer *buffer); +OpenEscapeSigs * + open_escape_sigs__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void open_escape_sigs__free_unpacked + (OpenEscapeSigs *message, + ProtobufCAllocator *allocator); /* OpenCommitSig methods */ void open_commit_sig__init (OpenCommitSig *message); @@ -592,25 +561,6 @@ OpenCommitSig * void open_commit_sig__free_unpacked (OpenCommitSig *message, ProtobufCAllocator *allocator); -/* OpenAnchorScriptsigs methods */ -void open_anchor_scriptsigs__init - (OpenAnchorScriptsigs *message); -size_t open_anchor_scriptsigs__get_packed_size - (const OpenAnchorScriptsigs *message); -size_t open_anchor_scriptsigs__pack - (const OpenAnchorScriptsigs *message, - uint8_t *out); -size_t open_anchor_scriptsigs__pack_to_buffer - (const OpenAnchorScriptsigs *message, - ProtobufCBuffer *buffer); -OpenAnchorScriptsigs * - open_anchor_scriptsigs__unpack - (ProtobufCAllocator *allocator, - size_t len, - const uint8_t *data); -void open_anchor_scriptsigs__free_unpacked - (OpenAnchorScriptsigs *message, - ProtobufCAllocator *allocator); /* OpenComplete methods */ void open_complete__init (OpenComplete *message); @@ -790,27 +740,24 @@ typedef void (*Sha256Hash_Closure) typedef void (*Signature_Closure) (const Signature *message, void *closure_data); -typedef void (*BitcoinInput_Closure) - (const BitcoinInput *message, +typedef void (*AnchorSpend_Closure) + (const AnchorSpend *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); typedef void (*OpenChannel_Closure) (const OpenChannel *message, void *closure_data); +typedef void (*OpenAnchor_Closure) + (const OpenAnchor *message, + void *closure_data); +typedef void (*OpenEscapeSigs_Closure) + (const OpenEscapeSigs *message, + void *closure_data); typedef void (*OpenCommitSig_Closure) (const OpenCommitSig *message, void *closure_data); -typedef void (*OpenAnchorScriptsigs_Closure) - (const OpenAnchorScriptsigs *message, - void *closure_data); typedef void (*OpenComplete_Closure) (const OpenComplete *message, void *closure_data); @@ -846,13 +793,12 @@ typedef void (*Pkt_Closure) extern const ProtobufCMessageDescriptor sha256_hash__descriptor; extern const ProtobufCMessageDescriptor signature__descriptor; -extern const ProtobufCMessageDescriptor bitcoin_input__descriptor; +extern const ProtobufCMessageDescriptor anchor_spend__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_anchor__descriptor; +extern const ProtobufCMessageDescriptor open_escape_sigs__descriptor; extern const ProtobufCMessageDescriptor open_commit_sig__descriptor; -extern const ProtobufCMessageDescriptor open_anchor_scriptsigs__descriptor; extern const ProtobufCMessageDescriptor open_complete__descriptor; extern const ProtobufCMessageDescriptor update__descriptor; extern const ProtobufCMessageDescriptor update_accept__descriptor; diff --git a/lightning.proto b/lightning.proto index a09e805ab..5335e80f3 100644 --- a/lightning.proto +++ b/lightning.proto @@ -24,16 +24,13 @@ message signature { required fixed64 s4 = 8; } -// 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; +// To update the channel (commit tx or close tx) we need a signature for each +// input. +message anchor_spend { + // From first anchor input. + required signature sig0 = 1; + // From second anchor input. + required signature sig1 = 2; } // Pubkey for commitment transaction input. @@ -42,28 +39,6 @@ message bitcoin_pubkey { 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. - 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 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) - required uint64 total = 4; - // How many confirmations on anchor before we'll use channel. - required uint32 min_confirms = 10; -} - // // Packet Types // @@ -77,24 +52,38 @@ message open_channel { } // Hash seed for revoking commitment transactions. required sha256_hash revocation_hash = 4; - // How to pay money to us from commit_tx. + // How to pay money to us from commit_tx (also for escape txs) required bitcoin_pubkey final = 5; // How much transaction fee we'll pay for commitment txs. required uint64 commitment_fee = 6; - // The anchor transaction details. - required anchor anchor = 7; - // Maximum transaction version we support. - required uint32 tx_version = 8; + // Key for commitment tx 2of2. + required bitcoin_pubkey commitkey = 7; + // How much we'll be putting into channel + required uint64 total_input = 8; + // Secret hash for escape transactions. + required sha256_hash escape_hash = 9; + // How many confirmations on anchor before we'll use channel. + required uint32 min_confirms = 10; } -// Supply signature for commitment tx -message open_commit_sig { - required signature sig = 1; +// Give them the txid of our anchor transaction. +message open_anchor { + required sha256_hash anchor_txid = 1; + // Which output of anchor goes to this. + required uint32 index = 2; } -// Supply ScriptSig for each anchor tx inputs. -message open_anchor_scriptsigs { - repeated bytes script = 1; +// Give them signatures for their escape transactions. +message open_escape_sigs { + // Signature for their escape tx. + required signature escape = 1; + // Signature for their fast-escape tx. + required signature fast_escape = 2; +} + +// Supply signatures for commitment tx +message open_commit_sig { + required anchor_spend sigs = 1; } // Indicates we've seen transaction reach min-depth. @@ -115,16 +104,16 @@ message update { // OK, I accept that update; here's your signature. message update_accept { - // Signature for your new commitment tx. - required signature sig = 1; + // Signatures for your new commitment tx. + required anchor_spend sigs = 1; // Hash for which I will supply preimage to revoke this new commit tx. required sha256_hash revocation_hash = 3; } // Thanks for accepting, here's my last bit. message update_signature { - // Signature for your new commitment tx. - required signature sig = 1; + // Signatures for your new commitment tx. + required anchor_spend sigs = 1; // Hash preimage which revokes old commitment tx. required sha256_hash revocation_preimage = 2; } @@ -137,16 +126,15 @@ message update_complete { // Begin cooperative close of channel. message close_channel { - // This is our signature a new transaction which spends the anchor - // output to my open->final and your open->final, - // as per the last commit tx. - required signature sig = 1; + // These are our signatures on a new transaction which spends the anchor + // outputs to my open->final and your open->final, as per the last commit tx. + required anchor_spend sigs = 1; } // OK, here's my sig so you can broadcast it too. We're done. message close_channel_complete { - // This is my signature for that same tx. - required signature sig = 1; + // These are my signatures for that same tx. + required anchor_spend sigs = 1; } // This means we're going to hang up; it's to help diagnose only! @@ -159,8 +147,9 @@ message pkt { oneof pkt { // Opening open_channel open = 201; + open_anchor open_anchor = 203; + open_escape_sigs open_escape_sigs = 205; open_commit_sig open_commit_sig = 202; - open_anchor_scriptsigs open_anchor_scriptsigs = 203; open_complete open_complete = 204; // Updating (most common) update update = 1; diff --git a/pkt.c b/pkt.c index 7e783b475..16762ac68 100644 --- a/pkt.c +++ b/pkt.c @@ -33,24 +33,25 @@ static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, void *msg) struct pkt *openchannel_pkt(const tal_t *ctx, const struct sha256 *revocation_hash, - const struct pubkey *to_me, + const struct pubkey *commit, + const struct pubkey *final, u64 commitment_fee, u32 rel_locktime_seconds, - Anchor *anchor) + u64 anchor_amount, + const struct sha256 *escape_hash, + u32 min_confirms) { OpenChannel o = OPEN_CHANNEL__INIT; - /* Required fields must be set: pack functions don't check! */ - assert(anchor->inputs); - assert(anchor->pubkey); - o.revocation_hash = sha256_to_proto(ctx, revocation_hash); - o.final = pubkey_to_proto(ctx, to_me); + o.commitkey = pubkey_to_proto(ctx, commit); + o.final = pubkey_to_proto(ctx, final); 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 = BITCOIN_TX_VERSION; + o.total_input = anchor_amount; + o.escape_hash = sha256_to_proto(ctx, escape_hash); + o.min_confirms = min_confirms; { size_t len = open_channel__get_packed_size(&o); @@ -93,41 +94,44 @@ Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect) return ret; } -struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs) +struct pkt *open_anchor_pkt(const tal_t *ctx, const struct sha256_double *txid, + u32 index) { - OpenAnchorScriptsigs o = OPEN_ANCHOR_SCRIPTSIGS__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_SCRIPTSIGS, &o); + OpenAnchor oa = OPEN_ANCHOR__INIT; + + oa.anchor_txid = sha256_to_proto(ctx, &txid->sha); + oa.index = index; + return to_pkt(ctx, PKT__PKT_OPEN_ANCHOR, &oa); } -struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig) +struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sigs) { OpenCommitSig o = OPEN_COMMIT_SIG__INIT; - - o.sig = signature_to_proto(ctx, sig); + o.sigs = tal(ctx, AnchorSpend); + anchor_spend__init(o.sigs); + o.sigs->sig0 = signature_to_proto(ctx, &sigs[0]); + o.sigs->sig1 = signature_to_proto(ctx, &sigs[1]); return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o); } -struct pkt *close_channel_pkt(const tal_t *ctx, const struct signature *sig) +struct pkt *close_channel_pkt(const tal_t *ctx, const struct signature *sigs) { CloseChannel c = CLOSE_CHANNEL__INIT; - c.sig = signature_to_proto(ctx, sig); + c.sigs = tal(ctx, AnchorSpend); + anchor_spend__init(c.sigs); + c.sigs->sig0 = signature_to_proto(ctx, &sigs[0]); + c.sigs->sig1 = signature_to_proto(ctx, &sigs[1]); return to_pkt(ctx, PKT__PKT_CLOSE, &c); } struct pkt *close_channel_complete_pkt(const tal_t *ctx, - const struct signature *sig) + const struct signature *sigs) { CloseChannelComplete c = CLOSE_CHANNEL_COMPLETE__INIT; - c.sig = signature_to_proto(ctx, sig); + c.sigs = tal(ctx, AnchorSpend); + anchor_spend__init(c.sigs); + c.sigs->sig0 = signature_to_proto(ctx, &sigs[0]); + c.sigs->sig1 = signature_to_proto(ctx, &sigs[1]); return to_pkt(ctx, PKT__PKT_CLOSE_COMPLETE, &c); } @@ -142,21 +146,27 @@ struct pkt *update_pkt(const tal_t *ctx, } struct pkt *update_accept_pkt(const tal_t *ctx, - struct signature *sig, + const struct signature *sigs, const struct sha256 *revocation_hash) { UpdateAccept ua = UPDATE_ACCEPT__INIT; - ua.sig = signature_to_proto(ctx, sig); + ua.sigs = tal(ctx, AnchorSpend); + anchor_spend__init(ua.sigs); + ua.sigs->sig0 = signature_to_proto(ctx, &sigs[0]); + ua.sigs->sig1 = signature_to_proto(ctx, &sigs[1]); ua.revocation_hash = sha256_to_proto(ctx, revocation_hash); return to_pkt(ctx, PKT__PKT_UPDATE_ACCEPT, &ua); } struct pkt *update_signature_pkt(const tal_t *ctx, - const struct signature *sig, + const struct signature *sigs, const struct sha256 *revocation_preimage) { UpdateSignature us = UPDATE_SIGNATURE__INIT; - us.sig = signature_to_proto(ctx, sig); + us.sigs = tal(ctx, AnchorSpend); + anchor_spend__init(us.sigs); + us.sigs->sig0 = signature_to_proto(ctx, &sigs[0]); + us.sigs->sig1 = signature_to_proto(ctx, &sigs[1]); us.revocation_preimage = sha256_to_proto(ctx, revocation_preimage); return to_pkt(ctx, PKT__PKT_UPDATE_SIGNATURE, &us); } diff --git a/pkt.h b/pkt.h index 20d7fd066..04d9123af 100644 --- a/pkt.h +++ b/pkt.h @@ -24,6 +24,7 @@ Pkt *any_pkt_from_file(const char *filename); size_t pkt_totlen(const struct pkt *pkt); struct sha256; +struct sha256_double; struct bitcoin_compressed_pubkey; struct signature; struct pubkey; @@ -32,47 +33,58 @@ struct pubkey; * openchannel_pkt - create an openchannel message * @ctx: tal context to allocate off. * @revocation_hash: first hash value generated from seed. - * @to_me: the pubkey for the commit transactions' P2SH output. + * @commit: the pubkey for commit transactions. + * @final: the pubkey for the commit transactions' output and escape input. * @commitment_fee: the fee to use for commitment tx. * @rel_locktime_seconds: relative seconds for commitment locktime. - * @anchor: the anchor transaction details. + * @anchor_txid: the anchor transaction ID. + * @anchor_amount: the anchor amount. + * @escape_hash: the hash whose preimage will revoke our escape txs. + * @min_confirms: how many confirms we want on anchor. */ struct pkt *openchannel_pkt(const tal_t *ctx, const struct sha256 *revocation_hash, - const struct pubkey *to_me, + const struct pubkey *commit, + const struct pubkey *final, u64 commitment_fee, u32 rel_locktime_seconds, - Anchor *anchor); + u64 anchor_amount, + const struct sha256 *escape_hash, + u32 min_confirms); /** - * open_anchor_sig_pkt - create an open_anchor_sig message + * open_anchor_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. + * @txid: the anchor's txid + * @index: the anchor's output to spend. */ -struct pkt *open_anchor_sig_pkt(const tal_t *ctx, u8 **sigs, size_t num_sigs); +struct pkt *open_anchor_pkt(const tal_t *ctx, + const struct sha256_double *txid, u32 index); /** * open_commit_sig_pkt - create an open_commit_sig message * @ctx: tal context to allocate off. - * @sig: the signature for the commit transaction input. + * @sigs: two signatures for the commit transaction inputs */ -struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig); +struct pkt *open_commit_sig_pkt(const tal_t *ctx, + const struct signature *sigs); /** * close_channel_pkt - create an close_channel message * @ctx: tal context to allocate off. - * @sig: the signature for the close transaction input. + * @sigs: two signatures for the close transaction inputs */ -struct pkt *close_channel_pkt(const tal_t *ctx, const struct signature *sig); +struct pkt *close_channel_pkt(const tal_t *ctx, + const struct signature *sigs); /** * close_channel_complete_pkt - create an close_channel_complete message * @ctx: tal context to allocate off. - * @sig: the signature for the close transaction input. + * @sigs: two signatures for the close transaction inputs */ struct pkt *close_channel_complete_pkt(const tal_t *ctx, - const struct signature *sig); + const struct signature *sigs); + /** * update_pkt - create an update message @@ -87,21 +99,21 @@ struct pkt *update_pkt(const tal_t *ctx, /** * update_accept_pkt - create an update_accept message * @ctx: tal context to allocate off. - * @sig: the signature for the close transaction input. + * @sigs: two signatures for the commit transaction inputs * @revocation_hash: hash to revoke the next tx. */ struct pkt *update_accept_pkt(const tal_t *ctx, - struct signature *sig, + const struct signature *sigs, const struct sha256 *revocation_hash); /** * update_signature_pkt - create an update_signature message * @ctx: tal context to allocate off. - * @sig: the signature for the close transaction input. + * @sigs: two signatures for the commit transaction inputs * @revocation_preimage: preimage to revoke existing (now-obsolete) tx. */ struct pkt *update_signature_pkt(const tal_t *ctx, - const struct signature *sig, + const struct signature *sigs, const struct sha256 *revocation_preimage); /** * update_complete_pkt - create an update_accept message diff --git a/test-cli/HOWTO-USE.md b/test-cli/HOWTO-USE.md index a3289ffac..ebd328faa 100644 --- a/test-cli/HOWTO-USE.md +++ b/test-cli/HOWTO-USE.md @@ -41,98 +41,116 @@ For each side A and B you need: 7. FINALKEY: The private key for FINALADDR eg. `alpha-cli -regtest -testnet=0 dumpprivkey ` 8. TXIN{1-n}: One or more unspent transaction outputs on testnet. - These are in form "///". + These are in form "////". eg. scripts/getinput.sh (`scripts/getinput.sh 2`, etc). -9. TXINKEY{1-n}: The private keys to spend the TXINs. - eg. `scripts/getinput.sh --privkey` can get these. +9. ESCAPE-SECRET: A secret 256-bit number, in hex. + Try 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff STEP 1 ------ First each side needs to tell the other what it wants the channel to look like, including how many satoshis to put in the channel. -Note that the default anchor fee is 5000 satoshi each, (use -`--anchor-fee=` to override), so your amount must be less than or equal -to the total inputs plus this fee. - A: Create a channel open request packet: - test-cli/open-channel ///... > A-open.pb + test-cli/open-channel > A-open.pb B: The same: - test-cli/open-channel ///... > B-open.pb + test-cli/open-channel > B-open.pb STEP 2 ------ -Create the signatures for the anchor transaction: we don't send them -until we have completed the commitment transaction though, so we're sure -we can get our funds back. We need one TXINKEY for each TXIN: +Each side creates their anchor transaction which pays to a 2 of 2 +(spendable with their own key and the other's TMPKEY or FINALKEY). We +don't send them until we have completed the escape transactions +though, so we're sure we can get our funds back. + +The change-pubkey arg is only used if you supply inputs which are greater +than the amount promised in the open packet. A: + test-cli/create-anchor-tx A-open.pb B-open.pb ////... > A-anchor.tx - test-cli/open-anchor-scriptsigs A-open.pb B-open.pb ... > A-anchor-scriptsigs.pb B: - - test-cli/open-anchor-scriptsigs B-open.pb A-open.pb ... > B-anchor-scriptsigs.pb + test-cli/create-anchor-tx A-open.pb B-open.pb ////... > B-anchor.tx STEP 3 ------ -Now both sides create the commitment transaction signatures which spend -the transaction output: +Send transaction ID and output number of the anchor to the other side: A: + test-cli/open-anchor-id A-anchor.tx > A-anchor-id.pb - test-cli/open-commit-sig A-open.pb B-open.pb > A-commit-sig.pb B: - - test-cli/open-commit-sig B-open.pb A-open.ob > B-commit-sig.pb + test-cli/open-anchor-id B-anchor.tx > B-anchor-id.pb STEP 4 ------ -Check the commitment signatures from the other side, and produce commit txs. +Create signatures for the other side's escape transaction(s) which +allow return of funds if something goes wrong: A: + test-cli/open-escape-sigs A-open.pb B-open.pb B-anchor-id.pb > A-escape-sigs.pb - test-cli/check-commit-sig A-open.pb B-open.pb B-commit-sig.pb > A-commit-0.tx B: - - test-cli/check-commit-sig B-open.pb A-open.pb A-commit-sig.pb > B-commit-0.tx + test-cli/open-escape-sigs B-open.pb A-open.pb A-anchor-id.pb > B-escape-sigs.pb STEP 5 ------ -Check the anchor signatures from the other side, and use them to generate the -anchor transaction (as a hex string, suitable for bitcoind). +Check the escape signatures from the other side, and use them to create our +escape txs. A: + test-cli/create-escape A-open.pb B-open.pb A-anchor-id.pb B-escape-sigs.pb > A-escape.tx + test-cli/create-escape --fast A-open.pb B-open.pb A-anchor-id.pb B-escape-sigs.pb > A-fast-escape.tx - test-cli/check-anchor-scriptsigs A-open.pb B-open.pb A-anchor-scriptsigs.pb B-anchor-scriptsigs.pb > A-anchor.tx B: + test-cli/create-escape B-open.pb A-open.pb B-anchor-id.pb A-escape-sigs.pb > B-escape.tx + test-cli/create-escape --fast B-open.pb A-open.pb B-anchor-id.pb A-escape-sigs.pb > B-fast-escape.tx - test-cli/check-anchor-scriptsigs B-open.pb A-open.pb B-anchor-scriptsigs.pb A-anchor-scriptsigs.pb > B-anchor.tx +STEP 6 +------ +Now both sides create the commitment transaction signatures which spend +the anchors outputs: -They should be identical: +A: + + test-cli/open-commit-sig A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb > A-commit-sig.pb +B: - cmp A-anchor.tx B-anchor.tx || echo FAIL + test-cli/open-commit-sig B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb > B-commit-sig.pb -STEP 6 +STEP 7 +------ +Check the commitment signatures from the other side, and produce commit txs. + +A: + + test-cli/check-commit-sig A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb B-commit-sig.pb > A-commit-0.tx +B: + + test-cli/check-commit-sig B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-commit-sig.pb > B-commit-0.tx + +STEP 8 ------ -Broadcast the anchor transaction: +Broadcast the anchor transactions (note they contain their inputs amounts +separated by colons for internal use: the daemon only wants the raw transaction): -Either one: +A: + alpha-cli -regtest -testnet=0 sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid - alpha-cli -regtest -testnet=0 sendrawtransaction `cat A-anchor.tx` > anchor.txid +B: + alpha-cli -regtest -testnet=0 sendrawtransaction `cut -d: -f1 B-anchor.tx` > B-anchor.txid Generate blocks until we have enough confirms (I don't do this, so I can reset the entire state by restarting bitcoind with `-zapwallettxes=1`): A: - - while [ 0$(alpha-cli -regtest -testnet=0 getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $(test-cli/get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done + while [ 0$(alpha-cli -regtest -testnet=0 getrawtransaction $(cat B-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $(test-cli/get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done B: - - while [ 0$(alpha-cli -regtest -testnet=0 getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $(test-cli/get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done + while [ 0$(alpha-cli -regtest -testnet=0 getrawtransaction $(cat A-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $(test-cli/get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done Using a Generalized Channel =========================== @@ -149,19 +167,19 @@ revocation hash for the new tx: B: - test-cli/update-channel-accept B-anchor.tx B-open.pb A-open.pb A-update-1.pb > B-update-accept-1.pb + test-cli/update-channel-accept B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-update-1.pb > B-update-accept-1.pb A completes its side by signing the new tx, and revoking the old: A: - test-cli/update-channel-signature A-anchor.tx A-open.pb B-open.pb A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb + test-cli/update-channel-signature A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb B now revokes its old tx: B: - test-cli/update-channel-complete B-anchor.tx B-open.pb A-open.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb + test-cli/update-channel-complete B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb B checks that the commit tx is indeed revoked. @@ -178,7 +196,7 @@ since the initial tx (here we just have one, A-update-1.pb): A: - test-cli/create-commit-tx A-anchor.tx A-open.pb B-open.pb A-update-1.pb B-update-accept-1.pb > A-commit-1.tx + test-cli/create-commit-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb A-update-1.pb B-update-accept-1.pb > A-commit-1.tx Special Effects: Trying To Cheat ================================ @@ -187,7 +205,7 @@ A now tries to spend an old (revoked) commitment tx: A: - test-cli/create-commit-tx A-anchor.tx A-open.pb B-open.pb B-commit-sig.pb > commit-0.tx + test-cli/create-commit-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb B-commit-sig.pb > commit-0.tx A: @@ -235,20 +253,20 @@ reflect the final commitment total: A: - ./close-channel A-anchor.tx A-open.pb B-open.pb A-update-1.pb > A-close.pb + ./close-channel A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb A-update-1.pb > A-close.pb B: - ./close-channel --complete A-anchor.tx B-open.pb A-open.pb A-update-1.pb > B-close-accept.pb + ./close-channel --complete B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-update-1.pb > B-close-accept.pb Both ends have both signatures now, so either can create the close tx: A: - ./create-close-tx A-anchor.tx A-open.pb B-open.pb A-close.pb B-close-accept.pb > A-close.tx + ./create-close-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb A-close.pb B-close-accept.pb > A-close.tx B: - ./create-close-tx A-anchor.tx B-open.pb A-open.pb A-close.pb B-close-accept.pb > B-close.tx + ./create-close-tx B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-close.pb B-close-accept.pb > B-close.tx They should be identical: diff --git a/test-cli/check-anchor-scriptsigs.c b/test-cli/check-anchor-scriptsigs.c deleted file mode 100644 index 21e9b182b..000000000 --- a/test-cli/check-anchor-scriptsigs.c +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include "lightning.pb-c.h" -#include "anchor.h" -#include "bitcoin/base58.h" -#include "pkt.h" -#include "bitcoin/script.h" -#include "permute_tx.h" -#include "bitcoin/signature.h" -#include "commit_tx.h" -#include "bitcoin/pubkey.h" -#include - -int main(int argc, char *argv[]) -{ - const tal_t *ctx = tal_arr(NULL, char, 0); - OpenChannel *o1, *o2; - OpenAnchorScriptsigs *ss1, *ss2; - struct bitcoin_tx *anchor; - struct sha256_double txid; - size_t *inmap, *outmap; - - err_set_progname(argv[0]); - - opt_register_noarg("--help|-h", opt_usage_and_exit, - " \n" - "Output the anchor transaction by merging the scriptsigs", - "Print this message."); - - opt_parse(&argc, argv, opt_log_stderr_exit); - - if (argc != 5) - opt_usage_exit_fail("Expected 6 arguments"); - - o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; - ss1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) - ->open_anchor_scriptsigs; - ss2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) - ->open_anchor_scriptsigs; - - anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap); - if (!anchor) - errx(1, "Failed transaction merge"); - if (!anchor_add_scriptsigs(anchor, ss1, ss2, inmap)) - errx(1, "Wrong number of scriptsigs"); - - bitcoin_txid(anchor, &txid); - - if (!bitcoin_tx_write(STDOUT_FILENO, anchor)) - err(1, "Writing out anchor transaction"); - - tal_free(ctx); - return 0; -} - diff --git a/test-cli/check-commit-sig.c b/test-cli/check-commit-sig.c index 9593478c8..eb3b291c1 100644 --- a/test-cli/check-commit-sig.c +++ b/test-cli/check-commit-sig.c @@ -21,82 +21,90 @@ int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; + OpenAnchor *oa1, *oa2; OpenCommitSig *cs2; - struct bitcoin_tx *anchor, *commit; - struct sha256_double txid; - u8 *subscript; - size_t *inmap, *outmap; - struct pubkey pubkey1, pubkey2; - struct bitcoin_signature sig1, sig2; + AnchorSpend mysigs = ANCHOR_SPEND__INIT; + struct bitcoin_tx *commit; + struct sha256_double anchor_txid1, anchor_txid2; + struct pubkey pubkey1, pubkey2, final1, final2; + struct signature sigs[2]; struct privkey privkey; bool testnet; - struct sha256 rhash; + struct sha256 rhash, escape_hash1, escape_hash2; + size_t inmap[2]; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " \n" + " \n" "Output the commitment transaction if both signatures are valid", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc != 5) - opt_usage_exit_fail("Expected 4 arguments"); + if (argc != 7) + opt_usage_exit_fail("Expected 6 arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; - cs2 = pkt_from_file(argv[3], PKT__PKT_OPEN_COMMIT_SIG)->open_commit_sig; - - if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[4]); + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); + cs2 = pkt_from_file(argv[5], PKT__PKT_OPEN_COMMIT_SIG)->open_commit_sig; + + if (!key_from_base58(argv[6], strlen(argv[6]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[6]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[4]); + errx(1, "Private key '%s' not on testnet!", argv[6]); /* Pubkey well-formed? */ - if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) - errx(1, "Invalid anchor-2 key"); - - /* Get the transaction ID of the anchor. */ - anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap); - if (!anchor) - errx(1, "Failed transaction merge"); - anchor_txid(anchor, &txid); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid open-2 key"); + if (!proto_to_pubkey(o2->final, &final2)) + errx(1, "Invalid o2 final pubkey"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); /* Now create our commitment tx. */ proto_to_sha256(o1->revocation_hash, &rhash); - commit = create_commit_tx(ctx, o1, o2, &rhash, 0, &txid, outmap[0]); + commit = create_commit_tx(ctx, o1, o2, &rhash, 0, + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Contributions %llu & %llu vs fees %llu & %llu", - (long long)o1->anchor->total, - (long long)o2->anchor->total, + (long long)o1->total_input, + (long long)o2->total_input, (long long)o1->commitment_fee, (long long)o2->commitment_fee); - /* FIXME: Creating out signature just to check the script we create - * is overkill: if their signature and pubkey signed the commit txin, - * we're happy. */ - sig1.stype = SIGHASH_ALL; - subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript), - &privkey, &pubkey1, &sig1.sig); - - /* Signatures well-formed? */ - if (!proto_to_signature(cs2->sig, &sig2.sig)) - errx(1, "Invalid commit-sig-2"); - sig2.stype = SIGHASH_ALL; - - /* Combined signatures must validate correctly. */ - if (!check_2of2_sig(commit, 0, subscript, tal_count(subscript), - &pubkey1, &pubkey2, &sig1, &sig2)) - errx(1, "Signature failed"); - - /* Create p2sh input for commit */ - commit->input[0].script = scriptsig_p2sh_2of2(commit, &sig1, &sig2, - &pubkey1, &pubkey2); - commit->input[0].script_length = tal_count(commit->input[0].script); + /* Check they signed out anchor inputs correctly. */ + if (!check_anchor_spend(commit, inmap, &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey2, cs2->sigs)) + errx(1, "Bad signature"); + + if (!sign_anchor_spend(commit, inmap, &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey1, &privkey, sigs)) + errx(1, "Could not sign tx"); + + /* populate_anchor_inscripts wants args in protobuf */ + mysigs.sig0 = signature_to_proto(ctx, &sigs[0]); + mysigs.sig1 = signature_to_proto(ctx, &sigs[1]); + + /* Shouldn't fail, since we checked them in check_anchor_spend */ + if (!populate_anchor_inscripts(commit, commit, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &mysigs, + cs2->sigs)) + errx(1, "Malformed signatures"); /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, commit)) diff --git a/test-cli/close-channel.c b/test-cli/close-channel.c index eef274fab..1c9e0ee08 100644 --- a/test-cli/close-channel.c +++ b/test-cli/close-channel.c @@ -23,16 +23,17 @@ 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; + OpenAnchor *oa1, *oa2; + struct sha256_double anchor_txid1, anchor_txid2; + struct bitcoin_tx *close_tx; + struct sha256 escape_hash1, escape_hash2; struct pkt *pkt; - struct signature sig; + struct signature sigs[2]; struct privkey privkey; bool testnet, complete = false; - struct pubkey pubkey1, pubkey2; - u8 *redeemscript; + struct pubkey pubkey1, pubkey2, final1, final2; int64_t delta; - size_t i, anchor_out; + size_t i, inmap[2]; err_set_progname(argv[0]); @@ -40,61 +41,82 @@ int main(int argc, char *argv[]) opt_register_noarg("--complete", opt_set_bool, &complete, "Create a close_transaction_complete msg instead"); opt_register_noarg("--help|-h", opt_usage_and_exit, - " [update-protobuf]...\n" + " [update-protobuf]...\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"); + if (argc < 6) + opt_usage_exit_fail("Expected 5+ 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; + o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); - if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[4]); + if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[4]); - - bitcoin_txid(anchor, &anchor_txid); + errx(1, "Private key '%s' not on testnet!", argv[5]); /* Get delta by accumulting all the updates. */ delta = 0; - for (i = 5; i < argc; i++) { + for (i = 6; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* Get pubkeys */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2)) + if (!proto_to_pubkey(o1->commitkey, &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)) + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 commit pubkey"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) errx(1, "Invalid o2 final pubkey"); - /* This is what the anchor pays to; figure out whick output. */ - redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - - /* Now create the close tx to spend 2/2 output of anchor. */ - /* Assumes that updates are all from closer -> closee */ - anchor_out = find_p2sh_out(anchor, redeemscript); + /* Now create the close tx to spend 2/2 outputs of anchors. */ close_tx = create_close_tx(ctx, o1, o2, complete ? -delta : delta, - &anchor_txid, - anchor->output[anchor_out].amount, - anchor_out); - - /* Sign it for them. */ - sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript), - &privkey, &pubkey1, &sig); + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); + warnx("input[0].txid = %02x%02x%02x%02x...", + close_tx->input[0].txid.sha.u.u8[0], + close_tx->input[0].txid.sha.u.u8[1], + close_tx->input[0].txid.sha.u.u8[2], + close_tx->input[0].txid.sha.u.u8[3]); + warnx("input[1].txid = %02x%02x%02x%02x...", + close_tx->input[1].txid.sha.u.u8[0], + close_tx->input[1].txid.sha.u.u8[1], + close_tx->input[1].txid.sha.u.u8[2], + close_tx->input[1].txid.sha.u.u8[3]); + warnx("input %zu should be %02x%02x%02x%02x...", + inmap[0], + anchor_txid1.sha.u.u8[0], + anchor_txid1.sha.u.u8[1], + anchor_txid1.sha.u.u8[2], + anchor_txid1.sha.u.u8[3]); + + /* Sign close. */ + if (!sign_anchor_spend(close_tx, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey1, &privkey, sigs)) + errx(1, "Failed creating signatures"); if (complete) - pkt = close_channel_complete_pkt(ctx, &sig); + pkt = close_channel_complete_pkt(ctx, sigs); else - pkt = close_channel_pkt(ctx, &sig); + pkt = close_channel_pkt(ctx, sigs); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); diff --git a/test-cli/create-anchor-tx.c b/test-cli/create-anchor-tx.c new file mode 100644 index 000000000..bd10b87bd --- /dev/null +++ b/test-cli/create-anchor-tx.c @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include "lightning.pb-c.h" +#include "bitcoin/base58.h" +#include "pkt.h" +#include "bitcoin/script.h" +#include "bitcoin/address.h" +#include "bitcoin/tx.h" +#include "bitcoin/pubkey.h" +#include "bitcoin/privkey.h" +#include "bitcoin/shadouble.h" +#include "protobuf_convert.h" +#include +#include +#include "opt_bits.h" + +struct input { + struct bitcoin_tx_input in; + struct privkey privkey; + struct pubkey pubkey; + struct bitcoin_signature sig; +}; + +static void parse_anchor_input(const char *spec, struct input *in) +{ + const char *slash; + char *end; + long l; + bool testnet; + + slash = strchr(spec, '/'); + if (!slash) + errx(1, "Expected / in ////"); + + if (!bitcoin_txid_from_hex(spec, slash - spec, &in->in.txid)) + errx(1, "Expected 256-bit hex txid before /"); + + in->in.index = l = strtol(slash + 1, &end, 10); + if (end == slash + 1 || *end != '/' || (int64_t)in->in.index != (int64_t)l) + errx(1, "Expected after /"); + + slash = end; + in->in.input_amount = l = strtol(slash + 1, &end, 10); + if (end == slash + 1 || *end != '/' || (int64_t)in->in.input_amount != (int64_t)l) + errx(1, "Expected after second /"); + + slash = end; + end = (char *)slash + 1 + strcspn(slash + 1, "/"); + in->in.script_length = hex_data_size(end - (slash + 1)); + in->in.script = tal_arr(in, u8, in->in.script_length); + if (!hex_decode(slash + 1, end - (slash + 1), + in->in.script, in->in.script_length)) + errx(1, "Expected hex string after third /"); + + if (*end != '/') + errx(1, "Expected / after hexscript"); + + if (!key_from_base58(end+1, strlen(end + 1), &testnet, + &in->privkey, &in->pubkey)) + errx(1, "Invalid private key '%s'", end+1); + if (!testnet) + errx(1, "Private key '%s' not on testnet!", end+1); +} + +/* Create an anchor transaction which pays to the commit/escape 2of2 script. */ +int main(int argc, char *argv[]) +{ + const tal_t *ctx = tal_arr(NULL, char, 0); + OpenChannel *o1, *o2; + size_t i; + u64 anchor_fee, total_in, change; + struct input *in; + u8 *redeemscript; + struct pubkey ourkey, their_commit_key, their_escape_key; + struct sha256 escape_hash; + struct bitcoin_tx *anchor; + + err_set_progname(argv[0]); + + /* Default values. */ + anchor_fee = 10000; + + opt_register_noarg("--help|-h", opt_usage_and_exit, + " ////...\n" + "A test program to create an anchor transaction on stdout.", + "Print this message."); + opt_register_arg("--anchor-fee=", + opt_set_bits, opt_show_bits, &anchor_fee, + "100's of satoshi to pay for anchor"); + + opt_parse(&argc, argv, opt_log_stderr_exit); + + if (argc < 5) + opt_usage_exit_fail("Expected 4 or more arguments"); + + o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + if (!proto_to_pubkey(o2->final, &their_escape_key) + || !proto_to_pubkey(o1->commitkey, &ourkey) + || !proto_to_pubkey(o2->commitkey, &their_commit_key)) + errx(1, "Invalid key"); + proto_to_sha256(o1->escape_hash, &escape_hash); + + in = tal_arr(ctx, struct input, argc - 4); + + total_in = 0; + for (i = 0; i < tal_count(in); i++) { + parse_anchor_input(argv[4+i], &in[i]); + total_in += in[i].in.input_amount; + } + + if (total_in < o1->total_input + anchor_fee) + errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)", + (unsigned long long)total_in, + (unsigned long long)o1->total_input, + (unsigned long long)anchor_fee); + + change = total_in - (o1->total_input + anchor_fee); + + /* If there's change, we have an extra output. */ + anchor = bitcoin_tx(ctx, tal_count(in), change ? 2 : 1); + anchor->fee = anchor_fee; + + redeemscript = bitcoin_redeem_anchor(ctx, + &ourkey, &their_commit_key, + &their_escape_key, + &escape_hash); + + /* Set up outputs. */ + anchor->output[0].amount = o1->total_input; + anchor->output[0].script = scriptpubkey_p2sh(anchor, redeemscript); + anchor->output[0].script_length = tal_count(anchor->output[0].script); + + if (change) { + struct pubkey change_key; + + if (!pubkey_from_hexstr(argv[3], &change_key)) + errx(1, "Invalid change key %s", argv[3]); + + redeemscript = bitcoin_redeem_single(anchor, &change_key); + anchor->output[1].amount = change; + anchor->output[1].script = scriptpubkey_p2sh(anchor, + redeemscript); + anchor->output[1].script_length + = tal_count(anchor->output[1].script); + } + + /* Set up inputs (leaving scripts empty for signing) */ + for (i = 0; i < tal_count(in); i++) { + anchor->input[i].input_amount = in[i].in.input_amount; + anchor->input[i].txid = in[i].in.txid; + anchor->input[i].index = in[i].in.index; + } + + /* Now, sign each input. */ + for (i = 0; i < tal_count(in); i++) { + in[i].sig.stype = SIGHASH_ALL; + if (!sign_tx_input(ctx, anchor, i, in[i].in.script, + in[i].in.script_length, + &in[i].privkey, &in[i].pubkey, + &in[i].sig.sig)) + errx(1, "Error signing input %zi", i); + } + + /* Finally, complete inputs using signatures. */ + for (i = 0; i < tal_count(in); i++) { + if (!is_pay_to_pubkey_hash(in[i].in.script, + in[i].in.script_length)) + errx(1, "FIXME: Don't know how to handle input %zi", i); + anchor->input[i].script + = scriptsig_pay_to_pubkeyhash(anchor, &in[i].pubkey, + &in[i].sig); + anchor->input[i].script_length + = tal_count(anchor->input[i].script); + } + + /* Print it out in hex. */ + if (!bitcoin_tx_write(STDOUT_FILENO, anchor)) + err(1, "Writing out transaction"); + + tal_free(ctx); + return 0; +} diff --git a/test-cli/create-close-tx.c b/test-cli/create-close-tx.c index e7f081691..adab0063f 100644 --- a/test-cli/create-close-tx.c +++ b/test-cli/create-close-tx.c @@ -21,76 +21,81 @@ 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 bitcoin_signature sig1, sig2; - struct pubkey pubkey1, pubkey2; - u8 *redeemscript; + OpenAnchor *oa1, *oa2; + struct bitcoin_tx *close_tx; + struct sha256_double anchor_txid1, anchor_txid2; + struct sha256 escape_hash1, escape_hash2; + struct pubkey pubkey1, pubkey2, final1, final2; CloseChannel *close; CloseChannelComplete *closecomplete; - size_t i, anchor_out; + size_t i, inmap[2]; int64_t delta; err_set_progname(argv[0]); /* FIXME: Take update.pbs to adjust channel */ opt_register_noarg("--help|-h", opt_usage_and_exit, - " [update-protobuf]...\n" + " [update-protobuf]...\n" "Create the close transaction from the signatures", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc < 6) - opt_usage_exit_fail("Expected 5+ arguments"); + if (argc < 7) + opt_usage_exit_fail("Expected 6+ 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; - close = pkt_from_file(argv[4], PKT__PKT_CLOSE)->close; - closecomplete = pkt_from_file(argv[5], PKT__PKT_CLOSE_COMPLETE)->close_complete; - - bitcoin_txid(anchor, &anchor_txid); + o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); + close = pkt_from_file(argv[5], PKT__PKT_CLOSE)->close; + closecomplete = pkt_from_file(argv[6], PKT__PKT_CLOSE_COMPLETE)->close_complete; /* Pubkeys well-formed? */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey1)) - errx(1, "Invalid anchor-1 key"); - if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) - errx(1, "Invalid anchor-2 key"); + if (!proto_to_pubkey(o1->commitkey, &pubkey1)) + errx(1, "Invalid open-1 key"); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid open-2 key"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) + errx(1, "Invalid o2 final pubkey"); /* Get delta by accumulting all the updates. */ delta = 0; - for (i = 6; i < argc; i++) { + for (i = 7; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } - /* This is what the anchor pays to; figure out which output. */ - redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - - /* Now create the close tx to spend 2/2 output of anchor. */ - anchor_out = find_p2sh_out(anchor, redeemscript); - close_tx = create_close_tx(ctx, o1, o2, delta, &anchor_txid, - anchor->output[anchor_out].amount, - anchor_out); - - /* Signatures well-formed? */ - sig1.stype = sig2.stype = SIGHASH_ALL; - if (!proto_to_signature(close->sig, &sig1.sig)) - errx(1, "Invalid close-packet"); - if (!proto_to_signature(closecomplete->sig, &sig2.sig)) - errx(1, "Invalid closecomplete-packet"); + close_tx = create_close_tx(ctx, o1, o2, delta, + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); - /* Combined signatures must validate correctly. */ - if (!check_2of2_sig(close_tx, 0, redeemscript, tal_count(redeemscript), - &pubkey1, &pubkey2, &sig1, &sig2)) - errx(1, "Signature failed"); - - /* Create p2sh input for close_tx */ - close_tx->input[0].script = scriptsig_p2sh_2of2(close_tx, &sig1, &sig2, - &pubkey1, &pubkey2); - close_tx->input[0].script_length = tal_count(close_tx->input[0].script); + if (!check_anchor_spend(close_tx, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey1, close->sigs)) + errx(1, "Close signature check failed"); + + if (!check_anchor_spend(close_tx, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey2, closecomplete->sigs)) + errx(1, "Closecomplete signature check failed"); + if (!populate_anchor_inscripts(close_tx, close_tx, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + close->sigs, + closecomplete->sigs)) + errx(1, "Malformed signatures"); + /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, close_tx)) err(1, "Writing out transaction"); diff --git a/test-cli/create-commit-spend-tx.c b/test-cli/create-commit-spend-tx.c index b2a65a975..29e7406ee 100644 --- a/test-cli/create-commit-spend-tx.c +++ b/test-cli/create-commit-spend-tx.c @@ -6,7 +6,6 @@ #include #include #include "lightning.pb-c.h" -#include "anchor.h" #include "bitcoin/base58.h" #include "pkt.h" #include "bitcoin/script.h" diff --git a/test-cli/create-commit-tx.c b/test-cli/create-commit-tx.c index a93e1d0a9..c4407f810 100644 --- a/test-cli/create-commit-tx.c +++ b/test-cli/create-commit-tx.c @@ -23,101 +23,120 @@ int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; + OpenAnchor *oa1, *oa2; Pkt *pkt; - struct bitcoin_tx *anchor, *commit; - struct sha256_double anchor_txid; + AnchorSpend mysigs = ANCHOR_SPEND__INIT; + struct bitcoin_tx *commit; + struct sha256_double anchor_txid1, anchor_txid2; + struct sha256 escape_hash1, escape_hash2; struct privkey privkey; bool testnet; - struct bitcoin_signature sig1, sig2; - size_t i; - struct pubkey pubkey1, pubkey2; - u8 *redeemscript; + struct signature sigs[2]; + AnchorSpend *their_sigs; + size_t i, inmap[2]; + struct pubkey pubkey1, pubkey2, final1, final2; int64_t delta; struct sha256 rhash; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " [final-update-accept|open-commit-sig] []\n" + " [final-update-accept|open-commit-sig] []\n" "Create the signature needed for the commit transaction", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc < 6) - opt_usage_exit_fail("Expected 5+ arguments"); + if (argc < 7) + opt_usage_exit_fail("Expected 6+ arguments"); - anchor = bitcoin_tx_from_file(ctx, argv[1]); - bitcoin_txid(anchor, &anchor_txid); - o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; + o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); - if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[4]); + if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[4]); + errx(1, "Private key '%s' not on testnet!", argv[5]); /* Get pubkeys */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2)) - errx(1, "Invalid o1 anchor pubkey"); + if (!proto_to_pubkey(o1->commitkey, &pubkey2)) + errx(1, "Invalid o1 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 anchor pubkey"); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 pubkey"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) + errx(1, "Invalid o2 final pubkey"); /* Their signature comes from open-commit or from update-accept. */ - sig2.stype = SIGHASH_ALL; - pkt = any_pkt_from_file(argv[5]); + pkt = any_pkt_from_file(argv[6]); switch (pkt->pkt_case) { case PKT__PKT_UPDATE_ACCEPT: - if (!proto_to_signature(pkt->update_accept->sig, &sig2.sig)) - errx(1, "Invalid update-accept sig"); + their_sigs = pkt->update_accept->sigs; break; case PKT__PKT_OPEN_COMMIT_SIG: - if (!proto_to_signature(pkt->open_commit_sig->sig, &sig2.sig)) - errx(1, "Invalid open-commit-sig sig"); + their_sigs = pkt->open_commit_sig->sigs; break; default: errx(1, "Unexpected packet type %u in %s", - pkt->pkt_case, argv[5]); + pkt->pkt_case, argv[6]); } /* Initial revocation hash comes from open. */ proto_to_sha256(o1->revocation_hash, &rhash); delta = 0; - /* Figure out cumulative delta since anchor, update revocation hash */ - for (i = 6; i < argc; i++) { + /* Figure out cumulative delta since anchors, update revocation hash */ + for (i = 7; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; proto_to_sha256(u->revocation_hash, &rhash); } - redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - /* Now create commitment tx to spend 2/2 output of anchor. */ - commit = create_commit_tx(ctx, o1, o2, &rhash, delta, &anchor_txid, - find_p2sh_out(anchor, redeemscript)); + /* Now create commitment tx to spend 2/2 outputs of anchors. */ + commit = create_commit_tx(ctx, o1, o2, &rhash, delta, + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Bad commit amounts"); - /* We generate our signature. */ - sig1.stype = SIGHASH_ALL; - sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), - &privkey, &pubkey1, &sig1.sig); - - if (!check_2of2_sig(commit, 0, redeemscript, tal_count(redeemscript), - &pubkey1, &pubkey2, &sig1, &sig2)) - errx(1, "Signature failed"); - - /* Create p2sh input for commit */ - commit->input[0].script = scriptsig_p2sh_2of2(commit, &sig1, &sig2, - &pubkey1, &pubkey2); - commit->input[0].script_length = tal_count(commit->input[0].script); - + if (!check_anchor_spend(commit, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey2, their_sigs)) + errx(1, "Bad signatures"); + + /* We generate our signatures. */ + if (!sign_anchor_spend(commit, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey1, &privkey, sigs)) + errx(1, "Could not create signatures"); + + /* populate_anchor_inscripts wants args in protobuf */ + mysigs.sig0 = signature_to_proto(ctx, &sigs[0]); + mysigs.sig1 = signature_to_proto(ctx, &sigs[1]); + + /* Shouldn't fail, since we checked them in check_anchor_spend */ + if (!populate_anchor_inscripts(commit, commit, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &mysigs, their_sigs)) + errx(1, "Malformed signatures"); + /* Print it out in hex. */ if (!bitcoin_tx_write(STDOUT_FILENO, commit)) err(1, "Writing out transaction"); diff --git a/test-cli/create-steal-tx.c b/test-cli/create-steal-tx.c index 3c5c4f2e4..bbb9c4868 100644 --- a/test-cli/create-steal-tx.c +++ b/test-cli/create-steal-tx.c @@ -5,7 +5,6 @@ #include #include #include "lightning.pb-c.h" -#include "anchor.h" #include "bitcoin/base58.h" #include "pkt.h" #include "bitcoin/script.h" diff --git a/test-cli/get-anchor-depth.c b/test-cli/get-anchor-depth.c index 9717b65ac..ef7756e92 100644 --- a/test-cli/get-anchor-depth.c +++ b/test-cli/get-anchor-depth.c @@ -5,7 +5,6 @@ #include #include #include "lightning.pb-c.h" -#include "anchor.h" #include "bitcoin/base58.h" #include "pkt.h" #include "bitcoin/script.h" @@ -33,7 +32,7 @@ int main(int argc, char *argv[]) opt_usage_exit_fail("Expected one argument"); o = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; - printf("%u\n", o->anchor->min_confirms); + printf("%u\n", o->min_confirms); tal_free(ctx); return 0; diff --git a/test-cli/open-anchor-id.c b/test-cli/open-anchor-id.c new file mode 100644 index 000000000..727485f5e --- /dev/null +++ b/test-cli/open-anchor-id.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include "lightning.pb-c.h" +#include "bitcoin/base58.h" +#include "pkt.h" +#include "bitcoin/script.h" +#include "bitcoin/address.h" +#include "bitcoin/tx.h" +#include "bitcoin/pubkey.h" +#include "bitcoin/privkey.h" +#include "bitcoin/shadouble.h" +#include "protobuf_convert.h" +#include +#include +#include "opt_bits.h" + +int main(int argc, char *argv[]) +{ + struct pkt *pkt; + const tal_t *ctx = tal_arr(NULL, char, 0); + struct bitcoin_tx *anchor; + struct sha256_double txid; + unsigned int i; + + err_set_progname(argv[0]); + + opt_register_noarg("--help|-h", opt_usage_and_exit, + " \n" + "A test program to output open-anchor on stdout.", + "Print this message."); + + opt_parse(&argc, argv, opt_log_stderr_exit); + + if (argc != 3) + opt_usage_exit_fail("Expected 1 argument"); + + anchor = bitcoin_tx_from_file(ctx, argv[1]); + bitcoin_txid(anchor, &txid); + + /* Figure out which output is for the commit tx. */ + if (anchor->output_count != 1) { + u8 *script; + struct pubkey change_key; + if (!pubkey_from_hexstr(argv[2], &change_key)) + errx(1, "Invalid change key %s", argv[2]); + + if (anchor->output_count != 2) + errx(1, "Expected 1 or 2 outputs on anchor"); + + script = scriptpubkey_p2sh(anchor, + bitcoin_redeem_single(anchor, + &change_key)); + for (i = 0; i < anchor->output_count; i++) { + if (anchor->output[i].script_length != tal_count(script)) + continue; + if (memcmp(anchor->output[i].script, script, + tal_count(script)) == 0) + break; + } + if (i == anchor->output_count) + errx(1, "No output to change found"); + + /* We found change output, so we want the other one. */ + i = !i; + } else + i = 0; + + pkt = open_anchor_pkt(ctx, &txid, i); + if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) + err(1, "Writing out packet"); + + tal_free(ctx); + return 0; +} diff --git a/test-cli/open-anchor-scriptsigs.c b/test-cli/open-anchor-scriptsigs.c deleted file mode 100644 index 2152f4979..000000000 --- a/test-cli/open-anchor-scriptsigs.c +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include "bitcoin/tx.h" -#include "bitcoin/signature.h" -#include "lightning.pb-c.h" -#include "pkt.h" -#include "bitcoin/script.h" -#include "bitcoin/address.h" -#include "bitcoin/base58.h" -#include "anchor.h" -#include "bitcoin/pubkey.h" -#include "bitcoin/privkey.h" - -#include - -/* All the input scripts are already set to 0. We just need to make this one. */ -static u8 *tx_scriptsig(const tal_t *ctx, - struct bitcoin_tx *tx, - unsigned int i, - const BitcoinInput *input, - struct privkey *privkey, - const struct pubkey *pubkey) -{ - struct bitcoin_signature sig; - - sig.stype = SIGHASH_ALL; - if (!sign_tx_input(ctx, tx, i, - input->subscript.data, input->subscript.len, - privkey, pubkey, &sig.sig)) - return NULL; - - if (!is_pay_to_pubkey_hash(input->subscript.data, input->subscript.len)) - errx(1, "FIXME: Don't know how to handle input"); - return scriptsig_pay_to_pubkeyhash(ctx, pubkey, &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, - " ...\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_exit_fail("Expected 2 or more arguments"); - - o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; - - /* FIXME: We should check that their locktime is sane here, - * since we're bound to it. Also min_confirms, etc. */ - - /* Create merged transaction */ - anchor = anchor_tx_create(ctx, o1, o2, &map, NULL); - 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++) { - struct pubkey pubkey; - struct privkey privkey; - bool testnet; - - if (!key_from_base58(argv[3+i], strlen(argv[3+i]), - &testnet, &privkey, &pubkey)) - errx(1, "Invalid private key '%s'", argv[3+i]); - if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[3+i]); - - sigs[i] = tx_scriptsig(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, pkt_totlen(pkt))) - err(1, "Writing out packet"); - - tal_free(ctx); - return 0; -} diff --git a/test-cli/open-channel.c b/test-cli/open-channel.c index 71c6ca65f..afcd41e47 100644 --- a/test-cli/open-channel.c +++ b/test-cli/open-channel.c @@ -22,78 +22,34 @@ /* Bitcoin nodes are allowed to be 2 hours in the future. */ #define LOCKTIME_MIN (2 * 60 * 60) -static BitcoinInput *parse_anchor_input(const tal_t *ctx, const char *spec) -{ - BitcoinInput *in = tal(ctx, BitcoinInput); - struct sha256_double txid; - const char *slash; - char *end; - long l; - - bitcoin_input__init(in); - - slash = strchr(spec, '/'); - if (!slash) - errx(1, "Expected / in ///"); - - if (!bitcoin_txid_from_hex(spec, slash - spec, &txid)) - errx(1, "Expected 256-bit hex txid before /"); - in->txid = sha256_to_proto(in, &txid.sha); - - in->output = l = strtol(slash + 1, &end, 10); - if (end == slash + 1 || *end != '/' || (int64_t)in->output != (int64_t)l) - errx(1, "Expected after /"); - - 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 after second /"); - - 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; -} - /* Simple helper to open a channel. */ int main(int argc, char *argv[]) { - struct sha256 seed, revocation_hash; + struct sha256 seed, revocation_hash, escape_secret, escape_hash; 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; + unsigned int locktime_seconds, min_confirms; bool testnet; - size_t i; - struct pubkey commitkey, outkey, changekey; + struct pubkey commitkey, outkey; struct privkey commitprivkey, outprivkey; err_set_progname(argv[0]); /* Default values. */ - anchor.min_confirms = 3; - /* Remember, other side contributes to fee, too. */ - anchor.fee = 5000; + min_confirms = 3; /* We only need this for involuntary close, so make it larger. */ commit_tx_fee = 100000; /* This means we have ~1 day before they can steal our money. */ 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", - opt_set_uintval, opt_show_uintval, &anchor.min_confirms, + opt_set_uintval, opt_show_uintval, &min_confirms, "Number of anchor confirmations before channel is active"); - opt_register_arg("--anchor-fee=", - opt_set_bits, opt_show_bits, &anchor.fee, - "100's of satoshi to pay for anchor"); opt_register_arg("--commitment-fee=", opt_set_bits, opt_show_bits, &commit_tx_fee, "100's of satoshi to pay for commitment"); @@ -103,65 +59,45 @@ int main(int argc, char *argv[]) opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc < 7) - opt_usage_exit_fail("Expected 6 or more arguments"); + if (argc != 6) + opt_usage_exit_fail("Expected 5 arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); - anchor.total = atol(argv[2]); - if (!anchor.total) + total_in = atol(argv[2]); + if (!total_in) errx(1, "Invalid total: must be > 0"); - 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. */ - if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, + if (!key_from_base58(argv[3], strlen(argv[3]), &testnet, &commitprivkey, &commitkey)) - errx(1, "Invalid private key '%s'", argv[4]); + errx(1, "Invalid private key '%s'", argv[3]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[4]); + errx(1, "Private key '%s' not on testnet!", argv[3]); - if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, + if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &outprivkey, &outkey)) - errx(1, "Invalid private key '%s'", argv[5]); + errx(1, "Invalid private key '%s'", argv[4]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[5]); + errx(1, "Private key '%s' not on testnet!", argv[4]); - anchor.n_inputs = (argc - 6); - anchor.inputs = tal_arr(ctx, BitcoinInput *, anchor.n_inputs); - anchor.pubkey = pubkey_to_proto(ctx, &commitkey); - - 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, Change); - change__init(anchor.change); - anchor.change->pubkey = pubkey_to_proto(anchor.change, - &changekey); - anchor.change->amount = total_in - (anchor.total + anchor.fee); - } + if (!hex_decode(argv[5], strlen(argv[5]), &escape_secret, + sizeof(escape_secret))) + errx(1, "Invalid escape hash '%s' - need 256 hex bits", argv[5]); /* Get first revocation hash. */ shachain_from_seed(&seed, 0, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); - pkt = openchannel_pkt(ctx, &revocation_hash, &outkey, - commit_tx_fee, locktime_seconds, &anchor); + /* Get hash from escape secret. */ + sha256(&escape_hash, escape_secret.u.u8, sizeof(escape_secret.u.u8)); + + pkt = openchannel_pkt(ctx, &revocation_hash, &commitkey, &outkey, + commit_tx_fee, locktime_seconds, total_in, + &escape_hash, min_confirms); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); diff --git a/test-cli/open-commit-sig.c b/test-cli/open-commit-sig.c index d959cc286..e03e58a27 100644 --- a/test-cli/open-commit-sig.c +++ b/test-cli/open-commit-sig.c @@ -22,67 +22,74 @@ int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); OpenChannel *o1, *o2; - struct bitcoin_tx *anchor, *commit; - struct sha256_double txid; + OpenAnchor *oa1, *oa2; + struct bitcoin_tx *commit; + struct sha256 escape_hash1, escape_hash2; + struct sha256_double anchor_txid1, anchor_txid2; struct pkt *pkt; - struct signature sig; - size_t *inmap, *outmap; + struct signature sigs[2]; struct privkey privkey; bool testnet; - struct pubkey pubkey1, pubkey2; - u8 *subscript; + struct pubkey pubkey1, pubkey2, final1, final2; struct sha256 rhash; + size_t inmap[2]; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " \n" + " \n" "Create the signature needed for the commit transaction", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc != 4) - opt_usage_exit_fail("Expected 3 arguments"); + if (argc != 6) + opt_usage_exit_fail("Expected 5 arguments"); o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; - - if (!key_from_base58(argv[3], strlen(argv[3]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[3]); + proto_to_sha256(o2->escape_hash, &escape_hash2); + if (!proto_to_pubkey(o2->final, &final2)) + errx(1, "Invalid o2 final pubkey"); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 commit pubkey"); + oa1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + + if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[5]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[3]); - - /* Create merged anchor transaction */ - anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap); - if (!anchor) - errx(1, "Failed transaction merge"); + errx(1, "Private key '%s' not on testnet!", argv[5]); - /* Get the transaction ID of the anchor. */ - anchor_txid(anchor, &txid); + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); - /* Now create THEIR commitment tx to spend 2/2 output of anchor. */ + /* Now create THEIR commitment tx to spend outputs of anchors. */ proto_to_sha256(o2->revocation_hash, &rhash); - commit = create_commit_tx(ctx, o2, o1, &rhash, 0, &txid, outmap[0]); + commit = create_commit_tx(ctx, o2, o1, &rhash, 0, + &anchor_txid2, oa2->index, o2->total_input, + &anchor_txid1, oa1->index, o1->total_input, + inmap); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Contributions %llu & %llu vs fees %llu & %llu", - (long long)o1->anchor->total, - (long long)o2->anchor->total, + (long long)o1->total_input, + (long long)o2->total_input, (long long)o1->commitment_fee, (long long)o2->commitment_fee); - /* Their pubkey must be valid */ - if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) - errx(1, "Invalid public open-channel-file2"); - - /* Sign it for them. */ - subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript), - &privkey, &pubkey1, &sig); + /* Since we're signing theirs, "my" and "their" args are backwards. */ + if (!sign_anchor_spend(commit, inmap, + &pubkey2, &final2, &escape_hash2, + &pubkey1, &final1, &escape_hash1, + &pubkey1, &privkey, sigs)) + errx(1, "Could not sign tx"); - pkt = open_commit_sig_pkt(ctx, &sig); + pkt = open_commit_sig_pkt(ctx, sigs); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); diff --git a/test-cli/scripts/getinput.sh b/test-cli/scripts/getinput.sh index 85195cc1a..c2f046f87 100755 --- a/test-cli/scripts/getinput.sh +++ b/test-cli/scripts/getinput.sh @@ -8,10 +8,6 @@ set -e . `dirname $0`/vars.sh -if [ n"$1" = n--privkey ]; then - KEY=1 - shift -fi NUM=1 if [ $# = 1 ]; then NUM=$1 @@ -19,18 +15,15 @@ if [ $# = 1 ]; then fi if [ $# -gt 0 ]; then - echo "Usage: getinput.sh [--privkey] [INPUT-INDEX]" + echo "Usage: getinput.sh [INPUT-INDEX]" exit 1 fi -if [ -n "$KEY" ]; then - ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1` - $CLI dumpprivkey $ADDR -else - TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` - OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1` - AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'` - SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` +TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` +OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1` +AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'` +SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1` +ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1` +PRIVKEY=`$CLI dumpprivkey $ADDR` - echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT -fi +echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT/$PRIVKEY diff --git a/test-cli/scripts/test.sh b/test-cli/scripts/test.sh index fdf363e75..dd1c5f02b 100755 --- a/test-cli/scripts/test.sh +++ b/test-cli/scripts/test.sh @@ -66,13 +66,14 @@ B_FINALADDR=`scripts/get-new-address.sh` #B_FINALADDR=mvQgfEX4iMSEYqD31524jASQviPwPwpvuv A_TXIN=`scripts/getinput.sh $A_INPUTNUM` -A_TXINKEY=`scripts/getinput.sh --privkey $A_INPUTNUM` B_TXIN=`scripts/getinput.sh $B_INPUTNUM` -B_TXINKEY=`scripts/getinput.sh --privkey $B_INPUTNUM` A_SEED=00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff B_SEED=112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 +A_ESCSECRET=00112233445566778899aabbccddeeff00112233445566778899aabbccddeef0 +B_ESCSECRET=112233445566778899aabbccddeeff00112233445566778899aabbccddeeff0f + A_CHANGEPUBKEY=`getpubkey $A_CHANGEADDR` A_TMPKEY=`getprivkey $A_TMPADDR` A_FINALKEY=`getprivkey $A_FINALADDR` @@ -82,56 +83,56 @@ B_TMPKEY=`getprivkey $B_TMPADDR` B_FINALKEY=`getprivkey $B_FINALADDR` # Both sides say what they want from channel -$PREFIX ./open-channel $A_SEED $A_AMOUNT $A_CHANGEPUBKEY $A_TMPKEY $A_FINALKEY $A_TXIN > A-open.pb +# FIXME: Use pubkeys for tmpkey and finalkey here! +$PREFIX ./open-channel $A_SEED $A_AMOUNT $A_TMPKEY $A_FINALKEY $A_ESCSECRET > A-open.pb # B asks for a (dangerously) short locktime, for testing unilateral close. -$PREFIX ./open-channel --locktime=60 $B_SEED $B_AMOUNT $B_CHANGEPUBKEY $B_TMPKEY $B_FINALKEY $B_TXIN > B-open.pb +$PREFIX ./open-channel --locktime=60 $B_SEED $B_AMOUNT $B_TMPKEY $B_FINALKEY $B_ESCSECRET > B-open.pb -# Now sign anchor. -$PREFIX ./open-anchor-scriptsigs A-open.pb B-open.pb $A_TXINKEY > A-anchor-scriptsigs.pb -$PREFIX ./open-anchor-scriptsigs B-open.pb A-open.pb $B_TXINKEY > B-anchor-scriptsigs.pb +# Now create anchors. +$PREFIX ./create-anchor-tx A-open.pb B-open.pb $A_CHANGEPUBKEY $A_TXIN > A-anchor.tx +$PREFIX ./create-anchor-tx B-open.pb A-open.pb $B_CHANGEPUBKEY $B_TXIN > B-anchor.tx -# Now create commit signature -$PREFIX ./open-commit-sig A-open.pb B-open.pb $A_TMPKEY > A-commit-sig.pb +# Now tell the other side about it. +$PREFIX ./open-anchor-id A-anchor.tx $A_CHANGEPUBKEY > A-anchor-id.pb +$PREFIX ./open-anchor-id B-anchor.tx $B_CHANGEPUBKEY > B-anchor-id.pb -$PREFIX ./open-commit-sig B-open.pb A-open.pb $B_TMPKEY > B-commit-sig.pb +# Now create commit signature +$PREFIX ./open-commit-sig A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY > A-commit-sig.pb +$PREFIX ./open-commit-sig B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb $B_TMPKEY > B-commit-sig.pb # Now check it. -$PREFIX ./check-commit-sig A-open.pb B-open.pb B-commit-sig.pb $A_TMPKEY > A-commit.tx -$PREFIX ./check-commit-sig B-open.pb A-open.pb A-commit-sig.pb $B_TMPKEY > B-commit.tx - -# Now check anchor sigs and make sure they're the same. -$PREFIX ./check-anchor-scriptsigs A-open.pb B-open.pb A-anchor-scriptsigs.pb B-anchor-scriptsigs.pb > A-anchor.tx -$PREFIX ./check-anchor-scriptsigs B-open.pb A-open.pb B-anchor-scriptsigs.pb A-anchor-scriptsigs.pb > B-anchor.tx -cmp A-anchor.tx B-anchor.tx +$PREFIX ./check-commit-sig A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb B-commit-sig.pb $A_TMPKEY > A-commit.tx +$PREFIX ./check-commit-sig B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-commit-sig.pb $B_TMPKEY > B-commit.tx -# Broadcast -$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > anchor.txid +# Broadcast anchors +$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid +$CLI sendrawtransaction `cut -d: -f1 B-anchor.tx` > B-anchor.txid # # Wait for confirms -# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done +# while [ 0$($CLI getrawtransaction $(cat B-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done -# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done +# while [ 0$($CLI getrawtransaction $(cat A-anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done # Just for testing, generate the first transaction. -$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-commit-sig.pb > A-commit-0.tx +$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY B-commit-sig.pb > A-commit-0.tx # Now, update the channel, so I pay you 500 satoshi. $PREFIX ./update-channel --to-them=500 $A_SEED > A-update-1.pb -$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb > B-update-accept-1.pb -$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb -$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb +$PREFIX ./update-channel-accept $B_SEED B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb $B_TMPKEY A-update-1.pb > B-update-accept-1.pb +$PREFIX ./update-channel-signature $A_SEED A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb +$PREFIX ./update-channel-complete $B_SEED B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb # Just for testing, generate second transaction -$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-1.pb A-update-1.pb > A-commit-1.tx +$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY B-update-accept-1.pb A-update-1.pb > A-commit-1.tx # Now you pay me 1000. $PREFIX ./update-channel --from-them=1000 $A_SEED A-update-1.pb > A-update-2.pb -$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-2.pb A-update-1.pb > B-update-accept-2.pb 2>/dev/null -$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-2.pb B-update-accept-2.pb A-update-1.pb > A-update-sig-2.pb -$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-2.pb A-update-sig-2.pb A-update-1.pb > B-update-complete-2.pb +$PREFIX ./update-channel-accept $B_SEED B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb $B_TMPKEY A-update-2.pb A-update-1.pb > B-update-accept-2.pb 2>/dev/null +$PREFIX ./update-channel-signature $A_SEED A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY A-update-2.pb B-update-accept-2.pb A-update-1.pb > A-update-sig-2.pb +$PREFIX ./update-channel-complete $B_SEED B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb A-update-2.pb A-update-sig-2.pb A-update-1.pb > B-update-complete-2.pb # Just for testing, generate third transaction -$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-2.pb A-update-1.pb A-update-2.pb > A-commit-2.tx +$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY B-update-accept-2.pb A-update-1.pb A-update-2.pb > A-commit-2.tx if [ x"$1" = x--steal ]; then # A stupidly broadcasts a revoked transaction. @@ -152,8 +153,8 @@ if [ x"$1" = x--unilateral ]; then fi # Now close channel by mutual consent. -$PREFIX ./close-channel A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb A-update-2.pb > A-close.pb -$PREFIX ./close-channel --complete B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb A-update-2.pb > B-close-complete.pb -$PREFIX ./create-close-tx A-anchor.tx A-open.pb B-open.pb A-close.pb B-close-complete.pb A-update-1.pb A-update-2.pb > A-close.tx +$PREFIX ./close-channel A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb $A_TMPKEY A-update-1.pb A-update-2.pb > A-close.pb +$PREFIX ./close-channel --complete B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb $B_TMPKEY A-update-1.pb A-update-2.pb > B-close-complete.pb +$PREFIX ./create-close-tx A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb A-close.pb B-close-complete.pb A-update-1.pb A-update-2.pb > A-close.tx $CLI sendrawtransaction `cut -d: -f1 A-close.tx` > close.txid diff --git a/test-cli/update-channel-accept.c b/test-cli/update-channel-accept.c index 8e483c3a4..4f2679464 100644 --- a/test-cli/update-channel-accept.c +++ b/test-cli/update-channel-accept.c @@ -22,24 +22,24 @@ int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); - struct sha256 seed, revocation_hash, their_rhash; + struct sha256 seed, revocation_hash, their_rhash, escape_hash1, escape_hash2; OpenChannel *o1, *o2; + OpenAnchor *oa1, *oa2; Update *update; - struct bitcoin_tx *anchor, *commit; - struct sha256_double anchor_txid; + struct bitcoin_tx *commit; + struct sha256_double anchor_txid1, anchor_txid2; struct pkt *pkt; - struct bitcoin_signature sig; + struct signature sigs[2]; struct privkey privkey; bool testnet; - struct pubkey pubkey1, pubkey2; - u8 *redeemscript; + struct pubkey pubkey1, pubkey2, final1, final2; int64_t delta; - size_t i, p2sh_out; + size_t i, inmap[2]; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " [previous-updates]\n" + " [previous-updates]\n" "Accept a new update message", "Print this message."); @@ -51,57 +51,65 @@ int main(int argc, char *argv[]) if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); - anchor = bitcoin_tx_from_file(ctx, argv[2]); - bitcoin_txid(anchor, &anchor_txid); - o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; - - if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[5]); + o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[5], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); + + if (!key_from_base58(argv[6], strlen(argv[6]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[6]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[5]); + errx(1, "Private key '%s' not on testnet!", argv[6]); - update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update; + update = pkt_from_file(argv[7], PKT__PKT_UPDATE)->update; /* Figure out cumulative delta since anchor. */ delta = update->delta; - for (i = 7; i < argc; i++) { + for (i = 8; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* Get next revocation hash. */ - shachain_from_seed(&seed, argc - 6, &revocation_hash); + shachain_from_seed(&seed, argc - 7, &revocation_hash); sha256(&revocation_hash, revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); /* Get pubkeys */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2)) + if (!proto_to_pubkey(o1->commitkey, &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)) + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 commit pubkey"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) errx(1, "Invalid o2 final pubkey"); - /* This is what the anchor pays to; figure out whick output. */ - redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - p2sh_out = find_p2sh_out(anchor, redeemscript); - - /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ + /* Now create THEIR new commitment tx to spend 2/2 outputs of anchors. */ proto_to_sha256(update->revocation_hash, &their_rhash); commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta, - &anchor_txid, p2sh_out); + &anchor_txid2, oa2->index, o2->total_input, + &anchor_txid1, oa1->index, o1->total_input, + inmap); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Delta too large"); - /* Sign it for them. */ - sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), - &privkey, &pubkey1, &sig.sig); + /* Sign it for them (since its theirs, reverse args). */ + if (!sign_anchor_spend(commit, inmap, &pubkey2, &final2, &escape_hash2, + &pubkey1, &final1, &escape_hash1, + &pubkey1, &privkey, sigs)) + errx(1, "Failed creating signatures"); - pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash); + pkt = update_accept_pkt(ctx, sigs, &revocation_hash); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); diff --git a/test-cli/update-channel-complete.c b/test-cli/update-channel-complete.c index 6c45fc02c..01e4d883e 100644 --- a/test-cli/update-channel-complete.c +++ b/test-cli/update-channel-complete.c @@ -24,45 +24,49 @@ int main(int argc, char *argv[]) const tal_t *ctx = tal_arr(NULL, char, 0); struct sha256 seed, revocation_hash, our_rhash, their_rhash, preimage; OpenChannel *o1, *o2; + OpenAnchor *oa1, *oa2; UpdateSignature *us; Update *update; struct pkt *pkt; - struct bitcoin_tx *anchor, *commit; - struct pubkey pubkey1, pubkey2; - size_t i, num_updates, p2sh_out; - struct sha256_double anchor_txid; - struct bitcoin_signature sig; + struct bitcoin_tx *commit; + struct pubkey pubkey1, pubkey2, final1, final2; + size_t i, num_updates, inmap[2]; + struct sha256_double anchor_txid1, anchor_txid2; + struct sha256 escape_hash1, escape_hash2; int64_t delta; - u8 *redeemscript; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " [previous-updates]\n" + " [previous-updates]\n" "Create a new update-complete message", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc < 7) - opt_usage_exit_fail("Expected 6+ arguments"); + if (argc < 8) + opt_usage_exit_fail("Expected 7+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); - anchor = bitcoin_tx_from_file(ctx, argv[2]); - bitcoin_txid(anchor, &anchor_txid); - o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; - update = pkt_from_file(argv[5], PKT__PKT_UPDATE)->update; - us = pkt_from_file(argv[6], PKT__PKT_UPDATE_SIGNATURE)->update_signature; + o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[5], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); + update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update; + us = pkt_from_file(argv[7], PKT__PKT_UPDATE_SIGNATURE)->update_signature; /* We need last revocation hash (either in update or update-accept), * and the delta */ proto_to_sha256(o2->revocation_hash, &revocation_hash); num_updates = 0; delta = update->delta; - for (i = 7; i < argc; i++) { + for (i = 8; i < argc; i++) { Pkt *p = any_pkt_from_file(argv[i]); switch (p->pkt_case) { case PKT__PKT_UPDATE: @@ -89,30 +93,30 @@ int main(int argc, char *argv[]) errx(1, "Their preimage was incorrect"); /* Get pubkeys */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey1)) + if (!proto_to_pubkey(o1->commitkey, &pubkey1)) errx(1, "Invalid o1 commit pubkey"); - if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o2 final pubkey"); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 commit pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) errx(1, "Invalid o2 final pubkey"); - - /* This is what the anchor pays to; figure out whick output. */ - redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); - p2sh_out = find_p2sh_out(anchor, redeemscript); /* Check their signature signs our new commit tx correctly. */ shachain_from_seed(&seed, num_updates + 1, &preimage); sha256(&our_rhash, &preimage, sizeof(preimage)); commit = create_commit_tx(ctx, o1, o2, &our_rhash, delta, - &anchor_txid, p2sh_out); + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); if (!commit) errx(1, "Delta too large"); - sig.stype = SIGHASH_ALL; - if (!proto_to_signature(us->sig, &sig.sig)) - errx(1, "Invalid update-signature signature"); - - if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript), - &pubkey2, &sig)) - errx(1, "Invalid signature."); + if (!check_anchor_spend(commit, inmap, + &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey2, us->sigs)) + errx(1, "Bad signatures"); /* Hand over our preimage for previous tx. */ shachain_from_seed(&seed, num_updates, &preimage); diff --git a/test-cli/update-channel-signature.c b/test-cli/update-channel-signature.c index 40d0968a3..900fd2bcf 100644 --- a/test-cli/update-channel-signature.c +++ b/test-cli/update-channel-signature.c @@ -22,107 +22,110 @@ int main(int argc, char *argv[]) { const tal_t *ctx = tal_arr(NULL, char, 0); - struct sha256 seed, revocation_hash, preimage; + struct sha256 seed, revocation_hash, preimage, + escape_hash1, escape_hash2; OpenChannel *o1, *o2; + OpenAnchor *oa1, *oa2; UpdateAccept *ua; Update *update; - struct bitcoin_tx *anchor, *commit; - struct sha256_double anchor_txid; + struct bitcoin_tx *commit; + struct sha256_double anchor_txid1, anchor_txid2; struct pkt *pkt; - struct bitcoin_signature sig; + struct signature sigs[2]; struct privkey privkey; bool testnet; - struct pubkey pubkey1, pubkey2; - u8 *redeemscript; + struct pubkey pubkey1, pubkey2, final1, final2; int64_t delta; - size_t i, p2sh_out; + size_t i, inmap[2]; err_set_progname(argv[0]); opt_register_noarg("--help|-h", opt_usage_and_exit, - " [previous-updates]...\n" + " [previous-updates]...\n" "Create a new update-channel-signature message", "Print this message."); opt_parse(&argc, argv, opt_log_stderr_exit); - if (argc < 8) - opt_usage_exit_fail("Expected 7+ arguments"); + if (argc < 9) + opt_usage_exit_fail("Expected 8+ arguments"); if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); - anchor = bitcoin_tx_from_file(ctx, argv[2]); - bitcoin_txid(anchor, &anchor_txid); - o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; - o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; - - if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1)) - errx(1, "Invalid private key '%s'", argv[5]); + o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; + proto_to_sha256(o1->escape_hash, &escape_hash1); + o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; + proto_to_sha256(o2->escape_hash, &escape_hash2); + oa1 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; + oa2 = pkt_from_file(argv[5], PKT__PKT_OPEN_ANCHOR)->open_anchor; + proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha); + proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha); + + if (!key_from_base58(argv[6], strlen(argv[6]), &testnet, &privkey, &pubkey1)) + errx(1, "Invalid private key '%s'", argv[6]); if (!testnet) - errx(1, "Private key '%s' not on testnet!", argv[5]); - - update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update; - ua = pkt_from_file(argv[7], PKT__PKT_UPDATE_ACCEPT)->update_accept; + errx(1, "Private key '%s' not on testnet!", argv[6]); - sig.stype = SIGHASH_ALL; - if (!proto_to_signature(ua->sig, &sig.sig)) - errx(1, "Invalid update signature"); + update = pkt_from_file(argv[7], PKT__PKT_UPDATE)->update; + ua = pkt_from_file(argv[8], PKT__PKT_UPDATE_ACCEPT)->update_accept; /* Figure out cumulative delta since anchor. */ delta = 0; - for (i = 8; i < argc; i++) { + for (i = 9; i < argc; i++) { Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update; delta += u->delta; } /* Give up revocation preimage for old tx. */ - shachain_from_seed(&seed, argc - 7 - 1, &preimage); + shachain_from_seed(&seed, argc - 8 - 1, &preimage); /* Get pubkeys */ - if (!proto_to_pubkey(o1->anchor->pubkey, &pubkey2)) + if (!proto_to_pubkey(o1->commitkey, &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); - p2sh_out = find_p2sh_out(anchor, redeemscript); + if (!proto_to_pubkey(o2->commitkey, &pubkey2)) + errx(1, "Invalid o2 commit pubkey"); + if (!proto_to_pubkey(o1->final, &final1)) + errx(1, "Invalid o1 final pubkey"); + if (!proto_to_pubkey(o2->final, &final2)) + errx(1, "Invalid o2 final pubkey"); /* Check our new commit is signed correctly by them. */ proto_to_sha256(update->revocation_hash, &revocation_hash); commit = create_commit_tx(ctx, o1, o2, &revocation_hash, delta, - &anchor_txid, p2sh_out); + &anchor_txid1, oa1->index, o1->total_input, + &anchor_txid2, oa2->index, o2->total_input, + inmap); if (!commit) errx(1, "Delta too large"); - /* Check their signature signs this input correctly. */ - if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript), - &pubkey2, &sig)) - errx(1, "Invalid signature."); + /* Check their signatures sign this input correctly. */ + if (!check_anchor_spend(commit, inmap, &pubkey1, &final1, &escape_hash1, + &pubkey2, &final2, &escape_hash2, + &pubkey2, ua->sigs)) + errx(1, "Invalid signatures"); /* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ proto_to_sha256(ua->revocation_hash, &revocation_hash); commit = create_commit_tx(ctx, o2, o1, &revocation_hash, -delta, - &anchor_txid, - find_p2sh_out(anchor, redeemscript)); + &anchor_txid2, oa2->index, o2->total_input, + &anchor_txid1, oa1->index, o1->total_input, + inmap); /* If contributions don't exceed fees, this fails. */ if (!commit) errx(1, "Delta too large"); - /* Their pubkey must be valid */ - if (!proto_to_pubkey(o2->anchor->pubkey, &pubkey2)) - errx(1, "Invalid public open-channel-file2"); - - /* Sign it for them. */ - sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript), - &privkey, &pubkey1, &sig.sig); + /* Sign it for them (since its theirs, reverse args). */ + if (!sign_anchor_spend(commit, inmap, &pubkey2, &final2, &escape_hash2, + &pubkey1, &final1, &escape_hash1, + &pubkey1, &privkey, sigs)) + errx(1, "Failed creating signatures"); - pkt = update_signature_pkt(ctx, &sig.sig, &preimage); + pkt = update_signature_pkt(ctx, sigs, &preimage); if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) err(1, "Writing out packet"); diff --git a/test-cli/update-channel.c b/test-cli/update-channel.c index be2ed6cf4..d969b4d02 100644 --- a/test-cli/update-channel.c +++ b/test-cli/update-channel.c @@ -6,7 +6,6 @@ #include #include #include "lightning.pb-c.h" -#include "anchor.h" #include "bitcoin/base58.h" #include "pkt.h" #include "bitcoin/script.h"