mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-02-22 14:42:40 +01:00
Remove test-cli
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>
This commit is contained in:
parent
35ab923163
commit
09358498cd
29 changed files with 6 additions and 3391 deletions
47
Makefile
47
Makefile
|
@ -28,28 +28,6 @@ BITCOIN_FEATURES := \
|
|||
#FEATURES := $(ALPHA_FEATURES)
|
||||
FEATURES := $(BITCOIN_FEATURES)
|
||||
|
||||
TEST_CLI_PROGRAMS := \
|
||||
test-cli/check-commit-sig \
|
||||
test-cli/close-channel \
|
||||
test-cli/create-anchor-tx \
|
||||
test-cli/create-close-tx \
|
||||
test-cli/create-commit-spend-tx \
|
||||
test-cli/create-commit-tx \
|
||||
test-cli/create-htlc-spend-tx \
|
||||
test-cli/create-steal-tx \
|
||||
test-cli/get-anchor-depth \
|
||||
test-cli/open-anchor \
|
||||
test-cli/open-channel \
|
||||
test-cli/open-commit-sig \
|
||||
test-cli/txid-of \
|
||||
test-cli/update-channel \
|
||||
test-cli/update-channel-accept \
|
||||
test-cli/update-channel-complete \
|
||||
test-cli/update-channel-htlc \
|
||||
test-cli/update-channel-htlc-complete \
|
||||
test-cli/update-channel-htlc-remove \
|
||||
test-cli/update-channel-signature
|
||||
|
||||
TEST_PROGRAMS := \
|
||||
test/test_state_coverage \
|
||||
test/onion_key \
|
||||
|
@ -78,9 +56,6 @@ CORE_SRC := \
|
|||
version.c
|
||||
CORE_OBJS := $(CORE_SRC:.c=.o)
|
||||
|
||||
TEST_CLI_SRC := test-cli/gather_updates.c test-cli/pkt.c test-cli/tx_from_file.c
|
||||
TEST_CLI_OBJS := $(TEST_CLI_SRC:.c=.o)
|
||||
|
||||
CCAN_OBJS := \
|
||||
ccan-crypto-ripemd160.o \
|
||||
ccan-crypto-sha256.o \
|
||||
|
@ -165,10 +140,6 @@ CCAN_HEADERS := \
|
|||
$(CCANDIR)/ccan/timer/timer.h \
|
||||
$(CCANDIR)/ccan/typesafe_cb/typesafe_cb.h
|
||||
|
||||
TEST_CLI_HEADERS := test-cli/gather_updates.h \
|
||||
test-cli/pkt.h \
|
||||
test-cli/tx_from_file.h
|
||||
|
||||
BITCOIN_HEADERS := bitcoin/address.h \
|
||||
bitcoin/base58.h \
|
||||
bitcoin/locktime.h \
|
||||
|
@ -198,7 +169,7 @@ GEN_HEADERS := gen_state_names.h \
|
|||
|
||||
CDUMP_OBJS := ccan-cdump.o ccan-strmap.o
|
||||
|
||||
PROGRAMS := $(TEST_CLI_PROGRAMS) $(TEST_PROGRAMS)
|
||||
PROGRAMS := $(TEST_PROGRAMS)
|
||||
|
||||
CWARNFLAGS := -Werror -Wall -Wundef -Wmissing-prototypes -Wmissing-declarations -Wstrict-prototypes -Wold-style-definition
|
||||
CDEBUGFLAGS := -g -fstack-protector
|
||||
|
@ -210,19 +181,15 @@ $(PROGRAMS): CFLAGS+=-I.
|
|||
default: $(PROGRAMS) daemon-all
|
||||
|
||||
# Everything depends on the CCAN headers.
|
||||
$(CCAN_OBJS) $(CDUMP_OBJS) $(HELPER_OBJS) $(BITCOIN_OBJS) $(TEST_CLI_PROGRAMS:=.o) $(TEST_PROGRAMS:=.o): $(CCAN_HEADERS)
|
||||
$(CCAN_OBJS) $(CDUMP_OBJS) $(HELPER_OBJS) $(BITCOIN_OBJS) $(TEST_PROGRAMS:=.o): $(CCAN_HEADERS)
|
||||
|
||||
# Except for CCAN, everything depends on bitcoin/ and core headers.
|
||||
$(HELPER_OBJS) $(BITCOIN_OBJS) $(TEST_CLI_PROGRAMS:=.o) $(TEST_PROGRAMS:=.o): $(BITCOIN_HEADERS) $(CORE_HEADERS) $(GEN_HEADERS)
|
||||
|
||||
# Test-cli utils depends on CLI headers too.
|
||||
$(TEST_CLI_PROGRAMS:=.o): $(TEST_CLI_HEADERS)
|
||||
$(HELPER_OBJS) $(BITCOIN_OBJS) $(TEST_PROGRAMS:=.o): $(BITCOIN_HEADERS) $(CORE_HEADERS) $(GEN_HEADERS)
|
||||
|
||||
# These don't work in parallel, so we open-code them
|
||||
test-cli-tests: $(TEST_CLI_PROGRAMS) daemon-all
|
||||
daemon-tests: daemon-all
|
||||
cd test-cli; scripts/shutdown.sh 2>/dev/null || true
|
||||
set -e; for arg in "" "--timeout-anchor"; do daemon/test/test.sh $$arg; done
|
||||
set -e; cd test-cli; for args in "" --steal --unilateral --htlc-onchain; do scripts/setup.sh && scripts/test.sh $$args && scripts/shutdown.sh; done
|
||||
|
||||
test-onion: test/test_onion test/onion_key
|
||||
set -e; TMPF=/tmp/onion.$$$$; test/test_onion --generate $$(test/onion_key --pub `seq 20`) > $$TMPF; for k in `seq 20`; do test/test_onion --decode $$(test/onion_key --priv $$k) < $$TMPF > $$TMPF.unwrap; mv $$TMPF.unwrap $$TMPF; done; rm -f $$TMPF
|
||||
|
@ -236,7 +203,7 @@ test-onion3: test/test_onion test/onion_key
|
|||
test-onion4: test/test_onion test/onion_key
|
||||
set -e; TMPF=/tmp/onion.$$$$; python test/test_onion.py generate $$(test/onion_key --pub `seq 20`) > $$TMPF; for k in `seq 20`; do python test/test_onion.py decode $$(test/onion_key --priv $$k) $$(test/onion_key --pub $$k) < $$TMPF > $$TMPF.unwrap; mv $$TMPF.unwrap $$TMPF; done; rm -f $$TMPF
|
||||
|
||||
check: test-cli-tests test-onion
|
||||
check: daemon-tests test-onion
|
||||
|
||||
# Keep includes in alpha order.
|
||||
check-src-include-order/%: %
|
||||
|
@ -250,7 +217,6 @@ check-hdr-include-order/%: %
|
|||
# Make sure Makefile includes all headers.
|
||||
check-makefile: check-daemon-makefile
|
||||
@if [ "`echo bitcoin/*.h`" != "$(BITCOIN_HEADERS)" ]; then echo BITCOIN_HEADERS incorrect; exit 1; fi
|
||||
@if [ "`echo test-cli/*.h`" != "$(TEST_CLI_HEADERS)" ]; then echo TEST_CLI_HEADERS incorrect; exit 1; fi
|
||||
@if [ x"`ls *.h | grep -v ^gen_ | fgrep -v lightning.pb-c.h | tr '\n' ' '`" != x"$(CORE_HEADERS) " ]; then echo CORE_HEADERS incorrect; exit 1; fi
|
||||
@if [ x"$(CCANDIR)/config.h `find $(CCANDIR)/ccan -name '*.h' | grep -v /test/ | LC_ALL=C sort | tr '\n' ' '`" != x"$(CCAN_HEADERS) " ]; then echo CCAN_HEADERS incorrect; exit 1; fi
|
||||
|
||||
|
@ -283,7 +249,6 @@ secp256k1/libsecp256k1.la:
|
|||
lightning.pb-c.c lightning.pb-c.h: lightning.proto
|
||||
$(PROTOCC) lightning.proto --c_out=.
|
||||
|
||||
$(TEST_CLI_PROGRAMS): % : %.o $(CORE_OBJS) $(BITCOIN_OBJS) $(CCAN_OBJS) $(TEST_CLI_OBJS) libsecp256k1.a
|
||||
$(TEST_PROGRAMS): % : %.o $(BITCOIN_OBJS) $(CCAN_OBJS) version.o libsecp256k1.a
|
||||
|
||||
ccan/config.h: ccan/tools/configurator/configurator
|
||||
|
@ -341,7 +306,7 @@ maintainter-clean: distclean
|
|||
clean: daemon-clean
|
||||
$(MAKE) -C secp256k1/ clean || true
|
||||
$(RM) libsecp256k1.{a,la}
|
||||
$(RM) $(PROGRAMS) test-cli/leak-anchor-sigs
|
||||
$(RM) $(PROGRAMS)
|
||||
$(RM) bitcoin/*.o *.o $(PROGRAMS:=.o) $(CCAN_OBJS)
|
||||
$(RM) doc/deployable-lightning.{aux,bbl,blg,dvi,log,out,tex}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
255
test-cli/pkt.c
255
test-cli/pkt.c
|
@ -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);
|
||||
}
|
174
test-cli/pkt.h
174
test-cli/pkt.h
|
@ -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…
Add table
Reference in a new issue