core-lightning/devtools/mkclose.c
darosior 273029f244 wallet: set nLockTime to the tip for withdrawal transactions
This sets the nLockTime to the tip (and accordingly each input's nSequence to
0xfffffffe) for withdrawal transactions.

Even if the anti fee-sniping argument might not be valid until some time yet,
this makes our regular wallet transactions far less distinguishable from
bitcoind's ones since it now defaults to using native Segwit transactions
(like us). Moreover other wallets are likely to implement this (if they
haven't already).

Changelog-Added: wallet: withdrawal transactions now sets nlocktime to the current tip.
2020-02-03 00:45:27 +00:00

191 lines
6.1 KiB
C

/* 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 struct node_id *node_id,
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, 0);
/* 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;
}