Skip to content

Commit 9284819

Browse files
committed
commit_tx: expose more internal functions.
without having to build it, which is needed for limit enforcement. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent e8e96e6 commit 9284819

File tree

3 files changed

+101
-58
lines changed

3 files changed

+101
-58
lines changed

lightningd/commit_tx.c

Lines changed: 83 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,11 @@ u64 htlc_success_fee(u64 feerate_per_kw)
7373
return feerate_per_kw * 673 / 1000;
7474
}
7575

76-
static const struct htlc **untrimmed(const tal_t *ctx,
77-
const struct htlc **htlcs,
78-
enum side side,
79-
u64 htlc_fee, u64 dust_limit_satoshis)
76+
static bool trim(const struct htlc *htlc,
77+
u64 feerate_per_kw, u64 dust_limit_satoshis,
78+
enum side side)
8079
{
81-
const struct htlc **arr;
82-
size_t i, n;
80+
u64 htlc_fee;
8381

8482
/* BOLT #3:
8583
*
@@ -88,29 +86,36 @@ static const struct htlc **untrimmed(const tal_t *ctx,
8886
* owner, the commitment transaction MUST NOT contain that output,
8987
* otherwise it MUST be generated as specified in [Offered HTLC
9088
* Outputs](#offered-htlc-outputs).
89+
*/
90+
if (htlc_owner(htlc) == side)
91+
htlc_fee = htlc_timeout_fee(feerate_per_kw);
92+
/* BOLT #3:
9193
*
9294
* For every received HTLC, if the HTLC amount minus the HTLC-success
9395
* fee would be less than `dust-limit-satoshis` set by the transaction
9496
* owner, the commitment transaction MUST NOT contain that output,
9597
* otherwise it MUST be generated as specified in [Received HTLC
9698
* Outputs](#received-htlc-outputs).
9799
*/
98-
arr = tal_arr(ctx, const struct htlc *, tal_count(htlcs));
99-
for (i = n = 0; i < tal_count(htlcs); i++) {
100-
if (htlc_owner(htlcs[i]) != side)
101-
continue;
102-
if (htlcs[i]->msatoshi / 1000 < dust_limit_satoshis + htlc_fee)
103-
continue;
104-
arr[n++] = htlcs[i];
105-
}
100+
else
101+
htlc_fee = htlc_success_fee(feerate_per_kw);
106102

107-
assert(n <= tal_count(arr));
108-
tal_resize(&arr, n);
103+
return htlc->msatoshi / 1000 < dust_limit_satoshis + htlc_fee;
104+
}
109105

110-
return arr;
106+
size_t commit_tx_num_untrimmed(const struct htlc **htlcs,
107+
u64 feerate_per_kw, u64 dust_limit_satoshis,
108+
enum side side)
109+
{
110+
size_t i, n;
111+
112+
for (i = n = 0; i < tal_count(htlcs); i++)
113+
n += !trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side);
114+
115+
return n;
111116
}
112117

113-
static u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs)
118+
u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs)
114119
{
115120
u64 weight;
116121

@@ -139,6 +144,38 @@ static u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs)
139144
return feerate_per_kw * weight / 1000;
140145
}
141146

147+
static void add_offered_htlc_out(struct bitcoin_tx *tx, size_t n,
148+
const struct htlc *htlc,
149+
const struct pubkey *selfkey,
150+
const struct pubkey *otherkey)
151+
{
152+
u8 *wscript = bitcoin_wscript_htlc_offer(tx,
153+
selfkey, otherkey,
154+
&htlc->rhash);
155+
tx->output[n].amount = htlc->msatoshi / 1000;
156+
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
157+
SUPERVERBOSE("# HTLC offered amount %"PRIu64" wscript %s\n",
158+
tx->output[n].amount, tal_hex(wscript, wscript));
159+
tal_free(wscript);
160+
}
161+
162+
static void add_received_htlc_out(struct bitcoin_tx *tx, size_t n,
163+
const struct htlc *htlc,
164+
const struct pubkey *selfkey,
165+
const struct pubkey *otherkey)
166+
{
167+
u8 *wscript = bitcoin_wscript_htlc_receive(tx,
168+
&htlc->expiry,
169+
selfkey, otherkey,
170+
&htlc->rhash);
171+
tx->output[n].amount = htlc->msatoshi / 1000;
172+
tx->output[n].script = scriptpubkey_p2wsh(tx->output, wscript);
173+
SUPERVERBOSE("# HTLC received amount %"PRIu64" wscript %s\n",
174+
tx->output[n].amount,
175+
tal_hex(wscript, wscript));
176+
tal_free(wscript);
177+
}
178+
142179
struct bitcoin_tx *commit_tx(const tal_t *ctx,
143180
const struct sha256_double *funding_txid,
144181
unsigned int funding_txout,
@@ -159,10 +196,9 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
159196
enum side side)
160197
{
161198
const tal_t *tmpctx = tal_tmpctx(ctx);
162-
const struct htlc **offered, **received;
163199
u64 base_fee_msat;
164200
struct bitcoin_tx *tx;
165-
size_t i, n;
201+
size_t i, n, untrimmed;
166202

167203
assert(self_pay_msat + other_pay_msat <= funding_satoshis * 1000);
168204

@@ -171,22 +207,16 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
171207
* 1. Calculate which committed HTLCs need to be trimmed (see
172208
* [Trimmed Outputs](#trimmed-outputs)).
173209
*/
174-
offered = untrimmed(tmpctx, htlcs, side,
175-
htlc_timeout_fee(feerate_per_kw),
176-
dust_limit_satoshis);
177-
received = untrimmed(tmpctx, htlcs, !side,
178-
htlc_success_fee(feerate_per_kw),
179-
dust_limit_satoshis);
210+
untrimmed = commit_tx_num_untrimmed(htlcs,
211+
feerate_per_kw,
212+
dust_limit_satoshis, side);
180213

181214
/* BOLT #3:
182215
*
183216
* 2. Calculate the base [commitment transaction
184217
* fee](#fee-calculation).
185218
*/
186-
base_fee_msat = commit_tx_base_fee(feerate_per_kw,
187-
tal_count(offered)
188-
+ tal_count(received))
189-
* 1000;
219+
base_fee_msat = commit_tx_base_fee(feerate_per_kw, untrimmed) * 1000;
190220

191221
SUPERVERBOSE("# base commitment transaction fee = %"PRIu64"\n",
192222
base_fee_msat / 1000);
@@ -200,45 +230,41 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
200230
&self_pay_msat, &other_pay_msat);
201231

202232
/* Worst-case sizing: both to-local and to-remote outputs. */
203-
tx = bitcoin_tx(ctx, 1, tal_count(offered) + tal_count(received) + 2);
233+
tx = bitcoin_tx(ctx, 1, untrimmed + 2);
204234

205235
/* We keep track of which outputs have which HTLCs */
206236
*htlcmap = tal_arr(tx, const struct htlc *, tal_count(tx->output));
207237

238+
/* This could be done in a single loop, but we follow the BOLT
239+
* literally to make comments in test vectors clearer. */
240+
241+
n = 0;
208242
/* BOLT #3:
209243
*
210-
* 3. For every offered HTLC, if it is not trimmed, add an [offered
211-
* HTLC output](#offered-htlc-outputs).
244+
* 3. For every offered HTLC, if it is not trimmed, add an
245+
* [offered HTLC output](#offered-htlc-outputs).
212246
*/
213-
n = 0;
214-
for (i = 0; i < tal_count(offered); i++, n++) {
215-
u8 *wscript = bitcoin_wscript_htlc_offer(tmpctx,
216-
selfkey, otherkey,
217-
&offered[i]->rhash);
218-
tx->output[n].amount = offered[i]->msatoshi / 1000;
219-
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
220-
(*htlcmap)[n] = offered[i];
221-
SUPERVERBOSE("# HTLC offered amount %"PRIu64" wscript %s\n",
222-
tx->output[n].amount,
223-
tal_hex(tmpctx, wscript));
247+
for (i = 0; i < tal_count(htlcs); i++) {
248+
if (htlc_owner(htlcs[i]) != side)
249+
continue;
250+
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side))
251+
continue;
252+
add_offered_htlc_out(tx, n, htlcs[i], selfkey, otherkey);
253+
(*htlcmap)[n++] = htlcs[i];
224254
}
225255

226256
/* BOLT #3:
227257
*
228-
* 4. For every received HTLC, if it is not trimmed, add an [received
229-
* HTLC output](#received-htlc-outputs).
258+
* 4. For every received HTLC, if it is not trimmed, add an
259+
* [received HTLC output](#received-htlc-outputs).
230260
*/
231-
for (i = 0; i < tal_count(received); i++, n++) {
232-
u8 *wscript = bitcoin_wscript_htlc_receive(tmpctx,
233-
&received[i]->expiry,
234-
selfkey, otherkey,
235-
&received[i]->rhash);
236-
tx->output[n].amount = received[i]->msatoshi / 1000;
237-
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
238-
(*htlcmap)[n] = received[i];
239-
SUPERVERBOSE("# HTLC received amount %"PRIu64" wscript %s\n",
240-
tx->output[n].amount,
241-
tal_hex(tmpctx, wscript));
261+
for (i = 0; i < tal_count(htlcs); i++) {
262+
if (htlc_owner(htlcs[i]) == side)
263+
continue;
264+
if (trim(htlcs[i], feerate_per_kw, dust_limit_satoshis, side))
265+
continue;
266+
add_received_htlc_out(tx, n, htlcs[i],selfkey, otherkey);
267+
(*htlcmap)[n++] = htlcs[i];
242268
}
243269

244270
/* BOLT #3:

lightningd/commit_tx.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,23 @@ u64 commit_number_obscurer(const struct pubkey *opener_payment_basepoint,
2020
u64 htlc_success_fee(u64 feerate_per_kw);
2121
u64 htlc_timeout_fee(u64 feerate_per_kw);
2222

23+
/**
24+
* commit_tx_num_untrimmed: how many of these htlc outputs will commit tx have?
25+
* @htlcs: tal_arr of HTLCs
26+
* @feerate_per_kw: feerate to use
27+
* @dust_limit_satoshis: dust limit below which to trim outputs.
28+
* @side: from which side's point of view
29+
*
30+
* We need @side because HTLC fees are different for offered and
31+
* received HTLCs.
32+
*/
33+
size_t commit_tx_num_untrimmed(const struct htlc **htlcs,
34+
u64 feerate_per_kw, u64 dust_limit_satoshis,
35+
enum side side);
36+
37+
/* Helper to calculate the base fee if we add this extra htlc */
38+
u64 commit_tx_base_fee(u64 feerate_per_kw, size_t num_untrimmed_htlcs);
39+
2340
/**
2441
* commit_tx: create (unsigned) commitment tx to spend the funding tx output
2542
* @ctx: context to allocate transaction and @htlc_map from.

lightningd/test/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ update-mocks: $(LIGHTNINGD_TEST_SRC:%=update-mocks/%)
1010

1111
$(LIGHTNINGD_TEST_PROGRAMS): $(CCAN_OBJS) $(CORE_OBJS) $(CORE_TX_OBJS) $(BITCOIN_OBJS) $(WIRE_OBJS) $(LIBBASE58_OBJS) $(LIGHTNINGD_OLD_LIB_OBJS) utils.o libsecp256k1.a libsodium.a
1212

13-
$(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS)
13+
$(LIGHTNINGD_TEST_OBJS): $(LIGHTNINGD_HEADERS) $(LIGHTNINGD_SRC) $(LIGHTNINGD_LIB_SRC)
1414

1515
lightningd/tests: $(LIGHTNINGD_TEST_PROGRAMS:%=unittest/%)
1616

0 commit comments

Comments
 (0)