Skip to content

Commit 3746ea3

Browse files
rustyrussellcdecker
authored andcommittedOct 23, 2018
channeld: tiebreak identical HTLC outputs by CLTV.
This was suggested by Pierre-Marie as the solution to the 'same HTLC, different CLTV' signature mismatch. Signed-off-by: Rusty Russell <[email protected]>
1 parent 0006d57 commit 3746ea3

8 files changed

+73
-28
lines changed
 

‎channeld/commit_tx.c

+12-2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
107107
u64 base_fee_msat;
108108
struct bitcoin_tx *tx;
109109
size_t i, n, untrimmed;
110+
u32 *cltvs;
110111

111112
assert(self_pay_msat + other_pay_msat <= funding_satoshis * 1000);
112113

@@ -160,6 +161,10 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
160161
/* We keep track of which outputs have which HTLCs */
161162
*htlcmap = tal_arr(tx, const struct htlc *, tal_count(tx->output));
162163

164+
/* We keep cltvs for tie-breaking HTLC outputs; we use the same order
165+
* for sending the htlc txs, so it may matter. */
166+
cltvs = tal_arr(tmpctx, u32, tal_count(tx->output));
167+
163168
/* This could be done in a single loop, but we follow the BOLT
164169
* literally to make comments in test vectors clearer. */
165170

@@ -176,6 +181,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
176181
continue;
177182
add_offered_htlc_out(tx, n, htlcs[i], keyset);
178183
(*htlcmap)[n] = htlcs[i];
184+
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
179185
n++;
180186
}
181187

@@ -191,6 +197,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
191197
continue;
192198
add_received_htlc_out(tx, n, htlcs[i], keyset);
193199
(*htlcmap)[n] = htlcs[i];
200+
cltvs[n] = abs_locktime_to_blocks(&htlcs[i]->expiry);
194201
n++;
195202
}
196203

@@ -205,6 +212,8 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
205212
tx->output[n].amount = self_pay_msat / 1000;
206213
tx->output[n].script = scriptpubkey_p2wsh(tx, wscript);
207214
(*htlcmap)[n] = NULL;
215+
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
216+
* However, valgrind will warn us something wierd is happening */
208217
SUPERVERBOSE("# to-local amount %"PRIu64" wscript %s\n",
209218
tx->output[n].amount,
210219
tal_hex(tmpctx, wscript));
@@ -229,6 +238,8 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
229238
tx->output[n].script = scriptpubkey_p2wpkh(tx,
230239
&keyset->other_payment_key);
231240
(*htlcmap)[n] = NULL;
241+
/* We don't assign cltvs[n]: if we use it, order doesn't matter.
242+
* However, valgrind will warn us something wierd is happening */
232243
SUPERVERBOSE("# to-remote amount %"PRIu64" P2WPKH(%s)\n",
233244
tx->output[n].amount,
234245
type_to_string(tmpctx, struct pubkey,
@@ -245,8 +256,7 @@ struct bitcoin_tx *commit_tx(const tal_t *ctx,
245256
* 7. Sort the outputs into [BIP 69
246257
* order](#transaction-input-and-output-ordering)
247258
*/
248-
permute_outputs(tx->output, tal_count(tx->output),
249-
(const void **)*htlcmap);
259+
permute_outputs(tx->output, cltvs, (const void **)*htlcmap);
250260

251261
/* BOLT #3:
252262
*

‎common/close_tx.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,6 @@ struct bitcoin_tx *create_close_tx(const tal_t *ctx,
5858
return tal_free(tx);
5959
tal_resize(&tx->output, num_outputs);
6060

61-
permute_outputs(tx->output, num_outputs, NULL);
61+
permute_outputs(tx->output, NULL, NULL);
6262
return tx;
6363
}

‎common/funding_tx.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,12 @@ struct bitcoin_tx *funding_tx(const tal_t *ctx,
5252
map[1] = int2ptr(1);
5353
tx->output[1].script = scriptpubkey_p2wpkh(tx, changekey);
5454
tx->output[1].amount = change_satoshis;
55-
permute_outputs(tx->output, tal_count(tx->output), map);
55+
permute_outputs(tx->output, NULL, map);
5656
*outnum = (map[0] == int2ptr(0) ? 0 : 1);
5757
} else {
5858
*outnum = 0;
5959
}
6060

61-
permute_inputs(tx->input, tal_count(tx->input), (const void **)utxomap);
61+
permute_inputs(tx->input, (const void **)utxomap);
6262
return tx;
6363
}

‎common/initial_commit_tx.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ struct bitcoin_tx *initial_commit_tx(const tal_t *ctx,
194194
* 7. Sort the outputs into [BIP 69
195195
* order](#transaction-input-and-output-ordering)
196196
*/
197-
permute_outputs(tx->output, tal_count(tx->output), NULL);
197+
permute_outputs(tx->output, NULL, NULL);
198198

199199
/* BOLT #3:
200200
*

‎common/permute_tx.c

+42-14
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ static void swap_inputs(struct bitcoin_tx_input *inputs,
5454
}
5555
}
5656

57-
void permute_inputs(struct bitcoin_tx_input *inputs, size_t num_inputs,
57+
void permute_inputs(struct bitcoin_tx_input *inputs,
5858
const void **map)
5959
{
6060
size_t i;
61+
size_t num_inputs = tal_count(inputs);
6162

6263
/* We can't permute nothing! */
6364
if (num_inputs == 0)
@@ -73,10 +74,10 @@ void permute_inputs(struct bitcoin_tx_input *inputs, size_t num_inputs,
7374

7475
static void swap_outputs(struct bitcoin_tx_output *outputs,
7576
const void **map,
77+
u32 *cltvs,
7678
size_t i1, size_t i2)
7779
{
7880
struct bitcoin_tx_output tmpoutput;
79-
const void *tmp;
8081

8182
if (i1 == i2)
8283
return;
@@ -86,49 +87,74 @@ static void swap_outputs(struct bitcoin_tx_output *outputs,
8687
outputs[i2] = tmpoutput;
8788

8889
if (map) {
89-
tmp = map[i1];
90+
const void *tmp = map[i1];
9091
map[i1] = map[i2];
9192
map[i2] = tmp;
9293
}
94+
95+
if (cltvs) {
96+
u32 tmp = cltvs[i1];
97+
cltvs[i1] = cltvs[i2];
98+
cltvs[i2] = tmp;
99+
}
93100
}
94101

95102
static bool output_better(const struct bitcoin_tx_output *a,
96-
const struct bitcoin_tx_output *b)
103+
u32 cltv_a,
104+
const struct bitcoin_tx_output *b,
105+
u32 cltv_b)
97106
{
98-
size_t len;
107+
size_t len, lena, lenb;
99108
int ret;
100109

101110
if (a->amount != b->amount)
102111
return a->amount < b->amount;
103112

104113
/* Lexicographical sort. */
105-
if (tal_count(a->script) < tal_count(b->script))
106-
len = tal_count(a->script);
114+
lena = tal_count(a->script);
115+
lenb = tal_count(b->script);
116+
if (lena < lenb)
117+
len = lena;
107118
else
108-
len = tal_count(b->script);
119+
len = lenb;
109120

110121
ret = memcmp(a->script, b->script, len);
111122
if (ret != 0)
112123
return ret < 0;
113124

114-
return tal_count(a->script) < tal_count(b->script);
125+
if (lena != lenb)
126+
return lena < lenb;
127+
128+
return cltv_a < cltv_b;
129+
}
130+
131+
static u32 cltv_of(const u32 *cltvs, size_t idx)
132+
{
133+
if (!cltvs)
134+
return 0;
135+
return cltvs[idx];
115136
}
116137

117-
static size_t find_best_out(struct bitcoin_tx_output *outputs, size_t num)
138+
static size_t find_best_out(struct bitcoin_tx_output *outputs,
139+
const u32 *cltvs,
140+
size_t num)
118141
{
119142
size_t i, best = 0;
120143

121144
for (i = 1; i < num; i++) {
122-
if (output_better(&outputs[i], &outputs[best]))
145+
if (output_better(&outputs[i], cltv_of(cltvs, i),
146+
&outputs[best], cltv_of(cltvs, best)))
123147
best = i;
124148
}
125149
return best;
126150
}
127151

128-
void permute_outputs(struct bitcoin_tx_output *outputs, size_t num_outputs,
152+
void permute_outputs(struct bitcoin_tx_output *outputs,
153+
u32 *cltvs,
129154
const void **map)
130155
{
131156
size_t i;
157+
size_t num_outputs = tal_count(outputs);
132158

133159
/* We can't permute nothing! */
134160
if (num_outputs == 0)
@@ -137,7 +163,9 @@ void permute_outputs(struct bitcoin_tx_output *outputs, size_t num_outputs,
137163
/* Now do a dumb sort (num_outputs is small). */
138164
for (i = 0; i < num_outputs-1; i++) {
139165
/* Swap best into first place. */
140-
swap_outputs(outputs, map,
141-
i, i + find_best_out(outputs + i, num_outputs - i));
166+
swap_outputs(outputs, map, cltvs,
167+
i, i + find_best_out(outputs + i,
168+
cltvs ? cltvs + i : NULL,
169+
num_outputs - i));
142170
}
143171
}

‎common/permute_tx.h

+13-5
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,23 @@
55

66
struct htlc;
77

8-
/* Permute the transaction into BIP69 order. */
9-
void permute_inputs(struct bitcoin_tx_input *inputs, size_t num_inputs,
10-
const void **map);
8+
/**
9+
* permute_inputs: permute the transaction inputs into BIP69 order.
10+
* @inputs: usually bitcoin_tx->inputs, must be tal_arr.
11+
* @map: if non-NULL, pointers to be permuted the same as the inputs.
12+
*/
13+
void permute_inputs(struct bitcoin_tx_input *inputs, const void **map);
1114

12-
/* If @map is non-NULL, it will be permuted the same as the outputs.
15+
/**
16+
* permute_outputs: permute the transaction outputs into BIP69 + cltv order.
17+
* @outputs: usually bitcoin_tx->outputs, must be tal_arr.
18+
* @cltvs: CLTV delays to use as a tie-breaker, or NULL.
19+
* @map: if non-NULL, pointers to be permuted the same as the outputs.
1320
*
1421
* So the caller initiates the map with which htlcs are used, it
1522
* can easily see which htlc (if any) is in output #0 with map[0].
1623
*/
17-
void permute_outputs(struct bitcoin_tx_output *outputs, size_t num_outputs,
24+
void permute_outputs(struct bitcoin_tx_output *outputs,
25+
u32 *cltvs,
1826
const void **map);
1927
#endif /* LIGHTNING_COMMON_PERMUTE_TX_H */

‎common/withdraw_tx.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ struct bitcoin_tx *withdraw_tx(const tal_t *ctx,
3838
map[1] = int2ptr(1);
3939
tx->output[1].script = scriptpubkey_p2wpkh(tx, changekey);
4040
tx->output[1].amount = changesat;
41-
permute_outputs(tx->output, tal_count(tx->output), map);
41+
permute_outputs(tx->output, NULL, map);
4242
}
43-
permute_inputs(tx->input, tal_count(tx->input), (const void **)utxos);
43+
permute_inputs(tx->input, (const void **)utxos);
4444
return tx;
4545
}
4646

‎tests/test_pay.py

-1
Original file line numberDiff line numberDiff line change
@@ -1049,7 +1049,6 @@ def test_forward_stats(node_factory, bitcoind):
10491049
assert l3.rpc.getinfo()['msatoshi_fees_collected'] == 0
10501050

10511051

1052-
@pytest.mark.xfail(strict=True)
10531052
@unittest.skipIf(not DEVELOPER, "needs DEVELOPER=1 for dev_ignore_htlcs")
10541053
def test_htlcs_cltv_only_difference(node_factory, bitcoind):
10551054
# l1 -> l2 -> l3 -> l4

0 commit comments

Comments
 (0)
Please sign in to comment.