Browse Source
These utilities allow us to create valid test txs and information given both sides' complete set of secrets. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>pull/2938/head
Rusty Russell
6 years ago
committed by
neil saitug
4 changed files with 506 additions and 1 deletions
@ -0,0 +1,367 @@ |
|||||
|
/* For example, in the spec tests we use the following:
|
||||
|
* |
||||
|
* lightning/devtools/mkcommit 0 41085b995c1f591cfc3ae79ccde012bf0b37c7bde23d80a61c9732bdd6210b2f 0 999878sat 253 999878sat local \ |
||||
|
6 546 9900sat \ |
||||
|
6 546 9900sat \ |
||||
|
0000000000000000000000000000000000000000000000000000000000000020 0000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000021 0000000000000000000000000000000000000000000000000000000000000022 0000000000000000000000000000000000000000000000000000000000000023 0000000000000000000000000000000000000000000000000000000000000024 \ |
||||
|
0000000000000000000000000000000000000000000000000000000000000010 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0000000000000000000000000000000000000000000000000000000000000011 0000000000000000000000000000000000000000000000000000000000000012 0000000000000000000000000000000000000000000000000000000000000013 0000000000000000000000000000000000000000000000000000000000000014 |
||||
|
*/ |
||||
|
#include <bitcoin/script.h> |
||||
|
#include <bitcoin/tx.h> |
||||
|
#include <ccan/err/err.h> |
||||
|
#include <ccan/str/hex/hex.h> |
||||
|
#include <common/amount.h> |
||||
|
#include <common/derive_basepoints.h> |
||||
|
#include <common/initial_commit_tx.h> |
||||
|
#include <common/keyset.h> |
||||
|
#include <common/status.h> |
||||
|
#include <common/type_to_string.h> |
||||
|
#include <inttypes.h> |
||||
|
#include <stdio.h> |
||||
|
|
||||
|
void status_fmt(enum log_level level, const char *fmt, ...) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/* Code to make a commitment tx, useful for generating test cases. */ |
||||
|
static int parse_secrets(char *argv[], |
||||
|
struct secrets *secrets, |
||||
|
struct sha256 *seed, |
||||
|
const char *desc) |
||||
|
{ |
||||
|
int argnum = 0; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&secrets->funding_privkey, |
||||
|
sizeof(secrets->funding_privkey))) |
||||
|
errx(1, "Parsing %s.funding_privkey", desc); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
seed, sizeof(*seed))) |
||||
|
errx(1, "Parsing %s seed", desc); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&secrets->revocation_basepoint_secret, |
||||
|
sizeof(secrets->revocation_basepoint_secret))) |
||||
|
errx(1, "Parsing %s.revocation_basepoint_secret", desc); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&secrets->payment_basepoint_secret, |
||||
|
sizeof(secrets->payment_basepoint_secret))) |
||||
|
errx(1, "Parsing %s.payment_basepoint_secret", desc); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&secrets->delayed_payment_basepoint_secret, |
||||
|
sizeof(secrets->delayed_payment_basepoint_secret))) |
||||
|
errx(1, "Parsing %s.delayed_payment_basepoint_secret", desc); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&secrets->htlc_basepoint_secret, |
||||
|
sizeof(secrets->htlc_basepoint_secret))) |
||||
|
errx(1, "Parsing %s.htlc_basepoint_secret", desc); |
||||
|
argnum++; |
||||
|
return argnum; |
||||
|
} |
||||
|
|
||||
|
static void print_basepoints(const char *desc, |
||||
|
const struct secrets *secrets, |
||||
|
const struct sha256 *shaseed, |
||||
|
const struct basepoints *basepoints, |
||||
|
const struct pubkey *fundingkey, |
||||
|
u64 commitnum) |
||||
|
{ |
||||
|
struct secret per_commitment_secret; |
||||
|
struct pubkey per_commitment_point; |
||||
|
|
||||
|
printf("## %s\n", desc); |
||||
|
printf("# funding_privkey=%s\n", |
||||
|
type_to_string(NULL, struct secret, &secrets->funding_privkey.secret)); |
||||
|
printf("funding_pubkey=%s\n", |
||||
|
type_to_string(NULL, struct pubkey, fundingkey)); |
||||
|
printf("# revocation_basepoint_secret=%s\n", |
||||
|
type_to_string(NULL, struct secret, |
||||
|
&secrets->revocation_basepoint_secret)); |
||||
|
printf("revocation_basepoint=%s\n", |
||||
|
type_to_string(NULL, struct pubkey, &basepoints->revocation)); |
||||
|
printf("# payment_basepoint_secret=%s\n", |
||||
|
type_to_string(NULL, struct secret, |
||||
|
&secrets->payment_basepoint_secret)); |
||||
|
printf("payment_basepoint=%s\n", |
||||
|
type_to_string(NULL, struct pubkey, &basepoints->payment)); |
||||
|
printf("# delayed_payment_basepoint_secret=%s\n", |
||||
|
type_to_string(NULL, struct secret, |
||||
|
&secrets->delayed_payment_basepoint_secret)); |
||||
|
printf("delayed_payment_basepoint=%s\n", |
||||
|
type_to_string(NULL, struct pubkey, &basepoints->delayed_payment)); |
||||
|
printf("# htlc_basepoint_secret=%s\n", |
||||
|
type_to_string(NULL, struct secret, |
||||
|
&secrets->htlc_basepoint_secret)); |
||||
|
printf("htlc_basepoint=%s\n", |
||||
|
type_to_string(NULL, struct pubkey, &basepoints->htlc)); |
||||
|
if (!per_commit_secret(shaseed, &per_commitment_secret, commitnum)) |
||||
|
errx(1, "Bad deriving %s per_commitment_secret", desc); |
||||
|
if (!per_commit_point(shaseed, &per_commitment_point, commitnum)) |
||||
|
errx(1, "Bad deriving %s per_commitment_point", desc); |
||||
|
printf("# shachain seed=%s\n", |
||||
|
type_to_string(NULL, struct sha256, shaseed)); |
||||
|
printf("# per_commitment_secret %"PRIu64"=%s\n", |
||||
|
commitnum, |
||||
|
type_to_string(NULL, struct secret, &per_commitment_secret)); |
||||
|
printf("per_commitment_point %"PRIu64"=%s\n\n", |
||||
|
commitnum, |
||||
|
type_to_string(NULL, struct pubkey, &per_commitment_point)); |
||||
|
} |
||||
|
|
||||
|
struct settings { |
||||
|
u32 to_self_delay; |
||||
|
struct amount_sat dustlimit; |
||||
|
struct amount_sat reserve; |
||||
|
}; |
||||
|
|
||||
|
static int parse_settings(char *argv[], |
||||
|
struct settings *settings, |
||||
|
const char *desc) |
||||
|
{ |
||||
|
int argnum = 0; |
||||
|
settings->to_self_delay = atoi(argv[argnum]); |
||||
|
argnum++; |
||||
|
if (!parse_amount_sat(&settings->dustlimit, |
||||
|
argv[argnum], strlen(argv[argnum]))) |
||||
|
errx(1, "Bad %s dustlimit", desc); |
||||
|
argnum++; |
||||
|
if (!parse_amount_sat(&settings->reserve, |
||||
|
argv[argnum], strlen(argv[argnum]))) |
||||
|
errx(1, "Bad %s reserve", desc); |
||||
|
argnum++; |
||||
|
return argnum; |
||||
|
} |
||||
|
|
||||
|
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 secrets local, remote; |
||||
|
struct sha256 localseed, remoteseed; |
||||
|
struct basepoints localbase, remotebase; |
||||
|
struct pubkey funding_localkey, funding_remotekey; |
||||
|
u64 commitnum; |
||||
|
struct amount_sat funding_amount; |
||||
|
struct bitcoin_txid funding_txid; |
||||
|
unsigned int funding_outnum; |
||||
|
unsigned int feerate_per_kw; |
||||
|
struct pubkey local_per_commit_point, remote_per_commit_point; |
||||
|
struct keyset localkeys, remotekeys; |
||||
|
struct bitcoin_signature local_sig, remote_sig; |
||||
|
struct settings localsettings, remotesettings; |
||||
|
struct amount_msat local_msat, remote_msat; |
||||
|
int argnum; |
||||
|
struct bitcoin_tx *local_tx, *remote_tx; |
||||
|
enum side fee_payer; |
||||
|
char *err; |
||||
|
u8 **witness; |
||||
|
|
||||
|
setup_locale(); |
||||
|
|
||||
|
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | |
||||
|
SECP256K1_CONTEXT_SIGN); |
||||
|
|
||||
|
if (argc != 1 + 7 + 3*2 + 6*2) |
||||
|
errx(1, "Usage: mkcommit <commitnum> <funding-txid> <funding-txout> <funding-amount> <feerate-per-kw> <local-msat> <fee-payer> <localsettings> <remotesettings> <remote-reserve> <localsecrets> <remotesecrets>\n" |
||||
|
"Where <settings> are:\n" |
||||
|
" <to-self-delay>\n" |
||||
|
" <dustlimit>\n" |
||||
|
" <reserve-sat>\n" |
||||
|
"Where <secrets> are:\n" |
||||
|
" <funding-privkey>\n" |
||||
|
" <shachain-seed>\n" |
||||
|
" <revocation-base-secret>\n" |
||||
|
" <payment-base-secret>\n" |
||||
|
" <delayed-payment-base-secret>\n" |
||||
|
" <htlc-base-secret>"); |
||||
|
|
||||
|
argnum = 1; |
||||
|
commitnum = atol(argv[argnum++]); |
||||
|
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 (streq(argv[argnum], "local")) |
||||
|
fee_payer = LOCAL; |
||||
|
else if (streq(argv[argnum], "remote")) |
||||
|
fee_payer = REMOTE; |
||||
|
else |
||||
|
errx(1, "fee-payer must be 'local' or 'remote'"); |
||||
|
argnum++; |
||||
|
|
||||
|
argnum += parse_settings(argv + argnum, &localsettings, "local"); |
||||
|
argnum += parse_settings(argv + argnum, &remotesettings, "remote"); |
||||
|
|
||||
|
argnum += parse_secrets(argv + argnum, &local, &localseed, "local"); |
||||
|
argnum += parse_secrets(argv + argnum, &remote, &remoteseed, "remote"); |
||||
|
|
||||
|
if (!amount_sat_sub_msat(&remote_msat, funding_amount, local_msat)) |
||||
|
errx(1, "Can't afford local_msat"); |
||||
|
|
||||
|
if (!pubkey_from_privkey(&local.funding_privkey, &funding_localkey) |
||||
|
|| !pubkey_from_secret(&local.revocation_basepoint_secret, |
||||
|
&localbase.revocation) |
||||
|
|| !pubkey_from_secret(&local.payment_basepoint_secret, |
||||
|
&localbase.payment) |
||||
|
|| !pubkey_from_secret(&local.delayed_payment_basepoint_secret, |
||||
|
&localbase.delayed_payment) |
||||
|
|| !pubkey_from_secret(&local.htlc_basepoint_secret, |
||||
|
&localbase.htlc)) |
||||
|
errx(1, "Bad deriving local basepoints"); |
||||
|
|
||||
|
if (!pubkey_from_privkey(&remote.funding_privkey, &funding_remotekey) |
||||
|
|| !pubkey_from_secret(&remote.revocation_basepoint_secret, |
||||
|
&remotebase.revocation) |
||||
|
|| !pubkey_from_secret(&remote.payment_basepoint_secret, |
||||
|
&remotebase.payment) |
||||
|
|| !pubkey_from_secret(&remote.delayed_payment_basepoint_secret, |
||||
|
&remotebase.delayed_payment) |
||||
|
|| !pubkey_from_secret(&remote.htlc_basepoint_secret, |
||||
|
&remotebase.htlc)) |
||||
|
errx(1, "Bad deriving remote basepoints"); |
||||
|
|
||||
|
print_basepoints("local", |
||||
|
&local, &localseed, |
||||
|
&localbase, &funding_localkey, commitnum); |
||||
|
print_basepoints("remote", |
||||
|
&remote, &remoteseed, |
||||
|
&remotebase, &funding_remotekey, commitnum); |
||||
|
|
||||
|
u8 *funding_wscript = bitcoin_redeem_2of2(NULL, |
||||
|
&funding_localkey, |
||||
|
&funding_remotekey); |
||||
|
|
||||
|
/* Create the local commitment_tx */ |
||||
|
if (!per_commit_point(&localseed, &local_per_commit_point, commitnum)) |
||||
|
errx(1, "Bad deriving local per-commitment-point"); |
||||
|
|
||||
|
if (!derive_keyset(&local_per_commit_point, &localbase, &remotebase, |
||||
|
&localkeys)) |
||||
|
errx(1, "Bad deriving local keyset"); |
||||
|
|
||||
|
local_tx = initial_commit_tx(NULL, &funding_txid, funding_outnum, |
||||
|
funding_amount, fee_payer, |
||||
|
localsettings.to_self_delay, |
||||
|
&localkeys, |
||||
|
feerate_per_kw, |
||||
|
localsettings.dustlimit, |
||||
|
local_msat, |
||||
|
remote_msat, |
||||
|
localsettings.reserve, |
||||
|
commitnum |
||||
|
^ commit_number_obscurer(&localbase.payment, |
||||
|
&remotebase.payment), |
||||
|
LOCAL, &err); |
||||
|
if (!local_tx) |
||||
|
errx(1, "Can't make local commit tx: %s", err); |
||||
|
local_tx->input_amounts[0] |
||||
|
= tal_dup(local_tx, struct amount_sat, &funding_amount); |
||||
|
|
||||
|
printf("## local_commitment\n" |
||||
|
"# input amount %s, funding_wscript %s, key %s\n", |
||||
|
type_to_string(NULL, struct amount_sat, &funding_amount), |
||||
|
tal_hex(NULL, funding_wscript), |
||||
|
type_to_string(NULL, struct pubkey, &funding_localkey)); |
||||
|
printf("# unsigned local commitment tx: %s\n", |
||||
|
tal_hex(NULL, linearize_tx(NULL, local_tx))); |
||||
|
|
||||
|
sign_tx_input(local_tx, 0, NULL, funding_wscript, |
||||
|
&local.funding_privkey, |
||||
|
&funding_localkey, |
||||
|
SIGHASH_ALL, |
||||
|
&local_sig); |
||||
|
printf("localsig_on_local: %s\n", sig_as_hex(&local_sig)); |
||||
|
|
||||
|
sign_tx_input(local_tx, 0, NULL, funding_wscript, |
||||
|
&remote.funding_privkey, |
||||
|
&funding_remotekey, |
||||
|
SIGHASH_ALL, |
||||
|
&remote_sig); |
||||
|
printf("remotesig_on_local: %s\n", sig_as_hex(&remote_sig)); |
||||
|
|
||||
|
witness = |
||||
|
bitcoin_witness_2of2(NULL, &local_sig, &remote_sig, |
||||
|
&funding_localkey, &funding_remotekey); |
||||
|
bitcoin_tx_input_set_witness(local_tx, 0, witness); |
||||
|
|
||||
|
printf("# signed local commitment: %s\n\n", |
||||
|
tal_hex(NULL, linearize_tx(NULL, local_tx))); |
||||
|
|
||||
|
/* Create the remote commitment tx */ |
||||
|
if (!per_commit_point(&remoteseed, &remote_per_commit_point, commitnum)) |
||||
|
errx(1, "Bad deriving remote per-commitment-point"); |
||||
|
if (!derive_keyset(&remote_per_commit_point, &remotebase, &localbase, |
||||
|
&remotekeys)) |
||||
|
errx(1, "Bad deriving remote keyset"); |
||||
|
|
||||
|
remote_tx = initial_commit_tx(NULL, &funding_txid, funding_outnum, |
||||
|
funding_amount, |
||||
|
fee_payer, |
||||
|
remotesettings.to_self_delay, |
||||
|
&remotekeys, |
||||
|
feerate_per_kw, |
||||
|
remotesettings.dustlimit, |
||||
|
remote_msat, |
||||
|
local_msat, |
||||
|
remotesettings.reserve, |
||||
|
commitnum |
||||
|
^ commit_number_obscurer(&localbase.payment, |
||||
|
&remotebase.payment), |
||||
|
REMOTE, &err); |
||||
|
if (!remote_tx) |
||||
|
errx(1, "Can't make remote commit tx: %s", err); |
||||
|
remote_tx->input_amounts[0] |
||||
|
= tal_dup(remote_tx, struct amount_sat, &funding_amount); |
||||
|
|
||||
|
printf("## remote_commitment\n" |
||||
|
"# input amount %s, funding_wscript %s, key %s\n", |
||||
|
type_to_string(NULL, struct amount_sat, &funding_amount), |
||||
|
tal_hex(NULL, funding_wscript), |
||||
|
type_to_string(NULL, struct pubkey, &funding_remotekey)); |
||||
|
printf("# unsigned remote commitment tx: %s\n", |
||||
|
tal_hex(NULL, linearize_tx(NULL, remote_tx))); |
||||
|
|
||||
|
sign_tx_input(remote_tx, 0, NULL, funding_wscript, |
||||
|
&local.funding_privkey, |
||||
|
&funding_localkey, |
||||
|
SIGHASH_ALL, |
||||
|
&local_sig); |
||||
|
printf("localsig_on_remote: %s\n", sig_as_hex(&local_sig)); |
||||
|
|
||||
|
sign_tx_input(remote_tx, 0, NULL, funding_wscript, |
||||
|
&remote.funding_privkey, |
||||
|
&funding_remotekey, |
||||
|
SIGHASH_ALL, |
||||
|
&remote_sig); |
||||
|
printf("remotesig_on_remote: %s\n", sig_as_hex(&remote_sig)); |
||||
|
|
||||
|
witness = |
||||
|
bitcoin_witness_2of2(NULL, &local_sig, &remote_sig, |
||||
|
&funding_localkey, &funding_remotekey); |
||||
|
bitcoin_tx_input_set_witness(remote_tx, 0, witness); |
||||
|
|
||||
|
printf("# signed remote commitment: %s\n", |
||||
|
tal_hex(NULL, linearize_tx(NULL, remote_tx))); |
||||
|
|
||||
|
return 0; |
||||
|
} |
@ -0,0 +1,133 @@ |
|||||
|
/* For example, in the spec tests we use the following keys:
|
||||
|
* |
||||
|
* lightning/devtools/mkfunding 16835ac8c154b616baac524163f41fb0c4f82c7b972ad35d4d6f18d854f6856b 1 0.01btc 253 76edf0c303b9e692da9cb491abedef46ca5b81d32f102eb4648461b239cb0f99 0000000000000000000000000000000000000000000000000000000000000010 0000000000000000000000000000000000000000000000000000000000000020 |
||||
|
*/ |
||||
|
#include <bitcoin/address.h> |
||||
|
#include <bitcoin/script.h> |
||||
|
#include <bitcoin/tx.h> |
||||
|
#include <ccan/err/err.h> |
||||
|
#include <ccan/str/hex/hex.h> |
||||
|
#include <common/amount.h> |
||||
|
#include <common/derive_basepoints.h> |
||||
|
#include <common/funding_tx.h> |
||||
|
#include <common/initial_commit_tx.h> |
||||
|
#include <common/keyset.h> |
||||
|
#include <common/status.h> |
||||
|
#include <common/type_to_string.h> |
||||
|
#include <common/utxo.h> |
||||
|
#include <stdio.h> |
||||
|
|
||||
|
void status_fmt(enum log_level level, const char *fmt, ...) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
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 privkey input_privkey; |
||||
|
struct privkey local_funding_privkey, remote_funding_privkey; |
||||
|
struct pubkey funding_localkey, funding_remotekey, inputkey; |
||||
|
struct amount_sat fee, funding_amount; |
||||
|
unsigned int feerate_per_kw; |
||||
|
int argnum; |
||||
|
struct bitcoin_tx *tx; |
||||
|
u16 outnum; |
||||
|
size_t weight; |
||||
|
struct utxo input; |
||||
|
const struct utxo **utxomap; |
||||
|
struct bitcoin_signature sig; |
||||
|
struct bitcoin_txid txid; |
||||
|
|
||||
|
setup_locale(); |
||||
|
|
||||
|
secp256k1_ctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | |
||||
|
SECP256K1_CONTEXT_SIGN); |
||||
|
|
||||
|
if (argc != 1 + 7) |
||||
|
errx(1, "Usage: mkfunding <input-txid> <input-txout> <input-amount> <feerate-per-kw> <input-privkey> <local-funding-privkey> <remote-funding-privkey>"); |
||||
|
|
||||
|
input.is_p2sh = false; |
||||
|
input.close_info = NULL; |
||||
|
|
||||
|
argnum = 1; |
||||
|
if (!bitcoin_txid_from_hex(argv[argnum], |
||||
|
strlen(argv[argnum]), &input.txid)) |
||||
|
errx(1, "Bad input-txid"); |
||||
|
argnum++; |
||||
|
input.outnum = atoi(argv[argnum++]); |
||||
|
if (!parse_amount_sat(&input.amount, argv[argnum], strlen(argv[argnum]))) |
||||
|
errx(1, "Bad input-amount"); |
||||
|
argnum++; |
||||
|
feerate_per_kw = atoi(argv[argnum++]); |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&input_privkey, sizeof(input_privkey))) |
||||
|
errx(1, "Parsing input-privkey"); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&local_funding_privkey, sizeof(local_funding_privkey))) |
||||
|
errx(1, "Parsing local-funding-privkey"); |
||||
|
argnum++; |
||||
|
if (!hex_decode(argv[argnum], strlen(argv[argnum]), |
||||
|
&remote_funding_privkey, sizeof(remote_funding_privkey))) |
||||
|
errx(1, "Parsing remote-funding-privkey"); |
||||
|
argnum++; |
||||
|
|
||||
|
if (!pubkey_from_privkey(&input_privkey, &inputkey) |
||||
|
|| !pubkey_from_privkey(&local_funding_privkey, &funding_localkey) |
||||
|
|| !pubkey_from_privkey(&remote_funding_privkey, &funding_remotekey)) |
||||
|
errx(1, "Bad privkeys"); |
||||
|
|
||||
|
/* nVersion, input count, output count, nLocktime */ |
||||
|
weight = 4 * (4 + 1 + 1 + 4); |
||||
|
/* Single output: Satoshis, script length, p2wsh. */ |
||||
|
weight += 4 * (8 + 1 + BITCOIN_SCRIPTPUBKEY_P2WSH_LEN); |
||||
|
/* Single input: txid, index, scriptlen, nSequence */ |
||||
|
weight += 4 * (32 + 4 + 1 + 4); |
||||
|
/* Single witness: witness element count, len[0], sig, len[2], key */ |
||||
|
weight += 1 + (1 + 73 + 1 + 33); |
||||
|
|
||||
|
fee = amount_tx_fee(feerate_per_kw, weight); |
||||
|
if (!amount_sat_sub(&funding_amount, input.amount, fee)) |
||||
|
errx(1, "Input %s can't afford fee %s", |
||||
|
type_to_string(NULL, struct amount_sat, &input.amount), |
||||
|
type_to_string(NULL, struct amount_sat, &fee)); |
||||
|
|
||||
|
/* funding_tx wants a utxo array. */ |
||||
|
utxomap = tal_arr(tmpctx, const struct utxo *, 1); |
||||
|
utxomap[0] = &input; |
||||
|
|
||||
|
/* No change output, so we don't need a bip32 base. */ |
||||
|
tx = funding_tx(NULL, &outnum, utxomap, funding_amount, |
||||
|
&funding_localkey, &funding_remotekey, |
||||
|
AMOUNT_SAT(0), NULL, NULL); |
||||
|
|
||||
|
/* P2WSH of inputkey */ |
||||
|
bitcoin_tx_input_set_script(tx, 0, NULL); |
||||
|
sign_tx_input(tx, 0, NULL, p2wpkh_scriptcode(NULL, &inputkey), |
||||
|
&input_privkey, &inputkey, |
||||
|
SIGHASH_ALL, &sig); |
||||
|
|
||||
|
printf("# funding sig: %s\n", sig_as_hex(&sig)); |
||||
|
printf("# funding amount: %s\n", |
||||
|
type_to_string(NULL, struct amount_sat, &funding_amount)); |
||||
|
|
||||
|
bitcoin_txid(tx, &txid); |
||||
|
printf("# funding txid: %s\n", |
||||
|
type_to_string(NULL, struct bitcoin_txid, &txid)); |
||||
|
|
||||
|
bitcoin_tx_input_set_witness( |
||||
|
tx, 0, bitcoin_witness_p2wpkh(NULL, &sig, &inputkey)); |
||||
|
|
||||
|
printf("tx: %s\n", tal_hex(NULL, linearize_tx(NULL, tx))); |
||||
|
|
||||
|
return 0; |
||||
|
} |
Loading…
Reference in new issue