Skip to content

Commit 97118cf

Browse files
committed
Handle batched commitment_signed messages
Update commitment_signed message to contain the funding_txid instead of both that and a batch_size. The spec was updated to batch messages using start_batch, which contains the batch_size. This commit also updates PeerManager to batch commitment_signed messages in this manner instead of the previous custom approach.
1 parent 2461f1a commit 97118cf

File tree

6 files changed

+58
-65
lines changed

6 files changed

+58
-65
lines changed

lightning/src/ln/channel.rs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4943,7 +4943,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
49434943
channel_id: self.channel_id,
49444944
htlc_signatures: vec![],
49454945
signature,
4946-
batch: None,
4946+
funding_txid: funding.get_funding_txo().map(|funding_txo| funding_txo.txid),
49474947
#[cfg(taproot)]
49484948
partial_signature_with_nonce: None,
49494949
})
@@ -5909,10 +5909,6 @@ impl<SP: Deref> FundedChannel<SP> where
59095909
)));
59105910
}
59115911

5912-
if msg.batch.is_some() {
5913-
return Err(ChannelError::close("Peer sent initial commitment_signed with a batch".to_owned()));
5914-
}
5915-
59165912
let holder_commitment_point = &mut self.holder_commitment_point.clone();
59175913
self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "initial commitment_signed");
59185914

@@ -9176,20 +9172,11 @@ impl<SP: Deref> FundedChannel<SP> where
91769172
}
91779173
}
91789174

9179-
let batch = if self.pending_funding.is_empty() { None } else {
9180-
Some(msgs::CommitmentSignedBatch {
9181-
batch_size: self.pending_funding.len() as u16 + 1,
9182-
funding_txid: funding
9183-
.get_funding_txo()
9184-
.expect("splices should have their funding transactions negotiated before exiting quiescence while un-negotiated splices are discarded on reload")
9185-
.txid,
9186-
})
9187-
};
91889175
Ok(msgs::CommitmentSigned {
91899176
channel_id: self.context.channel_id,
91909177
signature,
91919178
htlc_signatures,
9192-
batch,
9179+
funding_txid: funding.get_funding_txo().map(|funding_txo| funding_txo.txid),
91939180
#[cfg(taproot)]
91949181
partial_signature_with_nonce: None,
91959182
})

lightning/src/ln/dual_funding_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ fn do_test_v2_channel_establishment(session: V2ChannelEstablishmentTestSession)
183183
)
184184
.unwrap(),
185185
htlc_signatures: vec![],
186-
batch: None,
186+
funding_txid: None,
187187
#[cfg(taproot)]
188188
partial_signature_with_nonce: None,
189189
};

lightning/src/ln/htlc_reserve_unit_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -899,7 +899,7 @@ pub fn test_fee_spike_violation_fails_htlc() {
899899
channel_id: chan.2,
900900
signature: res.0,
901901
htlc_signatures: res.1,
902-
batch: None,
902+
funding_txid: None,
903903
#[cfg(taproot)]
904904
partial_signature_with_nonce: None,
905905
};

lightning/src/ln/msgs.rs

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -807,15 +807,6 @@ pub struct UpdateFailMalformedHTLC {
807807
pub failure_code: u16,
808808
}
809809

810-
/// Optional batch parameters for `commitment_signed` message.
811-
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
812-
pub struct CommitmentSignedBatch {
813-
/// Batch size N: all N `commitment_signed` messages must be received before being processed
814-
pub batch_size: u16,
815-
/// The funding transaction, to discriminate among multiple pending funding transactions (e.g. in case of splicing)
816-
pub funding_txid: Txid,
817-
}
818-
819810
/// A [`commitment_signed`] message to be sent to or received from a peer.
820811
///
821812
/// [`commitment_signed`]: https://github.com/lightning/bolts/blob/master/02-peer-protocol.md#committing-updates-so-far-commitment_signed
@@ -827,8 +818,8 @@ pub struct CommitmentSigned {
827818
pub signature: Signature,
828819
/// Signatures on the HTLC transactions
829820
pub htlc_signatures: Vec<Signature>,
830-
/// Optional batch size and other parameters
831-
pub batch: Option<CommitmentSignedBatch>,
821+
/// The funding transaction, to discriminate among multiple pending funding transactions (e.g. in case of splicing)
822+
pub funding_txid: Option<Txid>,
832823
#[cfg(taproot)]
833824
/// The partial Taproot signature on the commitment transaction
834825
pub partial_signature_with_nonce: Option<PartialSignatureWithNonce>,
@@ -1971,15 +1962,14 @@ pub trait ChannelMessageHandler: BaseMessageHandler {
19711962
) {
19721963
assert!(!batch.is_empty());
19731964
if batch.len() == 1 {
1974-
assert!(batch[0].batch.is_none());
19751965
self.handle_commitment_signed(their_node_id, &batch[0]);
19761966
} else {
19771967
let channel_id = batch[0].channel_id;
19781968
let batch: BTreeMap<Txid, CommitmentSigned> = batch
19791969
.iter()
19801970
.cloned()
1981-
.map(|mut cs| {
1982-
let funding_txid = cs.batch.take().unwrap().funding_txid;
1971+
.map(|cs| {
1972+
let funding_txid = cs.funding_txid.unwrap();
19831973
(funding_txid, cs)
19841974
})
19851975
.collect();
@@ -2753,18 +2743,13 @@ impl_writeable!(ClosingSignedFeeRange, {
27532743
max_fee_satoshis
27542744
});
27552745

2756-
impl_writeable_msg!(CommitmentSignedBatch, {
2757-
batch_size,
2758-
funding_txid,
2759-
}, {});
2760-
27612746
#[cfg(not(taproot))]
27622747
impl_writeable_msg!(CommitmentSigned, {
27632748
channel_id,
27642749
signature,
27652750
htlc_signatures
27662751
}, {
2767-
(0, batch, option),
2752+
(1, funding_txid, option),
27682753
});
27692754

27702755
#[cfg(taproot)]
@@ -2773,7 +2758,7 @@ impl_writeable_msg!(CommitmentSigned, {
27732758
signature,
27742759
htlc_signatures
27752760
}, {
2776-
(0, batch, option),
2761+
(1, funding_txid, option),
27772762
(2, partial_signature_with_nonce, option),
27782763
});
27792764

@@ -5634,13 +5619,10 @@ mod tests {
56345619
channel_id: ChannelId::from_bytes([2; 32]),
56355620
signature: sig_1,
56365621
htlc_signatures: if htlcs { vec![sig_2, sig_3, sig_4] } else { Vec::new() },
5637-
batch: Some(msgs::CommitmentSignedBatch {
5638-
batch_size: 3,
5639-
funding_txid: Txid::from_str(
5622+
funding_txid: Some(Txid::from_str(
56405623
"c2d4449afa8d26140898dd54d3390b057ba2a5afcf03ba29d7dc0d8b9ffe966e",
56415624
)
5642-
.unwrap(),
5643-
}),
5625+
.unwrap()),
56445626
#[cfg(taproot)]
56455627
partial_signature_with_nonce: None,
56465628
};
@@ -5651,7 +5633,7 @@ mod tests {
56515633
} else {
56525634
target_value += "0000";
56535635
}
5654-
target_value += "002200036e96fe9f8b0ddcd729ba03cfafa5a27b050b39d354dd980814268dfa9a44d4c2"; // batch
5636+
target_value += "01206e96fe9f8b0ddcd729ba03cfafa5a27b050b39d354dd980814268dfa9a44d4c2"; // funding_txid
56555637
assert_eq!(encoded_value.as_hex().to_string(), target_value);
56565638
}
56575639

lightning/src/ln/peer_handler.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ struct Peer {
618618

619619
inbound_connection: bool,
620620

621-
commitment_signed_batch: Option<(ChannelId, BTreeMap<Txid, msgs::CommitmentSigned>)>,
621+
commitment_signed_batch: Option<(ChannelId, usize, BTreeMap<Txid, msgs::CommitmentSigned>)>,
622622
}
623623

624624
impl Peer {
@@ -1770,41 +1770,58 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
17701770

17711771
// During splicing, commitment_signed messages need to be collected into a single batch
17721772
// before they are handled.
1773-
if let wire::Message::CommitmentSigned(msg) = message {
1774-
if let Some(ref batch) = msg.batch {
1775-
let (channel_id, buffer) = peer_lock
1776-
.commitment_signed_batch
1777-
.get_or_insert_with(|| (msg.channel_id, BTreeMap::new()));
1773+
if let wire::Message::StartBatch(msg) = message {
1774+
if peer_lock.commitment_signed_batch.is_some() {
1775+
log_debug!(logger, "Peer {} sent start_batch for channel {} before previous batch completed", log_pubkey!(their_node_id), &msg.channel_id);
1776+
return Err(PeerHandleError { }.into());
1777+
}
1778+
1779+
let batch_size = msg.batch_size as usize;
1780+
if batch_size <= 1 {
1781+
log_debug!(logger, "Peer {} sent start_batch for channel {} not strictly greater than 1", log_pubkey!(their_node_id), &msg.channel_id);
1782+
return Err(PeerHandleError { }.into());
1783+
}
17781784

1785+
const COMMITMENT_SIGNED_BATCH_LIMIT: usize = 20;
1786+
if batch_size > COMMITMENT_SIGNED_BATCH_LIMIT {
1787+
log_debug!(logger, "Peer {} sent start_batch for channel {} exceeding the limit", log_pubkey!(their_node_id), &msg.channel_id);
1788+
return Err(PeerHandleError { }.into());
1789+
}
1790+
1791+
peer_lock.commitment_signed_batch = Some((msg.channel_id, batch_size, BTreeMap::new()));
1792+
1793+
return Ok(None);
1794+
}
1795+
1796+
if let wire::Message::CommitmentSigned(msg) = message {
1797+
if let Some((channel_id, batch_size, buffer)) = &mut peer_lock.commitment_signed_batch {
17791798
if msg.channel_id != *channel_id {
17801799
log_debug!(logger, "Peer {} sent batched commitment_signed for the wrong channel (expected: {}, actual: {})", log_pubkey!(their_node_id), channel_id, &msg.channel_id);
17811800
return Err(PeerHandleError { }.into());
17821801
}
17831802

1784-
const COMMITMENT_SIGNED_BATCH_LIMIT: usize = 100;
1785-
if buffer.len() == COMMITMENT_SIGNED_BATCH_LIMIT {
1786-
log_debug!(logger, "Peer {} sent batched commitment_signed for channel {} exceeding the limit", log_pubkey!(their_node_id), channel_id);
1787-
return Err(PeerHandleError { }.into());
1788-
}
1803+
let funding_txid = match msg.funding_txid {
1804+
Some(funding_txid) => funding_txid,
1805+
None => {
1806+
log_debug!(logger, "Peer {} sent batched commitment_signed without a funding_txid for channel {}", log_pubkey!(their_node_id), channel_id);
1807+
return Err(PeerHandleError { }.into());
1808+
},
1809+
};
17891810

1790-
let batch_size = batch.batch_size as usize;
1791-
match buffer.entry(batch.funding_txid) {
1811+
match buffer.entry(funding_txid) {
17921812
btree_map::Entry::Vacant(entry) => { entry.insert(msg); },
17931813
btree_map::Entry::Occupied(_) => {
1794-
log_debug!(logger, "Peer {} sent batched commitment_signed with duplicate funding_txid {} for channel {}", log_pubkey!(their_node_id), channel_id, &batch.funding_txid);
1814+
log_debug!(logger, "Peer {} sent batched commitment_signed with duplicate funding_txid {} for channel {}", log_pubkey!(their_node_id), funding_txid, channel_id);
17951815
return Err(PeerHandleError { }.into());
17961816
}
17971817
}
17981818

1799-
if buffer.len() >= batch_size {
1800-
let (channel_id, batch) = peer_lock.commitment_signed_batch.take().expect("batch should have been inserted");
1819+
if buffer.len() == *batch_size {
1820+
let (channel_id, _, batch) = peer_lock.commitment_signed_batch.take().expect("batch should have been inserted");
18011821
return Ok(Some(LogicalMessage::CommitmentSignedBatch(channel_id, batch)));
18021822
} else {
18031823
return Ok(None);
18041824
}
1805-
} else if peer_lock.commitment_signed_batch.is_some() {
1806-
log_debug!(logger, "Peer {} sent non-batched commitment_signed for channel {} when expecting batched commitment_signed", log_pubkey!(their_node_id), &msg.channel_id);
1807-
return Err(PeerHandleError { }.into());
18081825
} else {
18091826
return Ok(Some(LogicalMessage::FromWire(wire::Message::CommitmentSigned(msg))));
18101827
}
@@ -2405,6 +2422,13 @@ impl<Descriptor: SocketDescriptor, CM: Deref, RM: Deref, OM: Deref, L: Deref, CM
24052422
if let &Some(ref msg) = update_fee {
24062423
self.enqueue_message(&mut *peer, msg);
24072424
}
2425+
if commitment_signed.len() > 1 {
2426+
let msg = msgs::StartBatch {
2427+
channel_id: *channel_id,
2428+
batch_size: commitment_signed.len() as u16,
2429+
};
2430+
self.enqueue_message(&mut *peer, &msg);
2431+
}
24082432
for msg in commitment_signed {
24092433
self.enqueue_message(&mut *peer, msg);
24102434
}

lightning/src/ln/update_fee_tests.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ pub fn test_update_fee_that_funder_cannot_afford() {
505505
channel_id: chan.2,
506506
signature: res.0,
507507
htlc_signatures: res.1,
508-
batch: None,
508+
funding_txid: None,
509509
#[cfg(taproot)]
510510
partial_signature_with_nonce: None,
511511
};
@@ -598,7 +598,7 @@ pub fn test_update_fee_that_saturates_subs() {
598598
channel_id: chan_id,
599599
signature: res.0,
600600
htlc_signatures: res.1,
601-
batch: None,
601+
funding_txid: None,
602602
#[cfg(taproot)]
603603
partial_signature_with_nonce: None,
604604
};

0 commit comments

Comments
 (0)