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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell
2015-07-24 16:00:10 +09:30
parent 11099d738f
commit c03c878afc
33 changed files with 1644 additions and 1623 deletions

View File

@@ -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 <FINALADDR>`
8. TXIN{1-n}: One or more unspent transaction outputs on testnet.
These are in form "<txid>/<outnum>/<amount>/<scriptsig>".
These are in form "<txid>/<outnum>/<amount>/<scriptsig>/<privkey>".
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-SEED> <amount> <A-CHANGEPUBKEY> <A-TMPKEY> <A-FINALKEY> <txid>/<outnum>/<amount>/<scriptsig>... > A-open.pb
test-cli/open-channel <A-SEED> <amount> <A-TMPKEY> <A-FINALKEY> <A-ESCAPE-SECRET> > A-open.pb
B: The same:
test-cli/open-channel <B-SEED> <amount> <B-CHANGEPUBKEY> <B-TMPKEY> <B-FINALKEY> <txid>/<outnum>/<amount>/<scriptsig>... > B-open.pb
test-cli/open-channel <B-SEED> <amount> <B-TMPKEY> <B-FINALKEY> <B-ESCAPE-SECRET> > 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-CHANGEPUBKEY> <txid>/<outnum>/<amount>/<scriptsig>/<privkey>... > A-anchor.tx
test-cli/open-anchor-scriptsigs A-open.pb B-open.pb <A-TXINKEY>... > A-anchor-scriptsigs.pb
B:
test-cli/open-anchor-scriptsigs B-open.pb A-open.pb <B-TXINKEY>... > B-anchor-scriptsigs.pb
test-cli/create-anchor-tx A-open.pb B-open.pb <B-CHANGEPUBKEY> <txid>/<outnum>/<amount>/<scriptsig>/<privkey>... > B-anchor.tx
STEP 3
------
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
B:
test-cli/open-anchor-id B-anchor.tx > B-anchor-id.pb
STEP 4
------
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-TMPKEY> <A-FINALKEY> > A-escape-sigs.pb
B:
test-cli/open-escape-sigs B-open.pb A-open.pb A-anchor-id.pb <B-TMPKEY> <B-FINALKEY> > B-escape-sigs.pb
STEP 5
------
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-FINALKEY> > A-escape.tx
test-cli/create-escape --fast A-open.pb B-open.pb A-anchor-id.pb B-escape-sigs.pb <A-FINALKEY> > A-fast-escape.tx
B:
test-cli/create-escape B-open.pb A-open.pb B-anchor-id.pb A-escape-sigs.pb <B-FINALKEY> > B-escape.tx
test-cli/create-escape --fast B-open.pb A-open.pb B-anchor-id.pb A-escape-sigs.pb <B-FINALKEY> > B-fast-escape.tx
STEP 6
------
Now both sides create the commitment transaction signatures which spend
the transaction output:
the anchors outputs:
A:
test-cli/open-commit-sig A-open.pb B-open.pb <A-TMPKEY> > A-commit-sig.pb
test-cli/open-commit-sig A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb <A-TMPKEY> > A-commit-sig.pb
B:
test-cli/open-commit-sig B-open.pb A-open.ob <B-TMPKEY> > B-commit-sig.pb
test-cli/open-commit-sig B-open.pb A-open.pb B-anchor-id.pb A-anchor-id.pb <B-TMPKEY> > B-commit-sig.pb
STEP 4
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 B-commit-sig.pb <A-TMPKEY> > A-commit-0.tx
test-cli/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-0.tx
B:
test-cli/check-commit-sig B-open.pb A-open.pb A-commit-sig.pb <B-TMPKEY> > B-commit-0.tx
test-cli/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-0.tx
STEP 5
STEP 8
------
Check the anchor signatures from the other side, and use them to generate the
anchor transaction (as a hex string, suitable for bitcoind).
Broadcast the anchor transactions (note they contain their inputs amounts
separated by colons for internal use: the daemon only wants the raw transaction):
A:
alpha-cli -regtest -testnet=0 sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid
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/check-anchor-scriptsigs B-open.pb A-open.pb B-anchor-scriptsigs.pb A-anchor-scriptsigs.pb > B-anchor.tx
They should be identical:
cmp A-anchor.tx B-anchor.tx || echo FAIL
STEP 6
------
Broadcast the anchor transaction:
Either one:
alpha-cli -regtest -testnet=0 sendrawtransaction `cat A-anchor.tx` > anchor.txid
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-SEED> B-anchor.tx B-open.pb A-open.pb <B-TMPKEY> A-update-1.pb > B-update-accept-1.pb
test-cli/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
A completes its side by signing the new tx, and revoking the old:
A:
test-cli/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
test-cli/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
B now revokes its old tx:
B:
test-cli/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
test-cli/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
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-TMPKEY> > 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-TMPKEY> > 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 <A-TMPKEY> 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 <A-TMPKEY> 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-TMPKEY> A-update-1.pb > A-close.pb
./close-channel A-open.pb B-open.pb A-anchor-id.pb B-anchor-id.pb <A-TMPKEY> A-update-1.pb > A-close.pb
B:
./close-channel --complete A-anchor.tx B-open.pb A-open.pb <B-TMPKEY> 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 <B-TMPKEY> 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:

View File

@@ -1,61 +0,0 @@
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <ccan/opt/opt.h>
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include <ccan/structeq/structeq.h>
#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 <unistd.h>
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,
"<open-channel-file1> <open-channel-file2> <anchor-sig2-1> <anchor-sigs2>\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;
}

View File

@@ -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,
"<open-channel-file1> <open-channel-file2> <commit-sig-2> <commit-key1>\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <commit-sig-2> <commit-key1>\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;
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[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[4]);
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);
/* 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");
/* Signatures well-formed? */
if (!proto_to_signature(cs2->sig, &sig2.sig))
errx(1, "Invalid commit-sig-2");
sig2.stype = SIGHASH_ALL;
if (!sign_anchor_spend(commit, inmap, &pubkey1, &final1, &escape_hash1,
&pubkey2, &final2, &escape_hash2,
&pubkey1, &privkey, sigs))
errx(1, "Could not sign tx");
/* Combined signatures must validate correctly. */
if (!check_2of2_sig(commit, 0, subscript, tal_count(subscript),
&pubkey1, &pubkey2, &sig1, &sig2))
errx(1, "Signature failed");
/* populate_anchor_inscripts wants args in protobuf */
mysigs.sig0 = signature_to_proto(ctx, &sigs[0]);
mysigs.sig1 = signature_to_proto(ctx, &sigs[1]);
/* 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);
/* 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))

View File

@@ -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,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [update-protobuf]...\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <commit-privkey> [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);
&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 it for them. */
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
&privkey, &pubkey1, &sig);
/* 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");

188
test-cli/create-anchor-tx.c Normal file
View File

@@ -0,0 +1,188 @@
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <ccan/opt/opt.h>
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "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 <unistd.h>
#include <time.h>
#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 <txid>/<num>/<satoshis>/<hexscript>/<privkey>");
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 <outputnum> 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 <satoshis> 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,
"<our-open.pb> <their-open.pb> <change-pubkey> <txid>/<outnum>/<satoshis>/<script-in-hex>/<privkey>...\n"
"A test program to create an anchor transaction on stdout.",
"Print this message.");
opt_register_arg("--anchor-fee=<bits>",
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;
}

View File

@@ -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,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <close-protobuf> <close-complete-protobuf> [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);
close_tx = create_close_tx(ctx, o1, o2, delta,
&anchor_txid1, oa1->index, o1->total_input,
&anchor_txid2, oa2->index, o2->total_input,
inmap);
/* 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");
/* 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");

View File

@@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/structeq/structeq.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"

View File

@@ -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,
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [final-update-accept|open-commit-sig] [<updates>]\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <commit-privkey> [final-update-accept|open-commit-sig] [<updates>]\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_anchor_spend(commit, inmap,
&pubkey1, &final1, &escape_hash1,
&pubkey2, &final2, &escape_hash2,
&pubkey2, their_sigs))
errx(1, "Bad signatures");
if (!check_2of2_sig(commit, 0, redeemscript, tal_count(redeemscript),
&pubkey1, &pubkey2, &sig1, &sig2))
errx(1, "Signature failed");
/* 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");
/* 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);
/* 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");

View File

@@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"

View File

@@ -5,7 +5,6 @@
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#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;

79
test-cli/open-anchor-id.c Normal file
View File

@@ -0,0 +1,79 @@
#include <ccan/crypto/shachain/shachain.h>
#include <ccan/short_types/short_types.h>
#include <ccan/tal/tal.h>
#include <ccan/opt/opt.h>
#include <ccan/str/hex/hex.h>
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "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 <unistd.h>
#include <time.h>
#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,
"<anchor-tx-file> <change-key>\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;
}

View File

@@ -1,98 +0,0 @@
#include <ccan/err/err.h>
#include <ccan/opt/opt.h>
#include <ccan/read_write_all/read_write_all.h>
#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 <unistd.h>
/* 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,
"<open-channel-file1> <open-channel-file2> <privkey>...\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;
}

View File

@@ -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 <txid>/<num>/<satoshis>/<hexscript>");
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 <outputnum> 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 <satoshis> 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,
"<seed> <amount> <changepubkey> <commitprivkey> <outprivkey> <txid>/<outnum>/<satoshis>/<script-in-hex>...\n"
"<seed> <amount> <commitprivkey> <outprivkey> <escape-secret>\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=<bits>",
opt_set_bits, opt_show_bits, &anchor.fee,
"100's of satoshi to pay for anchor");
opt_register_arg("--commitment-fee=<bits>",
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[3]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[3]);
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet,
&outprivkey, &outkey))
errx(1, "Invalid private key '%s'", argv[4]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[4]);
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet,
&outprivkey, &outkey))
errx(1, "Invalid private key '%s'", argv[5]);
if (!testnet)
errx(1, "Private key '%s' not on testnet!", argv[5]);
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");

View File

@@ -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,
"<open-channel-file1> <open-channel-file2> <commit-privkey>\n"
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <commit-privkey>\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;
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[3], strlen(argv[3]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[3]);
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]);
errx(1, "Private key '%s' not on testnet!", argv[5]);
/* Create merged anchor transaction */
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
if (!anchor)
errx(1, "Failed transaction merge");
proto_to_sha256(oa1->anchor_txid, &anchor_txid1.sha);
proto_to_sha256(oa2->anchor_txid, &anchor_txid2.sha);
/* Get the transaction ID of the anchor. */
anchor_txid(anchor, &txid);
/* 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");
/* 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");
/* Sign it for them. */
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
&privkey, &pubkey1, &sig);
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");

View File

@@ -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

View File

@@ -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 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
# Now create commit signature
$PREFIX ./open-commit-sig A-open.pb B-open.pb $A_TMPKEY > A-commit-sig.pb
$PREFIX ./open-commit-sig B-open.pb A-open.pb $B_TMPKEY > B-commit-sig.pb
$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
$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
# 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
# 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

View File

@@ -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,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> [previous-updates]\n"
"<seed> <open-channel-file1> <open-channel-file2> <anchor-id-file1> <anchor-id-file2> <commit-privkey> <update-protobuf> [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;
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[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[5]);
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");

View File

@@ -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,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <update-protobuf> <update-signature-protobuf> [previous-updates]\n"
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <update-protobuf> <update-signature-protobuf> [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);

View File

@@ -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,
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> <update-accept-protobuf> [previous-updates]...\n"
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file1> <open-anchor-file2> <commit-privkey> <update-protobuf> <update-accept-protobuf> [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;
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[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
errx(1, "Invalid private key '%s'", argv[5]);
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;
ua = pkt_from_file(argv[7], PKT__PKT_UPDATE_ACCEPT)->update_accept;
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 (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");
/* Sign it for them. */
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
&privkey, &pubkey1, &sig.sig);
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");

View File

@@ -6,7 +6,6 @@
#include <ccan/err/err.h>
#include <ccan/read_write_all/read_write_all.h>
#include "lightning.pb-c.h"
#include "anchor.h"
#include "bitcoin/base58.h"
#include "pkt.h"
#include "bitcoin/script.h"