forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkclose.c
188 lines (165 loc) · 6.11 KB
/
mkclose.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
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;
}