Skip to content

Commit cb70577

Browse files
committed
splice: Implement start_batch
Implement the sending and receiving of `start_batch` as per t-bast’s spec. Changelog-Added: support for `start_batch`
1 parent f2f7b6e commit cb70577

File tree

13 files changed

+235
-51
lines changed

13 files changed

+235
-51
lines changed

channeld/channeld.c

Lines changed: 118 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,12 +1197,7 @@ static u8 *send_commit_part(const tal_t *ctx,
11971197
(int)splice_amnt, (int)remote_splice_amnt,
11981198
remote_index);
11991199

1200-
if (batch_size > 1) {
1201-
cs_tlv->splice_info = tal(cs_tlv, struct tlv_commitment_signed_tlvs_splice_info);
1202-
1203-
cs_tlv->splice_info->batch_size = batch_size;
1204-
cs_tlv->splice_info->funding_txid = funding->txid;
1205-
}
1200+
cs_tlv->splice_info = tal_dup(cs_tlv, struct bitcoin_txid, &funding->txid);
12061201
}
12071202

12081203
txs = channel_txs(tmpctx, funding, funding_sats, &htlc_map,
@@ -1274,6 +1269,72 @@ static s64 sats_diff(struct amount_sat a, struct amount_sat b)
12741269
return (s64)a.satoshis - (s64)b.satoshis; /* Raw: splicing numbers can wrap! */
12751270
}
12761271

1272+
static void send_message_batch(struct peer *peer, u8 **msgs)
1273+
{
1274+
size_t size;
1275+
size_t hdr_size = tal_bytelen(towire_protocol_batch_element(tmpctx,
1276+
&peer->channel_id,
1277+
0));
1278+
u8 *batch_msg, *final_msg, *final_msg_ptr;
1279+
struct tlv_start_batch_tlvs *tlvs;
1280+
1281+
assert(tal_count(msgs) > 0);
1282+
1283+
if (tal_count(msgs) == 1) {
1284+
peer_write(peer->pps, msgs[0]);
1285+
return;
1286+
}
1287+
1288+
/* We prefix each message with an interal wire type,
1289+
* protocol_batch_element. connectd will eat each message so they don't
1290+
* actually go out to the peer. It's just so connectd can chop up the
1291+
* message batch back out into individual messages. */
1292+
1293+
size = 0;
1294+
for(u32 i = 0; i < tal_count(msgs); i++)
1295+
size += tal_bytelen(msgs[i]) + hdr_size;
1296+
1297+
tlvs = tlv_start_batch_tlvs_new(tmpctx);
1298+
tlvs->batch_info = tal(tlvs, u16);
1299+
*tlvs->batch_info = WIRE_COMMITMENT_SIGNED;
1300+
batch_msg = towire_start_batch(tmpctx, &peer->channel_id,
1301+
tal_count(msgs), tlvs);
1302+
size += tal_bytelen(batch_msg) + hdr_size;
1303+
1304+
/* Now we know the size of our `final_msg` so we allocate. */
1305+
final_msg = tal_arr(tmpctx, u8, size);
1306+
final_msg_ptr = final_msg;
1307+
1308+
status_debug("proto_batch Building batch with %zu bytes, msgs: %zu",
1309+
size, tal_count(msgs));
1310+
1311+
memcpy(final_msg_ptr,
1312+
towire_protocol_batch_element(tmpctx,
1313+
&peer->channel_id,
1314+
tal_bytelen(batch_msg)),
1315+
hdr_size);
1316+
final_msg_ptr += hdr_size;
1317+
1318+
memcpy(final_msg_ptr, batch_msg, tal_bytelen(batch_msg));
1319+
final_msg_ptr += tal_bytelen(batch_msg);
1320+
1321+
/* Now copy the bytes from all messages in `msgs` */
1322+
for(u32 i = 0; i < tal_count(msgs); i++) {
1323+
memcpy(final_msg_ptr,
1324+
towire_protocol_batch_element(tmpctx,
1325+
&peer->channel_id,
1326+
tal_bytelen(msgs[i])),
1327+
hdr_size);
1328+
final_msg_ptr += hdr_size;
1329+
1330+
memcpy(final_msg_ptr, msgs[i], tal_bytelen(msgs[i]));
1331+
final_msg_ptr += tal_bytelen(msgs[i]);
1332+
}
1333+
1334+
assert(final_msg + size == final_msg_ptr);
1335+
peer_write(peer->pps, take(final_msg));
1336+
}
1337+
12771338
static void send_commit(struct peer *peer)
12781339
{
12791340
const struct htlc **changed_htlcs;
@@ -1440,8 +1501,7 @@ static void send_commit(struct peer *peer)
14401501

14411502
peer->next_index[REMOTE]++;
14421503

1443-
for(u32 i = 0; i < tal_count(msgs); i++)
1444-
peer_write(peer->pps, take(msgs[i]));
1504+
send_message_batch(peer, msgs);
14451505

14461506
maybe_send_shutdown(peer);
14471507

@@ -1963,11 +2023,11 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
19632023
if (peer->splice_state->await_commitment_succcess
19642024
&& !tal_count(peer->splice_state->inflights) && cs_tlv && cs_tlv->splice_info) {
19652025
if (!bitcoin_txid_eq(&peer->channel->funding.txid,
1966-
&cs_tlv->splice_info->funding_txid)) {
2026+
cs_tlv->splice_info)) {
19672027
status_info("Ignoring stale commit_sig for channel_id"
19682028
" %s, as %s is locked in now.",
19692029
fmt_bitcoin_txid(tmpctx,
1970-
&cs_tlv->splice_info->funding_txid),
2030+
cs_tlv->splice_info),
19712031
fmt_bitcoin_txid(tmpctx,
19722032
&peer->channel->funding.txid));
19732033
return NULL;
@@ -2017,22 +2077,17 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
20172077
outpoint = peer->splice_state->inflights[commit_index - 1]->outpoint;
20182078
funding_sats = peer->splice_state->inflights[commit_index - 1]->amnt;
20192079

2020-
if (cs_tlv && cs_tlv->splice_info
2021-
&& cs_tlv->splice_info->batch_size == 1)
2022-
peer_failed_err(peer->pps, &peer->channel_id,
2023-
"batch_size can never be 1");
2024-
20252080
status_debug("handle_peer_commit_sig for inflight outpoint %s",
20262081
fmt_bitcoin_txid(tmpctx, &outpoint.txid));
20272082

20282083
if (cs_tlv->splice_info
20292084
&& !bitcoin_txid_eq(&outpoint.txid,
2030-
&cs_tlv->splice_info->funding_txid))
2085+
cs_tlv->splice_info))
20312086
peer_failed_err(peer->pps, &peer->channel_id,
20322087
"Expected commit sig message for %s but"
20332088
" got %s",
20342089
fmt_bitcoin_txid(tmpctx, &outpoint.txid),
2035-
fmt_bitcoin_txid(tmpctx, &cs_tlv->splice_info->funding_txid));
2090+
fmt_bitcoin_txid(tmpctx, cs_tlv->splice_info));
20362091
}
20372092
else {
20382093
outpoint = peer->channel->funding;
@@ -2089,7 +2144,7 @@ static struct commitsig_info *handle_peer_commit_sig(struct peer *peer,
20892144
fmt_amount_sat(tmpctx, funding_sats),
20902145
cs_tlv && cs_tlv->splice_info
20912146
? fmt_bitcoin_txid(tmpctx,
2092-
&cs_tlv->splice_info->funding_txid)
2147+
cs_tlv->splice_info)
20932148
: "N/A",
20942149
peer->splice_state->await_commitment_succcess ? "yes"
20952150
: "no",
@@ -2253,7 +2308,7 @@ static int commit_index_from_msg(const u8 *msg, struct peer *peer)
22532308
if (!cs_tlv || !cs_tlv->splice_info)
22542309
return -1;
22552310

2256-
funding_txid = cs_tlv->splice_info->funding_txid;
2311+
funding_txid = *cs_tlv->splice_info;
22572312

22582313
if (bitcoin_txid_eq(&funding_txid, &peer->channel->funding.txid))
22592314
return 0;
@@ -2306,28 +2361,29 @@ static struct commitsig_info *handle_peer_commit_sig_batch(struct peer *peer,
23062361
s64 remote_splice_amnt,
23072362
u64 local_index,
23082363
const struct pubkey *local_per_commit,
2309-
bool allow_empty_commit)
2364+
bool allow_empty_commit,
2365+
u16 batch_size)
23102366
{
23112367
struct channel_id channel_id;
23122368
struct bitcoin_signature commit_sig;
23132369
secp256k1_ecdsa_signature *raw_sigs;
2314-
u16 batch_size;
23152370
const u8 **msg_batch;
23162371
enum peer_wire type;
23172372
struct tlv_commitment_signed_tlvs *cs_tlv
23182373
= tlv_commitment_signed_tlvs_new(tmpctx);
23192374
status_debug("fromwire_commitment_signed(%p) primary", msg);
2375+
check_tx_abort(peer, msg, NULL);
2376+
type = fromwire_peektype(msg);
2377+
if (type != WIRE_COMMITMENT_SIGNED)
2378+
peer_failed_err(peer->pps, &peer->channel_id,
2379+
"Expected WIRE_COMMITMENT_SIGNED but got %s.",
2380+
peer_wire_name(type));
23202381
if (!fromwire_commitment_signed(tmpctx, msg,
23212382
&channel_id, &commit_sig.s, &raw_sigs,
23222383
&cs_tlv))
23232384
peer_failed_warn(peer->pps, &peer->channel_id,
23242385
"Bad commit_sig %s", tal_hex(msg, msg));
23252386

2326-
/* Default batch_size is 1 */
2327-
batch_size = 1;
2328-
if (cs_tlv->splice_info && cs_tlv->splice_info->batch_size)
2329-
batch_size = cs_tlv->splice_info->batch_size;
2330-
23312387
msg_batch = tal_arr(tmpctx, const u8*, batch_size);
23322388
msg_batch[0] = msg;
23332389
status_debug("msg_batch[0]: %p", msg_batch[0]);
@@ -2363,14 +2419,6 @@ static struct commitsig_info *handle_peer_commit_sig_batch(struct peer *peer,
23632419
" splice_info",
23642420
tal_hex(sub_msg, sub_msg), i, batch_size);
23652421

2366-
if (!sub_cs_tlv->splice_info
2367-
|| sub_cs_tlv->splice_info->batch_size != batch_size)
2368-
peer_failed_err(peer->pps, &peer->channel_id,
2369-
"batch_size value mismatch in"
2370-
" commit_sig bundle, item [%"PRIu16
2371-
"/%"PRIu16"] %s", i, batch_size,
2372-
tal_hex(sub_msg, sub_msg));
2373-
23742422
msg_batch[i] = sub_msg;
23752423
status_debug("msg_batch[%d]: %p", (int)i, msg_batch[i]);
23762424
}
@@ -2385,6 +2433,35 @@ static struct commitsig_info *handle_peer_commit_sig_batch(struct peer *peer,
23852433
allow_empty_commit, msg_batch);
23862434
}
23872435

2436+
static void handle_peer_start_batch(struct peer *peer, const u8 *msg)
2437+
{
2438+
u16 batch_size;
2439+
struct channel_id channel_id;
2440+
struct tlv_start_batch_tlvs *tlvs;
2441+
if (!fromwire_start_batch(tmpctx, msg, &channel_id, &batch_size, &tlvs))
2442+
peer_failed_warn(peer->pps, &peer->channel_id,
2443+
"Bad start_batch %s", tal_hex(msg, msg));
2444+
2445+
if (!tlvs || !tlvs->batch_info
2446+
|| *tlvs->batch_info != WIRE_COMMITMENT_SIGNED) {
2447+
status_unusual("Ignoring Unrecognized start_batch message type"
2448+
" %s, expected WIRE_COMMITMENT_SIGNED.",
2449+
tlvs && tlvs->batch_info
2450+
? peer_wire_name(*tlvs->batch_info)
2451+
: "N/A");
2452+
return;
2453+
}
2454+
2455+
handle_peer_commit_sig_batch(peer, peer_read(tmpctx, peer->pps), 0,
2456+
peer->channel->funding_pubkey[REMOTE],
2457+
NULL, 0, 0,
2458+
peer->next_index[LOCAL],
2459+
&peer->next_local_per_commit,
2460+
false,
2461+
batch_size);
2462+
}
2463+
2464+
23882465
/* Pops the penalty base for the given commitnum from our internal list. There
23892466
* may not be one, in which case we return NULL and leave the list
23902467
* unmodified. */
@@ -4850,13 +4927,17 @@ static void peer_in(struct peer *peer, const u8 *msg)
48504927
case WIRE_UPDATE_ADD_HTLC:
48514928
handle_peer_add_htlc(peer, msg);
48524929
return;
4930+
case WIRE_START_BATCH:
4931+
handle_peer_start_batch(peer, msg);
4932+
return;
48534933
case WIRE_COMMITMENT_SIGNED:
48544934
handle_peer_commit_sig_batch(peer, msg, 0,
48554935
peer->channel->funding_pubkey[REMOTE],
48564936
NULL, 0, 0,
48574937
peer->next_index[LOCAL],
48584938
&peer->next_local_per_commit,
4859-
false);
4939+
false,
4940+
1);
48604941
return;
48614942
case WIRE_UPDATE_FEE:
48624943
handle_peer_feechange(peer, msg);
@@ -4920,6 +5001,7 @@ static void peer_in(struct peer *peer, const u8 *msg)
49205001
return;
49215002

49225003
/* These are all swallowed by connectd */
5004+
case WIRE_PROTOCOL_BATCH_ELEMENT:
49235005
case WIRE_CHANNEL_ANNOUNCEMENT:
49245006
case WIRE_CHANNEL_UPDATE:
49255007
case WIRE_NODE_ANNOUNCEMENT:
@@ -5122,8 +5204,7 @@ static void resend_commitment(struct peer *peer, struct changed_htlc *last)
51225204
peer->splice_state->inflights[i]->remote_funding));
51235205
}
51245206

5125-
for(i = 0; i < tal_count(msgs); i++)
5126-
peer_write(peer->pps, take(msgs[i]));
5207+
send_message_batch(peer, msgs);
51275208

51285209
/* If we have already received the revocation for the previous, the
51295210
* other side shouldn't be asking for a retransmit! */

common/gossmap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,8 @@ const void *gossmap_stream_next(const tal_t *ctx,
17991799
case WIRE_UPDATE_FULFILL_HTLC:
18001800
case WIRE_UPDATE_FAIL_HTLC:
18011801
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
1802+
case WIRE_PROTOCOL_BATCH_ELEMENT:
1803+
case WIRE_START_BATCH:
18021804
case WIRE_COMMITMENT_SIGNED:
18031805
case WIRE_REVOKE_AND_ACK:
18041806
case WIRE_UPDATE_FEE:

common/interactivetx.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ static u8 *read_next_msg(const tal_t *ctx,
163163
case WIRE_UPDATE_FULFILL_HTLC:
164164
case WIRE_UPDATE_FAIL_HTLC:
165165
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
166+
case WIRE_PROTOCOL_BATCH_ELEMENT:
167+
case WIRE_START_BATCH:
166168
case WIRE_COMMITMENT_SIGNED:
167169
case WIRE_REVOKE_AND_ACK:
168170
case WIRE_UPDATE_FEE:
@@ -771,6 +773,8 @@ char *process_interactivetx_updates(const tal_t *ctx,
771773
case WIRE_UPDATE_FULFILL_HTLC:
772774
case WIRE_UPDATE_FAIL_HTLC:
773775
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
776+
case WIRE_PROTOCOL_BATCH_ELEMENT:
777+
case WIRE_START_BATCH:
774778
case WIRE_COMMITMENT_SIGNED:
775779
case WIRE_REVOKE_AND_ACK:
776780
case WIRE_UPDATE_FEE:

common/status_levels.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ enum status_failreason {
3737
/* Gossipd sent unknown/malformed command, or fd failed */
3838
STATUS_FAIL_GOSSIP_IO,
3939

40+
/* Connect daemon received a malformed protocol_batch_element */
41+
STATUS_FAIL_PROTO_BATCH,
42+
4043
/* Other internal error. */
4144
STATUS_FAIL_INTERNAL_ERROR,
4245
};

connectd/gossip_rcvd_filter.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ static bool is_msg_gossip_broadcast(const u8 *cursor)
7373
case WIRE_UPDATE_FULFILL_HTLC:
7474
case WIRE_UPDATE_FAIL_HTLC:
7575
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
76+
case WIRE_PROTOCOL_BATCH_ELEMENT:
77+
case WIRE_START_BATCH:
7678
case WIRE_COMMITMENT_SIGNED:
7779
case WIRE_REVOKE_AND_ACK:
7880
case WIRE_UPDATE_FEE:

connectd/gossip_store.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ static bool public_msg_type(enum peer_wire type)
8282
case WIRE_UPDATE_FULFILL_HTLC:
8383
case WIRE_UPDATE_FAIL_HTLC:
8484
case WIRE_UPDATE_FAIL_MALFORMED_HTLC:
85+
case WIRE_PROTOCOL_BATCH_ELEMENT:
86+
case WIRE_START_BATCH:
8587
case WIRE_COMMITMENT_SIGNED:
8688
case WIRE_REVOKE_AND_ACK:
8789
case WIRE_UPDATE_FEE:

0 commit comments

Comments
 (0)