Skip to content

Commit 2f196dc

Browse files
committed
splice: Allow commit_sig batch in any order
Other implementations are sending commit_sig batches in different orders. We add support for them being in any order by ordering the batch of messages after receiving them. Changelog-Changed: Increase interop compatability by loosening requirement that commitment signed messages be received in a particular order and sorting them internally.
1 parent 9dfc62b commit 2f196dc

File tree

1 file changed

+155
-21
lines changed

1 file changed

+155
-21
lines changed

channeld/channeld.c

Lines changed: 155 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,10 @@ struct commitsig_info {
18891889
*
18901890
* `commit_index` 0 refers to the funding commit. `commit_index` 1 and above
18911891
* refer to inflight splices.
1892+
*
1893+
* `msg_batch` refers to the entire batch of messages in this commit_sig bundle
1894+
* with index 0 being the funding commit_sig and the rest being inflights. The
1895+
* inflight msgs must be in the same order as the inflight array.
18921896
*/
18931897
static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
18941898
const u8 *msg,
@@ -1899,7 +1903,8 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
18991903
s64 remote_splice_amnt,
19001904
u64 local_index,
19011905
const struct pubkey *local_per_commit,
1902-
bool allow_empty_commit)
1906+
bool allow_empty_commit,
1907+
const u8 **msg_batch)
19031908
{
19041909
struct commitsig_info *result;
19051910
struct channel_id channel_id;
@@ -1913,8 +1918,6 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
19131918
size_t i;
19141919
const struct hsm_htlc *htlcs;
19151920
const u8 * msg2;
1916-
u8 *splice_msg;
1917-
int type;
19181921
struct bitcoin_outpoint outpoint;
19191922
struct amount_sat funding_sats;
19201923
struct channel_id active_id;
@@ -2144,9 +2147,17 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
21442147
result->old_secret = old_secret;
21452148
/* Only the parent call continues from here.
21462149
* Return for all child calls. */
2147-
if(commit_index)
2150+
if (commit_index)
21482151
return result;
21492152

2153+
if (tal_count(msg_batch) - 1 < tal_count(peer->splice_state->inflights))
2154+
peer_failed_err(peer->pps, &peer->channel_id,
2155+
"commit_sig batch was too small (%zu). It must"
2156+
" include a commit sig for all inflights plus"
2157+
" channel funding (req: %zu).",
2158+
tal_count(msg_batch),
2159+
tal_count(peer->splice_state->inflights));
2160+
21502161
commitsigs = tal_arr(NULL, const struct commitsig*, 0);
21512162
/* We expect multiple consequtive commit_sig messages if we have
21522163
* inflight splices. Since consequtive is requred, we recurse for
@@ -2156,23 +2167,13 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
21562167
peer->channel->funding_sats);
21572168
s64 sub_splice_amnt = peer->splice_state->inflights[i]->splice_amnt;
21582169

2159-
splice_msg = peer_read(tmpctx, peer->pps);
2160-
check_tx_abort(peer, splice_msg);
2161-
/* Check type for cleaner failure message */
2162-
type = fromwire_peektype(msg);
2163-
if (type != WIRE_COMMITMENT_SIGNED)
2164-
peer_failed_err(peer->pps, &peer->channel_id,
2165-
"Expected splice related "
2166-
"WIRE_COMMITMENT_SIGNED but got %s",
2167-
peer_wire_name(type));
2168-
21692170
/* We purposely just store the last commit msg in result */
2170-
result = handle_peer_commit_sig(peer, splice_msg, i + 1,
2171+
result = handle_peer_commit_sig(peer, msg_batch[i + 1], i + 1,
21712172
peer->splice_state->inflights[i]->remote_funding,
21722173
changed_htlcs, sub_splice_amnt,
21732174
funding_diff - sub_splice_amnt,
21742175
local_index, local_per_commit,
2175-
allow_empty_commit);
2176+
allow_empty_commit, NULL);
21762177
old_secret = result->old_secret;
21772178
tal_arr_expand(&commitsigs, result->commitsig);
21782179
tal_steal(commitsigs, result);
@@ -2201,6 +2202,136 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
22012202
return result;
22022203
}
22032204

2205+
/* Returns 0 if this is for funding, and 1+ for items in inflight array.
2206+
* Returns -1 if the value is not recognized.
2207+
*/
2208+
static int commit_index_from_msg(const u8 *msg, struct peer *peer)
2209+
{
2210+
struct channel_id funding_id;
2211+
struct channel_id channel_id;
2212+
struct bitcoin_signature commit_sig;
2213+
secp256k1_ecdsa_signature *raw_sigs;
2214+
struct tlv_commitment_signed_tlvs *cs_tlv
2215+
= tlv_commitment_signed_tlvs_new(tmpctx);
2216+
fromwire_commitment_signed(tmpctx, msg, &channel_id, &commit_sig.s,
2217+
&raw_sigs, &cs_tlv);
2218+
2219+
derive_channel_id(&funding_id, &peer->channel->funding);
2220+
if (channel_id_eq(&funding_id, &channel_id))
2221+
return 0;
2222+
2223+
for (int i = 0; i < tal_count(peer->splice_state->inflights); i++) {
2224+
struct channel_id splice_id;
2225+
derive_channel_id(&splice_id,
2226+
&peer->splice_state->inflights[i]->outpoint);
2227+
2228+
if (channel_id_eq(&splice_id, &channel_id))
2229+
return i + 1;
2230+
}
2231+
2232+
return -1;
2233+
}
2234+
2235+
static int commit_cmp(const void *a, const void *n, void *peer)
2236+
{
2237+
int commit_index_a = commit_index_from_msg(*(u8**)a, peer);
2238+
int commit_index_n = commit_index_from_msg(*(u8**)n, peer);
2239+
2240+
if (commit_index_a == commit_index_n)
2241+
return 0;
2242+
2243+
/* Unrecognized commits go on the end */
2244+
if (commit_index_a == -1)
2245+
return 1;
2246+
2247+
if (commit_index_n == -1)
2248+
return -1;
2249+
2250+
/* Otherwise we sort by commit_index */
2251+
return commit_index_a - commit_index_n;
2252+
}
2253+
2254+
static struct commitsig_info *handle_peer_commit_sig_batch(struct peer *peer,
2255+
const u8 *msg,
2256+
u32 commit_index,
2257+
struct pubkey remote_funding,
2258+
const struct htlc **changed_htlcs,
2259+
s64 splice_amnt,
2260+
s64 remote_splice_amnt,
2261+
u64 local_index,
2262+
const struct pubkey *local_per_commit,
2263+
bool allow_empty_commit)
2264+
{
2265+
struct channel_id channel_id;
2266+
struct bitcoin_signature commit_sig;
2267+
secp256k1_ecdsa_signature *raw_sigs;
2268+
u16 batch_size;
2269+
const u8 **msg_batch;
2270+
enum peer_wire type;
2271+
struct tlv_commitment_signed_tlvs *cs_tlv
2272+
= tlv_commitment_signed_tlvs_new(tmpctx);
2273+
status_info("fromwire_commitment_signed(%p) primary", msg);
2274+
if (!fromwire_commitment_signed(tmpctx, msg,
2275+
&channel_id, &commit_sig.s, &raw_sigs,
2276+
&cs_tlv))
2277+
peer_failed_warn(peer->pps, &peer->channel_id,
2278+
"Bad commit_sig %s", tal_hex(msg, msg));
2279+
2280+
/* Default batch_size is 1 */
2281+
batch_size = 1;
2282+
if (cs_tlv->splice_info && cs_tlv->splice_info->batch_size)
2283+
batch_size = cs_tlv->splice_info->batch_size;
2284+
2285+
msg_batch = tal_arr(tmpctx, const u8*, batch_size);
2286+
msg_batch[0] = msg;
2287+
status_info("msg_batch[0]: %p", msg_batch[0]);
2288+
2289+
/* Already received commitment signed once, so start at i = 1 */
2290+
for (u16 i = 1; i < batch_size; i++) {
2291+
struct tlv_commitment_signed_tlvs *sub_cs_tlv
2292+
= tlv_commitment_signed_tlvs_new(tmpctx);
2293+
u8 *sub_msg = peer_read(tmpctx, peer->pps);
2294+
check_tx_abort(peer, sub_msg);
2295+
2296+
/* Check type for cleaner failure message */
2297+
type = fromwire_peektype(sub_msg);
2298+
if (type != WIRE_COMMITMENT_SIGNED)
2299+
peer_failed_err(peer->pps, &peer->channel_id,
2300+
"Expected splice related "
2301+
"WIRE_COMMITMENT_SIGNED but got %s",
2302+
peer_wire_name(type));
2303+
status_info("fromwire_commitment_signed(%p) splice index %d", sub_msg, (int)i);
2304+
if (!fromwire_commitment_signed(tmpctx, sub_msg,
2305+
&channel_id, &commit_sig.s,
2306+
&raw_sigs, &sub_cs_tlv))
2307+
peer_failed_warn(peer->pps, &peer->channel_id,
2308+
"Bad commit_sig %s"
2309+
" in commit_sig batch:"
2310+
" [%"PRIu16"/%"PRIu16"]",
2311+
tal_hex(sub_msg, sub_msg), i, batch_size);
2312+
2313+
if (!sub_cs_tlv->splice_info
2314+
|| sub_cs_tlv->splice_info->batch_size != batch_size)
2315+
peer_failed_err(peer->pps, &peer->channel_id,
2316+
"batch_size value mismatch in"
2317+
" commit_sig bundle, item [%"PRIu16
2318+
"/%"PRIu16"] %s", i, batch_size,
2319+
tal_hex(sub_msg, sub_msg));
2320+
2321+
msg_batch[i] = sub_msg;
2322+
status_info("msg_batch[%d]: %p", (int)i, msg_batch[i]);
2323+
}
2324+
2325+
status_info("Sorting the msg_batch of tal_count %d, batch_size: %d", (int)tal_count(msg_batch), (int)batch_size);
2326+
asort(msg_batch, tal_count(msg_batch), commit_cmp, peer);
2327+
2328+
return handle_peer_commit_sig(peer, msg, commit_index, remote_funding,
2329+
changed_htlcs, splice_amnt,
2330+
remote_splice_amnt, local_index,
2331+
local_per_commit, allow_empty_commit,
2332+
msg_batch);
2333+
}
2334+
22042335
/* Pops the penalty base for the given commitnum from our internal list. There
22052336
* may not be one, in which case we return NULL and leave the list
22062337
* unmodified. */
@@ -2847,7 +2978,8 @@ static struct commitsig *interactive_send_commitments(struct peer *peer,
28472978
remote_splice_amnt,
28482979
next_index_local - 1,
28492980
&my_current_per_commitment_point,
2850-
true);
2981+
true,
2982+
NULL);
28512983
}
28522984
}
28532985

@@ -4571,10 +4703,12 @@ static void peer_in(struct peer *peer, const u8 *msg)
45714703
handle_peer_add_htlc(peer, msg);
45724704
return;
45734705
case WIRE_COMMITMENT_SIGNED:
4574-
handle_peer_commit_sig(peer, msg, 0,
4575-
peer->channel->funding_pubkey[REMOTE],
4576-
NULL, 0, 0, peer->next_index[LOCAL],
4577-
&peer->next_local_per_commit, false);
4706+
handle_peer_commit_sig_batch(peer, msg, 0,
4707+
peer->channel->funding_pubkey[REMOTE],
4708+
NULL, 0, 0,
4709+
peer->next_index[LOCAL],
4710+
&peer->next_local_per_commit,
4711+
false);
45784712
return;
45794713
case WIRE_UPDATE_FEE:
45804714
handle_peer_feechange(peer, msg);

0 commit comments

Comments
 (0)