From 1e9eecee732603a481b50b3a34bdc1e171551363 Mon Sep 17 00:00:00 2001 From: optout <13562139+optout21@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:01:14 +0200 Subject: [PATCH] Send&handle&encode infrastructure for splicing messages --- lightning-net-tokio/src/lib.rs | 3 + lightning/src/events/mod.rs | 21 +++++++ lightning/src/ln/channelmanager.rs | 22 ++++++++ lightning/src/ln/functional_test_utils.rs | 9 +++ lightning/src/ln/msgs.rs | 69 ++++++++++++++++++++++- lightning/src/ln/peer_handler.rs | 38 +++++++++++++ lightning/src/ln/wire.rs | 31 ++++++++++ lightning/src/util/test_utils.rs | 9 +++ 8 files changed, 201 insertions(+), 1 deletion(-) diff --git a/lightning-net-tokio/src/lib.rs b/lightning-net-tokio/src/lib.rs index 6e2ea3f14c1..4fb976f175a 100644 --- a/lightning-net-tokio/src/lib.rs +++ b/lightning-net-tokio/src/lib.rs @@ -606,6 +606,9 @@ mod tests { fn handle_channel_update(&self, _their_node_id: &PublicKey, _msg: &ChannelUpdate) {} fn handle_open_channel_v2(&self, _their_node_id: &PublicKey, _msg: &OpenChannelV2) {} fn handle_accept_channel_v2(&self, _their_node_id: &PublicKey, _msg: &AcceptChannelV2) {} + fn handle_splice(&self, _their_node_id: &PublicKey, _msg: &Splice) {} + fn handle_splice_ack(&self, _their_node_id: &PublicKey, _msg: &SpliceAck) {} + fn handle_splice_locked(&self, _their_node_id: &PublicKey, _msg: &SpliceLocked) {} fn handle_tx_add_input(&self, _their_node_id: &PublicKey, _msg: &TxAddInput) {} fn handle_tx_add_output(&self, _their_node_id: &PublicKey, _msg: &TxAddOutput) {} fn handle_tx_remove_input(&self, _their_node_id: &PublicKey, _msg: &TxRemoveInput) {} diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index 95f2eb357dc..91e3ab8f45b 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -1606,6 +1606,27 @@ pub enum MessageSendEvent { /// The message which should be sent. msg: msgs::FundingSigned, }, + /// Used to indicate that a splice message should be sent to the peer with the given node id. + SendSplice { + /// The node_id of the node which should receive this message + node_id: PublicKey, + /// The message which should be sent. + msg: msgs::Splice, + }, + /// Used to indicate that a splice_ack message should be sent to the peer with the given node id. + SendSpliceAck { + /// The node_id of the node which should receive this message + node_id: PublicKey, + /// The message which should be sent. + msg: msgs::SpliceAck, + }, + /// Used to indicate that a splice_locked message should be sent to the peer with the given node id. + SendSpliceLocked { + /// The node_id of the node which should receive this message + node_id: PublicKey, + /// The message which should be sent. + msg: msgs::SpliceLocked, + }, /// Used to indicate that a tx_add_input message should be sent to the peer with the given node_id. SendTxAddInput { /// The node_id of the node which should receive this message diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 213a2882fbc..89800d4181a 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -7326,6 +7326,24 @@ where let _ = handle_error!(self, self.internal_channel_ready(counterparty_node_id, msg), *counterparty_node_id); } + fn handle_splice(&self, counterparty_node_id: &PublicKey, msg: &msgs::Splice) { + let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported".to_owned(), + msg.channel_id.clone())), *counterparty_node_id); + } + + fn handle_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) { + let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported (splice_ack)".to_owned(), + msg.channel_id.clone())), *counterparty_node_id); + } + + fn handle_splice_locked(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceLocked) { + let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( + "Splicing not supported (splice_locked)".to_owned(), + msg.channel_id.clone())), *counterparty_node_id); + } + fn handle_shutdown(&self, counterparty_node_id: &PublicKey, msg: &msgs::Shutdown) { let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); let _ = handle_error!(self, self.internal_shutdown(counterparty_node_id, msg), *counterparty_node_id); @@ -7438,6 +7456,10 @@ where // Common Channel Establishment &events::MessageSendEvent::SendChannelReady { .. } => false, &events::MessageSendEvent::SendAnnouncementSignatures { .. } => false, + // Splicing + &events::MessageSendEvent::SendSplice { .. } => false, + &events::MessageSendEvent::SendSpliceAck { .. } => false, + &events::MessageSendEvent::SendSpliceLocked { .. } => false, // Interactive Transaction Construction &events::MessageSendEvent::SendTxAddInput { .. } => false, &events::MessageSendEvent::SendTxAddOutput { .. } => false, diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index b8c2e085999..a7d7902ddaa 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -765,6 +765,15 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut MessageSendEvent::SendOpenChannelV2 { node_id, .. } => { node_id == msg_node_id }, + MessageSendEvent::SendSplice { node_id, .. } => { + node_id == msg_node_id + }, + MessageSendEvent::SendSpliceAck { node_id, .. } => { + node_id == msg_node_id + }, + MessageSendEvent::SendSpliceLocked { node_id, .. } => { + node_id == msg_node_id + }, MessageSendEvent::SendTxAddInput { node_id, .. } => { node_id == msg_node_id }, diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 8015eb990c9..1ab68178332 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -1276,12 +1276,20 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { /// Handle an incoming `channel_ready` message from the given peer. fn handle_channel_ready(&self, their_node_id: &PublicKey, msg: &ChannelReady); - // Channl close: + // Channel close: /// Handle an incoming `shutdown` message from the given peer. fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown); /// Handle an incoming `closing_signed` message from the given peer. fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned); + // Splicing + /// Handle an incoming `splice` message from the given peer. + fn handle_splice(&self, their_node_id: &PublicKey, msg: &Splice); + /// Handle an incoming `splice_ack` message from the given peer. + fn handle_splice_ack(&self, their_node_id: &PublicKey, msg: &SpliceAck); + /// Handle an incoming `splice_locked` message from the given peer. + fn handle_splice_locked(&self, their_node_id: &PublicKey, msg: &SpliceLocked); + // Interactive channel construction /// Handle an incoming `tx_add_input message` from the given peer. fn handle_tx_add_input(&self, their_node_id: &PublicKey, msg: &TxAddInput); @@ -1660,6 +1668,26 @@ impl_writeable_msg!(AcceptChannelV2, { (2, require_confirmed_inputs, option), }); +impl_writeable_msg!(Splice, { + channel_id, + chain_hash, + relative_satoshis, + funding_feerate_perkw, + locktime, + funding_pubkey, +}, {}); + +impl_writeable_msg!(SpliceAck, { + channel_id, + chain_hash, + relative_satoshis, + funding_pubkey, +}, {}); + +impl_writeable_msg!(SpliceLocked, { + channel_id, +}, {}); + impl_writeable_msg!(TxAddInput, { channel_id, serial_id, @@ -3162,6 +3190,45 @@ mod tests { assert_eq!(encoded_value, target_value); } + #[test] + fn encoding_splice() { + let secp_ctx = Secp256k1::new(); + let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let splice = msgs::Splice { + chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(), + channel_id: ChannelId::from_bytes([2; 32]), + relative_satoshis: 123456, + funding_feerate_perkw: 2000, + locktime: 0, + funding_pubkey: pubkey_1, + }; + let encoded_value = splice.encode(); + assert_eq!(hex::encode(encoded_value), "0202020202020202020202020202020202020202020202020202020202020202000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f000000000001e240000007d000000000031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"); + } + + #[test] + fn encoding_splice_ack() { + let secp_ctx = Secp256k1::new(); + let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx); + let splice = msgs::SpliceAck { + chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(), + channel_id: ChannelId::from_bytes([2; 32]), + relative_satoshis: 123456, + funding_pubkey: pubkey_1, + }; + let encoded_value = splice.encode(); + assert_eq!(hex::encode(encoded_value), "0202020202020202020202020202020202020202020202020202020202020202000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f000000000001e240031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"); + } + + #[test] + fn encoding_splice_locked() { + let splice = msgs::SpliceLocked { + channel_id: ChannelId::from_bytes([2; 32]), + }; + let encoded_value = splice.encode(); + assert_eq!(hex::encode(encoded_value), "0202020202020202020202020202020202020202020202020202020202020202"); + } + #[test] fn encoding_tx_add_input() { let tx_add_input = msgs::TxAddInput { diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index 7565246fe34..d556553d74e 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -227,6 +227,15 @@ impl ChannelMessageHandler for ErroringMessageHandler { fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &msgs::ClosingSigned) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } + fn handle_splice(&self, their_node_id: &PublicKey, msg: &msgs::Splice) { + ErroringMessageHandler::push_error(&self, their_node_id, msg.channel_id); + } + fn handle_splice_ack(&self, their_node_id: &PublicKey, msg: &msgs::SpliceAck) { + ErroringMessageHandler::push_error(&self, their_node_id, msg.channel_id); + } + fn handle_splice_locked(&self, their_node_id: &PublicKey, msg: &msgs::SpliceLocked) { + ErroringMessageHandler::push_error(&self, their_node_id, msg.channel_id); + } fn handle_update_add_htlc(&self, their_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC) { ErroringMessageHandler::push_error(self, their_node_id, msg.channel_id); } @@ -1637,6 +1646,17 @@ impl { + self.message_handler.chan_handler.handle_splice(&their_node_id, &msg); + } + wire::Message::SpliceAck(msg) => { + self.message_handler.chan_handler.handle_splice_ack(&their_node_id, &msg); + } + wire::Message::SpliceLocked(msg) => { + self.message_handler.chan_handler.handle_splice_locked(&their_node_id, &msg); + } + // Interactive transaction construction messages: wire::Message::TxAddInput(msg) => { self.message_handler.chan_handler.handle_tx_add_input(&their_node_id, &msg); @@ -1956,6 +1976,24 @@ impl { + log_debug!(self.logger, "Handling SendSplice event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + &msg.channel_id); + self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg); + } + MessageSendEvent::SendSpliceAck { ref node_id, ref msg} => { + log_debug!(self.logger, "Handling SendSpliceAck event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + &msg.channel_id); + self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg); + } + MessageSendEvent::SendSpliceLocked { ref node_id, ref msg} => { + log_debug!(self.logger, "Handling SendSpliceLocked event in peer_handler for node {} for channel {}", + log_pubkey!(node_id), + &msg.channel_id); + self.enqueue_message(&mut *get_peer_for_forwarding!(node_id), msg); + } MessageSendEvent::SendTxAddInput { ref node_id, ref msg } => { log_debug!(self.logger, "Handling SendTxAddInput event in peer_handler for node {} for channel {}", log_pubkey!(node_id), diff --git a/lightning/src/ln/wire.rs b/lightning/src/ln/wire.rs index 88e2ad7c1da..af39c896654 100644 --- a/lightning/src/ln/wire.rs +++ b/lightning/src/ln/wire.rs @@ -59,6 +59,9 @@ pub(crate) enum Message where T: core::fmt::Debug + Type + TestEq { AcceptChannelV2(msgs::AcceptChannelV2), FundingCreated(msgs::FundingCreated), FundingSigned(msgs::FundingSigned), + Splice(msgs::Splice), + SpliceAck(msgs::SpliceAck), + SpliceLocked(msgs::SpliceLocked), TxAddInput(msgs::TxAddInput), TxAddOutput(msgs::TxAddOutput), TxRemoveInput(msgs::TxRemoveInput), @@ -110,6 +113,9 @@ impl Writeable for Message where T: core::fmt::Debug + Type + TestEq { &Message::AcceptChannelV2(ref msg) => msg.write(writer), &Message::FundingCreated(ref msg) => msg.write(writer), &Message::FundingSigned(ref msg) => msg.write(writer), + &Message::Splice(ref msg) => msg.write(writer), + &Message::SpliceAck(ref msg) => msg.write(writer), + &Message::SpliceLocked(ref msg) => msg.write(writer), &Message::TxAddInput(ref msg) => msg.write(writer), &Message::TxAddOutput(ref msg) => msg.write(writer), &Message::TxRemoveInput(ref msg) => msg.write(writer), @@ -161,6 +167,9 @@ impl Type for Message where T: core::fmt::Debug + Type + TestEq { &Message::AcceptChannelV2(ref msg) => msg.type_id(), &Message::FundingCreated(ref msg) => msg.type_id(), &Message::FundingSigned(ref msg) => msg.type_id(), + &Message::Splice(ref msg) => msg.type_id(), + &Message::SpliceAck(ref msg) => msg.type_id(), + &Message::SpliceLocked(ref msg) => msg.type_id(), &Message::TxAddInput(ref msg) => msg.type_id(), &Message::TxAddOutput(ref msg) => msg.type_id(), &Message::TxRemoveInput(ref msg) => msg.type_id(), @@ -258,6 +267,15 @@ fn do_read(buffer: &mut R, message_type: u1 msgs::FundingSigned::TYPE => { Ok(Message::FundingSigned(Readable::read(buffer)?)) }, + msgs::Splice::TYPE => { + Ok(Message::Splice(Readable::read(buffer)?)) + }, + msgs::SpliceAck::TYPE => { + Ok(Message::SpliceAck(Readable::read(buffer)?)) + }, + msgs::SpliceLocked::TYPE => { + Ok(Message::SpliceLocked(Readable::read(buffer)?)) + }, msgs::TxAddInput::TYPE => { Ok(Message::TxAddInput(Readable::read(buffer)?)) }, @@ -464,6 +482,19 @@ impl Encode for msgs::AcceptChannelV2 { const TYPE: u16 = 65; } +impl Encode for msgs::Splice { + // TODO(splicing) Double check with spec; spec contains 74, which is probably wrong as it is used by tx_Abort; CLN uses 75 + const TYPE: u16 = 75; +} + +impl Encode for msgs::SpliceAck { + const TYPE: u16 = 76; +} + +impl Encode for msgs::SpliceLocked { + const TYPE: u16 = 77; +} + impl Encode for msgs::TxAddInput { const TYPE: u16 = 66; } diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 7a9ce06910b..c627f318d66 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -542,6 +542,15 @@ impl msgs::ChannelMessageHandler for TestChannelMessageHandler { fn handle_closing_signed(&self, _their_node_id: &PublicKey, msg: &msgs::ClosingSigned) { self.received_msg(wire::Message::ClosingSigned(msg.clone())); } + fn handle_splice(&self, _their_node_id: &PublicKey, msg: &msgs::Splice) { + self.received_msg(wire::Message::Splice(msg.clone())); + } + fn handle_splice_ack(&self, _their_node_id: &PublicKey, msg: &msgs::SpliceAck) { + self.received_msg(wire::Message::SpliceAck(msg.clone())); + } + fn handle_splice_locked(&self, _their_node_id: &PublicKey, msg: &msgs::SpliceLocked) { + self.received_msg(wire::Message::SpliceLocked(msg.clone())); + } fn handle_update_add_htlc(&self, _their_node_id: &PublicKey, msg: &msgs::UpdateAddHTLC) { self.received_msg(wire::Message::UpdateAddHTLC(msg.clone())); }