Skip to content

Commit d46a049

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 ee6ded1 commit d46a049

File tree

1 file changed

+151
-21
lines changed

1 file changed

+151
-21
lines changed

channeld/channeld.c

Lines changed: 151 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1887,6 +1887,10 @@ struct commitsig_info {
18871887
*
18881888
* `commit_index` 0 refers to the funding commit. `commit_index` 1 and above
18891889
* refer to inflight splices.
1890+
*
1891+
* `msg_batch` refers to the entire batch of messages in this commit_sig bundle
1892+
* with index 0 being the funding commit_sig and the rest being inflights. The
1893+
* inflight msgs must be in the same order as the inflight array.
18901894
*/
18911895
static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
18921896
const u8 *msg,
@@ -1897,7 +1901,8 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
18971901
s64 remote_splice_amnt,
18981902
u64 local_index,
18991903
const struct pubkey *local_per_commit,
1900-
bool allow_empty_commit)
1904+
bool allow_empty_commit,
1905+
const u8 **msg_batch)
19011906
{
19021907
struct commitsig_info *result;
19031908
struct channel_id channel_id;
@@ -1911,8 +1916,6 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
19111916
size_t i;
19121917
struct simple_htlc **htlcs;
19131918
const u8 * msg2;
1914-
u8 *splice_msg;
1915-
int type;
19161919
struct bitcoin_outpoint outpoint;
19171920
struct amount_sat funding_sats;
19181921
struct channel_id active_id;
@@ -2142,9 +2145,17 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
21422145
result->old_secret = old_secret;
21432146
/* Only the parent call continues from here.
21442147
* Return for all child calls. */
2145-
if(commit_index)
2148+
if (commit_index)
21462149
return result;
21472150

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

2157-
splice_msg = peer_read(tmpctx, peer->pps);
2158-
check_tx_abort(peer, splice_msg);
2159-
/* Check type for cleaner failure message */
2160-
type = fromwire_peektype(msg);
2161-
if (type != WIRE_COMMITMENT_SIGNED)
2162-
peer_failed_err(peer->pps, &peer->channel_id,
2163-
"Expected splice related "
2164-
"WIRE_COMMITMENT_SIGNED but got %s",
2165-
peer_wire_name(type));
2166-
21672168
/* We purposely just store the last commit msg in result */
2168-
result = handle_peer_commit_sig(peer, splice_msg, i + 1,
2169+
result = handle_peer_commit_sig(peer, msg_batch[i + 1], i + 1,
21692170
peer->splice_state->inflights[i]->remote_funding,
21702171
changed_htlcs, sub_splice_amnt,
21712172
funding_diff - sub_splice_amnt,
21722173
local_index, local_per_commit,
2173-
allow_empty_commit);
2174+
allow_empty_commit, NULL);
21742175
old_secret = result->old_secret;
21752176
tal_arr_expand(&commitsigs, result->commitsig);
21762177
tal_steal(commitsigs, result);
@@ -2199,6 +2200,132 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
21992200
return result;
22002201
}
22012202

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

@@ -4569,10 +4697,12 @@ static void peer_in(struct peer *peer, const u8 *msg)
45694697
handle_peer_add_htlc(peer, msg);
45704698
return;
45714699
case WIRE_COMMITMENT_SIGNED:
4572-
handle_peer_commit_sig(peer, msg, 0,
4573-
peer->channel->funding_pubkey[REMOTE],
4574-
NULL, 0, 0, peer->next_index[LOCAL],
4575-
&peer->next_local_per_commit, false);
4700+
handle_peer_commit_sig_batch(peer, msg, 0,
4701+
peer->channel->funding_pubkey[REMOTE],
4702+
NULL, 0, 0,
4703+
peer->next_index[LOCAL],
4704+
&peer->next_local_per_commit,
4705+
false);
45764706
return;
45774707
case WIRE_UPDATE_FEE:
45784708
handle_peer_feechange(peer, msg);

0 commit comments

Comments
 (0)