Browse Source
We're about to change the protocol again, and I don't want to do the grunt work to update these. They were useful for pre-build protocol testing, though. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>ppa-0.6.1
Rusty Russell
9 years ago
29 changed files with 6 additions and 3391 deletions
@ -1,100 +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 "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "protobuf_convert.h" |
|||
#include "funding.h" |
|||
#include "gather_updates.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit; |
|||
u8 *subscript; |
|||
struct pubkey pubkey1, pubkey2; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct sha256 rhash; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <commit-key1> [<commit-sig>]\n" |
|||
"Check the commit sig is valid (either in open-anchor or commit-sig packet)", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 5 && argc != 6) |
|||
opt_usage_exit_fail("Expected 4 or 5 arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[4]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[4]); |
|||
|
|||
sig.stype = SIGHASH_ALL; |
|||
if (argc == 6) { |
|||
OpenCommitSig *cs = pkt_from_file(argv[5], |
|||
PKT__PKT_OPEN_COMMIT_SIG) |
|||
->open_commit_sig; |
|||
if (!proto_to_signature(cs->sig, &sig.sig)) |
|||
errx(1, "Bad signature in %s", argv[5]); |
|||
} else { |
|||
if (!proto_to_signature(a->commit_sig, &sig.sig)) |
|||
errx(1, "Bad signature in %s", argv[3]); |
|||
} |
|||
|
|||
/* Pubkey well-formed? */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit_key"); |
|||
|
|||
if (is_funder(o1) == is_funder(o2)) |
|||
errx(1, "Must be exactly one funder"); |
|||
|
|||
cstate = initial_funding(ctx, is_funder(o1), a->amount, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee)); |
|||
if (!cstate) |
|||
errx(1, "Invalid open combination (need to cover fees)"); |
|||
|
|||
/* Now create our commitment tx. */ |
|||
proto_to_sha256(o1->revocation_hash, &rhash); |
|||
commit = commit_tx_from_pkts(ctx, o1, o2, a, &rhash, cstate); |
|||
|
|||
/* Check signature. */ |
|||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
if (!check_tx_sig(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY), |
|||
commit, 0, subscript, tal_count(subscript), |
|||
&pubkey2, &sig)) |
|||
errx(1, "Their signature invalid"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,123 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.h" |
|||
#include "bitcoin/base58.h" |
|||
#include "pkt.h" |
|||
#include "bitcoin/script.h" |
|||
#include "permute_tx.h" |
|||
#include "funding.h" |
|||
#include "commit_tx.h" |
|||
#include "bitcoin/signature.h" |
|||
#include "bitcoin/pubkey.h" |
|||
#include "bitcoin/privkey.h" |
|||
#include "close_tx.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "opt_bits.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *close_tx; |
|||
struct pkt *pkt; |
|||
struct signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct pubkey pubkey1, pubkey2, final1, final2; |
|||
struct sha256_double anchor_txid; |
|||
u8 *redeemscript; |
|||
char *close_file = NULL; |
|||
u64 close_fee = 10000; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_arg("--complete=<close-msg-file>", |
|||
opt_set_charp, NULL, &close_file, |
|||
"Create a close_transaction_complete msg instead"); |
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <anchor-file> <commit-privkey> [{+/-}update-protobuf]...\n" |
|||
"Create the signature needed for the close transaction", |
|||
"Print this message."); |
|||
opt_register_arg("--close-fee=<bits>", |
|||
opt_set_bits, opt_show_bits, &close_fee, |
|||
"100's of satoshi to pay for close tx"); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 5) |
|||
opt_usage_exit_fail("Expected 4+ arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[4]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[4]); |
|||
|
|||
if (close_file) { |
|||
CloseChannel *c; |
|||
c = pkt_from_file(close_file, PKT__PKT_CLOSE)->close; |
|||
close_fee = c->close_fee; |
|||
} |
|||
|
|||
cstate = gather_updates(ctx, o1, o2, a, close_fee, argv + 5, NULL, |
|||
NULL, NULL, NULL); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o1 commit pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit pubkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->final_key, &final1)) |
|||
errx(1, "Invalid o1 final pubkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->final_key, &final2)) |
|||
errx(1, "Invalid o2 final pubkey"); |
|||
|
|||
/* This is what the anchor pays to. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
proto_to_sha256(a->txid, &anchor_txid.sha); |
|||
close_tx = create_close_tx(secp256k1_context_create(0), |
|||
ctx, &final1, &final2, |
|||
&anchor_txid, a->output_index, a->amount, |
|||
cstate->a.pay_msat / 1000, |
|||
cstate->b.pay_msat / 1000); |
|||
|
|||
/* Sign it for them. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
close_tx, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig); |
|||
|
|||
if (close_file) |
|||
pkt = close_channel_complete_pkt(ctx, &sig); |
|||
else |
|||
pkt = close_channel_pkt(ctx, close_fee, &sig); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,196 +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/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" |
|||
#include "version.h" |
|||
|
|||
/* Bitcoin nodes are allowed to be 2 hours in the future. */ |
|||
#define LOCKTIME_MIN (2 * 60 * 60) |
|||
|
|||
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(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
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); |
|||
} |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
OpenChannel *o1, *o2; |
|||
struct bitcoin_tx *anchor; |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
u64 anchor_fee, amount, total_in, change; |
|||
struct input *in; |
|||
u8 *redeemscript; |
|||
size_t i; |
|||
struct pubkey pubkey1, pubkey2; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
anchor_fee = 10000; |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <amount> <changepubkey> <txid>/<outnum>/<satoshis>/<script-in-hex>/<privkey>...\n" |
|||
"A test program to create an anchor tx 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_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 6) |
|||
opt_usage_exit_fail("Expected 5 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(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey1)) |
|||
errx(1, "Invalid o1 commit_key"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit_key"); |
|||
|
|||
amount = atol(argv[3]); |
|||
if (!amount) |
|||
errx(1, "Invalid total: must be > 0"); |
|||
|
|||
in = tal_arr(ctx, struct input, argc - 5); |
|||
|
|||
total_in = 0; |
|||
for (i = 0; i < tal_count(in); i++) { |
|||
parse_anchor_input(argv[5+i], &in[i]); |
|||
total_in += in[i].in.input_amount; |
|||
} |
|||
|
|||
if (total_in < amount + anchor_fee) |
|||
errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)", |
|||
(unsigned long long)total_in, |
|||
(unsigned long long)amount, |
|||
(unsigned long long)anchor_fee); |
|||
|
|||
change = total_in - (amount + 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; |
|||
|
|||
/* Commitment redeems this via 2 of 2 payment. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
/* Set up outputs. */ |
|||
anchor->output[0].amount = amount; |
|||
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(secp256k1_context_create(0), |
|||
argv[4], strlen(argv[4]), &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; |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
anchor, i, in[i].in.script, |
|||
in[i].in.script_length, |
|||
&in[i].privkey, &in[i].pubkey, |
|||
&in[i].sig.sig); |
|||
} |
|||
|
|||
/* 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; |
|||
} |
@ -1,109 +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 "lightning.pb-c.h" |
|||
#include "bitcoin/base58.h" |
|||
#include "pkt.h" |
|||
#include "bitcoin/script.h" |
|||
#include "permute_tx.h" |
|||
#include "bitcoin/signature.h" |
|||
#include "bitcoin/pubkey.h" |
|||
#include "close_tx.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *close_tx; |
|||
struct bitcoin_signature sig1, sig2; |
|||
struct pubkey pubkey1, pubkey2, final1, final2; |
|||
struct sha256_double anchor_txid; |
|||
u8 *redeemscript; |
|||
CloseChannel *close; |
|||
CloseChannelComplete *closecomplete; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
/* FIXME: Take update.pbs to adjust channel */ |
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n" |
|||
"Create the close transaction from the signatures", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 6) |
|||
opt_usage_exit_fail("Expected 5+ arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
close = pkt_from_file(argv[4], PKT__PKT_CLOSE)->close; |
|||
closecomplete = pkt_from_file(argv[5], PKT__PKT_CLOSE_COMPLETE)->close_complete; |
|||
|
|||
/* Pubkeys well-formed? */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey1)) |
|||
errx(1, "Invalid o1 commit_key"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit_key"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->final_key, &final1)) |
|||
errx(1, "Invalid o1 final pubkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->final_key, &final2)) |
|||
errx(1, "Invalid o2 final pubkey"); |
|||
|
|||
/* Get delta by accumulting all the updates. */ |
|||
cstate = gather_updates(ctx, o1, o2, a, close->close_fee, argv + 6, |
|||
NULL, NULL, NULL, NULL); |
|||
|
|||
/* 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. */ |
|||
proto_to_sha256(a->txid, &anchor_txid.sha); |
|||
close_tx = create_close_tx(secp256k1_context_create(0), |
|||
ctx, &final1, &final2, |
|||
&anchor_txid, a->output_index, a->amount, |
|||
cstate->a.pay_msat / 1000, |
|||
cstate->b.pay_msat / 1000); |
|||
|
|||
/* 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(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY), |
|||
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); |
|||
|
|||
/* Print it out in hex. */ |
|||
if (!bitcoin_tx_write(STDOUT_FILENO, close_tx)) |
|||
err(1, "Writing out transaction"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,137 +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 "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 "bitcoin/privkey.h" |
|||
#include "bitcoin/address.h" |
|||
#include "opt_bits.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "test-cli/gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include "bitcoin/locktime.h" |
|||
#include "tx_from_file.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit, *tx; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct pubkey pubkey1, pubkey2, outpubkey; |
|||
u8 *redeemscript; |
|||
struct sha256 rhash; |
|||
size_t p2sh_out; |
|||
u64 fee = 10000; |
|||
struct rel_locktime locktime; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
/* FIXME: If we've updated channel since, we need the final
|
|||
* revocation hash we sent (either update_accept or update_complete) */ |
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<commitment-tx> <open-channel-file1> <open-channel-file2> <open-anchor-file> <my-privoutkey> <someaddress> [previous-updates]\n" |
|||
"Create the transaction to spend our commit transaction", |
|||
"Print this message."); |
|||
opt_register_arg("--fee=<bits>", |
|||
opt_set_bits, opt_show_bits, &fee, |
|||
"100's of satoshi to pay in transaction fee"); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 6) |
|||
opt_usage_exit_fail("Expected 5+ arguments"); |
|||
|
|||
commit = 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; |
|||
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
if (!proto_to_rel_locktime(o2->delay, &locktime)) |
|||
errx(1, "Invalid locktime in o2"); |
|||
|
|||
/* We need our private key to spend commit output. */ |
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
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[5]); |
|||
|
|||
if (!pubkey_from_hexstr(secp256k1_context_create(0), |
|||
argv[6], strlen(argv[6]), &outpubkey)) |
|||
errx(1, "Invalid bitcoin pubkey '%s'", argv[6]); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->final_key, &pubkey2)) |
|||
errx(1, "Invalid o1 final pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->final_key, &pubkey2)) |
|||
errx(1, "Invalid o2 final pubkey"); |
|||
|
|||
/* We use this simply to get final revocation hash. */ |
|||
gather_updates(ctx, o1, o2, a, |
|||
commit_fee(o1->commitment_fee, o2->commitment_fee), |
|||
argv + 7, |
|||
NULL, &rhash, NULL, NULL); |
|||
|
|||
/* Create redeem script */ |
|||
redeemscript = bitcoin_redeem_secret_or_delay(ctx, &pubkey1, &locktime, |
|||
&pubkey2, &rhash); |
|||
|
|||
/* Now, create transaction to spend it. */ |
|||
tx = bitcoin_tx(ctx, 1, 1); |
|||
bitcoin_txid(commit, &tx->input[0].txid); |
|||
p2sh_out = find_p2sh_out(commit, redeemscript); |
|||
tx->input[0].index = p2sh_out; |
|||
tx->input[0].input_amount = commit->output[p2sh_out].amount; |
|||
tx->fee = fee; |
|||
|
|||
tx->input[0].sequence_number = bitcoin_nsequence(&locktime); |
|||
|
|||
if (commit->output[p2sh_out].amount <= fee) |
|||
errx(1, "Amount of %llu won't exceed fee", |
|||
(unsigned long long)commit->output[p2sh_out].amount); |
|||
|
|||
tx->output[0].amount = commit->output[p2sh_out].amount - fee; |
|||
tx->output[0].script = scriptpubkey_p2sh(tx, |
|||
bitcoin_redeem_single(tx, &outpubkey)); |
|||
tx->output[0].script_length = tal_count(tx->output[0].script); |
|||
|
|||
/* Now get signature, to set up input script. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
tx, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig.sig); |
|||
sig.stype = SIGHASH_ALL; |
|||
tx->input[0].script = scriptsig_p2sh_secret(tx, NULL, 0, &sig, |
|||
redeemscript, |
|||
tal_count(redeemscript)); |
|||
tx->input[0].script_length = tal_count(tx->input[0].script); |
|||
|
|||
/* Print it out in hex. */ |
|||
if (!bitcoin_tx_write(STDOUT_FILENO, tx)) |
|||
err(1, "Writing out transaction"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,112 +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 "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
/* FIXME: this code doesn't work if we're not the ones proposing the delta */ |
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct bitcoin_signature sig1, sig2; |
|||
struct pubkey pubkey1, pubkey2; |
|||
u8 *redeemscript; |
|||
struct sha256 rhash; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> [<updates>]\n" |
|||
"Create the signature needed for the commit transaction", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 5) |
|||
opt_usage_exit_fail("Expected 4+ arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[4]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[4]); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o1 commit pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit pubkey"); |
|||
|
|||
sig2.stype = SIGHASH_ALL; |
|||
|
|||
cstate = gather_updates(ctx, o1, o2, a, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee), |
|||
argv + 5, |
|||
NULL, &rhash, NULL, &sig2.sig); |
|||
|
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
/* Now create commitment tx to spend 2/2 output of anchor. */ |
|||
commit = commit_tx_from_pkts(ctx, o1, o2, a, &rhash, cstate); |
|||
|
|||
/* This only fails on malformed packets */ |
|||
if (!commit) |
|||
errx(1, "Malformed packets"); |
|||
|
|||
/* We generate our signature. */ |
|||
sig1.stype = SIGHASH_ALL; |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig1.sig); |
|||
|
|||
/* Check it works with theirs... */ |
|||
if (!check_2of2_sig(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY), |
|||
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); |
|||
|
|||
/* Print it out in hex. */ |
|||
if (!bitcoin_tx_write(STDOUT_FILENO, commit)) |
|||
err(1, "Writing out transaction"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,212 +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 "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 "bitcoin/privkey.h" |
|||
#include "protobuf_convert.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "bitcoin/locktime.h" |
|||
#include "version.h" |
|||
#include "tx_from_file.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 revoke_hash, htlc_rhash, val, expect; |
|||
OpenChannel *o1, *o2; |
|||
UpdateAddHtlc *u; |
|||
struct bitcoin_tx *commit, *tx; |
|||
u8 *redeemscript; |
|||
struct pubkey pubkey1, pubkey2, key, outpubkey; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct rel_locktime locktime; |
|||
struct abs_locktime htlc_abstimeout; |
|||
char *rvalue = NULL, *preimage = NULL; |
|||
bool received, own_commit_tx; |
|||
Pkt *pkt; |
|||
const void *secret = NULL; |
|||
size_t secret_len = 0; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_arg("--rvalue", opt_set_charp, NULL, &rvalue, |
|||
"Use R value to spend htlc output"); |
|||
opt_register_arg("--commit-preimage=<update-msg>", opt_set_charp, NULL, &preimage, |
|||
"Use commit revocation preimage to spend htlc output"); |
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <commit-tx> [+-]<htlc-add-message-file> <final-update-message-for-commit-tx> <final-privkey> <outpubkey>\n" |
|||
"Create a transaction which spends commit-tx's htlc output, and sends it P2SH to outpubkey\n" |
|||
"It relies on timeout, unless --rvalue or --commit-preimage is specified", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 8) |
|||
opt_usage_exit_fail("Expected 7 arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
commit = bitcoin_tx_from_file(ctx, argv[3]); |
|||
if (strstarts(argv[4], "+")) |
|||
received = false; |
|||
else if (strstarts(argv[4], "-")) |
|||
received = true; |
|||
else |
|||
errx(1, "%s doesn't begin with + or -", argv[4]); |
|||
u = pkt_from_file(argv[4]+1, PKT__PKT_UPDATE_ADD_HTLC)->update_add_htlc; |
|||
|
|||
/* This gives us the revocation hash. */ |
|||
pkt = any_pkt_from_file(argv[5]); |
|||
switch (pkt->pkt_case) { |
|||
case PKT__PKT_UPDATE_ADD_HTLC: |
|||
proto_to_sha256(pkt->update_add_htlc->revocation_hash, |
|||
&revoke_hash); |
|||
break; |
|||
case PKT__PKT_UPDATE: |
|||
proto_to_sha256(pkt->update->revocation_hash, &revoke_hash); |
|||
break; |
|||
case PKT__PKT_UPDATE_ACCEPT: |
|||
proto_to_sha256(pkt->update_accept->revocation_hash, |
|||
&revoke_hash); |
|||
break; |
|||
default: |
|||
errx(1, "Expected update or update-add-htlc for %s", argv[5]); |
|||
} |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[6], strlen(argv[6]), &testnet, &privkey, &key)) |
|||
errx(1, "Invalid private key '%s'", argv[6]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[6]); |
|||
|
|||
if (!pubkey_from_hexstr(secp256k1_context_create(0), |
|||
argv[7], strlen(argv[7]), &outpubkey)) |
|||
errx(1, "Invalid commit key '%s'", argv[7]); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->final_key, &pubkey1)) |
|||
errx(1, "Invalid o1 final pubkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->final_key, &pubkey2)) |
|||
errx(1, "Invalid o2 final pubkey"); |
|||
|
|||
if (pubkey_eq(&key, &pubkey1)) { |
|||
own_commit_tx = true; |
|||
} else if (pubkey_eq(&key, &pubkey2)) { |
|||
own_commit_tx = false; |
|||
} else |
|||
errx(1, "Privkey doesn't match either key"); |
|||
|
|||
if (!proto_to_rel_locktime(o2->delay, &locktime)) |
|||
errx(1, "Invalid o2 delay"); |
|||
if (!proto_to_abs_locktime(u->expiry, &htlc_abstimeout)) |
|||
errx(1, "Invalid htlc expiry"); |
|||
proto_to_sha256(u->r_hash, &htlc_rhash); |
|||
|
|||
if (received) { |
|||
redeemscript = scriptpubkey_htlc_recv(ctx, &pubkey1, &pubkey2, |
|||
&htlc_abstimeout, |
|||
&locktime, &revoke_hash, |
|||
&htlc_rhash); |
|||
} else { |
|||
redeemscript = scriptpubkey_htlc_send(ctx, &pubkey1, &pubkey2, |
|||
&htlc_abstimeout, |
|||
&locktime, &revoke_hash, |
|||
&htlc_rhash); |
|||
} |
|||
|
|||
if (rvalue) { |
|||
if (!hex_decode(rvalue, strlen(rvalue), &val, sizeof(val))) |
|||
errx(1, "Invalid rvalue '%s' - need 256 hex bits", |
|||
rvalue); |
|||
sha256(&expect, &val, sizeof(val)); |
|||
if (!structeq(&expect, &htlc_rhash)) |
|||
errx(1, "--rvalue is not correct"); |
|||
secret = &val; |
|||
secret_len = sizeof(val); |
|||
} |
|||
if (preimage) { |
|||
Pkt *pkt = any_pkt_from_file(preimage); |
|||
switch (pkt->pkt_case) { |
|||
case PKT__PKT_UPDATE_SIGNATURE: |
|||
proto_to_sha256(pkt->update_signature->revocation_preimage, |
|||
&val); |
|||
break; |
|||
case PKT__PKT_UPDATE_COMPLETE: |
|||
proto_to_sha256(pkt->update_complete->revocation_preimage, |
|||
&val); |
|||
break; |
|||
default: |
|||
errx(1, "Expected update or update-complete in %s", |
|||
preimage); |
|||
} |
|||
sha256(&expect, &val, sizeof(val)); |
|||
if (!structeq(&expect, &revoke_hash)) |
|||
errx(1, "--commit-preimage is not correct"); |
|||
secret = &val; |
|||
secret_len = sizeof(val); |
|||
} |
|||
|
|||
tx = bitcoin_tx(ctx, 1, 1); |
|||
bitcoin_txid(commit, &tx->input[0].txid); |
|||
tx->input[0].index = find_p2sh_out(commit, redeemscript); |
|||
tx->input[0].input_amount = commit->output[tx->input[0].index].amount; |
|||
|
|||
if (!secret_len) { |
|||
/* We must be relying on HTLC timeout. */ |
|||
tx->lock_time = htlc_abstimeout.locktime; |
|||
/* Locktime only applies if an input has seq != ffffffff... */ |
|||
tx->input[0].sequence_number = 0; |
|||
} |
|||
|
|||
/* If it's our own commit tx, we also need delay. */ |
|||
if (own_commit_tx) |
|||
tx->input[0].sequence_number = bitcoin_nsequence(&locktime); |
|||
|
|||
/* Leave 10,000 satoshi as fee (if we can!). */ |
|||
tx->fee = 10000; |
|||
if (tx->input[0].input_amount <= tx->fee) |
|||
errx(1, "Cannot afford fee: only %llu satoshi!", |
|||
(long long)tx->input[0].input_amount); |
|||
tx->output[0].amount = tx->input[0].input_amount - tx->fee; |
|||
tx->output[0].script = scriptpubkey_p2sh(tx, |
|||
bitcoin_redeem_single(tx, &outpubkey)); |
|||
tx->output[0].script_length = tal_count(tx->output[0].script); |
|||
|
|||
/* Now get signature, to set up input script. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
tx, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &key, &sig.sig); |
|||
|
|||
sig.stype = SIGHASH_ALL; |
|||
tx->input[0].script = scriptsig_p2sh_secret(tx, secret, secret_len, |
|||
&sig, |
|||
redeemscript, |
|||
tal_count(redeemscript)); |
|||
tx->input[0].script_length = tal_count(tx->input[0].script); |
|||
|
|||
/* Print it out in hex. */ |
|||
if (!bitcoin_tx_write(STDOUT_FILENO, tx)) |
|||
err(1, "Writing out transaction"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,140 +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 "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "protobuf_convert.h" |
|||
#include "version.h" |
|||
#include "bitcoin/locktime.h" |
|||
#include "tx_from_file.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 revoke_preimage, revoke_hash; |
|||
OpenChannel *o1, *o2; |
|||
Pkt *pkt; |
|||
struct bitcoin_tx *commit, *tx; |
|||
u8 *redeemscript, *p2sh; |
|||
size_t i; |
|||
struct pubkey pubkey1, pubkey2, outpubkey; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct rel_locktime locktime; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<commit-tx> <revocation-preimage> <final-privkey> <open-channel-file1> <open-channel-file2> <outpubkey>\n" |
|||
"Create a transaction which spends commit-tx's revocable output, and sends it P2SH to outpubkey", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 7) |
|||
opt_usage_exit_fail("Expected 6 arguments"); |
|||
|
|||
commit = bitcoin_tx_from_file(ctx, argv[1]); |
|||
|
|||
pkt = any_pkt_from_file(argv[2]); |
|||
switch (pkt->pkt_case) { |
|||
case PKT__PKT_UPDATE_SIGNATURE: |
|||
proto_to_sha256(pkt->update_signature->revocation_preimage, |
|||
&revoke_preimage); |
|||
break; |
|||
case PKT__PKT_UPDATE_COMPLETE: |
|||
proto_to_sha256(pkt->update_complete->revocation_preimage, |
|||
&revoke_preimage); |
|||
break; |
|||
default: |
|||
errx(1, "Expected update or update-complete in %s", argv[2]); |
|||
} |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[3], strlen(argv[3]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[3]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[3]); |
|||
|
|||
o1 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[5], PKT__PKT_OPEN)->open; |
|||
if (!proto_to_rel_locktime(o1->delay, &locktime)) |
|||
errx(1, "Invalid locktime in o2"); |
|||
|
|||
if (!pubkey_from_hexstr(secp256k1_context_create(0), |
|||
argv[6], strlen(argv[6]), &outpubkey)) |
|||
errx(1, "Invalid bitcoin pubkey '%s'", argv[6]); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->final_key, &pubkey2)) |
|||
errx(1, "Invalid o1 final pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->final_key, &pubkey2)) |
|||
errx(1, "Invalid o2 final pubkey"); |
|||
|
|||
/* Now, which commit output? Match redeem script. */ |
|||
sha256(&revoke_hash, &revoke_preimage, sizeof(revoke_preimage)); |
|||
redeemscript = bitcoin_redeem_secret_or_delay(ctx, &pubkey2, |
|||
&locktime, |
|||
&pubkey1, &revoke_hash); |
|||
p2sh = scriptpubkey_p2sh(ctx, redeemscript); |
|||
|
|||
for (i = 0; i < commit->output_count; i++) { |
|||
if (commit->output[i].script_length != tal_count(p2sh)) |
|||
continue; |
|||
if (memcmp(commit->output[i].script, p2sh, tal_count(p2sh)) == 0) |
|||
break; |
|||
} |
|||
if (i == commit->output_count) |
|||
errx(1, "No matching output in %s", argv[1]); |
|||
|
|||
tx = bitcoin_tx(ctx, 1, 1); |
|||
bitcoin_txid(commit, &tx->input[0].txid); |
|||
tx->input[0].index = i; |
|||
tx->input[0].input_amount = commit->output[i].amount; |
|||
|
|||
/* Leave 10,000 satoshi as fee. */ |
|||
tx->fee = 10000; |
|||
tx->output[0].amount = commit->output[i].amount - tx->fee; |
|||
tx->output[0].script = scriptpubkey_p2sh(tx, |
|||
bitcoin_redeem_single(tx, &outpubkey)); |
|||
tx->output[0].script_length = tal_count(tx->output[0].script); |
|||
|
|||
/* Now get signature, to set up input script. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
tx, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig.sig); |
|||
sig.stype = SIGHASH_ALL; |
|||
tx->input[0].script = scriptsig_p2sh_secret(tx, |
|||
&revoke_preimage, |
|||
sizeof(revoke_preimage), |
|||
&sig, |
|||
redeemscript, |
|||
tal_count(redeemscript)); |
|||
tx->input[0].script_length = tal_count(tx->input[0].script); |
|||
|
|||
/* Print it out in hex. */ |
|||
if (!bitcoin_tx_write(STDOUT_FILENO, tx)) |
|||
err(1, "Writing out transaction"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,370 +0,0 @@ |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/crypto/sha256/sha256.h> |
|||
#include <ccan/structeq/structeq.h> |
|||
#include "test-cli/gather_updates.h" |
|||
#include "commit_tx.h" |
|||
#include "funding.h" |
|||
#include "pkt.h" |
|||
#include "protobuf_convert.h" |
|||
|
|||
static void check_preimage(const Sha256Hash *preimage, |
|||
const struct sha256 *old, |
|||
const struct sha256 *h, |
|||
const char *file) |
|||
{ |
|||
struct sha256 sha; |
|||
|
|||
if (!h) |
|||
return; |
|||
|
|||
proto_to_sha256(preimage, &sha); |
|||
sha256(&sha, &sha, sizeof(sha)); |
|||
if (!structeq(&sha, old)) |
|||
errx(1, "Invalid preimage in %s!", file); |
|||
} |
|||
|
|||
/* Returns tal_count(oneside->htlcs) if not found. */ |
|||
static size_t find_htlc(struct channel_oneside *oneside, |
|||
const Sha256Hash *rhash) |
|||
{ |
|||
size_t i, n; |
|||
struct sha256 h; |
|||
|
|||
proto_to_sha256(rhash, &h); |
|||
|
|||
n = tal_count(oneside->htlcs); |
|||
for (i = 0; i < n; i++) { |
|||
if (structeq(&oneside->htlcs[i].rhash, &h)) |
|||
break; |
|||
} |
|||
return i; |
|||
} |
|||
|
|||
static void add_htlc(struct channel_oneside *oneside, |
|||
const UpdateAddHtlc *ah, |
|||
const char *file) |
|||
{ |
|||
size_t num = tal_count(oneside->htlcs); |
|||
struct sha256 rhash; |
|||
struct abs_locktime expiry; |
|||
|
|||
if (find_htlc(oneside, ah->r_hash) != num) |
|||
errx(1, "Duplicate R hash in %s", file); |
|||
|
|||
proto_to_sha256(ah->r_hash, &rhash); |
|||
proto_to_abs_locktime(ah->expiry, &expiry); |
|||
funding_add_htlc(oneside, ah->amount_msat, &expiry, &rhash); |
|||
} |
|||
|
|||
static void remove_htlc(struct channel_oneside *oneside, size_t n) |
|||
{ |
|||
size_t num = tal_count(oneside->htlcs); |
|||
|
|||
assert(n < num); |
|||
|
|||
/* Remove. */ |
|||
if (num > 0) |
|||
oneside->htlcs[n] = oneside->htlcs[num-1]; |
|||
tal_resize(&oneside->htlcs, num - 1); |
|||
} |
|||
|
|||
static void update_rhash(const Sha256Hash *rhash, |
|||
bool received, |
|||
size_t *num_updates, |
|||
struct sha256 *old_our_rhash, |
|||
struct sha256 *old_their_rhash, |
|||
struct sha256 *our_rhash, |
|||
struct sha256 *their_rhash) |
|||
{ |
|||
/* Update rhash (and save old one for checking) */ |
|||
if (received) { |
|||
*old_their_rhash = *their_rhash; |
|||
proto_to_sha256(rhash, their_rhash); |
|||
} else { |
|||
*old_our_rhash = *our_rhash; |
|||
proto_to_sha256(rhash, our_rhash); |
|||
} |
|||
/* If they care, we count number of updates. */ |
|||
if (num_updates) |
|||
(*num_updates)++; |
|||
} |
|||
|
|||
static uint32_t htlcs_total(const struct channel_htlc *htlcs) |
|||
{ |
|||
size_t i, n = tal_count(htlcs); |
|||
uint32_t total = 0; |
|||
|
|||
for (i = 0; i < n; i++) |
|||
total += htlcs[i].msatoshis; |
|||
return total; |
|||
} |
|||
|
|||
/* Takes complete update history, gets summary of last state. */ |
|||
struct channel_state *gather_updates(const tal_t *ctx, |
|||
const OpenChannel *o1, const OpenChannel *o2, |
|||
const OpenAnchor *oa, uint64_t fee, |
|||
char **argv, |
|||
size_t *num_updates, |
|||
struct sha256 *our_rhash, |
|||
struct sha256 *their_rhash, |
|||
struct signature *their_commit_sig) |
|||
{ |
|||
Signature *sig = NULL; |
|||
struct sha256 old_our_rhash, old_their_rhash, rhash1, rhash2; |
|||
struct channel_state *cstate; |
|||
|
|||
/* Start sanity check. */ |
|||
if (is_funder(o1) == is_funder(o2)) |
|||
errx(1, "Must be exactly one funder"); |
|||
|
|||
cstate = initial_funding(NULL, is_funder(o1), oa->amount, fee); |
|||
if (!cstate) |
|||
errx(1, "Invalid open combination (need to cover fees)"); |
|||
|
|||
/* If they don't want these, use dummy ones. */ |
|||
if (!our_rhash) |
|||
our_rhash = &rhash1; |
|||
|
|||
if (!their_rhash) |
|||
their_rhash = &rhash2; |
|||
|
|||
proto_to_sha256(o1->revocation_hash, our_rhash); |
|||
proto_to_sha256(o2->revocation_hash, their_rhash); |
|||
|
|||
assert(tal_count(cstate->a.htlcs) == 0); |
|||
assert(tal_count(cstate->b.htlcs) == 0); |
|||
|
|||
/* If o2 sent anchor, it contains their commit sig. */ |
|||
if (o2->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR) |
|||
sig = oa->commit_sig; |
|||
|
|||
if (num_updates) |
|||
*num_updates = 0; |
|||
while (*argv) { |
|||
int64_t delta, amount; |
|||
size_t n; |
|||
bool received; |
|||
Pkt *pkt; |
|||
|
|||
/* + marks messages sent by us, - for messages from them */ |
|||
if (strstarts(*argv, "+")) { |
|||
received = false; |
|||
} else if (strstarts(*argv, "-")) { |
|||
received = true; |
|||
} else |
|||
errx(1, "%s does not start with +/-", *argv); |
|||
|
|||
pkt = any_pkt_from_file(*argv + 1); |
|||
switch (pkt->pkt_case) { |
|||
case PKT__PKT_OPEN_COMMIT_SIG: |
|||
if (received) |
|||
sig = pkt->open_commit_sig->sig; |
|||
break; |
|||
case PKT__PKT_UPDATE_ADD_HTLC: |
|||
amount = pkt->update_add_htlc->amount_msat; |
|||
if (received) { |
|||
if (!funding_delta(is_funder(o2), oa->amount, |
|||
0, amount, |
|||
&cstate->b, &cstate->a)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
add_htlc(&cstate->b, pkt->update_add_htlc, |
|||
*argv); |
|||
} else { |
|||
if (!funding_delta(is_funder(o1), oa->amount, |
|||
0, amount, |
|||
&cstate->a, &cstate->b)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
add_htlc(&cstate->a, pkt->update_add_htlc, |
|||
*argv); |
|||
} |
|||
|
|||
update_rhash(pkt->update_add_htlc->revocation_hash, |
|||
received, num_updates, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
|
|||
case PKT__PKT_UPDATE_TIMEDOUT_HTLC: |
|||
if (received) { |
|||
n = find_htlc(&cstate->b, |
|||
pkt->update_timedout_htlc->r_hash); |
|||
if (n == tal_count(cstate->b.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->b.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o2), oa->amount, |
|||
0, -amount, |
|||
&cstate->b, &cstate->a)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->b, n); |
|||
} else { |
|||
n = find_htlc(&cstate->a, |
|||
pkt->update_timedout_htlc->r_hash); |
|||
if (n == tal_count(cstate->a.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->a.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o1), oa->amount, |
|||
0, -amount, |
|||
&cstate->a, &cstate->b)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->a, n); |
|||
} |
|||
update_rhash(pkt->update_timedout_htlc->revocation_hash, |
|||
received, num_updates, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
|
|||
/* HTLC acceptor sends this to initiator. */ |
|||
case PKT__PKT_UPDATE_ROUTEFAIL_HTLC: |
|||
if (received) { |
|||
n = find_htlc(&cstate->a, |
|||
pkt->update_routefail_htlc->r_hash); |
|||
if (n == tal_count(cstate->a.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->a.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o1), oa->amount, |
|||
0, -amount, |
|||
&cstate->a, &cstate->b)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->a, n); |
|||
} else { |
|||
n = find_htlc(&cstate->b, |
|||
pkt->update_routefail_htlc->r_hash); |
|||
if (n == tal_count(cstate->b.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->b.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o2), oa->amount, |
|||
0, -amount, |
|||
&cstate->b, &cstate->a)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->b, n); |
|||
} |
|||
update_rhash(pkt->update_routefail_htlc->revocation_hash, |
|||
received, num_updates, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
|
|||
case PKT__PKT_UPDATE_FULFILL_HTLC: { |
|||
struct sha256 r_hash, r_val; |
|||
Sha256Hash *rh; |
|||
|
|||
/* Get hash, to find the HTLC. */ |
|||
proto_to_sha256(pkt->update_fulfill_htlc->r, &r_val); |
|||
sha256(&r_hash, &r_val, sizeof(r_val)); |
|||
rh = sha256_to_proto(ctx, &r_hash); |
|||
|
|||
if (received) { |
|||
u64 b_before = cstate->b.pay_msat + cstate->b.fee_msat; |
|||
/* HTLC was us->them, funds go to them. */ |
|||
n = find_htlc(&cstate->a, rh); |
|||
if (n == tal_count(cstate->a.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->a.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o1), oa->amount, |
|||
-amount, -amount, |
|||
&cstate->a, &cstate->b)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->a, n); |
|||
assert(cstate->b.pay_msat + cstate->b.fee_msat |
|||
== b_before + amount); |
|||
} else { |
|||
/* HTLC was them->us, funds go to us. */ |
|||
n = find_htlc(&cstate->b, rh); |
|||
if (n == tal_count(cstate->b.htlcs)) |
|||
errx(1, "Unknown R hash in %s", *argv); |
|||
amount = cstate->b.htlcs[n].msatoshis; |
|||
if (!funding_delta(is_funder(o2), oa->amount, |
|||
-amount, -amount, |
|||
&cstate->b, &cstate->a)) |
|||
errx(1, "Impossible htlc %llu %s", |
|||
(long long)amount, *argv); |
|||
remove_htlc(&cstate->b, n); |
|||
} |
|||
update_rhash(pkt->update_fulfill_htlc->revocation_hash, |
|||
received, num_updates, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
} |
|||
|
|||
case PKT__PKT_UPDATE: |
|||
if (received) |
|||
delta = -pkt->update->delta_msat; |
|||
else |
|||
delta = pkt->update->delta_msat; |
|||
if (!funding_delta(is_funder(o1), oa->amount, delta, 0, |
|||
&cstate->a, &cstate->b)) |
|||
errx(1, "Impossible funding update %lli %s", |
|||
(long long)delta, *argv); |
|||
|
|||
update_rhash(pkt->update->revocation_hash, |
|||
received, num_updates, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
case PKT__PKT_UPDATE_ACCEPT: |
|||
if (received) |
|||
sig = pkt->update_accept->sig; |
|||
|
|||
/* Does not increase num_updates */ |
|||
update_rhash(pkt->update_accept->revocation_hash, |
|||
received, NULL, |
|||
&old_our_rhash, &old_their_rhash, |
|||
our_rhash, their_rhash); |
|||
break; |
|||
case PKT__PKT_UPDATE_SIGNATURE: |
|||
if (received) { |
|||
sig = pkt->update_signature->sig; |
|||
check_preimage(pkt->update_signature |
|||
->revocation_preimage, |
|||
&old_their_rhash, their_rhash, |
|||
*argv); |
|||
} else { |
|||
check_preimage(pkt->update_signature |
|||
->revocation_preimage, |
|||
&old_our_rhash, our_rhash, |
|||
*argv); |
|||
} |
|||
break; |
|||
case PKT__PKT_UPDATE_COMPLETE: |
|||
if (received) { |
|||
check_preimage(pkt->update_complete |
|||
->revocation_preimage, |
|||
&old_their_rhash, their_rhash, |
|||
*argv); |
|||
} else { |
|||
check_preimage(pkt->update_complete |
|||
->revocation_preimage, |
|||
&old_our_rhash, our_rhash, |
|||
*argv); |
|||
} |
|||
break; |
|||
default: |
|||
errx(1, "Unexpected packet type %u", pkt->pkt_case); |
|||
} |
|||
argv++; |
|||
} |
|||
|
|||
if (their_commit_sig) { |
|||
if (!sig) |
|||
errx(1, "No commit signature message found"); |
|||
if (!proto_to_signature(sig, their_commit_sig)) |
|||
errx(1, "Invalid signature"); |
|||
} |
|||
|
|||
assert(htlcs_total(cstate->a.htlcs) |
|||
+ cstate->a.pay_msat + cstate->a.fee_msat |
|||
+ htlcs_total(cstate->b.htlcs) |
|||
+ cstate->b.pay_msat + cstate->b.fee_msat |
|||
== oa->amount * 1000); |
|||
|
|||
return cstate; |
|||
} |
@ -1,27 +0,0 @@ |
|||
#ifndef GATHER_UPDATES_H |
|||
#define GATHER_UPDATES_H |
|||
#include <ccan/tal/tal.h> |
|||
#include "lightning.pb-c.h" |
|||
|
|||
struct signature; |
|||
struct sha256; |
|||
struct channel_state; |
|||
|
|||
struct channel_state *gather_updates(const tal_t *ctx, |
|||
const OpenChannel *o1, const OpenChannel *o2, |
|||
const OpenAnchor *oa, uint64_t fee, |
|||
char **argv, |
|||
size_t *num_updates, |
|||
struct sha256 *our_rhash, |
|||
struct sha256 *their_rhash, |
|||
struct signature *their_commit_sig); |
|||
|
|||
/**
|
|||
* is_funder: helper to tell you if this is offering to fund channel. |
|||
* @o: the openchannel packet. |
|||
*/ |
|||
static inline bool is_funder(const OpenChannel *o) |
|||
{ |
|||
return o->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR; |
|||
} |
|||
#endif /* GATHER_UPDATES_H */ |
@ -1,42 +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 "lightning.pb-c.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 "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file>\n" |
|||
"Prints anchor depth as contained in OpenChannel message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 2) |
|||
opt_usage_exit_fail("Expected one argument"); |
|||
|
|||
o = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
printf("%u\n", o->min_depth); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,38 +0,0 @@ |
|||
/* Insecure hack to leak signatures early, to make up for non-normalized txs */ |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/opt/opt.h> |
|||
#include <ccan/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.h" |
|||
#include "pkt.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenAnchorScriptsigs *s; |
|||
struct pkt *pkt; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-anchor-sig-file>\n" |
|||
"Create LeakAnchorSigsAndPretendWeDidnt to stdout", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 2) |
|||
opt_usage_exit_fail("Expected 1 argument"); |
|||
|
|||
s = pkt_from_file(argv[1], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS) |
|||
->open_anchor_scriptsigs; |
|||
|
|||
pkt = leak_anchor_sigs_and_pretend_we_didnt_pkt(ctx, s); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,105 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.h" |
|||
#include "bitcoin/base58.h" |
|||
#include "pkt.h" |
|||
#include "funding.h" |
|||
#include "gather_updates.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 "commit_tx.h" |
|||
#include "protobuf_convert.h" |
|||
#include "find_p2sh_out.h" |
|||
#include <unistd.h> |
|||
#include <time.h> |
|||
#include "opt_bits.h" |
|||
#include "version.h" |
|||
#include "tx_from_file.h" |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct bitcoin_tx *anchor, *commit; |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor oa = OPEN_ANCHOR__INIT; |
|||
struct sha256_double txid; |
|||
struct sha256 rhash; |
|||
struct pkt *pkt; |
|||
struct pubkey pubkey1, pubkey2; |
|||
struct privkey privkey; |
|||
struct signature sig; |
|||
bool testnet; |
|||
u8 *redeemscript; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <anchor-tx-file> <commit-privkey1>\n" |
|||
"A test program to output open_anchor message on stdout.", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 5) |
|||
opt_usage_exit_fail("Expected 4 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(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit_key"); |
|||
|
|||
anchor = bitcoin_tx_from_file(ctx, argv[3]); |
|||
bitcoin_txid(anchor, &txid); |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[4]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[4]); |
|||
|
|||
/* Figure out which output we want for commit tx. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
oa.txid = sha256_to_proto(ctx, &txid.sha); |
|||
oa.output_index = find_p2sh_out(anchor, redeemscript); |
|||
oa.amount = anchor->output[oa.output_index].amount; |
|||
|
|||
/* Figure out initial how much to us, how much to them. */ |
|||
if (is_funder(o1) == is_funder(o2)) |
|||
errx(1, "Must be exactly one funder"); |
|||
|
|||
cstate = initial_funding(ctx, is_funder(o1), oa.amount, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee)); |
|||
if (!cstate) |
|||
errx(1, "Invalid open combination (need to cover fees)"); |
|||
|
|||
/* Now, create signature for their commitment tx. */ |
|||
proto_to_sha256(o2->revocation_hash, &rhash); |
|||
invert_cstate(cstate); |
|||
commit = commit_tx_from_pkts(ctx, o2, o1, &oa, &rhash, cstate); |
|||
|
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig); |
|||
|
|||
oa.commit_sig = signature_to_proto(ctx, &sig); |
|||
pkt = open_anchor_pkt(ctx, &oa); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,100 +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/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" |
|||
#include "version.h" |
|||
|
|||
/* Bitcoin nodes are allowed to be 2 hours in the future. */ |
|||
#define LOCKTIME_MIN (2 * 60 * 60) |
|||
|
|||
/* Simple helper to open a channel. */ |
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
struct sha256 seed, revocation_hash; |
|||
struct pkt *pkt; |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
unsigned int locktime_seconds, min_confirms; |
|||
u64 commit_tx_fee; |
|||
bool offer_anchor = false; |
|||
struct pubkey commitkey, finalkey; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
/* This means we have ~1 day before they can steal our money. */ |
|||
locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60; |
|||
/* Zero, unless they set --offer-anchor or --min-anchor-confirms */ |
|||
min_confirms = 0; |
|||
/* We only need this for involuntary close, so make it larger. */ |
|||
commit_tx_fee = 100000; |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <commitpubkey> <finalpubkey>\n" |
|||
"A test program to output openchannel on stdout.", |
|||
"Print this message."); |
|||
opt_register_arg("--min-anchor-confirms", |
|||
opt_set_uintval, opt_show_uintval, &min_confirms, |
|||
"Number of anchor confirmations before channel is active"); |
|||
opt_register_arg("--locktime=<seconds>", |
|||
opt_set_uintval, opt_show_uintval, &locktime_seconds, |
|||
"Seconds to lock out our transaction redemption"); |
|||
opt_register_noarg("--offer-anchor", |
|||
opt_set_bool, &offer_anchor, |
|||
"Offer to create anchor transaction"); |
|||
opt_register_arg("--commitment-fee=<bits>", |
|||
opt_set_bits, opt_show_bits, &commit_tx_fee, |
|||
"100's of satoshi to pay for commitment"); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 4) |
|||
opt_usage_exit_fail("Expected 3 arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
|
|||
if (!pubkey_from_hexstr(secp256k1_context_create(0), |
|||
argv[2], strlen(argv[2]), &commitkey)) |
|||
errx(1, "Invalid commit key '%s'", argv[2]); |
|||
|
|||
if (!pubkey_from_hexstr(secp256k1_context_create(0), |
|||
argv[3], strlen(argv[3]), &finalkey)) |
|||
errx(1, "Invalid final key '%s'", argv[3]); |
|||
|
|||
if (offer_anchor && min_confirms == 0) |
|||
min_confirms = 3; |
|||
|
|||
/* Get first revocation hash. */ |
|||
shachain_from_seed(&seed, 0, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
pkt = open_channel_pkt(ctx, &revocation_hash, &commitkey, &finalkey, |
|||
locktime_seconds, |
|||
offer_anchor |
|||
? OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR |
|||
: OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR, |
|||
min_confirms, commit_tx_fee); |
|||
|
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,97 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "protobuf_convert.h" |
|||
#include "funding.h" |
|||
#include "gather_updates.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit; |
|||
struct pkt *pkt; |
|||
struct signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct pubkey pubkey1, pubkey2; |
|||
u8 *subscript; |
|||
struct sha256 rhash; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <commit-privkey>\n" |
|||
"Create the signature needed for the commit transaction", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 5) |
|||
opt_usage_exit_fail("Expected 4 arguments"); |
|||
|
|||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1)) |
|||
errx(1, "Invalid private key '%s'", argv[4]); |
|||
if (!testnet) |
|||
errx(1, "Private key '%s' not on testnet!", argv[4]); |
|||
|
|||
if (is_funder(o1) == is_funder(o2)) |
|||
errx(1, "Must be exactly one funder"); |
|||
|
|||
/* Now create THEIR commitment tx to spend 2/2 output of anchor. */ |
|||
cstate = initial_funding(ctx, is_funder(o2), a->amount, |
|||
commit_fee(o2->commitment_fee, |
|||
o1->commitment_fee)); |
|||
if (!cstate) |
|||
errx(1, "Invalid open combination (too low for fees)"); |
|||
|
|||
proto_to_sha256(o2->revocation_hash, &rhash); |
|||
commit = commit_tx_from_pkts(ctx, o2, o1, a, &rhash, cstate); |
|||
|
|||
/* If contributions don't exceed fees, this fails. */ |
|||
if (!commit) |
|||
errx(1, "Invalid packets?"); |
|||
|
|||
/* Their pubkey must be valid */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid public open-channel-file2"); |
|||
|
|||
/* Sign it for them. */ |
|||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
commit, 0, subscript, tal_count(subscript), |
|||
&privkey, &pubkey1, &sig); |
|||
|
|||
pkt = open_commit_sig_pkt(ctx, &sig); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,255 +0,0 @@ |
|||
#include "bitcoin/address.h" |
|||
#include "bitcoin/locktime.h" |
|||
#include "bitcoin/pubkey.h" |
|||
#include "bitcoin/signature.h" |
|||
#include "bitcoin/tx.h" |
|||
#include "commit_tx.h" |
|||
#include "pkt.h" |
|||
#include "protobuf_convert.h" |
|||
#include <ccan/crypto/sha256/sha256.h> |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/tal/grab_file/grab_file.h> |
|||
|
|||
size_t pkt_totlen(const struct pkt *pkt) |
|||
{ |
|||
return sizeof(pkt->len) + pkt->len; |
|||
} |
|||
|
|||
static struct pkt *to_pkt(const tal_t *ctx, Pkt__PktCase type, const void *msg) |
|||
{ |
|||
struct pkt *ret; |
|||
size_t len; |
|||
Pkt p = PKT__INIT; |
|||
|
|||
p.pkt_case = type; |
|||
/* This is a union, so doesn't matter which we assign. */ |
|||
p.error = (Error *)msg; |
|||
|
|||
len = pkt__get_packed_size(&p); |
|||
ret = (struct pkt *)tal_arr(ctx, u8, sizeof(ret->len) + len); |
|||
ret->len = len; |
|||
|
|||
pkt__pack(&p, ret->data); |
|||
return ret; |
|||
} |
|||
|
|||
struct pkt *open_channel_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct pubkey *commit, |
|||
const struct pubkey *final, |
|||
u32 rel_locktime_seconds, |
|||
OpenChannel__AnchorOffer offer_anchor, |
|||
u32 min_depth, |
|||
u64 commitment_fee) |
|||
{ |
|||
OpenChannel o = OPEN_CHANNEL__INIT; |
|||
Locktime lt = LOCKTIME__INIT; |
|||
|
|||
o.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
o.commit_key = pubkey_to_proto(ctx, commit); |
|||
o.final_key = pubkey_to_proto(ctx, final); |
|||
lt.locktime_case = LOCKTIME__LOCKTIME_SECONDS; |
|||
lt.seconds = rel_locktime_seconds; |
|||
o.delay = < |
|||
o.commitment_fee = commitment_fee; |
|||
o.anch = offer_anchor; |
|||
assert(o.anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR |
|||
|| o.anch == OPEN_CHANNEL__ANCHOR_OFFER__WONT_CREATE_ANCHOR); |
|||
|
|||
o.min_depth = min_depth; |
|||
|
|||
{ |
|||
size_t len = open_channel__get_packed_size(&o); |
|||
unsigned char *pb = malloc(len); |
|||
open_channel__pack(&o, pb); |
|||
assert(open_channel__unpack(NULL, len, pb)); |
|||
free(pb); |
|||
} |
|||
|
|||
return to_pkt(ctx, PKT__PKT_OPEN, &o); |
|||
} |
|||
|
|||
struct pkt *open_anchor_pkt(const tal_t *ctx, const OpenAnchor *oa_msg) |
|||
{ |
|||
return to_pkt(ctx, PKT__PKT_OPEN_ANCHOR, oa_msg); |
|||
} |
|||
|
|||
Pkt *any_pkt_from_file(const char *filename) |
|||
{ |
|||
struct pkt *pkt; |
|||
Pkt *ret; |
|||
size_t len; |
|||
|
|||
pkt = grab_file(NULL, filename); |
|||
if (!pkt) |
|||
err(1, "Opening %s", filename); |
|||
|
|||
len = tal_count(pkt) - 1; |
|||
if (len < sizeof(pkt->len) || len != sizeof(pkt->len) + pkt->len) |
|||
errx(1, "%s length is wrong", filename); |
|||
len -= sizeof(pkt->len); |
|||
|
|||
ret = pkt__unpack(NULL, len, pkt->data); |
|||
if (!ret) |
|||
errx(1, "Unpack failed for %s", filename); |
|||
return ret; |
|||
} |
|||
|
|||
Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect) |
|||
{ |
|||
Pkt *ret = any_pkt_from_file(filename); |
|||
|
|||
if (ret->pkt_case != expect) |
|||
errx(1, "Unexpected type %i in %s", ret->pkt_case, filename); |
|||
return ret; |
|||
} |
|||
|
|||
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig) |
|||
{ |
|||
OpenCommitSig o = OPEN_COMMIT_SIG__INIT; |
|||
|
|||
o.sig = signature_to_proto(ctx, sig); |
|||
return to_pkt(ctx, PKT__PKT_OPEN_COMMIT_SIG, &o); |
|||
} |
|||
|
|||
struct pkt *close_channel_pkt(const tal_t *ctx, |
|||
uint64_t fee, |
|||
const struct signature *sig) |
|||
{ |
|||
CloseChannel c = CLOSE_CHANNEL__INIT; |
|||
c.close_fee = fee; |
|||
c.sig = signature_to_proto(ctx, sig); |
|||
return to_pkt(ctx, PKT__PKT_CLOSE, &c); |
|||
} |
|||
|
|||
struct pkt *close_channel_complete_pkt(const tal_t *ctx, |
|||
const struct signature *sig) |
|||
{ |
|||
CloseChannelComplete c = CLOSE_CHANNEL_COMPLETE__INIT; |
|||
c.sig = signature_to_proto(ctx, sig); |
|||
return to_pkt(ctx, PKT__PKT_CLOSE_COMPLETE, &c); |
|||
} |
|||
|
|||
struct pkt *update_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
s64 delta) |
|||
{ |
|||
Update u = UPDATE__INIT; |
|||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
u.delta_msat = delta * 1000; |
|||
return to_pkt(ctx, PKT__PKT_UPDATE, &u); |
|||
} |
|||
|
|||
struct pkt *update_htlc_add_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
u32 value, |
|||
const struct sha256 *htlc_rhash, |
|||
u32 abs_locktime_seconds) |
|||
{ |
|||
UpdateAddHtlc u = UPDATE_ADD_HTLC__INIT; |
|||
Locktime l = LOCKTIME__INIT; |
|||
|
|||
/* HTLC total must fit in 32 bits. */ |
|||
if (value > (1ULL << 32) / 1000) |
|||
return NULL; |
|||
|
|||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
u.amount_msat = value * 1000; |
|||
u.r_hash = sha256_to_proto(ctx, htlc_rhash); |
|||
l.locktime_case = LOCKTIME__LOCKTIME_SECONDS; |
|||
l.seconds = abs_locktime_seconds; |
|||
u.expiry = &l; |
|||
|
|||
return to_pkt(ctx, PKT__PKT_UPDATE_ADD_HTLC, &u); |
|||
} |
|||
|
|||
struct pkt *update_htlc_complete_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *rval) |
|||
{ |
|||
UpdateFulfillHtlc u = UPDATE_FULFILL_HTLC__INIT; |
|||
|
|||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
u.r = sha256_to_proto(ctx, rval); |
|||
|
|||
return to_pkt(ctx, PKT__PKT_UPDATE_FULFILL_HTLC, &u); |
|||
} |
|||
|
|||
struct pkt *update_htlc_timedout_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *htlc_rhash) |
|||
{ |
|||
UpdateTimedoutHtlc u = UPDATE_TIMEDOUT_HTLC__INIT; |
|||
|
|||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
u.r_hash = sha256_to_proto(ctx, htlc_rhash); |
|||
|
|||
return to_pkt(ctx, PKT__PKT_UPDATE_TIMEDOUT_HTLC, &u); |
|||
} |
|||
|
|||
struct pkt *update_htlc_routefail_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *htlc_rhash) |
|||
{ |
|||
UpdateRoutefailHtlc u = UPDATE_ROUTEFAIL_HTLC__INIT; |
|||
|
|||
u.revocation_hash = sha256_to_proto(ctx, revocation_hash); |
|||
u.r_hash = sha256_to_proto(ctx, htlc_rhash); |
|||
|
|||
return to_pkt(ctx, PKT__PKT_UPDATE_ROUTEFAIL_HTLC, &u); |
|||
} |
|||
|
|||
struct pkt *update_accept_pkt(const tal_t *ctx, |
|||
struct signature *sig, |
|||
const struct sha256 *revocation_hash) |
|||
{ |
|||
UpdateAccept ua = UPDATE_ACCEPT__INIT; |
|||
ua.sig = signature_to_proto(ctx, sig); |
|||
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 sha256 *revocation_preimage) |
|||
{ |
|||
UpdateSignature us = UPDATE_SIGNATURE__INIT; |
|||
us.sig = signature_to_proto(ctx, sig); |
|||
us.revocation_preimage = sha256_to_proto(ctx, revocation_preimage); |
|||
return to_pkt(ctx, PKT__PKT_UPDATE_SIGNATURE, &us); |
|||
} |
|||
|
|||
struct pkt *update_complete_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_preimage) |
|||
{ |
|||
UpdateComplete uc = UPDATE_COMPLETE__INIT; |
|||
uc.revocation_preimage = sha256_to_proto(ctx, revocation_preimage); |
|||
return to_pkt(ctx, PKT__PKT_UPDATE_COMPLETE, &uc); |
|||
} |
|||
|
|||
struct bitcoin_tx *commit_tx_from_pkts(const tal_t *ctx, |
|||
OpenChannel *ours, |
|||
OpenChannel *theirs, |
|||
OpenAnchor *anchor, |
|||
const struct sha256 *rhash, |
|||
const struct channel_state *cstate) |
|||
{ |
|||
struct pubkey ourkey, theirkey; |
|||
struct sha256_double txid; |
|||
struct rel_locktime locktime; |
|||
|
|||
proto_to_sha256(anchor->txid, &txid.sha); |
|||
/* Output goes to our final pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
ours->final_key, &ourkey)) |
|||
return NULL; |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
theirs->final_key, &theirkey)) |
|||
return NULL; |
|||
if (!proto_to_rel_locktime(theirs->delay, &locktime)) |
|||
return NULL; |
|||
|
|||
return create_commit_tx(ctx, &ourkey, &theirkey, &locktime, |
|||
&txid, anchor->output_index, anchor->amount, |
|||
rhash, cstate); |
|||
} |
@ -1,174 +0,0 @@ |
|||
#ifndef LIGHTNING_PKT_H |
|||
#define LIGHTNING_PKT_H |
|||
#include "config.h" |
|||
|
|||
/* Simple (non-threadsafe!) wrapper for protobufs.
|
|||
* |
|||
* This could be a simple set of macros, if the protobuf-c people hadn't |
|||
* insisted on "prettifing" the names they generate into CamelCase. |
|||
*/ |
|||
#include "lightning.pb-c.h" |
|||
#include <ccan/short_types/short_types.h> |
|||
#include <ccan/tal/tal.h> |
|||
|
|||
/* A packet, ready to be de-protobuf'ed. */ |
|||
struct pkt { |
|||
u32 len; |
|||
u8 data[]; |
|||
}; |
|||
|
|||
/* Utility helper: dies if there's a problem. */ |
|||
Pkt *pkt_from_file(const char *filename, Pkt__PktCase expect); |
|||
Pkt *any_pkt_from_file(const char *filename); |
|||
|
|||
/* Total length of packet, including header. */ |
|||
size_t pkt_totlen(const struct pkt *pkt); |
|||
|
|||
struct sha256; |
|||
struct bitcoin_compressed_pubkey; |
|||
struct signature; |
|||
struct pubkey; |
|||
|
|||
/**
|
|||
* open_channel_pkt - create an openchannel message |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: first hash value generated from seed. |
|||
* @commit: the pubkey for the anchor transactions' P2SH output. |
|||
* @final: the pubkey for the commit transactions' P2SH output. |
|||
* @rel_locktime_seconds: relative seconds for commitment locktime. |
|||
* @offer_anchor: whether we will offer anchor. |
|||
* @min_depth: minimum depth to insist on (if non-zero) |
|||
* @commitment_fee: fee we would like for commitment txs. |
|||
*/ |
|||
struct pkt *open_channel_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct pubkey *commit, |
|||
const struct pubkey *final, |
|||
u32 rel_locktime_seconds, |
|||
OpenChannel__AnchorOffer offer_anchor, |
|||
u32 min_depth, |
|||
u64 commitment_fee); |
|||
|
|||
/**
|
|||
* open_anchor_pkt - create an open_anchor message packet |
|||
* @ctx: tal context to allocate off. |
|||
* @oa_msg: the OpenAnchor message. |
|||
*/ |
|||
struct pkt *open_anchor_pkt(const tal_t *ctx, const OpenAnchor *oa_msg); |
|||
|
|||
/**
|
|||
* open_commit_sig_pkt - create an open_commit_sig message |
|||
* @ctx: tal context to allocate off. |
|||
* @sig: the signature for the commit transaction input. |
|||
*/ |
|||
struct pkt *open_commit_sig_pkt(const tal_t *ctx, const struct signature *sig); |
|||
|
|||
/**
|
|||
* close_channel_pkt - create an close_channel message |
|||
* @ctx: tal context to allocate off. |
|||
* @fee: the fee for the transaction. |
|||
* @sig: the signature for the close transaction input. |
|||
*/ |
|||
struct pkt *close_channel_pkt(const tal_t *ctx, |
|||
uint64_t fee, |
|||
const struct signature *sig); |
|||
|
|||
/**
|
|||
* close_channel_complete_pkt - create an close_channel_complete message |
|||
* @ctx: tal context to allocate off. |
|||
* @sig: the signature for the close transaction input. |
|||
*/ |
|||
struct pkt *close_channel_complete_pkt(const tal_t *ctx, |
|||
const struct signature *sig); |
|||
|
|||
/**
|
|||
* update_pkt - create an update message |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: the revocation hash for the next tx. |
|||
* @delta: the change in satoshis (to me). |
|||
*/ |
|||
struct pkt *update_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
s64 delta); |
|||
|
|||
/**
|
|||
* update_htlc_add_pkt - create an update message adding a HTLC |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: the revocation hash for the next commitment tx. |
|||
* @val: the change in satoshis (from me). |
|||
* @htlc_rhash: the hash of the htlc secret. |
|||
* @abs_locktime_seconds: the HTLC timeout. |
|||
*/ |
|||
struct pkt *update_htlc_add_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
u32 value, |
|||
const struct sha256 *htlc_rhash, |
|||
u32 abs_locktime_seconds); |
|||
|
|||
/**
|
|||
* update_htlc_complete_pkt - create an update message completing a HTLC |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: the revocation hash for the next commitment tx. |
|||
* @rval: the r value for the HTLC |
|||
*/ |
|||
struct pkt *update_htlc_complete_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *rval); |
|||
|
|||
/**
|
|||
* update_htlc_timedout_pkt - create an update message removing a HTLC |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: the revocation hash for the next commitment tx. |
|||
* @htlc_rhash: the hash of the htlc secret. |
|||
*/ |
|||
struct pkt *update_htlc_timedout_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *htlc_rhash); |
|||
|
|||
/**
|
|||
* update_htlc_routefail_pkt - create an update message removing a HTLC |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_hash: the revocation hash for the next commitment tx. |
|||
* @htlc_rhash: the hash of the htlc secret. |
|||
*/ |
|||
struct pkt *update_htlc_routefail_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_hash, |
|||
const struct sha256 *htlc_rhash); |
|||
|
|||
/**
|
|||
* update_accept_pkt - create an update_accept message |
|||
* @ctx: tal context to allocate off. |
|||
* @sig: the signature for the close transaction input. |
|||
* @revocation_hash: hash to revoke the next tx. |
|||
*/ |
|||
struct pkt *update_accept_pkt(const tal_t *ctx, |
|||
struct signature *sig, |
|||
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. |
|||
* @revocation_preimage: preimage to revoke existing (now-obsolete) tx. |
|||
*/ |
|||
struct pkt *update_signature_pkt(const tal_t *ctx, |
|||
const struct signature *sig, |
|||
const struct sha256 *revocation_preimage); |
|||
/**
|
|||
* update_complete_pkt - create an update_accept message |
|||
* @ctx: tal context to allocate off. |
|||
* @revocation_preimage: preimage to revoke existing (now-obsolete) tx. |
|||
*/ |
|||
struct pkt *update_complete_pkt(const tal_t *ctx, |
|||
const struct sha256 *revocation_preimage); |
|||
|
|||
struct channel_state; |
|||
|
|||
struct bitcoin_tx *commit_tx_from_pkts(const tal_t *ctx, |
|||
OpenChannel *ours, |
|||
OpenChannel *theirs, |
|||
OpenAnchor *anchor, |
|||
const struct sha256 *rhash, |
|||
const struct channel_state *cstate); |
|||
|
|||
#endif /* LIGHTNING_PKT_H */ |
@ -1,317 +0,0 @@ |
|||
#! /bin/sh |
|||
set -e |
|||
|
|||
# Expect to be run from test-cli dir. |
|||
. scripts/vars.sh |
|||
|
|||
# How long to lock transactions |
|||
# CSV only supports 512-second granularity, so that's the minimum. |
|||
TEST_LOCKTIME=512 |
|||
|
|||
getpubkey() |
|||
{ |
|||
$CLI validateaddress $1 | sed -n 's/.*"pubkey" *: "\([0-9a-f]*\)".*/\1/p' |
|||
} |
|||
|
|||
getprivkey() |
|||
{ |
|||
$CLI dumpprivkey $1 |
|||
} |
|||
|
|||
send_after_delay() |
|||
{ |
|||
# Confirm them. |
|||
scripts/generate-block.sh |
|||
|
|||
# For bitcoin testing, OP_CHECKSEQUENCEVERIFY is a NOP. |
|||
# But nSequence enforcement is enough to stop it. |
|||
if [ $SEQ_ENFORCEMENT = true ]; then |
|||
# OP_CHECKSEQUENCEVERIFY will stop us spending for $TEST_LOCKTIME seconds. |
|||
for tx; do |
|||
if $CLI sendrawtransaction $tx 2> /dev/null; then |
|||
echo OP_CHECKSEQUENCEVERIFY broken for $tx! >&2 |
|||
exit 1 |
|||
fi |
|||
done |
|||
fi |
|||
|
|||
# Bitcoin still respects lock_time, which is used for HTLCs. |
|||
|
|||
# Bitcoin bumps block times so that blocks are valid. |
|||
TIME=$($CLI getblock $($CLI getbestblockhash) | sed -n 's/.*"time" *: *\([0-9]*\),/\1/p') |
|||
$CLI setmocktime $(($TIME + $TEST_LOCKTIME)) |
|||
|
|||
# Move median time, for sure! |
|||
for i in `seq 6`; do scripts/generate-block.sh; done |
|||
|
|||
for tx; do |
|||
$CLI sendrawtransaction $tx |
|||
done |
|||
} |
|||
|
|||
if [ x$1 != x ] && [ x$1 != x--steal ] && [ x$1 != x--unilateral ] && [ x$1 != x--htlc-onchain ]; then |
|||
echo Usage: "[--steal|--unilateral|--htlc-onchain]" >&2 |
|||
exit 1 |
|||
fi |
|||
|
|||
# Find the inputs number corresponding to that 0.01 btc out |
|||
for i in $(seq 1 $($CLI listunspent | grep -c txid) ); do |
|||
if scripts/getinput.sh $i | grep -q "$TX.*/1000000/"; then |
|||
A_INPUTNUM=$i; |
|||
fi |
|||
done |
|||
|
|||
if [ -z "$A_INPUTNUM" ]; then |
|||
echo "Can't find 1000000 satoshi input" >&2 |
|||
exit 1 |
|||
fi |
|||
|
|||
A_AMOUNT=900000 |
|||
|
|||
A_CHANGEADDR=`scripts/get-new-address.sh` |
|||
A_TMPADDR=`scripts/get-new-address.sh` |
|||
A_FINALADDR=`scripts/get-new-address.sh` |
|||
|
|||
B_CHANGEADDR=`scripts/get-new-address.sh` |
|||
B_TMPADDR=`scripts/get-new-address.sh` |
|||
B_FINALADDR=`scripts/get-new-address.sh` |
|||
|
|||
#A_CHANGEADDR=mzJseRSpUnmUDRJkp9Jp3XRmLKRrFk8KEF |
|||
#A_TMPADDR=mxAucVQU1WWRcMd9ubx1gisteFuy5MgSVh |
|||
#A_FINALADDR=mgjMAVHe8Kgx38SY3apjHdLwz2deJ2ZY2H |
|||
|
|||
#B_CHANGEADDR=mmCiKXHPWunBMFhqZx7fg1v23HssJJesLV |
|||
#B_TMPADDR=mvY4WDonPXq3Xa3NL4uSG26PXKRuLsXGTT |
|||
#B_FINALADDR=mvQgfEX4iMSEYqD31524jASQviPwPwpvuv |
|||
|
|||
A_TXIN=`scripts/getinput.sh $A_INPUTNUM` |
|||
|
|||
A_SEED=00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff |
|||
B_SEED=112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 |
|||
|
|||
A_HTLC1=deadbeefbadc0ffeedeadbeefbadc0ffeedeadbeefbadc0ffeedeadbeefbadc0 |
|||
A_CHANGEPUBKEY=`getpubkey $A_CHANGEADDR` |
|||
A_TMPKEY=`getprivkey $A_TMPADDR` |
|||
A_TMPPUBKEY=`getpubkey $A_TMPADDR` |
|||
A_FINALKEY=`getprivkey $A_FINALADDR` |
|||
A_FINALPUBKEY=`getpubkey $A_FINALADDR` |
|||
|
|||
B_HTLC1=badc0de5badc0de5badc0de5badc0de5badc0de5badc0de5badc0de5badc0de5 |
|||
B_CHANGEPUBKEY=`getpubkey $B_CHANGEADDR` |
|||
B_TMPKEY=`getprivkey $B_TMPADDR` |
|||
B_TMPPUBKEY=`getpubkey $B_TMPADDR` |
|||
B_FINALKEY=`getprivkey $B_FINALADDR` |
|||
B_FINALPUBKEY=`getpubkey $B_FINALADDR` |
|||
|
|||
# Both sides say what they want from channel (A offers anchor) |
|||
$PREFIX ./open-channel --offer-anchor $A_SEED $A_TMPPUBKEY $A_FINALPUBKEY > A-open.pb |
|||
# B asks for a (dangerously) short locktime, for testing unilateral close. |
|||
$PREFIX ./open-channel --locktime=$TEST_LOCKTIME $B_SEED $B_TMPPUBKEY $B_FINALPUBKEY > B-open.pb |
|||
|
|||
# Now A creates anchor (does not broadcast!) |
|||
$PREFIX ./create-anchor-tx A-open.pb B-open.pb $A_AMOUNT $A_CHANGEPUBKEY $A_TXIN > A-anchor.tx |
|||
|
|||
# Now A sends info about anchor output, and signature for commit tx. |
|||
$PREFIX ./open-anchor A-open.pb B-open.pb A-anchor.tx $A_TMPKEY > A-anchor.pb |
|||
|
|||
# Now B signs commit sig for anchor. |
|||
$PREFIX ./open-commit-sig B-open.pb A-open.pb A-anchor.pb $B_TMPKEY > B-commit-sig.pb |
|||
|
|||
# Now check sigs. |
|||
$PREFIX ./check-commit-sig A-open.pb B-open.pb A-anchor.pb $A_TMPKEY B-commit-sig.pb |
|||
$PREFIX ./check-commit-sig B-open.pb A-open.pb A-anchor.pb $B_TMPKEY |
|||
|
|||
# A broadcasts anchor |
|||
$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid |
|||
|
|||
# Wait for confirms |
|||
while [ 0$($CLI getrawtransaction $(cat A-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 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 |
|||
|
|||
# Update traffic sent so far. |
|||
A_UPDATE_PKTS="-- -B-commit-sig.pb" |
|||
B_UPDATE_PKTS="-- +B-commit-sig.pb" |
|||
|
|||
# Just for testing, generate the first commit transactions. |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-0.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-0.tx |
|||
|
|||
# Now, update the channel, so I pay you 80000 satoshi (covers 50000 fee) |
|||
$PREFIX ./update-channel --to-them=80000 $A_SEED 1 > A-update-1.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-1.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-1.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-accept-1.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-accept-1.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-accept-1.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-sig-1.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-sig-1.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-sig-1.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $B_SEED B-open.pb A-open.pb A-anchor.pb $B_UPDATE_PKTS > B-update-complete-1.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-complete-1.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-complete-1.pb" |
|||
|
|||
# Just for testing, generate second transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-1.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-1.tx |
|||
|
|||
# Now you pay me 5000. |
|||
$PREFIX ./update-channel --to-them=5000 $B_SEED 2 > B-update-2.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-2.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-2.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-accept-2.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-accept-2.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-accept-2.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-sig-2.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-sig-2.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-sig-2.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $A_SEED A-open.pb B-open.pb A-anchor.pb $A_UPDATE_PKTS > A-update-complete-2.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-complete-2.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-complete-2.pb" |
|||
|
|||
# Just for testing, generate third transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-2.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-2.tx |
|||
|
|||
# Now, A offers an HTLC for 10001 satoshi. |
|||
$PREFIX ./update-channel-htlc $A_SEED 3 10001 $A_HTLC1 $((`date +%s` + $TEST_LOCKTIME)) > A-update-htlc-3.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-htlc-3.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-htlc-3.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-accept-3.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-accept-3.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-accept-3.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-sig-3.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-sig-3.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-sig-3.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $B_SEED B-open.pb A-open.pb A-anchor.pb $B_UPDATE_PKTS > B-update-complete-3.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-complete-3.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-complete-3.pb" |
|||
|
|||
# Just for testing, generate that transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-3.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-3.tx |
|||
|
|||
# Now, B offers an HTLC for 10002 satoshi. |
|||
$PREFIX ./update-channel-htlc $B_SEED 4 10002 $B_HTLC1 $((`date +%s` + $TEST_LOCKTIME)) > B-update-htlc-4.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-htlc-4.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-htlc-4.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-accept-4.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-accept-4.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-accept-4.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-sig-4.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-sig-4.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-sig-4.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $A_SEED A-open.pb B-open.pb A-anchor.pb $A_UPDATE_PKTS > A-update-complete-4.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-complete-4.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-complete-4.pb" |
|||
|
|||
# Just for testing, generate that transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-4.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-4.tx |
|||
|
|||
# Solve the HTLCs with the R value on the chain. |
|||
if [ x"$1" = x--htlc-onchain ]; then |
|||
$CLI sendrawtransaction `cut -d: -f1 A-commit-4.tx` > A-commit-4.txid |
|||
|
|||
# Now, B can claim A's HTLC using R value. |
|||
# It's A's commit tx, so most of cmdline is written from A's POV. |
|||
$PREFIX ./create-htlc-spend-tx --rvalue=$A_HTLC1 -- A-open.pb B-open.pb A-commit-4.tx +A-update-htlc-3.pb A-update-accept-4.pb $B_FINALKEY $B_CHANGEPUBKEY > B-htlc-3-spend.tx |
|||
$CLI sendrawtransaction `cut -d: -f1 B-htlc-3-spend.tx` > B-htlc-3-spend.txid |
|||
|
|||
# A can claim using B's HTLC using R value, after delay. |
|||
$PREFIX ./create-htlc-spend-tx --rvalue=$B_HTLC1 -- A-open.pb B-open.pb A-commit-4.tx -B-update-htlc-4.pb A-update-accept-4.pb $A_FINALKEY $A_CHANGEPUBKEY > A-htlc-4-spend.tx |
|||
send_after_delay `cut -d: -f1 A-htlc-4-spend.tx` > A-htlc-4-spend.txid |
|||
exit 0 |
|||
fi |
|||
|
|||
if [ x"$1" = x--unilateral ]; then |
|||
# Use commit-4, which has htlcs. |
|||
$CLI sendrawtransaction `cut -d: -f1 A-commit-4.tx` > A-commit-4.txid |
|||
$PREFIX ./create-commit-spend-tx A-commit-4.tx A-open.pb B-open.pb A-anchor.pb $A_FINALKEY $A_CHANGEPUBKEY $A_UPDATE_PKTS > A-spend.tx |
|||
$PREFIX ./create-htlc-spend-tx A-open.pb B-open.pb A-commit-4.tx +A-update-htlc-3.pb A-update-accept-4.pb $A_FINALKEY $A_CHANGEPUBKEY > A-htlc-3-spend.tx |
|||
$PREFIX ./create-htlc-spend-tx -- A-open.pb B-open.pb A-commit-4.tx -B-update-htlc-4.pb A-update-accept-4.pb $B_FINALKEY $B_CHANGEPUBKEY > B-htlc-4-spend.tx |
|||
# HTLCs conveniently set to $TEST_LOCKTIME seconds, though absolute. Script |
|||
# shouldn't be that slow, so they should be unspendable to start. |
|||
send_after_delay `cut -d: -f1 A-spend.tx` `cut -d: -f1 A-htlc-3-spend.tx` `cut -d: -f1 B-htlc-4-spend.tx` > A-spend.txids |
|||
exit 0 |
|||
fi |
|||
|
|||
# B completes A's HTLC using R value. |
|||
$PREFIX ./update-channel-htlc-complete $B_SEED 5 $A_HTLC1 > B-update-htlc-complete-5.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-htlc-complete-5.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-htlc-complete-5.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-accept-5.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-accept-5.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-accept-5.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-sig-5.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-sig-5.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-sig-5.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $A_SEED A-open.pb B-open.pb A-anchor.pb $A_UPDATE_PKTS > A-update-complete-5.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-complete-5.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-complete-5.pb" |
|||
|
|||
# Just for testing, generate that transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-5.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-5.tx |
|||
|
|||
# Now, B tries to remove its HTLC (A accepts) |
|||
$PREFIX ./update-channel-htlc-remove $B_SEED 6 B-update-htlc-4.pb > B-update-htlc-remove-6.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-htlc-remove-6.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-htlc-remove-6.pb" |
|||
|
|||
$PREFIX ./update-channel-accept $A_SEED A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-update-accept-6.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-accept-6.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-accept-6.pb" |
|||
|
|||
$PREFIX ./update-channel-signature $B_SEED B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-update-sig-6.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS -B-update-sig-6.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS +B-update-sig-6.pb" |
|||
|
|||
$PREFIX ./update-channel-complete $A_SEED A-open.pb B-open.pb A-anchor.pb $A_UPDATE_PKTS > A-update-complete-6.pb |
|||
A_UPDATE_PKTS="$A_UPDATE_PKTS +A-update-complete-6.pb" |
|||
B_UPDATE_PKTS="$B_UPDATE_PKTS -A-update-complete-6.pb" |
|||
|
|||
# Just for testing, generate that transaction |
|||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-commit-6.tx |
|||
$PREFIX ./create-commit-tx B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-commit-6.tx |
|||
|
|||
if [ x"$1" = x--steal ]; then |
|||
# A stupidly broadcasts a revoked transaction. |
|||
$CLI sendrawtransaction `cut -d: -f1 A-commit-4.tx` > A-commit-4.txid |
|||
|
|||
# B uses the preimage from A-update-complete-5 to cash in. |
|||
$PREFIX ./create-steal-tx A-commit-4.tx A-update-complete-5.pb $B_FINALKEY B-open.pb A-open.pb $B_CHANGEPUBKEY > B-commit-steal.tx |
|||
|
|||
$CLI sendrawtransaction `cut -d: -f1 B-commit-steal.tx` > B-commit-steal.txid |
|||
|
|||
# Now B uses the same preimage to get the HTLC amounts too. |
|||
# It's A's commit tx, so most of cmdline is written from A's POV. |
|||
$PREFIX ./create-htlc-spend-tx --commit-preimage=A-update-complete-5.pb -- A-open.pb B-open.pb A-commit-4.tx +A-update-htlc-3.pb A-update-accept-4.pb $B_FINALKEY $B_CHANGEPUBKEY > B-htlc-steal-1.tx |
|||
$CLI sendrawtransaction `cut -d: -f1 B-htlc-steal-1.tx` > B-htlc-steal-1.txid |
|||
|
|||
$PREFIX ./create-htlc-spend-tx --commit-preimage=A-update-complete-5.pb -- A-open.pb B-open.pb A-commit-4.tx -B-update-htlc-4.pb A-update-accept-4.pb $B_FINALKEY $B_CHANGEPUBKEY > B-htlc-steal-2.tx |
|||
$CLI sendrawtransaction `cut -d: -f1 B-htlc-steal-2.tx` > B-htlc-steal-2.txid |
|||
exit 0 |
|||
fi |
|||
|
|||
# Now close channel by mutual consent. |
|||
$PREFIX ./close-channel A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-close.pb |
|||
$PREFIX ./close-channel --complete=A-close.pb B-open.pb A-open.pb A-anchor.pb $B_TMPKEY $B_UPDATE_PKTS > B-close-complete.pb |
|||
$PREFIX ./create-close-tx A-open.pb B-open.pb A-anchor.pb A-close.pb B-close-complete.pb $A_UPDATE_PKTS > A-close.tx |
|||
|
|||
$CLI sendrawtransaction `cut -d: -f1 A-close.tx` > close.txid |
@ -1,21 +0,0 @@ |
|||
#include "tx_from_file.h" |
|||
#include "bitcoin/tx.h" |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/tal/grab_file/grab_file.h> |
|||
|
|||
struct bitcoin_tx *bitcoin_tx_from_file(const tal_t *ctx, const char *filename) |
|||
{ |
|||
char *hex; |
|||
struct bitcoin_tx *tx; |
|||
|
|||
/* Grabs file, add nul at end. */ |
|||
hex = grab_file(ctx, filename); |
|||
if (!hex) |
|||
err(1, "Opening %s", filename); |
|||
|
|||
tx = bitcoin_tx_from_hex(ctx, hex, strlen(hex)); |
|||
if (!tx) |
|||
err(1, "Failed to decode tx '%s'", hex); |
|||
tal_free(hex); |
|||
return tx; |
|||
} |
@ -1,7 +0,0 @@ |
|||
#ifndef LIGHTNING_TEST_CLI_TX_FROM_FILE_H |
|||
#define LIGHTNING_TEST_CLI_TX_FROM_FILE_H |
|||
#include "config.h" |
|||
#include "bitcoin/tx.h" |
|||
|
|||
struct bitcoin_tx *bitcoin_tx_from_file(const tal_t *ctx, const char *filename); |
|||
#endif /* LIGHTNING_TEST_CLI_TX_FROM_FILE_H */ |
@ -1,46 +0,0 @@ |
|||
#include <ccan/crypto/shachain/shachain.h> |
|||
#include <ccan/read_write_all/read_write_all.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 "bitcoin/tx.h" |
|||
#include "version.h" |
|||
#include "tx_from_file.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct bitcoin_tx *tx; |
|||
struct sha256_double txid; |
|||
char str[hex_str_size(sizeof(txid))]; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
/* FIXME: Take update.pbs to adjust channel */ |
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<tx>\n" |
|||
"Print txid of the transaction in the file", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 2) |
|||
opt_usage_exit_fail("Expected 1 argument"); |
|||
|
|||
tx = bitcoin_tx_from_file(ctx, argv[1]); |
|||
bitcoin_txid(tx, &txid); |
|||
|
|||
if (!bitcoin_txid_to_hex(&txid, str, sizeof(str))) |
|||
abort(); |
|||
|
|||
/* Print it out. */ |
|||
if (!write_all(STDOUT_FILENO, str, strlen(str))) |
|||
err(1, "Writing out txid"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
@ -1,112 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, revocation_hash, their_rhash; |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit; |
|||
struct pkt *pkt; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
size_t num_updates; |
|||
struct pubkey pubkey1, pubkey2; |
|||
u8 *redeemscript; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-updates...>\n" |
|||
"Accept a new update message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 7) |
|||
opt_usage_exit_fail("Expected 6+ arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
|
|||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
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[5]); |
|||
|
|||
/* Figure out cumulative delta since anchor. */ |
|||
cstate = gather_updates(ctx, o1, o2, a, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee), |
|||
argv + 6, |
|||
&num_updates, NULL, &their_rhash, NULL); |
|||
|
|||
/* Get next revocation hash. */ |
|||
shachain_from_seed(&seed, num_updates, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o1 commit pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit pubkey"); |
|||
|
|||
/* This is what the anchor pays to; figure out whick output. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ |
|||
invert_cstate(cstate); |
|||
commit = commit_tx_from_pkts(ctx, o2, o1, a, &their_rhash, cstate); |
|||
|
|||
/* If contributions don't exceed fees, this fails. */ |
|||
if (!commit) |
|||
errx(1, "Delta too large"); |
|||
|
|||
/* Sign it for them. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig.sig); |
|||
|
|||
pkt = update_accept_pkt(ctx, &sig.sig, &revocation_hash); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,100 +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/read_write_all/read_write_all.h> |
|||
#include <ccan/structeq/structeq.h> |
|||
#include "lightning.pb-c.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 "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, our_rhash, their_rhash, preimage; |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct pkt *pkt; |
|||
struct bitcoin_tx *commit; |
|||
struct pubkey pubkey1, pubkey2; |
|||
size_t num_updates; |
|||
struct bitcoin_signature sig; |
|||
u8 *redeemscript; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <all-previous-updates>\n" |
|||
"Create a new update-complete message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc < 7) |
|||
opt_usage_exit_fail("Expected 6+ arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
|
|||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
sig.stype = SIGHASH_ALL; |
|||
|
|||
/* This also checks that preimage is correct! */ |
|||
cstate = gather_updates(ctx, o1, o2, a, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee), |
|||
argv + 5, |
|||
&num_updates, |
|||
&our_rhash, &their_rhash, &sig.sig); |
|||
if (num_updates < 1) |
|||
errx(1, "Expected at least one update!"); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey1)) |
|||
errx(1, "Invalid o1 commit pubkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit pubkey"); |
|||
|
|||
/* This is what the anchor pays to. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
/* Check their signature signs our new commit tx correctly. */ |
|||
commit = commit_tx_from_pkts(ctx, o1, o2, a, &our_rhash, cstate); |
|||
if (!commit) |
|||
errx(1, "Delta too large"); |
|||
|
|||
if (!check_tx_sig(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&pubkey2, &sig)) |
|||
errx(1, "Invalid signature."); |
|||
|
|||
/* Hand over our preimage for previous tx. */ |
|||
shachain_from_seed(&seed, num_updates - 1, &preimage); |
|||
pkt = update_complete_pkt(ctx, &preimage); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "find_p2sh_out.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, revocation_hash, rval; |
|||
struct pkt *pkt; |
|||
unsigned update_num; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <update-number> <r-value>\n" |
|||
"Create a new HTLC complete message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 4) |
|||
opt_usage_exit_fail("Expected 3 arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
update_num = atoi(argv[2]); |
|||
if (!update_num) |
|||
errx(1, "Update number %s invalid", argv[2]); |
|||
|
|||
if (!hex_decode(argv[3], strlen(argv[3]), &rval, sizeof(rval))) |
|||
errx(1, "Invalid rvalue '%s' - need 256 hex bits", argv[3]); |
|||
|
|||
/* Get next revocation hash. */ |
|||
shachain_from_seed(&seed, update_num, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
pkt = update_htlc_complete_pkt(ctx, &revocation_hash, &rval); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,71 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, htlc_rhash, revocation_hash; |
|||
struct pkt *pkt; |
|||
unsigned update_num; |
|||
UpdateAddHtlc *u; |
|||
bool routefail = false; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <update-number> <update-pkt>\n" |
|||
"Create a new HTLC (timedout) remove message", |
|||
"Print this message."); |
|||
opt_register_noarg("--routefail", opt_set_bool, &routefail, |
|||
"Generate a routefail instead of timedout"); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (argc != 4) |
|||
opt_usage_exit_fail("Expected 3 arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
update_num = atoi(argv[2]); |
|||
if (!update_num) |
|||
errx(1, "Update number %s invalid", argv[2]); |
|||
|
|||
u = pkt_from_file(argv[3], PKT__PKT_UPDATE_ADD_HTLC)->update_add_htlc; |
|||
proto_to_sha256(u->r_hash, &htlc_rhash); |
|||
|
|||
/* Get next revocation hash. */ |
|||
shachain_from_seed(&seed, update_num, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
if (routefail) |
|||
pkt = update_htlc_routefail_pkt(ctx, &revocation_hash, |
|||
&htlc_rhash); |
|||
else |
|||
pkt = update_htlc_timedout_pkt(ctx, &revocation_hash, |
|||
&htlc_rhash); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,76 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "find_p2sh_out.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, revocation_hash, rval, rhash; |
|||
struct pkt *pkt; |
|||
uint64_t htlc_val; |
|||
u32 locktime_seconds; |
|||
unsigned update_num; |
|||
char *endp; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <update-number> <satoshi> <r-value> <abs-locktime-seconds>\n" |
|||
"Create a new HTLC update message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
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]); |
|||
update_num = atoi(argv[2]); |
|||
if (!update_num) |
|||
errx(1, "Update number %s invalid", argv[2]); |
|||
|
|||
htlc_val = strtol(argv[3], &endp, 10); |
|||
if (*endp || !htlc_val) |
|||
errx(1, "Expected number for %s", argv[3]); |
|||
|
|||
if (!hex_decode(argv[4], strlen(argv[4]), &rval, sizeof(rval))) |
|||
errx(1, "Invalid rvalue '%s' - need 256 hex bits", argv[4]); |
|||
|
|||
locktime_seconds = strtol(argv[5], &endp, 10); |
|||
if (*endp || !locktime_seconds) |
|||
errx(1, "Expected locktime for %s", argv[5]); |
|||
|
|||
/* Get next revocation hash. */ |
|||
shachain_from_seed(&seed, update_num, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
/* Get htlc rvalue hash. */ |
|||
sha256(&rhash, &rval, sizeof(rval)); |
|||
|
|||
pkt = update_htlc_add_pkt(ctx, &revocation_hash, htlc_val, |
|||
&rhash, locktime_seconds); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,129 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "bitcoin/privkey.h" |
|||
#include "find_p2sh_out.h" |
|||
#include "protobuf_convert.h" |
|||
#include "gather_updates.h" |
|||
#include "funding.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, preimage, our_rhash, their_rhash; |
|||
OpenChannel *o1, *o2; |
|||
OpenAnchor *a; |
|||
struct bitcoin_tx *commit; |
|||
struct pkt *pkt; |
|||
struct bitcoin_signature sig; |
|||
struct privkey privkey; |
|||
bool testnet; |
|||
struct pubkey pubkey1, pubkey2; |
|||
u8 *redeemscript; |
|||
size_t num_updates; |
|||
struct channel_state *cstate; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-previous-updates>...\n" |
|||
"Create a new update-channel-signature message", |
|||
"Print this message."); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
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]); |
|||
|
|||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open; |
|||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open; |
|||
a = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR)->open_anchor; |
|||
|
|||
if (!key_from_base58(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|||
| SECP256K1_CONTEXT_SIGN), |
|||
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[5]); |
|||
|
|||
sig.stype = SIGHASH_ALL; |
|||
|
|||
/* Figure out cumulative delta since anchor. */ |
|||
cstate = gather_updates(ctx, o1, o2, a, |
|||
commit_fee(o1->commitment_fee, |
|||
o2->commitment_fee), |
|||
argv + 6, |
|||
&num_updates, |
|||
&our_rhash, &their_rhash, &sig.sig); |
|||
if (num_updates < 1) |
|||
errx(1, "Expected at least one update!"); |
|||
|
|||
/* Give up revocation preimage for old tx. */ |
|||
shachain_from_seed(&seed, num_updates - 1, &preimage); |
|||
|
|||
/* Get pubkeys */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o1->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o1 commit pubkey"); |
|||
if (!pubkey_eq(&pubkey1, &pubkey2)) |
|||
errx(1, "o1 pubkey != this privkey"); |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid o2 commit pubkey"); |
|||
|
|||
/* This is what the anchor pays to. */ |
|||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2); |
|||
|
|||
/* Check our new commit is signed correctly by them. */ |
|||
commit = commit_tx_from_pkts(ctx, o1, o2, a, &our_rhash, cstate); |
|||
if (!commit) |
|||
errx(1, "Invalid packets"); |
|||
|
|||
/* Check their signature signs this input correctly. */ |
|||
if (!check_tx_sig(secp256k1_context_create(SECP256K1_CONTEXT_VERIFY), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&pubkey2, &sig)) |
|||
errx(1, "Invalid signature."); |
|||
|
|||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */ |
|||
invert_cstate(cstate); |
|||
commit = commit_tx_from_pkts(ctx, o2, o1, a, &their_rhash, cstate); |
|||
if (!commit) |
|||
errx(1, "Invalid packets"); |
|||
|
|||
/* Their pubkey must be valid */ |
|||
if (!proto_to_pubkey(secp256k1_context_create(0), |
|||
o2->commit_key, &pubkey2)) |
|||
errx(1, "Invalid public open-channel-file2"); |
|||
|
|||
/* Sign it for them. */ |
|||
sign_tx_input(secp256k1_context_create(SECP256K1_CONTEXT_SIGN), |
|||
commit, 0, redeemscript, tal_count(redeemscript), |
|||
&privkey, &pubkey1, &sig.sig); |
|||
|
|||
pkt = update_signature_pkt(ctx, &sig.sig, &preimage); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
@ -1,73 +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/read_write_all/read_write_all.h> |
|||
#include "lightning.pb-c.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 "find_p2sh_out.h" |
|||
#include "version.h" |
|||
#include <unistd.h> |
|||
|
|||
int main(int argc, char *argv[]) |
|||
{ |
|||
const tal_t *ctx = tal_arr(NULL, char, 0); |
|||
struct sha256 seed, revocation_hash; |
|||
struct pkt *pkt; |
|||
unsigned long long to_them = 0, from_them = 0; |
|||
int64_t this_delta; |
|||
unsigned update_num; |
|||
|
|||
err_set_progname(argv[0]); |
|||
|
|||
opt_register_noarg("--help|-h", opt_usage_and_exit, |
|||
"<seed> <update-number>\n" |
|||
"Create a new update message", |
|||
"Print this message."); |
|||
opt_register_arg("--to-them=<satoshi>", |
|||
opt_set_ulonglongval_si, NULL, &to_them, |
|||
"Amount to pay them (must use this or --from-them)"); |
|||
opt_register_arg("--from-them=<satoshi>", |
|||
opt_set_ulonglongval_si, NULL, &from_them, |
|||
"Amount to pay us (must use this or --to-them)"); |
|||
opt_register_version(); |
|||
|
|||
opt_parse(&argc, argv, opt_log_stderr_exit); |
|||
|
|||
if (!from_them && !to_them) |
|||
opt_usage_exit_fail("Must use --to-them or --from-them"); |
|||
|
|||
if (argc != 3) |
|||
opt_usage_exit_fail("Expected 2 arguments"); |
|||
|
|||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed))) |
|||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]); |
|||
update_num = atoi(argv[2]); |
|||
if (!update_num) |
|||
errx(1, "Update number %s invalid", argv[2]); |
|||
|
|||
this_delta = from_them - to_them; |
|||
if (!this_delta) |
|||
errx(1, "Delta must not be zero"); |
|||
|
|||
/* Get next revocation hash. */ |
|||
shachain_from_seed(&seed, update_num, &revocation_hash); |
|||
sha256(&revocation_hash, |
|||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8)); |
|||
|
|||
pkt = update_pkt(ctx, &revocation_hash, this_delta); |
|||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt))) |
|||
err(1, "Writing out packet"); |
|||
|
|||
tal_free(ctx); |
|||
return 0; |
|||
} |
|||
|
Loading…
Reference in new issue