forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 1
/
commit_tx.c
297 lines (263 loc) · 8.27 KB
/
commit_tx.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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#include "bitcoin/locktime.h"
#include "bitcoin/pubkey.h"
#include "bitcoin/script.h"
#include "bitcoin/shadouble.h"
#include "bitcoin/tx.h"
#include "channel.h"
#include "commit_tx.h"
#include "log.h"
#include "lnchannel_internal.h"
#include "permute_tx.h"
#include "remove_dust.h"
#include "utils/overflows.h"
#include "utils/utils.h"
#include <assert.h>
#include <inttypes.h>
static const u32 current_version = 100;
u32 commit_generator_version()
{
return current_version;
}
bool check_commit_generator_compatible(u32 ver)
{
//TODO: keep version list ...
return ver == current_version;
}
u8 *wscript_for_htlc(const tal_t *ctx,
const struct LNchannel *lnchn,
const struct htlc *h,
const struct sha256 *rhash,
enum side side)
{
const struct LNChannel_visible_state *this_side, *other_side;
u8 *(*fn)(const tal_t *,
const struct pubkey *, const struct pubkey *,
const struct abs_locktime *, const struct rel_locktime *,
const struct sha256 *, const struct sha256 *);
/* scripts are different for htlcs offered vs accepted */
if (side == htlc_owner(h))
fn = bitcoin_redeem_htlc_send;
else
fn = bitcoin_redeem_htlc_recv;
if (side == LOCAL) {
this_side = &lnchn->local;
other_side = &lnchn->remote;
} else {
this_side = &lnchn->remote;
other_side = &lnchn->local;
}
return fn(ctx,
&this_side->finalkey, &other_side->finalkey,
&h->expiry, &this_side->locktime, rhash, &h->rhash);
}
static size_t count_htlcs(const struct htlc_map *htlcs, int flag)
{
struct htlc_map_iter it;
struct htlc *h;
size_t n = 0;
for (h = htlc_map_first(htlcs, &it); h; h = htlc_map_next(htlcs, &it)) {
if (htlc_has(h, flag))
n++;
}
return n;
}
u8 *commit_output_to_us(const tal_t *ctx,
const struct LNchannel *lnchn,
const struct sha256 *rhash,
enum side side,
u8 **wscript)
{
u8 *tmp;
if (!wscript)
wscript = &tmp;
/* Our output to ourself is encumbered by delay. */
if (side == LOCAL) {
*wscript = bitcoin_redeem_secret_or_delay(ctx,
&lnchn->local.finalkey,
&lnchn->remote.locktime,
&lnchn->remote.finalkey,
rhash);
return scriptpubkey_p2wsh(ctx, *wscript);
} else {
/* Their output to us is a simple p2wpkh */
*wscript = NULL;
return scriptpubkey_p2wpkh(ctx, &lnchn->local.finalkey);
}
}
u8 *commit_output_to_them(const tal_t *ctx,
const struct LNchannel *lnchn,
const struct sha256 *rhash,
enum side side,
u8 **wscript)
{
u8 *tmp;
if (!wscript)
wscript = &tmp;
/* Their output to themselves is encumbered by delay. */
if (side == REMOTE) {
*wscript = bitcoin_redeem_secret_or_delay(ctx,
&lnchn->remote.finalkey,
&lnchn->local.locktime,
&lnchn->local.finalkey,
rhash);
return scriptpubkey_p2wsh(ctx, *wscript);
} else {
/* Our output to them is a simple p2wpkh */
*wscript = NULL;
return scriptpubkey_p2wpkh(ctx, &lnchn->remote.finalkey);
}
}
/* Takes ownership of script. */
static bool add_output(struct bitcoin_tx *tx, u8 *script, u64 amount,
size_t *output_count,
u64 *total)
{
assert(*output_count < tal_count(tx->output));
if (is_dust(amount))
return false;
tx->output[*output_count].script = tal_steal(tx, script);
tx->output[*output_count].amount = amount;
(*output_count)++;
(*total) += amount;
return true;
}
struct bitcoin_tx *create_commit_tx(const tal_t *ctx,
struct LNchannel *lnchn,
const struct sha256 *rhash,
const struct channel_state *cstate,
enum side side,
bool *otherside_only,
struct htlc ***htlc_updates)
{
const tal_t *tmpctx = tal_tmpctx(ctx);
struct bitcoin_tx *tx;
uint64_t total = 0;
struct htlc_map_iter it;
struct htlc *h;
size_t output_count;
bool pays_to[2];
int committed_flag = HTLC_FLAG(side,HTLC_F_COMMITTED);
/* Now create commitment tx: one input, two outputs (plus htlcs) */
tx = bitcoin_tx(ctx, 1, 2 + count_htlcs(&lnchn->htlcs, committed_flag));
if (htlc_updates) {
*htlc_updates = tal_arrz(ctx, struct htlc *, tal_count(tx->output));
}
log_debug(lnchn->log, "Creating commitment tx:");
log_add_struct(lnchn->log, " rhash = %s", struct sha256, rhash);
log_add_struct(lnchn->log, " My finalkey = %s", struct pubkey,
&lnchn->local.finalkey);
log_add_struct(lnchn->log, " Their finalkey = %s", struct pubkey,
&lnchn->remote.finalkey);
log_add_struct(lnchn->log, " My locktime = %s", struct rel_locktime,
&lnchn->local.locktime);
log_add_struct(lnchn->log, " Their locktime = %s", struct rel_locktime,
&lnchn->remote.locktime);
/* Our input spends the anchor tx output. */
tx->input[0].txid = lnchn->anchor.txid;
tx->input[0].index = lnchn->anchor.index;
tx->input[0].amount = tal_dup(tx->input, u64, &lnchn->anchor.satoshis);
output_count = 0;
pays_to[LOCAL] = add_output(tx, commit_output_to_us(tmpctx, lnchn, rhash,
side, NULL),
cstate->side[LOCAL].pay_msat / 1000,
&output_count,
&total);
if (pays_to[LOCAL])
log_debug(lnchn->log, "Pays %u to local: %s",
cstate->side[LOCAL].pay_msat / 1000,
tal_hex(tmpctx, tx->output[output_count-1].script));
else
log_debug(lnchn->log, "DOES NOT pay %u to local",
cstate->side[LOCAL].pay_msat / 1000);
pays_to[REMOTE] = add_output(tx, commit_output_to_them(tmpctx, lnchn,
rhash, side,
NULL),
cstate->side[REMOTE].pay_msat / 1000,
&output_count,
&total);
if (pays_to[REMOTE])
log_debug(lnchn->log, "Pays %u to remote: %s",
cstate->side[REMOTE].pay_msat / 1000,
tal_hex(tmpctx, tx->output[output_count-1].script));
else
log_debug(lnchn->log, "DOES NOT pay %u to remote",
cstate->side[REMOTE].pay_msat / 1000);
/* If their tx doesn't pay to them, or our tx doesn't pay to us... */
*otherside_only = !pays_to[side];
/* First two outputs done, now for the HTLCs. */
for (h = htlc_map_first(&lnchn->htlcs, &it);
h;
h = htlc_map_next(&lnchn->htlcs, &it)) {
const u8 *wscript;
if (!htlc_has(h, committed_flag))
continue;
wscript = wscript_for_htlc(tmpctx, lnchn, h, rhash, side);
/* If we pay any HTLC, it's txout is not just to other side. */
if (add_output(tx, scriptpubkey_p2wsh(tmpctx, wscript),
h->msatoshi / 1000, &output_count, &total)) {
*otherside_only = false;
if (htlc_updates) {
(*htlc_updates)[output_count - 1] = h;
}
log_debug(lnchn->log, "Pays %"PRIu64" to htlc %s",
h->msatoshi / 1000, tal_hexstr(tmpctx, &h->rhash, sizeof(h->rhash)));
log_add_struct(lnchn->log, " expiry %s",
struct abs_locktime, &h->expiry);
log_add_struct(lnchn->log, " rhash %s", struct sha256,
&h->rhash);
log_debug(lnchn->log, "Script: %s",
tal_hex(tmpctx, wscript));
} else
log_debug(lnchn->log, "DOES NOT pay %"PRIu64" to htlc %s",
h->msatoshi / 1000, tal_hexstr(tmpctx, &h->rhash, sizeof(h->rhash)));
}
assert(total <= lnchn->anchor.satoshis);
tal_resize(&tx->output, output_count);
if (htlc_updates) {
tal_resize(htlc_updates, output_count);
permute_outputs(tx->output, tal_count(tx->output), (void **)*htlc_updates);
}
else {
permute_outputs(tx->output, tal_count(tx->output), NULL);
}
tal_free(tmpctx);
return tx;
}
void update_htlc_in_channel(struct LNchannel *lnchn,
enum side side, struct htlc **htlc_updates)
{
struct htlc *h;
size_t i, cnt;
cnt = tal_count(htlc_updates);
for (i = 0; i < cnt; ++i) {
h = htlc_updates[i];
if (h) {
if (side == REMOTE) {
h->in_commit_output[2] = h->in_commit_output[side];
}
h->in_commit_output[side] = i;
}
}
}
size_t find_redeem_output_from_commit_tx(const struct bitcoin_tx* commit_tx,
u8* script)
{
size_t i, last;
last = tal_count(commit_tx->output);
for (i = 0; i < last; ++i)
{
if (outputscript_eq(commit_tx->output, i, script)) {
return i;
}
}
return i;
}
size_t find_htlc_output_from_commit_tx(const struct bitcoin_tx* commit_tx,
u8* wscript)
{
const tal_t *tmpctx = tal_tmpctx(commit_tx);
u8* script = scriptpubkey_p2wsh(tmpctx, wscript);
size_t ret = find_redeem_output_from_commit_tx(commit_tx, script);
tal_free(tmpctx);
return ret;
}