mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-09 17:14:28 +01:00
protocol: switch to single-funder anchor model.
Most complex change was gather_updates(), which handles all the "what is the current state of the channel" logic for our dumb test utils. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -1,61 +0,0 @@
|
||||
#include <ccan/crypto/shachain/shachain.h>
|
||||
#include <ccan/short_types/short_types.h>
|
||||
#include <ccan/tal/tal.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
#include "permute_tx.h"
|
||||
#include "bitcoin/signature.h"
|
||||
#include "commit_tx.h"
|
||||
#include "bitcoin/pubkey.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
OpenAnchorScriptsigs *ss1, *ss2;
|
||||
struct bitcoin_tx *anchor;
|
||||
struct sha256_double txid;
|
||||
size_t *inmap, *outmap;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<open-channel-file1> <open-channel-file2> <anchor-sig2-1> <anchor-sigs2>\n"
|
||||
"Output the anchor transaction by merging the scriptsigs",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc != 5)
|
||||
opt_usage_exit_fail("Expected 6 arguments");
|
||||
|
||||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
ss1 = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS)
|
||||
->open_anchor_scriptsigs;
|
||||
ss2 = pkt_from_file(argv[4], PKT__PKT_OPEN_ANCHOR_SCRIPTSIGS)
|
||||
->open_anchor_scriptsigs;
|
||||
|
||||
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
|
||||
if (!anchor)
|
||||
errx(1, "Failed transaction merge");
|
||||
if (!anchor_add_scriptsigs(anchor, ss1, ss2, inmap))
|
||||
errx(1, "Wrong number of scriptsigs");
|
||||
|
||||
bitcoin_txid(anchor, &txid);
|
||||
|
||||
if (!bitcoin_tx_write(STDOUT_FILENO, anchor))
|
||||
err(1, "Writing out anchor transaction");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -15,92 +14,73 @@
|
||||
#include "bitcoin/pubkey.h"
|
||||
#include "bitcoin/privkey.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "funding.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
OpenCommitSig *cs2;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *commit;
|
||||
u8 *subscript;
|
||||
size_t *inmap, *outmap;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
struct bitcoin_signature sig1, sig2;
|
||||
struct bitcoin_signature sig;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
struct sha256 rhash;
|
||||
u64 our_amount, their_amount;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<open-channel-file1> <open-channel-file2> <commit-sig-2> <commit-key1>\n"
|
||||
"Output the commitment transaction if both signatures are valid",
|
||||
"<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_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc != 5)
|
||||
opt_usage_exit_fail("Expected 4 arguments");
|
||||
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;
|
||||
cs2 = pkt_from_file(argv[3], PKT__PKT_OPEN_COMMIT_SIG)->open_commit_sig;
|
||||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
|
||||
|
||||
if (!key_from_base58(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(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit_key");
|
||||
|
||||
/* Get the transaction ID of the anchor. */
|
||||
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
|
||||
if (!anchor)
|
||||
errx(1, "Failed transaction merge");
|
||||
anchor_txid(anchor, &txid);
|
||||
|
||||
if (!initial_funding(o1, o2, a, &our_amount, &their_amount))
|
||||
errx(1, "Invalid open combination (need 1 anchor offer)");
|
||||
|
||||
/* Now create our commitment tx. */
|
||||
proto_to_sha256(o1->revocation_hash, &rhash);
|
||||
commit = create_commit_tx(ctx, o1, o2, &rhash, 0, &txid, outmap[0]);
|
||||
commit = create_commit_tx(ctx, o1, o2, a, &rhash,
|
||||
our_amount, their_amount);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
if (!commit)
|
||||
errx(1, "Contributions %llu & %llu vs fees %llu & %llu",
|
||||
(long long)o1->anchor->total,
|
||||
(long long)o2->anchor->total,
|
||||
(long long)o1->commitment_fee,
|
||||
(long long)o2->commitment_fee);
|
||||
|
||||
/* FIXME: Creating out signature just to check the script we create
|
||||
* is overkill: if their signature and pubkey signed the commit txin,
|
||||
* we're happy. */
|
||||
sig1.stype = SIGHASH_ALL;
|
||||
/* Check signature. */
|
||||
subscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
sign_tx_input(ctx, commit, 0, subscript, tal_count(subscript),
|
||||
&privkey, &pubkey1, &sig1.sig);
|
||||
|
||||
/* Signatures well-formed? */
|
||||
if (!proto_to_signature(cs2->sig, &sig2.sig))
|
||||
errx(1, "Invalid commit-sig-2");
|
||||
sig2.stype = SIGHASH_ALL;
|
||||
|
||||
/* Combined signatures must validate correctly. */
|
||||
if (!check_2of2_sig(commit, 0, subscript, tal_count(subscript),
|
||||
&pubkey1, &pubkey2, &sig1, &sig2))
|
||||
errx(1, "Signature failed");
|
||||
|
||||
/* Create p2sh input for commit */
|
||||
commit->input[0].script = scriptsig_p2sh_2of2(commit, &sig1, &sig2,
|
||||
&pubkey1, &pubkey2);
|
||||
commit->input[0].script_length = tal_count(commit->input[0].script);
|
||||
|
||||
/* Print it out in hex. */
|
||||
if (!bitcoin_tx_write(STDOUT_FILENO, commit))
|
||||
err(1, "Writing out transaction");
|
||||
if (!check_tx_sig(commit, 0, subscript, tal_count(subscript),
|
||||
&pubkey2, &sig))
|
||||
errx(1, "Their signature invalid");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
|
||||
@@ -6,41 +6,40 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
#include "permute_tx.h"
|
||||
#include "funding.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 <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
struct bitcoin_tx *anchor, *close_tx;
|
||||
struct sha256_double anchor_txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct pkt *pkt;
|
||||
struct signature sig;
|
||||
struct privkey privkey;
|
||||
bool testnet, complete = false;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
int64_t delta;
|
||||
size_t i, anchor_out;
|
||||
uint64_t our_amount, their_amount;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
/* FIXME: Take update.pbs to adjust channel */
|
||||
opt_register_noarg("--complete", opt_set_bool, &complete,
|
||||
"Create a close_transaction_complete msg instead");
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [update-protobuf]...\n"
|
||||
"<open-channel-file1> <open-channel-file2> <anchor-file> <commit-privkey> [{+/-}update-protobuf]...\n"
|
||||
"Create the signature needed for the close transaction",
|
||||
"Print this message.");
|
||||
|
||||
@@ -49,23 +48,17 @@ int main(int argc, char *argv[])
|
||||
if (argc < 5)
|
||||
opt_usage_exit_fail("Expected 4+ arguments");
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[1]);
|
||||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
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(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]);
|
||||
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
|
||||
/* Get delta by accumulting all the updates. */
|
||||
delta = 0;
|
||||
for (i = 5; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
}
|
||||
gather_updates(o1, o2, a, argv + 5, &our_amount, &their_amount,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
@@ -76,16 +69,11 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
||||
/* This is what the anchor pays to; figure out whick output. */
|
||||
/* This is what the anchor pays to. */
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
|
||||
/* Now create the close tx to spend 2/2 output of anchor. */
|
||||
/* Assumes that updates are all from closer -> closee */
|
||||
anchor_out = find_p2sh_out(anchor, redeemscript);
|
||||
close_tx = create_close_tx(ctx, o1, o2, complete ? -delta : delta,
|
||||
&anchor_txid,
|
||||
anchor->output[anchor_out].amount,
|
||||
anchor_out);
|
||||
/* FIXME: Add fee! */
|
||||
close_tx = create_close_tx(ctx, o1, o2, a, our_amount, their_amount);
|
||||
|
||||
/* Sign it for them. */
|
||||
sign_tx_input(ctx, close_tx, 0, redeemscript, tal_count(redeemscript),
|
||||
|
||||
189
test-cli/create-anchor-tx.c
Normal file
189
test-cli/create-anchor-tx.c
Normal file
@@ -0,0 +1,189 @@
|
||||
#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"
|
||||
|
||||
/* 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(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_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(o1->commit_key, &pubkey1))
|
||||
errx(1, "Invalid o1 commit_key");
|
||||
if (!proto_to_pubkey(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(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;
|
||||
if (!sign_tx_input(ctx, anchor, i, in[i].in.script,
|
||||
in[i].in.script_length,
|
||||
&in[i].privkey, &in[i].pubkey,
|
||||
&in[i].sig.sig))
|
||||
errx(1, "Error signing input %zi", i);
|
||||
}
|
||||
|
||||
/* Finally, complete inputs using signatures. */
|
||||
for (i = 0; i < tal_count(in); i++) {
|
||||
if (!is_pay_to_pubkey_hash(in[i].in.script,
|
||||
in[i].in.script_length))
|
||||
errx(1, "FIXME: Don't know how to handle input %zi", i);
|
||||
anchor->input[i].script
|
||||
= scriptsig_pay_to_pubkeyhash(anchor, &in[i].pubkey,
|
||||
&in[i].sig);
|
||||
anchor->input[i].script_length
|
||||
= tal_count(anchor->input[i].script);
|
||||
}
|
||||
|
||||
/* Print it out in hex. */
|
||||
if (!bitcoin_tx_write(STDOUT_FILENO, anchor))
|
||||
err(1, "Writing out transaction");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -15,27 +14,27 @@
|
||||
#include "close_tx.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "gather_updates.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
struct bitcoin_tx *anchor, *close_tx;
|
||||
struct sha256_double anchor_txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *close_tx;
|
||||
struct bitcoin_signature sig1, sig2;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
CloseChannel *close;
|
||||
CloseChannelComplete *closecomplete;
|
||||
size_t i, anchor_out;
|
||||
int64_t delta;
|
||||
uint64_t our_amount, their_amount;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
/* FIXME: Take update.pbs to adjust channel */
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<anchor-tx> <open-channel-file1> <open-channel-file2> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n"
|
||||
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <close-protobuf> <close-complete-protobuf> [update-protobuf]...\n"
|
||||
"Create the close transaction from the signatures",
|
||||
"Print this message.");
|
||||
|
||||
@@ -44,14 +43,12 @@ int main(int argc, char *argv[])
|
||||
if (argc < 6)
|
||||
opt_usage_exit_fail("Expected 5+ arguments");
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[1]);
|
||||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
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;
|
||||
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
|
||||
/* Pubkeys well-formed? */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey1))
|
||||
errx(1, "Invalid o1 commit_key");
|
||||
@@ -59,20 +56,14 @@ int main(int argc, char *argv[])
|
||||
errx(1, "Invalid o2 commit_key");
|
||||
|
||||
/* Get delta by accumulting all the updates. */
|
||||
delta = 0;
|
||||
for (i = 6; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
}
|
||||
gather_updates(o1, o2, a, argv + 6, &our_amount, &their_amount,
|
||||
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. */
|
||||
anchor_out = find_p2sh_out(anchor, redeemscript);
|
||||
close_tx = create_close_tx(ctx, o1, o2, delta, &anchor_txid,
|
||||
anchor->output[anchor_out].amount,
|
||||
anchor_out);
|
||||
close_tx = create_close_tx(ctx, o1, o2, a, our_amount, their_amount);
|
||||
|
||||
/* Signatures well-formed? */
|
||||
sig1.stype = sig2.stype = SIGHASH_ALL;
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -19,12 +18,14 @@
|
||||
#include "opt_bits.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "test-cli/gather_updates.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;
|
||||
@@ -32,8 +33,8 @@ int main(int argc, char *argv[])
|
||||
struct pubkey pubkey1, pubkey2, outpubkey;
|
||||
u8 *redeemscript;
|
||||
struct sha256 rhash;
|
||||
size_t i, p2sh_out;
|
||||
u64 fee = 10000;
|
||||
size_t p2sh_out;
|
||||
u64 fee = 10000, our_amount, their_amount;
|
||||
u32 locktime;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
@@ -41,7 +42,7 @@ int main(int argc, char *argv[])
|
||||
/* 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> <my-privoutkey> <someaddress> [previous-updates]\n"
|
||||
"<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>",
|
||||
@@ -57,17 +58,18 @@ int main(int argc, char *argv[])
|
||||
|
||||
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_locktime(o2, &locktime))
|
||||
errx(1, "Invalid locktime in o2");
|
||||
|
||||
/* We need our private key to spend commit output. */
|
||||
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
|
||||
errx(1, "Invalid private key '%s'", argv[4]);
|
||||
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet, &privkey, &pubkey1))
|
||||
errx(1, "Invalid private key '%s'", argv[5]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[4]);
|
||||
errx(1, "Private key '%s' not on testnet!", argv[5]);
|
||||
|
||||
if (!pubkey_from_hexstr(argv[5], &outpubkey))
|
||||
errx(1, "Invalid bitcoin pubkey '%s'", argv[5]);
|
||||
if (!pubkey_from_hexstr(argv[6], &outpubkey))
|
||||
errx(1, "Invalid bitcoin pubkey '%s'", argv[6]);
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->final_key, &pubkey2))
|
||||
@@ -78,14 +80,9 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->final_key, &pubkey2))
|
||||
errx(1, "Invalid o2 final pubkey");
|
||||
|
||||
/* o1 gives us the revocation hash */
|
||||
proto_to_sha256(o1->revocation_hash, &rhash);
|
||||
|
||||
/* Latest revocation hash comes from last update. */
|
||||
for (i = 6; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
proto_to_sha256(u->revocation_hash, &rhash);
|
||||
}
|
||||
/* We use this simply to get final revocation hash. */
|
||||
gather_updates(o1, o2, a, argv + 7, &our_amount, &their_amount,
|
||||
&rhash, NULL, NULL);
|
||||
|
||||
/* Create redeem script */
|
||||
redeemscript = bitcoin_redeem_secret_or_delay(ctx, &pubkey1, locktime,
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -16,6 +15,7 @@
|
||||
#include "bitcoin/privkey.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "gather_updates.h"
|
||||
#include <unistd.h>
|
||||
|
||||
/* FIXME: this code doesn't work if we're not the ones proposing the delta */
|
||||
@@ -23,34 +23,31 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
Pkt *pkt;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double anchor_txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *commit;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
struct bitcoin_signature sig1, sig2;
|
||||
size_t i;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
int64_t delta;
|
||||
uint64_t our_amount, their_amount;
|
||||
struct sha256 rhash;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> [final-update-accept|open-commit-sig] [<updates>]\n"
|
||||
"<open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> [<updates>]\n"
|
||||
"Create the signature needed for the commit transaction",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc < 6)
|
||||
opt_usage_exit_fail("Expected 5+ arguments");
|
||||
if (argc < 5)
|
||||
opt_usage_exit_fail("Expected 4+ arguments");
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[1]);
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
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(argv[4], strlen(argv[4]), &testnet, &privkey, &pubkey1))
|
||||
errx(1, "Invalid private key '%s'", argv[4]);
|
||||
@@ -66,49 +63,27 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
||||
/* Their signature comes from open-commit or from update-accept. */
|
||||
sig2.stype = SIGHASH_ALL;
|
||||
pkt = any_pkt_from_file(argv[5]);
|
||||
|
||||
switch (pkt->pkt_case) {
|
||||
case PKT__PKT_UPDATE_ACCEPT:
|
||||
if (!proto_to_signature(pkt->update_accept->sig, &sig2.sig))
|
||||
errx(1, "Invalid update-accept sig");
|
||||
break;
|
||||
case PKT__PKT_OPEN_COMMIT_SIG:
|
||||
if (!proto_to_signature(pkt->open_commit_sig->sig, &sig2.sig))
|
||||
errx(1, "Invalid open-commit-sig sig");
|
||||
break;
|
||||
default:
|
||||
errx(1, "Unexpected packet type %u in %s",
|
||||
pkt->pkt_case, argv[5]);
|
||||
}
|
||||
gather_updates(o1, o2, a, argv + 5, &our_amount, &their_amount,
|
||||
&rhash, NULL, &sig2.sig);
|
||||
|
||||
/* Initial revocation hash comes from open. */
|
||||
proto_to_sha256(o1->revocation_hash, &rhash);
|
||||
|
||||
delta = 0;
|
||||
/* Figure out cumulative delta since anchor, update revocation hash */
|
||||
for (i = 6; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
proto_to_sha256(u->revocation_hash, &rhash);
|
||||
}
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
|
||||
/* Now create commitment tx to spend 2/2 output of anchor. */
|
||||
commit = create_commit_tx(ctx, o1, o2, &rhash, delta, &anchor_txid,
|
||||
find_p2sh_out(anchor, redeemscript));
|
||||
commit = create_commit_tx(ctx, o1, o2, a, &rhash,
|
||||
our_amount, their_amount);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
/* This only fails on malformed packets */
|
||||
if (!commit)
|
||||
errx(1, "Bad commit amounts");
|
||||
errx(1, "Malformed packets");
|
||||
|
||||
/* We generate our signature. */
|
||||
sig1.stype = SIGHASH_ALL;
|
||||
sign_tx_input(ctx, commit, 0, redeemscript, tal_count(redeemscript),
|
||||
&privkey, &pubkey1, &sig1.sig);
|
||||
|
||||
/* Check it works with theirs... */
|
||||
if (!check_2of2_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||
&pubkey1, &pubkey2, &sig1, &sig2))
|
||||
errx(1, "Signature failed");
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
|
||||
149
test-cli/gather_updates.c
Normal file
149
test-cli/gather_updates.c
Normal file
@@ -0,0 +1,149 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/crypto/sha256/sha256.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include "test-cli/gather_updates.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);
|
||||
}
|
||||
|
||||
static void get_rhash(const Sha256Hash *rhash, struct sha256 *old,
|
||||
struct sha256 *new)
|
||||
{
|
||||
if (new) {
|
||||
*old = *new;
|
||||
proto_to_sha256(rhash, new);
|
||||
}
|
||||
}
|
||||
|
||||
/* Takes complete update history, gets summary of last state. */
|
||||
uint64_t gather_updates(const OpenChannel *o1, const OpenChannel *o2,
|
||||
const OpenAnchor *oa,
|
||||
char **argv,
|
||||
uint64_t *our_amount, uint64_t *their_amount,
|
||||
struct sha256 *our_rhash,
|
||||
struct sha256 *their_rhash,
|
||||
struct signature *their_commit_sig)
|
||||
{
|
||||
uint64_t cdelta = 0;
|
||||
uint64_t num_updates = 0;
|
||||
Signature *sig = NULL;
|
||||
struct sha256 old_our_rhash, old_their_rhash;
|
||||
|
||||
/* Start sanity check. */
|
||||
if (!initial_funding(o1, o2, oa, our_amount, their_amount))
|
||||
errx(1, "Invalid open combination (need 1 anchor offer)");
|
||||
|
||||
if (our_rhash)
|
||||
proto_to_sha256(o1->revocation_hash, our_rhash);
|
||||
|
||||
if (their_rhash)
|
||||
proto_to_sha256(o2->revocation_hash, their_rhash);
|
||||
|
||||
/* If o2 sent anchor, it contains their commit sig. */
|
||||
if (o2->anch == OPEN_CHANNEL__ANCHOR_OFFER__WILL_CREATE_ANCHOR)
|
||||
sig = oa->commit_sig;
|
||||
|
||||
while (*argv) {
|
||||
int64_t delta;
|
||||
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: {
|
||||
if (received) {
|
||||
delta = -pkt->update->delta;
|
||||
get_rhash(pkt->update->revocation_hash,
|
||||
&old_their_rhash, their_rhash);
|
||||
} else {
|
||||
delta = pkt->update->delta;
|
||||
get_rhash(pkt->update->revocation_hash,
|
||||
&old_our_rhash, our_rhash);
|
||||
}
|
||||
if (!funding_delta(o1, o2, oa, &cdelta, delta,
|
||||
our_amount, their_amount))
|
||||
errx(1, "Impossible funding update %lli %s",
|
||||
(long long)delta, *argv);
|
||||
num_updates++;
|
||||
break;
|
||||
}
|
||||
case PKT__PKT_UPDATE_ACCEPT:
|
||||
if (received) {
|
||||
sig = pkt->update_accept->sig;
|
||||
get_rhash(pkt->update_accept->revocation_hash,
|
||||
&old_their_rhash, their_rhash);
|
||||
} else {
|
||||
get_rhash(pkt->update_accept->revocation_hash,
|
||||
&old_our_rhash, our_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");
|
||||
}
|
||||
|
||||
return num_updates;
|
||||
}
|
||||
16
test-cli/gather_updates.h
Normal file
16
test-cli/gather_updates.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef GATHER_UPDATES_H
|
||||
#define GATHER_UPDATES_H
|
||||
#include "lightning.pb-c.h"
|
||||
|
||||
struct signature;
|
||||
struct sha256;
|
||||
|
||||
uint64_t gather_updates(const OpenChannel *o1, const OpenChannel *o2,
|
||||
const OpenAnchor *oa,
|
||||
char **argv,
|
||||
uint64_t *our_amount, uint64_t *their_amount,
|
||||
struct sha256 *our_rhash,
|
||||
struct sha256 *their_rhash,
|
||||
struct signature *their_commit_sig);
|
||||
|
||||
#endif /* GATHER_UPDATES_H */
|
||||
@@ -5,7 +5,6 @@
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -33,7 +32,7 @@ int main(int argc, char *argv[])
|
||||
opt_usage_exit_fail("Expected one argument");
|
||||
|
||||
o = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
printf("%u\n", o->anchor->min_confirms);
|
||||
printf("%u\n", o->min_depth);
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "bitcoin/tx.h"
|
||||
#include "bitcoin/signature.h"
|
||||
#include "lightning.pb-c.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
#include "bitcoin/address.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/pubkey.h"
|
||||
#include "bitcoin/privkey.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/* All the input scripts are already set to 0. We just need to make this one. */
|
||||
static u8 *tx_scriptsig(const tal_t *ctx,
|
||||
struct bitcoin_tx *tx,
|
||||
unsigned int i,
|
||||
const BitcoinInput *input,
|
||||
struct privkey *privkey,
|
||||
const struct pubkey *pubkey)
|
||||
{
|
||||
struct bitcoin_signature sig;
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!sign_tx_input(ctx, tx, i,
|
||||
input->subscript.data, input->subscript.len,
|
||||
privkey, pubkey, &sig.sig))
|
||||
return NULL;
|
||||
|
||||
if (!is_pay_to_pubkey_hash(input->subscript.data, input->subscript.len))
|
||||
errx(1, "FIXME: Don't know how to handle input");
|
||||
return scriptsig_pay_to_pubkeyhash(ctx, pubkey, &sig);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
OpenChannel *o1, *o2;
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct bitcoin_tx *anchor;
|
||||
struct pkt *pkt;
|
||||
size_t i;
|
||||
u8 **sigs;
|
||||
size_t *map;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<open-channel-file1> <open-channel-file2> <privkey>...\n"
|
||||
"Create signatures for transactions, and output to stdout",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc < 3)
|
||||
opt_usage_exit_fail("Expected 2 or more arguments");
|
||||
|
||||
o1 = pkt_from_file(argv[1], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
|
||||
/* FIXME: We should check that their locktime is sane here,
|
||||
* since we're bound to it. Also min_confirms, etc. */
|
||||
|
||||
/* Create merged transaction */
|
||||
anchor = anchor_tx_create(ctx, o1, o2, &map, NULL);
|
||||
if (!anchor)
|
||||
errx(1, "Failed transaction merge");
|
||||
|
||||
/* Sign our inputs. */
|
||||
if (o1->anchor->n_inputs != argc - 3)
|
||||
errx(1, "Expected %zu private keys", o1->anchor->n_inputs);
|
||||
|
||||
sigs = tal_arr(ctx, u8 *, o1->anchor->n_inputs);
|
||||
for (i = 0; i < o1->anchor->n_inputs; i++) {
|
||||
struct pubkey pubkey;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
|
||||
if (!key_from_base58(argv[3+i], strlen(argv[3+i]),
|
||||
&testnet, &privkey, &pubkey))
|
||||
errx(1, "Invalid private key '%s'", argv[3+i]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[3+i]);
|
||||
|
||||
sigs[i] = tx_scriptsig(sigs, anchor, map[i],
|
||||
o1->anchor->inputs[i],
|
||||
&privkey, &pubkey);
|
||||
}
|
||||
|
||||
pkt = open_anchor_sig_pkt(ctx, sigs, o1->anchor->n_inputs);
|
||||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt)))
|
||||
err(1, "Writing out packet");
|
||||
|
||||
tal_free(ctx);
|
||||
return 0;
|
||||
}
|
||||
@@ -22,145 +22,61 @@
|
||||
/* Bitcoin nodes are allowed to be 2 hours in the future. */
|
||||
#define LOCKTIME_MIN (2 * 60 * 60)
|
||||
|
||||
static BitcoinInput *parse_anchor_input(const tal_t *ctx, const char *spec)
|
||||
{
|
||||
BitcoinInput *in = tal(ctx, BitcoinInput);
|
||||
struct sha256_double txid;
|
||||
const char *slash;
|
||||
char *end;
|
||||
long l;
|
||||
|
||||
bitcoin_input__init(in);
|
||||
|
||||
slash = strchr(spec, '/');
|
||||
if (!slash)
|
||||
errx(1, "Expected / in <txid>/<num>/<satoshis>/<hexscript>");
|
||||
|
||||
if (!bitcoin_txid_from_hex(spec, slash - spec, &txid))
|
||||
errx(1, "Expected 256-bit hex txid before /");
|
||||
in->txid = sha256_to_proto(in, &txid.sha);
|
||||
|
||||
in->output = l = strtol(slash + 1, &end, 10);
|
||||
if (end == slash + 1 || *end != '/' || (int64_t)in->output != (int64_t)l)
|
||||
errx(1, "Expected <outputnum> after /");
|
||||
|
||||
slash = end;
|
||||
in->amount = l = strtol(slash + 1, &end, 10);
|
||||
if (end == slash + 1 || *end != '/' || (int64_t)in->amount != (int64_t)l)
|
||||
errx(1, "Expected <satoshis> after second /");
|
||||
|
||||
slash = end;
|
||||
in->subscript.len = strlen(slash + 1) / 2;
|
||||
in->subscript.data = tal_arr(in, u8, in->subscript.len);
|
||||
if (!hex_decode(slash + 1, strlen(slash + 1),
|
||||
in->subscript.data, in->subscript.len))
|
||||
errx(1, "Expected hex string after third /");
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/* Simple helper to open a channel. */
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct sha256 seed, revocation_hash;
|
||||
struct pkt *pkt;
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
Anchor anchor = ANCHOR__INIT;
|
||||
u64 commit_tx_fee, total_in;
|
||||
unsigned int locktime_seconds;
|
||||
bool testnet;
|
||||
size_t i;
|
||||
struct pubkey commitkey, outkey, changekey;
|
||||
struct privkey commitprivkey, outprivkey;
|
||||
unsigned int locktime_seconds, min_confirms;
|
||||
bool offer_anchor = false;
|
||||
struct pubkey commitkey, finalkey;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
/* Default values. */
|
||||
anchor.min_confirms = 3;
|
||||
/* Remember, other side contributes to fee, too. */
|
||||
anchor.fee = 5000;
|
||||
/* We only need this for involuntary close, so make it larger. */
|
||||
commit_tx_fee = 100000;
|
||||
/* This means we have ~1 day before they can steal our money. */
|
||||
locktime_seconds = LOCKTIME_MIN + 24 * 60 * 60;
|
||||
/* Zero, unless they set --offer-anchor or --min-anchor-confirms */
|
||||
min_confirms = 0;
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<seed> <amount> <changepubkey> <commitprivkey> <outprivkey> <txid>/<outnum>/<satoshis>/<script-in-hex>...\n"
|
||||
"<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, &anchor.min_confirms,
|
||||
opt_set_uintval, opt_show_uintval, &min_confirms,
|
||||
"Number of anchor confirmations before channel is active");
|
||||
opt_register_arg("--anchor-fee=<bits>",
|
||||
opt_set_bits, opt_show_bits, &anchor.fee,
|
||||
"100's of satoshi to pay for anchor");
|
||||
opt_register_arg("--commitment-fee=<bits>",
|
||||
opt_set_bits, opt_show_bits, &commit_tx_fee,
|
||||
"100's of satoshi to pay for commitment");
|
||||
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_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc < 7)
|
||||
opt_usage_exit_fail("Expected 6 or more arguments");
|
||||
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]);
|
||||
|
||||
anchor.total = atol(argv[2]);
|
||||
if (!anchor.total)
|
||||
errx(1, "Invalid total: must be > 0");
|
||||
if (!pubkey_from_hexstr(argv[2], &commitkey))
|
||||
errx(1, "Invalid commit key '%s'", argv[2]);
|
||||
|
||||
if (!pubkey_from_hexstr(argv[3], &changekey))
|
||||
errx(1, "Invalid bitcoin pubkey '%s'", argv[3]);
|
||||
if (!pubkey_from_hexstr(argv[3], &finalkey))
|
||||
errx(1, "Invalid final key '%s'", argv[3]);
|
||||
|
||||
/* We don't really need the privkey here, but it's the most
|
||||
* convenient way to get the pubkey from bitcoind. */
|
||||
if (!key_from_base58(argv[4], strlen(argv[4]), &testnet,
|
||||
&commitprivkey, &commitkey))
|
||||
errx(1, "Invalid private key '%s'", argv[4]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[4]);
|
||||
|
||||
if (!key_from_base58(argv[5], strlen(argv[5]), &testnet,
|
||||
&outprivkey, &outkey))
|
||||
errx(1, "Invalid private key '%s'", argv[5]);
|
||||
if (!testnet)
|
||||
errx(1, "Private key '%s' not on testnet!", argv[5]);
|
||||
|
||||
anchor.n_inputs = (argc - 6);
|
||||
anchor.inputs = tal_arr(ctx, BitcoinInput *, anchor.n_inputs);
|
||||
|
||||
total_in = 0;
|
||||
for (i = 0; i < anchor.n_inputs; i++) {
|
||||
anchor.inputs[i] = parse_anchor_input(anchor.inputs, argv[i+6]);
|
||||
total_in += anchor.inputs[i]->amount;
|
||||
}
|
||||
|
||||
if (total_in < anchor.total + anchor.fee)
|
||||
errx(1, "Only %llu satoshi in, and %llu out (+%llu fee)",
|
||||
(unsigned long long)total_in,
|
||||
(unsigned long long)anchor.total,
|
||||
(unsigned long long)anchor.fee);
|
||||
|
||||
/* If there's change, say where to send it. */
|
||||
if (total_in != anchor.total + anchor.fee) {
|
||||
anchor.change = tal(ctx, Change);
|
||||
change__init(anchor.change);
|
||||
anchor.change->pubkey = pubkey_to_proto(anchor.change,
|
||||
&changekey);
|
||||
anchor.change->amount = total_in - (anchor.total + anchor.fee);
|
||||
}
|
||||
if (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 = openchannel_pkt(ctx, &revocation_hash, &commitkey, &outkey,
|
||||
commit_tx_fee, locktime_seconds, &anchor);
|
||||
pkt = open_channel_pkt(ctx, &revocation_hash, &commitkey, &finalkey,
|
||||
locktime_seconds, offer_anchor, min_confirms);
|
||||
|
||||
if (!write_all(STDOUT_FILENO, pkt, pkt_totlen(pkt)))
|
||||
err(1, "Writing out packet");
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -16,62 +15,55 @@
|
||||
#include "bitcoin/pubkey.h"
|
||||
#include "bitcoin/privkey.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "funding.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
OpenChannel *o1, *o2;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *commit;
|
||||
struct pkt *pkt;
|
||||
struct signature sig;
|
||||
size_t *inmap, *outmap;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *subscript;
|
||||
struct sha256 rhash;
|
||||
uint64_t to_them, to_us;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<open-channel-file1> <open-channel-file2> <commit-privkey>\n"
|
||||
"<open-channel-file1> <open-channel-file2> <open-anchor-file1> <commit-privkey>\n"
|
||||
"Create the signature needed for the commit transaction",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc != 4)
|
||||
opt_usage_exit_fail("Expected 3 arguments");
|
||||
if (argc != 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 (!key_from_base58(argv[3], strlen(argv[3]), &testnet, &privkey, &pubkey1))
|
||||
errx(1, "Invalid private key '%s'", argv[3]);
|
||||
a = pkt_from_file(argv[3], PKT__PKT_OPEN_ANCHOR)->open_anchor;
|
||||
|
||||
if (!key_from_base58(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[3]);
|
||||
|
||||
/* Create merged anchor transaction */
|
||||
anchor = anchor_tx_create(ctx, o1, o2, &inmap, &outmap);
|
||||
if (!anchor)
|
||||
errx(1, "Failed transaction merge");
|
||||
|
||||
/* Get the transaction ID of the anchor. */
|
||||
anchor_txid(anchor, &txid);
|
||||
errx(1, "Private key '%s' not on testnet!", argv[4]);
|
||||
|
||||
/* Now create THEIR commitment tx to spend 2/2 output of anchor. */
|
||||
if (!initial_funding(o1, o2, a, &to_us, &to_them))
|
||||
errx(1, "Invalid open combination (need 1 anchor offer)");
|
||||
|
||||
proto_to_sha256(o2->revocation_hash, &rhash);
|
||||
commit = create_commit_tx(ctx, o2, o1, &rhash, 0, &txid, outmap[0]);
|
||||
commit = create_commit_tx(ctx, o2, o1, a, &rhash, to_them, to_us);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
if (!commit)
|
||||
errx(1, "Contributions %llu & %llu vs fees %llu & %llu",
|
||||
(long long)o1->anchor->total,
|
||||
(long long)o2->anchor->total,
|
||||
(long long)o1->commitment_fee,
|
||||
(long long)o2->commitment_fee);
|
||||
errx(1, "Invalid packets?");
|
||||
|
||||
/* Their pubkey must be valid */
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
|
||||
@@ -8,10 +8,6 @@ set -e
|
||||
|
||||
. `dirname $0`/vars.sh
|
||||
|
||||
if [ n"$1" = n--privkey ]; then
|
||||
KEY=1
|
||||
shift
|
||||
fi
|
||||
NUM=1
|
||||
if [ $# = 1 ]; then
|
||||
NUM=$1
|
||||
@@ -19,18 +15,15 @@ if [ $# = 1 ]; then
|
||||
fi
|
||||
|
||||
if [ $# -gt 0 ]; then
|
||||
echo "Usage: getinput.sh [--privkey] [INPUT-INDEX]"
|
||||
echo "Usage: getinput.sh [INPUT-INDEX]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$KEY" ]; then
|
||||
ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
$CLI dumpprivkey $ADDR
|
||||
else
|
||||
TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1`
|
||||
AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'`
|
||||
SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
TXID=`$CLI listunspent | sed -n 's/^ *"txid" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
OUTNUM=`$CLI listunspent | sed -n 's/^ *"vout" *: *\([0-9]*\),$/\1/p' | tail -n +$NUM | head -n1`
|
||||
AMOUNT=`$CLI listunspent | sed -n 's/^ *"amount" *: *\([0-9.]*\),$/\1/p' | tail -n +$NUM | head -n1 | tr -d . | sed 's/^0*//'`
|
||||
SCRIPT=`$CLI listunspent | sed -n 's/^ *"scriptPubKey" *: *"\([0-9a-f]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
ADDR=`$CLI listunspent | sed -n 's/^ *"address" *: *"\([0-9a-zA-Z]*\)",$/\1/p' | tail -n +$NUM | head -n1`
|
||||
PRIVKEY=`$CLI dumpprivkey $ADDR`
|
||||
|
||||
echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT
|
||||
fi
|
||||
echo $TXID/$OUTNUM/$AMOUNT/$SCRIPT/$PRIVKEY
|
||||
|
||||
@@ -24,11 +24,10 @@ done
|
||||
scripts/generate-block.sh init
|
||||
|
||||
A1=`scripts/get-new-address.sh`
|
||||
A2=`scripts/get-new-address.sh`
|
||||
TX=`$CLI sendmany "" "{ \"$A1\":10, \"$A2\":10 }"`
|
||||
TX=`$CLI sendmany "" "{ \"$A1\":10 }"`
|
||||
scripts/generate-block.sh
|
||||
|
||||
# Find the inputs numbers corresponding to those 10 btc outs
|
||||
echo "Arguments to test.sh:"
|
||||
# Find the inputs number corresponding to that 10 btc out
|
||||
echo "Argument to test.sh:"
|
||||
for i in $(seq 1 $($CLI listunspent | grep -c txid) ); do scripts/getinput.sh $i | grep -q "$TX.*/1000000000/" && echo -n "$i "; done
|
||||
echo
|
||||
|
||||
@@ -36,18 +36,16 @@ send_after_delay()
|
||||
$CLI sendrawtransaction $1
|
||||
}
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo Usage: "INPUT1" "INPUT2" "[--steal|--unilateral]" >&2
|
||||
if [ $# = 0 ]; then
|
||||
echo Usage: "INPUT" "[--steal|--unilateral]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
A_INPUTNUM=$1
|
||||
B_INPUTNUM=$2
|
||||
shift 2
|
||||
shift
|
||||
#A_INPUTNUM=4
|
||||
#B_INPUTNUM=1
|
||||
A_AMOUNT=100000000
|
||||
B_AMOUNT=200000000
|
||||
|
||||
A_CHANGEADDR=`scripts/get-new-address.sh`
|
||||
A_TMPADDR=`scripts/get-new-address.sh`
|
||||
@@ -66,79 +64,104 @@ B_FINALADDR=`scripts/get-new-address.sh`
|
||||
#B_FINALADDR=mvQgfEX4iMSEYqD31524jASQviPwPwpvuv
|
||||
|
||||
A_TXIN=`scripts/getinput.sh $A_INPUTNUM`
|
||||
A_TXINKEY=`scripts/getinput.sh --privkey $A_INPUTNUM`
|
||||
B_TXIN=`scripts/getinput.sh $B_INPUTNUM`
|
||||
B_TXINKEY=`scripts/getinput.sh --privkey $B_INPUTNUM`
|
||||
|
||||
A_SEED=00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff
|
||||
B_SEED=112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00
|
||||
|
||||
A_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_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
|
||||
$PREFIX ./open-channel $A_SEED $A_AMOUNT $A_CHANGEPUBKEY $A_TMPKEY $A_FINALKEY $A_TXIN > A-open.pb
|
||||
# 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=60 $B_SEED $B_AMOUNT $B_CHANGEPUBKEY $B_TMPKEY $B_FINALKEY $B_TXIN > B-open.pb
|
||||
$PREFIX ./open-channel --locktime=60 $B_SEED $B_TMPPUBKEY $B_FINALPUBKEY > B-open.pb
|
||||
|
||||
# Now sign anchor.
|
||||
$PREFIX ./open-anchor-scriptsigs A-open.pb B-open.pb $A_TXINKEY > A-anchor-scriptsigs.pb
|
||||
$PREFIX ./open-anchor-scriptsigs B-open.pb A-open.pb $B_TXINKEY > B-anchor-scriptsigs.pb
|
||||
# Now 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 create commit signature
|
||||
$PREFIX ./open-commit-sig A-open.pb B-open.pb $A_TMPKEY > A-commit-sig.pb
|
||||
# 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
|
||||
|
||||
$PREFIX ./open-commit-sig B-open.pb A-open.pb $B_TMPKEY > B-commit-sig.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 it.
|
||||
$PREFIX ./check-commit-sig A-open.pb B-open.pb B-commit-sig.pb $A_TMPKEY > A-commit.tx
|
||||
$PREFIX ./check-commit-sig B-open.pb A-open.pb A-commit-sig.pb $B_TMPKEY > B-commit.tx
|
||||
# Now check 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
|
||||
|
||||
# Now check anchor sigs and make sure they're the same.
|
||||
$PREFIX ./check-anchor-scriptsigs A-open.pb B-open.pb A-anchor-scriptsigs.pb B-anchor-scriptsigs.pb > A-anchor.tx
|
||||
$PREFIX ./check-anchor-scriptsigs B-open.pb A-open.pb B-anchor-scriptsigs.pb A-anchor-scriptsigs.pb > B-anchor.tx
|
||||
cmp A-anchor.tx B-anchor.tx
|
||||
# A broadcasts anchor
|
||||
$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > A-anchor.txid
|
||||
|
||||
# Broadcast
|
||||
$CLI sendrawtransaction `cut -d: -f1 A-anchor.tx` > 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
|
||||
|
||||
# # Wait for confirms
|
||||
# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth A-open.pb) ]; do scripts/generate-block.sh; done
|
||||
while [ 0$($CLI getrawtransaction $(cat 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
|
||||
|
||||
# while [ 0$($CLI getrawtransaction $(cat anchor.txid) 1 | sed -n 's/.*"confirmations" : \([0-9]*\),/\1/p') -lt $($PREFIX ./get-anchor-depth B-open.pb) ]; do scripts/generate-block.sh; done
|
||||
# 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 transaction.
|
||||
$PREFIX ./create-commit-tx A-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-commit-sig.pb > A-commit-0.tx
|
||||
# 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 500 satoshi.
|
||||
$PREFIX ./update-channel --to-them=500 $A_SEED > A-update-1.pb
|
||||
$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb > B-update-accept-1.pb
|
||||
$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb B-update-accept-1.pb > A-update-sig-1.pb
|
||||
$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-1.pb A-update-sig-1.pb > B-update-complete-1.pb
|
||||
$PREFIX ./update-channel --to-them=500 $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-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-1.pb A-update-1.pb > A-commit-1.tx
|
||||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.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 1000.
|
||||
$PREFIX ./update-channel --from-them=1000 $A_SEED A-update-1.pb > A-update-2.pb
|
||||
$PREFIX ./update-channel-accept $B_SEED B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-2.pb A-update-1.pb > B-update-accept-2.pb 2>/dev/null
|
||||
$PREFIX ./update-channel-signature $A_SEED A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-2.pb B-update-accept-2.pb A-update-1.pb > A-update-sig-2.pb
|
||||
$PREFIX ./update-channel-complete $B_SEED B-anchor.tx B-open.pb A-open.pb A-update-2.pb A-update-sig-2.pb A-update-1.pb > B-update-complete-2.pb
|
||||
# Now you pay me 250.
|
||||
$PREFIX ./update-channel --to-them=250 $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-anchor.tx A-open.pb B-open.pb $A_TMPKEY B-update-accept-2.pb A-update-1.pb A-update-2.pb > A-commit-2.tx
|
||||
$PREFIX ./create-commit-tx A-open.pb B-open.pb A-anchor.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
|
||||
|
||||
if [ x"$1" = x--steal ]; then
|
||||
# A stupidly broadcasts a revoked transaction.
|
||||
$CLI sendrawtransaction `cut -d: -f1 A-commit-1.tx` > A-commit-1.txid
|
||||
|
||||
# B uses the preimage from A-update-sig-2 to cash in.
|
||||
$PREFIX ./create-steal-tx A-commit-1.tx A-update-sig-2.pb $B_FINALKEY B-open.pb A-open.pb $B_CHANGEPUBKEY > B-commit-steal.tx
|
||||
# B uses the preimage from A-update-complete-2 to cash in.
|
||||
$PREFIX ./create-steal-tx A-commit-1.tx A-update-complete-2.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
|
||||
exit 0
|
||||
@@ -146,14 +169,14 @@ fi
|
||||
|
||||
if [ x"$1" = x--unilateral ]; then
|
||||
$CLI sendrawtransaction `cut -d: -f1 A-commit-2.tx` > A-commit-2.txid
|
||||
$PREFIX ./create-commit-spend-tx A-commit-2.tx A-open.pb B-open.pb $A_FINALKEY $A_CHANGEPUBKEY A-update-1.pb A-update-2.pb > A-spend.tx
|
||||
$PREFIX ./create-commit-spend-tx A-commit-2.tx A-open.pb B-open.pb A-anchor.pb $A_FINALKEY $A_CHANGEPUBKEY $A_UPDATE_PKTS > A-spend.tx
|
||||
send_after_delay `cut -d: -f1 A-spend.tx` > A-spend.txid
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Now close channel by mutual consent.
|
||||
$PREFIX ./close-channel A-anchor.tx A-open.pb B-open.pb $A_TMPKEY A-update-1.pb A-update-2.pb > A-close.pb
|
||||
$PREFIX ./close-channel --complete B-anchor.tx B-open.pb A-open.pb $B_TMPKEY A-update-1.pb A-update-2.pb > B-close-complete.pb
|
||||
$PREFIX ./create-close-tx A-anchor.tx A-open.pb B-open.pb A-close.pb B-close-complete.pb A-update-1.pb A-update-2.pb > A-close.tx
|
||||
$PREFIX ./close-channel A-open.pb B-open.pb A-anchor.pb $A_TMPKEY $A_UPDATE_PKTS > A-close.pb
|
||||
$PREFIX ./close-channel --complete 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
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -17,6 +16,7 @@
|
||||
#include "bitcoin/privkey.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "gather_updates.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -24,54 +24,48 @@ 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;
|
||||
Update *update;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double anchor_txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *commit;
|
||||
struct pkt *pkt;
|
||||
struct bitcoin_signature sig;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
uint64_t num_updates;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
int64_t delta;
|
||||
size_t i, p2sh_out;
|
||||
uint64_t our_amount, their_amount;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> [previous-updates]\n"
|
||||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-updates...>\n"
|
||||
"Accept a new update message",
|
||||
"Print this message.");
|
||||
|
||||
opt_parse(&argc, argv, opt_log_stderr_exit);
|
||||
|
||||
if (argc < 6)
|
||||
opt_usage_exit_fail("Expected 5+ arguments");
|
||||
if (argc < 7)
|
||||
opt_usage_exit_fail("Expected 6+ arguments");
|
||||
|
||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[2]);
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
|
||||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
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(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]);
|
||||
|
||||
update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update;
|
||||
|
||||
/* Figure out cumulative delta since anchor. */
|
||||
delta = update->delta;
|
||||
for (i = 7; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
}
|
||||
num_updates = gather_updates(o1, o2, a, argv + 6,
|
||||
&our_amount, &their_amount,
|
||||
NULL, &their_rhash, NULL);
|
||||
|
||||
/* Get next revocation hash. */
|
||||
shachain_from_seed(&seed, argc - 6, &revocation_hash);
|
||||
shachain_from_seed(&seed, num_updates, &revocation_hash);
|
||||
sha256(&revocation_hash,
|
||||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
|
||||
|
||||
@@ -86,12 +80,10 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* This is what the anchor pays to; figure out whick output. */
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
||||
|
||||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
|
||||
proto_to_sha256(update->revocation_hash, &their_rhash);
|
||||
commit = create_commit_tx(ctx, o2, o1, &their_rhash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
commit = create_commit_tx(ctx, o2, o1, a, &their_rhash,
|
||||
their_amount, our_amount);
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
if (!commit)
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include <ccan/structeq/structeq.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -17,28 +16,28 @@
|
||||
#include "bitcoin/pubkey.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "gather_updates.h"
|
||||
#include "funding.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct sha256 seed, revocation_hash, our_rhash, their_rhash, preimage;
|
||||
struct sha256 seed, our_rhash, their_rhash, preimage;
|
||||
OpenChannel *o1, *o2;
|
||||
UpdateSignature *us;
|
||||
Update *update;
|
||||
OpenAnchor *a;
|
||||
struct pkt *pkt;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct bitcoin_tx *commit;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
size_t i, num_updates, p2sh_out;
|
||||
struct sha256_double anchor_txid;
|
||||
size_t num_updates;
|
||||
struct bitcoin_signature sig;
|
||||
int64_t delta;
|
||||
uint64_t our_amount, their_amount;
|
||||
u8 *redeemscript;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <update-protobuf> <update-signature-protobuf> [previous-updates]\n"
|
||||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <all-previous-updates>\n"
|
||||
"Create a new update-complete message",
|
||||
"Print this message.");
|
||||
|
||||
@@ -50,43 +49,18 @@ int main(int argc, char *argv[])
|
||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[2]);
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
|
||||
update = pkt_from_file(argv[5], PKT__PKT_UPDATE)->update;
|
||||
us = pkt_from_file(argv[6], PKT__PKT_UPDATE_SIGNATURE)->update_signature;
|
||||
|
||||
/* We need last revocation hash (either in update or update-accept),
|
||||
* and the delta */
|
||||
proto_to_sha256(o2->revocation_hash, &revocation_hash);
|
||||
num_updates = 0;
|
||||
delta = update->delta;
|
||||
for (i = 7; i < argc; i++) {
|
||||
Pkt *p = any_pkt_from_file(argv[i]);
|
||||
switch (p->pkt_case) {
|
||||
case PKT__PKT_UPDATE:
|
||||
proto_to_sha256(p->update->revocation_hash,
|
||||
&revocation_hash);
|
||||
delta += p->update->delta;
|
||||
num_updates++;
|
||||
break;
|
||||
case PKT__PKT_UPDATE_ACCEPT:
|
||||
if (i != argc - 1)
|
||||
errx(1, "Only need last update_accept");
|
||||
proto_to_sha256(p->update_accept->revocation_hash,
|
||||
&revocation_hash);
|
||||
break;
|
||||
default:
|
||||
errx(1, "Expected update/update-accept in %s", argv[i]);
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* They gave us right preimage to match rhash of previous commit tx? */
|
||||
proto_to_sha256(us->revocation_preimage, &preimage);
|
||||
sha256(&their_rhash, preimage.u.u8, sizeof(preimage.u.u8));
|
||||
if (!structeq(&their_rhash, &revocation_hash))
|
||||
errx(1, "Their preimage was incorrect");
|
||||
sig.stype = SIGHASH_ALL;
|
||||
|
||||
/* This also checks that preimage is correct! */
|
||||
num_updates = gather_updates(o1, o2, a, argv + 5,
|
||||
&our_amount, &their_amount,
|
||||
&our_rhash, &their_rhash, &sig.sig);
|
||||
if (num_updates < 1)
|
||||
errx(1, "Expected at least one update!");
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey1))
|
||||
@@ -94,28 +68,21 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
||||
/* This is what the anchor pays to; figure out whick output. */
|
||||
/* This is what the anchor pays to. */
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
||||
|
||||
/* Check their signature signs our new commit tx correctly. */
|
||||
shachain_from_seed(&seed, num_updates + 1, &preimage);
|
||||
sha256(&our_rhash, &preimage, sizeof(preimage));
|
||||
commit = create_commit_tx(ctx, o1, o2, &our_rhash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
commit = create_commit_tx(ctx, o1, o2, a, &our_rhash,
|
||||
our_amount, their_amount);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(us->sig, &sig.sig))
|
||||
errx(1, "Invalid update-signature signature");
|
||||
|
||||
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||
&pubkey2, &sig))
|
||||
errx(1, "Invalid signature.");
|
||||
|
||||
/* Hand over our preimage for previous tx. */
|
||||
shachain_from_seed(&seed, num_updates, &preimage);
|
||||
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");
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -17,30 +16,29 @@
|
||||
#include "bitcoin/privkey.h"
|
||||
#include "find_p2sh_out.h"
|
||||
#include "protobuf_convert.h"
|
||||
#include "gather_updates.h"
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const tal_t *ctx = tal_arr(NULL, char, 0);
|
||||
struct sha256 seed, revocation_hash, preimage;
|
||||
struct sha256 seed, preimage, our_rhash, their_rhash;
|
||||
OpenChannel *o1, *o2;
|
||||
UpdateAccept *ua;
|
||||
Update *update;
|
||||
struct bitcoin_tx *anchor, *commit;
|
||||
struct sha256_double anchor_txid;
|
||||
OpenAnchor *a;
|
||||
struct bitcoin_tx *commit;
|
||||
struct pkt *pkt;
|
||||
struct bitcoin_signature sig;
|
||||
struct privkey privkey;
|
||||
bool testnet;
|
||||
struct pubkey pubkey1, pubkey2;
|
||||
u8 *redeemscript;
|
||||
int64_t delta;
|
||||
size_t i, p2sh_out;
|
||||
uint64_t our_amount, their_amount;
|
||||
uint64_t num_updates;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
opt_register_noarg("--help|-h", opt_usage_and_exit,
|
||||
"<seed> <anchor-tx> <open-channel-file1> <open-channel-file2> <commit-privkey> <update-protobuf> <update-accept-protobuf> [previous-updates]...\n"
|
||||
"<seed> <open-channel-file1> <open-channel-file2> <open-anchor-file> <commit-privkey> <all-previous-updates>...\n"
|
||||
"Create a new update-channel-signature message",
|
||||
"Print this message.");
|
||||
|
||||
@@ -52,32 +50,27 @@ int main(int argc, char *argv[])
|
||||
if (!hex_decode(argv[1], strlen(argv[1]), &seed, sizeof(seed)))
|
||||
errx(1, "Invalid seed '%s' - need 256 hex bits", argv[1]);
|
||||
|
||||
anchor = bitcoin_tx_from_file(ctx, argv[2]);
|
||||
bitcoin_txid(anchor, &anchor_txid);
|
||||
o1 = pkt_from_file(argv[3], PKT__PKT_OPEN)->open;
|
||||
o2 = pkt_from_file(argv[4], PKT__PKT_OPEN)->open;
|
||||
o1 = pkt_from_file(argv[2], PKT__PKT_OPEN)->open;
|
||||
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(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]);
|
||||
|
||||
update = pkt_from_file(argv[6], PKT__PKT_UPDATE)->update;
|
||||
ua = pkt_from_file(argv[7], PKT__PKT_UPDATE_ACCEPT)->update_accept;
|
||||
|
||||
sig.stype = SIGHASH_ALL;
|
||||
if (!proto_to_signature(ua->sig, &sig.sig))
|
||||
errx(1, "Invalid update signature");
|
||||
|
||||
/* Figure out cumulative delta since anchor. */
|
||||
delta = 0;
|
||||
for (i = 8; i < argc; i++) {
|
||||
Update *u = pkt_from_file(argv[i], PKT__PKT_UPDATE)->update;
|
||||
delta += u->delta;
|
||||
}
|
||||
num_updates = gather_updates(o1, o2, a, argv + 6,
|
||||
&our_amount, &their_amount,
|
||||
&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, argc - 7 - 1, &preimage);
|
||||
fprintf(stderr, "Giving up preimage %u\n", (unsigned)num_updates - 1);
|
||||
shachain_from_seed(&seed, num_updates - 1, &preimage);
|
||||
|
||||
/* Get pubkeys */
|
||||
if (!proto_to_pubkey(o1->commit_key, &pubkey2))
|
||||
@@ -88,16 +81,14 @@ int main(int argc, char *argv[])
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
errx(1, "Invalid o2 commit pubkey");
|
||||
|
||||
/* This is what the anchor pays to; figure out whick output. */
|
||||
/* This is what the anchor pays to. */
|
||||
redeemscript = bitcoin_redeem_2of2(ctx, &pubkey1, &pubkey2);
|
||||
p2sh_out = find_p2sh_out(anchor, redeemscript);
|
||||
|
||||
/* Check our new commit is signed correctly by them. */
|
||||
proto_to_sha256(update->revocation_hash, &revocation_hash);
|
||||
commit = create_commit_tx(ctx, o1, o2, &revocation_hash, delta,
|
||||
&anchor_txid, p2sh_out);
|
||||
commit = create_commit_tx(ctx, o1, o2, a, &our_rhash,
|
||||
our_amount, their_amount);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
errx(1, "Invalid packets");
|
||||
|
||||
/* Check their signature signs this input correctly. */
|
||||
if (!check_tx_sig(commit, 0, redeemscript, tal_count(redeemscript),
|
||||
@@ -105,14 +96,10 @@ int main(int argc, char *argv[])
|
||||
errx(1, "Invalid signature.");
|
||||
|
||||
/* Now create THEIR new commitment tx to spend 2/2 output of anchor. */
|
||||
proto_to_sha256(ua->revocation_hash, &revocation_hash);
|
||||
commit = create_commit_tx(ctx, o2, o1, &revocation_hash, -delta,
|
||||
&anchor_txid,
|
||||
find_p2sh_out(anchor, redeemscript));
|
||||
|
||||
/* If contributions don't exceed fees, this fails. */
|
||||
commit = create_commit_tx(ctx, o2, o1, a, &their_rhash,
|
||||
their_amount, our_amount);
|
||||
if (!commit)
|
||||
errx(1, "Delta too large");
|
||||
errx(1, "Invalid packets");
|
||||
|
||||
/* Their pubkey must be valid */
|
||||
if (!proto_to_pubkey(o2->commit_key, &pubkey2))
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/read_write_all/read_write_all.h>
|
||||
#include "lightning.pb-c.h"
|
||||
#include "anchor.h"
|
||||
#include "bitcoin/base58.h"
|
||||
#include "pkt.h"
|
||||
#include "bitcoin/script.h"
|
||||
@@ -24,11 +23,12 @@ int main(int argc, char *argv[])
|
||||
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> [previous-updates]\n"
|
||||
"<seed> <update-number>\n"
|
||||
"Create a new update message",
|
||||
"Print this message.");
|
||||
opt_register_arg("--to-them=<satoshi>",
|
||||
@@ -43,18 +43,21 @@ int main(int argc, char *argv[])
|
||||
if (!from_them && !to_them)
|
||||
opt_usage_exit_fail("Must use --to-them or --from-them");
|
||||
|
||||
if (argc < 2)
|
||||
opt_usage_exit_fail("Expected 1+ arguments");
|
||||
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, argc - 2 + 1, &revocation_hash);
|
||||
shachain_from_seed(&seed, update_num, &revocation_hash);
|
||||
sha256(&revocation_hash,
|
||||
revocation_hash.u.u8, sizeof(revocation_hash.u.u8));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user