mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
devtools/mkclose: make a mutual close transaction.
Guess who's been writing gossip protocol tests? Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
c9817b225b
commit
9dd314226d
@ -1,6 +1,6 @@
|
||||
DEVTOOLS_SRC := devtools/gen_print_wire.c devtools/gen_print_onion_wire.c devtools/print_wire.c
|
||||
DEVTOOLS_OBJS := $(DEVTOOLS_SRC:.c=.o)
|
||||
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding
|
||||
DEVTOOLS := devtools/bolt11-cli devtools/decodemsg devtools/onion devtools/dump-gossipstore devtools/gossipwith devtools/create-gossipstore devtools/mkcommit devtools/mkfunding devtools/mkclose
|
||||
DEVTOOLS_TOOL_SRC := $(DEVTOOLS:=.c)
|
||||
DEVTOOLS_TOOL_OBJS := $(DEVTOOLS_TOOL_SRC:.c=.o)
|
||||
|
||||
@ -66,6 +66,8 @@ devtools/mkcommit: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) common/d
|
||||
|
||||
devtools/mkfunding: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o common/funding_tx.o common/utxo.o common/permute_tx.o common/key_derive.o devtools/mkfunding.o
|
||||
|
||||
devtools/mkclose: $(DEVTOOLS_COMMON_OBJS) $(CCAN_OBJS) $(BITCOIN_OBJS) wire/fromwire.o wire/towire.o wire/tlvstream.o devtools/mkclose.o
|
||||
|
||||
# Make sure these depend on everything.
|
||||
ALL_PROGRAMS += $(DEVTOOLS)
|
||||
ALL_OBJS += $(DEVTOOLS_OBJS) $(DEVTOOLS_TOOL_OBJS)
|
||||
|
188
devtools/mkclose.c
Normal file
188
devtools/mkclose.c
Normal file
@ -0,0 +1,188 @@
|
||||
/* Code to make a mutual close tx, useful for generating test cases.
|
||||
*
|
||||
* For example, in the spec tests we use the following:
|
||||
*
|
||||
* lightning/devtools/mkclose 189c40b0728f382fe91c87270926584e48e0af3a6789f37454afee6c7560311d 0 0.00999877btc 253 0.00999877btc 0000000000000000000000000000000000000000000000000000000000000010 0000000000000000000000000000000000000000000000000000000000000020 026957e53b46df017bd6460681d068e1d23a7b027de398272d0b15f59b78d060a9 03a9f795ff2e4c27091f40e8f8277301824d1c3dfa6b0204aa92347314e41b1033
|
||||
*/
|
||||
#include <bitcoin/script.h>
|
||||
#include <bitcoin/tx.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <channeld/full_channel.h>
|
||||
#include <common/amount.h>
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/htlc_wire.h>
|
||||
#include <common/initial_commit_tx.h>
|
||||
#include <common/key_derive.h>
|
||||
#include <common/keyset.h>
|
||||
#include <common/status.h>
|
||||
#include <common/type_to_string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool verbose = false;
|
||||
|
||||
void status_fmt(enum log_level level, const char *fmt, ...)
|
||||
{
|
||||
if (verbose) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
printf("#TRACE: ");
|
||||
vprintf(fmt, ap);
|
||||
printf("\n");
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void status_failed(enum status_failreason reason, const char *fmt, ...)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
static char *sig_as_hex(const struct bitcoin_signature *sig)
|
||||
{
|
||||
u8 compact_sig[64];
|
||||
|
||||
secp256k1_ecdsa_signature_serialize_compact(secp256k1_ctx,
|
||||
compact_sig,
|
||||
&sig->s);
|
||||
return tal_hexstr(NULL, compact_sig, sizeof(compact_sig));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct pubkey funding_pubkey[NUM_SIDES], outkey[NUM_SIDES];
|
||||
struct privkey funding_privkey[NUM_SIDES];
|
||||
struct amount_sat funding_amount;
|
||||
struct bitcoin_txid funding_txid;
|
||||
unsigned int funding_outnum;
|
||||
u32 feerate_per_kw;
|
||||
struct amount_sat fee;
|
||||
struct bitcoin_signature local_sig, remote_sig;
|
||||
struct amount_msat local_msat, remote_msat;
|
||||
int argnum, num_outputs;
|
||||
struct bitcoin_tx *tx;
|
||||
u8 **witness;
|
||||
const u8 *funding_wscript;
|
||||
const struct chainparams *chainparams = chainparams_for_network("bitcoin");
|
||||
const struct amount_sat dust_limit = AMOUNT_SAT(546);
|
||||
|
||||
setup_locale();
|
||||
|
||||
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY |
|
||||
SECP256K1_CONTEXT_SIGN);
|
||||
|
||||
if (argv[1] && streq(argv[1], "-v")) {
|
||||
verbose = true;
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (argc != 10)
|
||||
errx(1, "Usage: mkclose [-v] <funding-txid> <funding-txout> <funding-amount> <feerate-per-kw> <local-msat> <local-funding-privkey> <remote-funding-privkey> <local-close-pubkey> <remote-close-pubkey>\n"
|
||||
"(Fee is deducted from local-msat)");
|
||||
|
||||
argnum = 1;
|
||||
if (!bitcoin_txid_from_hex(argv[argnum],
|
||||
strlen(argv[argnum]), &funding_txid))
|
||||
errx(1, "Bad funding-txid");
|
||||
argnum++;
|
||||
funding_outnum = atoi(argv[argnum++]);
|
||||
if (!parse_amount_sat(&funding_amount, argv[argnum], strlen(argv[argnum])))
|
||||
errx(1, "Bad funding-amount");
|
||||
argnum++;
|
||||
feerate_per_kw = atoi(argv[argnum++]);
|
||||
if (!parse_amount_msat(&local_msat,
|
||||
argv[argnum], strlen(argv[argnum])))
|
||||
errx(1, "Bad local-msat");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&funding_privkey[LOCAL], sizeof(funding_privkey[LOCAL])))
|
||||
errx(1, "Parsing local-funding_privkey");
|
||||
argnum++;
|
||||
if (!hex_decode(argv[argnum], strlen(argv[argnum]),
|
||||
&funding_privkey[REMOTE], sizeof(funding_privkey[REMOTE])))
|
||||
errx(1, "Parsing remote-funding_privkey");
|
||||
argnum++;
|
||||
if (!pubkey_from_hexstr(argv[argnum], strlen(argv[argnum]),
|
||||
&outkey[LOCAL]))
|
||||
errx(1, "Parsing local-close-pubkey");
|
||||
argnum++;
|
||||
if (!pubkey_from_hexstr(argv[argnum], strlen(argv[argnum]),
|
||||
&outkey[REMOTE]))
|
||||
errx(1, "Parsing remote-close-pubkey");
|
||||
argnum++;
|
||||
|
||||
fee = commit_tx_base_fee(feerate_per_kw, 0);
|
||||
if (!amount_msat_sub_sat(&local_msat, local_msat, fee))
|
||||
errx(1, "Can't afford fee %s",
|
||||
type_to_string(NULL, struct amount_sat, &fee));
|
||||
if (!amount_sat_sub_msat(&remote_msat, funding_amount, local_msat))
|
||||
errx(1, "Can't afford local_msat");
|
||||
|
||||
if (!pubkey_from_privkey(&funding_privkey[LOCAL], &funding_pubkey[LOCAL])
|
||||
|| !pubkey_from_privkey(&funding_privkey[REMOTE], &funding_pubkey[REMOTE]))
|
||||
errx(1, "Bad deriving funding pubkeys");
|
||||
|
||||
tx = bitcoin_tx(NULL, chainparams, 1, 2);
|
||||
|
||||
/* Our input spends the anchor tx output. */
|
||||
bitcoin_tx_add_input(tx, &funding_txid, funding_outnum,
|
||||
BITCOIN_TX_DEFAULT_SEQUENCE, funding_amount, NULL);
|
||||
|
||||
num_outputs = 0;
|
||||
if (amount_msat_greater_eq_sat(local_msat, dust_limit)) {
|
||||
u8 *script = scriptpubkey_p2wpkh(NULL, &outkey[LOCAL]);
|
||||
printf("# local witness script: %s\n", tal_hex(NULL, script));
|
||||
/* One output is to us. */
|
||||
bitcoin_tx_add_output(tx, script,
|
||||
amount_msat_to_sat_round_down(local_msat));
|
||||
num_outputs++;
|
||||
} else
|
||||
printf("# local output trimmed\n");
|
||||
|
||||
if (amount_msat_greater_eq_sat(remote_msat, dust_limit)) {
|
||||
u8 *script = scriptpubkey_p2wpkh(NULL, &outkey[REMOTE]);
|
||||
printf("# remote witness script: %s\n", tal_hex(NULL, script));
|
||||
/* Other output is to them. */
|
||||
bitcoin_tx_add_output(tx, script,
|
||||
amount_msat_to_sat_round_down(remote_msat));
|
||||
num_outputs++;
|
||||
} else
|
||||
printf("# remote output trimmed\n");
|
||||
|
||||
/* Can't have no outputs at all! */
|
||||
if (num_outputs == 0)
|
||||
errx(1, "Can't afford any output!");
|
||||
|
||||
funding_wscript = bitcoin_redeem_2of2(NULL,
|
||||
&funding_pubkey[LOCAL],
|
||||
&funding_pubkey[REMOTE]);
|
||||
printf("# funding witness script = %s\n",
|
||||
tal_hex(NULL, funding_wscript));
|
||||
|
||||
/* Need input amount for signing */
|
||||
tx->input_amounts[0] = tal_dup(tx, struct amount_sat, &funding_amount);
|
||||
sign_tx_input(tx, 0, NULL, funding_wscript,
|
||||
&funding_privkey[LOCAL],
|
||||
&funding_pubkey[LOCAL],
|
||||
SIGHASH_ALL, &local_sig);
|
||||
printf("localsig: %s\n", sig_as_hex(&local_sig));
|
||||
sign_tx_input(tx, 0, NULL, funding_wscript,
|
||||
&funding_privkey[REMOTE],
|
||||
&funding_pubkey[REMOTE],
|
||||
SIGHASH_ALL, &remote_sig);
|
||||
printf("remotesig: %s\n", sig_as_hex(&remote_sig));
|
||||
|
||||
witness =
|
||||
bitcoin_witness_2of2(NULL, &local_sig, &remote_sig,
|
||||
&funding_pubkey[LOCAL],
|
||||
&funding_pubkey[REMOTE]);
|
||||
bitcoin_tx_input_set_witness(tx, 0, witness);
|
||||
printf("# signed close transaction: %s\n",
|
||||
tal_hex(NULL, linearize_tx(NULL, tx)));
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user